nrser 0.3.7 → 0.3.8

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: ea96a298163ec6b20a0437bc7ab7c8ea9200fd99
4
- data.tar.gz: c6aabc018e890bfa791e20925b2c32240c4110d7
3
+ metadata.gz: 20a9f5822833e3797ebf2ec2ba0b6e430ad7346e
4
+ data.tar.gz: 0dc5e6c87d30f0d9ed99692b33da84a4f2584db9
5
5
  SHA512:
6
- metadata.gz: 29d05d08cc6d63ee707ad4ce1bf34b4b148a132ee669749ad1a01eb392ba1ef6d842c1be240cbf0ec2d514e3acd320c70e2f84e86376d93ad54a688ffa428244
7
- data.tar.gz: 4dc97cdc270fc79692b1a7ffcba3c569ae3649247f78e16b128603933c40ebb05c925fe934b53a5c082f23788cde3444ba4cf7f082143b27274c53104647cac5
6
+ metadata.gz: 374129784c79fe2897c078beed6e4d7c168e9b2e79027bf293df15403eac73a505176db6238f2c9b14ba8d2ecbda399e61c5f2a57cce4b8ec79a0c7a12ec031e
7
+ data.tar.gz: ae5a9bb34f77b6d35976fbed02fa85b8267a34b9cfb0a0ec0b4db6b39bae1d38ed08c3c994f27439f437580ebc9023c6d23c19ef827b58691a5aca0969f4e17a
@@ -92,6 +92,16 @@ class Pathname
92
92
  end
93
93
 
94
94
 
95
+ # Shortcut to call {#to_rel} with `dot_slash=true`.
96
+ #
97
+ # @param base_dir: (see .to_rel)
98
+ # @return (see .to_rel)
99
+ #
100
+ def to_dot_rel **kwds
101
+ to_rel **kwds, dot_slash: true
102
+ end # #to_dot_rel
103
+
104
+
95
105
  # Just a quick cut for `.to_rel.to_s`, since I seem to use that sort of form
96
106
  # a lot.
97
107
  #
@@ -99,8 +109,18 @@ class Pathname
99
109
  #
100
110
  # @return [String]
101
111
  #
102
- def to_rel_s *args
103
- to_rel( *args ).to_s
112
+ def to_rel_s **kwds
113
+ to_rel( **kwds ).to_s
114
+ end
115
+
116
+
117
+ # Shortcut to call {#to_rel_s} with `dot_slash=true`.
118
+ #
119
+ # @param base_dir: (see .to_rel_s)
120
+ # @return (see .to_rel_s)
121
+ #
122
+ def to_dot_rel_s **kwds
123
+ to_rel_s( **kwds, dot_slash: true ).to_s
104
124
  end
105
125
 
106
126
  end # class Pathname
@@ -1,10 +1,27 @@
1
- module NRSER::Ext; end
1
+ # frozen_string_literal: true
2
+ # encoding: UTF-8
3
+
4
+
5
+ # Requirements
6
+ # ========================================================================
7
+
8
+ # Project / Package
9
+ # ------------------------------------------------------------------------
10
+
11
+ require 'nrser/functions/tree'
12
+
13
+
14
+ # Namespace
15
+ # ========================================================================
16
+
17
+ module NRSER
18
+ module Ext
2
19
 
3
20
 
4
21
  # Instance methods that are refined in to the Ruby built-ins that we consider
5
22
  # trees: {Array}, {Hash} and {OpenStruct}.
6
23
  #
7
- module NRSER::Ext::Tree
24
+ module Tree
8
25
 
9
26
  # Sends `self` to {NRSER.leaves}.
10
27
  def leaves
@@ -39,4 +56,11 @@ module NRSER::Ext::Tree
39
56
  NRSER.map_tree self, **options, &block
40
57
  end
41
58
 
42
- end # module NRSER::Ext::Tree
59
+ end # module Tree
60
+
61
+
62
+ # /Namespace
63
+ # ========================================================================
64
+
65
+ end # module Ext
66
+ end # module NRSER
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ require 'hamster'
11
+
12
+ require 'nrser/ext/tree'
13
+
14
+
15
+ # Namespace
16
+ # =======================================================================
17
+
18
+ module Hamster
19
+
20
+
21
+ # Definitions
22
+ # =======================================================================
23
+
24
+ class Hash
25
+
26
+ include NRSER::Ext::Tree
27
+
28
+ # Instance Methods
29
+ # ========================================================================
30
+
31
+ def to_mutable
32
+ each_with_object( {} ) { |(key, value), hash|
33
+ hash[ Hamster.to_mutable key ] = Hamster.to_mutable value
34
+ }
35
+ end
36
+
37
+
38
+ def as_json options = nil
39
+ to_h.as_json options
40
+ end
41
+
42
+
43
+ def to_yaml *args, &block
44
+ to_mutable.to_yaml *args, &block
45
+ end
46
+
47
+ end # class Hash
48
+
49
+
50
+ # /Namespace
51
+ # =======================================================================
52
+
53
+ end # module Hamster
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Stdlib
8
+ # ----------------------------------------------------------------------------
9
+
10
+ require 'set'
11
+
12
+ # Deps
13
+ # -----------------------------------------------------------------------
14
+
15
+ require 'hamster'
16
+
17
+ require 'nrser/ext/tree'
18
+
19
+
20
+ # Namespace
21
+ # =======================================================================
22
+
23
+ module Hamster
24
+
25
+
26
+ # Definitions
27
+ # =======================================================================
28
+
29
+ class Set
30
+
31
+ # Instance Methods
32
+ # ========================================================================
33
+
34
+ def to_mutable
35
+ each_with_object( ::Set[] ) { |member, set|
36
+ set << Hamster.to_mutable( member )
37
+ }
38
+ end
39
+
40
+
41
+ def to_mutable_array
42
+ each_with_object( [] ) { |member, array|
43
+ array << Hamster.to_mutable( member )
44
+ }
45
+ end
46
+
47
+
48
+ def to_h
49
+ each_with_object( {} ) { |member, hash| hash[member] = true }
50
+ end
51
+
52
+
53
+ def as_json options = nil
54
+ to_mutable_array.to_json options
55
+ # { '$set' => to_h.as_json( options ) }
56
+ end
57
+
58
+
59
+ def to_yaml *args, &block
60
+ to_mutable.to_yaml *args, &block
61
+ end
62
+
63
+ end # class Hash
64
+
65
+
66
+ # /Namespace
67
+ # =======================================================================
68
+
69
+ end # module Hamster
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Stdlib
8
+ # ----------------------------------------------------------------------------
9
+
10
+ require 'set'
11
+
12
+ # Deps
13
+ # -----------------------------------------------------------------------
14
+
15
+ require 'hamster'
16
+
17
+ require 'nrser/ext/tree'
18
+
19
+
20
+ # Namespace
21
+ # =======================================================================
22
+
23
+ module Hamster
24
+
25
+
26
+ # Definitions
27
+ # =======================================================================
28
+
29
+ class SortedSet
30
+
31
+ # Instance Methods
32
+ # ========================================================================
33
+
34
+ def to_mutable
35
+ each_with_object( ::SortedSet[] ) { |member, set|
36
+ set << Hamster.to_mutable( member )
37
+ }
38
+ end
39
+
40
+
41
+ def to_mutable_array
42
+ each_with_object( [] ) { |member, array|
43
+ array << Hamster.to_mutable( member )
44
+ }
45
+ end
46
+
47
+
48
+ def to_h
49
+ each_with_object( {} ) { |member, hash| hash[member] = true }
50
+ end
51
+
52
+
53
+ def as_json options = nil
54
+ to_mutable_array.to_json options
55
+ # { '$set' => to_h.as_json( options ) }
56
+ end
57
+
58
+
59
+ def to_yaml *args, &block
60
+ to_mutable.to_yaml *args, &block
61
+ end
62
+
63
+ end # class Hash
64
+
65
+
66
+ # /Namespace
67
+ # =======================================================================
68
+
69
+ end # module Hamster
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ require 'hamster'
11
+
12
+ require 'nrser/ext/tree'
13
+
14
+
15
+ # Namespace
16
+ # =======================================================================
17
+
18
+ module Hamster
19
+
20
+
21
+ # Definitions
22
+ # =======================================================================
23
+
24
+ class Vector
25
+
26
+ include NRSER::Ext::Tree
27
+
28
+ # Instance Methods
29
+ # ========================================================================
30
+
31
+ def to_mutable
32
+ each_with_object( [] ) { |entry, array|
33
+ array << Hamster.to_mutable( entry )
34
+ }
35
+ end
36
+
37
+
38
+ def as_json options = nil
39
+ to_mutable.as_json options
40
+ end
41
+
42
+
43
+ def to_yaml *args, &block
44
+ to_mutable.to_yaml *args, &block
45
+ end
46
+
47
+ end # class Hash
48
+
49
+
50
+ # /Namespace
51
+ # =======================================================================
52
+
53
+ end # module Hamster
@@ -0,0 +1,36 @@
1
+ require 'set'
2
+
3
+ require 'hamster'
4
+ require_relative './hamster/hash'
5
+ require_relative './hamster/vector'
6
+ require_relative './hamster/set'
7
+ require_relative './hamster/sorted_set'
8
+
9
+ module Hamster
10
+ # def self.regrow each_pair: ::Hash, each_index: ::Array, each:
11
+
12
+ def self.to_mutable obj
13
+ if obj.respond_to? :to_mutable
14
+ obj.to_mutable
15
+
16
+ elsif ::Array === obj
17
+ obj.map { |e| to_mutable e }
18
+
19
+ elsif ::Hash === obj
20
+ obj.each_with_object( {} ) { |(k, v), h|
21
+ h[ to_mutable k ] = to_mutable v
22
+ }
23
+
24
+ elsif ::SortedSet === obj
25
+ ::SortedSet.new obj.map { |m| to_mutable m }
26
+
27
+ elsif ::Set === obj
28
+ ::Set.new obj.map { |m| to_mutable m }
29
+
30
+ else
31
+ obj
32
+
33
+ end
34
+ end # .to_mutable
35
+
36
+ end
@@ -0,0 +1,233 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Stdlib
8
+ # -----------------------------------------------------------------------
9
+ require 'set'
10
+
11
+ # Deps
12
+ # -----------------------------------------------------------------------
13
+ require 'hamster'
14
+
15
+ # Project / Package
16
+ # -----------------------------------------------------------------------
17
+ require 'nrser/errors/type_error'
18
+ require 'nrser/props/immutable/hash'
19
+ require 'nrser/props/immutable/vector'
20
+
21
+ require 'nrser/refinements/types'
22
+ using NRSER::Types
23
+
24
+
25
+ # Definitions
26
+ # =======================================================================
27
+
28
+ # Sick of typing "Hamster::Hash"...
29
+ #
30
+ # Experimental Hamster sugary sweet builder shortcut things.
31
+ #
32
+ module I8
33
+
34
+ # Easy way to get the class names shorter..?
35
+ class Vector < Hamster::Vector; end
36
+ class Hash < Hamster::Hash; end
37
+ class Set < Hamster::Set; end
38
+ class SortedSet < Hamster::SortedSet; end
39
+ # class List < Hamster::List; end # Not a class! Ugh...
40
+
41
+
42
+ module Struct
43
+
44
+ def self.check_new_args! vector_prop_defs, hash_prop_defs
45
+
46
+ unless (vector_prop_defs.empty? && !hash_prop_defs.empty?) ||
47
+ (!vector_prop_defs.empty? && hash_prop_defs.empty?)
48
+
49
+ raise NRSER::ArgumentError.new \
50
+ "Exactly one of *args or **kwds must be empty",
51
+
52
+ args: vector_prop_defs,
53
+
54
+ kwds: hash_prop_defs,
55
+
56
+ details: -> {%{
57
+ {I8::Struct.define} proxies to either
58
+
59
+ 1. {I8::Struct::Vector.define}
60
+ 2. {I8::Struct::Hash.define}
61
+
62
+ depending on *where* the property definitions are passed:
63
+
64
+ 1. Positionally in `*args` -> {I8::Struct::Vector.new}
65
+ 2. By name in `**kwds` -> {I8::Struct::Hash.new}
66
+
67
+ Examples:
68
+
69
+ 1. Create a Point struct backed by an {I8::Vector}:
70
+
71
+ Point = I8::Struct.define [x: t.int], [y: t.int]
72
+
73
+ 2. Create a Point struct backed by an {I8::Hash}:
74
+
75
+ Point = I8::Struct.define x: t.int, y: t.int
76
+
77
+ }}
78
+
79
+ end # unless vector_prop_defs.empty? XOR hash_prop_defs.empty?
80
+
81
+ end # .check_new_args!
82
+
83
+ private_class_method :check_new_args!
84
+
85
+
86
+ def self.define *vector_prop_defs, **hash_prop_defs, &body
87
+ check_new_args! vector_prop_defs, hash_prop_defs
88
+
89
+ if !vector_prop_defs.empty?
90
+ raise "not implemented"
91
+ # I8::Struct::Vector.new
92
+ else
93
+ I8::Struct::Hash.new **hash_prop_defs, &body
94
+ end
95
+ end
96
+
97
+ singleton_class.send :alias_method, :new, :define
98
+
99
+
100
+ end # module Struct
101
+
102
+
103
+ class Struct::Hash < I8::Hash
104
+ include I8::Struct
105
+ include NRSER::Props::Immutable::Hash
106
+
107
+ def self.define **prop_defs, &body
108
+ Class.new( I8::Struct::Hash ) do
109
+ prop_defs.each do |name, settings|
110
+ kwds = t.match settings,
111
+ t.type, ->( type ) {{ type: type }},
112
+ t.hash_, settings
113
+
114
+ prop name, **kwds
115
+ end
116
+
117
+ class_exec &body if body
118
+ end
119
+ end
120
+
121
+ def self.new *args, **kwds, &block
122
+ if self == I8::Struct::Hash
123
+ define *args, **kwds, &block
124
+ else
125
+ # See NOTE in {I8::Struct::Vector.new}
126
+ if kwds.empty?
127
+ super( *args, &block )
128
+ else
129
+ super( *args, **kwds, &block )
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+
136
+ class Struct::Vector < I8::Vector
137
+ include I8::Struct
138
+ include NRSER::Props::Immutable::Vector
139
+
140
+ def self.define *prop_defs, &body
141
+ # Unwrap `[name: type]` format
142
+ prop_defs.map! { |prop_def|
143
+ if ::Array === prop_def &&
144
+ prop_def.length == 1 &&
145
+ ::Hash === prop_def[0]
146
+ prop_def[0]
147
+ else
148
+ prop_def
149
+ end
150
+ }
151
+
152
+ # Check we have a list of pairs with label keys
153
+ t.array( t.pair( key: t.label ) ).check! prop_defs
154
+
155
+ Class.new( I8::Struct::Vector ) do
156
+ prop_defs.each_with_index do |pair, index|
157
+ name, settings = pair.first
158
+
159
+ kwds = t.match settings,
160
+ t.type, ->( type ) {{ type: type }},
161
+ t.hash_, settings
162
+
163
+ prop name, **kwds, index: index
164
+ end
165
+
166
+ class_exec &body if body
167
+ end
168
+ end
169
+
170
+
171
+ def self.new *args, **kwds, &block
172
+ if self == I8::Struct::Vector
173
+ unless kwds.empty?
174
+ raise NRSER::ArgumentError.new \
175
+ "Can not supply keyword args",
176
+ args: args,
177
+ kwds: kwds
178
+ end
179
+
180
+ define *args, &block
181
+ else
182
+ # NOTE This is... weird. Just doing the normal
183
+ #
184
+ # super( *args, **kwds, &block )
185
+ #
186
+ # results in `*args` becoming `[*args, {}]` up the super chain
187
+ # when `kwds` is empty.
188
+ #
189
+ # I can't say I can understand it, but I seem to be able to fix
190
+ # it.
191
+ #
192
+ if kwds.empty?
193
+ super( *args, &block )
194
+ else
195
+ super( *args, **kwds, &block )
196
+ end
197
+ end
198
+ end
199
+
200
+ end # class Struct::Vector
201
+
202
+
203
+ def self.[] value
204
+ case value
205
+ when Hamster::Hash,
206
+ Hamster::Vector,
207
+ Hamster::Set,
208
+ Hamster::SortedSet,
209
+ Hamster::List
210
+ value
211
+ when ::Hash
212
+ I8::Hash[value]
213
+ when ::Array
214
+ I8::Vector.new value
215
+ when ::Set
216
+ I8::Set.new value
217
+ when ::SortedSet
218
+ I8::SortedSet.new value
219
+ else
220
+ raise NRSER::TypeError.new \
221
+ "Value must be Hash, Array, Set or SortedSet",
222
+ found: value
223
+ end
224
+ end # .[]
225
+
226
+ end # module I8
227
+
228
+
229
+ # Method proxy to {I8.[]} allowing for different syntaxes.
230
+ #
231
+ def I8 value = nil
232
+ I8[ value || yield ]
233
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Deps
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Need {SemanticLogger::LEVELS}
11
+ require 'semantic_logger'
12
+
13
+
14
+ # Refinements
15
+ # =======================================================================
16
+
17
+ require 'nrser/refinements/types'
18
+ using NRSER::Types
19
+
20
+
21
+ # Namespace
22
+ # =======================================================================
23
+
24
+ module NRSER
25
+ module Log
26
+
27
+
28
+ # Definitions
29
+ # =======================================================================
30
+
31
+ # Types for logging type things.
32
+ #
33
+ # @note
34
+ # This module is **NOT** required when loading {NRSER::Log}, and it **NEVER**
35
+ # should be! It is here for *other* gems and apps that depend on {NRSER}
36
+ # to use.
37
+ #
38
+ # Core logging should have the absolute minimal dependencies, because it's
39
+ # pretty much always going to be loaded and nothing it depends on can use
40
+ # it when loading up.
41
+ #
42
+ module Types
43
+ extend NRSER::Types::Factory
44
+
45
+ def_factory :level do |
46
+ name: 'LogLevel',
47
+ from_s: ->( string ) { string.to_sym },
48
+ **options
49
+ |
50
+ t.in SemanticLogger::LEVELS, from_s: from_s, name: name, **options
51
+ end
52
+
53
+
54
+ def_factory :stdio do |
55
+ name: 'StdIO',
56
+
57
+ from_s: ->( string ) {
58
+ case string
59
+ when '$stdout'
60
+ $stdout
61
+ when '$stderr'
62
+ $stderr
63
+ when 'STDOUT'
64
+ STDOUT
65
+ when 'STDERR'
66
+ STDERR
67
+ end
68
+ },
69
+
70
+ **options
71
+ |
72
+ t.is_a IO, name: name, from_s: from_s, **options
73
+ end
74
+
75
+ end # module Types
76
+
77
+
78
+ # /Namespace
79
+ # =======================================================================
80
+
81
+ end # module Log
82
+ end # module NRSER
data/lib/nrser/log.rb CHANGED
@@ -19,6 +19,8 @@ require "concurrent/map"
19
19
  # Project / Package
20
20
  # -----------------------------------------------------------------------
21
21
 
22
+ # Using {NRSER.truthy?} for ENV var values.
23
+ require 'nrser/functions/object/truthy'
22
24
 
23
25
  # Definitions
24
26
  # =======================================================================
@@ -38,10 +40,6 @@ module NRSER::Log
38
40
  require_relative './log/appender'
39
41
 
40
42
 
41
- # Constants
42
- # ========================================================================
43
-
44
-
45
43
  # Mixins
46
44
  # ========================================================================
47
45
 
@@ -359,14 +357,14 @@ module NRSER::Log
359
357
  # @param (see .setup!)
360
358
  # @return (see .setup!)
361
359
  #
362
- def self.setup_for_CLI! dest: $stderr,
360
+ def self.setup_for_cli! dest: $stderr,
363
361
  sync: true,
364
362
  **kwds
365
363
  setup! dest: dest, sync: sync, **kwds
366
- end # .setup_for_CLI!
364
+ end # .setup_for_cli!
367
365
 
368
- # Old name
369
- singleton_class.send :alias_method, :setup_for_cli!, :setup_for_CLI!
366
+ # Was the new name, then realized it was dumb and switched back :D
367
+ singleton_class.send :alias_method, :setup_for_CLI!, :setup_for_cli!
370
368
 
371
369
 
372
370
  # Call {.setup!} with some default keywords that are nice for interactive
@@ -696,6 +694,9 @@ module NRSER::Log
696
694
  old_appender = @appender
697
695
 
698
696
  @appender = case dest
697
+ when false
698
+ # Used to remove the appender and set {.appender} to `nil`.
699
+ nil
699
700
  when SemanticLogger::Subscriber, Hash
700
701
  # Can be handled directly
701
702
  SemanticLogger.add_appender dest
@@ -18,7 +18,7 @@ module NRSER::RSpex::ExampleGroup
18
18
  # @param [Array] *args
19
19
  # Arguments to call `subject` with to produce the new subject.
20
20
  #
21
- # @param [#call] &block
21
+ # @param [#call] &body
22
22
  # Block to execute in the context of the example group after refining
23
23
  # the subject.
24
24
  #
@@ -34,4 +34,25 @@ module NRSER::RSpex::ExampleGroup
34
34
  # Short / old name
35
35
  alias_method :called_with, :describe_called_with
36
36
 
37
+
38
+ # Version of {#describe_called_with} for when you have no arguments.
39
+ #
40
+ # @param [#call] &body
41
+ # Block to execute in the context of the example group after refining
42
+ # the subject.
43
+ #
44
+ # @return [void]
45
+ #
46
+ def describe_called &body
47
+ describe_x Args(),
48
+ type: :called_with,
49
+ subject_block: -> { super().call },
50
+ &body
51
+ end
52
+
53
+ alias_method :called, :describe_called
54
+ alias_method :when_called, :describe_called
55
+
56
+
57
+
37
58
  end # module NRSER::RSpex::ExampleGroup
@@ -2,13 +2,13 @@
2
2
 
3
3
  module NRSER::RSpex::ExampleGroup
4
4
 
5
- # @todo Document describe_instance method.
5
+ # Describe an instance of the described class by providing arguments for
6
+ # it's construction.
6
7
  #
7
- # @param [type] arg_name
8
- # @todo Add name param description.
8
+ # @param [Array] *constructor_args
9
+ # Arguments to pass to `.new` on {#described_class} to create instances.
9
10
  #
10
- # @return [return_type]
11
- # @todo Document return value.
11
+ # @return [void]
12
12
  #
13
13
  def describe_instance *constructor_args, &body
14
14
  describe_x ".new", Args(*constructor_args),
@@ -119,7 +119,7 @@ module NRSER::Types
119
119
  if type.has_from_data?
120
120
  begin
121
121
  return check!( type.from_data data )
122
- rescue Exception => error
122
+ rescue StandardError => error
123
123
  errors << error
124
124
  end
125
125
  end
@@ -78,7 +78,9 @@ module NRSER::Types::Factory
78
78
  maybe_options = options.slice *maybe_option_keys
79
79
  factory_options = options.except *maybe_option_keys
80
80
 
81
- maybe public_send( name, *args, **factory_options ), **maybe_options
81
+ NRSER::Types.maybe \
82
+ public_send( name, *args, **factory_options ),
83
+ **maybe_options
82
84
  end
83
85
 
84
86
  aliases.each do |alias_name|
@@ -89,4 +89,10 @@ module NRSER::Types
89
89
  def_factory :is_a do |mod, **options|
90
90
  IsA.new mod, **options
91
91
  end
92
+
93
+
94
+ def_factory :type do |**options|
95
+ is_a NRSER::Types::Type
96
+ end
97
+
92
98
  end # NRSER::Types
@@ -1,18 +1,91 @@
1
- require_relative './combinators'
2
- require_relative './nil'
1
+ # Requirements
2
+ # ========================================================================
3
3
 
4
- module NRSER::Types
5
-
6
- # Type satisfied by `nil` or the parametrized type.
4
+ # Project / Package
5
+ # ------------------------------------------------------------------------
6
+
7
+ require_relative './is_a'
8
+
9
+
10
+ # Namespace
11
+ # ========================================================================
12
+
13
+ module NRSER
14
+ module Types
15
+
16
+
17
+ # Definitions
18
+ # ========================================================================
19
+
20
+ class Maybe < Type
21
+
22
+ # Attributes
23
+ # ========================================================================
24
+
25
+ # The type of all members besides `nil`.
7
26
  #
8
- def_factory(
9
- :maybe,
10
- ) do |type, **options|
11
- union \
12
- self.nil,
13
- type,
14
- name: (options[:name] || "#{ type.name }?"),
15
- **options
27
+ # @return [Type]
28
+ #
29
+ attr_reader :type
30
+
31
+
32
+ # Constructor
33
+ # ======================================================================
34
+
35
+ # Instantiate a new `NRSER::Types::Maybe`.
36
+ def initialize type, **options
37
+ super **options
38
+ @type = NRSER::Types.make type
39
+ end # #initialize
40
+
41
+
42
+ # Instance Methods
43
+ # ========================================================================
44
+
45
+ def test? value
46
+ value.nil? || @type.test?( value )
16
47
  end
17
48
 
18
- end # NRSER::Types
49
+
50
+ def explain
51
+ "#{ @type.name }?"
52
+ end
53
+
54
+
55
+ def has_from_s?
56
+ !@from_s.nil? || type.has_from_s?
57
+ end
58
+
59
+
60
+ def custom_from_s string
61
+ type.from_s string
62
+ end
63
+
64
+ end # class Maybe
65
+
66
+
67
+ # @!group Type Factory Functions
68
+ # ----------------------------------------------------------------------------
69
+
70
+ # @!method
71
+ # Type satisfied by `nil` or the parametrized type.
72
+ #
73
+ # @param [Type] type
74
+ # The type values must be if they are not `nil`.
75
+ #
76
+ # @param **options (see Type.initialize)
77
+ #
78
+ # @return [Type]
79
+ #
80
+ def_factory :maybe do |type, **options|
81
+ Maybe.new type, **options
82
+ end
83
+
84
+ # @!endgroup Type Factory Functions # ****************************************
85
+
86
+
87
+ # /Namespace
88
+ # ========================================================================
89
+
90
+ end # module Types
91
+ end # module NRSER
@@ -44,11 +44,12 @@ module NRSER::Types
44
44
  end
45
45
 
46
46
 
47
- # A path is a non-empty {String} or {Pathname}.
48
- #
49
- # @param **options see NRSER::Types::Type#initialize
50
- #
51
- # @return [NRSER::Types::Type]
47
+ # @!method
48
+ # A path is a non-empty {String} or {Pathname}.
49
+ #
50
+ # @param **options see NRSER::Types::Type#initialize
51
+ #
52
+ # @return [NRSER::Types::Type]
52
53
  #
53
54
  def_factory :path do |name: 'Path', **options|
54
55
  one_of \
data/lib/nrser/version.rb CHANGED
@@ -18,7 +18,7 @@ module NRSER
18
18
  #
19
19
  # @return [String]
20
20
  #
21
- VERSION = '0.3.7'
21
+ VERSION = '0.3.8'
22
22
 
23
23
 
24
24
  module Version
data/lib/nrser.rb CHANGED
@@ -69,6 +69,8 @@ require_relative './nrser/core_ext/binding'
69
69
  # Then everything else...
70
70
  require_relative './nrser/char'
71
71
  require_relative './nrser/errors'
72
+ require 'nrser/gem_ext/hamster'
73
+
72
74
  require_relative './nrser/no_arg'
73
75
  require_relative './nrser/message'
74
76
  require_relative './nrser/collection'
@@ -0,0 +1,114 @@
1
+ require 'nrser/labs/i8'
2
+
3
+ describe_spec_file(
4
+ spec_path: __FILE__,
5
+ module: Hamster,
6
+ ) do
7
+
8
+ describe_setup %{
9
+ Converting Hamsters to regular structures with their `#to_mutable`
10
+ }.squish do
11
+
12
+ it %{ gets immutable objects nested inside mutable ones } do
13
+
14
+ # Because `I8({ x: 1 }) == { x: 1 }` (which is usually probably very nice
15
+ # to have) we have to do more than just compare with `==`.
16
+ #
17
+ # I *think* this accomplishes what we want...
18
+ #
19
+ def class_match actual, expected
20
+ return false unless actual == expected &&
21
+ actual.class == expected.class &&
22
+ actual.eql?( expected ) # This alone is prob
23
+ # enough...
24
+
25
+ case expected
26
+ when ::Hash, ::Array
27
+ expected.each_branch do |key, expected_value|
28
+ return false unless class_match( expected_value, actual[key] )
29
+ end
30
+ when ::Set
31
+ expected.each do |expected_value|
32
+ return false unless actual.include?( expected_value )
33
+ end
34
+ end
35
+
36
+ true
37
+ end
38
+
39
+ expect(
40
+ class_match(
41
+ I8({ x: { y: I8({ z: 1 }) } }).to_mutable,
42
+ { x: { y: { z: 1 } } }
43
+ )
44
+ ).to be true
45
+
46
+ expect(
47
+ class_match(
48
+ I8({ x: { y: I8({ z: 1 }) } }).to_mutable,
49
+ { x: { y: { z: 1 } } },
50
+ )
51
+ ).to be true
52
+
53
+ expect(
54
+ class_match(
55
+ I8({ items: [ I8({ id: 1 }), I8({ id: 2 }) ] }).to_mutable,
56
+ { items: [ { id: 1 }, {id: 2 } ] },
57
+ )
58
+ ).to be true
59
+
60
+ expect(
61
+ class_match(
62
+ I8({ items: Set[ I8({ id: 1 }), I8({ id: 2 }) ] }).to_mutable,
63
+ { items: Set[ { id: 1 }, {id: 2 } ] },
64
+ )
65
+ ).to be true
66
+ end
67
+
68
+ end # setup
69
+
70
+
71
+ describe_class Hamster::Hash do
72
+ describe_instance x: 1, y: 2, z: 3 do
73
+ describe_method :to_mutable do
74
+ when_called do
75
+ it { is_expected.to be_a( ::Hash ).and eq( {x: 1, y: 2, z: 3} ) }
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+
82
+ describe_class Hamster::Vector do
83
+ describe_instance [1, 2, 3] do
84
+ describe_method :to_mutable do
85
+ when_called do
86
+ it { is_expected.to be_a( ::Array ).and eq [1, 2, 3] }
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+
93
+ describe_class Hamster::Set do
94
+ describe_instance [1, 2, 3] do
95
+ describe_instance_method :to_mutable do
96
+ when_called {
97
+ it { is_expected.to be_a( ::Set ).and eq ::Set[1, 2, 3] }
98
+ }
99
+ end
100
+ end
101
+ end
102
+
103
+
104
+ describe_class Hamster::SortedSet do
105
+ describe_instance [1, 2, 3] do
106
+ describe_instance_method :to_mutable do
107
+ when_called {
108
+ it { is_expected.to be_a( ::SortedSet ).and eq ::SortedSet[1, 2, 3] }
109
+ }
110
+ end
111
+ end
112
+ end
113
+
114
+ end # Spec File Description
@@ -57,7 +57,7 @@ describe NRSER::Props::Immutable::Vector do
57
57
  # defined classes.
58
58
  def self.name; 'Point2DInt'; end
59
59
 
60
- # It's vital that we include the `key:` keyword argument, and that the
60
+ # It's vital that we include the `index:` keyword argument, and that the
61
61
  # values are non-negative integer indexes for the vector.
62
62
  prop :x, type: t.int, index: 0
63
63
  prop :y, type: t.int, index: 1
data/spec/spec_helper.rb CHANGED
@@ -32,6 +32,13 @@ RSpec.configure do |config|
32
32
 
33
33
  config.example_status_persistence_file_path = \
34
34
  NRSER::ROOT / 'tmp' / ".rspec_status"
35
+
36
+ # This allows you to limit a spec run to individual examples or groups
37
+ # you care about by tagging them with `:focus` metadata. When nothing
38
+ # is tagged with `:focus`, all examples get run. RSpec also provides
39
+ # aliases for `it`, `describe`, and `context` that include `:focus`
40
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
41
+ config.filter_run_when_matching :focus
35
42
  end
36
43
 
37
44
 
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.7
4
+ version: 0.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - nrser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-23 00:00:00.000000000 Z
11
+ date: 2018-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hamster
@@ -317,10 +317,16 @@ files:
317
317
  - lib/nrser/functions/tree/map_leaves.rb
318
318
  - lib/nrser/functions/tree/map_tree.rb
319
319
  - lib/nrser/functions/tree/transform.rb
320
+ - lib/nrser/gem_ext/hamster.rb
321
+ - lib/nrser/gem_ext/hamster/hash.rb
322
+ - lib/nrser/gem_ext/hamster/set.rb
323
+ - lib/nrser/gem_ext/hamster/sorted_set.rb
324
+ - lib/nrser/gem_ext/hamster/vector.rb
320
325
  - lib/nrser/graph/tsorter.rb
321
326
  - lib/nrser/labs.rb
322
327
  - lib/nrser/labs/core_ext/binding.rb
323
328
  - lib/nrser/labs/globlin.rb
329
+ - lib/nrser/labs/i8.rb
324
330
  - lib/nrser/labs/index.rb
325
331
  - lib/nrser/labs/stash.rb
326
332
  - lib/nrser/log.rb
@@ -332,6 +338,7 @@ files:
332
338
  - lib/nrser/log/logger.rb
333
339
  - lib/nrser/log/mixin.rb
334
340
  - lib/nrser/log/plugin.rb
341
+ - lib/nrser/log/types.rb
335
342
  - lib/nrser/mean_streak.rb
336
343
  - lib/nrser/mean_streak/document.rb
337
344
  - lib/nrser/message.rb
@@ -443,11 +450,12 @@ files:
443
450
  - spec/lib/nrser/functions/text/words_spec.rb
444
451
  - spec/lib/nrser/functions/tree/each_branch_spec.rb
445
452
  - spec/lib/nrser/functions/tree/leaves_spec.rb
446
- - spec/lib/nrser/functions/tree/map_branch_spec.rb
453
+ - spec/lib/nrser/functions/tree/map_branches_spec.rb
447
454
  - spec/lib/nrser/functions/tree/map_tree_spec.rb
448
455
  - spec/lib/nrser/functions/tree/transform_spec.rb
449
456
  - spec/lib/nrser/functions/tree/transformer_spec.rb
450
457
  - spec/lib/nrser/gem_ext/hamster/json_spec.rb
458
+ - spec/lib/nrser/gem_ext/hamster/to_mutable_spec.rb
451
459
  - spec/lib/nrser/labs/globlin_spec.rb
452
460
  - spec/lib/nrser/labs/index_spec.rb
453
461
  - spec/lib/nrser/mean_streak/design_spec.rb
@@ -535,11 +543,12 @@ test_files:
535
543
  - spec/lib/nrser/functions/text/words_spec.rb
536
544
  - spec/lib/nrser/functions/tree/each_branch_spec.rb
537
545
  - spec/lib/nrser/functions/tree/leaves_spec.rb
538
- - spec/lib/nrser/functions/tree/map_branch_spec.rb
546
+ - spec/lib/nrser/functions/tree/map_branches_spec.rb
539
547
  - spec/lib/nrser/functions/tree/map_tree_spec.rb
540
548
  - spec/lib/nrser/functions/tree/transform_spec.rb
541
549
  - spec/lib/nrser/functions/tree/transformer_spec.rb
542
550
  - spec/lib/nrser/gem_ext/hamster/json_spec.rb
551
+ - spec/lib/nrser/gem_ext/hamster/to_mutable_spec.rb
543
552
  - spec/lib/nrser/labs/globlin_spec.rb
544
553
  - spec/lib/nrser/labs/index_spec.rb
545
554
  - spec/lib/nrser/mean_streak/design_spec.rb