hanami-utils 2.0.0.alpha1 → 2.0.0.alpha2

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
2
  SHA256:
3
- metadata.gz: 2d4523d52299280469a80451592c55d5771aeaf8e0f93644291f5e9d7a66237a
4
- data.tar.gz: 27c144da73fcbd992b4fefdddb9dc1b5be1e58b5abff3fd4078c67f8ec561d43
3
+ metadata.gz: c8c15a181f268ff9117c181bfccc23c3fb63f31cbe38590f2d0b9f925e0fa9d1
4
+ data.tar.gz: bfdcc4baf599cd58adeb870ef700d705ec4cc58fdb58377f0028db177b3c431d
5
5
  SHA512:
6
- metadata.gz: e0e48686597a78927e05bff5da29e0ba0db65f8a03796b36046bb6f84cf35bf964662a87a73bad88bca47096b2b51e737bee0b0545f7341cbbd3579c4e74d4bf
7
- data.tar.gz: ebf2deed3ccf571a88ffd151d544254d483f65f26c5bf027c78cbe31220b22afc6b0c9f5b7a6223dd685c553b41fb80c2fe4a7b2a3629d4ab1cdfc5f9293e038
6
+ metadata.gz: 3099871c8e61b12217e0c9d5d2a5668daddcaf8d439190c2fb1a356a2b92d02859a1f258ba8b7517b3be8b3685664be1dd68676ecb7ae5f7f809e3a5371d1182
7
+ data.tar.gz: 3a7b06f9f9c7eda2f716f9e0fc77a9e4a97f5a5e6e6137b7dd6eb1e77b4f57a48249a364ea6a35712753582de244bc81e7978ac4c95bde7b2d8c86566a07c3c5
data/CHANGELOG.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # Hanami::Utils
2
2
  Ruby core extentions and class utilities for Hanami
3
3
 
4
+ ## v2.0.0.alpha2 - 2021-05-04
5
+ ### Changed
6
+ - [Luca Guidi] Drop support for Ruby: MRI 2.5.
7
+ - [Luca Guidi] Transform `Utils::String` from class to module
8
+
4
9
  ## v2.0.0.alpha1 - 2019-01-30
5
10
  ### Added
6
11
  - [Gustavo Caso] Introduce `Hanami::Middleware` namespace
@@ -18,6 +23,42 @@ Ruby core extentions and class utilities for Hanami
18
23
  - [Gustavo Caso] Remove `Utils::File.rewrite`
19
24
  - [Vladimir Suvorov] Remove `Utils::Class.load_from_pattern!`
20
25
 
26
+ ## v1.3.8 - 2021-05-03
27
+ ### Fixed
28
+ - [Hiếu Nguyễn] Ensure `Hanami::Interactor#initialize` to accept keyword arguments while working with Ruby 3
29
+
30
+ ## v1.3.7 - 2021-01-04
31
+ ### Added
32
+ - [Luca Guidi] Official support for Ruby: MRI 3.0
33
+ - [Khai Le] Allow `Hanami::Logger` to filter sensitive data for an array of hashes
34
+
35
+ ### Fixed
36
+ - [Hiếu Nguyễn] Ensure `Hanami::Logger` to not mutate `Hash` input when filtering sensitive data
37
+
38
+ ## v1.3.6 - 2020-01-07
39
+ ### Added
40
+ - [Luca Guidi] Official support for Ruby: MRI 2.7
41
+
42
+ ### Fixed
43
+ - [ippachi] `Utils::Files.append`: don't check breakline if file is empty
44
+
45
+ ## v1.3.5 - 2019-10-25
46
+ ### Fixed
47
+ - [Ivan Kabluchkov] Ensure `Hanami::Logger` filters to not crash when logger stream is a closed tempfile
48
+ - [Luca Guidi] Ensure `Utils::Files.append` to append contents properly when existing file doesn't end with a newline
49
+
50
+ ## v1.3.4 - 2019-09-27
51
+ ### Added
52
+ - [Luca Guidi] Let `Utils::BasicObject` to lookup constants at the top-level namespace
53
+
54
+ ## v1.3.3 - 2019-09-13
55
+ ### Fixed
56
+ - [Mauro Morales] Ensure `Utils::Inflector.pluralize` and `.singularize` to work with words that contain an underscore (`_`)
57
+
58
+ ## v1.3.2 - 2019-06-21
59
+ ### Added
60
+ - [Vladislav Yashin & Luca Guidi] Added `Utils::BasicObject#instance_of?`, `#is_a?`, and `#kind_of`
61
+
21
62
  ## v1.3.1 - 2019-01-18
22
63
  ### Added
23
64
  - [Luca Guidi] Official support for Ruby: MRI 2.6
data/README.md CHANGED
@@ -5,9 +5,8 @@ Ruby core extensions and class utilities for [Hanami](http://hanamirb.org)
5
5
  ## Status
6
6
 
7
7
  [![Gem Version](https://badge.fury.io/rb/hanami-utils.svg)](https://badge.fury.io/rb/hanami-utils)
8
- [![TravisCI](https://travis-ci.org/hanami/utils.svg?branch=master)](https://travis-ci.org/hanami/utils)
9
- [![CircleCI](https://circleci.com/gh/hanami/utils/tree/master.svg?style=svg)](https://circleci.com/gh/hanami/utils/tree/master)
10
- [![Test Coverage](https://codecov.io/gh/hanami/utils/branch/master/graph/badge.svg)](https://codecov.io/gh/hanami/utils)
8
+ [![CI](https://github.com/hanami/utils/workflows/ci/badge.svg?branch=unstable)](https://github.com/hanami/utils/actions?query=workflow%3Aci+branch%3Aunstable)
9
+ [![Test Coverage](https://codecov.io/gh/hanami/utils/branch/unstable/graph/badge.svg)](https://codecov.io/gh/hanami/utils)
11
10
  [![Depfu](https://badges.depfu.com/badges/a8545fb67cf32a2c75b6227bc0821027/overview.svg)](https://depfu.com/github/hanami/utils?project=Bundler)
12
11
  [![Inline Docs](http://inch-ci.org/github/hanami/utils.svg)](http://inch-ci.org/github/hanami/utils)
13
12
 
@@ -22,7 +21,7 @@ Ruby core extensions and class utilities for [Hanami](http://hanamirb.org)
22
21
 
23
22
  ## Rubies
24
23
 
25
- __Hanami::Utils__ supports Ruby (MRI) 2.5+
24
+ __Hanami::Utils__ supports Ruby (MRI) 2.6+
26
25
 
27
26
  ## Installation
28
27
 
@@ -141,6 +140,6 @@ __Hanami::Utils__ uses [Semantic Versioning 2.0.0](http://semver.org)
141
140
 
142
141
  ## Copyright
143
142
 
144
- Copyright © 2014-2019 Luca Guidi – Released under MIT License
143
+ Copyright © 2014-2021 Luca Guidi – Released under MIT License
145
144
 
146
145
  This project was formerly known as Lotus (`lotus-utils`).
data/hanami-utils.gemspec CHANGED
@@ -18,12 +18,13 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
- spec.required_ruby_version = ">= 2.5.0"
21
+ spec.required_ruby_version = ">= 2.6.0"
22
22
 
23
- spec.add_dependency "transproc", "~> 1.0"
23
+ spec.add_dependency "dry-transformer", "~> 0.1"
24
24
  spec.add_dependency "concurrent-ruby", "~> 1.0"
25
25
 
26
26
  spec.add_development_dependency "bundler", ">= 1.6", "< 3"
27
- spec.add_development_dependency "rake", "~> 12"
28
- spec.add_development_dependency "rspec", "~> 3.7"
27
+ spec.add_development_dependency "rake", "~> 13"
28
+ spec.add_development_dependency "rspec", "~> 3.9"
29
+ spec.add_development_dependency "rubocop", "0.91"
29
30
  end
@@ -19,14 +19,14 @@ module Hanami
19
19
  # @api private
20
20
  #
21
21
  # @see Hanami::Interactor::Result#respond_to_missing?
22
- METHODS = ::Hash[initialize: true,
23
- success?: true,
22
+ METHODS = ::Hash[initialize: true,
23
+ success?: true,
24
24
  successful?: true,
25
- failure?: true,
26
- fail!: true,
27
- prepare!: true,
28
- errors: true,
29
- error: true].freeze
25
+ failure?: true,
26
+ fail!: true,
27
+ prepare!: true,
28
+ errors: true,
29
+ error: true].freeze
30
30
 
31
31
  # Initialize a new result
32
32
  #
@@ -42,7 +42,7 @@ module Hanami
42
42
  @success = true
43
43
  end
44
44
 
45
- # Check if the current status is successful
45
+ # Checks if the current status is successful
46
46
  #
47
47
  # @return [TrueClass,FalseClass] the result of the check
48
48
  #
@@ -52,9 +52,9 @@ module Hanami
52
52
  end
53
53
 
54
54
  # @since 0.3.5
55
- alias success? successful?
55
+ alias_method :success?, :successful?
56
56
 
57
- # Check if the current status is not successful
57
+ # Checks if the current status is not successful
58
58
  #
59
59
  # @return [TrueClass,FalseClass] the result of the check
60
60
  #
@@ -63,7 +63,7 @@ module Hanami
63
63
  !successful?
64
64
  end
65
65
 
66
- # Force the status to be a failure
66
+ # Forces the status to be a failure
67
67
  #
68
68
  # @since 0.3.5
69
69
  def fail!
@@ -106,7 +106,7 @@ module Hanami
106
106
  errors.first
107
107
  end
108
108
 
109
- # Prepare the result before to be returned
109
+ # Prepares the result before to be returned
110
110
  #
111
111
  # @param payload [Hash] an updated payload
112
112
  #
@@ -181,10 +181,18 @@ module Hanami
181
181
  # # ...
182
182
  # end
183
183
  # end
184
- def initialize(*args)
185
- super
186
- ensure
187
- @__result = ::Hanami::Interactor::Result.new
184
+ if RUBY_VERSION >= "3.0"
185
+ def initialize(*args, **kwargs)
186
+ super
187
+ ensure
188
+ @__result = ::Hanami::Interactor::Result.new
189
+ end
190
+ else
191
+ def initialize(*args)
192
+ super
193
+ ensure
194
+ @__result = ::Hanami::Interactor::Result.new
195
+ end
188
196
  end
189
197
 
190
198
  # Triggers the operation and return a result.
@@ -353,33 +361,57 @@ module Hanami
353
361
  # end
354
362
  #
355
363
  # Signup.new.call # => NoMethodError
356
- def call(*args)
357
- @__result = ::Hanami::Interactor::Result.new
358
- _call(*args) { super }
364
+ if RUBY_VERSION >= "3.0"
365
+ def call(*args, **kwargs)
366
+ @__result = ::Hanami::Interactor::Result.new
367
+ _call(*args, **kwargs) { super }
368
+ end
369
+ else
370
+ def call(*args)
371
+ @__result = ::Hanami::Interactor::Result.new
372
+ _call(*args) { super }
373
+ end
359
374
  end
360
375
 
361
376
  private
362
377
 
363
378
  # @api private
364
379
  # @since 1.1.0
365
- def _call(*args)
366
- catch :fail do
367
- validate!(*args)
368
- yield
380
+ if RUBY_VERSION >= "3.0"
381
+ def _call(*args, **kwargs)
382
+ catch :fail do
383
+ validate!(*args, **kwargs)
384
+ yield
385
+ end
386
+
387
+ _prepare!
369
388
  end
389
+ else
390
+ def _call(*args)
391
+ catch :fail do
392
+ validate!(*args)
393
+ yield
394
+ end
370
395
 
371
- _prepare!
396
+ _prepare!
397
+ end
372
398
  end
373
399
 
374
400
  # @since 1.1.0
375
- def validate!(*args)
376
- fail! unless valid?(*args)
401
+ if RUBY_VERSION >= "3.0"
402
+ def validate!(*args, **kwargs)
403
+ fail! unless valid?(*args, **kwargs)
404
+ end
405
+ else
406
+ def validate!(*args)
407
+ fail! unless valid?(*args)
408
+ end
377
409
  end
378
410
  end
379
411
 
380
412
  private
381
413
 
382
- # Check if proceed with <tt>#call</tt> invokation.
414
+ # Checks if proceed with <tt>#call</tt> invocation.
383
415
  # By default it returns <tt>true</tt>.
384
416
  #
385
417
  # Developers can override it.
@@ -391,7 +423,7 @@ module Hanami
391
423
  true
392
424
  end
393
425
 
394
- # Fail and interrupt the current flow.
426
+ # Fails and interrupts the current flow.
395
427
  #
396
428
  # @since 0.3.5
397
429
  #
@@ -430,7 +462,7 @@ module Hanami
430
462
  throw :fail
431
463
  end
432
464
 
433
- # Log an error without interrupting the flow.
465
+ # Logs an error without interrupting the flow.
434
466
  #
435
467
  # When used, the returned result won't be successful.
436
468
  #
@@ -485,7 +517,7 @@ module Hanami
485
517
  false
486
518
  end
487
519
 
488
- # Log an error AND interrupting the flow.
520
+ # Logs an error and interrupts the flow.
489
521
  #
490
522
  # When used, the returned result won't be successful.
491
523
  #
@@ -581,7 +613,7 @@ module Hanami
581
613
  end
582
614
  end
583
615
 
584
- # Expose local instance variables into the returning value of <tt>#call</tt>
616
+ # Exposes local instance variables into the returning value of <tt>#call</tt>
585
617
  #
586
618
  # @param instance_variable_names [Symbol,Array<Symbol>] one or more instance
587
619
  # variable names
@@ -590,7 +622,7 @@ module Hanami
590
622
  #
591
623
  # @see Hanami::Interactor::Result
592
624
  #
593
- # @example Expose instance variable
625
+ # @example Exposes instance variable
594
626
  #
595
627
  # class Signup
596
628
  # include Hanami::Interactor
data/lib/hanami/logger.rb CHANGED
@@ -7,7 +7,7 @@ require "hanami/utils/files"
7
7
  module Hanami
8
8
  # Hanami logger
9
9
  #
10
- # Implement with the same interface of Ruby std lib `Logger`.
10
+ # Implementation with the same interface of Ruby std lib `Logger`.
11
11
  # It uses `STDOUT`, `STDERR`, file name or open file as output stream.
12
12
  #
13
13
  #
@@ -16,7 +16,7 @@ module Hanami
16
16
  #
17
17
  # This is useful for auto-tagging the output. Eg (`app=Booshelf`).
18
18
  #
19
- # When used stand alone (eg. `Hanami::Logger.info`), it tags lines with `app=Shared`.
19
+ # When used standalone (eg. `Hanami::Logger.info`), it tags lines with `app=Shared`.
20
20
  #
21
21
  #
22
22
  # The available severity levels are the same of `Logger`:
@@ -30,7 +30,7 @@ module Hanami
30
30
  #
31
31
  # Those levels are available both as class and instance methods.
32
32
  #
33
- # Also Hanami::Logger support different formatters. Now available only two:
33
+ # Also Hanami::Logger supports different formatters. Now available only two:
34
34
  #
35
35
  # * Formatter (default)
36
36
  # * JSONFormatter
@@ -132,11 +132,11 @@ module Hanami
132
132
  # @since 0.8.0
133
133
  # @api private
134
134
  LEVELS = ::Hash[
135
- "debug" => DEBUG,
136
- "info" => INFO,
137
- "warn" => WARN,
138
- "error" => ERROR,
139
- "fatal" => FATAL,
135
+ "debug" => DEBUG,
136
+ "info" => INFO,
137
+ "warn" => WARN,
138
+ "error" => ERROR,
139
+ "fatal" => FATAL,
140
140
  "unknown" => UNKNOWN
141
141
  ].freeze
142
142
 
@@ -279,9 +279,9 @@ module Hanami
279
279
  # logger.info "Hello World"
280
280
  #
281
281
  # # => {"app":"Hanami","severity":"DEBUG","time":"2017-03-30T13:57:59Z","message":"Hello World"}
282
- # rubocop:disable Lint/HandleExceptions
282
+ # rubocop:disable Lint/SuppressedException
283
283
  # rubocop:disable Metrics/ParameterLists
284
- def initialize(application_name = nil, *args, stream: $stdout, level: DEBUG, formatter: nil, filter: [], colorizer: nil)
284
+ def initialize(application_name = nil, *args, stream: $stdout, level: DEBUG, formatter: nil, filter: [], colorizer: nil) # rubocop:disable Layout/LineLength
285
285
  begin
286
286
  Utils::Files.mkdir_p(stream)
287
287
  rescue TypeError
@@ -296,7 +296,7 @@ module Hanami
296
296
  end
297
297
 
298
298
  # rubocop:enable Metrics/ParameterLists
299
- # rubocop:enable Lint/HandleExceptions
299
+ # rubocop:enable Lint/SuppressedException
300
300
 
301
301
  # Returns the current application name, this is used for tagging purposes
302
302
  #
@@ -313,11 +313,11 @@ module Hanami
313
313
  super _level(value)
314
314
  end
315
315
 
316
- # Close the logging stream if this stream isn't an STDOUT
316
+ # Closes the logging stream if this stream isn't an STDOUT
317
317
  #
318
318
  # @since 0.8.0
319
319
  def close
320
- super unless [STDOUT, $stdout].include?(@stream)
320
+ super unless [STDOUT, $stdout].include?(@stream) # rubocop:disable Style/GlobalStdStream
321
321
  end
322
322
 
323
323
  private
@@ -14,9 +14,9 @@ module Hanami
14
14
  # @api private
15
15
  def call(app, severity, datetime, _progname)
16
16
  ::Hash[
17
- app: app,
17
+ app: app,
18
18
  severity: severity,
19
- time: datetime,
19
+ time: datetime,
20
20
  ]
21
21
  end
22
22
  end
@@ -44,9 +44,9 @@ module Hanami
44
44
  # @return [::Hash] an Hash containing the keys `:app`, `:severity`, and `:time`
45
45
  def call(app, severity, datetime, _progname)
46
46
  ::Hash[
47
- app: app(app),
47
+ app: app(app),
48
48
  severity: severity(severity),
49
- time: datetime(datetime),
49
+ time: datetime(datetime),
50
50
  ]
51
51
  end
52
52
 
@@ -57,18 +57,18 @@ module Hanami
57
57
  # @since 1.2.0
58
58
  # @api private
59
59
  COLORS = ::Hash[
60
- app: :blue,
60
+ app: :blue,
61
61
  datetime: :cyan,
62
62
  ].freeze
63
63
 
64
64
  # @since 1.2.0
65
65
  # @api private
66
66
  LEVELS = ::Hash[
67
- Hanami::Logger::DEBUG => :cyan,
68
- Hanami::Logger::INFO => :magenta,
69
- Hanami::Logger::WARN => :yellow,
70
- Hanami::Logger::ERROR => :red,
71
- Hanami::Logger::FATAL => :red,
67
+ Hanami::Logger::DEBUG => :cyan,
68
+ Hanami::Logger::INFO => :magenta,
69
+ Hanami::Logger::WARN => :yellow,
70
+ Hanami::Logger::ERROR => :red,
71
+ Hanami::Logger::FATAL => :red,
72
72
  Hanami::Logger::UNKNOWN => :blue,
73
73
  ].freeze
74
74
 
@@ -9,21 +9,19 @@ module Hanami
9
9
  # @since 1.1.0
10
10
  # @api private
11
11
  class Filter
12
- # @since 1.1.0
12
+ # @since 1.3.7
13
13
  # @api private
14
- def initialize(filters = [])
14
+ FILTERED_VALUE = "[FILTERED]"
15
+
16
+ def initialize(filters = [], mask: FILTERED_VALUE)
15
17
  @filters = filters
18
+ @mask = mask
16
19
  end
17
20
 
18
21
  # @since 1.1.0
19
22
  # @api private
20
- def call(hash)
21
- _filtered_keys(hash).each do |key|
22
- *keys, last = _actual_keys(hash, key.split("."))
23
- keys.inject(hash, :fetch)[last] = "[FILTERED]"
24
- end
25
-
26
- hash
23
+ def call(params)
24
+ _filter(_copy_params(params))
27
25
  end
28
26
 
29
27
  private
@@ -32,6 +30,29 @@ module Hanami
32
30
  # @api private
33
31
  attr_reader :filters
34
32
 
33
+ # @since 1.3.7
34
+ # @api private
35
+ attr_reader :mask
36
+
37
+ # This is a simple deep merge to merge the original input
38
+ # with the filtered hash which contains '[FILTERED]' string.
39
+ #
40
+ # It only deep-merges if the conflict values are both hashes.
41
+ #
42
+ # @since 1.3.7
43
+ # @api private
44
+ def _deep_merge(original_hash, filtered_hash)
45
+ original_hash.merge(filtered_hash) do |_key, original_item, filtered_item|
46
+ if original_item.is_a?(Hash) && filtered_item.is_a?(Hash)
47
+ _deep_merge(original_item, filtered_item)
48
+ elsif filtered_item == FILTERED_VALUE
49
+ filtered_item
50
+ else
51
+ original_item
52
+ end
53
+ end
54
+ end
55
+
35
56
  # @since 1.1.0
36
57
  # @api private
37
58
  def _filtered_keys(hash)
@@ -42,7 +63,7 @@ module Hanami
42
63
  # @api private
43
64
  def _key_paths(hash, base = nil)
44
65
  hash.inject([]) do |results, (k, v)|
45
- results + (v.respond_to?(:each) ? _key_paths(v, _build_path(base, k)) : [_build_path(base, k)])
66
+ results + (_key_paths?(v) ? _key_paths(v, _build_path(base, k)) : [_build_path(base, k)])
46
67
  end
47
68
  end
48
69
 
@@ -63,6 +84,61 @@ module Hanami
63
84
  res + [correct_key]
64
85
  end
65
86
  end
87
+
88
+ # Check if the given value can be iterated (`Enumerable`) and that isn't a `File`.
89
+ # This is useful to detect closed `Tempfiles`.
90
+ #
91
+ # @since 1.3.5
92
+ # @api private
93
+ #
94
+ # @see https://github.com/hanami/utils/pull/342
95
+ def _key_paths?(value)
96
+ value.is_a?(Enumerable) && !value.is_a?(File)
97
+ end
98
+
99
+ # @since 1.3.7
100
+ # @api private
101
+ def _deep_dup(hash)
102
+ hash.transform_values do |value|
103
+ if value.is_a?(Hash)
104
+ _deep_dup(value)
105
+ else
106
+ _key_paths?(value) ? value.dup : value
107
+ end
108
+ end
109
+ end
110
+
111
+ # @since 1.3.7
112
+ # @api private
113
+ def _copy_params(params)
114
+ case params
115
+ when Hash
116
+ _deep_dup(params)
117
+ when Array
118
+ params.map { |hash| _deep_dup(hash) }
119
+ end
120
+ end
121
+
122
+ # @since 1.3.7
123
+ # @api private
124
+ def _filter_hash(hash)
125
+ _filtered_keys(hash).each do |key|
126
+ *keys, last = _actual_keys(hash, key.split("."))
127
+ keys.inject(hash, :fetch)[last] = mask
128
+ end
129
+ hash
130
+ end
131
+
132
+ # @since 1.3.7
133
+ # @api private
134
+ def _filter(params)
135
+ case params
136
+ when Hash
137
+ _filter_hash(params)
138
+ when Array
139
+ params.map { |hash| _filter_hash(hash) }
140
+ end
141
+ end
66
142
  end
67
143
  end
68
144
  end