smart_initializer 0.1.0.alpha3 → 0.3.1

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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +36 -5
  4. data/CHANGELOG.md +19 -0
  5. data/Gemfile.lock +63 -43
  6. data/README.md +227 -11
  7. data/Rakefile +1 -1
  8. data/bin/rspec +54 -0
  9. data/gemfiles/with_external_deps.gemfile +7 -0
  10. data/gemfiles/with_external_deps.gemfile.lock +102 -0
  11. data/gemfiles/without_external_deps.gemfile +5 -0
  12. data/gemfiles/without_external_deps.gemfile.lock +100 -0
  13. data/lib/smart_core/initializer.rb +44 -34
  14. data/lib/smart_core/initializer/attribute.rb +12 -5
  15. data/lib/smart_core/initializer/attribute/factory.rb +47 -27
  16. data/lib/smart_core/initializer/attribute/parameters.rb +12 -4
  17. data/lib/smart_core/initializer/configuration.rb +33 -0
  18. data/lib/smart_core/initializer/constructor.rb +35 -8
  19. data/lib/smart_core/initializer/{attribute → constructor}/definer.rb +64 -12
  20. data/lib/smart_core/initializer/dsl.rb +49 -10
  21. data/lib/smart_core/initializer/dsl/inheritance.rb +1 -0
  22. data/lib/smart_core/initializer/errors.rb +44 -0
  23. data/lib/smart_core/initializer/extensions.rb +9 -0
  24. data/lib/smart_core/initializer/extensions/abstract.rb +8 -0
  25. data/lib/smart_core/initializer/extensions/ext_init.rb +31 -0
  26. data/lib/smart_core/initializer/extensions/list.rb +74 -0
  27. data/lib/smart_core/initializer/functionality.rb +36 -0
  28. data/lib/smart_core/initializer/instance_attribute_accessing.rb +51 -0
  29. data/lib/smart_core/initializer/plugins.rb +17 -0
  30. data/lib/smart_core/initializer/plugins/abstract.rb +55 -0
  31. data/lib/smart_core/initializer/plugins/access_mixin.rb +47 -0
  32. data/lib/smart_core/initializer/plugins/registry.rb +166 -0
  33. data/lib/smart_core/initializer/plugins/registry_interface.rb +77 -0
  34. data/lib/smart_core/initializer/plugins/thy_types.rb +30 -0
  35. data/lib/smart_core/initializer/plugins/thy_types/errors.rb +11 -0
  36. data/lib/smart_core/initializer/plugins/thy_types/thy_types.rb +23 -0
  37. data/lib/smart_core/initializer/plugins/thy_types/thy_types/abstract_factory.rb +78 -0
  38. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation.rb +12 -0
  39. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/base.rb +9 -0
  40. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/cast.rb +21 -0
  41. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/valid.rb +16 -0
  42. data/lib/smart_core/initializer/plugins/thy_types/thy_types/operation/validate.rb +19 -0
  43. data/lib/smart_core/initializer/settings.rb +49 -0
  44. data/lib/smart_core/initializer/settings/duplicator.rb +20 -0
  45. data/lib/smart_core/initializer/settings/type_system.rb +69 -0
  46. data/lib/smart_core/initializer/type_system.rb +16 -0
  47. data/lib/smart_core/initializer/type_system/interop.rb +103 -0
  48. data/lib/smart_core/initializer/type_system/interop/abstract_factory.rb +70 -0
  49. data/lib/smart_core/initializer/type_system/interop/aliasing.rb +72 -0
  50. data/lib/smart_core/initializer/type_system/interop/aliasing/alias_list.rb +141 -0
  51. data/lib/smart_core/initializer/type_system/interop/operation.rb +30 -0
  52. data/lib/smart_core/initializer/type_system/registry.rb +174 -0
  53. data/lib/smart_core/initializer/type_system/registry_interface.rb +102 -0
  54. data/lib/smart_core/initializer/type_system/smart_types.rb +48 -0
  55. data/lib/smart_core/initializer/type_system/smart_types/abstract_factory.rb +72 -0
  56. data/lib/smart_core/initializer/type_system/smart_types/operation.rb +13 -0
  57. data/lib/smart_core/initializer/type_system/smart_types/operation/base.rb +8 -0
  58. data/lib/smart_core/initializer/type_system/smart_types/operation/cast.rb +16 -0
  59. data/lib/smart_core/initializer/type_system/smart_types/operation/valid.rb +16 -0
  60. data/lib/smart_core/initializer/type_system/smart_types/operation/validate.rb +16 -0
  61. data/lib/smart_core/initializer/version.rb +2 -1
  62. data/smart_initializer.gemspec +13 -9
  63. metadata +73 -17
  64. data/lib/smart_core/initializer/type_aliasing.rb +0 -50
  65. data/lib/smart_core/initializer/type_aliasing/alias_list.rb +0 -101
@@ -13,6 +13,7 @@ module SmartCore::Initializer::DSL::Inheritance
13
13
  def inherit(base:, child:)
14
14
  child.__params__.concat(base.__params__)
15
15
  child.__options__.concat(base.__options__)
16
+ child.__init_extensions__.concat(base.__init_extensions__)
16
17
  end
17
18
  end
18
19
  end
@@ -32,4 +32,48 @@ module SmartCore::Initializer
32
32
  # @api public
33
33
  # @since 0.1.0
34
34
  NoTypeAliasError = Class.new(Error)
35
+
36
+ # @api public
37
+ # @since 0.1.0
38
+ PluginError = Class.new(Error)
39
+
40
+ # @api public
41
+ # @since 0.1.0
42
+ UnresolvedPluginDependencyError = Class.new(PluginError)
43
+
44
+ # @api public
45
+ # @since 0.1.0
46
+ AlreadyRegisteredPluginError = Class.new(PluginError)
47
+
48
+ # @api public
49
+ # @since 0.1.0
50
+ UnregisteredPluginError = Class.new(PluginError)
51
+
52
+ # @api public
53
+ # @since 0.1.0
54
+ TypeSystemError = Class.new(Error)
55
+
56
+ # @api public
57
+ # @since 0.1.0
58
+ TypeAliasNotFoundError = Class.new(TypeSystemError)
59
+
60
+ # @api public
61
+ # @since 0.1.0
62
+ IncorrectTypeSystemInteropError = Class.new(TypeSystemError)
63
+
64
+ # @api public
65
+ # @since 0.1.0
66
+ IncorrectTypeObjectError = Class.new(TypeSystemError)
67
+
68
+ # @api public
69
+ # @since 0.1.0
70
+ UnsupportedTypeSystemError = Class.new(TypeSystemError)
71
+
72
+ # @api public
73
+ # @since 0.1.0
74
+ UnsupportedTypeOperationError = Class.new(TypeSystemError)
75
+
76
+ # @api public
77
+ # @since 0.1.0
78
+ TypeCastingUnsupportedError = Class.new(UnsupportedTypeOperationError)
35
79
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Initializer::Extensions
6
+ require_relative 'extensions/abstract'
7
+ require_relative 'extensions/ext_init'
8
+ require_relative 'extensions/list'
9
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Extensions::Abstract
6
+ # @!method dup
7
+ # @return [SmartCore::Initializer::Extensions::Abstract]
8
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Extensions::ExtInit < SmartCore::Initializer::Extensions::Abstract
6
+ # @param extender [Proc]
7
+ # @return [void]
8
+ #
9
+ # @api private
10
+ # @since 0.1.0
11
+ def initialize(extender)
12
+ @extender = extender
13
+ end
14
+
15
+ # @param instance [Any]
16
+ # @return [void]
17
+ #
18
+ # @api private
19
+ # @since 0.1.0
20
+ def call(instance)
21
+ extender.call(instance)
22
+ end
23
+
24
+ private
25
+
26
+ # @return [Proc]
27
+ #
28
+ # @api private
29
+ # @since0 0.1.0
30
+ attr_reader :extender
31
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Extensions::List
6
+ # @since 0.1.0
7
+ include Enumerable
8
+
9
+ # @return [void]
10
+ #
11
+ # @api private
12
+ # @since 0.1.0
13
+ def initialize
14
+ @extensions = []
15
+ @lock = SmartCore::Engine::Lock.new
16
+ end
17
+
18
+ # @param extension [SmartCore::Initializer::Extensions::Abstract]
19
+ # @return [void]
20
+ #
21
+ # @api private
22
+ # @since 0.1.0
23
+ def add(extension)
24
+ thread_safe { extensions << extension }
25
+ end
26
+ alias_method :<<, :add
27
+
28
+ # @param list [SmartCore::Initializer::Extensions::List]
29
+ # @return [void]
30
+ #
31
+ # @api private
32
+ # @since 0.1.0
33
+ def concat(list)
34
+ thread_safe do
35
+ list.each { |extension| add(extension.dup) }
36
+ end
37
+ end
38
+
39
+ # @param block [Block]
40
+ # @return [Enumerable]
41
+ #
42
+ # @api private
43
+ # @since 0.1.0
44
+ def each(&block)
45
+ thread_safe do
46
+ block_given? ? extensions.each(&block) : extensions.each
47
+ end
48
+ end
49
+
50
+ # @return [Integer]
51
+ #
52
+ # @api private
53
+ # @since 0.1.0
54
+ def size
55
+ thread_safe { extensions.size }
56
+ end
57
+
58
+ private
59
+
60
+ # @return [Array<SmartCore::Initializer::Extensions::Abstract>]
61
+ #
62
+ # @api private
63
+ # @since 0.1.0
64
+ attr_reader :extensions
65
+
66
+ # @param block [Block]
67
+ # @return [Any]
68
+ #
69
+ # @api private
70
+ # @since 0.1.0
71
+ def thread_safe(&block)
72
+ @lock.synchronize(&block)
73
+ end
74
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.3.0
5
+ module SmartCore::Initializer::Functionality
6
+ # @return [NilClass]
7
+ #
8
+ # @api private
9
+ # @since 0.3.0
10
+ INITIAL_TYPE_SYSTEM = nil
11
+
12
+ class << self
13
+ # @option type_system [String, Symbol, NilClass]
14
+ # @return [Module]
15
+ #
16
+ # @api private
17
+ # @since 0.3.0
18
+ def includable_module(type_system: INITIAL_TYPE_SYSTEM)
19
+ Module.new.tap do |extension|
20
+ extension.singleton_class.define_method(:included) do |base_klass|
21
+ base_klass.include(::SmartCore::Initializer)
22
+ base_klass.__initializer_settings__.type_system = type_system
23
+ end
24
+ end
25
+ end
26
+
27
+ # @param base_klass [Class]
28
+ # @return [void]
29
+ #
30
+ # @api private
31
+ # @since 0.3.0
32
+ def seed_to(base_klass)
33
+ base_klass.extend(SmartCore::Initializer::DSL)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.3.0
5
+ module SmartCore::Initializer::InstanceAttributeAccessing
6
+ # @return [Hash<Symbol,Any>]
7
+ #
8
+ # @api public
9
+ # @since 0.3.0
10
+ def __params__
11
+ __collect_params__
12
+ end
13
+
14
+ # @return [Hash<Symbol,Any>]
15
+ #
16
+ # @api public
17
+ # @since 0.3.0
18
+ def __options__
19
+ __collect_options__
20
+ end
21
+
22
+ # @return [Hash<Symbol,Any>]
23
+ #
24
+ # @api public
25
+ # @since 0.3.0
26
+ def __attributes__
27
+ __collect_params__.merge(__collect_options__)
28
+ end
29
+
30
+ private
31
+
32
+ # @return [Hash<Symbol,Any>]
33
+ #
34
+ # @api private
35
+ # @since 0.3.0
36
+ def __collect_params__
37
+ self.class.__params__.each_with_object({}) do |param, memo|
38
+ memo[param.name] = instance_variable_get("@#{param.name}")
39
+ end
40
+ end
41
+
42
+ # @return [Hash<Symbol,Any>]
43
+ #
44
+ # @api private
45
+ # @since 0.3.0
46
+ def __collect_options__
47
+ self.class.__options__.each_with_object({}) do |option, memo|
48
+ memo[option.name] = instance_variable_get("@#{option.name}")
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Initializer::Plugins
6
+ require_relative 'plugins/abstract'
7
+ require_relative 'plugins/registry'
8
+ require_relative 'plugins/registry_interface.rb'
9
+ require_relative 'plugins/access_mixin'
10
+ require_relative 'plugins/thy_types'
11
+
12
+ # @since 0.1.0
13
+ extend SmartCore::Initializer::Plugins::RegistryInterface
14
+
15
+ # @since 0.1.0
16
+ register_plugin('thy_types', SmartCore::Initializer::Plugins::ThyTypes)
17
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Plugins::Abstract
6
+ class << self
7
+ # @param child_klass [Class]
8
+ # @return [void]
9
+ #
10
+ # @api private
11
+ # @since 0.1.0
12
+ def inherited(child_klass)
13
+ child_klass.instance_variable_set(:@__loaded__, false)
14
+ child_klass.instance_variable_set(:@__lock__, Mutex.new)
15
+ super
16
+ end
17
+
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 0.1.0
22
+ def load!
23
+ __thread_safe__ do
24
+ unless @__loaded__
25
+ @__loaded__ = true
26
+ install!
27
+ end
28
+ end
29
+ end
30
+
31
+ # @return [Boolean]
32
+ #
33
+ # @api private
34
+ # @since 0.1.0
35
+ def loaded?
36
+ __thread_safe__ { @__loaded__ }
37
+ end
38
+
39
+ private
40
+
41
+ # @return [void]
42
+ #
43
+ # @api private
44
+ # @since 0.1.0
45
+ def install!; end
46
+
47
+ # @return [Any]
48
+ #
49
+ # @api private
50
+ # @since 0.1.0
51
+ def __thread_safe__
52
+ @__lock__.synchronize { yield }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Initializer::Plugins::AccessMixin
6
+ # @param plugin_name [Symbol, String]
7
+ # @return [void]
8
+ #
9
+ # @see SmartCore::Initializer::Plugins
10
+ #
11
+ # @api public
12
+ # @since 0.1.0
13
+ def plugin(plugin_name)
14
+ SmartCore::Initializer::Plugins.load(plugin_name)
15
+ end
16
+
17
+ # @return [Array<String>]
18
+ #
19
+ # @see SmartCore::Initializer::Plugins
20
+ #
21
+ # @api public
22
+ # @since 0.1.0
23
+ def plugins
24
+ SmartCore::Initializer::Plugins.names
25
+ end
26
+
27
+ # @return [Hash<String,Class<SmartCore::Initializer::Plugins::Abstract>>]
28
+ #
29
+ # @api private
30
+ # @since 0.1.0
31
+ def loaded_plugins
32
+ SmartCore::Initializer::Plugins.loaded_plugins
33
+ end
34
+ alias_method :enabled_plugins, :loaded_plugins
35
+
36
+ # @param plugin_name [String, Symbol]
37
+ # @param plugin_klass [Class<SmartCore::Initializer::Plugins::Abstract>]
38
+ # @return [void]
39
+ #
40
+ # @see SmartCore::Initializer::Plugins
41
+ #
42
+ # @api public
43
+ # @since 0.1.0
44
+ def register_plugin(plugin_name, plugin_klass)
45
+ SmartCore::Initializer::Plugins.register_plugin(plugin_name, plugin_klass)
46
+ end
47
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Initializer::Plugins::Registry
6
+ # @since 0.1.0
7
+ include Enumerable
8
+
9
+ # @return [void]
10
+ #
11
+ # @api private
12
+ # @since 0.1.0
13
+ def initialize
14
+ @plugin_set = {}
15
+ @access_lock = Mutex.new
16
+ end
17
+
18
+ # @param plugin_name [Symbol, String]
19
+ # @return [SmartCore::Initializer::Plugins::Abstract]
20
+ #
21
+ # @api private
22
+ # @since 0.1.0
23
+ def [](plugin_name)
24
+ thread_safe { fetch(plugin_name) }
25
+ end
26
+
27
+ # @param plugin_name [Symbol, String]
28
+ # @param plugin_module [SmartCore::Initializer::Plugins::Abstract]
29
+ # @return [void]
30
+ #
31
+ # @api private
32
+ # @since 0.1.0
33
+ def register(plugin_name, plugin_module)
34
+ thread_safe { apply(plugin_name, plugin_module) }
35
+ end
36
+ alias_method :[]=, :register
37
+
38
+ # @return [Array<String>]
39
+ #
40
+ # @api private
41
+ # @since 0.1.0
42
+ def names
43
+ thread_safe { plugin_names }
44
+ end
45
+
46
+ # @return [Hash<String,Class<SmartCore::Initializer::Plugins::Abstract>>]
47
+ #
48
+ # @api private
49
+ # @since 0.1.0
50
+ def loaded
51
+ thread_safe { loaded_plugins }
52
+ end
53
+
54
+ # @param block [Block]
55
+ # @return [Enumerable]
56
+ #
57
+ # @api private
58
+ # @since 0.1.0
59
+ def each(&block)
60
+ thread_safe { iterate(&block) }
61
+ end
62
+
63
+ private
64
+
65
+ # @return [Hash]
66
+ #
67
+ # @api private
68
+ # @since 0.1.0
69
+ attr_reader :plugin_set
70
+
71
+ # @return [Mutex]
72
+ #
73
+ # @api private
74
+ # @since 0.1.0
75
+ attr_reader :access_lock
76
+
77
+ # @return [void]
78
+ #
79
+ # @api private
80
+ # @since 0.1.0
81
+ def thread_safe
82
+ access_lock.synchronize { yield if block_given? }
83
+ end
84
+
85
+ # @return [Array<String>]
86
+ #
87
+ # @api private
88
+ # @since 0.1.0
89
+ def plugin_names
90
+ plugin_set.keys
91
+ end
92
+
93
+ # @param block [Block]
94
+ # @return [Enumerable]
95
+ #
96
+ # @api private
97
+ # @since 0.1.0
98
+ def iterate(&block)
99
+ block_given? ? plugin_set.each_pair(&block) : plugin_set.each_pair
100
+ end
101
+
102
+ # @param plugin_name [String]
103
+ # @return [Boolean]
104
+ #
105
+ # @api private
106
+ # @since 0.1.0
107
+ def registered?(plugin_name)
108
+ plugin_set.key?(plugin_name)
109
+ end
110
+
111
+ # @return [Array<SmartCore::Initializer::Plugins::Abstract>]
112
+ #
113
+ # @api private
114
+ # @since 0.1.0
115
+ def loaded_plugins
116
+ plugin_set.select { |_plugin_name, plugin_module| plugin_module.loaded? }
117
+ end
118
+
119
+ # @param plugin_name [Symbol, String]
120
+ # @param plugin_module [SmartCore::Initializer::Plugins::Abstract]
121
+ # @return [void]
122
+ #
123
+ # @raise [SmartCore::Initializer::AlreadyRegisteredPluginError]
124
+ #
125
+ # @api private
126
+ # @since 0.1.0
127
+ def apply(plugin_name, plugin_module)
128
+ plugin_name = indifferently_accessible_plugin_name(plugin_name)
129
+
130
+ if registered?(plugin_name)
131
+ raise(SmartCore::Initializer::AlreadyRegisteredPluginError, <<~ERROR_MESSAGE)
132
+ #{plugin_name} plugin already exists
133
+ ERROR_MESSAGE
134
+ end
135
+
136
+ plugin_set[plugin_name] = plugin_module
137
+ end
138
+
139
+ # @param plugin_name [Symbol, String]
140
+ # @return [SmartCore::Initializer::Plugins::Abstract]
141
+ #
142
+ # @raise [SmartCore::Initializer::UnregisteredPluginError]
143
+ #
144
+ # @api private
145
+ # @since 0.1.0
146
+ def fetch(plugin_name)
147
+ plugin_name = indifferently_accessible_plugin_name(plugin_name)
148
+
149
+ unless registered?(plugin_name)
150
+ raise(SmartCore::Initializer::UnregisteredPluginError, <<~ERROR_MESSAGE)
151
+ #{plugin_name} plugin is not registered
152
+ ERROR_MESSAGE
153
+ end
154
+
155
+ plugin_set[plugin_name]
156
+ end
157
+
158
+ # @param key [Symbol, String]
159
+ # @return [String]
160
+ #
161
+ # @api private
162
+ # @since 0.1.0
163
+ def indifferently_accessible_plugin_name(plugin_name)
164
+ plugin_name.to_s
165
+ end
166
+ end