dry-configurable 0.16.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d8c3e4ebee8cf7f978c48580f64c1547c6c818b50ed7064b0758b4bffb072ee
4
- data.tar.gz: 2aa701383b59289fbe591100642027fc5bc0d074bd0ec5d6d085359293af0f8f
3
+ metadata.gz: 5d067b9cb78be3e3904b22ab5e73a6903cecb387c241d08c875f2a1eaf1002a4
4
+ data.tar.gz: c7f9be3367d11ea23c10a8a73d0a63d0fab54a1cf6cd2f5053e8845b808bd801
5
5
  SHA512:
6
- metadata.gz: 221e2cfb38c4eae38ab6b56250e2d70672c9d1e6883b048f5a6bc807d0996065bf1b8e4a102fd78b6a95a4a4ffcf21dcfd46c64737acd915b3d1b80f9dca273e
7
- data.tar.gz: 1f04a6b9af22d12a6b310902cdf5761362762a7fcca97c78a2feb17a28ce3199285a8cd1b6e80c56cde10f7fc2983c8598990fa263e5e55656502ad22761dd2e
6
+ metadata.gz: 45d5b855ac62fa249080b1c40ed9faf0644cf9daa3d3a18c8c3cc0780723006dd510d3b0cb156d2251962775f95396b591e96136d951e08e4679dd684118601d
7
+ data.tar.gz: fc7420686647324a2c671f183aff7b1fc69131f80db292d0847e53dc5744e16904f56dc74a35b6dadb6cce1f4927409a632d026d7127ccb5844d9b8ba67b4e98
data/CHANGELOG.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  ## 0.16.1 2022-10-13
4
4
 
5
+
5
6
  ### Changed
6
7
 
7
8
  - Restored performance of config value reads (direct reader methods as well as aggregate methods like `#values` and `#to_h`) to pre-0.16.0 levels (#149 by @timriley)
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.required_ruby_version = ">= 2.7.0"
30
30
 
31
31
  # to update dependencies edit project.yml
32
- spec.add_runtime_dependency "dry-core", "~> 0.6"
32
+ spec.add_runtime_dependency "dry-core", "~> 1.0", "< 2"
33
33
  spec.add_runtime_dependency "zeitwerk", "~> 2.6"
34
34
 
35
35
  spec.add_development_dependency "bundler"
@@ -13,7 +13,7 @@ module Dry
13
13
 
14
14
  subclass.instance_variable_set(:@__config_extension__, __config_extension__)
15
15
 
16
- new_settings = _settings.dup
16
+ new_settings = settings.dup
17
17
  subclass.instance_variable_set(:@_settings, new_settings)
18
18
 
19
19
  # Only classes **extending** Dry::Configurable have class-level config. When
@@ -43,28 +43,19 @@ module Dry
43
43
  def setting(*args, **options, &block)
44
44
  setting = __config_dsl__.setting(*args, **options, &block)
45
45
 
46
- _settings << setting
46
+ settings << setting
47
47
 
48
48
  __config_reader__.define(setting.name) if setting.reader?
49
49
 
50
50
  self
51
51
  end
52
52
 
53
- # Return declared settings
54
- #
55
- # @return [Set<Symbol>]
56
- #
57
- # @api public
58
- def settings
59
- Set[*_settings.map(&:name)]
60
- end
61
-
62
- # Return declared settings
53
+ # Returns the defined settings for the class.
63
54
  #
64
55
  # @return [Settings]
65
56
  #
66
57
  # @api public
67
- def _settings
58
+ def settings
68
59
  @_settings ||= Settings.new
69
60
  end
70
61
 
@@ -78,7 +69,7 @@ module Dry
78
69
  end
79
70
 
80
71
  # @api private
81
- def __config_build__(settings = _settings)
72
+ def __config_build__(settings = self.settings)
82
73
  __config_extension__.config_class.new(settings)
83
74
  end
84
75
 
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/core/constants"
4
3
  require "set"
5
4
 
6
- require "dry/core/equalizer"
7
-
8
5
  module Dry
9
6
  module Configurable
10
7
  # Config exposes setting values through a convenient API
@@ -70,7 +67,7 @@ module Dry
70
67
  # @param [String,Symbol] name
71
68
  # @param [Object] value
72
69
  def []=(name, value)
73
- raise FrozenConfig, "Cannot modify frozen config" if frozen?
70
+ raise FrozenConfigError, "Cannot modify frozen config" if frozen?
74
71
 
75
72
  name = name.to_sym
76
73
 
@@ -149,7 +146,19 @@ module Dry
149
146
  end
150
147
 
151
148
  # @api private
149
+ alias_method :_dry_equalizer_hash, :hash
150
+
151
+ # @api public
152
+ def hash
153
+ return @__hash__ if instance_variable_defined?(:@__hash__)
154
+
155
+ _dry_equalizer_hash
156
+ end
157
+
158
+ # @api public
152
159
  def finalize!(freeze_values: false)
160
+ return self if frozen?
161
+
153
162
  values.each_value do |value|
154
163
  if value.is_a?(self.class)
155
164
  value.finalize!(freeze_values: freeze_values)
@@ -158,6 +167,13 @@ module Dry
158
167
  end
159
168
  end
160
169
 
170
+ # Memoize the hash for the object when finalizing (regardless of whether values themselves
171
+ # are to be frozen; the intention of finalization is that no further changes should be
172
+ # made). The benefit of freezing the hash at this point is that it saves repeated expensive
173
+ # computation (through Dry::Equalizer's hash implementation) if that hash is to be used
174
+ # later in performance-sensitive situations, such as when serving as a cache key or similar.
175
+ @__hash__ = _dry_equalizer_hash
176
+
161
177
  freeze
162
178
  end
163
179
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/core/constants"
4
-
5
3
  module Dry
6
4
  # Shared constants
7
5
  #
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/core/deprecations"
4
-
5
3
  module Dry
6
4
  module Configurable
7
5
  # Setting DSL used by the class API
@@ -6,7 +6,8 @@ module Dry
6
6
  # @api public
7
7
  module Configurable
8
8
  Error = Class.new(::StandardError)
9
- AlreadyIncluded = ::Class.new(Error)
10
- FrozenConfig = ::Class.new(Error)
9
+
10
+ AlreadyIncludedError = Class.new(Error)
11
+ FrozenConfigError = Class.new(Error)
11
12
  end
12
13
  end
@@ -26,7 +26,7 @@ module Dry
26
26
 
27
27
  # @api private
28
28
  def included(klass)
29
- raise AlreadyIncluded if klass.include?(InstanceMethods)
29
+ raise AlreadyIncludedError if klass.include?(InstanceMethods)
30
30
 
31
31
  super
32
32
 
@@ -12,7 +12,7 @@ module Dry
12
12
  module Initializer
13
13
  # @api private
14
14
  def initialize(*)
15
- @config = self.class.__config_build__(self.class._settings)
15
+ @config = self.class.__config_build__(self.class.settings)
16
16
 
17
17
  super
18
18
  end
@@ -8,7 +8,7 @@ module Dry
8
8
  module Methods
9
9
  # @api public
10
10
  def configure(&block)
11
- raise FrozenConfig, "Cannot modify frozen config" if frozen?
11
+ raise FrozenConfigError, "Cannot modify frozen config" if config.frozen?
12
12
 
13
13
  yield(config) if block
14
14
  self
@@ -2,43 +2,41 @@
2
2
 
3
3
  require "set"
4
4
 
5
- require "dry/core/equalizer"
6
-
7
5
  module Dry
8
6
  module Configurable
9
- # This class represents a setting and is used internally.
7
+ # A defined setting.
10
8
  #
11
- # @api private
9
+ # @api public
12
10
  class Setting
13
11
  include Dry::Equalizer(:name, :default, :constructor, :children, :options, inspect: false)
14
12
 
15
- OPTIONS = %i[default reader constructor cloneable settings config_class].freeze
13
+ OPTIONS = %i[default reader constructor mutable cloneable settings config_class].freeze
16
14
 
17
15
  DEFAULT_CONSTRUCTOR = -> v { v }.freeze
18
16
 
19
- CLONEABLE_VALUE_TYPES = [Array, Hash, Set, Config].freeze
17
+ MUTABLE_VALUE_TYPES = [Array, Hash, Set, Config].freeze
20
18
 
21
- # @api private
19
+ # @api public
22
20
  attr_reader :name
23
21
 
24
- # @api private
22
+ # @api public
25
23
  attr_reader :default
26
24
 
27
- # @api private
28
- attr_reader :cloneable
25
+ # @api public
26
+ attr_reader :mutable
29
27
 
30
- # @api private
28
+ # @api public
31
29
  attr_reader :constructor
32
30
 
33
- # @api private
31
+ # @api public
34
32
  attr_reader :children
35
33
 
36
- # @api private
34
+ # @api public
37
35
  attr_reader :options
38
36
 
39
37
  # @api private
40
- def self.cloneable_value?(value)
41
- CLONEABLE_VALUE_TYPES.any? { |type| value.is_a?(type) }
38
+ def self.mutable_value?(value)
39
+ MUTABLE_VALUE_TYPES.any? { |type| value.is_a?(type) }
42
40
  end
43
41
 
44
42
  # @api private
@@ -51,8 +49,9 @@ module Dry
51
49
  )
52
50
  @name = name
53
51
  @default = default
54
- @cloneable = children.any? || options.fetch(:cloneable) {
55
- Setting.cloneable_value?(default)
52
+ @mutable = children.any? || options.fetch(:mutable) {
53
+ # Allow `cloneable` as an option alias for `mutable`
54
+ options.fetch(:cloneable) { Setting.mutable_value?(default) }
56
55
  }
57
56
  @constructor = constructor
58
57
  @children = children
@@ -64,10 +63,11 @@ module Dry
64
63
  options[:reader].equal?(true)
65
64
  end
66
65
 
67
- # @api private
68
- def cloneable?
69
- cloneable
66
+ # @api public
67
+ def mutable?
68
+ mutable
70
69
  end
70
+ alias_method :cloneable?, :mutable?
71
71
 
72
72
  # @api private
73
73
  def to_value
@@ -77,7 +77,7 @@ module Dry
77
77
  value = default
78
78
  value = constructor.(value) unless value.eql?(Undefined)
79
79
 
80
- cloneable? ? value.dup : value
80
+ mutable? ? value.dup : value
81
81
  end
82
82
  end
83
83
  end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/core/equalizer"
4
-
5
3
  module Dry
6
4
  module Configurable
7
- # A settings map
5
+ # A collection of defined settings on a given class.
8
6
  #
9
7
  # @api private
10
8
  class Settings
@@ -20,37 +18,48 @@ module Dry
20
18
  @settings = settings.each_with_object({}) { |s, m| m[s.name] = s }
21
19
  end
22
20
 
21
+ # @api private
22
+ private def initialize_copy(source)
23
+ @settings = source.settings.dup
24
+ end
25
+
23
26
  # @api private
24
27
  def <<(setting)
25
28
  settings[setting.name] = setting
26
29
  self
27
30
  end
28
31
 
29
- # @api private
32
+ # Returns the setting for the given name, if found.
33
+ #
34
+ # @return [Setting, nil] the setting, or nil if not found
35
+ #
36
+ # @api public
30
37
  def [](name)
31
38
  settings[name]
32
39
  end
33
40
 
34
- # @api private
41
+ # Returns true if a setting for the given name is defined.
42
+ #
43
+ # @return [Boolean]
44
+ #
45
+ # @api public
35
46
  def key?(name)
36
47
  keys.include?(name)
37
48
  end
38
49
 
39
- # @api private
50
+ # Returns the list of defined setting names.
51
+ #
52
+ # @return [Array<Symbol>]
53
+ #
54
+ # @api public
40
55
  def keys
41
56
  settings.keys
42
57
  end
43
58
 
44
- # @api private
59
+ # @api public
45
60
  def each(&block)
46
61
  settings.each_value(&block)
47
62
  end
48
-
49
- private
50
-
51
- def initialize_copy(source)
52
- @settings = source.settings.dup
53
- end
54
63
  end
55
64
  end
56
65
  end
@@ -3,6 +3,6 @@
3
3
  module Dry
4
4
  module Configurable
5
5
  # @api public
6
- VERSION = "0.16.1"
6
+ VERSION = "1.0.0"
7
7
  end
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "zeitwerk"
4
4
 
5
- require "dry/core/constants"
5
+ require "dry/core"
6
6
  require "dry/configurable/constants"
7
7
  require "dry/configurable/errors"
8
8
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-configurable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Holland
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-12 00:00:00.000000000 Z
11
+ date: 2022-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-core
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.6'
19
+ version: '1.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '0.6'
29
+ version: '1.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: zeitwerk
29
35
  requirement: !ruby/object:Gem::Requirement