dry-monads 1.3.5 → 1.4.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +140 -80
  3. data/LICENSE +1 -1
  4. data/README.md +5 -4
  5. data/dry-monads.gemspec +30 -30
  6. data/lib/dry-monads.rb +1 -1
  7. data/lib/dry/monads.rb +2 -2
  8. data/lib/dry/monads/all.rb +2 -2
  9. data/lib/dry/monads/constants.rb +1 -1
  10. data/lib/dry/monads/do.rb +52 -18
  11. data/lib/dry/monads/do/all.rb +36 -17
  12. data/lib/dry/monads/either.rb +7 -7
  13. data/lib/dry/monads/errors.rb +5 -2
  14. data/lib/dry/monads/lazy.rb +15 -4
  15. data/lib/dry/monads/list.rb +28 -28
  16. data/lib/dry/monads/maybe.rb +87 -19
  17. data/lib/dry/monads/registry.rb +10 -10
  18. data/lib/dry/monads/result.rb +38 -12
  19. data/lib/dry/monads/result/fixed.rb +33 -24
  20. data/lib/dry/monads/right_biased.rb +35 -16
  21. data/lib/dry/monads/task.rb +20 -20
  22. data/lib/dry/monads/transformer.rb +2 -1
  23. data/lib/dry/monads/traverse.rb +7 -1
  24. data/lib/dry/monads/try.rb +45 -12
  25. data/lib/dry/monads/unit.rb +6 -2
  26. data/lib/dry/monads/validated.rb +20 -16
  27. data/lib/dry/monads/version.rb +1 -1
  28. data/lib/json/add/dry/monads/maybe.rb +3 -3
  29. metadata +18 -69
  30. data/.codeclimate.yml +0 -12
  31. data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +0 -10
  32. data/.github/ISSUE_TEMPLATE/---bug-report.md +0 -30
  33. data/.github/ISSUE_TEMPLATE/---feature-request.md +0 -18
  34. data/.github/workflows/ci.yml +0 -52
  35. data/.github/workflows/docsite.yml +0 -34
  36. data/.github/workflows/sync_configs.yml +0 -56
  37. data/.gitignore +0 -10
  38. data/.rspec +0 -4
  39. data/.rubocop.yml +0 -101
  40. data/.yardopts +0 -4
  41. data/CODE_OF_CONDUCT.md +0 -13
  42. data/CONTRIBUTING.md +0 -29
  43. data/Gemfile +0 -19
  44. data/Gemfile.devtools +0 -14
  45. data/Rakefile +0 -8
  46. data/bin/.gitkeep +0 -0
  47. data/bin/console +0 -17
  48. data/bin/setup +0 -7
  49. data/docsite/source/case-equality.html.md +0 -42
  50. data/docsite/source/do-notation.html.md +0 -207
  51. data/docsite/source/getting-started.html.md +0 -142
  52. data/docsite/source/index.html.md +0 -179
  53. data/docsite/source/list.html.md +0 -87
  54. data/docsite/source/maybe.html.md +0 -146
  55. data/docsite/source/pattern-matching.html.md +0 -68
  56. data/docsite/source/result.html.md +0 -190
  57. data/docsite/source/task.html.md +0 -126
  58. data/docsite/source/tracing-failures.html.md +0 -32
  59. data/docsite/source/try.html.md +0 -76
  60. data/docsite/source/unit.html.md +0 -36
  61. data/docsite/source/validated.html.md +0 -88
  62. data/log/.gitkeep +0 -0
  63. data/project.yml +0 -2
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2020 dry-rb team
3
+ Copyright (c) 2015-2021 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,3 +1,4 @@
1
+ <!--- this file is synced from dry-rb/template-gem project -->
1
2
  [gem]: https://rubygems.org/gems/dry-monads
2
3
  [actions]: https://github.com/dry-rb/dry-monads/actions
3
4
  [codacy]: https://www.codacy.com/gh/dry-rb/dry-monads
@@ -7,22 +8,22 @@
7
8
  # dry-monads [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
8
9
 
9
10
  [![Gem Version](https://badge.fury.io/rb/dry-monads.svg)][gem]
10
- [![CI Status](https://github.com/dry-rb/dry-monads/workflows/ci/badge.svg)][actions]
11
+ [![CI Status](https://github.com/dry-rb/dry-monads/workflows/CI/badge.svg)][actions]
11
12
  [![Codacy Badge](https://api.codacy.com/project/badge/Grade/f2eed41bf7f04b38b0a7691c2cf6e73c)][codacy]
12
13
  [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/f2eed41bf7f04b38b0a7691c2cf6e73c)][codacy]
13
14
  [![Inline docs](http://inch-ci.org/github/dry-rb/dry-monads.svg?branch=master)][inchpages]
14
15
 
15
16
  ## Links
16
17
 
17
- * [User documentation](http://dry-rb.org/gems/dry-monads)
18
+ * [User documentation](https://dry-rb.org/gems/dry-monads)
18
19
  * [API documentation](http://rubydoc.info/gems/dry-monads)
19
20
 
20
21
  ## Supported Ruby versions
21
22
 
22
23
  This library officially supports the following Ruby versions:
23
24
 
24
- * MRI >= `2.4`
25
- * jruby >= `9.2`
25
+ * MRI `>= 2.6.0`
26
+ * ~~jruby~~ `>= 9.3` (we are waiting for [2.6 support](https://github.com/jruby/jruby/issues/6161))
26
27
 
27
28
  ## License
28
29
 
data/dry-monads.gemspec CHANGED
@@ -1,39 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('lib', __dir__)
3
+ # this file is synced from dry-rb/template-gem project
4
+
5
+ lib = File.expand_path("lib", __dir__)
4
6
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'dry/monads/version'
7
+ require "dry/monads/version"
6
8
 
7
9
  Gem::Specification.new do |spec|
8
- spec.name = 'dry-monads'
10
+ spec.name = "dry-monads"
11
+ spec.authors = ["Nikita Shilnikov"]
12
+ spec.email = ["fg@flashgordon.ru"]
13
+ spec.license = "MIT"
9
14
  spec.version = Dry::Monads::VERSION.dup
10
- spec.authors = ['Nikita Shilnikov']
11
- spec.email = ['fg@flashgordon.ru']
12
- spec.license = 'MIT'
13
15
 
14
- spec.summary = 'Common monads for Ruby.'
16
+ spec.summary = "Common monads for Ruby"
15
17
  spec.description = spec.summary
16
- spec.homepage = 'https://github.com/dry-rb/dry-monads'
17
-
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
- else
23
- raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
24
- end
25
-
26
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
- spec.bindir = 'exe'
28
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
- spec.require_paths = ['lib']
30
- spec.required_ruby_version = '>= 2.4.0'
31
- spec.add_dependency 'concurrent-ruby', '~> 1.0'
32
- spec.add_dependency 'dry-core', '~> 0.4', '>= 0.4.4'
33
- spec.add_dependency 'dry-equalizer'
34
-
35
- spec.add_development_dependency 'bundler'
36
- spec.add_development_dependency 'dry-types', '>= 0.12'
37
- spec.add_development_dependency 'rake'
38
- spec.add_development_dependency 'rspec'
18
+ spec.homepage = "https://dry-rb.org/gems/dry-monads"
19
+ spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-monads.gemspec", "lib/**/*"]
20
+ spec.bindir = "bin"
21
+ spec.executables = []
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
25
+ spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-monads/blob/master/CHANGELOG.md"
26
+ spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-monads"
27
+ spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-monads/issues"
28
+
29
+ spec.required_ruby_version = ">= 2.6.0"
30
+
31
+ # to update dependencies edit project.yml
32
+ spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
33
+ spec.add_runtime_dependency "dry-core", "~> 0.7"
34
+
35
+ spec.add_development_dependency "bundler"
36
+ spec.add_development_dependency "dry-types", ">= 0.1.2"
37
+ spec.add_development_dependency "rake"
38
+ spec.add_development_dependency "rspec"
39
39
  end
data/lib/dry-monads.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/monads'
3
+ require "dry/monads"
data/lib/dry/monads.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/core/constants'
4
- require 'dry/monads/registry'
3
+ require "dry/core/constants"
4
+ require "dry/monads/registry"
5
5
 
6
6
  module Dry
7
7
  # Common, idiomatic monads for Ruby
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/monads'
4
- require 'dry/monads/registry'
3
+ require "dry/monads"
4
+ require "dry/monads/registry"
5
5
 
6
6
  module Dry
7
7
  module Monads
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/core/constants'
3
+ require "dry/core/constants"
4
4
 
5
5
  module Dry
6
6
  module Monads
data/lib/dry/monads/do.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/monads/list'
4
- require 'dry/monads/do/mixin'
5
- require 'dry/monads/constants'
3
+ require "dry/monads/list"
4
+ require "dry/monads/do/mixin"
5
+ require "dry/monads/constants"
6
6
 
7
7
  module Dry
8
8
  module Monads
@@ -12,7 +12,13 @@ module Dry
12
12
  module Do
13
13
  extend Mixin
14
14
 
15
- DELEGATE = ::RUBY_VERSION < '2.7' ? '*' : '...'
15
+ DELEGATE = ::RUBY_VERSION < "2.7" ? "*" : "..."
16
+
17
+ VISIBILITY_WORD = {
18
+ public: "",
19
+ private: "private ",
20
+ protected: "protected "
21
+ }.freeze
16
22
 
17
23
  # @api private
18
24
  class Halt < StandardError
@@ -26,6 +32,25 @@ module Dry
26
32
  end
27
33
  end
28
34
 
35
+ # @api private
36
+ class MethodTracker < ::Module
37
+ # @api private
38
+ def initialize(tracked_methods, base, wrapper)
39
+ module_eval do
40
+ private
41
+
42
+ define_method(:method_added) do |method|
43
+ super(method)
44
+
45
+ if tracked_methods.include?(method)
46
+ visibility = Do.method_visibility(base, method)
47
+ Do.wrap_method(wrapper, method, visibility)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
29
54
  class << self
30
55
  # Generates a module that passes a block to methods
31
56
  # that either unwraps a single-valued monadic value or halts
@@ -84,13 +109,11 @@ module Dry
84
109
  # @param [Array<Symbol>] methods
85
110
  # @return [Module]
86
111
  def for(*methods)
87
- mod = ::Module.new do
88
- methods.each { |method_name| Do.wrap_method(self, method_name) }
89
- end
90
-
91
112
  ::Module.new do
92
113
  singleton_class.send(:define_method, :included) do |base|
114
+ mod = ::Module.new
93
115
  base.prepend(mod)
116
+ base.extend(MethodTracker.new(methods, base, mod))
94
117
  end
95
118
  end
96
119
  end
@@ -100,23 +123,34 @@ module Dry
100
123
  super
101
124
 
102
125
  # Actually mixes in Do::All
103
- require 'dry/monads/do/all'
126
+ require "dry/monads/do/all"
104
127
  base.include All
105
128
  end
106
129
 
107
130
  # @api private
108
- def wrap_method(target, method_name)
131
+ def wrap_method(target, method, visibility)
109
132
  target.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
110
- def #{method_name}(#{DELEGATE})
111
- if block_given?
112
- super
113
- else
114
- Do.() { super { |*ms| Do.bind(ms) } }
115
- end
116
- end
133
+ #{VISIBILITY_WORD[visibility]} def #{method}(#{DELEGATE}) # private def create_acccount(...)
134
+ if block_given? # if block_given?
135
+ super # super
136
+ else # else
137
+ Do.() { super { |*ms| Do.bind(ms) } } # Do.() { super { |*ms| Do.bind(ms) } }
138
+ end # end
139
+ end # end
117
140
  RUBY
118
141
  end
119
142
 
143
+ # @api private
144
+ def method_visibility(mod, method)
145
+ if mod.public_method_defined?(method)
146
+ :public
147
+ elsif mod.private_method_defined?(method)
148
+ :private
149
+ else
150
+ :protected
151
+ end
152
+ end
153
+
120
154
  # @api private
121
155
  def coerce_to_monad(monads)
122
156
  return monads if monads.size != 1
@@ -135,7 +169,7 @@ module Dry
135
169
 
136
170
  # @api private
137
171
  def halt(result)
138
- raise Halt.new(result), EMPTY_STRING, []
172
+ raise Halt.new(result), "", []
139
173
  end
140
174
  end
141
175
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/monads/do'
3
+ require "dry/monads/do"
4
4
 
5
5
  module Dry
6
6
  module Monads
@@ -68,9 +68,10 @@ module Dry
68
68
  tracker = self
69
69
 
70
70
  module_eval do
71
+ private
72
+
71
73
  define_method(:method_added) do |method|
72
74
  super(method)
73
-
74
75
  tracker.wrap_method(self, method)
75
76
  end
76
77
 
@@ -93,20 +94,37 @@ module Dry
93
94
  end
94
95
 
95
96
  def wrap_method(target, method)
96
- Do.wrap_method(wrappers[target], method)
97
+ visibility = Do.method_visibility(target, method)
98
+ Do.wrap_method(wrappers[target], method, visibility)
97
99
  end
98
100
  end
99
101
 
100
- # @api private
101
- def self.included(base)
102
- super
102
+ class << self
103
+ # @api private
104
+ def included(base)
105
+ super
103
106
 
104
- wrappers = ::Hash.new { |h, k| h[k] = ::Module.new }
105
- tracker = MethodTracker.new(wrappers)
106
- base.extend(tracker)
107
- base.instance_methods(false).each { |m| tracker.wrap_method(base, m) }
107
+ wrappers = ::Hash.new { |h, k| h[k] = ::Module.new }
108
+ tracker = MethodTracker.new(wrappers)
109
+ base.extend(tracker)
110
+ base.extend(InstanceMixin) unless base.is_a?(::Class)
111
+ wrap_defined_methods(base, wrappers[base])
112
+ end
108
113
 
109
- base.extend(InstanceMixin) unless base.is_a?(::Class)
114
+ # @api private
115
+ def wrap_defined_methods(klass, target)
116
+ klass.public_instance_methods(false).each do |m|
117
+ Do.wrap_method(target, m, :public)
118
+ end
119
+
120
+ klass.protected_instance_methods(false).each do |m|
121
+ Do.wrap_method(target, m, :protected)
122
+ end
123
+
124
+ klass.private_instance_methods(false).each do |m|
125
+ Do.wrap_method(target, m, :private)
126
+ end
127
+ end
110
128
  end
111
129
 
112
130
  # @api private
@@ -116,17 +134,18 @@ module Dry
116
134
  super
117
135
 
118
136
  wrapper = ::Module.new
119
- object.singleton_class.prepend(wrapper)
137
+ eigenclass = object.singleton_class
138
+ eigenclass.prepend(wrapper)
120
139
  object.define_singleton_method(:singleton_method_added) do |method|
121
140
  super(method)
122
141
 
123
142
  next if method.equal?(:singleton_method_added)
124
143
 
125
- Do.wrap_method(wrapper, method)
126
- end
127
- object.singleton_class.instance_methods(false).each do |m|
128
- Do.wrap_method(wrapper, m)
144
+ visibility = Do.method_visibility(eigenclass, method)
145
+ Do.wrap_method(wrapper, method, visibility)
129
146
  end
147
+
148
+ All.wrap_defined_methods(eigenclass, wrapper)
130
149
  end
131
150
  end
132
151
 
@@ -134,7 +153,7 @@ module Dry
134
153
  end
135
154
  end
136
155
 
137
- require 'dry/monads/registry'
156
+ require "dry/monads/registry"
138
157
  register_mixin(:do, Do::All)
139
158
  end
140
159
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/core/deprecations'
3
+ require "dry/core/deprecations"
4
4
 
5
- Dry::Core::Deprecations.warn('Either monad was renamed to Result', tag: :'dry-monads')
5
+ Dry::Core::Deprecations.warn("Either monad was renamed to Result", tag: :"dry-monads")
6
6
 
7
- require 'dry/monads/result'
7
+ require "dry/monads/result"
8
8
 
9
9
  module Dry
10
10
  module Monads
@@ -12,7 +12,7 @@ module Dry
12
12
  deprecate_constant :Either
13
13
 
14
14
  class Result
15
- extend Dry::Core::Deprecations[:'dry-monads']
15
+ extend ::Dry::Core::Deprecations[:"dry-monads"]
16
16
 
17
17
  deprecate :to_either, :to_result
18
18
 
@@ -24,7 +24,7 @@ module Dry
24
24
 
25
25
  module Mixin
26
26
  module Constructors
27
- extend Dry::Core::Deprecations[:'dry-monads']
27
+ extend Dry::Core::Deprecations[:"dry-monads"]
28
28
 
29
29
  Right = Success
30
30
  Left = Failure
@@ -51,13 +51,13 @@ module Dry
51
51
 
52
52
  class Try
53
53
  class Value
54
- extend Dry::Core::Deprecations[:'dry-monads']
54
+ extend Dry::Core::Deprecations[:"dry-monads"]
55
55
 
56
56
  deprecate :to_either, :to_result
57
57
  end
58
58
 
59
59
  class Error
60
- extend Dry::Core::Deprecations[:'dry-monads']
60
+ extend Dry::Core::Deprecations[:"dry-monads"]
61
61
 
62
62
  deprecate :to_either, :to_result
63
63
  end
@@ -4,8 +4,11 @@ module Dry
4
4
  module Monads
5
5
  # An unsuccessful result of extracting a value from a monad.
6
6
  class UnwrapError < StandardError
7
- def initialize(ctx)
8
- super("value! was called on #{ctx.inspect}")
7
+ attr_reader :receiver
8
+
9
+ def initialize(receiver)
10
+ @receiver = receiver
11
+ super("value! was called on #{receiver.inspect}")
9
12
  end
10
13
  end
11
14
 
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'concurrent/promise'
3
+ require "concurrent/promise"
4
4
 
5
- require 'dry/monads/task'
5
+ require "dry/core/deprecations"
6
+ require "dry/monads/task"
6
7
 
7
8
  module Dry
8
9
  module Monads
@@ -11,6 +12,8 @@ module Dry
11
12
  # computation is evaluated not more than once (compare with the built-in
12
13
  # lazy assignement ||= which does not guarantee this).
13
14
  class Lazy < Task
15
+ extend ::Dry::Core::Deprecations[:"dry-monads"]
16
+
14
17
  class << self
15
18
  # @private
16
19
  def new(promise = nil, &block)
@@ -41,6 +44,14 @@ module Dry
41
44
  self
42
45
  end
43
46
 
47
+ # @return [Boolean]
48
+ def evaluated?
49
+ @promise.complete?
50
+ end
51
+ deprecate :complete?, :evaluated?
52
+
53
+ undef_method :wait
54
+
44
55
  # @return [String]
45
56
  def to_s
46
57
  state = case promise.state
@@ -49,7 +60,7 @@ module Dry
49
60
  when :rejected
50
61
  "!#{promise.reason.inspect}"
51
62
  else
52
- '?'
63
+ "?"
53
64
  end
54
65
 
55
66
  "Lazy(#{state})"
@@ -80,7 +91,7 @@ module Dry
80
91
  end
81
92
  end
82
93
 
83
- require 'dry/monads/registry'
94
+ require "dry/monads/registry"
84
95
  register_mixin(:lazy, Lazy::Mixin)
85
96
  end
86
97
  end