obo_parser 0.3.3 → 0.3.4

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/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