nrser 0.0.29 → 0.0.30

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
2
  SHA1:
3
- metadata.gz: 2273f6424356766a1849b35fc437b13942f15af1
4
- data.tar.gz: 901f479555218cc42909235832f2271ca8f61579
3
+ metadata.gz: e894a45a17099589d7b23f53b7b2c416d448b6d3
4
+ data.tar.gz: 9e66a57ccee2dba38b1bf16e45a55197fa80ccac
5
5
  SHA512:
6
- metadata.gz: 87482595ba0e8a8fec1b3e7c3b3c368432a5edbef62a2704d721e61199177446a6d0e28ca4c2f1119db5d7adb8da8666ded661f3c79f20f44dbccee48b756e80
7
- data.tar.gz: 412d7fdbe26337164955f5a52e6bc70370f2bd5c1282797e66c91b794fa2b8471e2dc9865e9210b822490799194a90102242466967e233a23630f773ac6cf33b
6
+ metadata.gz: 1132214b192658affc169b261f8d9840cbae0d2f3c33e2a7f48c64e2bfb6876411b50e5a3aa0b22a5245d82aa5dae5b48ef3c16fee9fa4b1ab295793b9ff7413
7
+ data.tar.gz: 1676e9d23b8182bc24447008410498aeace1b57a5c0400f02da39cb1e2e64cb2f24099253dc0ad3815c9fb00e9de24e899ee5a5c6389cffc219aa1e711211a6e
@@ -204,5 +204,85 @@ module NRSER
204
204
  end # #enumerate_as_values
205
205
 
206
206
 
207
+ # Count entries in an {Enumerable} by the value returned when they are
208
+ # passed to the block.
209
+ #
210
+ # @example Count array entries by class
211
+ #
212
+ # [1, 2, :three, 'four', 5, :six].count_by &:class
213
+ # # => {Fixnum=>3, Symbol=>2, String=>1}
214
+ #
215
+ # @param [Enumerable<E>] enum
216
+ # {Enumerable} (or other object with compatible `#each_with_object` and
217
+ # `#to_enum` methods) you want to count.
218
+ #
219
+ # @param [Proc<(E)=>C>] &block
220
+ # Block mapping entries in `enum` to the group to count them in.
221
+ #
222
+ # @return [Hash{C=>Integer}]
223
+ # Hash mapping groups to positive integer counts.
224
+ #
225
+ def count_by enum, &block
226
+ enum.each_with_object( Hash.new 0 ) do |entry, hash|
227
+ hash[block.call entry] += 1
228
+ end
229
+ end
230
+
231
+
232
+ # Like `Enumerable#find`, but wraps each call to `&block` in a
233
+ # `begin` / `rescue`, returning the result of the first call that doesn't
234
+ # raise an error.
235
+ #
236
+ # If no calls succeed, raises a {NRSER::MultipleErrors} containing the
237
+ # errors from the block calls.
238
+ #
239
+ # @param [Enumerable<E>] enum
240
+ # Values to call `&block` with.
241
+ #
242
+ # @param [Proc<E=>V>] &block
243
+ # Block to call, which is expected to raise an error if it fails.
244
+ #
245
+ # @return [V]
246
+ # Result of first call to `&block` that doesn't raise.
247
+ #
248
+ # @raise [ArgumentError]
249
+ # If `enum` was empty (`enum#each` never yielded).
250
+ #
251
+ # @raise [NRSER::MultipleErrors]
252
+ # If all calls to `&block` failed.
253
+ #
254
+ def try_find enum, &block
255
+ errors = []
256
+
257
+ enum.each do |*args|
258
+ begin
259
+ result = block.call *args
260
+ rescue Exception => error
261
+ errors << error
262
+ else
263
+ return result
264
+ end
265
+ end
266
+
267
+ if errors.empty?
268
+ raise ArgumentError,
269
+ "Appears that enumerable was empty: #{ enum.inspect }"
270
+ else
271
+ raise NRSER::MultipleErrors.new errors
272
+ end
273
+ end
274
+
275
+
276
+ # TODO It would be nice for this to work...
277
+ #
278
+ # def to_enum object, meth, *args
279
+ # unless object.respond_to?( meth )
280
+ # object = NRSER::Enumerable.new object
281
+ # end
282
+ #
283
+ # object.to_enum meth, *args
284
+ # end
285
+
286
+
207
287
  end # class << self (Eigenclass)
208
288
  end # module NRSER
@@ -55,5 +55,52 @@ module NRSER
55
55
  end # #initialize
56
56
 
57
57
  end # class AbstractMethodError
58
+
59
+
60
+ # A wrapper error around a list of other errors.
61
+ #
62
+ class MultipleErrors < StandardError
63
+
64
+ # Attributes
65
+ # ======================================================================
66
+
67
+ # The individual errors that occurred.
68
+ #
69
+ # @return [Array<Exception>]
70
+ #
71
+ attr_reader :errors
72
+
73
+
74
+ # Constructor
75
+ # ======================================================================
76
+
77
+ # Instantiate a new `MultipleErrors`.
78
+ def initialize errors, headline: nil
79
+ @errors = errors
80
+
81
+ if headline.nil?
82
+ class_counts = NRSER.count_by( errors, &:class ).
83
+ map { |klass, count| "#{ klass } (#{ count })" }.
84
+ join( ', ' )
85
+
86
+ headline = "#{ errors.count } error(s) occurred - #{ class_counts }"
87
+ end
88
+
89
+ message = NRSER.erb binding, <<-END
90
+ <%= headline %>
91
+
92
+ <% errors.each_with_index do |error, index| %>
93
+ <%= (index.succ.to_s + ".").ljust( 3 ) %> <%= error.message %> (<%= error.class %>):
94
+ <%= error.backtrace.join( $/ ) %>
95
+ <% end %>
96
+
97
+ END
98
+
99
+ super message
100
+ end # #initialize
101
+
102
+
103
+ end # class MultipleErrors
104
+
58
105
 
59
106
  end # module NRSER
@@ -32,20 +32,34 @@ module NRSER::Refinements::Enumerable
32
32
  NRSER.to_h_by self, &block
33
33
  end
34
34
 
35
+
35
36
  # See {NRSER.enumerate_as_values}
36
37
  def enumerate_as_values
37
38
  NRSER.enumerate_as_values self
38
39
  end
39
40
 
41
+
40
42
  # Calls {NRSER.only} on `self`.
41
43
  def only **options
42
44
  NRSER.only self, **options
43
45
  end
44
46
 
47
+
45
48
  # See {NRSER.only!}
46
49
  def only!
47
50
  NRSER.only! self
48
51
  end
49
52
 
53
+
54
+ # See {NRSER.count_by}
55
+ def count_by &block
56
+ NRSER.count_by self, &block
57
+ end
58
+
59
+
60
+ # See {NRSER.try_find}
61
+ def try_find &block
62
+ NRSER.try_find self, &block
63
+ end
64
+
50
65
  end # module NRSER::Refinements::Enumerable
51
-
@@ -272,7 +272,58 @@ module NRSER::RSpex
272
272
  module_exec &body
273
273
  end # description,
274
274
 
275
- end # #describe_x
275
+ end # #describe_x_type
276
+
277
+
278
+ # **EXPERIMENTAL**
279
+ #
280
+ # Example group helper for use at the top level of each spec file to
281
+ # set a bunch of stuff up and build a helpful description.
282
+ #
283
+ # @todo
284
+ # This is totally just a one-off right now... would need to be
285
+ # generalized quite a bit...
286
+ #
287
+ # 1. Extraction of module, class, etc from metadata should be flexible
288
+ #
289
+ # 2. Built description would need to be conditional on what metadata
290
+ # was found.
291
+ #
292
+ # @param [String] description:
293
+ # A description of the spec file to add to the RSpec description.
294
+ #
295
+ # @param [String] spec_path:
296
+ # The path to the spec file (just feed it `__FILE__`).
297
+ #
298
+ # Probably possible to extract this somehow without having to provide it?
299
+ #
300
+ # @return [nil]
301
+ #
302
+ def describe_spec_file description:,
303
+ spec_path:,
304
+ bind_subject: true,
305
+ **metadata,
306
+ &body
307
+
308
+ meth = metadata[:module].method metadata[:method]
309
+ file, line = meth.source_location
310
+ path = Pathname.new file
311
+ loc = "./#{ path.relative_path_from Pathname.getwd }:#{ line }"
312
+
313
+ spec_rel_path = "./#{ Pathname.new( spec_path ).relative_path_from Pathname.getwd }"
314
+
315
+ desc = "#{ metadata[:module].name }.#{ metadata[:method] } (#{ loc }) #{ description } Spec (#{ spec_rel_path})"
316
+
317
+ describe desc, **metadata do
318
+ if bind_subject
319
+ subject { meth }
320
+ end
321
+
322
+ module_exec &body
323
+ end
324
+
325
+ nil
326
+ end # #describe_spec_file
276
327
 
277
328
 
278
329
  # @todo Document describe_instance method.
@@ -435,12 +486,17 @@ module NRSER::RSpex
435
486
  end
436
487
 
437
488
 
438
- def describe_module mod, **metadata, &block
489
+ def describe_module mod, bind_subject: true, **metadata, &block
439
490
  describe(
440
491
  "#{ NRSER::RSpex::PREFIXES[:module] } #{ mod.name }",
441
492
  type: :module,
493
+ module: mod,
442
494
  **metadata
443
495
  ) do
496
+ if bind_subject
497
+ subject { mod }
498
+ end
499
+
444
500
  module_exec &block
445
501
  end
446
502
  end # #describe_module
@@ -567,6 +623,8 @@ RSpec.configure do |config|
567
623
  config.add_setting :x_type_prefixes
568
624
  config.x_type_prefixes = \
569
625
  NRSER::RSpex::PREFIXES_BASE.merge( NRSER::RSpex::PREFIXES_MATH_ITALIC )
626
+
627
+ config.add_setting :x_type_prefixes
570
628
  end
571
629
 
572
630
  # Make available at the top-level
@@ -1,5 +1,5 @@
1
1
  module NRSER
2
- VERSION = "0.0.29"
2
+ VERSION = "0.0.30"
3
3
 
4
4
  module Version
5
5
 
@@ -0,0 +1,61 @@
1
+ describe_spec_file(
2
+ description: "Gotchas",
3
+ spec_path: __FILE__,
4
+ module: NRSER,
5
+ method: :dedent,
6
+ ) do
7
+
8
+ describe_section "Newline literals in HEREDOCs" do
9
+ # ========================================================================
10
+
11
+ subject do
12
+ super().call input
13
+ end
14
+
15
+ describe_group "when a HEREDOC has a with literal \\n" do
16
+ # ========================================================================
17
+
18
+ let :input do
19
+ <<-END
20
+ <%= headline %>
21
+
22
+ <% errors.each_with_index do |error, index| %>
23
+ <%= (index.succ.to_s + ".").ljust( 3 ) %> <%= error.message %> (<%= error.class %>):
24
+ <%= error.backtrace.join( "\n" ) %>
25
+ <% end %>
26
+
27
+ END
28
+ end
29
+
30
+ it "should NOT produce the desired dedent" do
31
+ expect( subject.lines.first ).not_to match /\A\S+/
32
+ end
33
+
34
+ end
35
+ # ************************************************************************
36
+
37
+
38
+ describe_group "when the HEREDOC uses $/ instead of \\n" do
39
+ let :input do
40
+ <<-END
41
+ <%= headline %>
42
+
43
+ <% errors.each_with_index do |error, index| %>
44
+ <%= (index.succ.to_s + ".").ljust( 3 ) %> <%= error.message %> (<%= error.class %>):
45
+ <%= error.backtrace.join( $/ ) %>
46
+ <% end %>
47
+
48
+ END
49
+ end
50
+
51
+ it "should produce the desired dedent" do
52
+ expect( subject.lines.first ).to match /\A\S+/
53
+ end
54
+
55
+ end # Group "when the HEREDOC uses $/ instead of \\n" Description
56
+
57
+ end # section Newline literals in HEREDOCs
58
+ # ************************************************************************
59
+
60
+ end # describe_spec_file
61
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nrser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.29
4
+ version: 0.0.30
5
5
  platform: ruby
6
6
  authors:
7
7
  - nrser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-21 00:00:00.000000000 Z
11
+ date: 2018-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -254,6 +254,7 @@ files:
254
254
  - spec/nrser/string/common_prefix_spec.rb
255
255
  - spec/nrser/string/looks_like_spec.rb
256
256
  - spec/nrser/template_spec.rb
257
+ - spec/nrser/text/dedent/gotchas_spec.rb
257
258
  - spec/nrser/text/dedent_spec.rb
258
259
  - spec/nrser/tree/each_branch_spec.rb
259
260
  - spec/nrser/tree/leaves_spec.rb
@@ -335,6 +336,7 @@ test_files:
335
336
  - spec/nrser/string/common_prefix_spec.rb
336
337
  - spec/nrser/string/looks_like_spec.rb
337
338
  - spec/nrser/template_spec.rb
339
+ - spec/nrser/text/dedent/gotchas_spec.rb
338
340
  - spec/nrser/text/dedent_spec.rb
339
341
  - spec/nrser/tree/each_branch_spec.rb
340
342
  - spec/nrser/tree/leaves_spec.rb