edn 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # edn-ruby
2
2
 
3
- © 2012 Relevance Inc and Clinton N. Dreisbach
3
+ © 2012 Relevance Inc
4
4
 
5
5
  **edn-ruby** is a Ruby library to read and write [edn][edn] (extensible data notation), a subset of Clojure used for transferring data between applications, much like JSON, YAML, or XML.
6
6
 
@@ -114,6 +114,10 @@ end
114
114
 
115
115
  This method calls `.to_edn` on the second argument and joins the arguments appropriately.
116
116
 
117
+ ## Contributors
118
+
119
+ * Clinton N. Dreisbach
120
+
117
121
  ## Contributing
118
122
 
119
123
  1. Fork it
data/edn.gemspec CHANGED
@@ -15,8 +15,8 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = EDN::VERSION
17
17
 
18
- gem.add_dependency 'parslet'
19
- gem.add_development_dependency 'pry'
20
- gem.add_development_dependency 'rspec'
21
- gem.add_development_dependency 'rantly'
18
+ gem.add_dependency 'parslet', '~> 1.4.0'
19
+ gem.add_development_dependency 'pry', '~> 0.9.10'
20
+ gem.add_development_dependency 'rspec', '~> 2.11.0'
21
+ gem.add_development_dependency 'rantly', '~> 0.3.1'
22
22
  end
data/lib/edn.rb CHANGED
@@ -46,7 +46,7 @@ module EDN
46
46
  end
47
47
 
48
48
  EDN.register("inst") do |value|
49
- Time.parse(value)
49
+ DateTime.parse(value)
50
50
  end
51
51
 
52
52
  EDN.register("uuid") do |value|
data/lib/edn/core_ext.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'time'
2
+ require 'bigdecimal'
2
3
 
3
4
  module EDN
4
5
  module CoreExt
@@ -8,6 +9,18 @@ module EDN
8
9
  end
9
10
  end
10
11
 
12
+ module Bignum
13
+ def to_edn
14
+ self.to_s + 'M'
15
+ end
16
+ end
17
+
18
+ module BigDecimal
19
+ def to_edn
20
+ self.to_s('F') + 'M'
21
+ end
22
+ end
23
+
11
24
  module String
12
25
  def to_edn
13
26
  self.inspect
@@ -44,6 +57,12 @@ module EDN
44
57
  end
45
58
  end
46
59
 
60
+ module DateTime
61
+ def to_edn
62
+ EDN.tagout("inst", self.rfc3339)
63
+ end
64
+ end
65
+
47
66
  module Time
48
67
  def to_edn
49
68
  EDN.tagout("inst", self.xmlschema)
@@ -53,6 +72,8 @@ module EDN
53
72
  end
54
73
 
55
74
  Numeric.send(:include, EDN::CoreExt::Unquoted)
75
+ Bignum.send(:include, EDN::CoreExt::Bignum)
76
+ BigDecimal.send(:include, EDN::CoreExt::BigDecimal)
56
77
  TrueClass.send(:include, EDN::CoreExt::Unquoted)
57
78
  FalseClass.send(:include, EDN::CoreExt::Unquoted)
58
79
  NilClass.send(:include, EDN::CoreExt::NilClass)
@@ -61,4 +82,5 @@ Symbol.send(:include, EDN::CoreExt::Symbol)
61
82
  Array.send(:include, EDN::CoreExt::Array)
62
83
  Hash.send(:include, EDN::CoreExt::Hash)
63
84
  Set.send(:include, EDN::CoreExt::Set)
85
+ DateTime.send(:include, EDN::CoreExt::DateTime)
64
86
  Time.send(:include, EDN::CoreExt::Time)
data/lib/edn/parser.rb CHANGED
@@ -28,7 +28,7 @@ module EDN
28
28
  }
29
29
 
30
30
  rule(:tagged_value) {
31
- (tag >> space >> base_value.as(:value)).as(:tagged_value)
31
+ tag >> space >> base_value.as(:value)
32
32
  }
33
33
 
34
34
  # Collections
@@ -66,7 +66,7 @@ module EDN
66
66
  rule(:integer) {
67
67
  (str('-').maybe >>
68
68
  (str('0') | match('[1-9]') >> digit.repeat)).as(:integer) >>
69
- str('N').maybe
69
+ str('N').maybe.as(:precision)
70
70
  }
71
71
 
72
72
  rule(:float) {
@@ -74,7 +74,7 @@ module EDN
74
74
  (str('0') | (match('[1-9]') >> digit.repeat)) >>
75
75
  str('.') >> digit.repeat(1) >>
76
76
  (match('[eE]') >> match('[\-+]').maybe >> digit.repeat).maybe).as(:float) >>
77
- str('M').maybe
77
+ str('M').maybe.as(:precision)
78
78
  }
79
79
 
80
80
  rule(:string) {
@@ -105,7 +105,7 @@ module EDN
105
105
  # Parts
106
106
 
107
107
  rule(:tag) {
108
- (str('#') >> symbol).as(:tag)
108
+ str('#') >> symbol.as(:tag)
109
109
  }
110
110
 
111
111
  rule(:symbol_chars) {
data/lib/edn/transform.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'edn/string_transformer'
2
2
  require 'edn/types'
3
+ require 'bigdecimal'
3
4
 
4
5
  module EDN
5
6
  class Transform < Parslet::Transform
@@ -7,8 +8,16 @@ module EDN
7
8
  rule(:false => simple(:x)) { false }
8
9
  rule(:nil => simple(:x)) { nil }
9
10
 
10
- rule(:integer => simple(:x)) { Integer(x) }
11
- rule(:float => simple(:x)) { Float(x) }
11
+ rule(:integer => simple(:num), :precision => simple(:n)) {
12
+ Integer(num)
13
+ }
14
+ rule(:float => simple(:num), :precision => simple(:n)) {
15
+ if n
16
+ BigDecimal(num)
17
+ else
18
+ Float(num)
19
+ end
20
+ }
12
21
 
13
22
  rule(:string => simple(:x)) { EDN::StringTransformer.parse_string(x) }
14
23
  rule(:keyword => simple(:x)) { x.to_sym }
@@ -27,8 +36,8 @@ module EDN
27
36
  rule(:set => subtree(:array)) { Set.new(array) }
28
37
  rule(:map => subtree(:array)) { Hash[array.map { |hash| [hash[:key], hash[:value]] }] }
29
38
 
30
- rule(:tagged_value => subtree(:x)) {
31
- EDN.tag_value(x[:tag].to_s, x[:value])
39
+ rule(:tag => simple(:tag), :value => subtree(:value)) {
40
+ EDN.tag_value(tag.to_s, value)
32
41
  }
33
42
  end
34
43
  end
data/lib/edn/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module EDN
2
- VERSION = "0.9.0"
2
+ VERSION = "0.9.1"
3
3
  end
@@ -151,6 +151,14 @@ describe EDN::Parser do
151
151
  end
152
152
 
153
153
  context "tagged value" do
154
+ context "#inst" do
155
+ it "should consume #inst" do
156
+ rant(RantlyHelpers::INST).each do |value|
157
+ parser.tagged_value.should parse(value)
158
+ end
159
+ end
160
+ end
161
+
154
162
  it "should consume tagged values" do
155
163
  rant(RantlyHelpers::TAGGED_VALUE).each do |value|
156
164
  parser.tagged_value.should parse(value)
@@ -3,13 +3,17 @@ require 'spec_helper'
3
3
  describe EDN::Transform do
4
4
  context "integer" do
5
5
  it "should emit an integer" do
6
- subject.apply(:integer => "1").should == 1
6
+ subject.apply(:integer => "1", :precision => nil).should == 1
7
7
  end
8
8
  end
9
9
 
10
10
  context "float" do
11
11
  it "should emit an float" do
12
- subject.apply(:float => "1.0").should == 1.0
12
+ subject.apply(:float => "1.0", :precision => nil).should == 1.0
13
+ end
14
+
15
+ it "should emit a BigDecimal if suffixed with M" do
16
+ subject.apply(:float => "1.0", :precision => "M").should == BigDecimal("1.0")
13
17
  end
14
18
  end
15
19
 
@@ -63,21 +67,21 @@ describe EDN::Transform do
63
67
  context "vector" do
64
68
  it "should emit an array" do
65
69
  subject.apply(:vector => []).should == []
66
- subject.apply(:vector => [{:integer => "1"}, {:string => "abc"}]).should == [1, "abc"]
67
- subject.apply(:vector => [{:vector => [{:integer => "1"}, {:string => "abc"}]}, {:float => "3.14"}]).should == [[1, "abc"], 3.14]
70
+ subject.apply(:vector => [{:integer => "1", :precision => nil}, {:string => "abc"}]).should == [1, "abc"]
71
+ subject.apply(:vector => [{:vector => [{:integer => "1", :precision => nil}, {:string => "abc"}]}, {:float => "3.14", :precision => nil}]).should == [[1, "abc"], 3.14]
68
72
  end
69
73
  end
70
74
 
71
75
  context "list" do
72
76
  it "should emit a list" do
73
77
  subject.apply(:list => []).should == EDN::Type::List.new
74
- subject.apply(:list => [{:integer => "1"}, {:string => "abc"}]).should == EDN::Type::List.new(1, "abc")
75
- subject.apply(:list => [{:list => [{:integer => "1"}, {:string => "abc"}]}, {:float => "3.14"}]).should == \
78
+ subject.apply(:list => [{:integer => "1", :precision => nil}, {:string => "abc"}]).should == EDN::Type::List.new(1, "abc")
79
+ subject.apply(:list => [{:list => [{:integer => "1", :precision => nil}, {:string => "abc"}]}, {:float => "3.14", :precision => nil}]).should == \
76
80
  EDN::Type::List.new(EDN::Type::List.new(1, "abc"), 3.14)
77
81
  end
78
82
 
79
83
  it "should be type-compatible with arrays" do
80
- subject.apply(:list => [{:integer => "1"}, {:string => "abc"}]).should == [1, "abc"]
84
+ subject.apply(:list => [{:integer => "1", :precision => nil}, {:string => "abc"}]).should == [1, "abc"]
81
85
  end
82
86
  end
83
87
 
@@ -91,8 +95,8 @@ describe EDN::Transform do
91
95
  context "map" do
92
96
  it "should emit a hash" do
93
97
  map_tree = {:map=>
94
- [ {:key=>{:keyword=>{:symbol=>"a"}}, :value=>{:integer=>"1"}},
95
- {:key=>{:keyword=>{:symbol=>"b"}}, :value=>{:integer=>"2"}}
98
+ [ {:key=>{:keyword=>{:symbol=>"a"}}, :value=>{:integer=>"1", :precision => nil}},
99
+ {:key=>{:keyword=>{:symbol=>"b"}}, :value=>{:integer=>"2", :precision => nil}}
96
100
  ]
97
101
  }
98
102
 
@@ -101,29 +105,52 @@ describe EDN::Transform do
101
105
 
102
106
  it "should work with nested maps" do
103
107
  map_tree = {:map=>
104
- [{:key=>{:keyword=>{:symbol=>"a"}}, :value=>{:integer=>"1"}},
105
- {:key=>{:keyword=>{:symbol=>"b"}}, :value=>{:integer=>"2"}},
108
+ [{:key=>{:keyword=>{:symbol=>"a"}}, :value=>{:integer=>"1", :precision => nil}},
109
+ {:key=>{:keyword=>{:symbol=>"b"}}, :value=>{:integer=>"2", :precision => nil}},
106
110
  {:key=>
107
111
  {:map=>
108
- [{:key=>{:keyword=>{:symbol=>"c"}}, :value=>{:integer=>"3"}}]},
109
- :value=>{:integer=>"4"}}]}
112
+ [{:key=>{:keyword=>{:symbol=>"c"}}, :value=>{:integer=>"3", :precision => nil}}]},
113
+ :value=>{:integer=>"4", :precision => nil}}]}
110
114
  subject.apply(map_tree).should == {:a => 1, :b => 2, {:c => 3} => 4}
111
115
  end
112
116
  end
113
117
 
114
118
  context "tagged value" do
115
119
  it "should emit a EDN::Type::Unknown if the tag is not registered" do
116
- subject.apply(:tagged_value => {
117
- :tag => 'uri', :value => {:string => 'http://google.com'}
118
- }).should == EDN::Type::Unknown.new("uri", "http://google.com")
120
+ subject.apply({:tag => {:symbol => 'uri'}, :value => {:string => 'http://google.com'}}).should == EDN::Type::Unknown.new("uri", "http://google.com")
119
121
  end
120
122
 
121
123
  it "should emit the transformed value if the tag is registered" do
122
124
  EDN.register("uri", lambda { |uri| URI(uri) })
123
- subject.apply(:tagged_value => {
124
- :tag => 'uri', :value => {:string => 'http://google.com'}
125
- }).should == URI("http://google.com")
125
+ subject.apply({:tag => {:symbol => 'uri'}, :value => {:string => 'http://google.com'}}).should == URI("http://google.com")
126
126
  EDN.unregister("uri") # cleanup
127
127
  end
128
+
129
+ it "should work with nested values" do
130
+ tree = {
131
+ :tag=>{:symbol=>"cnd/awesome"},
132
+ :value=>
133
+ {:vector=>
134
+ [{:keyword=>{:symbol=>"a"}},
135
+ {:list=>
136
+ [{:integer=>"1", :precision=>nil},
137
+ {:list=>
138
+ [{:integer=>"2", :precision=>nil},
139
+ {:integer=>"3", :precision=>nil}]}]},
140
+ {:keyword=>{:symbol=>"b"}},
141
+ {:keyword=>{:symbol=>"c"}},
142
+ {:set=>
143
+ [{:integer=>"1", :precision=>nil},
144
+ {:integer=>"2", :precision=>nil},
145
+ {:integer=>"3", :precision=>nil}]},
146
+ {:vector=>
147
+ [{:vector=>
148
+ [{:vector=>[{:integer=>"42", :precision=>nil}]},
149
+ {:integer=>"42", :precision=>nil}]}]}]}}
150
+ expected = EDN::Type::Unknown.new('cnd/awesome',
151
+ [:a, [1, [2, 3]], :b, :c,
152
+ Set.new([1, 2, 3]), [[[42], 42]]])
153
+ subject.apply(tree).should == expected
154
+ end
128
155
  end
129
156
  end
data/spec/edn_spec.rb CHANGED
@@ -7,6 +7,7 @@ describe EDN do
7
7
  it "reads single values" do
8
8
  EDN.read("1").should == 1
9
9
  EDN.read("3.14").should == 3.14
10
+ EDN.read("3.14M").should == BigDecimal("3.14")
10
11
  EDN.read('"hello\nworld"').should == "hello\nworld"
11
12
  EDN.read(':hello').should == :hello
12
13
  EDN.read(':hello/world').should == :"hello/world"
@@ -19,7 +20,7 @@ describe EDN do
19
20
  end
20
21
 
21
22
  it "reads #inst tagged values" do
22
- EDN.read('#inst "2012-09-10T16:16:03-04:00"').should == Time.new(2012, 9, 10, 16, 16, 3, '-04:00')
23
+ EDN.read('#inst "2012-09-10T16:16:03-04:00"').should == DateTime.new(2012, 9, 10, 16, 16, 3, '-04:00')
23
24
  end
24
25
 
25
26
  it "reads vectors" do
data/spec/spec_helper.rb CHANGED
@@ -12,6 +12,10 @@ end
12
12
 
13
13
  module RantlyHelpers
14
14
 
15
+ KEYWORD = lambda { |_|
16
+ call(SYMBOL).to_sym.to_edn
17
+ }
18
+
15
19
  SYMBOL = lambda { |_|
16
20
  branch(PLAIN_SYMBOL, NAMESPACED_SYMBOL)
17
21
  }
@@ -30,11 +34,11 @@ module RantlyHelpers
30
34
  [call(PLAIN_SYMBOL), call(PLAIN_SYMBOL)].join("/")
31
35
  }
32
36
 
33
- INTEGER = lambda { |_| integer.to_s }
37
+ INTEGER = lambda { |_| integer.to_edn }
34
38
 
35
- STRING = lambda { |_| sized(range(1, 100)) { string.inspect } }
39
+ STRING = lambda { |_| sized(range(1, 100)) { string.to_edn } }
36
40
 
37
- FLOAT = lambda { |_| (float * range(-1000, 1000)).to_s }
41
+ FLOAT = lambda { |_| (float * range(-1000, 1000)).to_edn }
38
42
 
39
43
  FLOAT_WITH_EXP = lambda { |_|
40
44
  # limited range because of Infinity
@@ -60,15 +64,15 @@ module RantlyHelpers
60
64
  }
61
65
 
62
66
  VECTOR = lambda { |_|
63
- "[" + call(ARRAY).join(" ") + "]"
67
+ call(ARRAY).to_edn
64
68
  }
65
69
 
66
70
  LIST = lambda { |_|
67
- "(" + call(ARRAY).join(" ") + ")"
71
+ EDN::Type::List.new(*call(ARRAY)).to_edn
68
72
  }
69
73
 
70
74
  SET = lambda { |_|
71
- '#{' + call(ARRAY).join(" ") + '}'
75
+ Set.new(call(ARRAY)).to_edn
72
76
  }
73
77
 
74
78
  MAP = lambda { |_|
@@ -81,6 +85,7 @@ module RantlyHelpers
81
85
 
82
86
  VALUE = lambda { |_|
83
87
  freq([10, BASIC_VALUE],
88
+ [1, INST],
84
89
  [1, TAGGED_VALUE])
85
90
  }
86
91
 
@@ -89,6 +94,7 @@ module RantlyHelpers
89
94
  FLOAT,
90
95
  FLOAT_WITH_EXP,
91
96
  STRING,
97
+ KEYWORD,
92
98
  SYMBOL,
93
99
  CHARACTER,
94
100
  BOOL_OR_NIL,
@@ -102,6 +108,10 @@ module RantlyHelpers
102
108
  "#" + [call(SYMBOL), call(BASIC_VALUE)].join(" ")
103
109
  }
104
110
 
111
+ INST = lambda { |_|
112
+ DateTime.new(range(0, 2500), range(1, 12), range(1, 28), range(0, 23), range(0, 59), range(0, 59), "#{range(-12,12)}").to_edn
113
+ }
114
+
105
115
  def rant(fun, count = REPEAT)
106
116
  Rantly(count) { call(fun) }
107
117
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,72 +9,72 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-10 00:00:00.000000000 Z
12
+ date: 2012-09-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parslet
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: 1.4.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ! '>='
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: '0'
29
+ version: 1.4.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: pry
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ! '>='
35
+ - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: '0'
37
+ version: 0.9.10
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ! '>='
43
+ - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: '0'
45
+ version: 0.9.10
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: rspec
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ! '>='
51
+ - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: '0'
53
+ version: 2.11.0
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ! '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: 2.11.0
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rantly
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  none: false
66
66
  requirements:
67
- - - ! '>='
67
+ - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: '0'
69
+ version: 0.3.1
70
70
  type: :development
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
- - - ! '>='
75
+ - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: '0'
77
+ version: 0.3.1
78
78
  description: ! '''edn implements a reader for Extensible Data Notation by Rich Hickey.'''
79
79
  email:
80
80
  - clinton@thinkrelevance.com
@@ -115,12 +115,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
115
  - - ! '>='
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
+ segments:
119
+ - 0
120
+ hash: -981297228036091023
118
121
  required_rubygems_version: !ruby/object:Gem::Requirement
119
122
  none: false
120
123
  requirements:
121
124
  - - ! '>='
122
125
  - !ruby/object:Gem::Version
123
126
  version: '0'
127
+ segments:
128
+ - 0
129
+ hash: -981297228036091023
124
130
  requirements: []
125
131
  rubyforge_project:
126
132
  rubygems_version: 1.8.23