edn 0.9.0 → 0.9.1

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