graphs 0.1.0-x86-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/graph.rb ADDED
@@ -0,0 +1,81 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require 'yaml'
4
+
5
+ class Graph
6
+
7
+ class NodeArray < Array
8
+
9
+ def initialize(*args)
10
+ super(*args)
11
+ @defaults = {}
12
+ end
13
+
14
+ def set_default(dict)
15
+ @defaults.update(dict)
16
+ self.map! { |e| e.update(@defaults) }
17
+ end
18
+
19
+ def push(o)
20
+ if (!o.is_a?(Hash))
21
+ raise TypeError.new "#{o.inspect} is not an Hash!"
22
+ end
23
+ o2 = o.clone
24
+ o2.update(@defaults)
25
+ super
26
+ end
27
+ end
28
+
29
+ class EdgeArray < NodeArray
30
+ end
31
+
32
+ attr_accessor :nodes, :edges
33
+
34
+ def initialize(nodes=nil, edges=nil)
35
+ @nodes = NodeArray.new(nodes || [])
36
+ @edges = EdgeArray.new(edges || [])
37
+ end
38
+
39
+ def ==(other)
40
+ if (!other.is_a?(Graph))
41
+ return false
42
+ end
43
+ (self.nodes === other.nodes) && (self.edges == other.edges)
44
+ end
45
+
46
+ def &(other)
47
+ if (!other.is_a?(Graph))
48
+ return nil
49
+ end
50
+
51
+ nodes = @nodes & other.nodes
52
+ edges = @edges & other.edges
53
+
54
+ Graph.new(nodes, edges)
55
+ end
56
+
57
+ def write(filename, opts=nil)
58
+
59
+ has_ext = filename.split('.')
60
+
61
+ if ((has_ext.length == 1) || (has_ext[-1] == 'yml'))
62
+ # YAML (default)
63
+ nodes = self.nodes.to_a
64
+ edges = self.edges.to_a
65
+
66
+ data = {'nodes'=>nodes, 'edges'=>edges}.to_yaml
67
+ f = open(filename+'.yml', 'w')
68
+ f.write(data)
69
+ f.close
70
+ else
71
+ ext = has_ext[-1]
72
+
73
+ m = (self.methods - Object.methods).map {|e| e.to_s}
74
+
75
+ if (m.include? '_write_'+ext.downcase)
76
+ self.send('_write_'+ext.downcase, filename, opts)
77
+ end
78
+ end
79
+
80
+ end
81
+ end
data/lib/graphs/gdf.rb ADDED
@@ -0,0 +1,182 @@
1
+ # -*- coding: UTF-8 -*-
2
+
3
+ require_relative '../graph'
4
+
5
+ class Graph
6
+ def to_gdf(opts=nil)
7
+ GDF::unparse(self, opts)
8
+ end
9
+
10
+ def _write_gdf(filename, opts=nil)
11
+ gdf = GDF::unparse(self, opts)
12
+ f = File.open(filename, 'w')
13
+ f.write(gdf)
14
+ f.close
15
+ end
16
+ end
17
+
18
+ module GDF
19
+
20
+ def self.load(filename)
21
+ self.parse(File.read(filename))
22
+ end
23
+
24
+ def self.parse(content)
25
+
26
+ if (content.nil? || content.length == 0)
27
+ return Graph.new([],[])
28
+ end
29
+
30
+ content = content.split("\n")
31
+
32
+ # lines index of 'nodedef>' and 'edgedef>'
33
+ nodes_def_index = -1
34
+ edges_def_index = -1
35
+
36
+ content.each_with_index {|l,i|
37
+ if l.start_with? 'nodedef>'
38
+ nodes_def_index = i
39
+ elsif l.start_with? 'edgedef>'
40
+ edges_def_index = i
41
+ end
42
+
43
+ if ((nodes_def_index >= 0) && (edges_def_index >= 0))
44
+ break
45
+ end
46
+ }
47
+
48
+ # no edges
49
+ if (edges_def_index == -1)
50
+ edges = []
51
+ edges_def_index = content.length
52
+ else
53
+ edges = content[edges_def_index+1..content.length]
54
+ end
55
+
56
+ fields_split = /[\t ]*,[\t ]*/
57
+
58
+ # only nodes lines
59
+ nodes = content[nodes_def_index+1..[edges_def_index-1, content.length].min] || []
60
+
61
+ nodes_def = content[nodes_def_index]
62
+ nodes_def = nodes_def['nodedef>'.length..nodes_def.length].strip.split(fields_split)
63
+ nodes_def.each_index {|i|
64
+ nodes_def[i] = read_def(nodes_def[i])
65
+ }
66
+
67
+ nodes.each_with_index {|n,i|
68
+ n2 = {}
69
+ n = n.split(fields_split)
70
+ n.zip(nodes_def).each {|val,label_type|
71
+ label, type = label_type
72
+ n2[label] = parse_field(val, type)
73
+ }
74
+ nodes[i] = n2
75
+ }
76
+
77
+ if (edges === [])
78
+ return Graph.new(nodes)
79
+ end
80
+
81
+ # only edges lines
82
+ edges_def = content[edges_def_index]
83
+ edges_def = edges_def['edgedef>'.length..edges_def.length].strip.split(fields_split)
84
+ edges_def.each_index {|i|
85
+ edges_def[i] = read_def(edges_def[i])
86
+ }
87
+
88
+ edges.each_with_index {|e,i|
89
+ e2 = {}
90
+ e = e.split(fields_split)
91
+
92
+ e.zip(edges_def).each {|val,label_type|
93
+ label, type = label_type
94
+ e2[label] = parse_field(val, type)
95
+ }
96
+ edges[i] = e2
97
+ }
98
+
99
+ Graph.new(nodes, edges)
100
+ end
101
+
102
+ def self.unparse(graph, opts=nil)
103
+
104
+ # nodes
105
+ gdf_s = 'nodedef>'
106
+
107
+ if (graph.nodes.length == 0)
108
+ return gdf_s
109
+ end
110
+
111
+ keys = graph.nodes[0].keys
112
+ nodedef = keys.map { |k| [k, self.get_type(graph.nodes[0][k], opts)] }
113
+
114
+ gdf_s += (nodedef.map {|nd| nd.join(' ')}).join(',') + "\n"
115
+
116
+ graph.nodes.each { |n|
117
+ gdf_s += n.values.join(',') + "\n"
118
+ }
119
+
120
+ # edges
121
+ gdf_s += 'edgedef>'
122
+
123
+ if (graph.edges.length == 0)
124
+ return gdf_s
125
+ end
126
+
127
+ keys = graph.edges[0].keys
128
+ edgedef = keys.map { |k| [k, self.get_type(graph.edges[0][k], opts)] }
129
+
130
+ gdf_s += (edgedef.map {|ed| ed.join(' ')}).join(',') + "\n"
131
+
132
+ graph.edges.each { |e|
133
+ gdf_s += e.values.join(',') + "\n"
134
+ }
135
+
136
+ gdf_s
137
+ end
138
+
139
+ private
140
+
141
+ # read the value of a node|edge field, and return the value's type (String)
142
+ def self.get_type(v, opts=nil)
143
+ opts = opts || {}
144
+
145
+ if v.is_a?(Fixnum)
146
+ return 'INT'
147
+ elsif v.is_a?(Bignum)
148
+ return opts[:gephi] ? 'INT' : 'BIGINT'
149
+ elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
150
+ return 'BOOLEAN'
151
+ elsif v.is_a?(Float)
152
+ return 'FLOAT'
153
+ else
154
+ return 'VARCHAR'
155
+ end
156
+ end
157
+
158
+ # read a (node|edge)def, and return ['label', 'type of value']
159
+ def self.read_def(s)
160
+ *label, value_type = s.split /\s+/
161
+ if /((tiny|small|medium|big)?int|integer)/i.match(value_type)
162
+ value_type = 'int'
163
+ elsif /(float|real|double)/i.match(value_type)
164
+ value_type = 'float'
165
+ elsif (value_type.downcase === 'boolean')
166
+ value_type = 'boolean'
167
+ end
168
+
169
+ [label.join(' '), value_type]
170
+ end
171
+
172
+ # read a field and return its value
173
+ def self.parse_field(f, value_type)
174
+ case value_type
175
+ when 'int' then f.to_i
176
+ when 'float' then f.to_f
177
+ when 'boolean' then !(/(null|false)/i =~ f)
178
+ else f
179
+ end
180
+ end
181
+
182
+ end
@@ -0,0 +1,220 @@
1
+ #! /usr/bin/ruby1.9.1
2
+
3
+ require '../lib/graph'
4
+ require '../lib/graphes/gdf'
5
+ require 'test/unit'
6
+
7
+ module Utils
8
+ def self.get_sample_graph
9
+ @@sample_graph_1
10
+ end
11
+
12
+ @@sample_graph_1 = "nodedef>label VARCHAR,num INT,biglabel VARCHAR\n"
13
+ @@sample_graph_1 += "toto,14,TOTO\nlala,5,LALA\ntiti,988,TITI\n"
14
+ @@sample_graph_1 += "edgedef>node1 VARCHAR,node2 VARCHAR,directed BOOLEAN\n"
15
+ @@sample_graph_1 += "toto,lala,true\nlala,titi,true\n"
16
+ @@sample_graph_1 += "titi,lala,false\ntiti,toto,true\n"
17
+ end
18
+
19
+ class GDF_Graph_test < Test::Unit::TestCase
20
+
21
+ # == Graph#to_gdf == #
22
+
23
+ def test_empty_graph_to_gdf
24
+ g = Graph.new
25
+ empty_gdf = "nodedef>"
26
+
27
+ assert_equal(empty_gdf, g.to_gdf)
28
+ end
29
+
30
+ def test_sample_graph_to_gdf
31
+ gdf = Utils::get_sample_graph
32
+ g = GDF::parse(gdf)
33
+ assert_equal(gdf, g.to_gdf)
34
+ end
35
+
36
+ # == Graph#write('….gdf') == #
37
+
38
+ def test_empty_graph_write_gdf
39
+ g = Graph.new
40
+ g.write('/tmp/_graph_test.gdf')
41
+ g2 = GDF.load('/tmp/_graph_test.gdf')
42
+ assert_equal(g, g2)
43
+ end
44
+
45
+ def setup
46
+ if File.exists? '/tmp/_graph_test.gdf'
47
+ File.delete '/tmp/_graph_test.gdf'
48
+ end
49
+ end
50
+ end
51
+
52
+ class GDF_test < Test::Unit::TestCase
53
+
54
+ # == GDF::parse == #
55
+
56
+ def test_parse_empty_graph
57
+ g = GDF::parse('')
58
+
59
+ assert_equal([], g.nodes)
60
+ assert_equal([], g.edges)
61
+ end
62
+
63
+ def test_parse_empty_graph_with_nodedef
64
+
65
+ s = "nodedef>label VARCHAR\n"
66
+
67
+ g = GDF::parse(s)
68
+
69
+ assert_equal([], g.nodes)
70
+ assert_equal([], g.edges)
71
+ end
72
+
73
+ def test_parse_empty_graph_with_nodedef_and_edgedef
74
+ s = "nodedef>label VARCHAR\nedgedef>node1 VARCHAR,node2 VARCHAR\n"
75
+ g = GDF::parse(s)
76
+
77
+ assert_equal([], g.nodes)
78
+ assert_equal([], g.edges)
79
+ end
80
+
81
+ def test_parse_one_node_no_edge_string_field
82
+ s = "nodedef>label VARCHAR\nfoo\n"
83
+ g = GDF::parse(s)
84
+
85
+ assert_equal(1, g.nodes.length)
86
+ assert_equal('foo', g.nodes[0]['label'])
87
+ assert_equal([], g.edges)
88
+ end
89
+
90
+ def test_parse_one_node_no_edge_tinyint_field
91
+ s = "nodedef>num TINYINT\n3\n"
92
+ g = GDF::parse(s)
93
+
94
+ assert_equal(1, g.nodes.length)
95
+ assert_equal(3, g.nodes[0]['num'])
96
+ assert_equal([], g.edges)
97
+ end
98
+
99
+ def test_parse_one_node_no_edge_smallint_field
100
+ s = "nodedef>num SMALLINT\n3\n"
101
+ g = GDF::parse(s)
102
+
103
+ assert_equal(1, g.nodes.length)
104
+ assert_equal(3, g.nodes[0]['num'])
105
+ assert_equal([], g.edges)
106
+ end
107
+
108
+ def test_parse_one_node_no_edge_int_field
109
+ s = "nodedef>num INT\n3\n"
110
+ g = GDF::parse(s)
111
+
112
+ assert_equal(1, g.nodes.length)
113
+ assert_equal(3, g.nodes[0]['num'])
114
+ assert_equal([], g.edges)
115
+ end
116
+
117
+ def test_parse_one_node_no_edge_negative_int_field
118
+ s = "nodedef>num INT\n-1337\n"
119
+ g = GDF::parse(s)
120
+
121
+ assert_equal(1, g.nodes.length)
122
+ assert_equal(-1337, g.nodes[0]['num'])
123
+ assert_equal([], g.edges)
124
+ end
125
+
126
+ def test_parse_one_node_no_edge_bigint_field
127
+ s = "nodedef>num BIGINT\n3\n"
128
+ g = GDF::parse(s)
129
+
130
+ assert_equal(1, g.nodes.length)
131
+ assert_equal(3, g.nodes[0]['num'])
132
+ assert_equal([], g.edges)
133
+ end
134
+
135
+ def test_parse_one_node_no_edge_float_field
136
+ s = "nodedef>num FLOAT\n3\n"
137
+ g = GDF::parse(s)
138
+
139
+ assert_equal(1, g.nodes.length)
140
+ assert_equal(3.0, g.nodes[0]['num'])
141
+ assert_equal([], g.edges)
142
+ end
143
+
144
+ def test_parse_one_node_no_edge_double_field
145
+ s = "nodedef>num FLOAT\n3\n"
146
+ g = GDF::parse(s)
147
+
148
+ assert_equal(1, g.nodes.length)
149
+ assert_equal(3.0, g.nodes[0]['num'])
150
+ assert_equal([], g.edges)
151
+ end
152
+
153
+ def test_parse_one_node_no_edge_real_field
154
+ s = "nodedef>num FLOAT\n3\n"
155
+ g = GDF::parse(s)
156
+
157
+ assert_equal(1, g.nodes.length)
158
+ assert_equal(3.0, g.nodes[0]['num'])
159
+ assert_equal([], g.edges)
160
+ end
161
+
162
+ def test_parse_one_node_no_edge_negative_real_field
163
+ s = "nodedef>num FLOAT\n-42.14\n"
164
+ g = GDF::parse(s)
165
+
166
+ assert_equal(1, g.nodes.length)
167
+ assert_equal(-42.14, g.nodes[0]['num'])
168
+ assert_equal([], g.edges)
169
+ end
170
+
171
+ def test_parse_one_node_no_edge_unknow_field_type
172
+ s = "nodedef>foo BAR\nfoobar"
173
+ g = GDF::parse(s)
174
+
175
+ assert_equal(1, g.nodes.length)
176
+ assert_equal('foobar', g.nodes[0]['foo'])
177
+ assert_equal([], g.edges)
178
+ end
179
+
180
+ def test_parse_sample_graph
181
+ g = GDF::parse(Utils::get_sample_graph)
182
+
183
+ assert_equal(3, g.nodes.length)
184
+ assert_equal(4, g.edges.length)
185
+
186
+ assert_equal('toto', g.nodes[0]['label'])
187
+ assert_equal('TOTO', g.nodes[0]['biglabel'])
188
+ assert_equal(988, g.nodes[2]['num'])
189
+
190
+ assert_equal('toto', g.edges[0]['node1'])
191
+ assert_equal('lala', g.edges[0]['node2'])
192
+ assert_equal(false, g.edges[2]['directed'])
193
+
194
+ end
195
+
196
+ # == GDF::unparse == #
197
+
198
+ def test_unparse_empty_graph
199
+ g = Graph.new
200
+
201
+ s = GDF::unparse(g)
202
+
203
+ assert_equal("nodedef>", s)
204
+ end
205
+
206
+ def test_unparse_sample_graph
207
+ g1 = GDF::parse(Utils::get_sample_graph)
208
+ g2 = GDF::parse(GDF::unparse(g1))
209
+
210
+ assert_equal(g1, g2)
211
+ end
212
+
213
+ def test_unparse_big_int_gephi
214
+ g = Graph.new([{'n'=>9999999999999999}])
215
+ gdf = GDF::unparse(g, {:gephi=>true})
216
+
217
+ assert_equal("nodedef>n INT\n9999999999999999\nedgedef>", gdf)
218
+
219
+ end
220
+ end
@@ -0,0 +1,5 @@
1
+ #! /usr/bin/ruby1.9.1
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ require 'test/unit'
5
+ require '../lib/graphes/gexf'
@@ -0,0 +1,174 @@
1
+ #! /usr/bin/ruby1.9.1
2
+ # -*- coding: UTF-8 -*-
3
+
4
+ require 'test/unit'
5
+ require 'yaml'
6
+ require_relative '../lib/graph'
7
+
8
+ class Graph_test < Test::Unit::TestCase
9
+
10
+ @@sample_graph = Graph.new(
11
+ [
12
+ {'label'=>'foo', 'id'=>2},
13
+ {'label'=>'bar', 'id'=>1},
14
+ {'label'=>'chuck', 'id'=>3}
15
+ ],
16
+ [
17
+ {'node1'=>'foo', 'node2'=>'bar'},
18
+ {'node1'=>'bar', 'node2'=>'foo'},
19
+ {'node1'=>'bar', 'node2'=>'chuck'},
20
+ {'node1'=>'foo', 'node2'=>'chuck'}
21
+ ]
22
+ )
23
+
24
+ def test_new_empty_graph
25
+ g = Graph.new
26
+
27
+ assert_equal([], g.nodes)
28
+ assert_equal([], g.edges)
29
+ end
30
+
31
+ # == Graph#== == #
32
+
33
+ def test_equal_graphs
34
+ g1 = @@sample_graph
35
+ g2 = @@sample_graph.clone()
36
+
37
+ assert_equal(true, g1==g2)
38
+ end
39
+
40
+ # == Graph::NodeArray#set_default == #
41
+
42
+ def test_nodearray_set_default_unexisting_property
43
+ g = Graph.new([{'name'=>'foo'}, {'name'=>'bar'}])
44
+ g.nodes.set_default 'age' => 21
45
+
46
+ assert_equal(21, g.nodes[0]['age'])
47
+ assert_equal(21, g.nodes[1]['age'])
48
+ end
49
+
50
+ def test_nodearray_set_default_existing_property
51
+ g = Graph.new([{'name'=>'foo', 'age'=>42}, {'name'=>'bar'}])
52
+ g.nodes.set_default 'age' => 21
53
+
54
+ assert_equal(21, g.nodes[0]['age'])
55
+ assert_equal(21, g.nodes[1]['age'])
56
+ end
57
+
58
+ def test_nodearray_set_default_unexisting_property_before_push
59
+ g = Graph.new([{'name'=>'foo'}])
60
+ g.nodes.set_default 'city' => 'Paris'
61
+ g.nodes.push({'name' => 'bar'})
62
+
63
+ assert_equal('Paris', g.nodes[0]['city'])
64
+ assert_equal('Paris', g.nodes[0]['city'])
65
+ end
66
+
67
+ def test_nodearray_set_default_existing_property_before_push
68
+ g = Graph.new([{'name'=>'foo', 'city'=>'London'}])
69
+ g.nodes.set_default 'city' => 'Paris'
70
+ g.nodes.push({'name' => 'bar'})
71
+
72
+ assert_equal('Paris', g.nodes[0]['city'])
73
+ assert_equal('Paris', g.nodes[0]['city'])
74
+ end
75
+
76
+ # == Graph::edgeArray#set_default == #
77
+
78
+ def test_edgearray_set_default_unexisting_property
79
+ g = Graph.new([],[{'node1'=>'foo', 'node2'=>'bar'}])
80
+ g.edges.set_default 'directed' => true
81
+
82
+ assert_equal(true, g.edges[0]['directed'])
83
+ end
84
+
85
+ def test_edgearray_set_default_existing_property
86
+ g = Graph.new([],
87
+ [{'node1'=>'foo', 'node2'=>'bar', 'directed'=>true},
88
+ {'node1'=>'bar', 'node2'=>'foo'}])
89
+ g.edges.set_default 'directed' => false
90
+
91
+ assert_equal(false, g.edges[0]['directed'])
92
+ assert_equal(false, g.edges[1]['directed'])
93
+ end
94
+
95
+ def test_edgearray_set_default_unexisting_property_before_push
96
+ g = Graph.new([], [{'node1'=>'foo', 'node2'=>'bar'}])
97
+ g.edges.set_default 'directed' => true
98
+ g.edges.push({'node1' => 'bar', 'node2'=>'foo'})
99
+
100
+ assert_equal(true, g.edges[0]['directed'])
101
+ assert_equal(true, g.edges[0]['directed'])
102
+ end
103
+
104
+ def test_edgearray_set_default_existing_property_before_push
105
+ g = Graph.new([],
106
+ [{'node1'=>'foo', 'node2'=>'bar', 'directed'=>true}])
107
+ g.edges.set_default 'node2' => 'foo'
108
+ g.edges.push({'node1' => 'bar', 'node2' => 'foo'})
109
+
110
+ assert_equal('foo', g.edges[0]['node2'])
111
+ assert_equal('foo', g.edges[0]['node2'])
112
+ end
113
+
114
+ # == Graph#& == #
115
+
116
+ def test_empty_graph_AND_empty_graph
117
+ g1 = Graph.new
118
+ g2 = Graph.new
119
+
120
+ assert_equal(g1, g1 & g2)
121
+ end
122
+
123
+ def test_one_node_graph_AND_empty_graph
124
+ g = Graph.new([{'label'=>'foo'}])
125
+ empty = Graph.new
126
+
127
+ assert_equal(empty, g & empty)
128
+ end
129
+
130
+ def test_empty_graph_AND_one_node_graph
131
+ g = Graph.new([{'label'=>'foo'}])
132
+ empty = Graph.new
133
+
134
+ assert_equal(empty, empty & g)
135
+ end
136
+
137
+ def test_sample_graph_AND_itself
138
+ g = @@sample_graph
139
+
140
+ assert_equal(g, g & g)
141
+ end
142
+
143
+ def test_one_node_graph_AND_one_other_node_graph
144
+ g = Graph.new([{'label'=>'foo'}])
145
+ h = Graph.new([{'label'=>'bar'}])
146
+ empty = Graph.new
147
+
148
+ assert_equal(empty, g & h)
149
+ end
150
+
151
+ def test_sample_graph_AND_no_graph
152
+ g = @@sample_graph
153
+
154
+ assert_equal(nil, g & 2)
155
+ assert_equal(nil, g & true)
156
+ assert_equal(nil, g & false)
157
+ assert_equal(nil, g & ['foo', 'bar'])
158
+ assert_equal(nil, g & {'foo'=>'bar'})
159
+ assert_equal(nil, g & 'foo')
160
+ end
161
+
162
+ # == Graph#write == #
163
+
164
+ def test_graph_write_no_ext
165
+ g = @@sample_graph
166
+ f = '/tmp/_graph_test'
167
+ g.write(f)
168
+ assert_equal(true, File.exists?(f))
169
+
170
+ dict = YAML.load(File.open(f))
171
+ assert_equal(g.nodes, dict['nodes'])
172
+ assert_equal(g.edges, dict['edges'])
173
+ end
174
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: graphs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: x86-linux
7
+ authors:
8
+ - Baptiste Fontaine
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-02 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Provide functions to (un)parse GDF files and generate graphs
15
+ email: batifon@yahoo.fr
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/graph.rb
21
+ - lib/graphs/gdf.rb
22
+ - tests/tests_gexf.rb
23
+ - tests/tests_graph.rb
24
+ - tests/tests_gdf.rb
25
+ homepage: https://github.com/bfontaine/Graph.rb
26
+ licenses:
27
+ - MIT
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 1.8.24
47
+ signing_key:
48
+ specification_version: 3
49
+ summary: Utilities to manipulate graph files
50
+ test_files:
51
+ - tests/tests_gexf.rb
52
+ - tests/tests_graph.rb
53
+ - tests/tests_gdf.rb