dry-system 0.21.0 → 0.22.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
  SHA256:
3
- metadata.gz: 1c0977524fa33277150e8611a851c557461c14357e1a5d9c1f1929c283f3c9b3
4
- data.tar.gz: 12de5eaa25ede9f5f959cd77e2af8f1d3b4b287aaebea1554c2915433743c290
3
+ metadata.gz: 2ce0d3b9c3094e2e7d1b20907a31107d6329221e6213839708f8cc7bac1321bd
4
+ data.tar.gz: 2e28bfe4758cace04f1978c2b17fa138921915d5db0b894796772fa428e12549
5
5
  SHA512:
6
- metadata.gz: 6976cb749c98ed536c5fb3e6ca67674aee2707b40cd5d196b6b82472edadfa10877bebac77631b0ebcc5fabe008514ed60e7d9be17ccd1343e8967836f319a11
7
- data.tar.gz: fd894f982bf214dac3ccfa0de1d4fd7f95beeea1f91234cd2868dfab4687b76ea831c153b429d8ba9bd9f04bcb46dd2815f87a7829e6b347b2d8992cf0ebd478
6
+ metadata.gz: 33e7e5e5cccf47481498a95c8dc37fdb282ab9005c595f4db30b05f84c842d5144ba7cfa0f3a15f895212dbb0034554f36d16649d004bf54eebc99dca70d53d1
7
+ data.tar.gz: dc441f94a5d1506e7c7bc4afd9e8ebfd43d43e7956af09e2a793df6d1b02b409ac8eb0252183cae6c388969f2e33b02522675794c1aa4c340f6c52efa0ad7344
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  <!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
2
2
 
3
+ ## 0.22.0 2022-01-06
4
+
5
+
6
+ ### Added
7
+
8
+ - Expanded public interfaces for `Dry::System::Config::ComponentDirs` and `Dry::System::Config::Namespaces` to better support programmatic construction and inspection of these configs (@timriley in #195)
9
+
10
+ ### Changed
11
+
12
+ - Deprecated `Dry::System::Config::Namespaces#root` as the way to add and configure a root namespace. Use `#add_root` instead (@timriley in #195)
13
+ - Allow bootsnap plugin to use bootsnap on Ruby versions up to 3.0 (pusewicz in #196)
14
+
15
+ [Compare v0.21.0...v0.22.0](https://github.com/dry-rb/dry-system/compare/v0.21.0...v0.22.0)
16
+
3
17
  ## 0.21.0 2021-11-01
4
18
 
5
19
 
@@ -29,6 +43,7 @@
29
43
  (@timriley in #181)
30
44
  - `Dry::System::Component#path` has been removed and replaced by `Component#require_path` and `Component#const_path` (@timriley in #181)
31
45
  - Unused `Dry::System::FileNotFoundError` and `Dry::System::InvalidComponentIdentifierTypeError` errors have been removed (@timriley in #194)
46
+ - Allow bootsnap for Rubies up to 3.0.x (via #196) (@pusewicz)
32
47
 
33
48
  [Compare v0.20.0...v0.21.0](https://github.com/dry-rb/dry-system/compare/v0.20.0...v0.21.0)
34
49
 
data/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  # dry-system [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
9
9
 
10
10
  [![Gem Version](https://badge.fury.io/rb/dry-system.svg)][gem]
11
- [![CI Status](https://github.com/dry-rb/dry-system/workflows/CI/badge.svg)][actions]
11
+ [![CI Status](https://github.com/dry-rb/dry-system/workflows/ci/badge.svg)][actions]
12
12
  [![Codacy Badge](https://api.codacy.com/project/badge/Grade/3a0e30d0ae2542c7ba047ba5f923c0bb)][codacy]
13
13
  [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/3a0e30d0ae2542c7ba047ba5f923c0bb)][codacy]
14
14
  [![Inline docs](http://inch-ci.org/github/dry-rb/dry-system.svg?branch=master)][inchpages]
@@ -9,6 +9,7 @@ require_relative "namespaces"
9
9
  module Dry
10
10
  module System
11
11
  module Config
12
+ # @api public
12
13
  class ComponentDir
13
14
  include Dry::Configurable
14
15
 
@@ -37,6 +38,7 @@ module Dry
37
38
  #
38
39
  # @see auto_register
39
40
  # @see Component
41
+ # @api public
40
42
  #
41
43
  # @!method auto_register
42
44
  #
@@ -45,6 +47,7 @@ module Dry
45
47
  # @return [Boolean, Proc] the configured policy
46
48
  #
47
49
  # @see auto_register=
50
+ # @api public
48
51
  setting :auto_register, default: true
49
52
 
50
53
  # @!method add_to_load_path=(policy)
@@ -60,6 +63,7 @@ module Dry
60
63
  #
61
64
  # @see add_to_load_path
62
65
  # @see Container.configure
66
+ # @api public
63
67
  #
64
68
  # @!method add_to_load_path
65
69
  #
@@ -68,6 +72,7 @@ module Dry
68
72
  # @return [Boolean]
69
73
  #
70
74
  # @see add_to_load_path=
75
+ # @api public
71
76
  setting :add_to_load_path, default: true
72
77
 
73
78
  # @!method loader=(loader)
@@ -85,6 +90,7 @@ module Dry
85
90
  # @see loader
86
91
  # @see Loader
87
92
  # @see Loader::Autoloading
93
+ # @api public
88
94
  #
89
95
  # @!method loader
90
96
  #
@@ -93,6 +99,7 @@ module Dry
93
99
  # @return [#call]
94
100
  #
95
101
  # @see loader=
102
+ # @api public
96
103
  setting :loader, default: Dry::System::Loader
97
104
 
98
105
  # @!method memoize=(policy)
@@ -119,6 +126,7 @@ module Dry
119
126
  #
120
127
  # @see memoize
121
128
  # @see Component
129
+ # @api public
122
130
  #
123
131
  # @!method memoize
124
132
  #
@@ -127,6 +135,7 @@ module Dry
127
135
  # @return [Boolean, Proc] the configured memoization policy
128
136
  #
129
137
  # @see memoize=
138
+ # @api public
130
139
  setting :memoize, default: false
131
140
 
132
141
  # @!method namespaces
@@ -135,11 +144,13 @@ module Dry
135
144
  #
136
145
  # Allows namespaces to added on the returned object via {Namespaces#add}.
137
146
  #
138
- # @see Namespaces#add
139
- #
140
147
  # @return [Namespaces] the namespaces
148
+ #
149
+ # @see Namespaces#add
150
+ # @api public
141
151
  setting :namespaces, default: Namespaces.new, cloneable: true
142
152
 
153
+ # @api public
143
154
  def default_namespace=(namespace)
144
155
  Dry::Core::Deprecations.announce(
145
156
  "Dry::System::Config::ComponentDir#default_namespace=",
@@ -157,6 +168,7 @@ module Dry
157
168
  namespaces.add namespace_path, key: nil
158
169
  end
159
170
 
171
+ # @api public
160
172
  def default_namespace
161
173
  Dry::Core::Deprecations.announce(
162
174
  "Dry::System::Config::ComponentDir#default_namespace",
@@ -179,7 +191,7 @@ module Dry
179
191
  # @return [String] the path
180
192
  attr_reader :path
181
193
 
182
- # @api private
194
+ # @api public
183
195
  def initialize(path)
184
196
  super()
185
197
  @path = path
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "concurrent/map"
4
3
  require "dry/system/constants"
5
4
  require "dry/system/errors"
6
5
  require_relative "component_dir"
@@ -8,6 +7,9 @@ require_relative "component_dir"
8
7
  module Dry
9
8
  module System
10
9
  module Config
10
+ # The configured component dirs for a container
11
+ #
12
+ # @api public
11
13
  class ComponentDirs
12
14
  # @!group Settings
13
15
 
@@ -63,71 +65,141 @@ module Dry
63
65
  #
64
66
  # @see memoize=
65
67
 
68
+ # rubocop:disable Layout/LineLength
69
+
66
70
  # @!method namespaces
67
71
  #
68
72
  # Returns the default configured namespaces for all added component dirs
69
73
  #
70
- # Allows namespaces to added on the returned object via {Namespaces#add}.
74
+ # Allows namespaces to added on the returned object via {Dry::System::Config::Namespaces#add}.
71
75
  #
72
- # @see Namespaces#add
76
+ # @see Dry::System::Config::Namespaces#add
73
77
  #
74
78
  # @return [Namespaces] the namespaces
75
79
 
80
+ # rubocop:enable Layout/LineLength
81
+
76
82
  # @!endgroup
77
83
 
78
84
  # A ComponentDir for configuring the default values to apply to all added
79
85
  # component dirs
80
86
  #
87
+ # @see #method_missing
81
88
  # @api private
82
89
  attr_reader :defaults
83
90
 
91
+ # Creates a new component dirs
92
+ #
84
93
  # @api private
85
94
  def initialize
86
- @dirs = Concurrent::Map.new
95
+ @dirs = {}
87
96
  @defaults = ComponentDir.new(nil)
88
97
  end
89
98
 
90
99
  # @api private
91
100
  def initialize_copy(source)
92
- @dirs = source.dirs.dup
101
+ @dirs = source.dirs.map { |path, dir| [path, dir.dup] }.to_h
93
102
  @defaults = source.defaults.dup
94
103
  end
95
104
 
96
- # Adds and configures a component dir
105
+ # Returns and optionally yields a previously added component dir
106
+ #
107
+ # @param path [String] the path for the component dir
108
+ # @yieldparam dir [ComponentDir] the component dir
109
+ #
110
+ # @return [ComponentDir] the component dir
111
+ #
112
+ # @api public
113
+ def dir(path)
114
+ dirs[path].tap do |dir|
115
+ # Defaults can be (re-)applied first, since the dir has already been added
116
+ apply_defaults_to_dir(dir) if dir
117
+ yield dir if block_given?
118
+ end
119
+ end
120
+ alias_method :[], :dir
121
+
122
+ # @overload add(path)
123
+ # Adds and configures a component dir for the given path
124
+ #
125
+ # @param path [String] the path for the component dir, relative to the configured
126
+ # container root
127
+ # @yieldparam dir [ComponentDir] the component dir to configure
97
128
  #
98
- # @param path [String] the path for the component dir, relative to the configured
99
- # container root
129
+ # @return [ComponentDir] the added component dir
100
130
  #
101
- # @yieldparam dir [ComponentDir] the component dir to configure
131
+ # @example
132
+ # component_dirs.add "lib" do |dir|
133
+ # dir.default_namespace = "my_app"
134
+ # end
102
135
  #
103
- # @return [ComponentDir] the added component dir
136
+ # @see ComponentDir
137
+ # @api public
104
138
  #
105
- # @example
106
- # component_dirs.add "lib" do |dir|
107
- # dir.default_namespace = "my_app"
108
- # end
139
+ # @overload add(dir)
140
+ # Adds a configured component dir
109
141
  #
110
- # @see ComponentDir
111
- def add(path)
142
+ # @param dir [ComponentDir] the configured component dir
143
+ #
144
+ # @return [ComponentDir] the added component dir
145
+ #
146
+ # @example
147
+ # dir = Dry::System::ComponentDir.new("lib")
148
+ # component_dirs.add dir
149
+ #
150
+ # @see ComponentDir
151
+ # @api public
152
+ def add(path_or_dir)
153
+ path, dir_to_add = path_and_dir(path_or_dir)
154
+
112
155
  raise ComponentDirAlreadyAddedError, path if dirs.key?(path)
113
156
 
114
- dirs[path] = ComponentDir.new(path).tap do |dir|
115
- yield dir if block_given?
157
+ dirs[path] = dir_to_add.tap do |dir|
158
+ # Defaults must be applied after yielding, since the dir is being newly added,
159
+ # and must have its configuration fully in place before we can know which
160
+ # defaults to apply
161
+ yield dir if path_or_dir == path && block_given?
116
162
  apply_defaults_to_dir(dir)
117
163
  end
118
164
  end
119
165
 
120
- # Returns the added component dirs, with default settings applied
166
+ # Deletes and returns a previously added component dir
121
167
  #
122
- # @return [Hash<String, ComponentDir>] the component dirs as a hash, keyed by path
123
- def dirs
124
- @dirs.each { |_, dir| apply_defaults_to_dir(dir) }
168
+ # @param path [String] the path for the component dir
169
+ #
170
+ # @return [ComponentDir] the removed component dir
171
+ #
172
+ # @api public
173
+ def delete(path)
174
+ dirs.delete(path)
125
175
  end
126
176
 
177
+ # Returns the paths of the component dirs
178
+ #
179
+ # @return [Array<String>] the component dir paths
180
+ #
181
+ # @api public
182
+ def paths
183
+ dirs.keys
184
+ end
185
+
186
+ # Returns the count of component dirs
187
+ #
188
+ # @return [Integer]
189
+ #
190
+ # @api public
191
+ def length
192
+ dirs.length
193
+ end
194
+ alias_method :size, :length
195
+
127
196
  # Returns the added component dirs, with default settings applied
128
197
  #
129
198
  # @return [Array<ComponentDir>]
199
+ #
200
+ # @api public
130
201
  def to_a
202
+ dirs.each { |_, dir| apply_defaults_to_dir(dir) }
131
203
  dirs.values
132
204
  end
133
205
 
@@ -135,12 +207,46 @@ module Dry
135
207
  # argument.
136
208
  #
137
209
  # @yieldparam dir [ComponentDir] the yielded component dir
210
+ #
211
+ # @api public
138
212
  def each(&block)
139
213
  to_a.each(&block)
140
214
  end
141
215
 
216
+ protected
217
+
218
+ # Returns the hash of component dirs, keyed by their paths
219
+ #
220
+ # Recently changed default configuration may not be applied to these dirs. Use
221
+ # #to_a or #each to access dirs with default configuration fully applied.
222
+ #
223
+ # This method exists to encapsulate the instance variable and to serve the needs
224
+ # of #initialize_copy
225
+ #
226
+ # @return [Hash{String => ComponentDir}]
227
+ #
228
+ # @api private
229
+ attr_reader :dirs
230
+
142
231
  private
143
232
 
233
+ # Converts a path string or pre-built component dir into a path and dir tuple
234
+ #
235
+ # @param path_or_dir [String,ComponentDir]
236
+ #
237
+ # @return [Array<(String, ComponentDir)>]
238
+ #
239
+ # @see #add
240
+ def path_and_dir(path_or_dir)
241
+ if path_or_dir.is_a?(ComponentDir)
242
+ dir = path_or_dir
243
+ [dir.path, dir]
244
+ else
245
+ path = path_or_dir
246
+ [path, ComponentDir.new(path)]
247
+ end
248
+ end
249
+
144
250
  # Applies default settings to a component dir. This is run every time the dirs are
145
251
  # accessed to ensure defaults are applied regardless of when new component dirs
146
252
  # are added. This method must be idempotent.
@@ -21,16 +21,19 @@ module Dry
21
21
  #
22
22
  # @see Namespaces#add
23
23
  #
24
- # @api private
24
+ # @api public
25
25
  class Namespace
26
26
  ROOT_PATH = nil
27
27
 
28
28
  include Dry::Equalizer(:path, :key, :const)
29
29
 
30
+ # @api public
30
31
  attr_reader :path
31
32
 
33
+ # @api public
32
34
  attr_reader :key
33
35
 
36
+ # @api public
34
37
  attr_reader :const
35
38
 
36
39
  # Returns a namespace configured to serve as the default root namespace for a
@@ -48,20 +51,24 @@ module Dry
48
51
  )
49
52
  end
50
53
 
54
+ # @api private
51
55
  def initialize(path:, key:, const:)
52
56
  @path = path
53
57
  @key = key
54
58
  @const = const
55
59
  end
56
60
 
61
+ # @api public
57
62
  def root?
58
63
  path == ROOT_PATH
59
64
  end
60
65
 
66
+ # @api public
61
67
  def path?
62
68
  !root?
63
69
  end
64
70
 
71
+ # @api private
65
72
  def default_key?
66
73
  key == path
67
74
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "dry/core/deprecations"
3
4
  require "dry/system/errors"
4
5
  require_relative "namespace"
5
6
 
@@ -26,6 +27,39 @@ module Dry
26
27
  @namespaces = source.namespaces.dup
27
28
  end
28
29
 
30
+ # Returns the namespace configured for the path, or nil if no such namespace has
31
+ # been configured
32
+ #
33
+ # @return [Namespace, nil] the namespace, if configured
34
+ #
35
+ # @api public
36
+ def namespace(path)
37
+ namespaces[path]
38
+ end
39
+ alias_method :[], :namespace
40
+
41
+ # Returns the namespace configured for the root path, or nil if the root namespace
42
+ # has not been configured
43
+ #
44
+ # @return [Namespace, nil] the root namespace, if configured
45
+ #
46
+ # @api public
47
+ def root(**options)
48
+ if options.any?
49
+ Dry::Core::Deprecations.announce(
50
+ "Dry::System::Config::Namespaces#root (with arguments)",
51
+ "Use `#add_root(key: nil, const: nil)` instead",
52
+ tag: "dry-system",
53
+ uplevel: 1
54
+ )
55
+
56
+ add_root(**options)
57
+ return
58
+ end
59
+
60
+ namespaces[Namespace::ROOT_PATH]
61
+ end
62
+
29
63
  # rubocop:disable Layout/LineLength
30
64
 
31
65
  # Adds a component dir namespace
@@ -62,8 +96,8 @@ module Dry
62
96
  #
63
97
  # @param path [String] the path to the sub-directory of source files to which this
64
98
  # namespace should apply, relative to the component dir
65
- # @param identifier [String, nil] the leading namespace to apply to the registered
66
- # identifiers for the components. Set `nil` for the identifiers to be top-level.
99
+ # @param key [String, nil] the leading namespace to apply to the container keys
100
+ # for the components. Set `nil` for the keys to be top-level.
67
101
  # @param const [String, nil] the Ruby constant namespace to expect for constants
68
102
  # defined within the components. This should be provided in underscored string
69
103
  # form, e.g. "hello_there/world" for a Ruby constant of `HelloThere::World`. Set
@@ -87,31 +121,84 @@ module Dry
87
121
  # @see #add
88
122
  #
89
123
  # @api public
90
- def root(key: nil, const: nil)
124
+ def add_root(key: nil, const: nil)
91
125
  add(Namespace::ROOT_PATH, key: key, const: const)
92
126
  end
93
127
 
94
- # @api private
128
+ # Deletes the configured namespace for the given path and returns the namespace
129
+ #
130
+ # If no namespace was previously configured for the given path, returns nil
131
+ #
132
+ # @param path [String] the path for the namespace
133
+ #
134
+ # @return [Namespace, nil]
135
+ #
136
+ # @api public
137
+ def delete(path)
138
+ namespaces.delete(path)
139
+ end
140
+
141
+ # Deletes the configured root namespace and returns the namespace
142
+ #
143
+ # If no root namespace was previously configured, returns nil
144
+ #
145
+ # @return [Namespace, nil]
146
+ #
147
+ # @api public
148
+ def delete_root
149
+ delete(Namespace::ROOT_PATH)
150
+ end
151
+
152
+ # Returns the paths of the configured namespaces
153
+ #
154
+ # @return [Array<String,nil>] the namespace paths, with nil representing the root
155
+ # namespace
156
+ #
157
+ # @api public
158
+ def paths
159
+ namespaces.keys
160
+ end
161
+
162
+ # Returns the count of configured namespaces
163
+ #
164
+ # @return [Integer]
165
+ #
166
+ # @api public
167
+ def length
168
+ namespaces.length
169
+ end
170
+ alias_method :size, :length
171
+
172
+ # Returns true if there are no configured namespaces
173
+ #
174
+ # @return [Boolean]
175
+ #
176
+ # @api public
95
177
  def empty?
96
178
  namespaces.empty?
97
179
  end
98
180
 
99
181
  # Returns the configured namespaces as an array
100
182
  #
101
- # This adds a root namespace to the end of the array if one was not configured
102
- # manually. This fallback ensures that all components in the component dir can be
103
- # loaded.
183
+ # Adds a default root namespace to the end of the array if one was not added
184
+ # explicitly. This fallback ensures that all components in the component dir can
185
+ # be loaded.
104
186
  #
105
187
  # @return [Array<Namespace>] the namespaces
106
188
  #
107
- # @api private
189
+ # @api public
108
190
  def to_a
109
191
  namespaces.values.tap do |arr|
110
192
  arr << Namespace.default_root unless arr.any?(&:root?)
111
193
  end
112
194
  end
113
195
 
114
- # @api private
196
+ # Calls the given block once for each configured namespace, passing the namespace
197
+ # as an argument.
198
+ #
199
+ # @yieldparam namespace [Namespace] the yielded namespace
200
+ #
201
+ # @api public
115
202
  def each(&block)
116
203
  to_a.each(&block)
117
204
  end
@@ -36,7 +36,7 @@ module Dry
36
36
 
37
37
  # @api private
38
38
  def bootsnap_available?
39
- RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.3.0" && RUBY_VERSION < "2.5.0"
39
+ RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.3.0" && RUBY_VERSION < "3.1.0"
40
40
  end
41
41
  end
42
42
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module System
5
- VERSION = "0.21.0"
5
+ VERSION = "0.22.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-system
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-31 00:00:00.000000000 Z
11
+ date: 2022-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby