stannum 0.1.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 +7 -0
- data/CHANGELOG.md +21 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/DEVELOPMENT.md +105 -0
- data/LICENSE +22 -0
- data/README.md +1327 -0
- data/config/locales/en.rb +47 -0
- data/lib/stannum/attribute.rb +115 -0
- data/lib/stannum/constraint.rb +65 -0
- data/lib/stannum/constraints/absence.rb +42 -0
- data/lib/stannum/constraints/anything.rb +28 -0
- data/lib/stannum/constraints/base.rb +285 -0
- data/lib/stannum/constraints/boolean.rb +33 -0
- data/lib/stannum/constraints/delegator.rb +71 -0
- data/lib/stannum/constraints/enum.rb +64 -0
- data/lib/stannum/constraints/equality.rb +47 -0
- data/lib/stannum/constraints/hashes/extra_keys.rb +126 -0
- data/lib/stannum/constraints/hashes/indifferent_key.rb +74 -0
- data/lib/stannum/constraints/hashes.rb +11 -0
- data/lib/stannum/constraints/identity.rb +46 -0
- data/lib/stannum/constraints/nothing.rb +28 -0
- data/lib/stannum/constraints/presence.rb +42 -0
- data/lib/stannum/constraints/signature.rb +92 -0
- data/lib/stannum/constraints/signatures/map.rb +17 -0
- data/lib/stannum/constraints/signatures/tuple.rb +17 -0
- data/lib/stannum/constraints/signatures.rb +11 -0
- data/lib/stannum/constraints/tuples/extra_items.rb +84 -0
- data/lib/stannum/constraints/tuples.rb +10 -0
- data/lib/stannum/constraints/type.rb +113 -0
- data/lib/stannum/constraints/types/array_type.rb +148 -0
- data/lib/stannum/constraints/types/big_decimal_type.rb +16 -0
- data/lib/stannum/constraints/types/date_time_type.rb +16 -0
- data/lib/stannum/constraints/types/date_type.rb +16 -0
- data/lib/stannum/constraints/types/float_type.rb +14 -0
- data/lib/stannum/constraints/types/hash_type.rb +205 -0
- data/lib/stannum/constraints/types/hash_with_indifferent_keys.rb +21 -0
- data/lib/stannum/constraints/types/hash_with_string_keys.rb +21 -0
- data/lib/stannum/constraints/types/hash_with_symbol_keys.rb +21 -0
- data/lib/stannum/constraints/types/integer_type.rb +14 -0
- data/lib/stannum/constraints/types/nil_type.rb +20 -0
- data/lib/stannum/constraints/types/proc_type.rb +14 -0
- data/lib/stannum/constraints/types/string_type.rb +14 -0
- data/lib/stannum/constraints/types/symbol_type.rb +14 -0
- data/lib/stannum/constraints/types/time_type.rb +14 -0
- data/lib/stannum/constraints/types.rb +25 -0
- data/lib/stannum/constraints/union.rb +85 -0
- data/lib/stannum/constraints.rb +26 -0
- data/lib/stannum/contract.rb +243 -0
- data/lib/stannum/contracts/array_contract.rb +108 -0
- data/lib/stannum/contracts/base.rb +597 -0
- data/lib/stannum/contracts/builder.rb +72 -0
- data/lib/stannum/contracts/definition.rb +74 -0
- data/lib/stannum/contracts/hash_contract.rb +136 -0
- data/lib/stannum/contracts/indifferent_hash_contract.rb +78 -0
- data/lib/stannum/contracts/map_contract.rb +199 -0
- data/lib/stannum/contracts/parameters/arguments_contract.rb +185 -0
- data/lib/stannum/contracts/parameters/keywords_contract.rb +174 -0
- data/lib/stannum/contracts/parameters/signature_contract.rb +29 -0
- data/lib/stannum/contracts/parameters.rb +15 -0
- data/lib/stannum/contracts/parameters_contract.rb +530 -0
- data/lib/stannum/contracts/tuple_contract.rb +213 -0
- data/lib/stannum/contracts.rb +19 -0
- data/lib/stannum/errors.rb +730 -0
- data/lib/stannum/messages/default_strategy.rb +124 -0
- data/lib/stannum/messages.rb +25 -0
- data/lib/stannum/parameter_validation.rb +216 -0
- data/lib/stannum/rspec/match_errors.rb +17 -0
- data/lib/stannum/rspec/match_errors_matcher.rb +93 -0
- data/lib/stannum/rspec/validate_parameter.rb +23 -0
- data/lib/stannum/rspec/validate_parameter_matcher.rb +506 -0
- data/lib/stannum/rspec.rb +8 -0
- data/lib/stannum/schema.rb +131 -0
- data/lib/stannum/struct.rb +444 -0
- data/lib/stannum/support/coercion.rb +114 -0
- data/lib/stannum/support/optional.rb +69 -0
- data/lib/stannum/support.rb +8 -0
- data/lib/stannum/version.rb +57 -0
- data/lib/stannum.rb +27 -0
- metadata +216 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/contracts/indifferent_hash_contract'
|
4
|
+
require 'stannum/contracts/parameters'
|
5
|
+
|
6
|
+
module Stannum::Contracts::Parameters
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
# A KeywordsContract constrains the keywords given for a method.
|
10
|
+
class KeywordsContract < Stannum::Contracts::IndifferentHashContract
|
11
|
+
# The :type of the error generated for extra keywords.
|
12
|
+
EXTRA_KEYWORDS_TYPE = 'stannum.constraints.parameters.extra_keywords'
|
13
|
+
|
14
|
+
# Value used when keywords hash does not have a value for the given key.
|
15
|
+
UNDEFINED = Object.new.freeze
|
16
|
+
|
17
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
18
|
+
# contract. Defaults to an empty Hash.
|
19
|
+
def initialize(**options)
|
20
|
+
super(
|
21
|
+
allow_extra_keys: false,
|
22
|
+
**options
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Adds a keyword constraint to the contract.
|
27
|
+
#
|
28
|
+
# Generates a keyword constraint based on the given type. If the type is
|
29
|
+
# a constraint, then the given constraint will be copied with the given
|
30
|
+
# options and added for the given keyword. If the type is a Class or a
|
31
|
+
# Module, then a Stannum::Constraints::Type constraint will be created with
|
32
|
+
# the given type and options and added for the keyword.
|
33
|
+
#
|
34
|
+
# @param keyword [Symbol] The keyword to constrain.
|
35
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected type
|
36
|
+
# of the argument.
|
37
|
+
# @param default [Boolean] If true, the keyword has a default value, and
|
38
|
+
# the constraint will ignore keywords with no value at that key.
|
39
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
40
|
+
# constraint. Defaults to an empty Hash.
|
41
|
+
#
|
42
|
+
# @return [Stannum::Contracts::Parameters::KeywordsContract] the contract.
|
43
|
+
def add_keyword_constraint(keyword, type, default: false, **options)
|
44
|
+
unless keyword.is_a?(Symbol)
|
45
|
+
raise ArgumentError, 'keyword must be a symbol'
|
46
|
+
end
|
47
|
+
|
48
|
+
constraint = Stannum::Support::Coercion.type_constraint(type, **options)
|
49
|
+
|
50
|
+
add_key_constraint(keyword, constraint, default: !!default, **options)
|
51
|
+
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sets a constraint for the variadic keywords.
|
56
|
+
#
|
57
|
+
# The given constraint must match the variadic keywords hash as a whole.
|
58
|
+
# To constraint each individual value, use #set_variadic_value_constraint.
|
59
|
+
#
|
60
|
+
# @param constraint [Stannum::Constraints::Base] The constraint to add.
|
61
|
+
# The variadic keywords (a hash) as a whole must match the given
|
62
|
+
# constraint.
|
63
|
+
# @param as [Symbol] A human-friendly reference for the additional
|
64
|
+
# keywords. Used when generating errors. Should be the same name used in
|
65
|
+
# the method definition.
|
66
|
+
#
|
67
|
+
# @return [self] the contract.
|
68
|
+
#
|
69
|
+
# @raise [RuntimeError] if the variadic keywords constraint is already set.
|
70
|
+
#
|
71
|
+
# @see #set_variadic_item_constraint
|
72
|
+
def set_variadic_constraint(constraint, as: nil)
|
73
|
+
raise 'variadic keywords constraint is already set' if allow_extra_keys?
|
74
|
+
|
75
|
+
options[:allow_extra_keys] = true
|
76
|
+
|
77
|
+
variadic_constraint.receiver = constraint
|
78
|
+
|
79
|
+
variadic_definition.options[:property_name] = as if as
|
80
|
+
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
# Sets a constraint for the variadic keyword values.
|
85
|
+
#
|
86
|
+
# The given type or constraint must individually match each value (if any)
|
87
|
+
# in the variadic keywords. To constrain the variadic keywords as a whole,
|
88
|
+
# use #set_variadic_constraint.
|
89
|
+
#
|
90
|
+
# @param value_type [Stannum::Constraints::Base, Class, Module] The type or
|
91
|
+
# constraint to add. If the type is a Class or Module, then it is
|
92
|
+
# converted to a Stannum::Constraints::Type. Each value in the variadic
|
93
|
+
# keywords must match the given constraint.
|
94
|
+
# @param as [Symbol] A human-friendly reference for the additional
|
95
|
+
# keywords. Used when generating errors. Should be the same name used in
|
96
|
+
# the method definition.
|
97
|
+
#
|
98
|
+
# @return [self] the contract.
|
99
|
+
#
|
100
|
+
# @raise [RuntimeError] if the variadic keywords constraint is already set.
|
101
|
+
#
|
102
|
+
# @see #set_variadic_constraint
|
103
|
+
def set_variadic_value_constraint(value_type, as: nil)
|
104
|
+
type = coerce_value_type(value_type)
|
105
|
+
constraint = Stannum::Constraints::Types::HashType.new(
|
106
|
+
key_type: Stannum::Constraints::Types::SymbolType.new,
|
107
|
+
value_type: type
|
108
|
+
)
|
109
|
+
|
110
|
+
set_variadic_constraint(constraint, as: as)
|
111
|
+
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
def add_errors_for(definition, value, errors)
|
116
|
+
return super unless value == UNDEFINED
|
117
|
+
|
118
|
+
super(definition, nil, errors)
|
119
|
+
end
|
120
|
+
|
121
|
+
def add_negated_errors_for(definition, value, errors)
|
122
|
+
return super unless value == UNDEFINED
|
123
|
+
|
124
|
+
super(definition, nil, errors)
|
125
|
+
end
|
126
|
+
|
127
|
+
def map_value(actual, **options)
|
128
|
+
return super unless options[:property_type] == :key
|
129
|
+
|
130
|
+
return super unless actual.is_a?(Hash)
|
131
|
+
|
132
|
+
return super if actual.key?(options[:property])
|
133
|
+
|
134
|
+
UNDEFINED
|
135
|
+
end
|
136
|
+
|
137
|
+
def match_constraint(definition, value)
|
138
|
+
return super unless value == UNDEFINED
|
139
|
+
|
140
|
+
definition.options[:default] ? true : super(definition, nil)
|
141
|
+
end
|
142
|
+
|
143
|
+
def match_negated_constraint(definition, value)
|
144
|
+
return super unless value == UNDEFINED
|
145
|
+
|
146
|
+
definition.options[:default] ? false : super(definition, nil)
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
attr_reader :variadic_constraint
|
152
|
+
|
153
|
+
attr_reader :variadic_definition
|
154
|
+
|
155
|
+
def add_extra_keys_constraint
|
156
|
+
keys = -> { expected_keys }
|
157
|
+
|
158
|
+
@variadic_constraint = Stannum::Constraints::Delegator.new(
|
159
|
+
Stannum::Constraints::Hashes::ExtraKeys.new(
|
160
|
+
keys,
|
161
|
+
type: EXTRA_KEYWORDS_TYPE
|
162
|
+
)
|
163
|
+
)
|
164
|
+
|
165
|
+
add_constraint @variadic_constraint
|
166
|
+
|
167
|
+
@variadic_definition = @constraints.last
|
168
|
+
end
|
169
|
+
|
170
|
+
def coerce_value_type(value_type)
|
171
|
+
Stannum::Support::Coercion.type_constraint(value_type, as: 'value type')
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/contracts/parameters'
|
4
|
+
|
5
|
+
module Stannum::Contracts::Parameters
|
6
|
+
# A SignatureContract defines a parameters object for a ParametersContract.
|
7
|
+
class SignatureContract < Stannum::Contracts::HashContract
|
8
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
9
|
+
# contract. Defaults to an empty Hash.
|
10
|
+
def initialize(**options)
|
11
|
+
super(key_type: Symbol, **options)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def define_constraints(&block)
|
17
|
+
super
|
18
|
+
|
19
|
+
add_key_constraint :arguments,
|
20
|
+
Stannum::Constraints::Types::ArrayType.new
|
21
|
+
add_key_constraint :keywords,
|
22
|
+
Stannum::Constraints::Types::HashType.new(
|
23
|
+
key_type: Stannum::Constraints::Types::SymbolType.new
|
24
|
+
)
|
25
|
+
add_key_constraint :block,
|
26
|
+
Stannum::Constraints::Types::ProcType.new(optional: true)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/contracts'
|
4
|
+
|
5
|
+
module Stannum::Contracts
|
6
|
+
# Namespace for contracts that constrain method parameters.
|
7
|
+
module Parameters
|
8
|
+
autoload :ArgumentsContract,
|
9
|
+
'stannum/contracts/parameters/arguments_contract'
|
10
|
+
autoload :KeywordsContract,
|
11
|
+
'stannum/contracts/parameters/keywords_contract'
|
12
|
+
autoload :SignatureContract,
|
13
|
+
'stannum/contracts/parameters/signature_contract'
|
14
|
+
end
|
15
|
+
end
|