nrser 0.2.2 → 0.3.0
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 +4 -4
- data/lib/nrser/char/alpha_numeric_sub.rb +1 -2
- data/lib/nrser/char.rb +0 -6
- data/lib/nrser/core_ext/array.rb +120 -0
- data/lib/nrser/core_ext/binding.rb +44 -0
- data/lib/nrser/{functions → core_ext}/enumerable/find_map.rb +18 -15
- data/lib/nrser/{ext → core_ext}/enumerable.rb +10 -24
- data/lib/nrser/core_ext/exception.rb +30 -0
- data/lib/nrser/core_ext/hash/extract_values_at.rb +49 -0
- data/lib/nrser/core_ext/hash/transform_values_with_keys.rb +24 -0
- data/lib/nrser/core_ext/hash.rb +50 -0
- data/lib/nrser/core_ext/module/method_objects.rb +96 -0
- data/lib/nrser/core_ext/module/names.rb +69 -0
- data/lib/nrser/core_ext/module/source_locations.rb +214 -0
- data/lib/nrser/core_ext/module.rb +2 -0
- data/lib/nrser/core_ext/object/lazy_var.rb +31 -0
- data/lib/nrser/core_ext/object.rb +46 -0
- data/lib/nrser/core_ext/open_struct.rb +6 -0
- data/lib/nrser/{ext → core_ext}/pathname.rb +8 -5
- data/lib/nrser/{ext → core_ext}/string.rb +6 -12
- data/lib/nrser/core_ext/symbol.rb +13 -0
- data/lib/nrser/core_ext/time.rb +46 -0
- data/lib/nrser/core_ext.rb +13 -0
- data/lib/nrser/errors/abstract_method_error.rb +150 -0
- data/lib/nrser/errors/argument_error.rb +42 -0
- data/lib/nrser/errors/nicer_error.rb +298 -72
- data/lib/nrser/errors/type_error.rb +46 -0
- data/lib/nrser/errors.rb +4 -53
- data/lib/nrser/ext/tree.rb +3 -0
- data/lib/nrser/functions/enumerable/associate.rb +6 -9
- data/lib/nrser/functions/enumerable/include_slice.rb +2 -3
- data/lib/nrser/functions/enumerable.rb +1 -3
- data/lib/nrser/functions/exception.rb +1 -1
- data/lib/nrser/functions/hash.rb +0 -6
- data/lib/nrser/functions/merge_by.rb +2 -2
- data/lib/nrser/functions/module/method_objects.rb +77 -0
- data/lib/nrser/functions/module.rb +1 -2
- data/lib/nrser/functions/open_struct.rb +25 -35
- data/lib/nrser/functions/proc.rb +1 -6
- data/lib/nrser/functions/string/looks_like.rb +32 -1
- data/lib/nrser/functions/string.rb +1 -40
- data/lib/nrser/functions/text/lines.rb +2 -1
- data/lib/nrser/functions.rb +0 -1
- data/lib/nrser/graph/tsorter.rb +41 -0
- data/lib/nrser/labs/core_ext/binding.rb +37 -0
- data/lib/nrser/labs/stash.rb +372 -0
- data/lib/nrser/{logging → log}/appender/sync.rb +3 -3
- data/lib/nrser/log/appender.rb +3 -0
- data/lib/nrser/{logging → log}/formatters/color.rb +47 -20
- data/lib/nrser/log/formatters/mixin.rb +270 -0
- data/lib/nrser/{logging → log}/formatters.rb +0 -0
- data/lib/nrser/log/logger.rb +229 -0
- data/lib/nrser/log/mixin.rb +56 -0
- data/lib/nrser/log.rb +723 -0
- data/lib/nrser/message.rb +24 -3
- data/lib/nrser/meta/source/location.rb +158 -0
- data/lib/nrser/meta.rb +1 -1
- data/lib/nrser/props/class_methods.rb +118 -0
- data/lib/nrser/props/immutable/hash.rb +111 -0
- data/lib/nrser/props/immutable/hash_variable.rb +82 -0
- data/lib/nrser/props/immutable/instance_variables.rb +48 -0
- data/lib/nrser/props/immutable/vector.rb +107 -0
- data/lib/nrser/props/instance_methods.rb +184 -0
- data/lib/nrser/props/metadata.rb +359 -0
- data/lib/nrser/props/mutable/instance_variables.rb +60 -0
- data/lib/nrser/props/mutable/stash.rb +199 -0
- data/lib/nrser/{meta/props → props}/prop.rb +217 -112
- data/lib/nrser/props/storage/instance_variable.rb +85 -0
- data/lib/nrser/props/storage/instance_variables.rb +67 -0
- data/lib/nrser/props/storage/key.rb +88 -0
- data/lib/nrser/props.rb +9 -0
- data/lib/nrser/refinements/sugar.rb +41 -0
- data/lib/nrser/refinements/types.rb +2 -2
- data/lib/nrser/refinements.rb +14 -16
- data/lib/nrser/rspex/example_group/describe_attribute.rb +24 -0
- data/lib/nrser/rspex/example_group/describe_called_with.rb +1 -6
- data/lib/nrser/rspex/example_group/{describe_use_case.rb → describe_case.rb} +6 -3
- data/lib/nrser/rspex/example_group/describe_class.rb +1 -0
- data/lib/nrser/rspex/example_group/describe_group.rb +29 -0
- data/lib/nrser/rspex/example_group/describe_instance_method.rb +2 -2
- data/lib/nrser/rspex/example_group/describe_message.rb +35 -0
- data/lib/nrser/rspex/example_group/describe_method.rb +23 -2
- data/lib/nrser/rspex/example_group/describe_module.rb +19 -0
- data/lib/nrser/rspex/example_group/describe_response_to.rb +32 -0
- data/lib/nrser/rspex/example_group/describe_section.rb +38 -0
- data/lib/nrser/rspex/example_group/describe_sent_to.rb +52 -0
- data/lib/nrser/rspex/example_group/describe_source_file.rb +49 -0
- data/lib/nrser/rspex/example_group/describe_spec_file.rb +41 -108
- data/lib/nrser/rspex/example_group/describe_when.rb +14 -7
- data/lib/nrser/rspex/example_group/describe_x.rb +39 -12
- data/lib/nrser/rspex/example_group/overrides.rb +66 -0
- data/lib/nrser/rspex/example_group.rb +20 -252
- data/lib/nrser/rspex/format.rb +83 -17
- data/lib/nrser/rspex.rb +4 -34
- data/lib/nrser/sugar/method_missing_forwarder.rb +50 -0
- data/lib/nrser/{env → sys/env}/path.rb +1 -2
- data/lib/nrser/{env.rb → sys/env.rb} +2 -1
- data/lib/nrser/sys.rb +5 -0
- data/lib/nrser/types/any.rb +36 -7
- data/lib/nrser/types/{array.rb → arrays.rb} +32 -81
- data/lib/nrser/types/attrs.rb +68 -15
- data/lib/nrser/types/booleans.rb +95 -34
- data/lib/nrser/types/bounded.rb +12 -10
- data/lib/nrser/types/combinators.rb +74 -37
- data/lib/nrser/types/errors/check_error.rb +86 -0
- data/lib/nrser/types/errors/from_string_error.rb +82 -0
- data/lib/nrser/types/factory.rb +91 -0
- data/lib/nrser/types/hashes.rb +171 -26
- data/lib/nrser/types/in.rb +25 -12
- data/lib/nrser/types/is.rb +50 -18
- data/lib/nrser/types/is_a.rb +52 -33
- data/lib/nrser/types/labels.rb +6 -33
- data/lib/nrser/types/maybe.rb +12 -4
- data/lib/nrser/types/nil.rb +24 -4
- data/lib/nrser/types/not.rb +6 -16
- data/lib/nrser/types/numbers.rb +94 -57
- data/lib/nrser/types/pairs.rb +57 -57
- data/lib/nrser/types/paths.rb +112 -133
- data/lib/nrser/types/responds.rb +64 -74
- data/lib/nrser/types/shape.rb +29 -24
- data/lib/nrser/types/strings.rb +25 -17
- data/lib/nrser/types/symbols.rb +19 -17
- data/lib/nrser/types/trees.rb +18 -70
- data/lib/nrser/types/tuples.rb +36 -40
- data/lib/nrser/types/type.rb +342 -91
- data/lib/nrser/types/when.rb +40 -18
- data/lib/nrser/types/where.rb +94 -9
- data/lib/nrser/types.rb +72 -63
- data/lib/nrser/version.rb +1 -1
- data/lib/nrser.rb +18 -18
- data/spec/lib/nrser/{functions/binding/template_spec.rb → core_ext/binding/erb_spec.rb} +5 -5
- data/spec/lib/nrser/{functions → core_ext}/enumerable/find_map_spec.rb +8 -6
- data/spec/lib/nrser/{refinements → core_ext}/hash_spec.rb +9 -22
- data/spec/lib/nrser/errors/abstract_method_error_spec.rb +12 -5
- data/spec/lib/nrser/functions/enumerable/{to_h_by_spec.rb → associate_spec.rb} +1 -1
- data/spec/lib/nrser/functions/merge_by_spec.rb +1 -1
- data/spec/lib/nrser/functions/tree/each_branch_spec.rb +3 -3
- data/spec/lib/nrser/functions/tree/transform_spec.rb +14 -15
- data/spec/lib/nrser/gem_ext/hamster/json_spec.rb +4 -0
- data/spec/lib/nrser/meta/source/location_spec.rb +86 -0
- data/spec/lib/nrser/props/immutable/hash_spec.rb +297 -0
- data/spec/lib/nrser/props/immutable/vector_spec.rb +296 -0
- data/spec/lib/nrser/{meta/props_spec.rb → props/original_props_spec.rb} +11 -16
- data/spec/lib/nrser/{meta/props → props}/to_and_from_data_spec.rb +10 -8
- data/spec/lib/nrser/refinements/array_spec.rb +2 -15
- data/spec/lib/nrser/refinements/erb_spec.rb +5 -7
- data/spec/lib/nrser/refinements/set_spec.rb +2 -15
- data/spec/lib/nrser/{env → sys/env}/path/insert_spec.rb +4 -2
- data/spec/lib/nrser/{env → sys/env}/path_spec.rb +4 -2
- data/spec/lib/nrser/types/array_spec.rb +8 -8
- data/spec/lib/nrser/types/paths_spec.rb +15 -18
- data/spec/spec_helper.rb +4 -0
- metadata +109 -69
- data/lib/nrser/ext/binding.rb +0 -36
- data/lib/nrser/ext/module.rb +0 -62
- data/lib/nrser/ext.rb +0 -8
- data/lib/nrser/functions/binding.rb +0 -76
- data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
- data/lib/nrser/functions/enumerable/map_values.rb +0 -94
- data/lib/nrser/functions/hash/deep_merge.rb +0 -57
- data/lib/nrser/functions/hash/except_keys.rb +0 -44
- data/lib/nrser/functions/hash/slice_keys.rb +0 -43
- data/lib/nrser/functions/hash/stringify_keys.rb +0 -55
- data/lib/nrser/functions/hash/symbolize_keys.rb +0 -57
- data/lib/nrser/functions/hash/transform_keys.rb +0 -140
- data/lib/nrser/functions/module/methods.rb +0 -206
- data/lib/nrser/functions/module/source_locations.rb +0 -213
- data/lib/nrser/logging/appender.rb +0 -3
- data/lib/nrser/logging.rb +0 -353
- data/lib/nrser/meta/props/base.rb +0 -31
- data/lib/nrser/meta/props.rb +0 -357
- data/lib/nrser/refinements/array.rb +0 -133
- data/lib/nrser/refinements/binding.rb +0 -6
- data/lib/nrser/refinements/enumerator.rb +0 -5
- data/lib/nrser/refinements/exception.rb +0 -35
- data/lib/nrser/refinements/hash.rb +0 -150
- data/lib/nrser/refinements/module.rb +0 -5
- data/lib/nrser/refinements/object.rb +0 -42
- data/lib/nrser/refinements/open_struct.rb +0 -28
- data/lib/nrser/refinements/pathname.rb +0 -5
- data/lib/nrser/refinements/set.rb +0 -5
- data/lib/nrser/refinements/string.rb +0 -5
- data/lib/nrser/refinements/symbol.rb +0 -20
- data/lib/nrser/rspex/described.rb +0 -99
- data/spec/design/mapping_spec.rb +0 -42
- data/spec/lib/nrser/functions/hash_spec.rb +0 -41
- data/spec/lib/nrser/functions/string/truncate_spec.rb +0 -11
- data/spec/lib/nrser/refinements/truncate_spec.rb +0 -10
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Project / Package
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
require 'nrser/errors/nicer_error'
|
10
|
+
|
11
|
+
|
12
|
+
# Definitions
|
13
|
+
# =======================================================================
|
14
|
+
|
15
|
+
# This error (or a subclass) is thrown when types fail to
|
16
|
+
# {NRSER::Types::Type.check!}.
|
17
|
+
#
|
18
|
+
class NRSER::Types::CheckError < ::TypeError
|
19
|
+
|
20
|
+
# Mixins
|
21
|
+
# ==========================================================================
|
22
|
+
|
23
|
+
include NRSER::NicerError
|
24
|
+
|
25
|
+
|
26
|
+
# Attributes
|
27
|
+
# ========================================================================
|
28
|
+
|
29
|
+
# The type that was checked against.
|
30
|
+
#
|
31
|
+
# @return [NRSER::Types::Type]
|
32
|
+
#
|
33
|
+
attr_reader :type
|
34
|
+
|
35
|
+
|
36
|
+
# The value that failed the type check.
|
37
|
+
#
|
38
|
+
# @return [*]
|
39
|
+
#
|
40
|
+
attr_reader :value
|
41
|
+
|
42
|
+
|
43
|
+
# Constructor
|
44
|
+
# ========================================================================
|
45
|
+
|
46
|
+
# Construct a `NicerError`.
|
47
|
+
#
|
48
|
+
# @param [*] value:
|
49
|
+
# The {#value} that failed the check.
|
50
|
+
#
|
51
|
+
# @param [NRSER::Types::Type] type:
|
52
|
+
# The type that was checked.
|
53
|
+
#
|
54
|
+
# @param details: (see NRSER::NicerError#initialize)
|
55
|
+
#
|
56
|
+
# @param **kwds
|
57
|
+
# See {NRSER::NicerError#initialize}
|
58
|
+
#
|
59
|
+
def initialize *message, value:, type:, details: nil, **kwds
|
60
|
+
@value = value
|
61
|
+
@type = type
|
62
|
+
|
63
|
+
if details.is_a?( Proc ) && details.arity != 0
|
64
|
+
orig_details = details
|
65
|
+
details = -> { orig_details.call type: type, value: value }
|
66
|
+
end
|
67
|
+
|
68
|
+
super \
|
69
|
+
*message,
|
70
|
+
type: type,
|
71
|
+
value: value,
|
72
|
+
details: details,
|
73
|
+
**kwds
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# Build default message when none provided.
|
78
|
+
#
|
79
|
+
# @return [String]
|
80
|
+
#
|
81
|
+
def default_message
|
82
|
+
["Value", value.inspect, "failed check for type", type.name]
|
83
|
+
end # #default_message
|
84
|
+
|
85
|
+
|
86
|
+
end # class NRSER::Types::TypeError
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Project / Package
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
require 'nrser/errors/nicer_error'
|
10
|
+
|
11
|
+
|
12
|
+
# Definitions
|
13
|
+
# =======================================================================
|
14
|
+
|
15
|
+
# Raised when a {NRSER::Types::Type} fails to load a value from a {String}
|
16
|
+
# (via it's `#from_s` method).
|
17
|
+
#
|
18
|
+
# This is a {NRSER::NicerError}.
|
19
|
+
#
|
20
|
+
class NRSER::Types::FromStringError < ::ArgumentError
|
21
|
+
|
22
|
+
# Mixins
|
23
|
+
# ==========================================================================
|
24
|
+
|
25
|
+
# Make life better.
|
26
|
+
include NRSER::NicerError
|
27
|
+
|
28
|
+
|
29
|
+
# Attributes
|
30
|
+
# ========================================================================
|
31
|
+
|
32
|
+
# The type that was checked against.
|
33
|
+
#
|
34
|
+
# @return [NRSER::Types::Type]
|
35
|
+
#
|
36
|
+
attr_reader :type
|
37
|
+
|
38
|
+
|
39
|
+
# The string we were trying to load from.
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
#
|
43
|
+
attr_reader :string
|
44
|
+
|
45
|
+
|
46
|
+
# Constructor
|
47
|
+
# ========================================================================
|
48
|
+
|
49
|
+
# Construct a `FromStringError`.
|
50
|
+
#
|
51
|
+
# @param *message (see NRSER::NicerError#initialize)
|
52
|
+
#
|
53
|
+
# @param [String] string:
|
54
|
+
# The string the type was trying to load a value from.
|
55
|
+
#
|
56
|
+
# @param [NRSER::Types::Type] type:
|
57
|
+
# The type that was trying to load.
|
58
|
+
#
|
59
|
+
# @param **kwds
|
60
|
+
# See {NRSER::NicerError#initialize}
|
61
|
+
#
|
62
|
+
def initialize *message, string:, type:, **kwds
|
63
|
+
@string = string
|
64
|
+
@type = type
|
65
|
+
|
66
|
+
super \
|
67
|
+
*message,
|
68
|
+
type: type,
|
69
|
+
string: string,
|
70
|
+
**kwds
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# Main message to use when none provided to {#initialize}.
|
75
|
+
#
|
76
|
+
# @return [String]
|
77
|
+
#
|
78
|
+
def default_message
|
79
|
+
["Failed to load type", type.name, "from string", string.inspect]
|
80
|
+
end
|
81
|
+
|
82
|
+
end # class NRSER::Types::TypeError
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Stdlib
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Deps
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
|
13
|
+
# Project / Package
|
14
|
+
# -----------------------------------------------------------------------
|
15
|
+
|
16
|
+
|
17
|
+
# Refinements
|
18
|
+
# =======================================================================
|
19
|
+
|
20
|
+
|
21
|
+
# Declarations
|
22
|
+
# =======================================================================
|
23
|
+
|
24
|
+
|
25
|
+
# Definitions
|
26
|
+
# =======================================================================
|
27
|
+
|
28
|
+
|
29
|
+
# @todo document NRSER::Types::Factory module.
|
30
|
+
module NRSER::Types::Factory
|
31
|
+
|
32
|
+
# Define a type factory.
|
33
|
+
#
|
34
|
+
# @!macro [attach] factory
|
35
|
+
# @param [Hash] **options
|
36
|
+
# Common type construction options, see {Type#initialize}.
|
37
|
+
#
|
38
|
+
# @return [NRSER::Types::Type]
|
39
|
+
# The type.
|
40
|
+
#
|
41
|
+
def def_factory name, maybe: true, aliases: [], &body
|
42
|
+
define_singleton_method name, &body
|
43
|
+
|
44
|
+
aliases.each do |alias_name|
|
45
|
+
if self.respond_to? alias_name
|
46
|
+
alias_name = alias_name + '_'
|
47
|
+
end
|
48
|
+
|
49
|
+
singleton_class.send :alias_method, alias_name, name
|
50
|
+
end
|
51
|
+
|
52
|
+
if maybe && !name.to_s.end_with?( '?' )
|
53
|
+
maybe_name = "#{ name }?".to_sym
|
54
|
+
|
55
|
+
if self.respond_to? maybe_name
|
56
|
+
maybe_name = "#{ name }_?".to_sym
|
57
|
+
end
|
58
|
+
|
59
|
+
# HACK Ugh maybe I wrote this quick to fix it, not sure if it's a decent
|
60
|
+
# idea.. basically, need to figure out what `options` keys go
|
61
|
+
# to {.maybe} and which ones go to the regular factory... matters
|
62
|
+
# for shit like {.attrs} and {.hash_type} 'cause they use option
|
63
|
+
# keys (whether they *should* is something I've debated... sigh,
|
64
|
+
# it is what it is for now).
|
65
|
+
#
|
66
|
+
# So they options that go to {.maybe} just go strait through to
|
67
|
+
# {Type#initialize}, so just grab that method, see what keys it
|
68
|
+
# takes, and then can slice and dice off that...
|
69
|
+
#
|
70
|
+
maybe_option_keys = Set.new \
|
71
|
+
NRSER::Types::Type.
|
72
|
+
instance_method( :initialize ).
|
73
|
+
parameters.
|
74
|
+
select { |param_type, name| param_type == :key }.
|
75
|
+
map { |param_type, name| name }
|
76
|
+
|
77
|
+
define_singleton_method maybe_name do |*args, **options|
|
78
|
+
maybe_options = options.slice *maybe_option_keys
|
79
|
+
factory_options = options.except *maybe_option_keys
|
80
|
+
|
81
|
+
maybe public_send( name, *args, **factory_options ), **maybe_options
|
82
|
+
end
|
83
|
+
|
84
|
+
aliases.each do |alias_name|
|
85
|
+
singleton_class.send :alias_method, "#{ alias_name }?", maybe_name
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end # module NRSER::Types::Factory
|
data/lib/nrser/types/hashes.rb
CHANGED
@@ -1,41 +1,185 @@
|
|
1
|
-
|
2
|
-
require 'nrser/types/type'
|
3
|
-
|
4
|
-
using NRSER
|
1
|
+
require_relative './type'
|
5
2
|
|
6
3
|
module NRSER::Types
|
7
|
-
|
4
|
+
|
5
|
+
# A type who's members simply are {Hash} instances.
|
6
|
+
#
|
7
|
+
# Implements {#from_s} to provide JSON/YAML detection, as well as "simple"
|
8
|
+
# loading aimed at CLI option values.
|
9
|
+
#
|
8
10
|
class HashType < IsA
|
9
|
-
|
11
|
+
|
12
|
+
# Constructor
|
13
|
+
# ========================================================================
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
**options
|
15
|
+
# Instantiate a new `HashType`.
|
16
|
+
def initialize **options
|
14
17
|
super ::Hash, **options
|
18
|
+
end # #initialize
|
19
|
+
|
20
|
+
|
21
|
+
# Instance Methods
|
22
|
+
# ========================================================================
|
23
|
+
|
24
|
+
# In order to provide the same interface as {HashOfType}, this method
|
25
|
+
# always returns {NRSER::Types.any}.
|
26
|
+
#
|
27
|
+
# @return [NRSER::Types::Type]
|
28
|
+
#
|
29
|
+
def keys; NRSER::Types.any; end
|
30
|
+
|
31
|
+
|
32
|
+
# In order to provide the same interface as {HashOfType}, this method
|
33
|
+
# always returns {NRSER::Types.any}.
|
34
|
+
#
|
35
|
+
# @return [NRSER::Types::Type]
|
36
|
+
#
|
37
|
+
def values; NRSER::Types.any; end
|
38
|
+
|
39
|
+
|
40
|
+
protected
|
41
|
+
# ========================================================================
|
42
|
+
|
43
|
+
# Hook to provide custom loading from strings, which will be called by
|
44
|
+
# {NRSER::Types::Type#from_s}, unless a `@from_s`
|
45
|
+
#
|
46
|
+
def custom_from_s string
|
47
|
+
# Does it looks like a JSON / inline-YAML object?
|
48
|
+
if NRSER.looks_like_json_object? string
|
49
|
+
# It does! Load it
|
50
|
+
begin
|
51
|
+
return YAML.load string
|
52
|
+
rescue
|
53
|
+
# pass - if we failed to load as JSON, it may just not be JSON, and
|
54
|
+
# we can try the split approach below.
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Try parsing as a "simple string", aimed at CLI option values.
|
59
|
+
from_simple_s string
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def from_simple_s string
|
64
|
+
hash = {}
|
65
|
+
|
66
|
+
pair_strs = string.split NRSER::Types::ArrayType::DEFAULT_SPLIT_WITH
|
67
|
+
|
68
|
+
pair_strs.each do |pair_str|
|
69
|
+
key_str, match, value_str = pair_str.rpartition /\:\s*/m
|
70
|
+
|
71
|
+
if match.empty?
|
72
|
+
raise NRSER::Types::FromStringError.new(
|
73
|
+
"Could not split pair string", pair_str,
|
74
|
+
type: self,
|
75
|
+
string: string,
|
76
|
+
pair_str: pair_str,
|
77
|
+
) do
|
78
|
+
<<~END
|
79
|
+
Trying to parse a {Hash} out of a string using the "simple"
|
80
|
+
approach, which splits
|
81
|
+
|
82
|
+
1. First by `,` (followed by any amount of whitespace)
|
83
|
+
2. Then by the last `:` in each of those splits (also followed)
|
84
|
+
by any amount of whitespace)
|
85
|
+
END
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
key = if keys == NRSER::Types.any
|
90
|
+
key_str
|
91
|
+
else
|
92
|
+
keys.from_s key_str
|
93
|
+
end
|
94
|
+
|
95
|
+
value = if values == NRSER::Types.any
|
96
|
+
value_str
|
97
|
+
else
|
98
|
+
values.from_s value_str
|
99
|
+
end
|
100
|
+
|
101
|
+
hash[key] = value
|
102
|
+
end
|
103
|
+
|
104
|
+
hash
|
105
|
+
end # #from_simple_s
|
106
|
+
|
107
|
+
public # end protected *****************************************************
|
108
|
+
|
109
|
+
end # class HashType
|
110
|
+
|
111
|
+
|
112
|
+
# A {Hash} type with typed keys and/or values.
|
113
|
+
#
|
114
|
+
class HashOfType < HashType
|
115
|
+
|
116
|
+
# Attributes
|
117
|
+
# ========================================================================
|
118
|
+
|
119
|
+
# The type of the hash keys.
|
120
|
+
#
|
121
|
+
# @return [NRSER::Types::Type]
|
122
|
+
#
|
123
|
+
attr_reader :keys
|
124
|
+
|
125
|
+
|
126
|
+
# The type of the hash values.
|
127
|
+
#
|
128
|
+
# @return [NRSER::Types::Type]
|
129
|
+
#
|
130
|
+
attr_reader :values
|
131
|
+
|
132
|
+
|
133
|
+
# Constructor
|
134
|
+
# ========================================================================
|
135
|
+
|
136
|
+
def initialize keys: NRSER::Types.any,
|
137
|
+
values: NRSER::Types.any,
|
138
|
+
**options
|
139
|
+
super **options
|
15
140
|
|
16
141
|
@keys = NRSER::Types.make keys
|
17
142
|
@values = NRSER::Types.make values
|
18
143
|
end
|
19
144
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
145
|
+
|
146
|
+
# Instance Methods
|
147
|
+
# ========================================================================
|
148
|
+
|
149
|
+
# Overridden to check that both the {#keys} and {#values} types can
|
150
|
+
# load from a string.
|
151
|
+
#
|
152
|
+
# @see NRSER::Types::Type#has_from_s?
|
153
|
+
#
|
154
|
+
def has_from_s?
|
155
|
+
!@from_s.nil? || [keys, values].all?( &:has_from_s )
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
# @see NRSER::Types::Type#test
|
160
|
+
#
|
161
|
+
# @return [Boolean]
|
162
|
+
#
|
163
|
+
def test? value
|
164
|
+
return false unless super( value )
|
26
165
|
|
27
166
|
value.all? { |k, v|
|
28
|
-
keys.test(k) && values.test(v)
|
167
|
+
keys.test( k ) && values.test( v )
|
29
168
|
}
|
30
169
|
end
|
31
170
|
|
32
|
-
|
33
|
-
|
171
|
+
|
172
|
+
# @see NRSER::Types::Type#explain
|
173
|
+
#
|
174
|
+
# @return [String]
|
175
|
+
#
|
176
|
+
def explain
|
177
|
+
"Hash<#{ keys.explain }, #{ values.explain }>"
|
34
178
|
end
|
179
|
+
|
35
180
|
end # HashType
|
181
|
+
|
36
182
|
|
37
|
-
|
38
|
-
|
39
183
|
# Type satisfied by {Hash} instances.
|
40
184
|
#
|
41
185
|
# @param [Array] *args
|
@@ -47,14 +191,15 @@ module NRSER::Types
|
|
47
191
|
# @return [NRSER::Types::Type]
|
48
192
|
# Newly constructed hash type from `args`.
|
49
193
|
#
|
50
|
-
def_factory
|
51
|
-
|
52
|
-
|
194
|
+
def_factory(
|
195
|
+
:hash_type,
|
196
|
+
aliases: [ :dict, :hash_ ]
|
197
|
+
) do |**kwds|
|
198
|
+
if kwds.key?( :keys ) || kwds.key?( :values )
|
199
|
+
HashOfType.new **kwds
|
53
200
|
else
|
54
|
-
HashType.new
|
201
|
+
HashType.new **kwds
|
55
202
|
end
|
56
203
|
end
|
57
204
|
|
58
|
-
HASH = HashType.new.freeze
|
59
|
-
|
60
205
|
end
|
data/lib/nrser/types/in.rb
CHANGED
@@ -1,26 +1,39 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
|
4
|
-
using NRSER
|
5
|
-
|
6
|
-
|
7
|
-
# Definitions
|
8
|
-
# =======================================================================
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
9
3
|
|
10
4
|
module NRSER::Types
|
11
5
|
|
12
6
|
# Type that tests value for membership in a group object via that object's
|
13
7
|
# `#include?` method.
|
14
8
|
#
|
9
|
+
# @todo
|
10
|
+
# I think I want to get rid of {.where}... which would elevate this to
|
11
|
+
# it's own class as a "fundamental" concept (I guess)... not so sure,
|
12
|
+
# really. The idea of membership is pretty wide-spread and important,
|
13
|
+
# but it's a bit a vague and inconsistently implemented things.
|
14
|
+
#
|
15
15
|
# @param [#include?] group
|
16
16
|
# `#include?` will be called on this value to determine type membership.
|
17
17
|
#
|
18
18
|
# @return [NRSER::Types::Type]
|
19
19
|
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
def_factory(
|
21
|
+
:in,
|
22
|
+
aliases: [ :member_of ],
|
23
|
+
) do |group, **options|
|
24
|
+
unless group.respond_to? :include?
|
25
|
+
raise NRSER::ArgumentError,
|
26
|
+
"In `group` must respond to `:include?`",
|
27
|
+
group: group
|
28
|
+
end
|
29
|
+
|
30
|
+
# Provide a some-what useful default name
|
31
|
+
options[:name] ||= "In<#{ NRSER.smart_ellipsis group.inspect, 64 }>"
|
32
|
+
|
33
|
+
# Unless a `from_s` is provided, just use the identity
|
34
|
+
options[:from_s] ||= ->( s ) { s }
|
35
|
+
|
36
|
+
where( **options ) { |value| group.include? value }
|
24
37
|
end # .in
|
25
38
|
|
26
39
|
end # module NRSER::Types
|
data/lib/nrser/types/is.rb
CHANGED
@@ -1,22 +1,58 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
|
2
|
+
# Requirements
|
3
|
+
# ========================================================================
|
4
|
+
|
5
|
+
# Stdlib
|
6
|
+
# ------------------------------------------------------------------------
|
7
|
+
|
8
|
+
# Deps
|
9
|
+
# ------------------------------------------------------------------------
|
10
|
+
|
11
|
+
# Need {Module#anonymous?}
|
12
|
+
require 'active_support/core_ext/module/anonymous'
|
13
|
+
|
14
|
+
|
15
|
+
# Project / Package
|
16
|
+
# ------------------------------------------------------------------------
|
17
|
+
|
18
|
+
require_relative './type'
|
19
|
+
|
4
20
|
|
5
21
|
module NRSER::Types
|
22
|
+
|
23
|
+
# Type satisfied only by it's exact {#value} object (identity comparison
|
24
|
+
# via `#equal?`).
|
25
|
+
#
|
6
26
|
class Is < NRSER::Types::Type
|
27
|
+
|
28
|
+
# Attributes
|
29
|
+
# ========================================================================
|
30
|
+
|
7
31
|
attr_reader :value
|
8
32
|
|
9
33
|
def initialize value, **options
|
10
34
|
super **options
|
11
|
-
|
12
35
|
@value = value
|
13
36
|
end
|
14
37
|
|
15
|
-
def
|
16
|
-
|
38
|
+
def explain
|
39
|
+
case value
|
40
|
+
when Module
|
41
|
+
module_type = if value.is_a?( Class ) then 'Class' else 'Module' end
|
42
|
+
|
43
|
+
name = if value.anonymous?
|
44
|
+
value.to_s.split( ':' ).last[0...-1]
|
45
|
+
else
|
46
|
+
value.name
|
47
|
+
end
|
48
|
+
|
49
|
+
"#{ module_type }<#{ name }>"
|
50
|
+
else
|
51
|
+
value.inspect
|
52
|
+
end
|
17
53
|
end
|
18
54
|
|
19
|
-
def test value
|
55
|
+
def test? value
|
20
56
|
@value.equal? value
|
21
57
|
end
|
22
58
|
|
@@ -26,19 +62,15 @@ module NRSER::Types
|
|
26
62
|
@value == other.value )
|
27
63
|
end
|
28
64
|
|
29
|
-
# @return [String]
|
30
|
-
# a brief string description of the type - just it's {#name} surrounded
|
31
|
-
# by some back-ticks to make it easy to see where it starts and stops.
|
32
|
-
#
|
33
|
-
def to_s
|
34
|
-
"{ x ≡ #{ @value.inspect } }"
|
35
|
-
end
|
36
|
-
|
37
|
-
alias_method :inspect, :to_s
|
38
65
|
end # Is
|
39
66
|
|
40
|
-
|
41
|
-
|
67
|
+
|
68
|
+
# Satisfied by the exact value only (identity comparison via
|
69
|
+
# `#equal?`).
|
70
|
+
#
|
71
|
+
# Useful for things like {Module}, {Class}, {Fixnum}, {Symbol}, `true`, etc.
|
72
|
+
#
|
73
|
+
def_factory :is do |value, **options|
|
42
74
|
Is.new value, **options
|
43
75
|
end
|
44
76
|
|