nrser 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|