dsl_compose 2.12.0 → 2.13.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +10 -0
- data/lib/dsl_compose/dsl/arguments/argument.rb +15 -1
- data/lib/dsl_compose/dsl/arguments.rb +3 -2
- data/lib/dsl_compose/dsl/dsl_method/interpreter.rb +5 -3
- data/lib/dsl_compose/dsl/interpreter.rb +5 -3
- data/lib/dsl_compose/interpreter/execution/arguments.rb +31 -11
- data/lib/dsl_compose/reader.rb +7 -6
- data/lib/dsl_compose/version.rb +1 -1
- data/sig/dsl_compose/dsl/arguments/argument.rbs +2 -1
- data/sig/dsl_compose/dsl/arguments.rbs +1 -1
- data/sig/dsl_compose/dsl/dsl_method/interpreter.rbs +1 -1
- data/sig/dsl_compose/dsl/interpreter.rbs +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 117789e8395652f4823ad048b258d2a683b65328d5817788b9d3d3d7bc377c8b
|
4
|
+
data.tar.gz: d4ad4b7a66de0cfd143006e4c9984bef0ce1c29e6e18b86a0621810cb2d11edb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbcf361a908dcd619664f12e50299f80092d5e2f4e8efb4f53320b2d13c3ca30ef334e429fe1a977fb899c0878f2dd26a30d9b067b74da22198eb2372984d2ad
|
7
|
+
data.tar.gz: 9e932a4d10693634bc25532d9d625ad1939f58c975bf90a0f4a0f1714586bdce5dc1650cf48cbfaa0655c56fbaa341fd27731953e4e3fe74fbefd63619fac6ad
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [2.13.1](https://github.com/craigulliott/dsl_compose/compare/v2.13.0...v2.13.1) (2023-09-05)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* fixed a nil value in error message caused by overwriting method argument ([dd7848b](https://github.com/craigulliott/dsl_compose/commit/dd7848b3861bff6176c8326f6784fb29f1ba2fdd))
|
9
|
+
|
10
|
+
## [2.13.0](https://github.com/craigulliott/dsl_compose/compare/v2.12.0...v2.13.0) (2023-09-04)
|
11
|
+
|
12
|
+
|
13
|
+
### Features
|
14
|
+
|
15
|
+
* optionally mark required arguments as keyword arguments ([9a1c901](https://github.com/craigulliott/dsl_compose/commit/9a1c90169fb36c550b0577034823579062120647))
|
16
|
+
|
3
17
|
## [2.12.0](https://github.com/craigulliott/dsl_compose/compare/v2.11.0...v2.12.0) (2023-09-02)
|
4
18
|
|
5
19
|
|
data/README.md
CHANGED
@@ -114,6 +114,16 @@ class Foo
|
|
114
114
|
validate_greater_than 0
|
115
115
|
end
|
116
116
|
|
117
|
+
# Required arguments for both DSLs and DSL methods are assumed to be standard ruby
|
118
|
+
# arguments by default, but can be declared as keyword arguments by passing `kwarg: true`.
|
119
|
+
# This is useful because sometimes keyword arguments can make your DSL more readable. This
|
120
|
+
# option does not exist for optional arguments, because optional arguments are always kwargs.
|
121
|
+
requires :required_keyword_argument, :symbol, kwarg: true do
|
122
|
+
# You should provide descriptions for your arguments. These descriptions will
|
123
|
+
# be used when generating your documentation. This description supports markdown
|
124
|
+
description "A description of the first argument for this method"
|
125
|
+
end
|
126
|
+
|
117
127
|
# All optional and required arguments can optionally accept an array of values. When using
|
118
128
|
# your final DSL, a single item can be provided but will automatically be converted to an
|
119
129
|
# array of items. All items in the array must be of the expected type.
|
@@ -13,6 +13,9 @@ module DSLCompose
|
|
13
13
|
class InvalidTypeError < StandardError
|
14
14
|
end
|
15
15
|
|
16
|
+
class ImpossibleKwargError < StandardError
|
17
|
+
end
|
18
|
+
|
16
19
|
class InvalidNameError < StandardError
|
17
20
|
end
|
18
21
|
|
@@ -42,6 +45,10 @@ module DSLCompose
|
|
42
45
|
attr_reader :type
|
43
46
|
# if required, then this Argument must be provided when calling its associated DSLMethod.
|
44
47
|
attr_reader :required
|
48
|
+
# If true, then this argument must be provided as a keyword argument, this is only appropriate for
|
49
|
+
# required arguments, as optional arguments are always passed as keywork arguments.
|
50
|
+
# arguments.
|
51
|
+
attr_reader :kwarg
|
45
52
|
# If true, then this argument accepts an array of values. It will also accept a single value,
|
46
53
|
# but that single value will be automatically converted to an array
|
47
54
|
attr_reader :array
|
@@ -71,9 +78,10 @@ module DSLCompose
|
|
71
78
|
# `name` must be a symbol.
|
72
79
|
# `required` is a boolean which determines if this Attribute must be provided when
|
73
80
|
# calling its associated DSLMethod.
|
81
|
+
# `kwarg` is a boolean which determines if a required Attribute must be provided as a keyword argument.
|
74
82
|
# `type` can be either :integer, :boolean, :float, :string or :symbol
|
75
83
|
# `block` contains the instructions to further configure this Attribute
|
76
|
-
def initialize name, required, type, array: false, &block
|
84
|
+
def initialize name, required, kwarg, type, array: false, &block
|
77
85
|
if name.is_a? Symbol
|
78
86
|
|
79
87
|
if RESERVED_ARGUMENT_NAMES.include? name
|
@@ -93,6 +101,12 @@ module DSLCompose
|
|
93
101
|
|
94
102
|
@required = required ? true : false
|
95
103
|
|
104
|
+
if @required == false && kwarg == true
|
105
|
+
raise ImpossibleKwargError, "Optional arguments must always be provided as keyword arguments. The argument `#{name}` can not be both required: false and kwarg: true."
|
106
|
+
end
|
107
|
+
|
108
|
+
@kwarg = kwarg ? true : false
|
109
|
+
|
96
110
|
@array = array ? true : false
|
97
111
|
|
98
112
|
# If a block was provided, then we evaluate it using a seperate
|
@@ -85,8 +85,9 @@ module DSLCompose
|
|
85
85
|
#
|
86
86
|
# Argument `name` must be unique within the DSLMethod.
|
87
87
|
# `required` must be a boolean, and determines if this argument will be required
|
88
|
+
# `kwarg` is a boolean which determines if a required Attribute must be provided as a keyword argument.
|
88
89
|
# or optional on the method which is exposed in our DSL.
|
89
|
-
def add_argument name, required, type, array: false, &block
|
90
|
+
def add_argument name, required, kwarg, type, array: false, &block
|
90
91
|
if @arguments.key? name
|
91
92
|
raise ArgumentAlreadyExistsError, "An argument with the name `#{name}` already exists for this DSL method"
|
92
93
|
end
|
@@ -96,7 +97,7 @@ module DSLCompose
|
|
96
97
|
raise ArgumentOrderingError, "Required arguments can not be added after optional ones"
|
97
98
|
end
|
98
99
|
|
99
|
-
@arguments[name] = Argument.new(name, required, type, array: array, &block)
|
100
|
+
@arguments[name] = Argument.new(name, required, kwarg, type, array: array, &block)
|
100
101
|
end
|
101
102
|
end
|
102
103
|
end
|
@@ -39,17 +39,19 @@ module DSLCompose
|
|
39
39
|
# `block` contains the argument definition and will be evaluated seperately
|
40
40
|
# by the Argument::Interpreter
|
41
41
|
def optional name, type, array: false, &block
|
42
|
-
@dsl_method.arguments.add_argument name, false, type, array: array, &block
|
42
|
+
@dsl_method.arguments.add_argument name, false, false, type, array: array, &block
|
43
43
|
end
|
44
44
|
|
45
45
|
# adds a new required argument to the DSLMethod
|
46
46
|
#
|
47
47
|
# name must be a symbol
|
48
|
+
# `kwarg` is a boolean which determines if a required Attribute must be provided as a keyword argument.
|
49
|
+
# `array` is a boolean which determines if this argument will accept an array of the given type or a single item
|
48
50
|
# `type` can be either :integer, :boolean, :float, :string or :symbol
|
49
51
|
# `block` contains the argument definition and will be evaluated seperately
|
50
52
|
# by the Argument::Interpreter
|
51
|
-
def requires name, type, array: false, &block
|
52
|
-
@dsl_method.arguments.add_argument name, true, type, array: array, &block
|
53
|
+
def requires name, type, kwarg: false, array: false, &block
|
54
|
+
@dsl_method.arguments.add_argument name, true, kwarg, type, array: array, &block
|
53
55
|
end
|
54
56
|
|
55
57
|
# executes the shared configuration block with the given name within the
|
@@ -66,17 +66,19 @@ module DSLCompose
|
|
66
66
|
# `block` contains the argument definition and will be evaluated seperately
|
67
67
|
# by the Argument::Interpreter
|
68
68
|
def optional name, type, array: false, &block
|
69
|
-
@dsl.arguments.add_argument name, false, type, array: array, &block
|
69
|
+
@dsl.arguments.add_argument name, false, false, type, array: array, &block
|
70
70
|
end
|
71
71
|
|
72
72
|
# adds a new required argument to the DSLMethod
|
73
73
|
#
|
74
74
|
# name must be a symbol
|
75
|
+
# `kwarg` is a boolean which determines if a required Attribute must be provided as a keyword argument.
|
76
|
+
# `array` is a boolean which determines if this argument will accept an array of the given type or a single item
|
75
77
|
# `type` can be either :integer, :boolean, :float, :string, :symbol, :class or :object
|
76
78
|
# `block` contains the argument definition and will be evaluated seperately
|
77
79
|
# by the Argument::Interpreter
|
78
|
-
def requires name, type, array: false, &block
|
79
|
-
@dsl.arguments.add_argument name, true, type, array: array, &block
|
80
|
+
def requires name, type, kwarg: false, array: false, &block
|
81
|
+
@dsl.arguments.add_argument name, true, kwarg, type, array: array, &block
|
80
82
|
end
|
81
83
|
|
82
84
|
# executes the shared configuration block with the given name within the
|
@@ -25,18 +25,38 @@ module DSLCompose
|
|
25
25
|
@arguments = {}
|
26
26
|
|
27
27
|
required_argument_count = arguments.required_arguments.count
|
28
|
+
required_non_kwarg_argument_count = arguments.required_arguments.count { |a| !a.kwarg }
|
28
29
|
has_optional_arguments = arguments.optional_arguments.any?
|
29
30
|
|
30
|
-
# the first N args, where N =
|
31
|
+
# the first N args, where N = required_non_kwarg_argument_count, are the
|
31
32
|
# provided required arguments
|
32
|
-
required_args = args.slice(0,
|
33
|
-
|
34
|
-
# all the
|
35
|
-
|
33
|
+
required_args = args.slice(0, required_non_kwarg_argument_count)
|
34
|
+
|
35
|
+
# the final argument is the object which contains all the keyword args (these keyword
|
36
|
+
# args could be optional or required)
|
37
|
+
all_kwargs = args[required_non_kwarg_argument_count]
|
38
|
+
|
39
|
+
# process all the required arguments which are kwargs
|
40
|
+
required_kwargs = arguments.required_arguments.filter { |a| a.kwarg }
|
41
|
+
required_kwargs.each do |required_kwarg|
|
42
|
+
if all_kwargs.key? required_kwarg.name
|
43
|
+
# add the keyword argument to the required args
|
44
|
+
required_args << all_kwargs[required_kwarg.name]
|
45
|
+
# delete the required kwarg from the kwargs hash, so that we are
|
46
|
+
# left with only the optional args
|
47
|
+
all_kwargs.delete required_kwarg.name
|
48
|
+
else
|
49
|
+
raise MissingRequiredArgumentsError, "The required kwarg `#{required_kwarg.name}` was not provided"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# at this point, all_kwargs should be a hash which only represents
|
54
|
+
# the optional arguments
|
55
|
+
optional_arg = all_kwargs
|
36
56
|
|
37
57
|
# assert that a value is provided for every required argument
|
38
58
|
unless required_argument_count == required_args.count
|
39
|
-
raise MissingRequiredArgumentsError, "This requires #{
|
59
|
+
raise MissingRequiredArgumentsError, "This requires #{required_non_kwarg_argument_count} arguments, but only #{required_args.count} were provided"
|
40
60
|
end
|
41
61
|
|
42
62
|
# assert that too many arguments have not been provided
|
@@ -61,7 +81,7 @@ module DSLCompose
|
|
61
81
|
end
|
62
82
|
|
63
83
|
# asset that, if provided, then the optional argument (always the last one) is a Hash
|
64
|
-
if has_optional_arguments && optional_arg.nil?
|
84
|
+
if has_optional_arguments && !optional_arg.nil?
|
65
85
|
unless optional_arg.is_a? Hash
|
66
86
|
raise OptionalArgumentsShouldBeHashError, "If provided, then the optional arguments must be last, and be represented as a Hash"
|
67
87
|
end
|
@@ -165,13 +185,13 @@ module DSLCompose
|
|
165
185
|
# to the corresponding class, logic which doesn't happen here in case the class doesnt
|
166
186
|
# exist yet)
|
167
187
|
required_arg_value = if required_argument.type == :class
|
168
|
-
if
|
169
|
-
|
188
|
+
if required_args[i].is_a?(Array)
|
189
|
+
required_args[i].map { |v| ClassCoerce.new v }
|
170
190
|
else
|
171
|
-
ClassCoerce.new
|
191
|
+
ClassCoerce.new required_args[i]
|
172
192
|
end
|
173
193
|
else
|
174
|
-
|
194
|
+
required_args[i]
|
175
195
|
end
|
176
196
|
|
177
197
|
if required_arg_value.is_a?(Array) && !required_argument.array
|
data/lib/dsl_compose/reader.rb
CHANGED
@@ -24,24 +24,25 @@ module DSLCompose
|
|
24
24
|
# Move up through this classes ancestors until we find the class which defined
|
25
25
|
# the DSL with the provided name. When we reach the top of the ancestor chain we
|
26
26
|
# exit the loop.
|
27
|
-
|
27
|
+
k = klass
|
28
|
+
while k
|
28
29
|
# if we find a DSL with this name, then store a reference to the DSL and the
|
29
30
|
# ancestor class where it was defined
|
30
|
-
if DSLs.class_dsl_exists?(
|
31
|
-
@dsl = DSLs.class_dsl(
|
32
|
-
@dsl_defining_class =
|
31
|
+
if DSLs.class_dsl_exists?(k, dsl_name)
|
32
|
+
@dsl = DSLs.class_dsl(k, dsl_name)
|
33
|
+
@dsl_defining_class = k
|
33
34
|
# stop once we find the DSL
|
34
35
|
break
|
35
36
|
end
|
36
37
|
|
37
38
|
# the DSL was not found here, so traverse up the provided classes hierachy
|
38
39
|
# and keep looking for where this DSL was initially defined
|
39
|
-
|
40
|
+
k = k.superclass
|
40
41
|
end
|
41
42
|
|
42
43
|
# if no DSL was found, then raise an error
|
43
44
|
if @dsl.nil? && @dsl_defining_class.nil?
|
44
|
-
raise DSLNotFound, "No DSL named `#{dsl_name}` was found for class `#{klass}`"
|
45
|
+
raise DSLNotFound, "No DSL named `#{dsl_name}` was found for class `#{@klass}`"
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
data/lib/dsl_compose/version.rb
CHANGED
@@ -9,6 +9,7 @@ module DSLCompose
|
|
9
9
|
attr_reader name: Symbol
|
10
10
|
attr_reader type: argument_type
|
11
11
|
attr_reader required: bool
|
12
|
+
attr_reader kwarg: bool
|
12
13
|
attr_reader array: bool
|
13
14
|
attr_reader description: String
|
14
15
|
|
@@ -27,7 +28,7 @@ module DSLCompose
|
|
27
28
|
attr_reader length_validation: LengthValidation
|
28
29
|
attr_reader is_a_validation: IsAValidation
|
29
30
|
|
30
|
-
def initialize: (Symbol name, bool required, argument_type `type`, ?array: bool) -> void
|
31
|
+
def initialize: (Symbol name, bool required, bool kwarg, argument_type `type`, ?array: bool) -> void
|
31
32
|
def set_description: (String description) -> void
|
32
33
|
def has_description?: () -> bool
|
33
34
|
def required?: -> bool
|
@@ -12,7 +12,7 @@ module DSLCompose
|
|
12
12
|
def optional_argument: (Symbol name) -> Argument
|
13
13
|
def required_argument: (Symbol name) -> Argument
|
14
14
|
def has_argument?: (Symbol name) -> bool
|
15
|
-
def add_argument: (Symbol name, bool required, argument_type `type`, ?array: bool) -> Argument
|
15
|
+
def add_argument: (Symbol name, bool required, bool kwarg, argument_type `type`, ?array: bool) -> Argument
|
16
16
|
|
17
17
|
class ArgumentDoesNotExistError < StandardError
|
18
18
|
end
|
@@ -11,7 +11,7 @@ module DSLCompose
|
|
11
11
|
private
|
12
12
|
def description: (String description) -> void
|
13
13
|
def optional: (Symbol name, argument_type `type`, ?array: bool) -> void
|
14
|
-
def requires: (Symbol name, argument_type `type`, ?array: bool) -> void
|
14
|
+
def requires: (Symbol name, argument_type `type`, ?kwarg: bool, ?array: bool) -> void
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -14,7 +14,7 @@ module DSLCompose
|
|
14
14
|
def add_method: (Symbol name, ?required: nil) -> void
|
15
15
|
def add_unique_method: (Symbol name, ?required: nil) -> void
|
16
16
|
def optional: (Symbol name, argument_type `type`, ?array: bool) -> void
|
17
|
-
def requires: (Symbol name, argument_type `type`, ?array: bool) -> void
|
17
|
+
def requires: (Symbol name, argument_type `type`, ?kwarg: bool, ?array: bool) -> void
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dsl_compose
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Craig Ulliott
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: class_spec_helper
|