configuratrix 0.0.1.alpha

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 93b3ad072cd0671d44b8070ed2001f10e1908b9fa763accb8c3b0a1f677dc1a0
4
+ data.tar.gz: 1120f79e5e750f1ad4f491dd863cb31652b475f1d529ee903d54d53b019fc57c
5
+ SHA512:
6
+ metadata.gz: fedc7ec78c63f6742a9ec315df056d7c93a4daef59186813ea80cd144b78235b3a5cc63ff80487dc35ebceb466738f449b591d7ae963ef148d5127fedf4e1498
7
+ data.tar.gz: 365e2c66a76e9d4d469cddcd9afabbbae4983a622ee9248e331a88be76f6f008303fc4c633a46e282b15d3a75628bea526eb9a2dbea7eb71a1a10b71ab2b7ece
@@ -0,0 +1,101 @@
1
+ module Configuratrix
2
+
3
+ class Err < StandardError
4
+ # By eliminating newlines in error messages, we can use heredocs in `raise`
5
+ # statements which is nice.
6
+ def initialize(message=nil)
7
+ unless message.nil?
8
+ message = message.lines(chomp: true).join(' ').strip
9
+ end
10
+ super(message)
11
+ end
12
+
13
+ # Allow errors to descend from each other in whatever groupings are useful,
14
+ # while still having them all be defined directly under Err.
15
+ def self.err(name, &block)
16
+ Err.const_set name, Class.new(self, &block)
17
+ end
18
+ private_class_method :err
19
+
20
+ # A value is referenced that has no value, not even nil.
21
+ err :NoSuchValue do
22
+ # A namespace was queried for a name it does not contain.
23
+ err :ValuelessKey
24
+ end
25
+
26
+ # A well-formed schema could not be defined as requested.
27
+ err :BadSchema do
28
+ # A name would become ambiguous by referring to multiple values.
29
+ err :NameCollision
30
+ # A name was given that is not acceptable in context.
31
+ err :NameIsInvalid do
32
+ # A reserved name was given to a real value.
33
+ err :WordIsReserved
34
+ end
35
+ # A schema is set up in a way that is not useful and may mask
36
+ # misconfiguration elsewhere.
37
+ err :PathologicalSchema
38
+ # A schema class tried to configure itself with respect to another schema
39
+ # class, but did it wrong.
40
+ err :NoCanToggle
41
+ # The type of a value is unspecified and could not be determined.
42
+ err :TypeUndefined
43
+ # An unmarshalled value was assigned to a field (e.g. as the default
44
+ # value), but it is not a value of the field's value_type.
45
+ err :ValueUnrecognized
46
+ # Wrong number of values: An unmarshalled value was assigned to a field
47
+ # (e.g. as the default value), but the plurality of the value is not
48
+ # appropriate for the arity of the field.
49
+ err :ArityMismatch
50
+ # When an existing schema is reopened for further editing to find that it's
51
+ # the wrong kind of schema for the context.
52
+ err :UnsafeReopen
53
+ end
54
+
55
+ # Though the schema is well-formed, a config could not be created from it.
56
+ err :BadConfig do
57
+ # An input could not be understood within the schema.
58
+ err :SchemaViolation do
59
+ # The configuration does not contain a value that the schema requires it
60
+ # to.
61
+ err :RequirementUnmet
62
+ # The configuration refers to a field not defined in the schema.
63
+ err :NoSuchField
64
+ # The configuration refers to a source not defined in the schema.
65
+ err :NoSuchSource
66
+ # The configuration refers to a value type not defined in the schema.
67
+ err :NoSuchType
68
+ # The value specified for a field was not usable by that field.
69
+ err :MarshalUnacceptable
70
+ end
71
+ # A source encountered a problem with its input other than a violation of
72
+ # the schema.
73
+ err :SourceRejected do
74
+ # The source's input text was in some way not well-formed
75
+ err :BadSyntax
76
+ # The field was specified in a source in a context not appropriate for
77
+ # the field's value type. Contrast this to MarshalUnacceptable: a Type
78
+ # with no #affirm specified is not applicable to an implicit command line
79
+ # specification like `--field`. There's not even a value to deem
80
+ # unacceptable.
81
+ err :FieldNotApplicable
82
+ # A reference was made to a field, but it can't be told which one.
83
+ err :AmbiguousName
84
+ # A value was given when no more were expected.
85
+ err :DanglingValue
86
+ # A value was neither omitted from a source, nor fully specified.
87
+ err :IncompleteValue
88
+ # The source needed to resolve a reference within the source text, but
89
+ # couldn't.
90
+ err :BadReference
91
+ end
92
+ end
93
+
94
+ # Like the ruby's ArgumentError, but plays nice with heredoc messages.
95
+ err :BadArgument
96
+
97
+ # Testing only: an error that will never be raised.
98
+ err :UnusedError
99
+ end
100
+
101
+ end
@@ -0,0 +1,5 @@
1
+ module Configuratrix
2
+ # It is frequently necessary to look up constants etc just in the local
3
+ # module and not in parents, but man is that an opaque interface.
4
+ NO_INHERIT = false
5
+ end
@@ -0,0 +1,65 @@
1
+ module Configuratrix
2
+ module Internal
3
+
4
+ module ConfigSchemaLanguageUtil
5
+ # Facilitate the slick no-default/default commaless syntax for minimally
6
+ # specifying a field.
7
+ # field :has_no_default
8
+ # vs.
9
+ # field defaults_to: :a_value
10
+ #
11
+ # Returns a triple of [name, has_default, default_value (if applicable)]
12
+ def self.unpack_field_args(name, kwargs, declaring: :field)
13
+ case kwargs.size
14
+ in 0
15
+ if name.nil?
16
+ raise Err::BadArgument, <<~END
17
+ #{declaring} declaration requires a name
18
+ END
19
+ end
20
+ [name.to_sym, false]
21
+ in 1
22
+ unless name.nil?
23
+ raise Err::BadArgument, <<~END
24
+ #{declaring} declaration can't mix positional and keyword
25
+ arguments
26
+ END
27
+ end
28
+ [kwargs.keys.first.to_sym, true, kwargs.values.first]
29
+ in (2...)
30
+ raise Err::BadArgument, <<~END
31
+ #{declaring} declaration takes no extra keywords
32
+ END
33
+ end
34
+ end
35
+
36
+ # Fetch (or create) the named field within the config schema.
37
+ def self.field_by_name(name, schema:)
38
+ NestingSchemaUtil.absent_local_or_remote(
39
+ name,
40
+ schema.method(:fields),
41
+ absent: -> { schema.field_add Field.nested_class!(name, under: schema) },
42
+ local: -> { schema.field_get name },
43
+ remote: -> { schema.field_lift name },
44
+ )
45
+ end
46
+
47
+ def self.resolve_file_source_schema(filename, format)
48
+ return format if format .is_a? Class
49
+
50
+ format ||= filename.split('.').last
51
+ source_name = (format.to_s.capitalize << "File").to_sym
52
+
53
+ unless Mutable::DefaultSources.const_defined? source_name
54
+ raise Err::ValuelessKey, <<~END
55
+ #{source_name} does not name a Source!
56
+ END
57
+ end
58
+
59
+ Mutable::DefaultSources.const_get source_name
60
+ end
61
+ end
62
+
63
+
64
+ end
65
+ end