dense 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 314a76ad0969382d65813cfa4ab3eb62db8a1ecf
4
- data.tar.gz: ff138616d42d086fd7abbd1beee76c9f81c55172
2
+ SHA256:
3
+ metadata.gz: 24371919775ff81e60eb86f0e9bae21a13a4cd4458e14a3584b05b7a16e7937b
4
+ data.tar.gz: '085c7f5db832b45f4c4f0127ad224d4dfa15402b444b5312274f54ac055825d3'
5
5
  SHA512:
6
- metadata.gz: bcc1ff383a330a6da5068fd16774663e65577290bc7737a02d5102188f5c79d0fb2cbd24a627d607c7366ec13262d738b12121d61ac62042cbdf37883d7d0cf7
7
- data.tar.gz: '098e9342bec870d2f21339c89e70d8825aaa24381234276d1e22f20391fd9488009589dcc1e1d01a1a75c57a0048dd8cb62b591ba2db55c5989519695dc86dff'
6
+ metadata.gz: f0f291761cfb4aaa3d6151e788dc9200a361deed8556167cc9a219b96f473a9e3373f822c93b2a6940370d0a3d01ad19c17ec1e4e9dfeef48cca399c3273bf7d
7
+ data.tar.gz: bd667ecb92422f129e474bd2f37121963f0e618b7166e80f82003462944d2616655034b51f567405c614fbfee2405c32f9dc6b3824e650c5de50f9efdf1cb1d5
@@ -2,6 +2,12 @@
2
2
  # dense
3
3
 
4
4
 
5
+ ## dense 1.1.1 released 2018-06-15
6
+
7
+ * Accept `[a;b;c]` union keys
8
+ * Accept regular expressions for object keys
9
+
10
+
5
11
  ## dense 1.1.0 released 2018-04-29
6
12
 
7
13
  * Add Dense.path(path) and Dense.gather(collection, path)
data/Makefile CHANGED
@@ -8,6 +8,7 @@ VERSION = \
8
8
 
9
9
  count_lines:
10
10
  find lib -name "*.rb" | xargs cat | ruby -e "p STDIN.readlines.count { |l| l = l.strip; l[0, 1] != '#' && l != '' }"
11
+ find spec -name "*.rb" | xargs cat | ruby -e "p STDIN.readlines.count { |l| l = l.strip; l[0, 1] != '#' && l != '' }"
11
12
  cl: count_lines
12
13
 
13
14
  gemspec_validate:
data/README.md CHANGED
@@ -117,7 +117,7 @@ When it doesn't find, it raises an instance of `KeyError`:
117
117
  ```ruby
118
118
  Dense.fetch({}, 'a.0.b')
119
119
  # raises
120
- # KeyError: Found nothing at "a" ("0.b" remains)
120
+ # KeyError: found nothing at "a" ("0.b" remains)
121
121
  ```
122
122
 
123
123
  It might instead raise an instance of `TypeError` if a non-integer key is requested of an array:
@@ -125,7 +125,7 @@ It might instead raise an instance of `TypeError` if a non-integer key is reques
125
125
  ```ruby
126
126
  Dense.fetch({ 'a' => [] }, 'a.k.b')
127
127
  # raises
128
- # TypeError: No key "k" for Array at "a"
128
+ # TypeError: no key "k" for Array at "a"
129
129
  ```
130
130
 
131
131
  See KeyError and TypeError below for more details.
@@ -207,7 +207,7 @@ r # => 'three'
207
207
 
208
208
  c = { 'a' => [] }
209
209
  Dense.set(c, 'a.b', 1)
210
- # => TypeError: No key "b" for Array at "a"
210
+ # => TypeError: no key "b" for Array at "a"
211
211
 
212
212
 
213
213
  c = { 'a' => {} }
@@ -217,7 +217,7 @@ r # => 1
217
217
 
218
218
  c = {}
219
219
  Dense.set(c, 'a.0', 1)
220
- # => KeyError: Found nothing at "a" ("0" remains)
220
+ # => KeyError: found nothing at "a" ("0" remains)
221
221
  ```
222
222
 
223
223
  Setting at multiple places in one go is possible:
@@ -282,11 +282,11 @@ r # => 3
282
282
  It fails with a `KeyError` or a `TypeError` if it cannot unset.
283
283
  ```ruby
284
284
  Dense.unset({}, 'a')
285
- # => KeyError: Found nothing at "a"
285
+ # => KeyError: found nothing at "a"
286
286
  Dense.unset([], 'a')
287
- # => TypeError: No key "a" for Array at root
287
+ # => TypeError: no key "a" for Array at root
288
288
  Dense.unset([], '1')
289
- # => KeyError: Found nothing at "1"
289
+ # => KeyError: found nothing at "1"
290
290
  ```
291
291
 
292
292
  Unsetting multiple values is OK:
@@ -309,7 +309,7 @@ e =
309
309
  rescue => err
310
310
  err
311
311
  end
312
- # => #<KeyError: Found nothing at "a" ("b" remains)>
312
+ # => #<KeyError: found nothing at "a" ("b" remains)>
313
313
  e.full_path
314
314
  # => "a"
315
315
  e.miss
@@ -27,9 +27,9 @@ Fetching deep in a dense structure. A kind of bastard of JSONPath.
27
27
  "#{s.name}.gemspec",
28
28
  ]
29
29
 
30
- s.add_runtime_dependency 'raabro', '>= 1.1.5'
30
+ s.add_runtime_dependency 'raabro', '~> 1.1', '>= 1.1.5'
31
31
 
32
- s.add_development_dependency 'rspec', '~> 3.4'
32
+ s.add_development_dependency 'rspec', '~> 3.7'
33
33
 
34
34
  s.require_path = 'lib'
35
35
  end
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Dense
3
3
 
4
- VERSION = '1.1.0'
4
+ VERSION = '1.1.1'
5
5
  end
6
6
 
7
7
  require 'raabro'
@@ -126,7 +126,7 @@ module Dense; class << self
126
126
  path1 = Dense::Path.make(miss[1] + [ miss[3] ]).to_s.inspect
127
127
  path2 = Dense::Path.make(miss[4]).to_s.inspect
128
128
 
129
- msg = "Found nothing at #{path1}"
129
+ msg = "found nothing at #{path1}"
130
130
  msg = "#{msg} (#{path2} remains)" if path2 != '""'
131
131
 
132
132
  make_error(KeyError, msg, path, miss)
@@ -138,7 +138,7 @@ module Dense; class << self
138
138
  cla = miss[2].class
139
139
  pat = miss[1].empty? ? 'root' : Dense::Path.make(miss[1]).to_s.inspect
140
140
 
141
- make_error(TypeError, "No key #{key} for #{cla} at #{pat}", path, miss)
141
+ make_error(TypeError, "no key #{key} for #{cla} at #{pat}", path, miss)
142
142
  end
143
143
 
144
144
  def miss_error(path, miss)
@@ -3,6 +3,17 @@ module Dense::Path::Parser include ::Raabro
3
3
 
4
4
  # piece parsers bottom to top
5
5
 
6
+ def rxnames(i)
7
+
8
+ rex(:rxnames, i, %r{
9
+ /(
10
+ \\[\/bfnrt] |
11
+ \\u[0-9a-fA-F]{4} |
12
+ [^/\b\f\n\r\t]
13
+ )*/[imxouesn]*
14
+ }x)
15
+ end
16
+
6
17
  def dqname(i)
7
18
 
8
19
  rex(:qname, i, %r{
@@ -26,7 +37,8 @@ module Dense::Path::Parser include ::Raabro
26
37
  end
27
38
 
28
39
  def dot(i); str(nil, i, '.'); end
29
- def comma(i); rex(nil, i, / *, */); end
40
+ def comma_or_semicolon(i); rex(nil, i, / *[,;] */); end
41
+
30
42
  def bend(i); str(nil, i, ']'); end
31
43
  def bstart(i); str(nil, i, '['); end
32
44
  def blank(i); str(:blank, i, ''); end
@@ -43,15 +55,23 @@ module Dense::Path::Parser include ::Raabro
43
55
  /(
44
56
  (-?\d+)?:(-?\d+)?:(-?\d+)? |
45
57
  (-?\d+)?:(-?\d+)? |
58
+ (-?\d+)?,(\d+)? |
46
59
  -?\d+
47
60
  )/x)
48
61
  end
49
62
 
50
63
  def escape(i); rex(:esc, i, /\\[.*]/); end
51
64
 
52
- def bindex(i); alt(:index, i, :dqname, :sqname, :star, :ses, :name, :blank); end
53
- def bindexes(i); jseq(:bindexes, i, :bindex, :comma); end
54
- def simple_index(i); alt(:index, i, :off, :escape, :star, :name); end
65
+ def bindex(i)
66
+ alt(:index, i, :dqname, :sqname, :star, :ses, :rxnames, :name, :blank)
67
+ end
68
+ def bindexes(i)
69
+ jseq(:bindexes, i, :bindex, :comma_or_semicolon)
70
+ end
71
+
72
+ def simple_index(i)
73
+ alt(:index, i, :off, :escape, :star, :rxnames, :name)
74
+ end
55
75
 
56
76
  def dotdot(i); str(:dotdot, i, '.'); end
57
77
  def dotdotstar(i); rex(:dotdotstar, i, /(\.\.\*|\.\[\*\])/); end
@@ -67,10 +87,21 @@ module Dense::Path::Parser include ::Raabro
67
87
  # rewrite parsed tree
68
88
 
69
89
  def rewrite_ses(t)
70
- a = t.string.split(':').collect { |e| e.empty? ? nil : e.to_i }
71
- return a[0] if a[1] == nil && a[2] == nil
72
- { start: a[0], end: a[1], step: a[2] }
90
+
91
+ s = t.string
92
+
93
+ if (a = s.split(',')).length == 2
94
+ { start: a[0].to_i, count: a[1].to_i }
95
+ else
96
+ a = s.split(':').collect { |e| e.empty? ? nil : e.to_i }
97
+ if a[1] == nil && a[2] == nil
98
+ a[0]
99
+ else
100
+ { start: a[0], end: a[1], step: a[2] }
101
+ end
102
+ end
73
103
  end
104
+
74
105
  def rewrite_esc(t); t.string[1, 1]; end
75
106
  def rewrite_star(t); :star; end
76
107
  def rewrite_dotdot(t); :dot; end
@@ -84,6 +115,30 @@ module Dense::Path::Parser include ::Raabro
84
115
 
85
116
  def rewrite_blank(t); nil; end
86
117
 
118
+ ENCODINGS = {
119
+ 'u' => 'UTF-8', 'e' => 'EUC-JP', 's' => 'Windows-31J', 'n' => 'ASCII-8BIT' }
120
+ R_ENCODINGS = ENCODINGS
121
+ .inject({}) { |h, (k, v)| h[v] = k; h }
122
+
123
+ def rewrite_rxnames(t)
124
+
125
+ m = t.string.match(/\A\/(.+)\/([imxuesn]*)\z/)
126
+
127
+ s = m[1]
128
+
129
+ e = ENCODINGS[(m[2].match(/[uesn]/) || [])[0]]
130
+ #s = s.force_encoding(e) if e
131
+ s = s.encode(e) if e
132
+
133
+ flags = 0
134
+ flags = flags | Regexp::EXTENDED if m[2].index('x')
135
+ flags = flags | Regexp::IGNORECASE if m[2].index('i')
136
+ #flags = flags | Regexp::MULTILINE if m[2].index('m')
137
+ flags = flags | Regexp::FIXEDENCODING if e
138
+
139
+ Regexp.new(s, flags)
140
+ end
141
+
87
142
  def rewrite_qname(t); t.string[1..-2]; end
88
143
  def rewrite_name(t); t.string; end
89
144
 
@@ -8,7 +8,7 @@ class Dense::Path
8
8
  @original = s
9
9
 
10
10
  fail ArgumentError.new(
11
- "Argument is a #{s.class}, not a String"
11
+ "argument is a #{s.class}, not a String"
12
12
  ) unless s.is_a?(String)
13
13
 
14
14
  s = ".#{s}" \
@@ -124,8 +124,13 @@ class Dense::Path
124
124
  return [ nil ] unless o.is_a?(Array)
125
125
 
126
126
  be = k[:start] || 0
127
- en = k[:end] || o.length - 1
128
- st = k[:step] || 1
127
+
128
+ en, st =
129
+ if co = k[:count]
130
+ [ be + co - 1, 1 ]
131
+ else
132
+ [ k[:end] || o.length - 1, k[:step] || 1 ]
133
+ end
129
134
 
130
135
  Range.new(be, en).step(st).to_a
131
136
  end
@@ -134,12 +139,18 @@ class Dense::Path
134
139
 
135
140
  return _resolve_hash_key(o, k) if k.is_a?(Hash)
136
141
 
137
- return [ k.to_s ] if o.is_a?(Hash)
142
+ if o.is_a?(Hash)
143
+
144
+ return o.keys.select { |ok| ok =~ k } if k.is_a?(Regexp)
145
+ [ k.to_s ]
146
+
147
+ else # o is a Array
138
148
 
139
- case k
140
- when /\Afirst\z/i then [ 0 ]
141
- when /\Alast\z/i then [ -1 ]
142
- else [ k ]
149
+ case k
150
+ when /\Afirst\z/i then [ 0 ]
151
+ when /\Alast\z/i then [ -1 ]
152
+ else [ k ]
153
+ end
143
154
  end
144
155
  end
145
156
 
@@ -251,12 +262,19 @@ class Dense::Path
251
262
 
252
263
  case elt
253
264
  when Hash
254
- s = [ "#{elt[:start]}:#{elt[:end]}", elt[:step] ].compact.join(':')
265
+ s =
266
+ if elt[:count]
267
+ [ elt[:start], elt[:count] ].collect(&:to_s).join(',')
268
+ else
269
+ [ "#{elt[:start]}:#{elt[:end]}", elt[:step] ].compact.join(':')
270
+ end
255
271
  in_array ? s : "[#{s}]"
256
272
  when Array
257
- "[#{elt.map { |e| _to_s(e, true) }.join(',')}#{elt.size < 2 ? ',' : ''}]"
273
+ "[#{elt.map { |e| _to_s(e, true) }.join(';')}#{elt.size < 2 ? ';' : ''}]"
258
274
  when String
259
275
  _str_to_s(elt, in_array)
276
+ when Regexp
277
+ _rex_to_s(elt)
260
278
  when :star
261
279
  '*'
262
280
  when :dot
@@ -278,5 +296,12 @@ class Dense::Path
278
296
  return "[#{elt.inspect}]" if s =~ /["']/
279
297
  s
280
298
  end
299
+
300
+ def _rex_to_s(r)
301
+
302
+ r.fixed_encoding? ?
303
+ r.inspect + (Dense::Path::Parser::R_ENCODINGS[r.encoding.name] || '') :
304
+ r.inspect
305
+ end
281
306
  end # Dense::Path
282
307
 
metadata CHANGED
@@ -1,19 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dense
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-29 00:00:00.000000000 Z
11
+ date: 2018-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: raabro
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
17
20
  - - ">="
18
21
  - !ruby/object:Gem::Version
19
22
  version: 1.1.5
@@ -21,6 +24,9 @@ dependencies:
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.1'
24
30
  - - ">="
25
31
  - !ruby/object:Gem::Version
26
32
  version: 1.1.5
@@ -30,14 +36,14 @@ dependencies:
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '3.4'
39
+ version: '3.7'
34
40
  type: :development
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '3.4'
46
+ version: '3.7'
41
47
  description: Fetching deep in a dense structure. A kind of bastard of JSONPath.
42
48
  email:
43
49
  - jmettraux+flor@gmail.com
@@ -74,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
80
  version: '0'
75
81
  requirements: []
76
82
  rubyforge_project:
77
- rubygems_version: 2.6.13
83
+ rubygems_version: 2.7.6
78
84
  signing_key:
79
85
  specification_version: 4
80
86
  summary: fetching deep in a dense structure