dry-core 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f18461caed54954ed1ded7991e22481fb2460f54
4
- data.tar.gz: 6f14a3398ad397e64db754967b4315a440b225f1
3
+ metadata.gz: 67a852de7314c5546f3d556d5f814270b1f4bd41
4
+ data.tar.gz: 8f34325aacc8019f2203c9486abdddacccaa4be1
5
5
  SHA512:
6
- metadata.gz: b68b62a1b7bceb698b669c9462c4bfded77dd1536dbcaaa201c76c34414df3d28e85042e106d2809ad118caabbd8ce84a4e5d09da835cf03dfa7f1f53ea7cda7
7
- data.tar.gz: 0960b20d7483027f61502c64c0c06d69f37bca79c90f6bc4aedc190328bf9d354ca323c17e34a28a281f9cf27b59b6acd6c51fb0d7f36089fb1665d9103257e2
6
+ metadata.gz: 4c8b853aecef987b247b614ddc828c94bf403660fd38b751f5f12042b5984049a7971df2c82e4de7c176d2655c91964366ca2fbb8285875478d48c586f051831
7
+ data.tar.gz: 6afcac12f9ad38b5fea9d069b48b6a6488c757cbb0c791833eb24298d35e0d3346544c1a84fba14149ea83aeae88cfc6af94719b6268cf95f9ecbdbbe81b444f
@@ -1,17 +1,18 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.1.9
4
+ - 2.1.10
5
5
  - 2.2.5
6
6
  - 2.3.1
7
- - rbx-2
8
7
  - jruby-9.1.4.0
9
8
  - ruby-head
9
+ - rbx
10
10
 
11
11
  before_install: gem update bundler
12
12
  matrix:
13
13
  allow_failures:
14
14
  - rvm: ruby-head
15
+ - rvm: rbx
15
16
  notifications:
16
17
  email:
17
18
  recipients:
@@ -25,4 +26,3 @@ notifications:
25
26
  on_success: change # options: [always|never|change] default: always
26
27
  on_failure: always # options: [always|never|change] default: always
27
28
  on_start: false # default: false
28
-
data/Gemfile CHANGED
@@ -3,6 +3,8 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :test do
6
+ gem 'activesupport', '~> 4.2'
7
+ gem 'inflecto', '~> 0.0', '>= 0.0.2'
6
8
  gem 'codeclimate-test-reporter', require: false
7
9
  gem 'simplecov', require: false
8
10
  end
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.bindir = 'exe'
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ['lib']
28
+ spec.required_ruby_version = '>= 2.1.0'
28
29
  spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
29
30
 
30
31
  spec.add_development_dependency 'bundler', '~> 1.12'
@@ -1 +1 @@
1
- require 'dry-core'
1
+ require 'dry/core'
@@ -29,16 +29,17 @@ module Dry
29
29
  # Prints a warning
30
30
  #
31
31
  # @param [String] msg Warning string
32
- def warn(msg)
33
- logger.warn(msg.gsub(/^\s+/, ''))
32
+ def warn(msg, tag: nil)
33
+ tagged = "[#{tag || 'deprecated'}] #{msg.gsub(/^\s+/, '')}"
34
+ logger.warn(tagged)
34
35
  end
35
36
 
36
37
  # Wraps arguments with a standard message format and prints a warning
37
38
  #
38
39
  # @param [Object] name what is deprecated
39
40
  # @param [String] msg additional message usually containing upgrade instructions
40
- def announce(name, msg)
41
- warn(deprecation_message(name, msg))
41
+ def announce(name, msg, tag: nil)
42
+ warn(deprecation_message(name, msg), tag: tag)
42
43
  end
43
44
 
44
45
  # @api private
@@ -72,83 +73,116 @@ module Dry
72
73
  # Returns the logger used for printing warnings.
73
74
  # You can provide your own with .set_logger!
74
75
  #
75
- # @param [String, Symbol] tag optional prefix for messages
76
76
  # @param [IO] output output stream
77
77
  #
78
78
  # @return [Logger]
79
- def logger(tag = nil, output = nil)
79
+ def logger(output = nil)
80
80
  if defined?(@logger)
81
81
  @logger
82
82
  else
83
- set_logger!(output: output, tag: tag)
83
+ set_logger!(output)
84
84
  end
85
85
  end
86
86
 
87
87
  # Sets a custom logger. This is a global settings.
88
88
  #
89
89
  # @option [IO] output output stream for messages
90
- # @option [String, Symbol] tag optional prefix
91
- #
92
- # TODO: Add support for per-module loggers so that at least
93
- # tag option won't conflict.
94
- def set_logger!(output: nil, tag: nil)
90
+ def set_logger!(output = nil)
95
91
  @logger = Logger.new(output || $stdout)
96
- @logger.formatter = proc { |_severity, _datetime, _progname, msg|
97
- "[#{tag || 'deprecated'}] #{msg}\n"
98
- }
92
+ @logger.formatter = proc { |_severity, _datetime, _progname, msg| "#{msg}\n" }
99
93
  @logger
100
94
  end
95
+
96
+ def [](tag)
97
+ Tagged.new(tag)
98
+ end
99
+ end
100
+
101
+ # @api private
102
+ class Tagged < Module
103
+ def initialize(tag)
104
+ @tag = tag
105
+ end
106
+
107
+ def extended(base)
108
+ base.extend Interface
109
+ base.deprecation_tag @tag
110
+ end
101
111
  end
102
112
 
103
- # Mark instance method as deprecated
104
- #
105
- # @param [Symbol] old_name deprecated method
106
- # @param [Symbol] new_name replacement (not required)
107
- # @option [String] message optional deprecation message
108
- def deprecate(old_name, new_name = nil, message: nil)
109
- full_msg = Deprecations.deprecated_method_message(
110
- "#{self.name}##{old_name}",
111
- new_name ? "#{self.name}##{new_name}" : nil,
112
- message
113
- )
114
-
115
- if new_name
116
- undef_method old_name
117
- define_method(old_name) do |*args, &block|
118
- Deprecations.warn(full_msg)
119
- __send__(new_name, *args, &block)
113
+ module Interface
114
+ # Sets/gets deprecation tag
115
+ #
116
+ # @option [String,Symbol] tag tag
117
+ def deprecation_tag(tag = nil)
118
+ if defined?(@deprecation_tag)
119
+ @deprecation_tag
120
+ else
121
+ @deprecation_tag = tag
120
122
  end
121
- else
122
- aliased_name = :"#{old_name}_without_deprecation"
123
- alias_method aliased_name, old_name
124
- private aliased_name
125
- undef_method old_name
126
- define_method(old_name) do |*args, &block|
127
- Deprecations.warn(full_msg)
128
- __send__(aliased_name, *args, &block)
123
+ end
124
+
125
+ # Issue a tagged warning message
126
+ #
127
+ # @param [String] msg warning message
128
+ def warn(msg)
129
+ Deprecations.warn(msg, tag: deprecation_tag)
130
+ end
131
+
132
+ # Mark instance method as deprecated
133
+ #
134
+ # @param [Symbol] old_name deprecated method
135
+ # @param [Symbol] new_name replacement (not required)
136
+ # @option [String] message optional deprecation message
137
+ def deprecate(old_name, new_name = nil, message: nil)
138
+ full_msg = Deprecations.deprecated_method_message(
139
+ "#{self.name}##{old_name}",
140
+ new_name ? "#{self.name}##{new_name}" : nil,
141
+ message
142
+ )
143
+ mod = self
144
+
145
+ if new_name
146
+ undef_method old_name
147
+
148
+ define_method(old_name) do |*args, &block|
149
+ mod.warn(full_msg)
150
+ __send__(new_name, *args, &block)
151
+ end
152
+ else
153
+ aliased_name = :"#{old_name}_without_deprecation"
154
+ alias_method aliased_name, old_name
155
+ private aliased_name
156
+ undef_method old_name
157
+
158
+ define_method(old_name) do |*args, &block|
159
+ mod.warn(full_msg)
160
+ __send__(aliased_name, *args, &block)
161
+ end
129
162
  end
130
163
  end
131
- end
132
164
 
133
- # Mark class-level method as deprecated
134
- #
135
- # @param [Symbol] old_name deprecated method
136
- # @param [Symbol] new_name replacement (not required)
137
- # @option [String] message optional deprecation message
138
- def deprecate_class_method(old_name, new_name = nil, message: nil)
139
- full_msg = Deprecations.deprecated_method_message(
140
- "#{self.name}.#{old_name}",
141
- new_name ? "#{self.name}.#{new_name}" : nil,
142
- message
143
- )
144
-
145
- meth = new_name ? method(new_name) : method(old_name)
146
-
147
- singleton_class.instance_exec do
148
- undef_method old_name
149
- define_method(old_name) do |*args, &block|
150
- Deprecations.warn(full_msg)
151
- meth.call(*args, &block)
165
+ # Mark class-level method as deprecated
166
+ #
167
+ # @param [Symbol] old_name deprecated method
168
+ # @param [Symbol] new_name replacement (not required)
169
+ # @option [String] message optional deprecation message
170
+ def deprecate_class_method(old_name, new_name = nil, message: nil)
171
+ full_msg = Deprecations.deprecated_method_message(
172
+ "#{self.name}.#{old_name}",
173
+ new_name ? "#{self.name}.#{new_name}" : nil,
174
+ message
175
+ )
176
+
177
+ meth = new_name ? method(new_name) : method(old_name)
178
+
179
+ singleton_class.instance_exec do
180
+ undef_method old_name
181
+
182
+ define_method(old_name) do |*args, &block|
183
+ warn(full_msg)
184
+ meth.call(*args, &block)
185
+ end
152
186
  end
153
187
  end
154
188
  end
@@ -34,6 +34,14 @@ module Dry
34
34
  @__available_extensions__[name] = block
35
35
  end
36
36
 
37
+ # Whether an extension is available
38
+ #
39
+ # @param [Symbol] name extension name
40
+ # @return [Boolean] Extension availability
41
+ def available_extension?(name)
42
+ @__available_extensions__.key?(name)
43
+ end
44
+
37
45
  # Enables specified extensions. Already enabled extensions remain untouched
38
46
  #
39
47
  # @param [Array<Symbol>] extensions list of extension names
@@ -0,0 +1,134 @@
1
+ module Dry
2
+ module Core
3
+ # Helper module providing thin interface around an inflection backend.
4
+ module Inflector
5
+ # List of supported backends
6
+ BACKENDS = {
7
+ activesupport: [
8
+ 'active_support/inflector',
9
+ proc { ::ActiveSupport::Inflector }
10
+ ],
11
+ inflecto: [
12
+ 'inflecto',
13
+ proc { ::Inflecto }
14
+ ]
15
+ }.freeze
16
+
17
+ # Try to activate a backend
18
+ #
19
+ # @api private
20
+ def self.realize_backend(path, backend_factory)
21
+ require path
22
+ rescue LoadError
23
+ nil
24
+ else
25
+ backend_factory.call
26
+ end
27
+
28
+ # Set up first available backend
29
+ #
30
+ # @api private
31
+ def self.detect_backend
32
+ BACKENDS.inject(nil) do |backend, (_, (path, factory))|
33
+ backend || realize_backend(path, factory)
34
+ end || raise(LoadError,
35
+ "No inflector library could be found: "\
36
+ "please install either the `inflecto` or `activesupport` gem.")
37
+ end
38
+
39
+ # Set preferred backend
40
+ #
41
+ # @param [Symbol] name backend name (:activesupport or :inflecto)
42
+ def self.select_backend(name = nil)
43
+ if name && !BACKENDS.key?(name)
44
+ raise NameError, "Invalid inflector library selection: '#{name}'"
45
+ end
46
+ @inflector = name ? realize_backend(*BACKENDS[name]) : detect_backend
47
+ end
48
+
49
+ # Inflector accessor. Lazily initializes a backend
50
+ #
51
+ # @api private
52
+ def self.inflector
53
+ defined?(@inflector) ? @inflector : select_backend
54
+ end
55
+
56
+ # Transform string to camel case
57
+ #
58
+ # @example
59
+ # Dry::Core::Inflector.camelize('foo_bar') # => 'FooBar'
60
+ #
61
+ # @param [String] input input string
62
+ # @return Transformed string
63
+ def self.camelize(input)
64
+ inflector.camelize(input)
65
+ end
66
+
67
+ # Transform string to snake case
68
+ #
69
+ # @example
70
+ # Dry::Core::Inflector.underscore('FooBar') # => 'foo_bar'
71
+ #
72
+ # @param [String] input input string
73
+ # @return Transformed string
74
+ def self.underscore(input)
75
+ inflector.underscore(input)
76
+ end
77
+
78
+ # Get a singlular form of a word
79
+ #
80
+ # @example
81
+ # Dry::Core::Inflector.singularize('chars') # => 'char'
82
+ #
83
+ # @param [String] input input string
84
+ # @return Transformed string
85
+ def self.singularize(input)
86
+ inflector.singularize(input)
87
+ end
88
+
89
+ # Get a plural form of a word
90
+ #
91
+ # @example
92
+ # Dry::Core::Inflector.pluralize('string') # => 'strings'
93
+ #
94
+ # @param [String] input input string
95
+ # @return Transformed string
96
+ def self.pluralize(input)
97
+ inflector.pluralize(input)
98
+ end
99
+
100
+ # Remove namespaces from a constant name
101
+ #
102
+ # @example
103
+ # Dry::Core::Inflector.demodulize('Deeply::Nested::Name') # => 'Name'
104
+ #
105
+ # @param [String] input input string
106
+ # @return Unnested constant name
107
+ def self.demodulize(input)
108
+ inflector.demodulize(input)
109
+ end
110
+
111
+ # Get a constant value by its name
112
+ #
113
+ # @example
114
+ # Dry::Core::Inflector.constantize('Foo::Bar') # => Foo::Bar
115
+ #
116
+ # @param [String] input input constant name
117
+ # @return Constant value
118
+ def self.constantize(input)
119
+ inflector.constantize(input)
120
+ end
121
+
122
+ # Transform a file path to a constant name
123
+ #
124
+ # @example
125
+ # Dry::Core::Inflector.classify('foo/bar') # => 'Foo::Bar'
126
+ #
127
+ # @param [String] input input string
128
+ # @return Constant name
129
+ def self.classify(input)
130
+ inflector.classify(input)
131
+ end
132
+ end
133
+ end
134
+ end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Core
3
- VERSION = '0.1.0'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nikita Shilnikov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-17 00:00:00.000000000 Z
11
+ date: 2016-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -90,6 +90,7 @@ files:
90
90
  - lib/dry/core/constants.rb
91
91
  - lib/dry/core/deprecations.rb
92
92
  - lib/dry/core/extensions.rb
93
+ - lib/dry/core/inflector.rb
93
94
  - lib/dry/core/version.rb
94
95
  homepage: https://github.com/dry-rb/dry-code
95
96
  licenses:
@@ -104,7 +105,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
104
105
  requirements:
105
106
  - - ">="
106
107
  - !ruby/object:Gem::Version
107
- version: '0'
108
+ version: 2.1.0
108
109
  required_rubygems_version: !ruby/object:Gem::Requirement
109
110
  requirements:
110
111
  - - ">="