Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package rubygem-dry-configurable for
openSUSE:Factory checked in at 2022-10-12 18:25:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-dry-configurable (Old)
and /work/SRC/openSUSE:Factory/.rubygem-dry-configurable.new.2275 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-dry-configurable"
Wed Oct 12 18:25:06 2022 rev:6 rq:1010052 version:0.16.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/rubygem-dry-configurable/rubygem-dry-configurable.changes
2022-08-09 15:26:35.461323227 +0200
+++
/work/SRC/openSUSE:Factory/.rubygem-dry-configurable.new.2275/rubygem-dry-configurable.changes
2022-10-12 18:26:53.757981019 +0200
@@ -1,0 +2,40 @@
+Mon Oct 10 13:03:10 UTC 2022 - Stephan Kulow <[email protected]>
+
+updated to version 0.16.0
+ see installed CHANGELOG.md
+
+ ## 0.16.0 2022-10-08
+
+
+ ### Added
+
+ - Support for custom config classes via `config_class:` option (#136 by
@solnic)
+
+ ```ruby
+ extend Dry::Configurable(config_class: MyConfig)
+ ```
+
+ Your config class should inherit from `Dry::Configurable::Config`.
+ - Return `Dry::Core::Constants::Undefined` (instead of nil) as the value for
non-configured settings via a `default_undefined: true` option (#141 by
@timriley)
+
+ ```ruby
+ extend Dry::Configurable(default_undefined: true)
+ ```
+
+ You must opt into this feature via the `default_undefined: true` option.
Non-configured setting values are still `nil` by default.
+
+ ### Fixed
+
+ - Remove exec bit from version.rb (#139 by @Fryguy)
+
+ ### Changed
+
+ - Improve memory usage by separating setting definitions from config values
(#138 by @timriley)
+
+ Your usage of dry-configurable may be impacted if you have been accessing
objects from `_settings` or the internals of `Dry::Configurable::Config`.
`_settings` now returns `Dry::Configurable::Setting` instances, which contain
only the details from the setting's definition. Setting _values_ remain in
`Dry::Configurable::Config`.
+ - Use Zeitwerk to speed up load time (#135 by @solnic)
+
+ [Compare
v0.15.0...v0.16.0](https://github.com/dry-rb/dry-configurable/compare/v0.15.0...v0.16.0)
+
+
+-------------------------------------------------------------------
Old:
----
dry-configurable-0.15.0.gem
New:
----
dry-configurable-0.16.0.gem
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ rubygem-dry-configurable.spec ++++++
--- /var/tmp/diff_new_pack.scBEVz/_old 2022-10-12 18:26:54.349982322 +0200
+++ /var/tmp/diff_new_pack.scBEVz/_new 2022-10-12 18:26:54.353982331 +0200
@@ -24,7 +24,7 @@
#
Name: rubygem-dry-configurable
-Version: 0.15.0
+Version: 0.16.0
Release: 0
%define mod_name dry-configurable
%define mod_full_name %{mod_name}-%{version}
++++++ dry-configurable-0.15.0.gem -> dry-configurable-0.16.0.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md
--- old/CHANGELOG.md 2022-04-21 09:30:01.000000000 +0200
+++ new/CHANGELOG.md 2022-10-08 01:24:53.000000000 +0200
@@ -1,5 +1,38 @@
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
+## 0.16.0 2022-10-08
+
+
+### Added
+
+- Support for custom config classes via `config_class:` option (#136 by
@solnic)
+
+ ```ruby
+ extend Dry::Configurable(config_class: MyConfig)
+ ```
+
+ Your config class should inherit from `Dry::Configurable::Config`.
+- Return `Dry::Core::Constants::Undefined` (instead of nil) as the value for
non-configured settings via a `default_undefined: true` option (#141 by
@timriley)
+
+ ```ruby
+ extend Dry::Configurable(default_undefined: true)
+ ```
+
+ You must opt into this feature via the `default_undefined: true` option.
Non-configured setting values are still `nil` by default.
+
+### Fixed
+
+- Remove exec bit from version.rb (#139 by @Fryguy)
+
+### Changed
+
+- Improve memory usage by separating setting definitions from config values
(#138 by @timriley)
+
+ Your usage of dry-configurable may be impacted if you have been accessing
objects from `_settings` or the internals of `Dry::Configurable::Config`.
`_settings` now returns `Dry::Configurable::Setting` instances, which contain
only the details from the setting's definition. Setting _values_ remain in
`Dry::Configurable::Config`.
+- Use Zeitwerk to speed up load time (#135 by @solnic)
+
+[Compare
v0.15.0...v0.16.0](https://github.com/dry-rb/dry-configurable/compare/v0.15.0...v0.16.0)
+
## 0.15.0 2022-04-21
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/LICENSE new/LICENSE
--- old/LICENSE 2022-04-21 09:30:01.000000000 +0200
+++ new/LICENSE 2022-10-08 01:24:53.000000000 +0200
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2015-2021 dry-rb team
+Copyright (c) 2015-2022 dry-rb team
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dry-configurable.gemspec new/dry-configurable.gemspec
--- old/dry-configurable.gemspec 2022-04-21 09:30:01.000000000 +0200
+++ new/dry-configurable.gemspec 2022-10-08 01:24:53.000000000 +0200
@@ -29,8 +29,8 @@
spec.required_ruby_version = ">= 2.7.0"
# to update dependencies edit project.yml
- spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
spec.add_runtime_dependency "dry-core", "~> 0.6"
+ spec.add_runtime_dependency "zeitwerk", "~> 2.6"
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/class_methods.rb
new/lib/dry/configurable/class_methods.rb
--- old/lib/dry/configurable/class_methods.rb 2022-04-21 09:30:01.000000000
+0200
+++ new/lib/dry/configurable/class_methods.rb 2022-10-08 01:24:53.000000000
+0200
@@ -2,11 +2,6 @@
require "set"
-require "dry/configurable/constants"
-require "dry/configurable/dsl"
-require "dry/configurable/methods"
-require "dry/configurable/settings"
-
module Dry
module Configurable
module ClassMethods
@@ -16,8 +11,17 @@
def inherited(subclass)
super
- subclass.instance_variable_set("@_settings", _settings.dup)
- subclass.instance_variable_set("@_config", config.dup) if
respond_to?(:config)
+ subclass.instance_variable_set(:@__config_extension__,
__config_extension__)
+
+ new_settings = _settings.dup
+ subclass.instance_variable_set(:@_settings, new_settings)
+
+ # Only classes **extending** Dry::Configurable have class-level
config. When
+ # Dry::Configurable is **included**, the class-level config method is
undefined because it
+ # resides at the instance-level instead (see `Configurable.included`).
+ if respond_to?(:config)
+ subclass.instance_variable_set(:@config,
config.dup_for_settings(new_settings))
+ end
end
# Add a setting to the configuration
@@ -52,7 +56,7 @@
#
# @api public
def settings
- @settings ||= Set[*_settings.map(&:name)]
+ Set[*_settings.map(&:name)]
end
# Return declared settings
@@ -70,17 +74,25 @@
#
# @api public
def config
- # The _settings provided to the Config remain shared between the class
and the
- # Config. This allows settings defined _after_ accessing the config to
become
- # available in subsequent accesses to the config. The config is duped
when
- # subclassing to ensure it remains distinct between subclasses and
parent classes
- # (see `.inherited` above).
- @config ||= Config.new(_settings)
+ @config ||= __config_build__
+ end
+
+ # @api private
+ def __config_build__(settings = _settings)
+ __config_extension__.config_class.new(settings)
+ end
+
+ # @api private
+ def __config_extension__
+ @__config_extension__
end
# @api private
def __config_dsl__
- @__config_dsl__ ||= DSL.new
+ @__config_dsl__ ||= DSL.new(
+ config_class: __config_extension__.config_class,
+ default_undefined: __config_extension__.default_undefined
+ )
end
# @api private
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/compiler.rb
new/lib/dry/configurable/compiler.rb
--- old/lib/dry/configurable/compiler.rb 2022-04-21 09:30:01.000000000
+0200
+++ new/lib/dry/configurable/compiler.rb 2022-10-08 01:24:53.000000000
+0200
@@ -1,8 +1,5 @@
# frozen_string_literal: true
-require "dry/configurable/setting"
-require "dry/configurable/settings"
-
module Dry
module Configurable
# Setting compiler used internally by the DSL
@@ -32,7 +29,9 @@
# @api private
def visit_nested(node)
parent, children = node
- visit(parent).nested(call(children))
+ name, opts = parent[1]
+
+ Setting.new(name, **opts, children: Settings.new(call(children)))
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/config.rb
new/lib/dry/configurable/config.rb
--- old/lib/dry/configurable/config.rb 2022-04-21 09:30:01.000000000 +0200
+++ new/lib/dry/configurable/config.rb 2022-10-08 01:24:53.000000000 +0200
@@ -1,12 +1,9 @@
# frozen_string_literal: true
-require "concurrent/map"
+require "dry/core/constants"
require "dry/core/equalizer"
-require "dry/configurable/constants"
-require "dry/configurable/errors"
-
module Dry
module Configurable
# Config exposes setting values through a convenient API
@@ -19,12 +16,17 @@
attr_reader :_settings
# @api private
- attr_reader :_resolved
+ attr_reader :_values
# @api private
- def initialize(settings)
+ def initialize(settings, values: {})
@_settings = settings
- @_resolved = Concurrent::Map.new
+ @_values = values
+ end
+
+ # @api private
+ def dup_for_settings(settings)
+ self.class.new(settings, values: dup_values)
end
# Get config value by a key
@@ -34,9 +36,18 @@
# @return Config value
def [](name)
name = name.to_sym
- raise ArgumentError, "+#{name}+ is not a setting name" unless
_settings.key?(name)
- _settings[name].value
+ unless (setting = _settings[name])
+ raise ArgumentError, "+#{name}+ is not a setting name"
+ end
+
+ _values.fetch(name) {
+ # When reading values, only capture cloneable (i.e. mutable) values
in local state, making
+ # it easier to determine which values have actually been changed vs
just read
+ setting.to_value.tap { |value|
+ _values[name] = value if setting.cloneable?
+ }
+ }
end
# Set config value.
@@ -45,7 +56,15 @@
# @param [String,Symbol] name
# @param [Object] value
def []=(name, value)
- public_send(:"#{name}=", value)
+ raise FrozenConfig, "Cannot modify frozen config" if frozen?
+
+ name = name.to_sym
+
+ unless (setting = _settings[name])
+ raise ArgumentError, "+#{name}+ is not a setting name"
+ end
+
+ _values[name] = setting.constructor.(value)
end
# Update config with new values
@@ -70,61 +89,96 @@
self
end
- # Dump config into a hash
+ # Returns true if the value for the given key has been set on this
config.
+ #
+ # For simple values, this returns true if the value has been explicitly
assigned.
+ #
+ # For cloneable (mutable) values, since these are captured on read,
returns true if the value
+ # does not compare equally to its corresdponing default value. This
relies on these objects
+ # having functioning `#==` checks.
+ #
+ # @return [Bool]
+ #
+ # @api public
+ def configured?(key)
+ if _settings[key].cloneable? && _values.key?(key)
+ return _values[key] != _settings[key].to_value
+ end
+
+ _values.key?(key)
+ end
+
+ # Returns the current config values.
+ #
+ # Nested configs remain in their {Config} instances.
#
# @return [Hash]
#
# @api public
def values
- _settings
- .map { |setting| [setting.name, setting.value] }
- .map { |key, value| [key, value.is_a?(self.class) ? value.to_h :
value] }
- .to_h
+ _settings.to_h { |setting| [setting.name, self[setting.name]] }
+ end
+
+ # Returns config values as a hash, with nested values also converted
from {Config} instances
+ # into hashes.
+ #
+ # @return [Hash]
+ #
+ # @api public
+ def to_h
+ values.to_h { |key, value| [key, value.is_a?(self.class) ? value.to_h
: value] }
end
- alias_method :to_h, :values
# @api private
def finalize!(freeze_values: false)
- _settings.finalize!(freeze_values: freeze_values)
+ values.each_value do |value|
+ if value.is_a?(self.class)
+ value.finalize!(freeze_values: freeze_values)
+ elsif freeze_values
+ value.freeze
+ end
+ end
+
freeze
end
# @api private
def pristine
- self.class.new(_settings.pristine)
- end
-
- # @api private
- def respond_to_missing?(meth, include_private = false)
- super || _settings.key?(resolve(meth))
+ self.class.new(_settings)
end
private
- # @api private
- def method_missing(meth, *args)
- setting = _settings[resolve(meth)]
+ def method_missing(name, *args)
+ setting_name = setting_name_from_method(name)
+ setting = _settings[setting_name]
super unless setting
- if setting.writer?(meth)
- raise FrozenConfig, "Cannot modify frozen config" if frozen?
-
- _settings << setting.with(input: args[0])
+ if name.end_with?("=")
+ self[setting_name] = args[0]
else
- setting.value
+ self[setting_name]
end
end
- # @api private
- def resolve(meth)
- _resolved.fetch(meth) { _resolved[meth] = meth.to_s.tr("=", "").to_sym
}
+ def respond_to_missing?(meth, include_private = false)
+ _settings.key?(setting_name_from_method(meth)) || super
+ end
+
+ def setting_name_from_method(method_name)
+ method_name.to_s.tr("=", "").to_sym
+ end
+
+ def dup_values
+ _values.each_with_object({}) { |(key, val), dup_hsh|
+ dup_hsh[key] = _settings[key].cloneable? ? val.dup : val
+ }
end
- # @api private
def initialize_copy(source)
super
- @_settings = source._settings.dup
+ @_values = source.__send__(:dup_values)
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/dsl.rb
new/lib/dry/configurable/dsl.rb
--- old/lib/dry/configurable/dsl.rb 2022-04-21 09:30:01.000000000 +0200
+++ new/lib/dry/configurable/dsl.rb 2022-10-08 01:24:53.000000000 +0200
@@ -1,10 +1,5 @@
# frozen_string_literal: true
-require "dry/configurable/constants"
-require "dry/configurable/flags"
-require "dry/configurable/setting"
-require "dry/configurable/settings"
-require "dry/configurable/compiler"
require "dry/core/deprecations"
module Dry
@@ -15,16 +10,16 @@
class DSL
VALID_NAME = /\A[a-z_]\w*\z/i.freeze
- # @api private
attr_reader :compiler
- # @api private
attr_reader :ast
- # @api private
- def initialize(&block)
+ attr_reader :options
+
+ def initialize(**options, &block)
@compiler = Compiler.new
@ast = []
+ @options = options
instance_exec(&block) if block
end
@@ -33,106 +28,15 @@
# @see ClassMethods.setting
# @api private
# @return Setting
- def setting(name, default = Undefined, **options, &block) #
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity,
Metrics/PerceivedComplexity
+ def setting(name, **options, &block) # rubocop:disable Metrics/AbcSize,
Metrics/PerceivedComplexity
unless VALID_NAME.match?(name.to_s)
raise ArgumentError, "#{name} is not a valid setting name"
end
- if default != Undefined
- if Dry::Configurable.warn_on_setting_positional_default
- Dry::Core::Deprecations.announce(
- "default value as positional argument to settings",
- "Provide a `default:` keyword argument instead",
- tag: "dry-configurable",
- uplevel: 2
- )
- end
-
- options = options.merge(default: default)
- end
-
- if RUBY_VERSION < "3.0" &&
- default == Undefined &&
- (valid_opts, invalid_opts = valid_and_invalid_options(options)) &&
- invalid_opts.any? &&
- valid_opts.none?
- # In Ruby 2.6 and 2.7, when a hash is given as the second positional
argument
- # (i.e. the hash is intended to be the setting's default value), and
there are
- # no other keyword arguments given, the hash is assigned to the
`options`
- # variable instead of `default`.
- #
- # For example, for this setting:
- #
- # setting :hash_setting, {my_hash: true}
- #
- # We'll have a `default` of `Undefined` and an `options` of
`{my_hash: true}`
- #
- # If any additional keyword arguments are provided, e.g.:
- #
- # setting :hash_setting, {my_hash: true}, reader: true
- #
- # Then we'll have a `default` of `{my_hash: true}` and an `options`
of `{reader:
- # true}`, which is what we want.
- #
- # To work around that first case and ensure our (deprecated)
backwards
- # compatibility holds for Ruby 2.6 and 2.7, we extract all invalid
options from
- # `options`, and if there are no remaining valid options (i.e. if
there were no
- # keyword arguments given), then we can infer the invalid options to
be a
- # default hash value for the setting.
- #
- # This approach also preserves the behavior of raising an
ArgumentError when a
- # distinct hash is _not_ intentionally provided as the second
positional
- # argument (i.e. it's not enclosed in braces), and instead invalid
keyword
- # arguments are given alongside valid ones. So this setting:
- #
- # setting :some_setting, invalid_option: true, reader: true
- #
- # Would raise an ArgumentError as expected.
- #
- # However, the one case we can't catch here is when invalid options
are supplied
- # without hash literal braces, but there are no other keyword
arguments
- # supplied. In this case, a setting like:
- #
- # setting :hash_setting, my_hash: true
- #
- # Is parsed identically to the first case described above:
- #
- # setting :hash_setting, {my_hash: true}
- #
- # So in both of these cases, the default value will become
`{my_hash: true}`. We
- # consider this unlikely to be a problem in practice, since users
are not likely
- # to be providing invalid options to `setting` and expecting them to
be ignored.
- # Additionally, the deprecation messages will make the new behavior
obvious, and
- # encourage the users to upgrade their setting definitions.
-
- if Dry::Configurable.warn_on_setting_positional_default
- Dry::Core::Deprecations.announce(
- "default value as positional argument to settings",
- "Provide a `default:` keyword argument instead",
- tag: "dry-configurable",
- uplevel: 2
- )
- end
-
- options = {default: invalid_opts}
- end
-
- if block && !block.arity.zero?
- if Dry::Configurable.warn_on_setting_constructor_block
- Dry::Core::Deprecations.announce(
- "passing a constructor as a block",
- "Provide a `constructor:` keyword argument instead",
- tag: "dry-configurable",
- uplevel: 2
- )
- end
-
- options = options.merge(constructor: block)
- block = nil
- end
-
ensure_valid_options(options)
+ options = {default: default, config_class: config_class, **options}
+
node = [:setting, [name.to_sym, options]]
if block
@@ -144,6 +48,14 @@
compiler.visit(ast.last)
end
+ def config_class
+ options[:config_class]
+ end
+
+ def default
+ options[:default_undefined] ? Undefined : nil
+ end
+
private
def ensure_valid_options(options)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/extension.rb
new/lib/dry/configurable/extension.rb
--- old/lib/dry/configurable/extension.rb 1970-01-01 01:00:00.000000000
+0100
+++ new/lib/dry/configurable/extension.rb 2022-10-08 01:24:53.000000000
+0200
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Dry
+ module Configurable
+ class Extension < Module
+ # @api private
+ attr_reader :config_class
+
+ # @api private
+ attr_reader :default_undefined
+
+ # @api private
+ def initialize(config_class: Configurable::Config, default_undefined:
false)
+ super()
+ @config_class = config_class
+ @default_undefined = default_undefined
+ freeze
+ end
+
+ # @api private
+ def extended(klass)
+ super
+ klass.extend(ClassMethods)
+ klass.instance_variable_set(:@__config_extension__, self)
+ end
+
+ # @api private
+ def included(klass)
+ raise AlreadyIncluded if klass.include?(InstanceMethods)
+
+ super
+
+ klass.class_eval do
+ extend(ClassMethods)
+ include(InstanceMethods)
+ prepend(Initializer)
+
+ class << self
+ undef :config
+ undef :configure
+ end
+ end
+
+ klass.instance_variable_set(:@__config_extension__, self)
+ end
+ end
+ end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/flags.rb
new/lib/dry/configurable/flags.rb
--- old/lib/dry/configurable/flags.rb 2022-04-21 09:30:01.000000000 +0200
+++ new/lib/dry/configurable/flags.rb 1970-01-01 01:00:00.000000000 +0100
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require "dry/core/class_attributes"
-
-module Dry
- module Configurable
- extend Core::ClassAttributes
-
- # Set to false to suppress deprecation warning when a setting default is
provided as a
- # positional argument
- defines :warn_on_setting_positional_default
- warn_on_setting_positional_default true
-
- # Set to false to suppress deprecation warning when a setting constructor
is provided
- # as a block
- defines :warn_on_setting_constructor_block
- warn_on_setting_constructor_block true
- end
-end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/instance_methods.rb
new/lib/dry/configurable/instance_methods.rb
--- old/lib/dry/configurable/instance_methods.rb 2022-04-21
09:30:01.000000000 +0200
+++ new/lib/dry/configurable/instance_methods.rb 2022-10-08
01:24:53.000000000 +0200
@@ -12,10 +12,7 @@
module Initializer
# @api private
def initialize(*)
- # Dup settings at time of initializing to ensure setting values are
specific to
- # this instance. This does mean that any settings defined on the class
_after_
- # initialization will not be available on the instance.
- @config = Config.new(self.class._settings.dup)
+ @config = self.class.__config_build__(self.class._settings)
super
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/methods.rb
new/lib/dry/configurable/methods.rb
--- old/lib/dry/configurable/methods.rb 2022-04-21 09:30:01.000000000 +0200
+++ new/lib/dry/configurable/methods.rb 2022-10-08 01:24:53.000000000 +0200
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "dry/configurable/errors"
-
module Dry
module Configurable
# Common API for both classes and instances
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/setting.rb
new/lib/dry/configurable/setting.rb
--- old/lib/dry/configurable/setting.rb 2022-04-21 09:30:01.000000000 +0200
+++ new/lib/dry/configurable/setting.rb 2022-10-08 01:24:53.000000000 +0200
@@ -4,18 +4,15 @@
require "dry/core/equalizer"
-require "dry/configurable/constants"
-require "dry/configurable/config"
-
module Dry
module Configurable
# This class represents a setting and is used internally.
#
# @api private
class Setting
- include Dry::Equalizer(:name, :value, :options, inspect: false)
+ include Dry::Equalizer(:name, :default, :constructor, :children,
:options, inspect: false)
- OPTIONS = %i[input default reader constructor cloneable settings].freeze
+ OPTIONS = %i[default reader constructor cloneable settings
config_class].freeze
DEFAULT_CONSTRUCTOR = -> v { v }.freeze
@@ -25,105 +22,35 @@
attr_reader :name
# @api private
- attr_reader :writer_name
+ attr_reader :default
# @api private
- attr_reader :input
+ attr_reader :constructor
# @api private
- attr_reader :default
+ attr_reader :children
# @api private
attr_reader :options
- # Specialized Setting which includes nested settings
- #
- # @api private
- class Nested < Setting
- CONSTRUCTOR = Config.method(:new)
-
- # @api private
- def pristine
- with(input: input.pristine)
- end
-
- # @api private
- def constructor
- CONSTRUCTOR
- end
- end
-
# @api private
def self.cloneable_value?(value)
CLONEABLE_VALUE_TYPES.any? { |type| value.is_a?(type) }
end
# @api private
- def initialize(name, input: Undefined, default: Undefined, **options)
+ def initialize(
+ name,
+ default:,
+ constructor: DEFAULT_CONSTRUCTOR,
+ children: EMPTY_ARRAY,
+ **options
+ )
@name = name
- @writer_name = :"#{name}="
- @options = options
-
- # Setting collections (see `Settings`) are shared between the
configurable class
- # and its `config` object, so for cloneable individual settings, we
duplicate
- # their _values_ as early as possible to ensure no impact from
unintended mutation
- @input = input
@default = default
- if cloneable?
- @input = input.dup
- @default = default.dup
- end
-
- evaluate if input_defined?
- end
-
- # @api private
- def input_defined?
- !input.equal?(Undefined)
- end
-
- # @api private
- def value
- return @value if evaluated?
-
- @value = constructor[Undefined.coalesce(input, default, nil)]
- end
- alias_method :evaluate, :value
- private :evaluate
-
- # @api private
- def evaluated?
- instance_variable_defined?(:@value)
- end
-
- # @api private
- def nested(settings)
- Nested.new(name, input: settings, **options)
- end
-
- # @api private
- def pristine
- with(input: Undefined)
- end
-
- # @api private
- def finalize!(freeze_values: false)
- if value.is_a?(Config)
- value.finalize!(freeze_values: freeze_values)
- elsif freeze_values
- value.freeze
- end
- freeze
- end
-
- # @api private
- def with(new_opts)
- self.class.new(name, input: input, default: default, **options,
**new_opts)
- end
-
- # @api private
- def constructor
- options[:constructor] || DEFAULT_CONSTRUCTOR
+ @constructor = constructor
+ @children = children
+ @options = options
end
# @api private
@@ -132,35 +59,19 @@
end
# @api private
- def writer?(meth)
- writer_name.equal?(meth)
- end
-
- # @api private
def cloneable?
- if options.key?(:cloneable)
- # Return cloneable option if explicitly set
- options[:cloneable]
- else
- # Otherwise, infer cloneable from any of the input, default, or value
- Setting.cloneable_value?(input) || Setting.cloneable_value?(default)
|| (
- evaluated? && Setting.cloneable_value?(value)
- )
- end
+ children.any? || options.fetch(:cloneable) {
Setting.cloneable_value?(default) }
end
- private
-
# @api private
- def initialize_copy(source)
- super
-
- @options = source.options.dup
+ def to_value
+ if children.any?
+ (options[:config_class] || Config).new(children)
+ else
+ value = default
+ value = constructor.(value) unless value.eql?(Undefined)
- if source.cloneable?
- @input = source.input.dup
- @default = source.default.dup
- @value = source.value.dup if source.evaluated?
+ cloneable? ? value.dup : value
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/settings.rb
new/lib/dry/configurable/settings.rb
--- old/lib/dry/configurable/settings.rb 2022-04-21 09:30:01.000000000
+0200
+++ new/lib/dry/configurable/settings.rb 2022-10-08 01:24:53.000000000
+0200
@@ -1,9 +1,6 @@
# frozen_string_literal: true
-require "concurrent/map"
-
require "dry/core/equalizer"
-require "dry/configurable/constants"
module Dry
module Configurable
@@ -11,27 +8,27 @@
#
# @api private
class Settings
- include Dry::Equalizer(:elements)
+ include Dry::Equalizer(:settings)
include Enumerable
# @api private
- attr_reader :elements
+ attr_reader :settings
# @api private
- def initialize(elements = EMPTY_ARRAY)
- initialize_elements(elements)
+ def initialize(settings = EMPTY_ARRAY)
+ @settings = settings.each_with_object({}) { |s, m| m[s.name] = s }
end
# @api private
def <<(setting)
- elements[setting.name] = setting
+ settings[setting.name] = setting
self
end
# @api private
def [](name)
- elements[name]
+ settings[name]
end
# @api private
@@ -41,37 +38,18 @@
# @api private
def keys
- elements.keys
+ settings.keys
end
# @api private
def each(&block)
- elements.values.each(&block)
- end
-
- # @api private
- def pristine
- self.class.new(map(&:pristine))
- end
-
- # @api private
- def finalize!(freeze_values: false)
- each { |element| element.finalize!(freeze_values: freeze_values) }
- freeze
+ settings.each_value(&block)
end
private
- # @api private
def initialize_copy(source)
- initialize_elements(source.map(&:dup))
- end
-
- # @api private
- def initialize_elements(elements)
- @elements = elements.each_with_object(Concurrent::Map.new) { |s, m|
- m[s.name] = s
- }
+ @settings = source.settings.dup
end
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable/version.rb
new/lib/dry/configurable/version.rb
--- old/lib/dry/configurable/version.rb 2022-04-21 09:30:01.000000000 +0200
+++ new/lib/dry/configurable/version.rb 2022-10-08 01:24:53.000000000 +0200
@@ -3,6 +3,6 @@
module Dry
module Configurable
# @api public
- VERSION = "0.15.0"
+ VERSION = "0.16.0"
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/lib/dry/configurable.rb new/lib/dry/configurable.rb
--- old/lib/dry/configurable.rb 2022-04-21 09:30:01.000000000 +0200
+++ new/lib/dry/configurable.rb 2022-10-08 01:24:53.000000000 +0200
@@ -1,15 +1,17 @@
# frozen_string_literal: true
-require "concurrent/array"
+require "zeitwerk"
+require "dry/core/constants"
require "dry/configurable/constants"
-require "dry/configurable/class_methods"
-require "dry/configurable/instance_methods"
-require "dry/configurable/config"
-require "dry/configurable/setting"
require "dry/configurable/errors"
module Dry
+ # @api public
+ def self.Configurable(**options)
+ Configurable::Extension.new(**options)
+ end
+
# A simple configuration mixin
#
# @example class-level configuration
@@ -44,27 +46,32 @@
#
# @api public
module Configurable
+ def self.loader
+ @loader ||= Zeitwerk::Loader.new.tap do |loader|
+ root = File.expand_path("..", __dir__)
+ loader.tag = "dry-configurable"
+ loader.inflector =
Zeitwerk::GemInflector.new("#{root}/dry-configurable.rb")
+ loader.push_dir(root)
+ loader.ignore(
+ "#{root}/dry-configurable.rb",
+ "#{root}/dry/configurable/{constants,errors,version}.rb"
+ )
+ loader.inflector.inflect("dsl" => "DSL")
+ end
+ end
+
# @api private
def self.extended(klass)
super
- klass.extend(ClassMethods)
+ klass.extend(Extension.new)
end
# @api private
def self.included(klass)
- raise AlreadyIncluded if klass.include?(InstanceMethods)
-
super
- klass.class_eval do
- extend(ClassMethods)
- include(InstanceMethods)
- prepend(Initializer)
-
- class << self
- undef :config
- undef :configure
- end
- end
+ klass.include(Extension.new)
end
+
+ loader.setup
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata 2022-04-21 09:30:01.000000000 +0200
+++ new/metadata 2022-10-08 01:24:53.000000000 +0200
@@ -1,43 +1,43 @@
--- !ruby/object:Gem::Specification
name: dry-configurable
version: !ruby/object:Gem::Version
- version: 0.15.0
+ version: 0.16.0
platform: ruby
authors:
- Andy Holland
-autorequire:
+autorequire:
bindir: bin
cert_chain: []
-date: 2022-04-21 00:00:00.000000000 Z
+date: 2022-10-07 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
- name: concurrent-ruby
+ name: dry-core
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: '1.0'
+ version: '0.6'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: '1.0'
+ version: '0.6'
- !ruby/object:Gem::Dependency
- name: dry-core
+ name: zeitwerk
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: '0.6'
+ version: '2.6'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
- version: '0.6'
+ version: '2.6'
- !ruby/object:Gem::Dependency
name: bundler
requirement: !ruby/object:Gem::Requirement
@@ -99,7 +99,7 @@
- lib/dry/configurable/constants.rb
- lib/dry/configurable/dsl.rb
- lib/dry/configurable/errors.rb
-- lib/dry/configurable/flags.rb
+- lib/dry/configurable/extension.rb
- lib/dry/configurable/instance_methods.rb
- lib/dry/configurable/methods.rb
- lib/dry/configurable/setting.rb
@@ -114,7 +114,7 @@
changelog_uri:
https://github.com/dry-rb/dry-configurable/blob/main/CHANGELOG.md
source_code_uri: https://github.com/dry-rb/dry-configurable
bug_tracker_uri: https://github.com/dry-rb/dry-configurable/issues
-post_install_message:
+post_install_message:
rdoc_options: []
require_paths:
- lib
@@ -129,8 +129,8 @@
- !ruby/object:Gem::Version
version: '0'
requirements: []
-rubygems_version: 3.1.6
-signing_key:
+rubygems_version: 3.3.7
+signing_key:
specification_version: 4
summary: A mixin to add configuration functionality to your classes
test_files: []