hanami-utils 2.0.0.alpha1 → 2.0.0.alpha2

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
  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