frise 0.2.0 → 0.3.0.pre
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 +5 -5
- data/.rubocop.yml +6 -0
- data/.travis.yml +1 -2
- data/CHANGELOG.md +1 -1
- data/Gemfile +2 -0
- data/Rakefile +2 -0
- data/frise.gemspec +6 -6
- data/lib/frise.rb +3 -0
- data/lib/frise/defaults_loader.rb +5 -1
- data/lib/frise/loader.rb +98 -29
- data/lib/frise/loader/lazy.rb +22 -0
- data/lib/frise/parser.rb +9 -1
- data/lib/frise/validator.rb +15 -10
- data/lib/frise/version.rb +3 -1
- metadata +19 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 72db98e097cb7abccf1a1208a53efa9a2486d49d3f58422a70e6f32ac7cbb2a8
|
4
|
+
data.tar.gz: 52f15d4c10262d54dc7534fa35c16abb66ad33d0498ceff612cc78124154fcf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75b318b997eb2ab66dada979b270e468430ca372982d035bba4de12a68a0622f6897d928e173b67d7e046be2ecdee0d7b1374e0a0d50da55e80354d60285eb9f
|
7
|
+
data.tar.gz: b25a7625181eaf4d90f202ca0aa9dc9095ada98318272c2d5c999beb8ea28e0e7af397b1612692bd18709a59dca4cab758d30ee515563806d6def511500243e7
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/frise.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path('
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require 'frise/version'
|
6
6
|
|
@@ -18,14 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
f.match(%r{^(test|spec|features|example)/})
|
19
19
|
end
|
20
20
|
spec.require_paths = ['lib']
|
21
|
-
spec.required_ruby_version = '>= 2.
|
21
|
+
spec.required_ruby_version = '>= 2.3.0'
|
22
22
|
|
23
23
|
spec.add_dependency 'liquid', '~> 3.0'
|
24
24
|
|
25
25
|
spec.add_development_dependency 'bundler', '~> 1.14'
|
26
26
|
spec.add_development_dependency 'coveralls', '~> 0.8.21'
|
27
|
-
spec.add_development_dependency '
|
28
|
-
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'rake', '~> 12.3'
|
29
28
|
spec.add_development_dependency 'rspec', '~> 3.4'
|
30
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
29
|
+
spec.add_development_dependency 'rubocop', '~> 0.53.0'
|
30
|
+
spec.add_development_dependency 'simplecov', '~> 0.14.1'
|
31
31
|
end
|
data/lib/frise.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'frise/parser'
|
2
4
|
|
3
5
|
module Frise
|
@@ -7,6 +9,8 @@ module Frise
|
|
7
9
|
# defaults and apply them to configuration objects.
|
8
10
|
module DefaultsLoader
|
9
11
|
class << self
|
12
|
+
SYMBOLS = %w[$all $optional].freeze
|
13
|
+
|
10
14
|
def widened_class(obj)
|
11
15
|
class_name = obj.class.to_s
|
12
16
|
return 'Boolean' if %w[TrueClass FalseClass].include? class_name
|
@@ -33,7 +37,7 @@ module Frise
|
|
33
37
|
elsif defaults.class == Hash && config.class == Hash
|
34
38
|
new_config = {}
|
35
39
|
(config.keys + defaults.keys).uniq.each do |key|
|
36
|
-
next if
|
40
|
+
next if SYMBOLS.include?(key)
|
37
41
|
new_config[key] = config[key]
|
38
42
|
new_config[key] = merge_defaults_obj(new_config[key], defaults[key]) if defaults.key?(key)
|
39
43
|
new_config[key] = merge_defaults_obj(new_config[key], defaults['$all']) unless new_config[key].nil?
|
data/lib/frise/loader.rb
CHANGED
@@ -1,60 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'frise/defaults_loader'
|
4
|
+
require 'frise/loader/lazy'
|
2
5
|
require 'frise/parser'
|
3
6
|
require 'frise/validator'
|
4
7
|
|
5
8
|
module Frise
|
6
9
|
# The entrypoint for loading configs from files according to the conventions defined for Frise.
|
7
10
|
#
|
8
|
-
# The load method loads a configuration file, merges
|
9
|
-
# its schema. Other methods in Loader perform only parts of the process.
|
11
|
+
# The load method loads a configuration file, merges the applicable includes and validates its schema.
|
10
12
|
class Loader
|
11
|
-
def initialize(
|
12
|
-
@
|
13
|
-
@
|
13
|
+
def initialize(include_sym: '$include', schema_sym: '$schema', pre_loaders: [], validators: nil, exit_on_fail: true)
|
14
|
+
@include_sym = include_sym
|
15
|
+
@schema_sym = schema_sym
|
14
16
|
@pre_loaders = pre_loaders
|
15
17
|
@validators = validators
|
18
|
+
@exit_on_fail = exit_on_fail
|
16
19
|
end
|
17
20
|
|
18
|
-
def load(config_file,
|
19
|
-
config = Parser.parse(config_file,
|
20
|
-
|
21
|
+
def load(config_file, global_vars = {})
|
22
|
+
config = Parser.parse(config_file, global_vars)
|
23
|
+
return nil unless config
|
21
24
|
|
22
25
|
@pre_loaders.each do |pre_loader|
|
23
26
|
config = pre_loader.call(config)
|
24
27
|
end
|
25
28
|
|
26
|
-
config =
|
27
|
-
|
29
|
+
config = process_includes(config, [], config, global_vars) if @include_sym
|
30
|
+
config = process_schemas(config, [], global_vars) if @schema_sym
|
31
|
+
config
|
28
32
|
end
|
29
33
|
|
30
|
-
|
31
|
-
merge_defaults_at(config, [], defaults_name, symbol_table)
|
32
|
-
end
|
34
|
+
private
|
33
35
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
)
|
36
|
+
def process_includes(config, at_path, root_config, global_vars)
|
37
|
+
return config unless config.class == Hash
|
38
|
+
|
39
|
+
config, defaults_confs = extract_include(config)
|
40
|
+
if defaults_confs.empty?
|
41
|
+
config.map { |k, v| [k, process_includes(v, at_path + [k], root_config, global_vars)] }.to_h
|
42
|
+
else
|
43
|
+
Lazy.new do
|
44
|
+
defaults_confs.each do |defaults_conf|
|
45
|
+
extra_vars = (defaults_conf['vars'] || {}).map { |k, v| [k, root_config.dig(*v.split('.'))] }.to_h
|
46
|
+
extra_consts = defaults_conf['constants'] || {}
|
47
|
+
symbol_table = merge_at(root_config, at_path, config)
|
48
|
+
.merge(global_vars).merge(extra_vars).merge(extra_consts).merge('_this' => config)
|
49
|
+
|
50
|
+
config = DefaultsLoader.merge_defaults_obj(config, Parser.parse(defaults_conf['file'], symbol_table))
|
51
|
+
end
|
52
|
+
process_includes(config, at_path, merge_at(root_config, at_path, config), global_vars)
|
53
|
+
end
|
40
54
|
end
|
41
|
-
config
|
42
55
|
end
|
43
56
|
|
44
|
-
def
|
45
|
-
|
57
|
+
def process_schema_includes(schema, global_vars)
|
58
|
+
return schema unless schema.class == Hash
|
59
|
+
|
60
|
+
schema, included_schemas = extract_include(schema)
|
61
|
+
if included_schemas.empty?
|
62
|
+
schema.map { |k, v| [k, process_schema_includes(v, global_vars)] }.to_h
|
63
|
+
else
|
64
|
+
included_schemas.each do |defaults_conf|
|
65
|
+
schema = Parser.parse(defaults_conf['file'], global_vars).merge(schema)
|
66
|
+
end
|
67
|
+
process_schema_includes(schema, global_vars)
|
68
|
+
end
|
46
69
|
end
|
47
70
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
71
|
+
def process_schemas(config, at_path, global_vars)
|
72
|
+
return config unless config.class == Hash
|
73
|
+
|
74
|
+
config = config.map do |k, v|
|
75
|
+
new_v = process_schemas(v, at_path + [k], global_vars)
|
76
|
+
return nil if !v.nil? && new_v.nil?
|
77
|
+
[k, new_v]
|
78
|
+
end.to_h
|
79
|
+
|
80
|
+
config, schema_files = extract_schema(config)
|
81
|
+
schema_files.each do |schema_file|
|
82
|
+
schema = Parser.parse(schema_file, global_vars)
|
83
|
+
schema = process_schema_includes(schema, global_vars)
|
84
|
+
|
85
|
+
errors = Validator.validate_obj(config,
|
86
|
+
schema,
|
87
|
+
path_prefix: at_path,
|
88
|
+
validators: @validators,
|
89
|
+
print: @exit_on_fail,
|
90
|
+
fatal: @exit_on_fail)
|
55
91
|
return nil if errors.any?
|
56
92
|
end
|
57
93
|
config
|
58
94
|
end
|
95
|
+
|
96
|
+
def extract_schema(config)
|
97
|
+
extract_special(config, @schema_sym) do |value|
|
98
|
+
case value
|
99
|
+
when String then value
|
100
|
+
else raise "Illegal value for a #{@schema_sym} element: #{value.inspect}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def extract_include(config)
|
106
|
+
extract_special(config, @include_sym) do |value|
|
107
|
+
case value
|
108
|
+
when Hash then value
|
109
|
+
when String then { 'file' => value }
|
110
|
+
else raise "Illegal value for a #{@include_sym} element: #{value.inspect}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def extract_special(config, key)
|
116
|
+
case config[key]
|
117
|
+
when nil then [config, []]
|
118
|
+
when Array then [config.reject { |k| k == key }, config[key].map { |e| yield e }]
|
119
|
+
else raise "Illegal value for #{key}: #{config[key].inspect}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def merge_at(config, at_path, to_merge)
|
124
|
+
return config.merge(to_merge) if at_path.empty?
|
125
|
+
head, *tail = at_path
|
126
|
+
config.merge(head => merge_at(config[head], tail, to_merge))
|
127
|
+
end
|
59
128
|
end
|
60
129
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Frise
|
4
|
+
class Loader
|
5
|
+
# A basic proxy object.
|
6
|
+
class Lazy < BasicObject
|
7
|
+
def initialize(&callable)
|
8
|
+
@callable = callable
|
9
|
+
end
|
10
|
+
|
11
|
+
def __target_object__
|
12
|
+
@__target_object__ ||= @callable.call
|
13
|
+
end
|
14
|
+
|
15
|
+
# rubocop:disable Style/MethodMissing
|
16
|
+
def method_missing(method_name, *args, &block)
|
17
|
+
__target_object__.send(method_name, *args, &block)
|
18
|
+
end
|
19
|
+
# rubocop:enable Style/MethodMissing
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/frise/parser.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'liquid'
|
2
4
|
require 'yaml'
|
3
5
|
|
@@ -9,9 +11,15 @@ module Frise
|
|
9
11
|
def parse(file, symbol_table = nil)
|
10
12
|
return nil unless File.file? file
|
11
13
|
content = File.open(file).read
|
12
|
-
content = Liquid::Template.parse(content).render symbol_table if symbol_table
|
14
|
+
content = Liquid::Template.parse(content).render with_internal_vars(file, symbol_table) if symbol_table
|
13
15
|
YAML.safe_load(content, [], [], true) || {}
|
14
16
|
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def with_internal_vars(file, symbol_table)
|
21
|
+
symbol_table.merge('_file_dir' => File.dirname(file))
|
22
|
+
end
|
15
23
|
end
|
16
24
|
end
|
17
25
|
end
|
data/lib/frise/validator.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'frise/parser'
|
4
5
|
require 'set'
|
@@ -164,32 +165,36 @@ module Frise
|
|
164
165
|
end
|
165
166
|
|
166
167
|
def self.validate_obj(config, schema, options = {})
|
167
|
-
|
168
|
-
|
168
|
+
validate_obj_at(config, [], schema, options)
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.validate_obj_at(config, at_path, schema, path_prefix: nil, validators: nil, print: nil, fatal: nil, raise_error: nil)
|
172
|
+
schema = parse_symbols(schema)
|
173
|
+
at_path.reverse.each { |key| schema = { key => schema, :allow_unknown_keys => true } }
|
174
|
+
|
175
|
+
validator = Validator.new(config, validators)
|
176
|
+
validator.validate_object((path_prefix || []).join('.'), config, schema)
|
169
177
|
|
170
178
|
if validator.errors.any?
|
171
|
-
if
|
179
|
+
if print
|
172
180
|
puts "#{validator.errors.length} config error(s) found:"
|
173
181
|
validator.errors.each do |error|
|
174
182
|
puts " - #{error}"
|
175
183
|
end
|
176
184
|
end
|
177
185
|
|
178
|
-
exit 1 if
|
179
|
-
raise ValidationError.new(validator.errors), 'Invalid configuration' if
|
186
|
+
exit 1 if fatal
|
187
|
+
raise ValidationError.new(validator.errors), 'Invalid configuration' if raise_error
|
180
188
|
end
|
181
189
|
validator.errors
|
182
190
|
end
|
183
191
|
|
184
192
|
def self.validate(config, schema_file, options = {})
|
185
|
-
|
186
|
-
validate_obj(config, schema, options)
|
193
|
+
validate_obj_at(config, [], Parser.parse(schema_file) || { allow_unknown_keys: true }, options)
|
187
194
|
end
|
188
195
|
|
189
196
|
def self.validate_at(config, at_path, schema_file, options = {})
|
190
|
-
|
191
|
-
at_path.reverse.each { |key| schema = { key => schema, :allow_unknown_keys => true } }
|
192
|
-
validate_obj(config, schema, options)
|
197
|
+
validate_obj_at(config, at_path, Parser.parse(schema_file) || { allow_unknown_keys: true }, options)
|
193
198
|
end
|
194
199
|
end
|
195
200
|
|
data/lib/frise/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: frise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ShiftForward
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: liquid
|
@@ -53,61 +53,61 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.8.21
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '12.3'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: '12.3'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '3.4'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '3.4'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rubocop
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 0.53.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 0.53.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: simplecov
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.
|
103
|
+
version: 0.14.1
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
110
|
+
version: 0.14.1
|
111
111
|
description:
|
112
112
|
email:
|
113
113
|
- info@shiftforward.eu
|
@@ -128,6 +128,7 @@ files:
|
|
128
128
|
- lib/frise.rb
|
129
129
|
- lib/frise/defaults_loader.rb
|
130
130
|
- lib/frise/loader.rb
|
131
|
+
- lib/frise/loader/lazy.rb
|
131
132
|
- lib/frise/parser.rb
|
132
133
|
- lib/frise/validator.rb
|
133
134
|
- lib/frise/version.rb
|
@@ -143,15 +144,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
144
|
requirements:
|
144
145
|
- - ">="
|
145
146
|
- !ruby/object:Gem::Version
|
146
|
-
version: 2.
|
147
|
+
version: 2.3.0
|
147
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
149
|
requirements:
|
149
|
-
- - "
|
150
|
+
- - ">"
|
150
151
|
- !ruby/object:Gem::Version
|
151
|
-
version:
|
152
|
+
version: 1.3.1
|
152
153
|
requirements: []
|
153
154
|
rubyforge_project:
|
154
|
-
rubygems_version: 2.6
|
155
|
+
rubygems_version: 2.7.6
|
155
156
|
signing_key:
|
156
157
|
specification_version: 4
|
157
158
|
summary: Ruby config library with schema validation, default values and templating
|