dense 1.1.0 → 1.1.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.
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