konfa 0.3.1 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '019c8e91eccb651e1797bd4f14936e7e993d90cf41da39315c0756a6f9edc337'
4
+ data.tar.gz: b9cd987595b57b4747dc147f565f91fa435669ca0b84db275f2f69ff5c6b9f41
5
+ SHA512:
6
+ metadata.gz: 28ec3dd4747fd0f64f2ea7cca123b014a31701d2667ada2240f2a5dbc319ba21321bf2e25d2dc92a85f2bc5246ca2fd5d9d9e1453daa26decc4e4a1d3099e713
7
+ data.tar.gz: 4d94c094df739eea1c0f90b82f0329f95cba20f2048500216a5eaafd6878c5841f575697c84f80196e15548b780f4861b92d43c5dc6a3398def760b0c5fae66a
@@ -1,29 +1,48 @@
1
- # -*- coding: utf-8 -*-
2
- require 'yaml'
1
+ require_relative File.join(File.dirname(__FILE__), 'konfa', 'initializer')
2
+ require_relative File.join(File.dirname(__FILE__), 'konfa', 'deprecation')
3
3
 
4
4
  module Konfa
5
5
  class Base
6
+ include Konfa::Initializer
7
+ include Konfa::Deprecation
8
+
6
9
  class << self
10
+
11
+ private
12
+
13
+ def default_values
14
+ self.allowed_variables.each do |key, value|
15
+ if !value.nil? && !value.kind_of?(String)
16
+ deprecated "[DEPRECATION] default value for #{key} will be automatically stringified in future versions"
17
+ end
18
+ end
19
+
20
+ self.allowed_variables
21
+ end
22
+
7
23
  protected
8
24
 
9
25
  #
10
- # The following methods are not a part of the public API. You may sublcass
26
+ # The following methods are not a part of the public API. You may subclass
11
27
  # them, but remember that unless you scope them as protected or private,
12
28
  # they will then be public
13
29
  #
14
30
 
15
- attr_writer :configuration, :deferred, :initialized_deferred
31
+ attr_writer :configuration, :initializer, :initialized
16
32
 
17
- def initialized_deferred
18
- @initialized_deferred ||= false
33
+ # [DEPRECATED] This method will be removed in favor of initialized? in Konfa 1.0
34
+ def initialized
35
+ @initialized ||= false
19
36
  end
20
37
 
21
38
  def configuration
22
- @configuration ||= self.allowed_variables
39
+ self.init
40
+ @configuration ||= default_values
23
41
  end
24
42
 
25
- def deferred
26
- @deferred ||= nil
43
+ # [DEPRECATED] This attribute will be removed in Konfa 1.0
44
+ def initializer
45
+ @initializer ||= nil
27
46
  end
28
47
 
29
48
  def truthy?(value)
@@ -39,11 +58,6 @@ module Konfa
39
58
  end
40
59
  end
41
60
 
42
- def do_deferred_initialization
43
- self.send(self.deferred.first, *self.deferred[1..-1])
44
- self.initialized_deferred = true
45
- end
46
-
47
61
  public
48
62
 
49
63
  #
@@ -63,20 +77,20 @@ module Konfa
63
77
  raise UnsupportedVariableError.new(key)
64
78
  end
65
79
 
66
- def do_deferred_initialization?
67
- !self.initialized_deferred && !self.deferred.nil?
68
- end
69
-
70
80
  #
71
81
  # The following methods provides the interface to this class
72
82
  #
73
83
 
74
84
  def get(variable)
75
- self.do_deferred_initialization if self.do_deferred_initialization?
76
85
  raise UnsupportedVariableError.new(variable) unless self.configuration.has_key? variable
77
86
  self.configuration[variable]
78
87
  end
79
88
 
89
+ def get!(variable)
90
+ raise NilVariableError.new(variable) if self.get(variable).nil?
91
+ self.get(variable)
92
+ end
93
+
80
94
  def true?(variable)
81
95
  self.truthy?(self.get(variable))
82
96
  end
@@ -93,8 +107,51 @@ module Konfa
93
107
  self.configuration.dup
94
108
  end
95
109
 
96
- def initialize_deferred(method, *args)
97
- self.deferred = [method, *args]
110
+ def init?
111
+ deprecated "[DEPRECATION] init? will be removed in Konfa 1.0, use initialized? instead"
112
+ !self.initialized && !self.initializer.nil?
113
+ end
114
+
115
+ def init
116
+ deprecated "[DEPRECATION] This style of initialization will no longer be supported in Konfa 1.0 and init "\
117
+ "will be removed. Use initialize! or read_from/initialized! instead"
118
+ return unless self.init?
119
+ # Set to true before calling to prevent recursion if
120
+ # an initializer is accessing the configuration
121
+ self.initialized = true
122
+ self.send(self.initializer.first, *self.initializer[1..-1])
123
+ self.after_initialize
124
+ end
125
+
126
+ def init_with(suffix, *args)
127
+ deprecated "[DEPRECATION] init will be removed in Konfa 1.0. Use read_from instead"
128
+ self.initializer = [:"init_with_#{suffix}", *args]
129
+ self
130
+ end
131
+
132
+ def reinit
133
+ deprecated "[DEPRECATION] reinit will be removed in Konfa 1.0. Use read_from to load multiple config files"
134
+ self.initialized = false
135
+ end
136
+
137
+ def read_from(initializer, *args)
138
+ raise AlreadyInitializedError if self.initialized?
139
+ raise UnsupportedInitializerError unless self.respond_to?(:"init_with_#{initializer}")
140
+
141
+ self.send(:"init_with_#{initializer}", *args)
142
+ self
143
+ end
144
+
145
+ def initialize!
146
+ raise AlreadyInitializedError if self.initialized?
147
+
148
+ @initialized = true
149
+ self.after_initialize
150
+ self
151
+ end
152
+
153
+ def initialized?
154
+ @initialized == true
98
155
  end
99
156
 
100
157
  def after_initialize
@@ -113,46 +170,11 @@ module Konfa
113
170
  result
114
171
  end
115
172
 
116
- # FIXME: Move out to external package
117
- def initialize_from_yaml(path)
118
- # FIXME: It would be a lot cleaner if the YAML library would raise an
119
- # exception if it fails to read the file. We'll handle it like this for now
120
- # load_file just returns "false" if it fails
121
- yaml_data = YAML.load_file(path)
122
-
123
- unless yaml_data.nil?
124
- raise InitializationError.new("Bad YAML format, key/value pairs expected") unless yaml_data.kind_of?(Hash)
125
-
126
- yaml_data.each do |variable, value|
127
- self.store(variable, value)
128
- end
129
- end
130
-
131
- after_initialize
132
- dump
133
- end
134
-
135
- # FIXME: Move out to external package
136
- def initialize_from_env
137
- conf_prefix = self.env_variable_prefix.upcase
138
-
139
- ENV.keys.reject { |key|
140
- key !~ /^#{conf_prefix}/ # Ignore everything that doesn't match the prefix
141
- }.each { |key|
142
- variable = key[conf_prefix.size..-1].downcase
143
-
144
- self.store(variable, ENV[key])
145
- }
146
-
147
- after_initialize
148
- dump
149
- end
150
173
  end
151
174
  end
152
175
 
153
- class InitializationError < StandardError
154
- end
155
-
156
- class UnsupportedVariableError < StandardError
157
- end
176
+ class UnsupportedInitializerError < StandardError; end
177
+ class AlreadyInitializedError < StandardError; end
178
+ class UnsupportedVariableError < StandardError; end
179
+ class NilVariableError < StandardError; end
158
180
  end
@@ -0,0 +1,8 @@
1
+ require 'konfa/autodoc/parser'
2
+ require 'konfa/autodoc/formatter'
3
+ require 'konfa/autodoc/markdown'
4
+
5
+ module Konfa
6
+ module AutoDoc
7
+ end
8
+ end
@@ -0,0 +1,24 @@
1
+ module Konfa
2
+ module AutoDoc
3
+ class Formatter
4
+ attr_reader :konfa_class
5
+ attr_accessor :version
6
+
7
+ def initialize(const, version=nil)
8
+ @konfa_class = const
9
+ @version = version
10
+ end
11
+
12
+ def generate
13
+ autodoc = Konfa::AutoDoc::Parser.new(@konfa_class)
14
+ format(autodoc.parse)
15
+ end
16
+
17
+ def format(variables)
18
+ raise ImplementationMissing.new
19
+ end
20
+
21
+ class ImplementationMissing < StandardError; end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ module Konfa
2
+ module AutoDoc
3
+ class Markdown < Formatter
4
+ def format(variables)
5
+ md_lines = [header(konfa_class.name)]
6
+ md_lines << "*Version: #{version}*" unless version.nil?
7
+
8
+ variables.each do |variable|
9
+ md_lines << header(variable.name, 2)
10
+ md_lines << "Default: *#{variable.default}*"
11
+ md_lines << variable.comment unless variable.comment.nil?
12
+ end
13
+
14
+ md_lines.join("\n\n")
15
+ end
16
+
17
+ private
18
+
19
+ def header(text, level=1)
20
+ "#{'#' * level} #{text}"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,66 @@
1
+ require "method_source"
2
+
3
+ module Konfa
4
+ module AutoDoc
5
+
6
+ Variable = Struct.new(:name, :default, :comment)
7
+
8
+ class Parser
9
+ attr_reader :variables, :konfa_class
10
+
11
+ def initialize(const)
12
+ @variables = []
13
+ @konfa_class = const
14
+ end
15
+
16
+ RE_VAR = /
17
+ (?:
18
+ :(\w+)\s*=> # 0: Old style hash key declaration - :key => 'value'
19
+ | # - or -
20
+ (\w+): # 1: New style hash key declaration - key: 'value'
21
+ )
22
+ \s*
23
+ (?:
24
+ (?:'|")(.+?)(?:'|") # 2: A string constant (FIXME: unless Backrefs to match leading and tailing quote)
25
+ | # - or -
26
+ ([\w\@\:\.]+) # 3: Bareword
27
+ )
28
+ \s*
29
+ ,? # - an optional comma -
30
+ \s*
31
+ (?:
32
+ \#\s*(.+?) # 4: An optional comment
33
+ (?=\n\s*(?: # Match all lines to next entry,
34
+ :\w+\s*=> # or end of hash declaraion. The lookahead
35
+ |\} # ensures we do not gobble up string for next match
36
+ |\w+:
37
+ ))
38
+ )?
39
+ /xm
40
+
41
+ def parse
42
+ @variables = []
43
+ code = @konfa_class.method(:allowed_variables).source
44
+ code.scan(RE_VAR).each do |tokens|
45
+ @variables << Variable.new(
46
+ tokens[0] || tokens[1],
47
+ tokens[2] || tokens[3],
48
+ trim_comment(tokens[4])
49
+ )
50
+ end
51
+
52
+ variables
53
+ end
54
+
55
+ private
56
+
57
+ def trim_comment(comment)
58
+ unless comment.nil?
59
+ comment.gsub!(/^\s*|\s*$/x, "") # The ^ and $ rather than \A and \Z anchors are intentional
60
+ comment.gsub!(/\n\#\s*/x, " ") # Not sure if we should perserve line breaks. We currenty do not. Can be fixed by using a zero width look-behind
61
+ end
62
+ comment
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,45 @@
1
+ module Konfa
2
+ module AutoDoc
3
+ module RSpec
4
+ shared_examples 'an Konfa::AutoDoc::Formatter subclass' do
5
+ let(:konfa_class) { double("KonfaClass") }
6
+
7
+ subject { described_class.new(konfa_class) }
8
+
9
+ it { is_expected.to be_kind_of Konfa::AutoDoc::Formatter }
10
+ it { is_expected.to respond_to :konfa_class }
11
+ it { is_expected.to respond_to :version }
12
+
13
+ it 'sets class as r/o accessor' do
14
+ expect(subject.konfa_class).to be konfa_class
15
+ end
16
+
17
+ it 'sets version as r/w accessor' do
18
+ expect(subject).to respond_to :version=
19
+ end
20
+
21
+ context '#generate' do
22
+ let(:autodoc_instance) { double }
23
+
24
+ before(:each) do
25
+ allow(Konfa::AutoDoc::Parser).to receive(:new).with(subject.konfa_class).and_return autodoc_instance
26
+ allow(subject).to receive(:format).and_return "something formatted"
27
+ allow(autodoc_instance).to receive(:parse).and_return "something parsed"
28
+ end
29
+
30
+ after(:each) do
31
+ subject.generate
32
+ end
33
+
34
+ it 'constructs a parser with konfa_class' do
35
+ expect(Konfa::AutoDoc::Parser).to receive(:new).with(subject.konfa_class).and_return autodoc_instance
36
+ end
37
+
38
+ it 'passes the parsed value to #format' do
39
+ expect(subject).to receive(:format).with("something parsed")
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ module Konfa
2
+ module Deprecation
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ @@deprecation_warnings = true
9
+
10
+ def deprecation_warnings=(val)
11
+ @@deprecation_warnings = val
12
+ end
13
+
14
+ def deprecation_warnings
15
+ @@deprecation_warnings
16
+ end
17
+
18
+ def deprecated(*args)
19
+ warn(*args) if @@deprecation_warnings
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ require 'yaml'
2
+
3
+ module Konfa
4
+ module Initializer
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def init_with_yaml(*paths)
11
+ paths.each do |path|
12
+ # FIXME: It would be a lot cleaner if the YAML library would raise an
13
+ # exception if it fails to read the file. We'll handle it like this for now
14
+ # load_file just returns "false" if it fails
15
+ yaml_data = YAML.load_file(path)
16
+
17
+ unless yaml_data.nil?
18
+ raise Konfa::InitializationError.new("Bad YAML format, key/value pairs expected") unless yaml_data.kind_of?(Hash)
19
+
20
+ yaml_data.each do |variable, value|
21
+ self.store(variable, value)
22
+ end
23
+ end
24
+ end
25
+
26
+ dump
27
+ end
28
+
29
+ def init_with_env
30
+ conf_prefix = self.env_variable_prefix.upcase
31
+
32
+ ENV.keys.reject { |key|
33
+ key !~ /^#{conf_prefix}/ # Ignore everything that doesn't match the prefix
34
+ }.each { |key|
35
+ variable = key[conf_prefix.size..-1].downcase
36
+
37
+ self.store(variable, ENV[key])
38
+ }
39
+
40
+ dump
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ class InitializationError < StandardError
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ module Konfa
2
+ module RSpec
3
+ shared_context 'with konfa' do |klass|
4
+ before {
5
+ @konfa_klass = klass
6
+ @konfa_stubbed_klasses = []
7
+ }
8
+
9
+ def let_config(variable, value, use_klass=@konfa_klass)
10
+ raise Konfa::UnsupportedVariableError.new(variable) unless use_klass.allowed_variables.has_key?(variable)
11
+ raise Konfa::RSpec::BadValueError.new(value) unless value.kind_of?(String) || value.kind_of?(NilClass)
12
+
13
+ unless @konfa_stubbed_klasses.include?(use_klass)
14
+ allow(use_klass).to receive(:get).and_call_original
15
+ @konfa_stubbed_klasses << use_klass
16
+ end
17
+
18
+ allow(use_klass).to receive(:get).with(variable).and_return(value)
19
+ end
20
+
21
+ def with_config(variables, use_klass=@konfa_klass)
22
+ variables.each_pair do |var, val|
23
+ let_config(var, val, use_klass)
24
+ end
25
+ end
26
+ end
27
+
28
+ class BadValueError < StandardError
29
+ def initialize(msg)
30
+ @type = msg.class.name
31
+ end
32
+
33
+ def to_s
34
+ "Konfa requires values to be of type String (or NilClass), you passed #{@type}"
35
+ end
36
+ end
37
+ end
38
+ end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: konfa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
5
- prerelease:
4
+ version: 0.5.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Gunnar Hansson
@@ -10,8 +9,64 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2014-11-06 00:00:00.000000000 Z
14
- dependencies: []
12
+ date: 2017-06-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: method_source
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.8'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.8'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '12.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '12.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.6'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.6'
56
+ - !ruby/object:Gem::Dependency
57
+ name: ruby_dep
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: 1.3.1
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 1.3.1
15
70
  description: Helps you avoid common pitfalls when dealing with app config
16
71
  email: code@avidiy.se
17
72
  executables: []
@@ -19,29 +74,35 @@ extensions: []
19
74
  extra_rdoc_files: []
20
75
  files:
21
76
  - lib/konfa.rb
22
- homepage: http://github.com/avidity/konfa
77
+ - lib/konfa/autodoc.rb
78
+ - lib/konfa/autodoc/formatter.rb
79
+ - lib/konfa/autodoc/markdown.rb
80
+ - lib/konfa/autodoc/parser.rb
81
+ - lib/konfa/autodoc/rspec.rb
82
+ - lib/konfa/deprecation.rb
83
+ - lib/konfa/initializer.rb
84
+ - lib/konfa/rspec.rb
85
+ homepage: http://github.com/promoteinternational/konfa
23
86
  licenses:
24
87
  - MIT
88
+ metadata: {}
25
89
  post_install_message:
26
90
  rdoc_options: []
27
91
  require_paths:
28
92
  - lib
29
93
  required_ruby_version: !ruby/object:Gem::Requirement
30
- none: false
31
94
  requirements:
32
- - - ! '>='
95
+ - - ">="
33
96
  - !ruby/object:Gem::Version
34
97
  version: 1.9.3
35
98
  required_rubygems_version: !ruby/object:Gem::Requirement
36
- none: false
37
99
  requirements:
38
- - - ! '>='
100
+ - - ">="
39
101
  - !ruby/object:Gem::Version
40
102
  version: '0'
41
103
  requirements: []
42
- rubyforge_project:
43
- rubygems_version: 1.8.23
104
+ rubygems_version: 3.0.3
44
105
  signing_key:
45
- specification_version: 3
106
+ specification_version: 4
46
107
  summary: Application configuration
47
108
  test_files: []