nrser 0.3.11 → 0.3.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/nrser/core_ext/array.rb +2 -35
- data/lib/nrser/core_ext/array/to_proc.rb +39 -0
- data/lib/nrser/core_ext/enumerable.rb +13 -1
- data/lib/nrser/core_ext/enumerable/slash_map.rb +37 -0
- data/lib/nrser/errors.rb +1 -0
- data/lib/nrser/errors/conflict_error.rb +13 -2
- data/lib/nrser/errors/unreachable_error.rb +41 -0
- data/lib/nrser/graph/tsorter.rb +13 -6
- data/lib/nrser/rspex.rb +11 -1
- data/lib/nrser/rspex/example_group.rb +1 -0
- data/lib/nrser/rspex/example_group/describe_message.rb +49 -31
- data/lib/nrser/rspex/example_group/describe_subject.rb +53 -0
- data/lib/nrser/types.rb +1 -0
- data/lib/nrser/types/arrays.rb +1 -1
- data/lib/nrser/types/booleans.rb +7 -5
- data/lib/nrser/types/doc/display_table.md +1 -1
- data/lib/nrser/types/enumerables.rb +142 -0
- data/lib/nrser/types/factory.rb +30 -22
- data/lib/nrser/types/numbers.rb +1 -0
- data/lib/nrser/types/paths.rb +9 -0
- data/lib/nrser/types/top.rb +5 -0
- data/lib/nrser/version.rb +1 -1
- data/spec/lib/nrser/types/enumerables_spec.rb +39 -0
- data/spec/lib/nrser/types/paths_spec.rb +19 -2
- data/spec/lib/nrser/types_spec.rb +10 -2
- metadata +15 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0455e10b137f0194452111ef3a4a55960a7b642
|
4
|
+
data.tar.gz: 4966b5b797d0de2da7f79687d05af23656740e2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aed3f495e077fa4c1167afe6113a5fea5d38f66ca9e7ade3961104b0d38c026f174f36d2bed8ae5b59a21b70515f687f1c1840ec1490403ca8ea4e151acf250d
|
7
|
+
data.tar.gz: 30d68b577092b8250349f636535a53de3031e7b44030c55d4bb4a5d0c7ee159ad65693f53a8100296f3f5b1613f02ca79ad0de284971ad5788514bdbe587b31f
|
data/lib/nrser/core_ext/array.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative './array/to_proc'
|
2
|
+
|
1
3
|
class Array
|
2
4
|
include NRSER::Ext::Tree
|
3
5
|
|
@@ -91,41 +93,6 @@ class Array
|
|
91
93
|
def to_chainer publicly: true
|
92
94
|
NRSER.chainer self, publicly: publicly
|
93
95
|
end # #to_chainer
|
94
|
-
|
95
|
-
|
96
|
-
# Returns a lambda that calls accepts a single arg and calls either:
|
97
|
-
#
|
98
|
-
# 1. `#[self.first]` if this array has only one entry.
|
99
|
-
# 2. `#dig( *self )` if this array has more than one entry.
|
100
|
-
#
|
101
|
-
# @example
|
102
|
-
# list = [{id: 1, name: "Neil"}, {id: 2, name: "Mica"}]
|
103
|
-
# list.assoc_by &[:id]
|
104
|
-
# # => {
|
105
|
-
# # 1 => {id: 1, name: "Neil"},
|
106
|
-
# # 2 => {id: 2, name: "Mica"},
|
107
|
-
# # }
|
108
|
-
#
|
109
|
-
# @return [Proc]
|
110
|
-
# Lambda proc that accepts a single argument and calls `#[]` or `#dig with
|
111
|
-
# this array's contents as the arguments.
|
112
|
-
#
|
113
|
-
def to_proc
|
114
|
-
method_name = case count
|
115
|
-
when 0
|
116
|
-
raise NRSER::CountError.new \
|
117
|
-
"Can not create getter proc from empty array",
|
118
|
-
value: self,
|
119
|
-
expected: '> 0',
|
120
|
-
count: count
|
121
|
-
when 1
|
122
|
-
:[]
|
123
|
-
else
|
124
|
-
:dig
|
125
|
-
end
|
126
|
-
|
127
|
-
NRSER::Message.new( method_name, *self ).to_proc
|
128
|
-
end # #to_proc
|
129
96
|
|
130
97
|
|
131
98
|
# Old name for {#to_proc}.
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'nrser/message'
|
2
|
+
|
3
|
+
class Array
|
4
|
+
|
5
|
+
# Returns a lambda that calls accepts a single arg and calls either:
|
6
|
+
#
|
7
|
+
# 1. `#[self.first]` if this array has only one entry.
|
8
|
+
# 2. `#dig( *self )` if this array has more than one entry.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# list = [{id: 1, name: "Neil"}, {id: 2, name: "Mica"}]
|
12
|
+
# list.assoc_by &[:id]
|
13
|
+
# # => {
|
14
|
+
# # 1 => {id: 1, name: "Neil"},
|
15
|
+
# # 2 => {id: 2, name: "Mica"},
|
16
|
+
# # }
|
17
|
+
#
|
18
|
+
# @return [Proc]
|
19
|
+
# Lambda proc that accepts a single argument and calls `#[]` or `#dig with
|
20
|
+
# this array's contents as the arguments.
|
21
|
+
#
|
22
|
+
def to_proc
|
23
|
+
method_name = case count
|
24
|
+
when 0
|
25
|
+
raise NRSER::CountError.new \
|
26
|
+
"Can not create getter proc from empty array",
|
27
|
+
value: self,
|
28
|
+
expected: '> 0',
|
29
|
+
count: count
|
30
|
+
when 1
|
31
|
+
:[]
|
32
|
+
else
|
33
|
+
:dig
|
34
|
+
end
|
35
|
+
|
36
|
+
NRSER::Message.new( method_name, *self ).to_proc
|
37
|
+
end # #to_proc
|
38
|
+
|
39
|
+
end # class Array
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'nrser/functions/enumerable/associate'
|
2
2
|
require_relative './enumerable/find_map'
|
3
|
+
require_relative './enumerable/slash_map'
|
3
4
|
|
4
5
|
|
5
6
|
# Instance methods to extend {Enumerable}.
|
@@ -16,6 +17,18 @@ module Enumerable
|
|
16
17
|
def find_only &block
|
17
18
|
NRSER.find_only self, &block
|
18
19
|
end
|
20
|
+
|
21
|
+
|
22
|
+
# Right now, *exactly* the same as {#find_only}... though I wished I had
|
23
|
+
# called it this and had {#find_only} return `nil` if it failed, as is
|
24
|
+
# kind-of a some-what established practice, because now I get confused.
|
25
|
+
#
|
26
|
+
# Maybe some day I will make that change. For now, this is here so when I
|
27
|
+
# forget and add the `!` it works.
|
28
|
+
#
|
29
|
+
def find_only! &block
|
30
|
+
NRSER.find_only self, &block
|
31
|
+
end
|
19
32
|
|
20
33
|
|
21
34
|
# See {NRSER.assoc_by}
|
@@ -65,5 +78,4 @@ module Enumerable
|
|
65
78
|
NRSER.slice? self, *args, &block
|
66
79
|
end
|
67
80
|
|
68
|
-
|
69
81
|
end # module Enumerable
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Enumerable
|
2
|
+
|
3
|
+
# @note EXPERIMENTAL!
|
4
|
+
#
|
5
|
+
# An idea I'm playing around with for convenient mapping of {Enumerable}.
|
6
|
+
#
|
7
|
+
# @example Extract Attributes
|
8
|
+
# Cat = Struct.new :name, :breed
|
9
|
+
#
|
10
|
+
# cats = [ Cat.new( 'Hudie', 'Chinese-American Shorthair' ),
|
11
|
+
# Cat.new( 'Oscar', 'Bengal' ) ]
|
12
|
+
#
|
13
|
+
# cats/:name #=> [ 'Hudie', 'Oscar' ]
|
14
|
+
# cats/:breed #=> [ 'Chinese-American Shorthair', 'Bengal' ]
|
15
|
+
#
|
16
|
+
# @example Extract Values
|
17
|
+
# # Need the array.to_proc ~> ->( key ) { array.dig *key } for it to really
|
18
|
+
# # *feel* nice... and that's the whole point!
|
19
|
+
# require 'nrser/core_ext/array/to_proc'
|
20
|
+
#
|
21
|
+
# kitties = [ { name: 'Hootie' },
|
22
|
+
# { name: 'Oscie' } ]
|
23
|
+
#
|
24
|
+
# kitties/[:name] #=> [ 'Hooie', 'Oscie' ]
|
25
|
+
#
|
26
|
+
# Not so bad, eh? I'm calling it "slash-map" for the moment, BTW.
|
27
|
+
#
|
28
|
+
# @param [#to_proc] proc_able
|
29
|
+
# Something that can be `#to_proc`'d for the {Enumerable#map}.
|
30
|
+
#
|
31
|
+
# @return [Enumerable]
|
32
|
+
#
|
33
|
+
def / proc_able
|
34
|
+
map &proc_able
|
35
|
+
end
|
36
|
+
|
37
|
+
end # module NRSER
|
data/lib/nrser/errors.rb
CHANGED
@@ -10,6 +10,12 @@
|
|
10
10
|
require_relative './nicer_error'
|
11
11
|
|
12
12
|
|
13
|
+
# Namespace
|
14
|
+
# ========================================================================
|
15
|
+
|
16
|
+
module NRSER
|
17
|
+
|
18
|
+
|
13
19
|
# Definitions
|
14
20
|
# =======================================================================
|
15
21
|
|
@@ -17,7 +23,12 @@ require_relative './nicer_error'
|
|
17
23
|
# it's not the type or an argument, but something about the data or
|
18
24
|
# configuration just isn't ok.
|
19
25
|
#
|
20
|
-
module NRSER
|
21
26
|
class ConflictError < ::StandardError
|
22
27
|
include NRSER::NicerError
|
23
|
-
end
|
28
|
+
end # class ConflictError
|
29
|
+
|
30
|
+
|
31
|
+
# /Namespace
|
32
|
+
# ========================================================================
|
33
|
+
|
34
|
+
end # module NRSER
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Project / Package
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
require_relative './nicer_error'
|
11
|
+
|
12
|
+
|
13
|
+
# Namespace
|
14
|
+
# ========================================================================
|
15
|
+
|
16
|
+
module NRSER
|
17
|
+
|
18
|
+
|
19
|
+
# Definitions
|
20
|
+
# =======================================================================
|
21
|
+
|
22
|
+
# Raised in places where execution should *never* reach.
|
23
|
+
#
|
24
|
+
class UnreachableError < ::RuntimeError
|
25
|
+
include NRSER::NicerError
|
26
|
+
|
27
|
+
# The default message
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
#
|
31
|
+
def default_message
|
32
|
+
"An expression that should be unreachable has been executed"
|
33
|
+
end
|
34
|
+
|
35
|
+
end # class UnreachableError
|
36
|
+
|
37
|
+
|
38
|
+
# /Namespace
|
39
|
+
# ========================================================================
|
40
|
+
|
41
|
+
end # module NRSER
|
data/lib/nrser/graph/tsorter.rb
CHANGED
@@ -11,11 +11,11 @@
|
|
11
11
|
require 'tsort'
|
12
12
|
|
13
13
|
|
14
|
-
#
|
15
|
-
#
|
14
|
+
# Namespace
|
15
|
+
# ========================================================================
|
16
16
|
|
17
|
-
module
|
18
|
-
module
|
17
|
+
module NRSER
|
18
|
+
module Graph
|
19
19
|
|
20
20
|
|
21
21
|
# Definitions
|
@@ -23,7 +23,7 @@ module NRSER::Graph; end
|
|
23
23
|
|
24
24
|
# Topologically sorts an {Enumerable} by a user-provided `child_node` block.
|
25
25
|
#
|
26
|
-
class
|
26
|
+
class TSorter
|
27
27
|
include TSort
|
28
28
|
|
29
29
|
def initialize entries, &each_child
|
@@ -38,4 +38,11 @@ class NRSER::Graph::TSorter
|
|
38
38
|
def tsort_each_child node, &block
|
39
39
|
@each_child.call node, &block
|
40
40
|
end
|
41
|
-
end # class
|
41
|
+
end # class TSorter
|
42
|
+
|
43
|
+
|
44
|
+
# /Namespace
|
45
|
+
# ========================================================================
|
46
|
+
|
47
|
+
end # module Graph
|
48
|
+
end # module NRSER
|
data/lib/nrser/rspex.rb
CHANGED
@@ -103,7 +103,13 @@ class Wrapper
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def wrap description = nil, &block
|
106
|
-
|
106
|
+
if block
|
107
|
+
Wrapper.new description: description, &block
|
108
|
+
else
|
109
|
+
Wrapper.new description: description.to_s do
|
110
|
+
send description
|
111
|
+
end
|
112
|
+
end
|
107
113
|
end
|
108
114
|
|
109
115
|
def unwrap obj, context: nil
|
@@ -114,6 +120,10 @@ def unwrap obj, context: nil
|
|
114
120
|
end
|
115
121
|
end
|
116
122
|
|
123
|
+
def msg *args, &block
|
124
|
+
NRSER::Message.from *args, &block
|
125
|
+
end
|
126
|
+
|
117
127
|
|
118
128
|
def List *args
|
119
129
|
NRSER::RSpex::List.new args
|
@@ -30,5 +30,6 @@ require_relative './example_group/describe_sent_to'
|
|
30
30
|
require_relative './example_group/describe_setup'
|
31
31
|
require_relative './example_group/describe_source_file'
|
32
32
|
require_relative './example_group/describe_spec_file'
|
33
|
+
require_relative './example_group/describe_subject'
|
33
34
|
require_relative './example_group/describe_when'
|
34
35
|
require_relative './example_group/describe_x'
|
@@ -1,35 +1,53 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
4
|
+
# Namespace
|
5
|
+
# ========================================================================
|
6
|
+
|
7
|
+
module NRSER
|
8
|
+
module RSpex
|
9
|
+
module ExampleGroup
|
10
|
+
|
11
|
+
|
12
|
+
# Definitions
|
13
|
+
# ========================================================================
|
14
|
+
|
15
|
+
# Describe a {NRSER::Message}. Useful when you have a message that you want
|
16
|
+
# to send to many receivers (see {#describe_sent_to}).
|
17
|
+
#
|
18
|
+
# @note
|
19
|
+
# Since the block is used for the example group body, if you want to
|
20
|
+
# describe a message with a {NRSER::Message#block} your need to create
|
21
|
+
# the message yourself and pass it as the only argument.
|
22
|
+
#
|
23
|
+
# @see #describe_x
|
24
|
+
#
|
25
|
+
# @param [Array] args
|
26
|
+
# Passed to {NRSER::Message.from} to get or create the message instance.
|
27
|
+
#
|
28
|
+
# @param &body (see #describe_x)
|
29
|
+
#
|
30
|
+
# @return (see #describe_x)
|
31
|
+
#
|
32
|
+
def describe_message *args, &body
|
33
|
+
message = NRSER::Message.from *args
|
34
34
|
|
35
|
-
|
35
|
+
describe_x \
|
36
|
+
message,
|
37
|
+
type: :message,
|
38
|
+
metadata: {
|
39
|
+
message: message,
|
40
|
+
},
|
41
|
+
subject_block: -> { message.send_to super() },
|
42
|
+
&body
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :MESSAGE, :describe_message
|
46
|
+
|
47
|
+
|
48
|
+
# /Namespace
|
49
|
+
# ========================================================================
|
50
|
+
|
51
|
+
end # module ExampleGroup
|
52
|
+
end # module RSpex
|
53
|
+
end # module NRSER
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
|
5
|
+
# Namespace
|
6
|
+
# ========================================================================
|
7
|
+
|
8
|
+
module NRSER
|
9
|
+
module RSpex
|
10
|
+
module ExampleGroup
|
11
|
+
|
12
|
+
|
13
|
+
# Definitions
|
14
|
+
# ========================================================================
|
15
|
+
|
16
|
+
# Define a example group binding a subject.
|
17
|
+
#
|
18
|
+
# @note Experimental - only used in Rash at the moment. I've wanted *something*
|
19
|
+
# like this to make binding subject less noisy, but I'm not sure this is
|
20
|
+
# exactly it yet...
|
21
|
+
#
|
22
|
+
# @see #describe_x
|
23
|
+
#
|
24
|
+
# @param [Object] subject
|
25
|
+
# The value to bind as the subject. May be wrapped.
|
26
|
+
#
|
27
|
+
# @param [Hash<Symbol, Object>] metadata
|
28
|
+
# Optional metadata for the example group.
|
29
|
+
#
|
30
|
+
# @param &body (see #describe_x)
|
31
|
+
#
|
32
|
+
# @return (see #describe_x)
|
33
|
+
#
|
34
|
+
def describe_subject subject, **metadata, &body
|
35
|
+
describe_x \
|
36
|
+
subject,
|
37
|
+
type: :subject,
|
38
|
+
metadata: metadata,
|
39
|
+
subject_block: -> { unwrap subject, context: self },
|
40
|
+
&body
|
41
|
+
end
|
42
|
+
|
43
|
+
# Short name
|
44
|
+
alias_method :SUBJECT, :describe_subject
|
45
|
+
|
46
|
+
|
47
|
+
# /Namespace
|
48
|
+
# ========================================================================
|
49
|
+
|
50
|
+
end # module ExampleGroup
|
51
|
+
end # module RSpex
|
52
|
+
end # module NRSER
|
53
|
+
|
data/lib/nrser/types.rb
CHANGED
data/lib/nrser/types/arrays.rb
CHANGED
data/lib/nrser/types/booleans.rb
CHANGED
@@ -46,7 +46,7 @@ class Boolean < Is
|
|
46
46
|
# ========================================================================
|
47
47
|
|
48
48
|
def custom_from_s string
|
49
|
-
return value if self::STRINGS.include?( string.downcase )
|
49
|
+
return value if self.class::STRINGS.include?( string.downcase )
|
50
50
|
|
51
51
|
raise NRSER::Types::FromStringError.new \
|
52
52
|
type: self,
|
@@ -74,7 +74,7 @@ end # class Boolean
|
|
74
74
|
# Provides a {#custom_from_s} to load from CLI options and ENV var-like
|
75
75
|
# string values.
|
76
76
|
#
|
77
|
-
class
|
77
|
+
class TrueType < Boolean
|
78
78
|
|
79
79
|
STRINGS = NRSER::TRUTHY_STRINGS
|
80
80
|
|
@@ -92,7 +92,7 @@ end # class True
|
|
92
92
|
# Provides a {#custom_from_s} to load from CLI options and ENV var-like
|
93
93
|
# string values.
|
94
94
|
#
|
95
|
-
class
|
95
|
+
class FalseType < Boolean
|
96
96
|
|
97
97
|
STRINGS = NRSER::FALSY_STRINGS
|
98
98
|
|
@@ -116,7 +116,7 @@ end # class FalseType
|
|
116
116
|
#
|
117
117
|
def_type :True,
|
118
118
|
&->( **options ) do
|
119
|
-
|
119
|
+
TrueType.new **options
|
120
120
|
end
|
121
121
|
|
122
122
|
|
@@ -131,7 +131,7 @@ end
|
|
131
131
|
#
|
132
132
|
def_type :False,
|
133
133
|
&->( **options ) do
|
134
|
-
|
134
|
+
FalseType.new **options
|
135
135
|
end # .False
|
136
136
|
|
137
137
|
|
@@ -145,6 +145,8 @@ end # .False
|
|
145
145
|
#
|
146
146
|
def_type :Boolean,
|
147
147
|
aliases: [ :bool ],
|
148
|
+
default_name: ->( *args, &block ) { 'Boolean' },
|
149
|
+
symbolic: '𝔹',
|
148
150
|
&->( **options ) do
|
149
151
|
union self.True, self.False, **options
|
150
152
|
end # .Boolean
|
@@ -53,7 +53,7 @@ to access it via the API.
|
|
53
53
|
| `t.PositiveInteger` | `PositiveInteger` | `ℤ⁺` | `(Integer & Bounded<min=1>)` |
|
54
54
|
| `t.NegativeInteger` | `NegativeInteger` | `ℤ⁻` | `(Integer & Bounded<max=-1>)` |
|
55
55
|
| `t.NonNegativeInteger` | `NonNegativeInteger` | `ℕ⁰` | `(Integer & Bounded<min=0>)` |
|
56
|
-
| `t.Boolean` | `Boolean` |
|
56
|
+
| `t.Boolean` | `Boolean` | `𝔹` | `(Is<true> \| Is<false>)` |
|
57
57
|
| `t.Bounded( min: 1, max: 2 )` | `Bounded<min=1, max=2>` | `(1..2)` | `Bounded<min=1, max=2>` |
|
58
58
|
| `t.Bounded( min: 1 )` | `Bounded<min=1>` | `(1..)` | `Bounded<min=1>` |
|
59
59
|
| `t.Array` | `Array` | `[*]` | `Array` |
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Project / Package
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Need {Module.safe_name}
|
11
|
+
require 'nrser/core_ext/module/names'
|
12
|
+
|
13
|
+
# Need {Types.Top} for the default entry type
|
14
|
+
require_relative './top'
|
15
|
+
|
16
|
+
|
17
|
+
# Namespace
|
18
|
+
# =======================================================================
|
19
|
+
|
20
|
+
module NRSER
|
21
|
+
module Types
|
22
|
+
|
23
|
+
|
24
|
+
# Definitions
|
25
|
+
# =======================================================================
|
26
|
+
|
27
|
+
# Type class that parameterizes {Enumerable} values of a homogeneous type.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# array_of_int = NRSER::Types::EnumerableType.new Array, Integer
|
31
|
+
# array_of_int.test? [1, 2, 3] #=> true
|
32
|
+
# array_of_int.test? [1, 2, 'three'] #=> false
|
33
|
+
# array_of_int.test? 'blah' #=> false
|
34
|
+
# array_of_int.test? [] #=> true
|
35
|
+
#
|
36
|
+
class EnumerableType < IsA
|
37
|
+
|
38
|
+
# Attributes
|
39
|
+
# ========================================================================
|
40
|
+
|
41
|
+
# Type all entries must satisfy.
|
42
|
+
#
|
43
|
+
# @return [Type]
|
44
|
+
#
|
45
|
+
attr_reader :entry_type
|
46
|
+
|
47
|
+
|
48
|
+
# Construction
|
49
|
+
# ========================================================================
|
50
|
+
|
51
|
+
# Instantiate a new `EnumerableType`.
|
52
|
+
def initialize enumerable_type = ::Enumerable,
|
53
|
+
entry_type = self.Top,
|
54
|
+
**options
|
55
|
+
super enumerable_type, **options
|
56
|
+
@entry_type = Types.make entry_type
|
57
|
+
end # #initialize
|
58
|
+
|
59
|
+
|
60
|
+
# Instance Methods
|
61
|
+
# ========================================================================
|
62
|
+
|
63
|
+
# @!group Display Instance Methods
|
64
|
+
# ------------------------------------------------------------------------
|
65
|
+
|
66
|
+
def explain
|
67
|
+
"#{ enumerable_type.safe_name }<#{ entry_type.explain }>"
|
68
|
+
end
|
69
|
+
|
70
|
+
# @!endgroup Display Instance Methods # ************************************
|
71
|
+
|
72
|
+
|
73
|
+
# Intuitive alias for {IsA#mod}.
|
74
|
+
#
|
75
|
+
# @return [Class]
|
76
|
+
#
|
77
|
+
def enumerable_type; mod; end
|
78
|
+
|
79
|
+
|
80
|
+
def test? value
|
81
|
+
# Test that `value` is of the right container class first
|
82
|
+
return false unless super( value )
|
83
|
+
|
84
|
+
# If that passed test all the entries against the type
|
85
|
+
value.all? &@entry_type.method( :test? )
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
end # class EnumerableType
|
90
|
+
|
91
|
+
|
92
|
+
# @!group Enumerable Type Factories
|
93
|
+
# --------------------------------------------------------------------------
|
94
|
+
|
95
|
+
# @!method self.Enumerable_ enumerable_type = ::Enumerable, entry_type = self.Top, **options
|
96
|
+
#
|
97
|
+
# @todo
|
98
|
+
# YARDdoc method name has an `_` suffix added to hack around an apparent
|
99
|
+
# bug in YARD - it seems the method name `Enumerable` matching the
|
100
|
+
# `Enumerable` class causes failure:
|
101
|
+
#
|
102
|
+
# ```
|
103
|
+
# [error]: Exception occurred while generating 'NRSER/Types/Type.html'
|
104
|
+
# [error]: ArgumentError: Invalid namespace object: #<yardoc method NRSER::Types.Enumerable>:YARD::CodeObjects::MethodObject
|
105
|
+
# [error]: Stack trace:
|
106
|
+
# //.bundle/ruby/2.3.0/gems/yard-0.9.16/lib/yard/code_objects/proxy.rb:67:in `initialize'
|
107
|
+
# //.bundle/ruby/2.3.0/gems/yard-0.9.16/lib/yard/registry_resolver.rb:87:in `new'
|
108
|
+
# //.bundle/ruby/2.3.0/gems/yard-0.9.16/lib/yard/registry_resolver.rb:87:in `lookup_by_path'
|
109
|
+
# //.bundle/ruby/2.3.0/gems/yard-0.9.16/lib/yard/registry.rb:304:in `resolve'
|
110
|
+
# //.bundle/ruby/2.3.0/gems/yard-0.9.16/lib/yard/templates/helpers/html_helper.rb:292:in `link_object'
|
111
|
+
# //.bundle/ruby/2.3.0/gems/yard-link_stdlib-0.1.0/lib/yard/link_stdlib/html_helper.rb:77:in `link_object'
|
112
|
+
# ```
|
113
|
+
#
|
114
|
+
# Types that parameterize {Enumerable} values of a homogeneous type.
|
115
|
+
#
|
116
|
+
# @param [Class] enumerable_type
|
117
|
+
# Required class of the container itself.
|
118
|
+
#
|
119
|
+
# @param [Type | Object] entry_type
|
120
|
+
# Type of the entries. If this is not a {Type}, one will be created from
|
121
|
+
# it via {NRSER::Types.make}.
|
122
|
+
#
|
123
|
+
# @param [Hash] options
|
124
|
+
# Passed to {Type#initialize}.
|
125
|
+
#
|
126
|
+
# @return [Type]
|
127
|
+
#
|
128
|
+
def_type :Enumerable,
|
129
|
+
aliases: [ :Enum, :enum ],
|
130
|
+
parameterize: [ :enumerable_type, :entry_type ],
|
131
|
+
&->( enumerable_type = ::Enumerable, entry_type = self.Top, **options ) do
|
132
|
+
EnumerableType.new enumerable_type, entry_type, **options
|
133
|
+
end # .Enumerable
|
134
|
+
|
135
|
+
|
136
|
+
# @!endgroup Enumerable Type Factories # ***********************************
|
137
|
+
|
138
|
+
# /Namespace
|
139
|
+
# =======================================================================
|
140
|
+
|
141
|
+
end # module Types
|
142
|
+
end # module NRSER
|
data/lib/nrser/types/factory.rb
CHANGED
@@ -113,36 +113,44 @@ module Factory
|
|
113
113
|
#
|
114
114
|
# @param [nil | false | Proc<(*args, &block): String>] default_name
|
115
115
|
#
|
116
|
-
# Controls
|
117
|
-
#
|
116
|
+
# Controls the default value assigned to the `name:` keyword argument (only
|
117
|
+
# relevant when a `name:` value is *not* explicitly passed when building the
|
118
|
+
# type).
|
118
119
|
#
|
119
120
|
# Everything here is done *before* the `options` are passed to the
|
120
|
-
# factory method's `&body`, so the body will see
|
121
|
-
#
|
121
|
+
# factory method's `&body`, so the body will see the default `name:` value
|
122
|
+
# in the factory method body.
|
122
123
|
#
|
123
124
|
# When...
|
124
125
|
#
|
125
|
-
# - `nil`
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
126
|
+
# - `default_name == nil`
|
127
|
+
#
|
128
|
+
# Behavior depends on the value of the `parameterize:` keyword:
|
129
|
+
#
|
130
|
+
# - `parameterize == nil`
|
131
|
+
#
|
132
|
+
# The `name` parameter will be used as the default value.
|
129
133
|
#
|
130
134
|
# This situation covers "static" types that will only differ by
|
131
|
-
# their `options`
|
132
|
-
#
|
133
|
-
#
|
135
|
+
# their `options` (custom {Type#from_s}, {Type#to_data}, etc.).
|
136
|
+
# Really, these are more like aliases since the types' member sets
|
137
|
+
# are identical.
|
134
138
|
#
|
135
|
-
# - `parameterize
|
136
|
-
# as `nil` if none is provided by the factory caller.
|
139
|
+
# - `parameterize != nil`
|
137
140
|
#
|
138
|
-
#
|
139
|
-
#
|
141
|
+
# The default `name:` value will be left as `nil`.
|
142
|
+
#
|
143
|
+
# - `default_name == false`
|
144
|
+
#
|
145
|
+
# The `name:` option will not be touched - it will stay `nil` unless the
|
146
|
+
# factory caller provides a value.
|
140
147
|
#
|
141
|
-
# - `Proc<(*args, &block)->String>`
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
# that
|
148
|
+
# - `default_name is a Proc<(*args, &block)->String>`
|
149
|
+
#
|
150
|
+
# When the factory caller does not provide a `name:` option this
|
151
|
+
# function will be called with the arguments (including `options`) and
|
152
|
+
# block (if any) that the factory method was called with, and is
|
153
|
+
# expected to return a {String} that will be set as the `name:` option.
|
146
154
|
#
|
147
155
|
# @param [nil | Symbol | Array<Symbol>] parameterize
|
148
156
|
# Indicates if the type is parameterized, and, if so, what arguments
|
@@ -200,9 +208,9 @@ module Factory
|
|
200
208
|
unless default_name.nil? ||
|
201
209
|
default_name == false ||
|
202
210
|
default_name.is_a?( Proc )
|
203
|
-
raise NRSER::TypeError
|
211
|
+
raise NRSER::TypeError.new \
|
204
212
|
"`default_name:` keyword argument must be {nil}, {false} or a {Proc},",
|
205
|
-
"found", default_name,
|
213
|
+
"found", default_name.inspect,
|
206
214
|
expected: [ nil, false, Proc ],
|
207
215
|
received: default_name
|
208
216
|
end
|
data/lib/nrser/types/numbers.rb
CHANGED
data/lib/nrser/types/paths.rb
CHANGED
@@ -167,6 +167,15 @@ def_type :HomePath,
|
|
167
167
|
end # .HomePath
|
168
168
|
|
169
169
|
|
170
|
+
def_type :TildePath,
|
171
|
+
&->( **options ) do
|
172
|
+
self.Intersection \
|
173
|
+
self.Path,
|
174
|
+
self.When( TILDE_PATH_RE ),
|
175
|
+
**options
|
176
|
+
end # .TildePath
|
177
|
+
|
178
|
+
|
170
179
|
# @!method self.AbsPath **options
|
171
180
|
# A relative {.Path}, which is just a {.Path} that's not {.AbsPath} or
|
172
181
|
# {.TildePath}.
|
data/lib/nrser/types/top.rb
CHANGED
@@ -30,6 +30,11 @@ class Top < NRSER::Types::Type
|
|
30
30
|
|
31
31
|
def initialize
|
32
32
|
super name: NAME
|
33
|
+
|
34
|
+
# All types maybe *should* be frozen so they can be used as prop defaults,
|
35
|
+
# but this is the first one I ran into in practice, so it's the first one
|
36
|
+
# to freeze.
|
37
|
+
freeze
|
33
38
|
end
|
34
39
|
|
35
40
|
def test? value
|
data/lib/nrser/version.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'nrser/refinements/types'
|
5
|
+
using NRSER::Types
|
6
|
+
|
7
|
+
|
8
|
+
SPEC_FILE(
|
9
|
+
spec_path: __FILE__,
|
10
|
+
module: NRSER::Types,
|
11
|
+
method: :Enumerable,
|
12
|
+
) do
|
13
|
+
|
14
|
+
it_behaves_like 'type maker method'
|
15
|
+
|
16
|
+
include_examples 'make type',
|
17
|
+
args: [ Array, Integer ],
|
18
|
+
|
19
|
+
accepts: [
|
20
|
+
[],
|
21
|
+
[1, 2, 3],
|
22
|
+
],
|
23
|
+
|
24
|
+
rejects: [
|
25
|
+
nil,
|
26
|
+
{},
|
27
|
+
Set[1, 2, 3],
|
28
|
+
],
|
29
|
+
|
30
|
+
and_is_expected: {
|
31
|
+
to: {
|
32
|
+
have_attributes: {
|
33
|
+
class: t::EnumerableType,
|
34
|
+
name: 'Array<Integer>',
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
end # SPEC_FILE
|
@@ -92,8 +92,25 @@ SPEC_FILE(
|
|
92
92
|
end # METHOD .path_seg
|
93
93
|
|
94
94
|
|
95
|
-
METHOD :
|
96
|
-
|
95
|
+
METHOD :TildePath do
|
96
|
+
include_examples 'make type',
|
97
|
+
accepts: [
|
98
|
+
'~',
|
99
|
+
'~/blah',
|
100
|
+
],
|
101
|
+
|
102
|
+
rejects: [
|
103
|
+
'hey/ho',
|
104
|
+
'./blah',
|
105
|
+
],
|
106
|
+
|
107
|
+
and_is_expected: {
|
108
|
+
to: {
|
109
|
+
have_attributes: {
|
110
|
+
name: 'TildePath',
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
97
114
|
end # METHOD .tilde_path Description
|
98
115
|
|
99
116
|
|
@@ -22,14 +22,22 @@ describe NRSER::Types do
|
|
22
22
|
fail: [{}],
|
23
23
|
},
|
24
24
|
|
25
|
-
t.
|
25
|
+
t.True => {
|
26
26
|
pass: [true],
|
27
27
|
fail: [1, 'true'],
|
28
|
+
from_s: {
|
29
|
+
pass: [ 'true', 'True', '1', 'T', 't'],
|
30
|
+
fail: [ 'f', '100' ],
|
31
|
+
}
|
28
32
|
},
|
29
33
|
|
30
|
-
t.
|
34
|
+
t.False => {
|
31
35
|
pass: [false],
|
32
36
|
fail: [true, 0, nil, 'false'],
|
37
|
+
from_s: {
|
38
|
+
pass: [ 'false', 'f', 'F', '0' ],
|
39
|
+
fail: [ 't', '-1' ],
|
40
|
+
}
|
33
41
|
},
|
34
42
|
|
35
43
|
t.bool => {
|
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.3.
|
4
|
+
version: 0.3.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nrser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hamster
|
@@ -31,6 +31,9 @@ dependencies:
|
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '4.2'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '4.4'
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -38,6 +41,9 @@ dependencies:
|
|
38
41
|
- - "~>"
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '4.2'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '4.4'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: awesome_print
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,9 +118,6 @@ dependencies:
|
|
112
118
|
name: bundler
|
113
119
|
requirement: !ruby/object:Gem::Requirement
|
114
120
|
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '1.16'
|
118
121
|
- - ">="
|
119
122
|
- !ruby/object:Gem::Version
|
120
123
|
version: 1.16.1
|
@@ -122,9 +125,6 @@ dependencies:
|
|
122
125
|
prerelease: false
|
123
126
|
version_requirements: !ruby/object:Gem::Requirement
|
124
127
|
requirements:
|
125
|
-
- - "~>"
|
126
|
-
- !ruby/object:Gem::Version
|
127
|
-
version: '1.16'
|
128
128
|
- - ">="
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: 1.16.1
|
@@ -312,9 +312,11 @@ files:
|
|
312
312
|
- lib/nrser/collection.rb
|
313
313
|
- lib/nrser/core_ext.rb
|
314
314
|
- lib/nrser/core_ext/array.rb
|
315
|
+
- lib/nrser/core_ext/array/to_proc.rb
|
315
316
|
- lib/nrser/core_ext/binding.rb
|
316
317
|
- lib/nrser/core_ext/enumerable.rb
|
317
318
|
- lib/nrser/core_ext/enumerable/find_map.rb
|
319
|
+
- lib/nrser/core_ext/enumerable/slash_map.rb
|
318
320
|
- lib/nrser/core_ext/exception.rb
|
319
321
|
- lib/nrser/core_ext/hash.rb
|
320
322
|
- lib/nrser/core_ext/hash/bury.rb
|
@@ -344,6 +346,7 @@ files:
|
|
344
346
|
- lib/nrser/errors/count_error.rb
|
345
347
|
- lib/nrser/errors/nicer_error.rb
|
346
348
|
- lib/nrser/errors/type_error.rb
|
349
|
+
- lib/nrser/errors/unreachable_error.rb
|
347
350
|
- lib/nrser/errors/value_error.rb
|
348
351
|
- lib/nrser/ext/tree.rb
|
349
352
|
- lib/nrser/functions.rb
|
@@ -462,6 +465,7 @@ files:
|
|
462
465
|
- lib/nrser/rspex/example_group/describe_setup.rb
|
463
466
|
- lib/nrser/rspex/example_group/describe_source_file.rb
|
464
467
|
- lib/nrser/rspex/example_group/describe_spec_file.rb
|
468
|
+
- lib/nrser/rspex/example_group/describe_subject.rb
|
465
469
|
- lib/nrser/rspex/example_group/describe_when.rb
|
466
470
|
- lib/nrser/rspex/example_group/describe_x.rb
|
467
471
|
- lib/nrser/rspex/example_group/overrides.rb
|
@@ -480,6 +484,7 @@ files:
|
|
480
484
|
- lib/nrser/types/collections.rb
|
481
485
|
- lib/nrser/types/combinators.rb
|
482
486
|
- lib/nrser/types/doc/display_table.md
|
487
|
+
- lib/nrser/types/enumerables.rb
|
483
488
|
- lib/nrser/types/eqiuvalent.rb
|
484
489
|
- lib/nrser/types/errors/check_error.rb
|
485
490
|
- lib/nrser/types/errors/from_string_error.rb
|
@@ -570,6 +575,7 @@ files:
|
|
570
575
|
- spec/lib/nrser/types/attrs_spec.rb
|
571
576
|
- spec/lib/nrser/types/combinators_spec.rb
|
572
577
|
- spec/lib/nrser/types/display_spec.rb
|
578
|
+
- spec/lib/nrser/types/enumerables_spec.rb
|
573
579
|
- spec/lib/nrser/types/is_spec.rb
|
574
580
|
- spec/lib/nrser/types/pairs_spec.rb
|
575
581
|
- spec/lib/nrser/types/paths_spec.rb
|
@@ -629,6 +635,7 @@ test_files:
|
|
629
635
|
- spec/lib/nrser/types/strings_spec.rb
|
630
636
|
- spec/lib/nrser/types/symbols_spec.rb
|
631
637
|
- spec/lib/nrser/types/tuples_spec.rb
|
638
|
+
- spec/lib/nrser/types/enumerables_spec.rb
|
632
639
|
- spec/lib/nrser/types/attrs_spec.rb
|
633
640
|
- spec/lib/nrser/core_ext/hash/short_transform_keys_spec.rb
|
634
641
|
- spec/lib/nrser/core_ext/hash_spec.rb
|