Skip to content

Commit

Permalink
Fix circular dependencies (#65)
Browse files Browse the repository at this point in the history
* Fix circular dependencies

* Remove old extension files

---------

Co-authored-by: Guillaume Dalle <22795598+gdalle@users.noreply.github.com>
  • Loading branch information
dgleich and gdalle authored Nov 6, 2024
1 parent 1e6ce43 commit 9d32f65
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 189 deletions.
6 changes: 2 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ EzXML = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615"
ParserCombinator = "fae87a5f-d1ad-5cf0-8f61-c941e1580b46"

[extensions]
GraphIODOTExt = "ParserCombinator"
GraphIOGEXFExt = "EzXML"
GraphIOGMLExt = "ParserCombinator"
GraphIOGraphMLExt = "EzXML"
GraphIOParserCombinator = "ParserCombinator"
GraphIOXML = "EzXML"
GraphIOLGCompressedExt = "CodecZlib"

[compat]
Expand Down
95 changes: 0 additions & 95 deletions ext/GraphIODOTExt.jl

This file was deleted.

58 changes: 0 additions & 58 deletions ext/GraphIOGEXFExt.jl

This file was deleted.

12 changes: 3 additions & 9 deletions ext/GraphIOLGCompressedExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,9 @@ module GraphIOLGCompressedExt
using Graphs
import Graphs: loadgraph, loadgraphs, savegraph, LGFormat

@static if isdefined(Base, :get_extension)
using GraphIO
using CodecZlib
import GraphIO.LGCompressed.LGCompressedFormat
else # not required for julia >= v1.9
using ..GraphIO
using ..CodecZlib
import ..GraphIO.LGCompressed.LGCompressedFormat
end
using GraphIO
using CodecZlib
import GraphIO.LGCompressed.LGCompressedFormat

function savegraph(
fn::AbstractString, g::AbstractGraph, gname::AbstractString, format::LGCompressedFormat
Expand Down
96 changes: 85 additions & 11 deletions ext/GraphIOGMLExt.jl → ext/GraphIOParserCombinator.jl
Original file line number Diff line number Diff line change
@@ -1,18 +1,92 @@
module GraphIOGMLExt
module GraphIOParserCombinator

using Graphs
import Graphs: loadgraph, loadgraphs, savegraph

@static if isdefined(Base, :get_extension)
using GraphIO
using ParserCombinator
import GraphIO.GML.GMLFormat
else # not required for julia >= v1.9
using ..GraphIO
using ..ParserCombinator
import ..GraphIO.GML.GMLFormat
using GraphIO
using ParserCombinator
import GraphIO.DOT.DOTFormat
import GraphIO.GML.GMLFormat

function savedot(io::IO, g::AbstractGraph, gname::String="")
isdir = is_directed(g)
println(io, (isdir ? "digraph " : "graph ") * gname * " {")
for i in vertices(g)
println(io, "\t" * string(i))
end
if isdir
for u in vertices(g)
out_nbrs = outneighbors(g, u)
length(out_nbrs) == 0 && continue
println(io, "\t" * string(u) * " -> {" * join(out_nbrs, ',') * "}")
end
else
for e in edges(g)
source = string(src(e))
dest = string(dst(e))
println(io, "\t" * source * " -- " * dest)
end
end
println(io, "}")
return 1
end

function savedot_mult(io::IO, graphs::Dict)
ng = 0
for (gname, g) in graphs
ng += savedot(io, g, gname)
end
return ng
end

function _dot_read_one_graph(pg::Parsers.DOT.Graph)
isdir = pg.directed
nvg = length(Parsers.DOT.nodes(pg))
nodedict = Dict(zip(collect(Parsers.DOT.nodes(pg)), 1:nvg))
if isdir
g = DiGraph(nvg)
else
g = Graph(nvg)
end
for es in Parsers.DOT.edges(pg)
s = nodedict[es[1]]
d = nodedict[es[2]]
add_edge!(g, s, d)
end
return g
end

function _name(pg::Parsers.DOT.Graph)
return if pg.id !== nothing
pg.id.id
else
Parsers.DOT.StringID(pg.directed ? "digraph" : "graph")
end
end

function loaddot(io::IO, gname::String)
p = Parsers.DOT.parse_dot(read(io, String))
for pg in p
_name(pg) == gname && return _dot_read_one_graph(pg)
end
return error("Graph $gname not found")
end

function loaddot_mult(io::IO)
p = Parsers.DOT.parse_dot(read(io, String))
graphs = Dict{String,AbstractGraph}()

for pg in p
graphs[_name(pg)] = _dot_read_one_graph(pg)
end
return graphs
end

loadgraph(io::IO, gname::String, ::DOTFormat) = loaddot(io, gname)
loadgraphs(io::IO, ::DOTFormat) = loaddot_mult(io)
savegraph(io::IO, g::AbstractGraph, gname::String, ::DOTFormat) = savedot(io, g, gname)
savegraph(io::IO, d::Dict, ::DOTFormat) = savedot_mult(io, d)

function _gml_read_one_graph(gs, dir)
nodes = [x[:id] for x in gs[:node]]
if dir
Expand Down Expand Up @@ -54,7 +128,7 @@ function loadgml_mult(io::IO)
end

"""
savegml(f, g, gname="graph")
savegml(f, g, gname="graph")
Write a graph `g` with name `gname` to an IO stream `io` in the
[GML](https://en.wikipedia.org/wiki/Graph_Modelling_Language) format. Return 1.
Expand Down Expand Up @@ -83,7 +157,7 @@ function savegml(io::IO, g::AbstractGraph, gname::String="")
end

"""
savegml_mult(io, graphs)
savegml_mult(io, graphs)
Write a dictionary of (name=>graph) to an IO stream `io` Return number of graphs written.
"""
function savegml_mult(io::IO, graphs::Dict)
Expand Down
59 changes: 48 additions & 11 deletions ext/GraphIOGraphMLExt.jl → ext/GraphIOXML.jl
Original file line number Diff line number Diff line change
@@ -1,18 +1,55 @@
module GraphIOGraphMLExt
module GraphIOXML

using Graphs
import Graphs: loadgraph, loadgraphs, savegraph

@static if isdefined(Base, :get_extension)
using GraphIO
using EzXML
import GraphIO.GraphML.GraphMLFormat
else # not required for julia >= v1.9
using ..GraphIO
using ..EzXML
import ..GraphIO.GraphML.GraphMLFormat
import Graphs: loadgraph, loadgraphs, savegraph, AbstractGraph

using GraphIO
using EzXML
import GraphIO.GEXF.GEXFFormat
import GraphIO.GraphML.GraphMLFormat

"""
savegexf(f, g, gname)
Write a graph `g` with name `gname` to an IO stream `io` in the
[Gexf](http://gexf.net/format/) format. Return 1 (number of graphs written).
"""
function savegexf(io::IO, g::AbstractGraph, gname::String)
xdoc = XMLDocument()
xroot = setroot!(xdoc, ElementNode("gexf"))
xroot["xmlns"] = "http://www.gexf.net/1.2draft"
xroot["version"] = "1.2"
xroot["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
xroot["xsi:schemaLocation"] = "http://www.gexf.net/1.2draft/gexf.xsd"

xmeta = addelement!(xroot, "meta")
addelement!(xmeta, "description", gname)
xg = addelement!(xroot, "graph")
strdir = is_directed(g) ? "directed" : "undirected"
xg["defaultedgetype"] = strdir

xnodes = addelement!(xg, "nodes")
for i in 1:nv(g)
xv = addelement!(xnodes, "node")
xv["id"] = "$(i-1)"
end

xedges = addelement!(xg, "edges")
m = 0
for e in edges(g)
xe = addelement!(xedges, "edge")
xe["id"] = "$m"
xe["source"] = "$(src(e)-1)"
xe["target"] = "$(dst(e)-1)"
m += 1
end

prettyprint(io, xdoc)
return 1
end

savegraph(io::IO, g::AbstractGraph, gname::String, ::GEXFFormat) = savegexf(io, g, gname)

function _graphml_read_one_graph(reader::EzXML.StreamReader, isdirected::Bool)
nodes = Dict{String,Int}()
xedges = Vector{Edge}()
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ include("graphio.jl")
Aqua.test_all(GraphIO)
end
@testset "Code formatting" begin
@test JuliaFormatter.format(GraphIO; verbose=false, overwrite=false)
@test JuliaFormatter.format(GraphIO; verbose=true, overwrite=false)
end
for name in modules
path = joinpath(testdir, name, "runtests.jl")
Expand Down

0 comments on commit 9d32f65

Please sign in to comment.