frise 0.2.0 → 0.3.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 658ef151a4948ba72f32f7dc5b51f5ddb3e6fb69
4
- data.tar.gz: 8b7498f11685e3c5d1a4bbce70c732d8a62e8eb6
2
+ SHA256:
3
+ metadata.gz: 72db98e097cb7abccf1a1208a53efa9a2486d49d3f58422a70e6f32ac7cbb2a8
4
+ data.tar.gz: 52f15d4c10262d54dc7534fa35c16abb66ad33d0498ceff612cc78124154fcf4
5
5
  SHA512:
6
- metadata.gz: 998d82e9c1a58efb14b5edd44deb4c85c62ced21cec664f29cffa3753f3742fc9e876fad96c9c3902fa2fc6a55d57622695bfe579acb6abb246695f8f7fe8b91
7
- data.tar.gz: f1a5e4ee436e6081a93fd204cfd7ee434aeb3d6ada5e90853f42467cf6339ca8a6c4dbc0b8d4b335d4e1d75e211e965736f84010cc3ffb31e6c37b668fafce9c
6
+ metadata.gz: 75b318b997eb2ab66dada979b270e468430ca372982d035bba4de12a68a0622f6897d928e173b67d7e046be2ecdee0d7b1374e0a0d50da55e80354d60285eb9f
7
+ data.tar.gz: b25a7625181eaf4d90f202ca0aa9dc9095ada98318272c2d5c999beb8ea28e0e7af397b1612692bd18709a59dca4cab758d30ee515563806d6def511500243e7
@@ -1,2 +1,8 @@
1
+ AllCops:
2
+ TargetRubyVersion: '2.3'
1
3
  Metrics:
2
4
  Enabled: false
5
+ Naming/UncommunicativeBlockParamName:
6
+ Enabled: false
7
+ Naming/UncommunicativeMethodParamName:
8
+ Enabled: false
@@ -1,6 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1
4
- - 2.2
5
3
  - 2.3
6
4
  - 2.4
5
+ - 2.5
@@ -1,4 +1,4 @@
1
- ### 0.2.0 (unreleased)
1
+ ### 0.2.0 (August 17, 2017)
2
2
 
3
3
  - New features
4
4
  - New schema types `$enum` and `$one_of` for specifying enumerations and values with multiple
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in frise.gemspec
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
 
3
5
  def load_if_available(req_path)
@@ -1,6 +1,6 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
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.1.0'
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 'simplecov', '~> 0.14.1'
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.49.1'
29
+ spec.add_development_dependency 'rubocop', '~> 0.53.0'
30
+ spec.add_development_dependency 'simplecov', '~> 0.14.1'
31
31
  end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'frise/defaults_loader'
4
+ require 'frise/loader/lazy'
2
5
  require 'frise/loader'
3
6
  require 'frise/parser'
4
7
  require 'frise/validator'
@@ -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 key.start_with?('$')
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?
@@ -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 it with the applicable defaults and validates
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(schema_load_paths: [], defaults_load_paths: [], pre_loaders: [], validators: nil)
12
- @schema_load_paths = schema_load_paths
13
- @defaults_load_paths = defaults_load_paths
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, exit_on_fail = true, symbol_table = {})
19
- config = Parser.parse(config_file, symbol_table) || {}
20
- config_name = File.basename(config_file)
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 = merge_defaults(config, config_name, symbol_table)
27
- validate(config, config_name, exit_on_fail)
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
- def merge_defaults(config, defaults_name, symbol_table = {})
31
- merge_defaults_at(config, [], defaults_name, symbol_table)
32
- end
34
+ private
33
35
 
34
- def merge_defaults_at(config, at_path, defaults_name, symbol_table = {})
35
- @defaults_load_paths.map do |defaults_dir|
36
- defaults_file = File.join(defaults_dir, defaults_name)
37
- config = DefaultsLoader.merge_defaults_at(
38
- config, at_path, defaults_file, symbol_table.merge(config)
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 validate(config, schema_name, exit_on_fail = true)
45
- validate_at(config, [], schema_name, exit_on_fail)
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 validate_at(config, at_path, schema_name, exit_on_fail = true)
49
- @schema_load_paths.map do |schema_dir|
50
- schema_file = File.join(schema_dir, schema_name)
51
- errors = Validator.validate_at(config, at_path, schema_file,
52
- validators: @validators,
53
- print: exit_on_fail,
54
- fatal: exit_on_fail)
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
@@ -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
@@ -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
- validator = Validator.new(config, options[:validators])
168
- validator.validate_object('', config, schema)
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 options[:print]
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 options[:fatal]
179
- raise ValidationError.new(validator.errors), 'Invalid configuration' if options[:raise_error]
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
- schema = parse_symbols(Parser.parse(schema_file) || { allow_unknown_keys: true })
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
- schema = parse_symbols(Parser.parse(schema_file) || { allow_unknown_keys: true })
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
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Frise
2
- VERSION = '0.2.0'.freeze
4
+ VERSION = '0.3.0.pre'
3
5
  end
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.2.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: 2017-08-17 00:00:00.000000000 Z
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: simplecov
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.14.1
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: 0.14.1
68
+ version: '12.3'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rake
70
+ name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '10.0'
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: '10.0'
82
+ version: '3.4'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rspec
84
+ name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.4'
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: '3.4'
96
+ version: 0.53.0
97
97
  - !ruby/object:Gem::Dependency
98
- name: rubocop
98
+ name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.49.1
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.49.1
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.1.0
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: '0'
152
+ version: 1.3.1
152
153
  requirements: []
153
154
  rubyforge_project:
154
- rubygems_version: 2.6.11
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