dry-types 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +306 -225
  3. data/LICENSE +1 -1
  4. data/README.md +14 -12
  5. data/dry-types.gemspec +27 -31
  6. data/lib/dry/types.rb +0 -9
  7. data/lib/dry/types/builder.rb +4 -0
  8. data/lib/dry/types/constructor/function.rb +17 -31
  9. data/lib/dry/types/core.rb +3 -1
  10. data/lib/dry/types/decorator.rb +0 -7
  11. data/lib/dry/types/extensions/maybe.rb +14 -14
  12. data/lib/dry/types/lax.rb +1 -4
  13. data/lib/dry/types/meta.rb +2 -2
  14. data/lib/dry/types/params.rb +1 -0
  15. data/lib/dry/types/result.rb +2 -2
  16. data/lib/dry/types/schema.rb +23 -2
  17. data/lib/dry/types/schema/key.rb +11 -2
  18. data/lib/dry/types/spec/types.rb +11 -0
  19. data/lib/dry/types/sum.rb +2 -2
  20. data/lib/dry/types/version.rb +1 -1
  21. metadata +21 -59
  22. data/.codeclimate.yml +0 -12
  23. data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +0 -10
  24. data/.github/ISSUE_TEMPLATE/---bug-report.md +0 -30
  25. data/.github/ISSUE_TEMPLATE/---feature-request.md +0 -18
  26. data/.github/workflows/custom_ci.yml +0 -76
  27. data/.github/workflows/docsite.yml +0 -34
  28. data/.github/workflows/sync_configs.yml +0 -34
  29. data/.gitignore +0 -11
  30. data/.rspec +0 -4
  31. data/.rubocop.yml +0 -92
  32. data/.yardopts +0 -9
  33. data/CODE_OF_CONDUCT.md +0 -13
  34. data/CONTRIBUTING.md +0 -29
  35. data/Gemfile +0 -34
  36. data/Rakefile +0 -22
  37. data/benchmarks/hash_schemas.rb +0 -55
  38. data/benchmarks/lax_schema.rb +0 -15
  39. data/benchmarks/profile_invalid_input.rb +0 -15
  40. data/benchmarks/profile_lax_schema_valid.rb +0 -16
  41. data/benchmarks/profile_valid_input.rb +0 -15
  42. data/benchmarks/schema_valid_vs_invalid.rb +0 -21
  43. data/benchmarks/setup.rb +0 -17
  44. data/docsite/source/array-with-member.html.md +0 -13
  45. data/docsite/source/built-in-types.html.md +0 -116
  46. data/docsite/source/constraints.html.md +0 -31
  47. data/docsite/source/custom-types.html.md +0 -93
  48. data/docsite/source/default-values.html.md +0 -91
  49. data/docsite/source/enum.html.md +0 -69
  50. data/docsite/source/extensions.html.md +0 -15
  51. data/docsite/source/extensions/maybe.html.md +0 -57
  52. data/docsite/source/extensions/monads.html.md +0 -61
  53. data/docsite/source/getting-started.html.md +0 -57
  54. data/docsite/source/hash-schemas.html.md +0 -169
  55. data/docsite/source/index.html.md +0 -156
  56. data/docsite/source/map.html.md +0 -17
  57. data/docsite/source/optional-values.html.md +0 -35
  58. data/docsite/source/sum.html.md +0 -21
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2019 dry-rb team
3
+ Copyright (c) 2015-2020 dry-rb team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,27 +1,29 @@
1
1
  [gem]: https://rubygems.org/gems/dry-types
2
- [ci]: https://github.com/dry-rb/dry-types/actions?query=workflow%3Aci
3
- [codeclimate]: https://codeclimate.com/github/dry-rb/dry-types
4
- [inchpages]: http://inch-ci.org/github/dry-rb/dry-types
2
+ [actions]: https://github.com/dry-rb/dry-types/actions
3
+ [codacy]: https://www.codacy.com/gh/dry-rb/dry-types
5
4
  [chat]: https://dry-rb.zulipchat.com
5
+ [inchpages]: http://inch-ci.org/github/dry-rb/dry-types
6
6
 
7
7
  # dry-types [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
8
8
 
9
9
  [![Gem Version](https://badge.fury.io/rb/dry-types.svg)][gem]
10
- [![Build Status](https://github.com/dry-rb/dry-types/workflows/ci/badge.svg)][ci]
11
- [![Code Climate](https://codeclimate.com/github/dry-rb/dry-types/badges/gpa.svg)][codeclimate]
12
- [![Test Coverage](https://codeclimate.com/github/dry-rb/dry-types/badges/coverage.svg)][codeclimate]
10
+ [![CI Status](https://github.com/dry-rb/dry-types/workflows/ci/badge.svg)][actions]
11
+ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/f2d71613195f4da993acb9ac9d6ea336)][codacy]
12
+ [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/f2d71613195f4da993acb9ac9d6ea336)][codacy]
13
13
  [![Inline docs](http://inch-ci.org/github/dry-rb/dry-types.svg?branch=master)][inchpages]
14
14
 
15
15
  ## Links
16
16
 
17
- - [Documentation](http://dry-rb.org/gems/dry-types)
17
+ * [User documentation](http://dry-rb.org/gems/dry-types)
18
+ * [API documentation](http://rubydoc.info/gems/dry-types)
18
19
 
19
- ## Development
20
+ ## Supported Ruby versions
20
21
 
21
- 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.
22
+ This library officially supports the following Ruby versions:
22
23
 
23
- 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).
24
+ * MRI >= `2.4`
25
+ * jruby >= `9.2`
24
26
 
25
- ## Contributing
27
+ ## License
26
28
 
27
- Bug reports and pull requests are welcome on GitHub at https://github.com/dry-rb/dry-types.
29
+ See `LICENSE` file.
data/dry-types.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # this file is managed by dry-rb/devtools project
2
3
 
3
4
  lib = File.expand_path('lib', __dir__)
4
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -6,42 +7,37 @@ require 'dry/types/version'
6
7
 
7
8
  Gem::Specification.new do |spec|
8
9
  spec.name = 'dry-types'
9
- spec.version = Dry::Types::VERSION.dup
10
- spec.authors = ['Piotr Solnica']
11
- spec.email = ['piotr.solnica@gmail.com']
10
+ spec.authors = ["Piotr Solnica"]
11
+ spec.email = ["piotr.solnica@gmail.com"]
12
12
  spec.license = 'MIT'
13
+ spec.version = Dry::Types::VERSION.dup
13
14
 
14
- spec.summary = 'Type system for Ruby supporting coercions, constraints and complex types like structs, value objects, enums etc.'
15
+ spec.summary = "Type system for Ruby supporting coercions, constraints and complex types like structs, value objects, enums etc"
15
16
  spec.description = spec.summary
16
- spec.homepage = 'https://github.com/dry-rb/dry-types'
17
+ spec.homepage = 'https://dry-rb.org/gems/dry-types'
18
+ spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-types.gemspec", "lib/**/*"]
19
+ spec.bindir = 'bin'
20
+ spec.executables = []
21
+ spec.require_paths = ['lib']
17
22
 
18
- # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
19
- # delete this section to allow pushing this gem to any host.
20
- if spec.respond_to?(:metadata)
21
- spec.metadata['allowed_push_host'] = 'https://rubygems.org'
22
- spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md'
23
- spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-types'
24
- spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-types/issues'
25
- else
26
- raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
27
- end
23
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
24
+ spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md'
25
+ spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-types'
26
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-types/issues'
28
27
 
29
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - ['bin/console', 'bin/setup']
30
- spec.bindir = 'exe'
31
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
- spec.require_paths = ['lib']
33
- spec.required_ruby_version = '>= 2.4.0'
28
+ spec.required_ruby_version = ">= 2.4.0"
34
29
 
35
- spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
36
- spec.add_runtime_dependency 'dry-container', '~> 0.3'
37
- spec.add_runtime_dependency 'dry-core', '~> 0.4', '>= 0.4.4'
38
- spec.add_runtime_dependency 'dry-equalizer', '~> 0.3'
39
- spec.add_runtime_dependency 'dry-inflector', '~> 0.1', '>= 0.1.2'
40
- spec.add_runtime_dependency 'dry-logic', '~> 1.0', '>= 1.0.2'
30
+ # to update dependencies edit project.yml
31
+ spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
32
+ spec.add_runtime_dependency "dry-container", "~> 0.3"
33
+ spec.add_runtime_dependency "dry-core", "~> 0.4", ">= 0.4.4"
34
+ spec.add_runtime_dependency "dry-equalizer", "~> 0.3"
35
+ spec.add_runtime_dependency "dry-inflector", "~> 0.1", ">= 0.1.2"
36
+ spec.add_runtime_dependency "dry-logic", "~> 1.0", ">= 1.0.2"
41
37
 
42
- spec.add_development_dependency 'bundler'
43
- spec.add_development_dependency 'dry-monads', '~> 0.2'
44
- spec.add_development_dependency 'rake', '~> 11.0'
45
- spec.add_development_dependency 'rspec', '~> 3.3'
46
- spec.add_development_dependency 'yard', '~> 0.9.5'
38
+ spec.add_development_dependency "bundler"
39
+ spec.add_development_dependency "dry-monads", "~> 1.0"
40
+ spec.add_development_dependency "rake"
41
+ spec.add_development_dependency "rspec"
42
+ spec.add_development_dependency "yard"
47
43
  end
data/lib/dry/types.rb CHANGED
@@ -133,15 +133,6 @@ module Dry
133
133
  @type_map ||= Concurrent::Map.new
134
134
  end
135
135
 
136
- # List of type keys defined in {Dry::Types.container}
137
- #
138
- # @return [String]
139
- #
140
- # @api private
141
- def self.type_keys
142
- container.keys
143
- end
144
-
145
136
  # @api private
146
137
  def self.const_missing(const)
147
138
  underscored = Inflector.underscore(const)
@@ -129,6 +129,10 @@ module Dry
129
129
  def constructor(constructor = nil, **options, &block)
130
130
  constructor_type.new(with(**options), fn: constructor || block)
131
131
  end
132
+ alias_method :append, :constructor
133
+ alias_method :prepend, :constructor
134
+ alias_method :>>, :constructor
135
+ alias_method :<<, :constructor
132
136
  end
133
137
  end
134
138
  end
@@ -15,7 +15,7 @@ module Dry
15
15
  class Safe < Function
16
16
  def call(input, &block)
17
17
  @fn.(input, &block)
18
- rescue NoMethodError, TypeError, ArgumentError => e
18
+ rescue ::NoMethodError, ::TypeError, ::ArgumentError => e
19
19
  CoercionError.handle(e, &block)
20
20
  end
21
21
  end
@@ -30,7 +30,7 @@ module Dry
30
30
  #
31
31
  # @return [Function]
32
32
  def self.call_class(method, public, safe)
33
- @cache.fetch_or_store([method, public, safe].hash) do
33
+ @cache.fetch_or_store([method, public, safe]) do
34
34
  if public
35
35
  ::Class.new(PublicCall) do
36
36
  include PublicCall.call_interface(method, safe)
@@ -53,7 +53,7 @@ module Dry
53
53
  #
54
54
  # @return [::Module]
55
55
  def self.call_interface(method, safe)
56
- @interfaces.fetch_or_store([method, safe].hash) do
56
+ @interfaces.fetch_or_store([method, safe]) do
57
57
  ::Module.new do
58
58
  if safe
59
59
  module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
@@ -65,7 +65,7 @@ module Dry
65
65
  module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
66
66
  def call(input, &block)
67
67
  @target.#{method}(input)
68
- rescue NoMethodError, TypeError, ArgumentError => error
68
+ rescue ::NoMethodError, ::TypeError, ::ArgumentError => error
69
69
  CoercionError.handle(error, &block)
70
70
  end
71
71
  RUBY
@@ -90,7 +90,7 @@ module Dry
90
90
  class PrivateSafeCall < PrivateCall
91
91
  def call(input, &block)
92
92
  @target.send(@name, input)
93
- rescue NoMethodError, TypeError, ArgumentError => e
93
+ rescue ::NoMethodError, ::TypeError, ::ArgumentError => e
94
94
  CoercionError.handle(e, &block)
95
95
  end
96
96
  end
@@ -121,7 +121,7 @@ module Dry
121
121
  # @param [#call] fn
122
122
  # @return [Function]
123
123
  def self.[](fn)
124
- raise ArgumentError, 'Missing constructor block' if fn.nil?
124
+ raise ::ArgumentError, 'Missing constructor block' if fn.nil?
125
125
 
126
126
  if fn.is_a?(Function)
127
127
  fn
@@ -146,7 +146,7 @@ module Dry
146
146
  last_arg.equal?(:block)
147
147
  end
148
148
 
149
- include Dry::Equalizer(:fn, immutable: true)
149
+ include ::Dry::Equalizer(:fn, immutable: true)
150
150
 
151
151
  attr_reader :fn
152
152
 
@@ -163,36 +163,22 @@ module Dry
163
163
  # @return [Array]
164
164
  def to_ast
165
165
  if fn.is_a?(::Proc)
166
- [:id, Dry::Types::FnContainer.register(fn)]
166
+ [:id, FnContainer.register(fn)]
167
167
  else
168
168
  [:callable, fn]
169
169
  end
170
170
  end
171
171
 
172
- if RUBY_VERSION >= '2.6'
173
- # @return [Function]
174
- def >>(other)
175
- proc = other.is_a?(::Proc) ? other : other.fn
176
- Function[@fn >> proc]
177
- end
178
-
179
- # @return [Function]
180
- def <<(other)
181
- proc = other.is_a?(::Proc) ? other : other.fn
182
- Function[@fn << proc]
183
- end
184
- else
185
- # @return [Function]
186
- def >>(other)
187
- proc = other.is_a?(::Proc) ? other : other.fn
188
- Function[-> x { proc[@fn[x]] }]
189
- end
172
+ # @return [Function]
173
+ def >>(other)
174
+ f = Function[other]
175
+ Function[-> x, &b { f.(self.(x, &b), &b) }]
176
+ end
190
177
 
191
- # @return [Function]
192
- def <<(other)
193
- proc = other.is_a?(::Proc) ? other : other.fn
194
- Function[-> x { @fn[proc[x]] }]
195
- end
178
+ # @return [Function]
179
+ def <<(other)
180
+ f = Function[other]
181
+ Function[-> x, &b { self.(f.(x, &b), &b) }]
196
182
  end
197
183
  end
198
184
  end
@@ -72,7 +72,9 @@ module Dry
72
72
 
73
73
  # Register optional strict {NON_NIL} types
74
74
  NON_NIL.each_key do |name|
75
- register("optional.strict.#{name}", self["strict.#{name}"].optional)
75
+ type = self[name.to_s].optional
76
+ register("optional.strict.#{name}", type)
77
+ register("optional.#{name}", type)
76
78
  end
77
79
 
78
80
  # Register optional {COERCIBLE} types
@@ -44,13 +44,6 @@ module Dry
44
44
  type.constrained?
45
45
  end
46
46
 
47
- # @return [Sum]
48
- #
49
- # @api public
50
- def optional
51
- Types['strict.nil'] | self
52
- end
53
-
54
47
  # @param [Symbol] meth
55
48
  # @param [Boolean] include_private
56
49
  #
@@ -10,11 +10,11 @@ module Dry
10
10
  # @api public
11
11
  class Maybe
12
12
  include Type
13
- include Dry::Equalizer(:type, :options, inspect: false, immutable: true)
13
+ include ::Dry::Equalizer(:type, :options, inspect: false, immutable: true)
14
14
  include Decorator
15
15
  include Builder
16
16
  include Printable
17
- include Dry::Monads::Maybe::Mixin
17
+ include ::Dry::Monads::Maybe::Mixin
18
18
 
19
19
  # @param [Dry::Monads::Maybe, Object] input
20
20
  #
@@ -23,7 +23,7 @@ module Dry
23
23
  # @api private
24
24
  def call_unsafe(input = Undefined)
25
25
  case input
26
- when Dry::Monads::Maybe
26
+ when ::Dry::Monads::Maybe
27
27
  input
28
28
  when Undefined
29
29
  None()
@@ -37,14 +37,14 @@ module Dry
37
37
  # @return [Dry::Monads::Maybe]
38
38
  #
39
39
  # @api private
40
- def call_safe(input = Undefined, &block)
40
+ def call_safe(input = Undefined)
41
41
  case input
42
- when Dry::Monads::Maybe
42
+ when ::Dry::Monads::Maybe
43
43
  input
44
44
  when Undefined
45
45
  None()
46
46
  else
47
- Maybe(type.call_safe(input, &block))
47
+ Maybe(type.call_safe(input) { |output = input| return yield(output) })
48
48
  end
49
49
  end
50
50
 
@@ -54,13 +54,13 @@ module Dry
54
54
  #
55
55
  # @api public
56
56
  def try(input = Undefined)
57
- res = if input.equal?(Undefined)
58
- None()
59
- else
60
- Maybe(type[input])
61
- end
57
+ result = type.try(input)
62
58
 
63
- Result::Success.new(res)
59
+ if result.success?
60
+ Result::Success.new(Maybe(result.input))
61
+ else
62
+ result
63
+ end
64
64
  end
65
65
 
66
66
  # @return [true]
@@ -93,7 +93,7 @@ module Dry
93
93
  #
94
94
  # @api public
95
95
  def maybe
96
- Maybe.new(Types['strict.nil'] | self)
96
+ Maybe.new(Types['nil'] | self)
97
97
  end
98
98
  end
99
99
 
@@ -119,7 +119,7 @@ module Dry
119
119
 
120
120
  # Register non-coercible maybe types
121
121
  NON_NIL.each_key do |name|
122
- register("maybe.strict.#{name}", self["strict.#{name}"].maybe)
122
+ register("maybe.strict.#{name}", self[name.to_s].maybe)
123
123
  end
124
124
 
125
125
  # Register coercible maybe types
data/lib/dry/types/lax.rb CHANGED
@@ -15,7 +15,7 @@ module Dry
15
15
  include Printable
16
16
  include Dry::Equalizer(:type, inspect: false, immutable: true)
17
17
 
18
- undef :options, :constructor
18
+ undef :options, :constructor, :<<, :>>, :prepend, :append
19
19
 
20
20
  # @param [Object] input
21
21
  #
@@ -40,9 +40,6 @@ module Dry
40
40
  # @api public
41
41
  def try(input, &block)
42
42
  type.try(input, &block)
43
- rescue CoercionError => e
44
- result = failure(input, e.message)
45
- block ? yield(result) : result
46
43
  end
47
44
 
48
45
  # @see Nominal#to_ast
@@ -28,8 +28,8 @@ module Dry
28
28
  # @return [Type] new type with added metadata
29
29
  #
30
30
  # @api public
31
- def meta(data = nil)
32
- if !data
31
+ def meta(data = Undefined)
32
+ if Undefined.equal?(data)
33
33
  @meta
34
34
  elsif data.empty?
35
35
  self
@@ -58,6 +58,7 @@ module Dry
58
58
 
59
59
  COERCIBLE.each_key do |name|
60
60
  next if name.equal?(:string)
61
+
61
62
  register("optional.params.#{name}", self['params.nil'] | self["params.#{name}"])
62
63
  end
63
64
  end
@@ -8,7 +8,7 @@ module Dry
8
8
  #
9
9
  # @api public
10
10
  class Result
11
- include Dry::Equalizer(:input, inspect: false, immutable: true)
11
+ include ::Dry::Equalizer(:input, immutable: true)
12
12
 
13
13
  # @return [Object]
14
14
  attr_reader :input
@@ -43,7 +43,7 @@ module Dry
43
43
  #
44
44
  # @api public
45
45
  class Failure < Result
46
- include Dry::Equalizer(:input, :error, inspect: false, immutable: true)
46
+ include ::Dry::Equalizer(:input, :error, immutable: true)
47
47
 
48
48
  # @return [#to_s]
49
49
  attr_reader :error
@@ -145,7 +145,7 @@ module Dry
145
145
  #
146
146
  # @api public
147
147
  def to_ast(meta: true)
148
- if RUBY_VERSION >= "2.5"
148
+ if RUBY_VERSION >= '2.5'
149
149
  opts = options.slice(:key_transform_fn, :type_transform_fn, :strict)
150
150
  else
151
151
  opts = options.select { |k, _|
@@ -179,7 +179,7 @@ module Dry
179
179
  with(strict: strict)
180
180
  end
181
181
 
182
- # Injects a key transformation function
182
+ # Inject a key transformation function
183
183
  #
184
184
  # @param [#call,nil] proc
185
185
  # @param [#call,nil] block
@@ -284,6 +284,27 @@ module Dry
284
284
  Lax.new(schema(keys.map(&:lax)))
285
285
  end
286
286
 
287
+ # Merge given schema keys into current schema
288
+ #
289
+ # A new instance is returned.
290
+ #
291
+ # @param schema [Schema]
292
+ # @return [Schema]
293
+ #
294
+ # @api public
295
+ def merge(other)
296
+ schema(other.keys)
297
+ end
298
+
299
+ # Empty schema with the same options
300
+ #
301
+ # @return [Schema]
302
+ #
303
+ # @api public
304
+ def clear
305
+ with(keys: EMPTY_ARRAY)
306
+ end
307
+
287
308
  private
288
309
 
289
310
  # @param [Array<Dry::Types::Schema::Keys>] keys