dry-types 0.10.3 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 39a0be1972bae04a7b9f3f45e5b4430948c825a1
4
- data.tar.gz: b74e55614628bc6a556ebef86a8bfa6abfc12e85
3
+ metadata.gz: 12cffdbb9c18b6f1ab0bb726c5a13fbd13c1178e
4
+ data.tar.gz: 150931c98379624c229416370bd63cd8830bbab5
5
5
  SHA512:
6
- metadata.gz: f2a0a595e1feb9a642269b6fdaaaf42be81f09a6cb31be3f30ed63a4ac85a1cf816fa1ba9e147b487cceff6436f52161fa032321c7828ed2c657d12a8fa13a72
7
- data.tar.gz: 1e5d6ad66e3fef84f7d31a0d430b2bb7b20c0225d5ad527e5cdf90a6f4dbcb12b8837705173372732034416aa76f6f915df044ef64305ad0d557675d8b1beca9
6
+ metadata.gz: 7b6bd371faf9ae94c6559c01309216205c3df88614c86cb2862929b2836d8cc4c32b76d916f6deeb6e4390bb296c8e1733e85e8997b3f00092584960961e02ee
7
+ data.tar.gz: 584c9552a9185595008a63c2ca6f3a8cc88ec56b7c063f720d36ff10d9c1b26b403443456416a484429cae4b7e10bd6a06995acd3adf99eb89b1026825a9fd83
@@ -9,17 +9,13 @@ script:
9
9
  - bundle exec rake
10
10
  rvm:
11
11
  - 2.2.7
12
- - 2.3.3
12
+ - 2.3.4
13
13
  - 2.4.1
14
- - jruby-9.1.8.0
15
- - rbx-3
14
+ - jruby-9.1.10.0
16
15
  env:
17
16
  global:
18
17
  - COVERAGE=true
19
18
  - JRUBY_OPTS='--dev -J-Xmx1024M'
20
- matrix:
21
- allow_failures:
22
- - rvm: rbx-3
23
19
  notifications:
24
20
  email: false
25
21
  webhooks:
@@ -1,3 +1,13 @@
1
+ # v0.11.0 2017-06-30
2
+
3
+ ## Added
4
+
5
+ * `#to_ast` available for all type objects (GustavoCaso)
6
+ * `Types::Array#of` as an alias for `#member` (maliqq)
7
+ * Detailed failure objects are passed to results which improves constraint violation messages (GustavoCaso)
8
+
9
+ [Compare v0.10.3...v0.11.0](https://github.com/dry-rb/dry-types/compare/v0.10.3...v0.11.0)
10
+
1
11
  # v0.10.3 2017-05-06
2
12
 
3
13
  ## Added
@@ -0,0 +1,29 @@
1
+ # Issue Guidelines
2
+
3
+ ## Reporting bugs
4
+
5
+ If you found a bug, report an issue and describe what's the expected behavior versus what actually happens. If the bug causes a crash, attach a full backtrace. If possible, a reproduction script showing the problem is highly appreciated.
6
+
7
+ ## Reporting feature requests
8
+
9
+ Report a feature request **only after discussing it first on [discuss.dry-rb.org](https://discuss.dry-rb.org)** where it was accepted. Please provide a concise description of the feature, don't link to a discussion thread, and instead summarize what was discussed.
10
+
11
+ ## Reporting questions, support requests, ideas, concerns etc.
12
+
13
+ **PLEASE DON'T** - use [discuss.dry-rb.org](http://discuss.dry-rb.org) instead.
14
+
15
+ # Pull Request Guidelines
16
+
17
+ A Pull Request will only be accepted if it addresses a specific issue that was reported previously, or fixes typos, mistakes in documentation etc.
18
+
19
+ Other requirements:
20
+
21
+ 1) Do not open a pull request if you can't provide tests along with it. If you have problems writing tests, ask for help in the related issue.
22
+ 2) Follow the style conventions of the surrounding code. In most cases, this is standard ruby style.
23
+ 3) Add API documentation if it's a new feature
24
+ 4) Update API documentation if it changes an existing feature
25
+ 5) Bonus points for sending a PR to [github.com/dry-rb/dry-rb.org](github.com/dry-rb/dry-rb.org) which updates user documentation and guides
26
+
27
+ # Asking for help
28
+
29
+ If these guidelines aren't helpful, and you're stuck, please post a message on [discuss.dry-rb.org](https://discuss.dry-rb.org).
data/README.md CHANGED
@@ -20,7 +20,7 @@
20
20
 
21
21
  ## Development
22
22
 
23
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
23
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake run_specs` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
24
24
 
25
25
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
26
26
 
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.bindir = "exe"
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
- spec.required_ruby_version = ">= 2.1.0"
29
+ spec.required_ruby_version = ">= 2.2.0"
30
30
 
31
31
  spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
32
32
  spec.add_runtime_dependency 'dry-core', '~> 0.2', '>= 0.2.1'
@@ -15,6 +15,7 @@ require 'dry/types/container'
15
15
  require 'dry/types/type'
16
16
  require 'dry/types/definition'
17
17
  require 'dry/types/constructor'
18
+ require 'dry/types/fn_container'
18
19
 
19
20
  require 'dry/types/errors'
20
21
 
@@ -51,6 +52,11 @@ module Dry
51
52
  @container ||= Container.new
52
53
  end
53
54
 
55
+ # @api private
56
+ def self.registered?(class_or_identifier)
57
+ container.key?(identifier(class_or_identifier))
58
+ end
59
+
54
60
  # @param [String] name
55
61
  # @param [Type] type
56
62
  # @param [#call,nil] block
@@ -14,6 +14,8 @@ module Dry
14
14
 
15
15
  Array::Member.new(primitive, options.merge(member: member))
16
16
  end
17
+
18
+ alias_method :of, :member
17
19
  end
18
20
  end
19
21
  end
@@ -48,6 +48,13 @@ module Dry
48
48
  block ? yield(failure) : failure
49
49
  end
50
50
  end
51
+
52
+ # @api public
53
+ #
54
+ # @see Definition#to_ast
55
+ def to_ast(meta: true)
56
+ [:array, [member.to_ast(meta: meta), meta ? self.meta : EMPTY_HASH]]
57
+ end
51
58
  end
52
59
  end
53
60
  end
@@ -11,73 +11,76 @@ module Dry
11
11
  visit(ast)
12
12
  end
13
13
 
14
- def visit(node, *args)
15
- send(:"visit_#{node[0]}", node[1], *args)
14
+ def visit(node)
15
+ type, body = node
16
+ send(:"visit_#{ type }", body)
16
17
  end
17
18
 
18
19
  def visit_constructor(node)
19
- primitive, fn = node
20
+ definition, fn_register_name, meta = node
21
+ fn = Dry::Types::FnContainer[fn_register_name]
22
+ primitive = visit(definition)
20
23
  Types::Constructor.new(primitive, &fn)
21
24
  end
22
25
 
23
- def visit_type(node)
24
- type, args = node
25
- meth = :"visit_#{type.tr('.', '_')}"
26
+ def visit_safe(node)
27
+ ast, meta = node
28
+ Types::Safe.new(visit(ast), meta: meta)
29
+ end
30
+
31
+ def visit_definition(node)
32
+ type, meta = node
26
33
 
27
- if respond_to?(meth) && args
28
- send(meth, args)
34
+ if registry.registered?(type)
35
+ registry[type].meta(meta)
29
36
  else
30
- registry[type]
37
+ Definition.new(type, meta: meta)
31
38
  end
32
39
  end
33
40
 
34
41
  def visit_sum(node)
35
- node.map { |type| visit(type) }.reduce(:|)
42
+ *types, meta = node
43
+ types.map { |type| visit(type) }.reduce(:|).meta(meta)
36
44
  end
37
45
 
38
46
  def visit_array(node)
39
- registry['array'].member(call(node))
47
+ member, meta = node
48
+ registry['array'].member(visit(member)).meta(meta)
40
49
  end
41
50
 
42
- def visit_form_array(node)
43
- registry['form.array'].member(call(node))
51
+ def visit_hash(node)
52
+ constructor, schema, meta = node
53
+ merge_with('hash', constructor, schema).meta(meta)
44
54
  end
45
55
 
46
- def visit_json_array(node)
47
- registry['json.array'].member(call(node))
56
+ def visit_json_hash(node)
57
+ schema, meta = node
58
+ merge_with('json.hash', :symbolized, schema).meta(meta)
48
59
  end
49
60
 
50
- def visit_hash(node)
51
- constructor, schema = node
52
- merge_with('hash', constructor, schema)
61
+ def visit_json_array(node)
62
+ member, meta = node
63
+ registry['json.array'].member(visit(member)).meta(meta)
53
64
  end
54
65
 
55
66
  def visit_form_hash(node)
56
- if node
57
- constructor, schema = node
58
- merge_with('form.hash', constructor, schema)
59
- else
60
- registry['form.hash']
61
- end
67
+ schema, meta = node
68
+ merge_with('form.hash', :symbolized, schema).meta(meta)
62
69
  end
63
70
 
64
- def visit_json_hash(node)
65
- if node
66
- constructor, schema = node
67
- merge_with('json.hash', constructor, schema)
68
- else
69
- registry['json.hash']
70
- end
71
+ def visit_form_array(node)
72
+ member, meta = node
73
+ registry['form.array'].member(visit(member)).meta(meta)
71
74
  end
72
75
 
73
- def visit_key(node)
74
- name, types = node
75
- { name => visit(types) }
76
+ def visit_member(node)
77
+ name, type = node
78
+ { name => visit(type) }
76
79
  end
77
80
 
78
81
  def merge_with(hash_id, constructor, schema)
79
82
  registry[hash_id].__send__(
80
- constructor, schema.map { |key| visit(key) }.reduce({}, :merge)
83
+ constructor, schema.map { |key| visit(key) }.reduce({}, :update)
81
84
  )
82
85
  end
83
86
  end
@@ -73,6 +73,15 @@ module Dry
73
73
  valid?(value)
74
74
  end
75
75
 
76
+ # @api public
77
+ #
78
+ # @see Definition#to_ast
79
+ def to_ast(meta: true)
80
+ [:constrained, [type.to_ast(meta: meta),
81
+ rule.to_ast,
82
+ meta ? self.meta : EMPTY_HASH]]
83
+ end
84
+
76
85
  private
77
86
 
78
87
  # @param [Object] response
@@ -72,8 +72,21 @@ module Dry
72
72
  Constrained::Coercible
73
73
  end
74
74
 
75
+ # @api public
76
+ #
77
+ # @see Definition#to_ast
78
+ def to_ast(meta: true)
79
+ [:constructor, [type.to_ast(meta: meta),
80
+ register_fn(fn),
81
+ meta ? self.meta : EMPTY_HASH]]
82
+ end
83
+
75
84
  private
76
85
 
86
+ def register_fn(fn)
87
+ Dry::Types::FnContainer.register(fn)
88
+ end
89
+
77
90
  # @param [Symbol] meth
78
91
  # @param [Boolean] include_private
79
92
  # @return [Boolean]
@@ -106,6 +106,15 @@ module Dry
106
106
  end
107
107
  alias_method :valid?, :primitive?
108
108
  alias_method :===, :primitive?
109
+
110
+ # Return AST representation of a type definition
111
+ #
112
+ # @api public
113
+ #
114
+ # @return [Array]
115
+ def to_ast(meta: true)
116
+ [:definition, [primitive, meta ? self.meta : EMPTY_HASH]]
117
+ end
109
118
  end
110
119
  end
111
120
  end
@@ -41,6 +41,13 @@ module Dry
41
41
  raise '.enum(*values).default(value) is not supported. Call '\
42
42
  '.default(value).enum(*values) instead'
43
43
  end
44
+
45
+ # @api public
46
+ #
47
+ # @see Definition#to_ast
48
+ def to_ast(meta: true)
49
+ [:enum, [type.to_ast(meta: meta), meta ? self.meta : EMPTY_HASH]]
50
+ end
44
51
  end
45
52
  end
46
53
  end
@@ -9,8 +9,9 @@ module Dry
9
9
  class SchemaError < TypeError
10
10
  # @param [String,Symbol] key
11
11
  # @param [Object] value
12
- def initialize(key, value)
13
- super("#{value.inspect} (#{value.class}) has invalid type for :#{key}")
12
+ # @param [String, #to_s] result
13
+ def initialize(key, value, result)
14
+ super("#{value.inspect} (#{value.class}) has invalid type for :#{key} violates constraints (#{result} failed)")
14
15
  end
15
16
  end
16
17
 
@@ -0,0 +1,33 @@
1
+ require 'dry/types/container'
2
+
3
+ module Dry
4
+ module Types
5
+ class FnContainer
6
+ # @api private
7
+ def self.container
8
+ @container ||= Container.new
9
+ end
10
+
11
+ # @api private
12
+ def self.register(function)
13
+ register_function_name = register_name(function)
14
+ container.register(register_function_name, function) unless container.key?(register_function_name)
15
+ register_function_name
16
+ end
17
+
18
+ # @api private
19
+ def self.[](function_name)
20
+ if container.key?(function_name)
21
+ container[function_name]
22
+ else
23
+ function_name
24
+ end
25
+ end
26
+
27
+ # @api private
28
+ def self.register_name(function)
29
+ "fn_#{function.object_id}"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -58,8 +58,23 @@ module Dry
58
58
  end
59
59
  end
60
60
 
61
+ def to_ast(meta: true)
62
+ [
63
+ :hash,
64
+ [
65
+ hash_type,
66
+ member_types.map { |name, member| [:member, [name, member.to_ast(meta: meta)]] },
67
+ meta ? self.meta : EMPTY_HASH
68
+ ]
69
+ ]
70
+ end
71
+
61
72
  private
62
73
 
74
+ def hash_type
75
+ :schema
76
+ end
77
+
63
78
  # @param [Hash] hash
64
79
  # @return [Hash{Symbol => Object}]
65
80
  def try_coerce(hash)
@@ -74,8 +89,8 @@ module Dry
74
89
  resolve(hash) do |type, key, value|
75
90
  begin
76
91
  type.call(value)
77
- rescue ConstraintError
78
- raise SchemaError.new(key, value)
92
+ rescue ConstraintError => e
93
+ raise SchemaError.new(key, value, e.result)
79
94
  end
80
95
  end
81
96
  end
@@ -114,6 +129,10 @@ module Dry
114
129
  class Permissive < Schema
115
130
  private
116
131
 
132
+ def hash_type
133
+ :permissive
134
+ end
135
+
117
136
  # @param [Symbol] key
118
137
  # @raise [MissingKeyError] when key is missing in given input
119
138
  def resolve_missing_value(_, key, _)
@@ -132,6 +151,10 @@ module Dry
132
151
  class Strict < Permissive
133
152
  private
134
153
 
154
+ def hash_type
155
+ :strict
156
+ end
157
+
135
158
  # @param [Hash] hash
136
159
  # @return [Hash{Symbol => Object}]
137
160
  # @raise [UnknownKeysError]
@@ -160,6 +183,10 @@ module Dry
160
183
  class StrictWithDefaults < Strict
161
184
  private
162
185
 
186
+ def hash_type
187
+ :strict_with_defaults
188
+ end
189
+
163
190
  # @param [Hash] result
164
191
  # @param [Symbol] key
165
192
  # @param [Type] type
@@ -203,12 +230,22 @@ module Dry
203
230
  block ? yield(result) : result
204
231
  end
205
232
  end
233
+
234
+ private
235
+
236
+ def hash_type
237
+ :weak
238
+ end
206
239
  end
207
240
 
208
241
  # {Symbolized} hash will turn string key names into symbols.
209
242
  class Symbolized < Weak
210
243
  private
211
244
 
245
+ def hash_type
246
+ :symbolized
247
+ end
248
+
212
249
  def resolve(hash)
213
250
  result = {}
214
251
  member_types.each do |key, type|
@@ -24,7 +24,13 @@ module Dry
24
24
  # @param [Hash] new metadata to merge into existing metadata
25
25
  # @return [Type] new type with added metadata
26
26
  def meta(data = nil)
27
- data ? with(meta: @meta.merge(data)) : @meta
27
+ if !data
28
+ @meta
29
+ elsif data.empty?
30
+ self
31
+ else
32
+ with(meta: @meta.merge(data))
33
+ end
28
34
  end
29
35
 
30
36
  # Resets meta
@@ -33,6 +33,19 @@ module Dry
33
33
  block ? yield(result) : result
34
34
  end
35
35
 
36
+ # @api public
37
+ #
38
+ # @see Definition#to_ast
39
+ def to_ast(meta: true)
40
+ [:safe, [type.to_ast, meta ? self.meta : EMPTY_HASH]]
41
+ end
42
+
43
+ # @api public
44
+ # @return [Safe]
45
+ def safe
46
+ self
47
+ end
48
+
36
49
  private
37
50
 
38
51
  # @param [Object, Dry::Types::Constructor] response
@@ -102,6 +102,13 @@ module Dry
102
102
  def valid?(value)
103
103
  left.valid?(value) || right.valid?(value)
104
104
  end
105
+
106
+ # @api public
107
+ #
108
+ # @see Definition#to_ast
109
+ def to_ast(meta: true)
110
+ [:sum, [left.to_ast(meta: meta), right.to_ast(meta: meta), meta ? self.meta : EMPTY_HASH]]
111
+ end
105
112
  end
106
113
  end
107
114
  end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Types
3
- VERSION = '0.10.3'.freeze
3
+ VERSION = '0.11.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-types
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.3
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-06 00:00:00.000000000 Z
11
+ date: 2017-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -209,6 +209,7 @@ files:
209
209
  - ".travis.yml"
210
210
  - ".yardopts"
211
211
  - CHANGELOG.md
212
+ - CONTRIBUTING.md
212
213
  - Gemfile
213
214
  - LICENSE
214
215
  - README.md
@@ -238,6 +239,7 @@ files:
238
239
  - lib/dry/types/errors.rb
239
240
  - lib/dry/types/extensions.rb
240
241
  - lib/dry/types/extensions/maybe.rb
242
+ - lib/dry/types/fn_container.rb
241
243
  - lib/dry/types/form.rb
242
244
  - lib/dry/types/hash.rb
243
245
  - lib/dry/types/hash/schema.rb
@@ -262,7 +264,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
262
264
  requirements:
263
265
  - - ">="
264
266
  - !ruby/object:Gem::Version
265
- version: 2.1.0
267
+ version: 2.2.0
266
268
  required_rubygems_version: !ruby/object:Gem::Requirement
267
269
  requirements:
268
270
  - - ">="
@@ -270,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
272
  version: '0'
271
273
  requirements: []
272
274
  rubyforge_project:
273
- rubygems_version: 2.6.11
275
+ rubygems_version: 2.6.9
274
276
  signing_key:
275
277
  specification_version: 4
276
278
  summary: Type system for Ruby supporting coercions, constraints and complex types