dry-configurable 0.9.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 +7 -0
- data/.codeclimate.yml +12 -0
- data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +10 -0
- data/.github/ISSUE_TEMPLATE/---bug-report.md +34 -0
- data/.github/ISSUE_TEMPLATE/---feature-request.md +18 -0
- data/.github/workflows/ci.yml +70 -0
- data/.github/workflows/docsite.yml +34 -0
- data/.github/workflows/sync_configs.yml +30 -0
- data/.gitignore +9 -0
- data/.rspec +4 -0
- data/.rubocop.yml +89 -0
- data/CHANGELOG.md +94 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/CONTRIBUTING.md +29 -0
- data/Gemfile +20 -0
- data/LICENSE +20 -0
- data/README.md +41 -0
- data/Rakefile +12 -0
- data/docsite/source/index.html.md +55 -0
- data/docsite/source/testing.html.md +27 -0
- data/dry-configurable.gemspec +29 -0
- data/lib/dry-configurable.rb +1 -0
- data/lib/dry/configurable.rb +191 -0
- data/lib/dry/configurable/config.rb +185 -0
- data/lib/dry/configurable/error.rb +7 -0
- data/lib/dry/configurable/setting.rb +46 -0
- data/lib/dry/configurable/settings.rb +117 -0
- data/lib/dry/configurable/settings/argument_parser.rb +50 -0
- data/lib/dry/configurable/test_interface.rb +26 -0
- data/lib/dry/configurable/version.rb +6 -0
- data/rakelib/rubocop.rake +18 -0
- metadata +151 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
module Dry
|
2
|
+
module Configurable
|
3
|
+
# This class represents a setting and is used internally.
|
4
|
+
#
|
5
|
+
# @private
|
6
|
+
class Setting
|
7
|
+
VALID_NAME = /\A[a-z_]\w*\z/i
|
8
|
+
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
attr_reader :options
|
12
|
+
|
13
|
+
attr_reader :processor
|
14
|
+
|
15
|
+
def initialize(name, value, processor, options = EMPTY_HASH)
|
16
|
+
unless VALID_NAME =~ name.to_s
|
17
|
+
raise ArgumentError, "+#{name}+ is not a valid setting name"
|
18
|
+
end
|
19
|
+
@name = name.to_sym
|
20
|
+
@value = value
|
21
|
+
@processor = processor
|
22
|
+
@options = options
|
23
|
+
end
|
24
|
+
|
25
|
+
def value
|
26
|
+
Undefined.default(@value, nil)
|
27
|
+
end
|
28
|
+
|
29
|
+
def undefined?
|
30
|
+
Undefined.equal?(@value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def reader?
|
34
|
+
options[:reader]
|
35
|
+
end
|
36
|
+
|
37
|
+
def node?
|
38
|
+
Settings === @value
|
39
|
+
end
|
40
|
+
|
41
|
+
def reserved?
|
42
|
+
options[:reserved]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'concurrent/array'
|
3
|
+
require 'dry/configurable/settings/argument_parser'
|
4
|
+
require 'dry/configurable/setting'
|
5
|
+
require 'dry/configurable/config'
|
6
|
+
|
7
|
+
module Dry
|
8
|
+
module Configurable
|
9
|
+
# A collection of settings. This is not part of the public API.
|
10
|
+
#
|
11
|
+
# @private
|
12
|
+
class Settings
|
13
|
+
Parser = ArgumentParser.new.freeze
|
14
|
+
|
15
|
+
class DSL
|
16
|
+
def self.call(&block)
|
17
|
+
new.instance_exec do
|
18
|
+
instance_exec(&block)
|
19
|
+
@settings
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@settings = Settings.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def setting(*args, &block)
|
28
|
+
@settings.add(*args, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Capture nested config definition
|
33
|
+
#
|
34
|
+
# @return [Dry::Configurable::Setting]
|
35
|
+
def self.capture(&block)
|
36
|
+
DSL.(&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :settings
|
40
|
+
|
41
|
+
attr_reader :config_class
|
42
|
+
|
43
|
+
attr_reader :index
|
44
|
+
private :index
|
45
|
+
|
46
|
+
def initialize(settings = ::Concurrent::Array.new)
|
47
|
+
@settings = settings
|
48
|
+
@config_class = Config[self]
|
49
|
+
@index = settings.map { |s| [s.name, s] }.to_h
|
50
|
+
yield(self) if block_given?
|
51
|
+
end
|
52
|
+
|
53
|
+
def add(key, value = Undefined, options = Undefined, &block)
|
54
|
+
extended = singleton_class < Configurable
|
55
|
+
raise_already_defined_config(key) if extended && configured?
|
56
|
+
|
57
|
+
*args, opts = Parser.(value, options, block)
|
58
|
+
|
59
|
+
Setting.new(key, *args, { **opts, reserved: reserved?(key) }).tap do |s|
|
60
|
+
settings.delete_if { |e| e.name.eql?(s.name) }
|
61
|
+
settings << s
|
62
|
+
index[s.name] = s
|
63
|
+
@names = nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def each
|
68
|
+
settings.each { |s| yield(s) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def names
|
72
|
+
@names ||= index.keys.to_set
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](name)
|
76
|
+
index[name]
|
77
|
+
end
|
78
|
+
|
79
|
+
def empty?
|
80
|
+
settings.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
def name?(name)
|
84
|
+
index.key?(name)
|
85
|
+
end
|
86
|
+
|
87
|
+
def dup
|
88
|
+
Settings.new(settings.dup)
|
89
|
+
end
|
90
|
+
|
91
|
+
def freeze
|
92
|
+
settings.freeze
|
93
|
+
super
|
94
|
+
end
|
95
|
+
|
96
|
+
def create_config
|
97
|
+
config_class.new
|
98
|
+
end
|
99
|
+
|
100
|
+
def config_defined?
|
101
|
+
config_class.config_defined?
|
102
|
+
end
|
103
|
+
|
104
|
+
def reserved?(name)
|
105
|
+
reserved_names.include?(name)
|
106
|
+
end
|
107
|
+
|
108
|
+
def reserved_names
|
109
|
+
@reserved_names ||= [
|
110
|
+
config_class.instance_methods(false),
|
111
|
+
config_class.superclass.instance_methods(false),
|
112
|
+
%i(class public_send)
|
113
|
+
].reduce(:+)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Dry
|
2
|
+
# Argument parser
|
3
|
+
#
|
4
|
+
# Passing and array or arguments, it will decide which one are arguments
|
5
|
+
# and which one are options.
|
6
|
+
#
|
7
|
+
# We have a limitation if setting the value without options, as a hash
|
8
|
+
# having the same key as one of the valid options, will parse the value
|
9
|
+
# as options. In this case, all unknown options will be reject with an exception.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# p = Dry::Configurable::ArgumentParser.new.('db:sqlite', reader: true)
|
13
|
+
#
|
14
|
+
# p[0] # => 'db:sqlite'
|
15
|
+
# p[1] # => ArgumentParser::DEFAULT_PROCESSOR
|
16
|
+
# p[2] # => { reader: true }
|
17
|
+
module Configurable
|
18
|
+
class Settings
|
19
|
+
# @private
|
20
|
+
class ArgumentParser
|
21
|
+
DEFAULT_PROCESSOR = ->(v) { v }
|
22
|
+
|
23
|
+
# @private
|
24
|
+
def call(val, opts, block)
|
25
|
+
if block && block.parameters.empty?
|
26
|
+
raise ArgumentError unless Undefined.equal?(opts)
|
27
|
+
|
28
|
+
processor = DEFAULT_PROCESSOR
|
29
|
+
|
30
|
+
value, options = Settings.capture(&block), val
|
31
|
+
else
|
32
|
+
processor = block || DEFAULT_PROCESSOR
|
33
|
+
|
34
|
+
if Undefined.equal?(opts) && val.is_a?(Hash) && val.key?(:reader)
|
35
|
+
value, options = Undefined, val
|
36
|
+
else
|
37
|
+
value, options = val, opts
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
[value, processor, options(**Undefined.default(options, EMPTY_HASH))]
|
42
|
+
end
|
43
|
+
|
44
|
+
def options(reader: false)
|
45
|
+
{ reader: reader }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Dry
|
2
|
+
module Configurable
|
3
|
+
# Methods meant to be used in a testing scenario
|
4
|
+
module TestInterface
|
5
|
+
# Resets configuration to default values
|
6
|
+
#
|
7
|
+
# @return [Dry::Configurable::Config]
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
def reset_config
|
11
|
+
@config = if self.is_a?(Module)
|
12
|
+
_settings.create_config
|
13
|
+
else
|
14
|
+
self.class._settings.create_config
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Mixes in test interface into the configurable module
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
def enable_test_interface
|
23
|
+
extend Dry::Configurable::TestInterface
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubocop/rake_task'
|
3
|
+
|
4
|
+
Rake::Task[:default].enhance [:rubocop]
|
5
|
+
|
6
|
+
RuboCop::RakeTask.new do |task|
|
7
|
+
task.options << '--display-cop-names'
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :rubocop do
|
11
|
+
desc 'Generate a configuration file acting as a TODO list.'
|
12
|
+
task :auto_gen_config do
|
13
|
+
exec 'bundle exec rubocop --auto-gen-config'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
rescue LoadError
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dry-configurable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andy Holland
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-11-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: concurrent-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-core
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.4'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 0.4.7
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.4'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.4.7
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bundler
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rake
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rspec
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
description:
|
90
|
+
email:
|
91
|
+
- andyholland1991@aol.com
|
92
|
+
executables: []
|
93
|
+
extensions: []
|
94
|
+
extra_rdoc_files: []
|
95
|
+
files:
|
96
|
+
- ".codeclimate.yml"
|
97
|
+
- ".github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md"
|
98
|
+
- ".github/ISSUE_TEMPLATE/---bug-report.md"
|
99
|
+
- ".github/ISSUE_TEMPLATE/---feature-request.md"
|
100
|
+
- ".github/workflows/ci.yml"
|
101
|
+
- ".github/workflows/docsite.yml"
|
102
|
+
- ".github/workflows/sync_configs.yml"
|
103
|
+
- ".gitignore"
|
104
|
+
- ".rspec"
|
105
|
+
- ".rubocop.yml"
|
106
|
+
- CHANGELOG.md
|
107
|
+
- CODE_OF_CONDUCT.md
|
108
|
+
- CONTRIBUTING.md
|
109
|
+
- Gemfile
|
110
|
+
- LICENSE
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- docsite/source/index.html.md
|
114
|
+
- docsite/source/testing.html.md
|
115
|
+
- dry-configurable.gemspec
|
116
|
+
- lib/dry-configurable.rb
|
117
|
+
- lib/dry/configurable.rb
|
118
|
+
- lib/dry/configurable/config.rb
|
119
|
+
- lib/dry/configurable/error.rb
|
120
|
+
- lib/dry/configurable/setting.rb
|
121
|
+
- lib/dry/configurable/settings.rb
|
122
|
+
- lib/dry/configurable/settings/argument_parser.rb
|
123
|
+
- lib/dry/configurable/test_interface.rb
|
124
|
+
- lib/dry/configurable/version.rb
|
125
|
+
- rakelib/rubocop.rake
|
126
|
+
homepage: https://github.com/dry-rb/dry-configurable
|
127
|
+
licenses:
|
128
|
+
- MIT
|
129
|
+
metadata:
|
130
|
+
source_code_uri: https://github.com/dry-rb/dry-configurable
|
131
|
+
changelog_uri: https://github.com/dry-rb/dry-configurable/blob/master/CHANGELOG.md
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options: []
|
134
|
+
require_paths:
|
135
|
+
- lib
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: 2.4.0
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
requirements: []
|
147
|
+
rubygems_version: 3.0.6
|
148
|
+
signing_key:
|
149
|
+
specification_version: 4
|
150
|
+
summary: A mixin to add configuration functionality to your classes
|
151
|
+
test_files: []
|