obo_parser 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -30,14 +30,18 @@ A simple Ruby gem for parsing OBO 1.2 formatted ontology files. Useful for repo
30
30
  first_typdef.id.value # => 'Some typedef id'
31
31
  first_typdef.name.value # => 'Some typedef name'
32
32
 
33
- foo.terms.first.tags_named('is_a') # => [OboParser#Tag, ... ]
34
- foo.terms.first.tags_named('is_a').first.tag # => 'is_a'
35
- foo.terms.first.tags_named('is_a').first.value # => 'Some Term id'
33
+ foo.terms.first.tags_named('synonym') # => [OboParser#Tag, ... ]
34
+ foo.terms.first.tags_named('synonym').first.tag # => 'synonym'
35
+ foo.terms.first.tags_named('synonym').first.value # => 'Some label'
36
+
37
+ foo.terms.first.relationships # => [['relation_ship', 'FOO:123'], ['other_relationship', 'FOO:456'] ...] An array of [relation, related term id], includes 'is_a', 'disjoint_from' and Typedefs
36
38
 
37
39
  See also /test/test_obo_parser.rb
38
40
 
39
41
  == Utilties
40
42
 
43
+ !! UTILTIES ARE PRESENTLY BORKED !!
44
+
41
45
  A small set of methods (e.g. comparing OBO ontologies) utilizing the gem are included in utilities.rb. See /lib/utilities.rb. For example, shared labels across sets of ontologies can be found and returned.
42
46
 
43
47
  == Copyright
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.3
1
+ 0.3.4
data/lib/obo_parser.rb CHANGED
@@ -34,6 +34,12 @@ module OboParser
34
34
  @terms.inject({}) {|sum, t| sum.update(t.id.value => t.name.value)}
35
35
  end
36
36
 
37
+ # A single line in a Stanza within an OBO file
38
+ class Tag
39
+ attr_accessor :tag, :value, :xrefs, :comment, :qualifier, :related_term, :relation
40
+ end
41
+
42
+ # A collection of single lines (Tags)
37
43
  class Stanza
38
44
  # Make special reference to several specific types of tags (:name, :id), subclasses will remove additional special typs from :other_tags
39
45
  attr_accessor :name, :id, :def, :other_tags
@@ -45,10 +51,11 @@ module OboParser
45
51
  t = tags.shift
46
52
 
47
53
  new_tag = OboParser::Tag.new
54
+
48
55
  new_tag.tag = t.tag
49
56
  new_tag.value = t.value
50
57
  new_tag.comment = t.comment
51
- new_tag.xrefs = t.xrefs
58
+ new_tag.xrefs = t.xrefs
52
59
 
53
60
  case new_tag.tag
54
61
  when 'id'
@@ -58,6 +65,11 @@ module OboParser
58
65
  when 'def'
59
66
  @def = new_tag
60
67
  else
68
+ if new_tag.tag == 'relationship'
69
+ new_tag.related_term = t.related_term
70
+ new_tag.relation = t.relation
71
+ end
72
+
61
73
  @other_tags.push(new_tag)
62
74
  end
63
75
  end
@@ -78,21 +90,23 @@ module OboParser
78
90
 
79
91
  # TODO: likely deprecate and run with one model (Stanza)
80
92
  class Term < Stanza
81
- # attr_accessor :some_term_specific_def
93
+ attr_accessor :relationships
82
94
  def initialize(tags)
83
- super
84
- # anonymous_tags = []
85
- # # Loop through "unclaimed" tags and reference those specific to Term
86
- # while @other_tags.size != 0
87
- # t = @other_tags.shift
88
- # case t.tag
89
- # when 'def'
90
- # @def = t
91
- # else
92
- # anonymous_tags.push(t)
93
- # end
94
- # end
95
- # @other_tags = anonymous_tags
95
+ super
96
+ @relationships = []
97
+ anonymous_tags = []
98
+ # Loop through "unclaimed" tags and reference those specific to Term
99
+ while @other_tags.size != 0
100
+ t = @other_tags.shift
101
+ case t.tag
102
+
103
+ when 'relationship'
104
+ @relationships.push([t.relation, t.related_term])
105
+ else
106
+ anonymous_tags.push(t)
107
+ end
108
+ end
109
+ @other_tags = anonymous_tags
96
110
  end
97
111
  end
98
112
 
@@ -114,10 +128,6 @@ module OboParser
114
128
  end
115
129
  end
116
130
 
117
- class Tag
118
- attr_accessor :tag, :value, :xrefs, :comment, :qualifier
119
- end
120
-
121
131
  end
122
132
 
123
133
  class OboParserBuilder
data/lib/parser.rb CHANGED
@@ -6,23 +6,24 @@ class OboParser::Parser
6
6
 
7
7
  def parse_file
8
8
  # At present we ignore the header lines
9
- while !@lexer.peek(OboParser::Tokens::Term)
9
+ while !@lexer.peek(OboParser::Tokens::Term) && !@lexer.peek(OboParser::Tokens::Typedef)
10
10
  @lexer.pop(OboParser::Tokens::TagValuePair)
11
11
  end
12
12
 
13
13
  i = 0
14
14
  while !@lexer.peek(OboParser::Tokens::Typedef) && !@lexer.peek(OboParser::Tokens::EndOfFile)
15
- raise OboParser::ParseError, "infinite loop in Terms" if i > 10000000 # there aren't that many words!
15
+ raise OboParser::ParseError, "infinite loop in Terms?" if i > 20000 # there aren't that many words!
16
16
  parse_term
17
17
  i += 1
18
18
  end
19
19
 
20
20
  i = 0
21
21
  while @lexer.peek(OboParser::Tokens::Typedef)
22
- raise OboParser::ParseError,"infinite loop in Typedefs" if i > 1000000
22
+ raise OboParser::ParseError,"infinite loop in Typedefs?" if i > 20000
23
23
  parse_typedef
24
24
  i += 1
25
25
  end
26
+
26
27
  end
27
28
 
28
29
  def parse_term
@@ -30,8 +31,18 @@ class OboParser::Parser
30
31
  tags = []
31
32
  while !@lexer.peek(OboParser::Tokens::Term) && !@lexer.peek(OboParser::Tokens::Typedef) && !@lexer.peek(OboParser::Tokens::EndOfFile)
32
33
  begin
33
- t = @lexer.pop(OboParser::Tokens::TagValuePair)
34
+
35
+ if @lexer.peek(OboParser::Tokens::IsATag)
36
+ t = @lexer.pop(OboParser::Tokens::IsATag)
37
+ elsif @lexer.peek(OboParser::Tokens::DisjointFromTag)
38
+ t = @lexer.pop(OboParser::Tokens::DisjointFromTag)
39
+ elsif @lexer.peek(OboParser::Tokens::RelationshipTag)
40
+ t = @lexer.pop(OboParser::Tokens::RelationshipTag)
41
+ else
42
+ t = @lexer.pop(OboParser::Tokens::TagValuePair)
43
+ end
34
44
  tags.push(t)
45
+
35
46
  rescue
36
47
  raise
37
48
  end
data/lib/tokens.rb CHANGED
@@ -17,45 +17,101 @@ module OboParser::Tokens
17
17
  @regexp = Regexp.new(/\A\s*(\[typedef\])\s*/i)
18
18
  end
19
19
 
20
+ # Token eeds simplification, likely through creating additional tokens for quoted qualifiers, optional modifiers ({}), and the creation of individual
21
+ # tokens for individual tags that don't conform to the pattern used for def: tags.
22
+ # The code can't presently handle escaped characters (like \,), as bizzarely found in some OBO files.
20
23
  class TagValuePair < Token
21
- attr_reader :tag, :comment, :xrefs, :qualifier
24
+ attr_reader :tag, :comment, :xrefs, :qualifier, :description
22
25
  @regexp = Regexp.new(/\A\s*([^:]+:.+)\s*\n*/i)
23
26
  def initialize(str)
24
27
  str.strip!
25
28
  tag, value = str.split(':',2)
26
29
  value.strip!
27
30
 
28
- # Handle comments
29
- if value =~ /(!\s*.+)\Z/i
31
+ if tag == 'comment'
32
+ @tag = tag.strip
33
+ @value = value.strip
34
+ return
35
+ end
36
+
37
+ @xrefs = []
38
+
39
+ # Handle inline comments
40
+ if value =~ /(\s+!\s*.+)\s*\n*\z/i
30
41
  @comment = $1
31
42
  value.gsub!(@comment, '')
32
- @comment.gsub!(/\A!\s*/, '')
33
43
  @comment.strip!
44
+ @comment.gsub!(/\A!\s*/, '')
45
+ end
46
+
47
+ value.strip!
48
+
49
+ # Qualifier for the whole tag
50
+ if value =~ /(\{[^{]*?\})\s*\n*\z/
51
+ @qualifier = $1
52
+ value.gsub!(@qualifier, '')
53
+ @qualifier.strip!
34
54
  end
35
55
 
36
- # Break out the xrefs, could be made made robust
37
- # Assumes non-quoted comma delimited in format 'foo:bar, stuff:things'
38
- if value =~ /(\s*\[.*\]\s*)/i
56
+ value.strip!
57
+
58
+ # Handle a xref list TODO: Tokenize
59
+ if value =~ /(\[.*\])/i
39
60
  xref_list = $1
40
61
  value.gsub!(xref_list, '')
62
+
41
63
  xref_list.strip!
42
- xref_list = xref_list[1..-2] # strip []
43
- @xrefs = xref_list.split(",")
64
+ xref_list = xref_list[1..-2] # [] off
65
+
66
+ qq = 0 # some failsafes
67
+ while xref_list.length > 0
68
+ qq += 1
69
+ raise "#{xref_list}" if qq > 500
70
+ xref_list.gsub!(/\A\s*,\s*/, '')
71
+
72
+ xref_list =~ /\A(.+?:[^\"|\{|\,]+)/i
73
+ v = $1
74
+
75
+ if !(v == "") && !v.nil?
76
+ v.strip!
77
+ r = Regexp.escape v
78
+ xref_list.gsub!(/\A#{r}\s*/, '')
79
+ @xrefs.push(v) if !v.nil?
80
+ end
81
+
82
+ xref_list.strip!
83
+
84
+ # A description
85
+ if xref_list =~ /\A(\s*".*?")/i
86
+ d = $1
87
+ r = Regexp.escape d
88
+ xref_list.gsub!(/\A#{r}/, '')
89
+ xref_list.strip!
90
+ end
91
+
92
+ # A optional modifier
93
+ if xref_list =~ /\A(\s*\{[^\}]*?\})/
94
+ m = $1
95
+ r = Regexp.escape m
96
+ xref_list.gsub!(/\A#{r}/, '')
97
+ xref_list.strip!
98
+ end
99
+
100
+ xref_list.strip!
101
+ end
44
102
  end
45
103
 
46
- if value =~ /\A\"/
47
- value =~ /(".*")/
48
- @value = $1
49
- value.gsub!(@value, '')
50
- @qualifier = value.strip
104
+ value.strip!
105
+
106
+ # At this point we still might have a '"foo" QUALIFIER' combination
107
+ if value =~ /\A(\"[^\"]*\")\s+(.*)/
108
+ @value = $1.strip
109
+ @qualifier = $2.strip if !$2.nil?
51
110
  else
52
111
  @value = value.strip
53
- @qualifier = nil
54
112
  end
55
-
56
- @value = @value[1..-2].strip if @value[0..0] == "\"" # get rid of quote marks
57
- @value = @value[1..-2].strip if @value[0..0] == "'" # get rid of quote marks
58
-
113
+
114
+ @value = @value[1..-2].strip if @value[0..0] == "\""
59
115
  @tag = tag.strip
60
116
  @value.strip!
61
117
  end
@@ -73,6 +129,51 @@ module OboParser::Tokens
73
129
  end
74
130
  end
75
131
 
132
+ class RelationshipTag < Token
133
+ attr_reader :tag, :related_term, :relation, :comment, :xrefs #, :qualifier
134
+ @regexp = Regexp.new(/\A\s*relationship:\s*(.+)\s*\n*/i) # returns key => value hash for tokens like 'foo=bar' or foo = 'b a ar'
135
+ def initialize(str)
136
+ @tag = 'relationship'
137
+ @xrefs = []
138
+ @relation, @related_term = str.split(/\s/,3)
139
+
140
+ str =~ /\s+!\s+(.*)\s*\n*/i
141
+ @comment = $1
142
+
143
+ @comment ||= ""
144
+ [@relation, @related_term, @comment].map(&:strip!)
145
+ end
146
+ end
147
+
148
+ class IsATag < Token
149
+ attr_reader :tag, :related_term, :relation, :comment, :xrefs #, :qualifier
150
+ @regexp = Regexp.new(/\A\s*is_a:\s*(.+)\s*\n*/i) # returns key => value hash for tokens like 'foo=bar' or foo = 'b a ar'
151
+ def initialize(str)
152
+ @tag = 'relationship'
153
+ @relation = 'is_a'
154
+ @related_term, @comment = str.split(/\s/,2)
155
+ @comment ||= ""
156
+ @comment.gsub!(/\A!\s*/, '')
157
+ [@relation, @related_term, @comment].map(&:strip!)
158
+ @xrefs = []
159
+ end
160
+ end
161
+
162
+ class DisjointFromTag < Token
163
+ attr_reader :tag, :related_term, :relation, :comment, :xrefs #, :qualifier
164
+ @regexp = Regexp.new(/\A\s*disjoint_from:\s*(.+)\s*\n*/i) # returns key => value hash for tokens like 'foo=bar' or foo = 'b a ar'
165
+ def initialize(str)
166
+ @tag = 'relationship'
167
+ @relation = 'disjoint_from'
168
+ @related_term, @comment = str.split(/\s/,2)
169
+ @comment ||= ""
170
+ @comment.gsub!(/\A!\s*/, '')
171
+ [@relation, @related_term, @comment].map(&:strip!)
172
+ @xrefs = []
173
+ end
174
+ end
175
+
176
+
76
177
  class NameValuePair < Token
77
178
  @regexp = Regexp.new('fail')
78
179
  end
@@ -167,6 +268,9 @@ module OboParser::Tokens
167
268
  OboParser::Tokens::Term,
168
269
  OboParser::Tokens::Typedef,
169
270
  OboParser::Tokens::LBracket,
271
+ OboParser::Tokens::DisjointFromTag,
272
+ OboParser::Tokens::IsATag,
273
+ OboParser::Tokens::RelationshipTag,
170
274
  OboParser::Tokens::TagValuePair,
171
275
  OboParser::Tokens::XrefList,
172
276
  OboParser::Tokens::EndOfFile
data/obo_parser.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{obo_parser}
8
- s.version = "0.3.3"
8
+ s.version = "0.3.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["mjy"]
12
- s.date = %q{2011-04-07}
12
+ s.date = %q{2011-04-11}
13
13
  s.description = %q{Provides all-in-one object containing the contents of an OBO formatted file. OBO version 1.2 is targeted, though this should work for 1.0. }
14
14
  s.email = %q{diapriid@gmail.com}
15
15
  s.extra_rdoc_files = [
data/test/cell.obo CHANGED
@@ -2979,7 +2979,7 @@ is_a: CL:0000412 ! polyploid cell
2979
2979
  [Term]
2980
2980
  id: CL:0000418
2981
2981
  name: arcade cell
2982
- def: "An epithelial cell found in C. elegans that firmly hold the outer body wall and the lips to the inner cylinder of the pharynx in a manner that keeps these organs from breaking apart, while still giving each organ freedom of movement during feeding." [GOC:tf\,, http://www.wormatlas.org/ver1/handbook/hypodermis/hypsupportother.htm#arcadecells]
2982
+ def: "An epithelial cell found in C. elegans that firmly hold the outer body wall and the lips to the inner cylinder of the pharynx in a manner that keeps these organs from breaking apart, while still giving each organ freedom of movement during feeding." [GOC:tf, http://www.wormatlas.org/ver1/handbook/hypodermis/hypsupportother.htm#arcadecells]
2983
2983
  is_a: CL:0000066 ! epithelial cell
2984
2984
 
2985
2985
  [Term]
@@ -25,18 +25,18 @@ class Test_Regex < Test::Unit::TestCase
25
25
  end
26
26
 
27
27
  class Test_Lexer < Test::Unit::TestCase
28
-
28
+
29
29
  def test_term
30
- lexer = OboParser::Lexer.new("[Term]")
31
- assert lexer.pop(OboParser::Tokens::Term)
30
+ lexer = OboParser::Lexer.new("[Term]")
31
+ assert lexer.pop(OboParser::Tokens::Term)
32
32
  end
33
-
33
+
34
34
  def test_end_of_file
35
- lexer = OboParser::Lexer.new(" \n\n")
36
- assert lexer.pop(OboParser::Tokens::EndOfFile)
37
-
38
- lexer = OboParser::Lexer.new("\n")
39
- assert lexer.pop(OboParser::Tokens::EndOfFile)
35
+ lexer = OboParser::Lexer.new(" \n\n")
36
+ assert lexer.pop(OboParser::Tokens::EndOfFile)
37
+
38
+ lexer = OboParser::Lexer.new("\n")
39
+ assert lexer.pop(OboParser::Tokens::EndOfFile)
40
40
  end
41
41
 
42
42
  def test_parse_term_stanza
@@ -69,8 +69,18 @@ class Test_Lexer < Test::Unit::TestCase
69
69
  assert_equal 'PATO:0001301', t.value
70
70
  end
71
71
 
72
+ def test_typdef
73
+ input = '[Typedef]
74
+ id: part_of
75
+ name: part of
76
+ is_transitive: true'
77
+ assert foo = parse_obo_file(input)
78
+ assert_equal 1, foo.typedefs.size
79
+ assert_equal 'part_of', foo.typedefs.first.id.value
80
+ end
81
+
72
82
  def test_parse_term_stanza2
73
- input = '[Term]
83
+ input = '[Term]
74
84
  id: CL:0000009
75
85
  name: fusiform initial
76
86
  alt_id: CL:0000274
@@ -85,23 +95,62 @@ class Test_Lexer < Test::Unit::TestCase
85
95
  assert_equal 'xylem initial', foo.terms.first.tags_named('synonym').first.value
86
96
  assert_equal 'xylem mother cell', foo.terms.first.tags_named('synonym')[1].value
87
97
  assert_equal 'CL:0000274', foo.terms.first.tags_named('alt_id').first.value
98
+
99
+ assert_equal 2, foo.terms.first.relationships.size
100
+ assert_equal(['CL:0000272', 'CL:0000610'], foo.terms.first.relationships.collect{|r| r[1]}.sort)
101
+ assert_equal(['is_a', 'is_a'], foo.terms.first.relationships.collect{|r| r[0]}.sort)
102
+
88
103
  end
89
104
 
90
105
  def test_parse_term
91
- lexer = OboParser::Lexer.new("[Term]")
92
- assert lexer.pop(OboParser::Tokens::Term)
106
+ lexer = OboParser::Lexer.new("[Term]")
107
+ assert lexer.pop(OboParser::Tokens::Term)
93
108
  end
94
109
 
95
110
  def test_xref_list
96
- lexer = OboParser::Lexer.new("[foo:bar, stuff:things]")
97
- assert t = lexer.pop(OboParser::Tokens::XrefList)
98
- hsh = {'foo' => 'bar', 'stuff' => 'things'}
99
- assert_equal hsh, t.value
111
+ lexer = OboParser::Lexer.new("[foo:bar, stuff:things]")
112
+ assert t = lexer.pop(OboParser::Tokens::XrefList)
113
+ assert_equal( {'foo' => 'bar', 'stuff' => 'things'} , t.value)
114
+ end
115
+
116
+ def test_relationship_tag
117
+ lexer = OboParser::Lexer.new("relationship: develops_from CL:0000333 ! neural crest cell")
118
+ assert t = lexer.pop(OboParser::Tokens::RelationshipTag)
119
+ assert_equal 'develops_from', t.relation
120
+ assert_equal 'CL:0000333', t.related_term
121
+ assert_equal 'relationship', t.tag
122
+
123
+ lexer = OboParser::Lexer.new("relationship: develops_from CL:0000333")
124
+ assert t = lexer.pop(OboParser::Tokens::RelationshipTag)
125
+ assert_equal 'develops_from', t.relation
126
+ assert_equal 'CL:0000333', t.related_term
127
+ assert_equal 'relationship', t.tag
128
+
129
+ lexer = OboParser::Lexer.new("is_a: CL:0000333 ! Foo")
130
+ assert t = lexer.pop(OboParser::Tokens::IsATag)
131
+ assert_equal 'is_a', t.relation
132
+ assert_equal 'CL:0000333', t.related_term
133
+ assert_equal 'Foo', t.comment
134
+
135
+ lexer = OboParser::Lexer.new("disjoint_from: CL:0000333")
136
+ assert t = lexer.pop(OboParser::Tokens::DisjointFromTag)
137
+ assert_equal 'disjoint_from', t.relation
138
+ assert_equal 'CL:0000333', t.related_term
139
+ assert_equal "", t.comment
140
+
141
+ lexer = OboParser::Lexer.new("relationship: part_of CL:0000333 ! Foo")
142
+ assert t = lexer.pop(OboParser::Tokens::RelationshipTag)
143
+ assert_equal 'part_of', t.relation
144
+ assert_equal 'CL:0000333', t.related_term
145
+ assert_equal 'Foo', t.comment
146
+
100
147
  end
101
148
 
149
+
150
+
102
151
  def test_tagvaluepair
103
- lexer = OboParser::Lexer.new("id: PATO:0000179")
104
- assert lexer.pop(OboParser::Tokens::TagValuePair)
152
+ lexer = OboParser::Lexer.new("id: PATO:0000179")
153
+ assert lexer.pop(OboParser::Tokens::TagValuePair)
105
154
  end
106
155
 
107
156
  def test_tagvaluepair_with_comments_and_xrefs
@@ -123,6 +172,22 @@ class Test_Lexer < Test::Unit::TestCase
123
172
  assert_equal([], t.xrefs)
124
173
  end
125
174
 
175
+ def test_that_xref_lists_parse_as_part_of_tagvalue_pair
176
+ lexer = OboParser::Lexer.new('def: "Foo and the bar, and stuff, and things. More stuff, and things!" [GO_REF:0000031 "Foo!" , GOC:msz {some=trailingmodifier}, GOC:tfm, ISBN:9780781765190 "Fundamental Immunology!, 6ed (Paul,ed), 2003", PMID:16014527] {qualifier=foo} ! and a comment')
177
+ assert t = lexer.pop(OboParser::Tokens::TagValuePair)
178
+ assert_equal 'def', t.tag
179
+ assert_equal 'Foo and the bar, and stuff, and things. More stuff, and things!', t.value
180
+ assert_equal(['GO_REF:0000031', 'GOC:msz', 'GOC:tfm', 'ISBN:9780781765190', 'PMID:16014527'], t.xrefs)
181
+ end
182
+
183
+ def test_crummy_space_filled_xrefs
184
+ lexer = OboParser::Lexer.new('def: "A quality inhering in a bearer by virtue of emitting light during exposure to radiation from an external source." [The Free Online dictionary:The Free Online dictionary "www.thefreedictionary.com/ -"]')
185
+ assert t = lexer.pop(OboParser::Tokens::TagValuePair)
186
+ assert_equal 'def', t.tag
187
+ assert_equal 'A quality inhering in a bearer by virtue of emitting light during exposure to radiation from an external source.', t.value
188
+ assert_equal(['The Free Online dictionary:The Free Online dictionary'], t.xrefs)
189
+ end
190
+
126
191
  end
127
192
 
128
193
  class Test_Parser < Test::Unit::TestCase
@@ -153,13 +218,7 @@ class Test_Parser < Test::Unit::TestCase
153
218
  assert_equal 'xylem mother cell', tmp[1].value
154
219
  assert_equal([], tmp[1].xrefs)
155
220
 
156
- assert_equal 2, foo.terms[9].tags_named('is_a').size
157
-
158
- end
159
-
160
-
161
- def teardown
162
- @of = nil
221
+ assert_equal 2, foo.terms[9].relationships.size
163
222
  end
164
223
 
165
224
  def test_file_completes_without_typedefs
@@ -167,5 +226,9 @@ class Test_Parser < Test::Unit::TestCase
167
226
  assert foo = parse_obo_file(@of2)
168
227
  end
169
228
 
229
+ def teardown
230
+ @of = nil
231
+ end
232
+
170
233
  end
171
234
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: obo_parser
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 3
10
- version: 0.3.3
9
+ - 4
10
+ version: 0.3.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - mjy
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-07 00:00:00 -04:00
18
+ date: 2011-04-11 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies: []
21
21