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,199 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Requirements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
# Project / Package
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Need {NRSER::Props} to include
|
11
|
+
require_relative '../../props'
|
12
|
+
|
13
|
+
# Need {NRSER::Stash} itself
|
14
|
+
require 'nrser/labs/stash'
|
15
|
+
|
16
|
+
# Gonna use {NRSER::Props::Storage::Key} for storage
|
17
|
+
require_relative '../storage/key'
|
18
|
+
|
19
|
+
|
20
|
+
# Declarations
|
21
|
+
# =======================================================================
|
22
|
+
|
23
|
+
module NRSER::Props::Mutable; end
|
24
|
+
|
25
|
+
|
26
|
+
# Definitions
|
27
|
+
# =======================================================================
|
28
|
+
|
29
|
+
module NRSER::Props::Mutable::Stash
|
30
|
+
|
31
|
+
# Constants
|
32
|
+
# ==========================================================================
|
33
|
+
|
34
|
+
STORAGE = NRSER::Props::Storage::Key.new \
|
35
|
+
immutable: false,
|
36
|
+
key_type: :name,
|
37
|
+
get: :_raw_get,
|
38
|
+
put: :_raw_put
|
39
|
+
|
40
|
+
|
41
|
+
# Module Methods
|
42
|
+
# ======================================================================
|
43
|
+
|
44
|
+
def self.included base
|
45
|
+
unless base < NRSER::Stash
|
46
|
+
raise binding.erb <<~END
|
47
|
+
This class is only for including in {Hash} subclasses!
|
48
|
+
END
|
49
|
+
end
|
50
|
+
|
51
|
+
base.include NRSER::Props
|
52
|
+
base.include InstanceMethods
|
53
|
+
base.metadata.storage STORAGE
|
54
|
+
base.metadata.freeze
|
55
|
+
end
|
56
|
+
|
57
|
+
# Methods to be mixed in at the class-level with
|
58
|
+
# {NRSER::Props::Mutable::Hash}.
|
59
|
+
module ClassMethods
|
60
|
+
|
61
|
+
def [] *args
|
62
|
+
new ::Hash[*args]
|
63
|
+
end
|
64
|
+
|
65
|
+
end # module ClassMethods
|
66
|
+
|
67
|
+
|
68
|
+
# Instance methods to mix in with {NRSER::Props::Mutable::Hash}.
|
69
|
+
#
|
70
|
+
# We want these to *override* {NRSER::Props::InstanceMethods}, so they
|
71
|
+
# need to be separate so we can include them after {NRSER::Props} in
|
72
|
+
# {NRSER::Props::Mutable::Hash.included}.
|
73
|
+
#
|
74
|
+
module InstanceMethods
|
75
|
+
|
76
|
+
def initialize_props values = {}
|
77
|
+
# Handles things like `[[:x, 1], [:y, 2]]`, since we know that's what is
|
78
|
+
# meant in that case
|
79
|
+
values = values.to_h unless values.respond_to?( :each_pair )
|
80
|
+
|
81
|
+
self.class.metadata.
|
82
|
+
each_primary_prop_value_from( values ) { |prop, value|
|
83
|
+
_raw_put prop.name, value
|
84
|
+
}
|
85
|
+
|
86
|
+
# Check additional type invariants
|
87
|
+
self.class.invariants.each do |type|
|
88
|
+
type.check self
|
89
|
+
end
|
90
|
+
|
91
|
+
# Load in additional non-prop values, if any
|
92
|
+
#
|
93
|
+
# TODO Optimize
|
94
|
+
#
|
95
|
+
|
96
|
+
prop_names = self.class.metadata.prop_names
|
97
|
+
|
98
|
+
values.each do |key, value|
|
99
|
+
unless prop_names.include? convert_key( key )
|
100
|
+
self[key] = value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end # #initialize_props
|
104
|
+
|
105
|
+
|
106
|
+
# Override {NRSER::Props::InstanceMethods#to_data} to handle non-prop
|
107
|
+
# values in the {NRSER::Stash}.
|
108
|
+
#
|
109
|
+
# @param [Boolean] only_props:
|
110
|
+
# When `true` only prop values will be added to the data hash.
|
111
|
+
#
|
112
|
+
# Otherwise, any non-prop keys and vales will be added as well
|
113
|
+
# (default behavior).
|
114
|
+
#
|
115
|
+
# @param **kwds
|
116
|
+
# See {NRSER::Props::InstanceMethods#to_data}.
|
117
|
+
#
|
118
|
+
# @return (see NRSER::Props::InstanceMethods#to_data)
|
119
|
+
#
|
120
|
+
def to_data only_props: false, **kwds
|
121
|
+
hash = super **kwds
|
122
|
+
|
123
|
+
unless only_props
|
124
|
+
each do |key, value|
|
125
|
+
# Data uses **string** keys
|
126
|
+
key = key.to_s
|
127
|
+
|
128
|
+
# See if the key is missing
|
129
|
+
unless hash.key?( key.to_s )
|
130
|
+
# It is, so let's fill it in
|
131
|
+
|
132
|
+
# If value knows how to be data, do that
|
133
|
+
value = value.to_data if value.respond_to?( :to_data )
|
134
|
+
|
135
|
+
# Set the key/value pair
|
136
|
+
hash[key] = value
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
hash
|
142
|
+
end # #to_data
|
143
|
+
|
144
|
+
|
145
|
+
def convert_key key
|
146
|
+
case key
|
147
|
+
when Symbol
|
148
|
+
key
|
149
|
+
when String
|
150
|
+
sym = key.to_sym
|
151
|
+
if self.metadata[ sym ]
|
152
|
+
sym
|
153
|
+
else
|
154
|
+
key
|
155
|
+
end
|
156
|
+
else
|
157
|
+
key
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
# Store a value at a key. If the key is a prop name, store it through the
|
163
|
+
# prop, which will check it's type.
|
164
|
+
#
|
165
|
+
# @param [Symbol | String] key
|
166
|
+
# @param [VALUE] value
|
167
|
+
#
|
168
|
+
# @return [VALUE]
|
169
|
+
# The stored value.
|
170
|
+
#
|
171
|
+
def put key, value
|
172
|
+
key = convert_key key
|
173
|
+
|
174
|
+
if (prop = self.class.metadata[ key ])
|
175
|
+
prop.set self, value
|
176
|
+
else
|
177
|
+
# We know {#convert_value} is a no-op so can skip it
|
178
|
+
_raw_put key, value
|
179
|
+
end
|
180
|
+
end # #put
|
181
|
+
|
182
|
+
|
183
|
+
def dup
|
184
|
+
self.class.new( self ).tap do |new_stash|
|
185
|
+
set_defaults new_stash
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
# Need to patch `#merge` since {NRSER::Props::InstanceMethods} defines
|
191
|
+
# it, which overrides {NRSER::Stash#merge}, so we just put it back.
|
192
|
+
#
|
193
|
+
def merge other_hash = {}, &block
|
194
|
+
dup.update other_hash, &block
|
195
|
+
end
|
196
|
+
|
197
|
+
end # module InstanceMethods
|
198
|
+
|
199
|
+
end # module NRSER::Props::Mutable::Stash
|
@@ -1,7 +1,20 @@
|
|
1
|
+
# Requirements
|
2
|
+
# =======================================================================
|
3
|
+
|
4
|
+
# Stdlib
|
5
|
+
# -----------------------------------------------------------------------
|
6
|
+
|
7
|
+
# Deps
|
8
|
+
# -----------------------------------------------------------------------
|
9
|
+
|
10
|
+
# Project / Package
|
11
|
+
# -----------------------------------------------------------------------
|
12
|
+
require 'nrser/refinements/types'
|
13
|
+
|
14
|
+
|
1
15
|
# Refinements
|
2
16
|
# =======================================================================
|
3
17
|
|
4
|
-
using NRSER
|
5
18
|
using NRSER::Types
|
6
19
|
|
7
20
|
|
@@ -9,8 +22,7 @@ using NRSER::Types
|
|
9
22
|
# =======================================================================
|
10
23
|
|
11
24
|
module NRSER; end
|
12
|
-
module NRSER::
|
13
|
-
module NRSER::Meta::Props; end
|
25
|
+
module NRSER::Props; end
|
14
26
|
|
15
27
|
|
16
28
|
# Definitions
|
@@ -21,7 +33,9 @@ module NRSER::Meta::Props; end
|
|
21
33
|
#
|
22
34
|
# Props are immutable by design.
|
23
35
|
#
|
24
|
-
class NRSER::
|
36
|
+
class NRSER::Props::Prop
|
37
|
+
|
38
|
+
include NRSER::Log::Mixin
|
25
39
|
|
26
40
|
# The class the prop was defined in.
|
27
41
|
#
|
@@ -38,13 +52,27 @@ class NRSER::Meta::Props::Prop
|
|
38
52
|
attr_reader :name
|
39
53
|
|
40
54
|
|
55
|
+
# The key under which the value will be stored in the storage.
|
56
|
+
#
|
57
|
+
# @return [nil | Integer]
|
58
|
+
#
|
59
|
+
attr_reader :index
|
60
|
+
|
61
|
+
|
41
62
|
# The type of the valid values for the property.
|
42
63
|
#
|
43
64
|
# @return [NRSER::Types::Type]
|
44
65
|
#
|
45
66
|
attr_reader :type
|
46
67
|
|
47
|
-
|
68
|
+
|
69
|
+
# Names of any props this one depends on (to create a default).
|
70
|
+
#
|
71
|
+
# @return [Array<Symbol>]
|
72
|
+
#
|
73
|
+
attr_reader :deps
|
74
|
+
|
75
|
+
|
48
76
|
# Optional name of instance variable (including the `@` prefix) or getter
|
49
77
|
# method (method that takes no arguments) that provides the property's
|
50
78
|
# value.
|
@@ -68,6 +96,13 @@ class NRSER::Meta::Props::Prop
|
|
68
96
|
attr_reader :source
|
69
97
|
|
70
98
|
|
99
|
+
# TODO document `aliases` attribute.
|
100
|
+
#
|
101
|
+
# @return [Array<Symbol>]
|
102
|
+
#
|
103
|
+
attr_reader :aliases
|
104
|
+
|
105
|
+
|
71
106
|
# Constructor
|
72
107
|
# =====================================================================
|
73
108
|
|
@@ -75,8 +110,8 @@ class NRSER::Meta::Props::Prop
|
|
75
110
|
#
|
76
111
|
# You should not need to construct a `Prop` directly unless you are doing
|
77
112
|
# custom meta-programming - they should be constructed for you via the
|
78
|
-
# `.prop` "macro" defined at {NRSER::
|
79
|
-
# that is extended in to classes including {NRSER::
|
113
|
+
# `.prop` "macro" defined at {NRSER::Props::Props::ClassMethods#prop}
|
114
|
+
# that is extended in to classes including {NRSER::Props::Props}.
|
80
115
|
#
|
81
116
|
# @param [nil | Proc | Object] default:
|
82
117
|
# A default value or a {Proc} used to get default values for *primary*
|
@@ -101,16 +136,29 @@ class NRSER::Meta::Props::Prop
|
|
101
136
|
default: nil,
|
102
137
|
source: nil,
|
103
138
|
to_data: nil,
|
104
|
-
from_data: nil
|
139
|
+
from_data: nil,
|
140
|
+
index: nil,
|
141
|
+
reader: nil,
|
142
|
+
writer: nil,
|
143
|
+
aliases: []
|
105
144
|
|
106
145
|
# Set these up first so {#to_s} works in case we need to raise errors.
|
107
146
|
@defined_in = defined_in
|
108
147
|
@name = t.sym.check name
|
148
|
+
@index = t.non_neg_int?.check! index
|
109
149
|
@type = t.make type
|
110
150
|
|
151
|
+
# Will be overridden in {#init_default!} if needed
|
152
|
+
@deps = []
|
153
|
+
|
111
154
|
@to_data = to_data
|
112
155
|
@from_data = from_data
|
113
156
|
|
157
|
+
@reader = t.bool?.check! reader
|
158
|
+
@writer = t.bool?.check! writer
|
159
|
+
|
160
|
+
@aliases = t.array( t.sym ).check! aliases
|
161
|
+
|
114
162
|
# Source
|
115
163
|
|
116
164
|
# normalize source to {nil}, {Symbol} or {Proc}
|
@@ -147,7 +195,7 @@ class NRSER::Meta::Props::Prop
|
|
147
195
|
# for sourced props
|
148
196
|
if source?
|
149
197
|
raise ArgumentError.new binding.erb <<-END
|
150
|
-
Can not construct {<%= self.class.
|
198
|
+
Can not construct {<%= self.class.safe_name %>} with `default` and `source`
|
151
199
|
|
152
200
|
Props with {#source} always get their value from that source, so
|
153
201
|
defaults don't make any sense.
|
@@ -166,8 +214,47 @@ class NRSER::Meta::Props::Prop
|
|
166
214
|
END
|
167
215
|
end
|
168
216
|
|
169
|
-
|
170
|
-
|
217
|
+
if Proc === default
|
218
|
+
case default.arity
|
219
|
+
when 0
|
220
|
+
# pass, no deps
|
221
|
+
when 1
|
222
|
+
# Check that it's valid and set deps
|
223
|
+
@deps = default.parameters.map do |param|
|
224
|
+
unless Array === param &&
|
225
|
+
:keyreq == param[0]
|
226
|
+
raise ArgumentError.new binding.erb <<~END
|
227
|
+
Prop default Proc that take args must take only required
|
228
|
+
keywords (`:keyreq` type)
|
229
|
+
|
230
|
+
This is because this is how the props system figures out
|
231
|
+
any dependency orders.
|
232
|
+
|
233
|
+
Found:
|
234
|
+
|
235
|
+
<%= default.parameters %>
|
236
|
+
|
237
|
+
For `default` for prop <%= full_name %>:
|
238
|
+
|
239
|
+
<%= self.pretty_inspect %>
|
240
|
+
|
241
|
+
END
|
242
|
+
end
|
243
|
+
|
244
|
+
# The keyword name
|
245
|
+
param[1]
|
246
|
+
end
|
247
|
+
else
|
248
|
+
raise ArgumentError.new binding.erb <<~END
|
249
|
+
Prop default Proc must take no params or only required keywords
|
250
|
+
({Proc#arity} of 0 or 1).
|
251
|
+
|
252
|
+
Default to prop <%= full_name %> has arity <%= default.arity %>.
|
253
|
+
|
254
|
+
END
|
255
|
+
end
|
256
|
+
|
257
|
+
elsif !default.frozen?
|
171
258
|
raise ArgumentError.new binding.erb <<-END
|
172
259
|
Non-proc default values must be frozen
|
173
260
|
|
@@ -195,13 +282,21 @@ class NRSER::Meta::Props::Prop
|
|
195
282
|
# Instance Methods
|
196
283
|
# ============================================================================
|
197
284
|
|
198
|
-
|
285
|
+
def names
|
286
|
+
[name, *aliases]
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
# Used by the {NRSER::Props::Props::ClassMethods.prop} "macro" method to
|
199
291
|
# determine if it should create a reader method on the propertied class.
|
200
292
|
#
|
201
293
|
# @return [Boolean]
|
202
294
|
# `true` if a reader method should be created for the prop value.
|
203
295
|
#
|
204
|
-
def create_reader?
|
296
|
+
def create_reader? name
|
297
|
+
# If the options was explicitly provided then return that
|
298
|
+
return @reader unless @reader.nil?
|
299
|
+
|
205
300
|
# Always create readers for primary props
|
206
301
|
return true if primary?
|
207
302
|
|
@@ -216,7 +311,7 @@ class NRSER::Meta::Props::Prop
|
|
216
311
|
end # #create_reader?
|
217
312
|
|
218
313
|
|
219
|
-
# Used by the {NRSER::
|
314
|
+
# Used by the {NRSER::Props::Props::ClassMethods.prop} "macro" method to
|
220
315
|
# determine if it should create a writer method on the propertied class.
|
221
316
|
#
|
222
317
|
# Right now, we don't create writers, but we will probably make them an
|
@@ -225,7 +320,13 @@ class NRSER::Meta::Props::Prop
|
|
225
320
|
# @return [Boolean]
|
226
321
|
# Always `false` for the moment.
|
227
322
|
#
|
228
|
-
def create_writer?
|
323
|
+
def create_writer? name
|
324
|
+
return @writer unless @writer.nil?
|
325
|
+
|
326
|
+
storage_immutable = defined_in.metadata.storage.try( :immutable? )
|
327
|
+
|
328
|
+
return !storage_immutable unless storage_immutable.nil?
|
329
|
+
|
229
330
|
false
|
230
331
|
end # #create_writer?
|
231
332
|
|
@@ -259,16 +360,37 @@ class NRSER::Meta::Props::Prop
|
|
259
360
|
alias_method :default?, :has_default?
|
260
361
|
|
261
362
|
|
262
|
-
|
363
|
+
# Get the default value for the property given the instance and values.
|
364
|
+
#
|
365
|
+
# @todo
|
366
|
+
# This is a shitty hack stop-gap until I really figure our how this should
|
367
|
+
# work.
|
368
|
+
#
|
369
|
+
# @param [Hash<Symbol, Object>] values
|
370
|
+
# Other prop values known at this point, keyed by name.
|
371
|
+
#
|
372
|
+
# @return [Object]
|
373
|
+
# Default value.
|
374
|
+
#
|
375
|
+
# @raise [NameError]
|
376
|
+
# If the prop doesn't have a default.
|
377
|
+
#
|
378
|
+
def default **values
|
263
379
|
if has_default?
|
264
380
|
if Proc === @default
|
265
|
-
@default.
|
381
|
+
case @default.arity
|
382
|
+
when 0
|
383
|
+
@default.call
|
384
|
+
else
|
385
|
+
kwds = values.slice *deps
|
386
|
+
@default.call **kwds
|
387
|
+
end
|
266
388
|
else
|
267
389
|
@default
|
268
390
|
end
|
269
391
|
else
|
270
|
-
raise NameError.new
|
271
|
-
Prop
|
392
|
+
raise NameError.new binding.erb <<-END
|
393
|
+
Prop <%= full_name %> has no default value (and none provided).
|
272
394
|
END
|
273
395
|
end
|
274
396
|
end
|
@@ -309,100 +431,107 @@ class NRSER::Meta::Props::Prop
|
|
309
431
|
end # #primary?
|
310
432
|
|
311
433
|
|
312
|
-
#
|
434
|
+
# Get the value of the prop from an instance.
|
313
435
|
#
|
314
|
-
# @
|
315
|
-
#
|
436
|
+
# @note
|
437
|
+
# At the moment, values are **not** type-checked when reading. Primary
|
438
|
+
# values are checked when setting, so they should be ok, but this does
|
439
|
+
# leave the possibility that props with a {#source} may return values
|
440
|
+
# that do not satisfy their types... :/
|
316
441
|
#
|
317
|
-
# @
|
318
|
-
#
|
442
|
+
# @param [NRSER::Props] instance
|
443
|
+
# An instance of {#defined_in}.
|
444
|
+
#
|
445
|
+
# @return
|
446
|
+
# Value from the instance's prop value storage (for {#primary?} props)
|
447
|
+
# or it's {#source}.
|
319
448
|
#
|
320
449
|
def get instance
|
321
450
|
if source?
|
322
451
|
if instance_variable_source?
|
323
452
|
instance.instance_variable_get source
|
324
453
|
else
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
else
|
331
|
-
raise TypeError.squished <<-END
|
332
|
-
Expected `Prop#source` to be a String, Symbol or Proc;
|
333
|
-
found #{ source.inspect }
|
334
|
-
END
|
335
|
-
end
|
454
|
+
t.match source,
|
455
|
+
t.or( String, Symbol ),
|
456
|
+
->( name ) { instance.send name },
|
457
|
+
Proc,
|
458
|
+
->( block ) { instance.instance_exec &block }
|
336
459
|
end
|
337
460
|
else
|
338
|
-
|
461
|
+
# Go through the storage engine
|
462
|
+
instance.class.metadata.storage.get instance, self
|
339
463
|
end
|
340
464
|
end # #get
|
341
465
|
|
342
466
|
|
343
|
-
#
|
467
|
+
# Set a value for a the prop on an instance.
|
344
468
|
#
|
345
|
-
# @param [
|
346
|
-
#
|
469
|
+
# @param [NRSER::Props] instance
|
470
|
+
# An instance of {#defined_in}.
|
347
471
|
#
|
348
|
-
# @
|
349
|
-
#
|
472
|
+
# @param [*] value
|
473
|
+
# A value that must satisfy {#type}.
|
474
|
+
#
|
475
|
+
# @return [nil]
|
476
|
+
#
|
477
|
+
# @raise [RuntimeError]
|
478
|
+
# If you try to set a value for a prop that isn't {#primary?}.
|
479
|
+
#
|
480
|
+
# @raise (see #check!)
|
350
481
|
#
|
351
482
|
def set instance, value
|
352
|
-
|
353
|
-
binding.erb
|
354
|
-
|
355
|
-
failed type check.
|
483
|
+
unless primary?
|
484
|
+
raise RuntimeError.new binding.erb <<~END
|
485
|
+
Only {#primary?} props can be set!
|
356
486
|
|
357
|
-
|
487
|
+
Tried to set prop #{ prop.name } to value
|
358
488
|
|
359
|
-
<%=
|
489
|
+
<%= value.pretty_inspect %>
|
360
490
|
|
361
|
-
|
491
|
+
in instance
|
362
492
|
|
363
|
-
<%=
|
493
|
+
<%= instance.pretty_inspect %>
|
364
494
|
|
365
495
|
END
|
366
496
|
end
|
367
497
|
|
368
|
-
|
498
|
+
instance.class.metadata.storage.put \
|
499
|
+
instance,
|
500
|
+
self,
|
501
|
+
check!( value )
|
502
|
+
|
503
|
+
nil
|
369
504
|
end # #set
|
370
505
|
|
371
506
|
|
372
|
-
#
|
507
|
+
# Check that a value satisfies the {#type}, raising if it doesn't.
|
373
508
|
#
|
374
|
-
# @param [
|
375
|
-
#
|
509
|
+
# @param [VALUE] value
|
510
|
+
# Value to check.
|
376
511
|
#
|
377
|
-
# @return [
|
378
|
-
#
|
512
|
+
# @return [VALUE]
|
513
|
+
# `value` arg that was passed in.
|
379
514
|
#
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
Prop:
|
399
|
-
|
400
|
-
<%= self.pretty_inspect %>
|
401
|
-
|
402
|
-
ERB
|
403
|
-
end
|
515
|
+
# @raise [NRSER::Types::CheckError]
|
516
|
+
# If `value` does not satisfy {#type}.
|
517
|
+
#
|
518
|
+
def check! value
|
519
|
+
type.check!( value ) do
|
520
|
+
binding.erb <<-END
|
521
|
+
Value of type <%= value.class.safe_name %> for prop <%= self.full_name %>
|
522
|
+
failed type check.
|
523
|
+
|
524
|
+
Must satisfy type:
|
525
|
+
|
526
|
+
<%= type %>
|
527
|
+
|
528
|
+
Given value:
|
529
|
+
|
530
|
+
<%= value.pretty_inspect %>
|
531
|
+
|
532
|
+
END
|
404
533
|
end
|
405
|
-
end # #
|
534
|
+
end # #check!
|
406
535
|
|
407
536
|
|
408
537
|
# Get the "data" value - a basic scalar or structure of hashes, arrays and
|
@@ -438,7 +567,7 @@ class NRSER::Meta::Props::Prop
|
|
438
567
|
# - The `to_data:` proc is called with the property value as the sole
|
439
568
|
# argument and the result is returned as the data.
|
440
569
|
#
|
441
|
-
# @param [NRSER::
|
570
|
+
# @param [NRSER::Props::Props] instance
|
442
571
|
# Instance to get the property value form.
|
443
572
|
#
|
444
573
|
# @return [Object]
|
@@ -474,13 +603,12 @@ class NRSER::Meta::Props::Prop
|
|
474
603
|
end # #to_data
|
475
604
|
|
476
605
|
|
477
|
-
#
|
606
|
+
# Load a value for the prop from "data".
|
478
607
|
#
|
479
|
-
# @param [
|
480
|
-
# @todo Add name param description.
|
608
|
+
# @param [*] data
|
481
609
|
#
|
482
|
-
# @return [
|
483
|
-
#
|
610
|
+
# @return [VALUE]
|
611
|
+
# The prop value to use.
|
484
612
|
#
|
485
613
|
def value_from_data data
|
486
614
|
value = case @from_data
|
@@ -498,7 +626,7 @@ class NRSER::Meta::Props::Prop
|
|
498
626
|
# The custom `from_data` configuration specifies a string or symbol name,
|
499
627
|
# which we interpret as a class method on the defining class and call
|
500
628
|
# with the data to produce a value.
|
501
|
-
@defined_in.send @
|
629
|
+
@defined_in.send @from_data, data
|
502
630
|
|
503
631
|
when Proc
|
504
632
|
# The custom `from_data` configuration provides a procedure, which we
|
@@ -536,30 +664,7 @@ class NRSER::Meta::Props::Prop
|
|
536
664
|
# a short string describing the instance.
|
537
665
|
#
|
538
666
|
def to_s
|
539
|
-
"#<#{ self.class.
|
667
|
+
"#<#{ self.class.safe_name } #{ full_name }:#{ type }>"
|
540
668
|
end # #to_s
|
541
669
|
|
542
|
-
|
543
|
-
private
|
544
|
-
|
545
|
-
# @todo Document values method.
|
546
|
-
#
|
547
|
-
# @param [type] arg_name
|
548
|
-
# @todo Add name param description.
|
549
|
-
#
|
550
|
-
# @return [return_type]
|
551
|
-
# @todo Document return value.
|
552
|
-
#
|
553
|
-
def values instance
|
554
|
-
unless instance.instance_variable_defined?(
|
555
|
-
NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME
|
556
|
-
)
|
557
|
-
instance.instance_variable_set \
|
558
|
-
NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME, {}
|
559
|
-
end
|
560
|
-
|
561
|
-
instance.instance_variable_get \
|
562
|
-
NRSER::Meta::Props::PROP_VALUES_VARIABLE_NAME
|
563
|
-
end # #value
|
564
|
-
|
565
|
-
end # class NRSER::Meta::Props::Prop
|
670
|
+
end # class NRSER::Props::Prop
|