hanami-utils 1.3.2 → 1.3.7

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: ab3141a4fd9052c6472d5bfd820eca5be30a9be7e3f8c7a8c5039ca14ff8a44e
4
- data.tar.gz: c6b7581c887b4c7dafe0834a5ee045eaef17d1ed9a82aeffd5e6de2c995093d6
3
+ metadata.gz: '02818d90409ea03d89ca587c97fe418bbf17a8694662a2313609c0710466b0f9'
4
+ data.tar.gz: 973ef420992dd9ea30ab880d43e8cc70eee59cae6fb7b1ba17038c5ce8d536a4
5
5
  SHA512:
6
- metadata.gz: e05b9c87e1e3206ba379a7f4d09fcae6602049d36548306ccec1abf89f7a2e2271ab995e2afa9702411062f3fd0f2e13e1bcdcd69868a63e05517fc36bf1c020
7
- data.tar.gz: 55e117ed1367cdd8791531e42b7da858641a6e36f24cd5d440371e006a704ffa53dd0e01d352e306dd6be1eedb4ba0ffd728228e01dfab0a9de9e6e3814cbd04
6
+ metadata.gz: d49d6ad21aa25f285c9165c4619d6b2d7fe348513481bf30b8f231211d4e270f7502e2e3594f082789fdf32e9170a33e038329394ae5f43170ab778ebe01892f
7
+ data.tar.gz: 8b8832a39855525d6818de385212fb1c9d7c5c0f79874f60ead95ee1c592377f6bfec0ade5701a4340b87fe920c495889a9586d81fe2091d8691b52b14f297fa
@@ -1,6 +1,34 @@
1
1
  # Hanami::Utils
2
2
  Ruby core extentions and class utilities for Hanami
3
3
 
4
+ ## v1.3.7 - 2021-01-04
5
+ ### Added
6
+ - [Luca Guidi] Official support for Ruby: MRI 3.0
7
+ - [Khai Le] Allow `Hanami::Logger` to filter sensitive data for an array of hashes
8
+
9
+ ### Fixed
10
+ - [Hiếu Nguyễn] Ensure `Hanami::Logger` to not mutate `Hash` input when filtering sensitive data
11
+
12
+ ## v1.3.6 - 2020-01-07
13
+ ### Added
14
+ - [Luca Guidi] Official support for Ruby: MRI 2.7
15
+
16
+ ### Fixed
17
+ - [ippachi] `Utils::Files.append`: don't check breakline if file is empty
18
+
19
+ ## v1.3.5 - 2019-10-25
20
+ ### Fixed
21
+ - [Ivan Kabluchkov] Ensure `Hanami::Logger` filters to not crash when logger stream is a closed tempfile
22
+ - [Luca Guidi] Ensure `Utils::Files.append` to append contents properly when existing file doesn't end with a newline
23
+
24
+ ## v1.3.4 - 2019-09-27
25
+ ### Added
26
+ - [Luca Guidi] Let `Utils::BasicObject` to lookup constants at the top-level namespace
27
+
28
+ ## v1.3.3 - 2019-09-13
29
+ ### Fixed
30
+ - [Mauro Morales] Ensure `Utils::Inflector.pluralize` and `.singularize` to work with words that contain an underscore (`_`)
31
+
4
32
  ## v1.3.2 - 2019-06-21
5
33
  ### Added
6
34
  - [Vladislav Yashin & Luca Guidi] Added `Utils::BasicObject#instance_of?`, `#is_a?`, and `#kind_of`
data/README.md CHANGED
@@ -5,8 +5,7 @@ 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)
8
+ [![CI](https://github.com/hanami/utils/workflows/ci/badge.svg?branch=master)](https://github.com/hanami/utils/actions?query=workflow%3Aci+branch%3Amaster)
10
9
  [![Test Coverage](https://codecov.io/gh/hanami/utils/branch/master/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)
@@ -150,6 +149,6 @@ __Hanami::Utils__ uses [Semantic Versioning 2.0.0](http://semver.org)
150
149
 
151
150
  ## Copyright
152
151
 
153
- Copyright © 2014-2017 Luca Guidi – Released under MIT License
152
+ Copyright © 2014-2021 Luca Guidi – Released under MIT License
154
153
 
155
154
  This project was formerly known as Lotus (`lotus-utils`).
@@ -1,27 +1,30 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'hanami/utils/version'
5
+ require "hanami/utils/version"
4
6
 
5
7
  Gem::Specification.new do |spec|
6
- spec.name = 'hanami-utils'
8
+ spec.name = "hanami-utils"
7
9
  spec.version = Hanami::Utils::VERSION
8
- spec.authors = ['Luca Guidi']
9
- spec.email = ['me@lucaguidi.com']
10
- spec.description = 'Hanami utilities'
11
- spec.summary = 'Ruby core extentions and Hanami utilities'
12
- spec.homepage = 'http://hanamirb.org'
13
- spec.license = 'MIT'
10
+ spec.authors = ["Luca Guidi"]
11
+ spec.email = ["me@lucaguidi.com"]
12
+ spec.description = "Hanami utilities"
13
+ spec.summary = "Ruby core extentions and Hanami utilities"
14
+ spec.homepage = "http://hanamirb.org"
15
+ spec.license = "MIT"
14
16
 
15
17
  spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md hanami-utils.gemspec`.split($/)
16
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
- spec.require_paths = ['lib']
19
- spec.required_ruby_version = '>= 2.3.0'
20
+ spec.require_paths = ["lib"]
21
+ spec.required_ruby_version = ">= 2.3.0"
20
22
 
21
- spec.add_dependency 'transproc', '~> 1.0'
22
- spec.add_dependency 'concurrent-ruby', '~> 1.0'
23
+ spec.add_dependency "transproc", "~> 1.0"
24
+ spec.add_dependency "concurrent-ruby", "~> 1.0"
23
25
 
24
- spec.add_development_dependency 'bundler', '>= 1.6', '< 3'
25
- spec.add_development_dependency 'rake', '~> 12'
26
- spec.add_development_dependency 'rspec', '~> 3.7'
26
+ spec.add_development_dependency "bundler", ">= 1.6", "< 3"
27
+ spec.add_development_dependency "rake", "~> 13"
28
+ spec.add_development_dependency "rspec", "~> 3.9"
29
+ spec.add_development_dependency "rubocop", "0.81" # rubocop 0.81+ removed support for Ruby 2.3
27
30
  end
@@ -1 +1,3 @@
1
- require 'hanami/utils'
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/utils"
@@ -1,6 +1,8 @@
1
- require 'hanami/utils/basic_object'
2
- require 'hanami/utils/class_attribute'
3
- require 'hanami/utils/hash'
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/utils/basic_object"
4
+ require "hanami/utils/class_attribute"
5
+ require "hanami/utils/hash"
4
6
 
5
7
  module Hanami
6
8
  # Hanami Interactor
@@ -17,14 +19,14 @@ module Hanami
17
19
  # @api private
18
20
  #
19
21
  # @see Hanami::Interactor::Result#respond_to_missing?
20
- METHODS = ::Hash[initialize: true,
21
- success?: true,
22
+ METHODS = ::Hash[initialize: true,
23
+ success?: true,
22
24
  successful?: true,
23
- failure?: true,
24
- fail!: true,
25
- prepare!: true,
26
- errors: true,
27
- error: true].freeze
25
+ failure?: true,
26
+ fail!: true,
27
+ prepare!: true,
28
+ errors: true,
29
+ error: true].freeze
28
30
 
29
31
  # Initialize a new result
30
32
  #
@@ -40,7 +42,7 @@ module Hanami
40
42
  @success = true
41
43
  end
42
44
 
43
- # Check if the current status is successful
45
+ # Checks if the current status is successful
44
46
  #
45
47
  # @return [TrueClass,FalseClass] the result of the check
46
48
  #
@@ -50,9 +52,9 @@ module Hanami
50
52
  end
51
53
 
52
54
  # @since 0.3.5
53
- alias success? successful?
55
+ alias_method :success?, :successful?
54
56
 
55
- # Check if the current status is not successful
57
+ # Checks if the current status is not successful
56
58
  #
57
59
  # @return [TrueClass,FalseClass] the result of the check
58
60
  #
@@ -61,7 +63,7 @@ module Hanami
61
63
  !successful?
62
64
  end
63
65
 
64
- # Force the status to be a failure
66
+ # Forces the status to be a failure
65
67
  #
66
68
  # @since 0.3.5
67
69
  def fail!
@@ -104,7 +106,7 @@ module Hanami
104
106
  errors.first
105
107
  end
106
108
 
107
- # Prepare the result before to be returned
109
+ # Prepares the result before to be returned
108
110
  #
109
111
  # @param payload [Hash] an updated payload
110
112
  #
@@ -351,33 +353,57 @@ module Hanami
351
353
  # end
352
354
  #
353
355
  # Signup.new.call # => NoMethodError
354
- def call(*args)
355
- @__result = ::Hanami::Interactor::Result.new
356
- _call(*args) { super }
356
+ if RUBY_VERSION >= "3.0"
357
+ def call(*args, **kwargs)
358
+ @__result = ::Hanami::Interactor::Result.new
359
+ _call(*args, **kwargs) { super }
360
+ end
361
+ else
362
+ def call(*args)
363
+ @__result = ::Hanami::Interactor::Result.new
364
+ _call(*args) { super }
365
+ end
357
366
  end
358
367
 
359
368
  private
360
369
 
361
370
  # @api private
362
371
  # @since 1.1.0
363
- def _call(*args)
364
- catch :fail do
365
- validate!(*args)
366
- yield
372
+ if RUBY_VERSION >= "3.0"
373
+ def _call(*args, **kwargs)
374
+ catch :fail do
375
+ validate!(*args, **kwargs)
376
+ yield
377
+ end
378
+
379
+ _prepare!
367
380
  end
381
+ else
382
+ def _call(*args)
383
+ catch :fail do
384
+ validate!(*args)
385
+ yield
386
+ end
368
387
 
369
- _prepare!
388
+ _prepare!
389
+ end
370
390
  end
371
391
 
372
392
  # @since 1.1.0
373
- def validate!(*args)
374
- fail! unless valid?(*args)
393
+ if RUBY_VERSION >= "3.0"
394
+ def validate!(*args, **kwargs)
395
+ fail! unless valid?(*args, **kwargs)
396
+ end
397
+ else
398
+ def validate!(*args)
399
+ fail! unless valid?(*args)
400
+ end
375
401
  end
376
402
  end
377
403
 
378
404
  private
379
405
 
380
- # Check if proceed with <tt>#call</tt> invokation.
406
+ # Checks if proceed with <tt>#call</tt> invocation.
381
407
  # By default it returns <tt>true</tt>.
382
408
  #
383
409
  # Developers can override it.
@@ -389,7 +415,7 @@ module Hanami
389
415
  true
390
416
  end
391
417
 
392
- # Fail and interrupt the current flow.
418
+ # Fails and interrupts the current flow.
393
419
  #
394
420
  # @since 0.3.5
395
421
  #
@@ -428,7 +454,7 @@ module Hanami
428
454
  throw :fail
429
455
  end
430
456
 
431
- # Log an error without interrupting the flow.
457
+ # Logs an error without interrupting the flow.
432
458
  #
433
459
  # When used, the returned result won't be successful.
434
460
  #
@@ -483,7 +509,7 @@ module Hanami
483
509
  false
484
510
  end
485
511
 
486
- # Log an error AND interrupting the flow.
512
+ # Logs an error and interrupts the flow.
487
513
  #
488
514
  # When used, the returned result won't be successful.
489
515
  #
@@ -579,7 +605,7 @@ module Hanami
579
605
  end
580
606
  end
581
607
 
582
- # Expose local instance variables into the returning value of <tt>#call</tt>
608
+ # Exposes local instance variables into the returning value of <tt>#call</tt>
583
609
  #
584
610
  # @param instance_variable_names [Symbol,Array<Symbol>] one or more instance
585
611
  # variable names
@@ -588,7 +614,7 @@ module Hanami
588
614
  #
589
615
  # @see Hanami::Interactor::Result
590
616
  #
591
- # @example Expose instance variable
617
+ # @example Exposes instance variable
592
618
  #
593
619
  # class Signup
594
620
  # include Hanami::Interactor
@@ -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,7 +313,7 @@ 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
@@ -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,64 @@ 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.map do |key, value|
103
+ [
104
+ key,
105
+ if value.is_a?(Hash)
106
+ _deep_dup(value)
107
+ else
108
+ _key_paths?(value) ? value.dup : value
109
+ end
110
+ ]
111
+ end.to_h
112
+ end
113
+
114
+ # @since 1.3.7
115
+ # @api private
116
+ def _copy_params(params)
117
+ case params
118
+ when Hash
119
+ _deep_dup(params)
120
+ when Array
121
+ params.map { |hash| _deep_dup(hash) }
122
+ end
123
+ end
124
+
125
+ # @since 1.3.7
126
+ # @api private
127
+ def _filter_hash(hash)
128
+ _filtered_keys(hash).each do |key|
129
+ *keys, last = _actual_keys(hash, key.split("."))
130
+ keys.inject(hash, :fetch)[last] = mask
131
+ end
132
+ hash
133
+ end
134
+
135
+ # @since 1.3.7
136
+ # @api private
137
+ def _filter(params)
138
+ case params
139
+ when Hash
140
+ _filter_hash(params)
141
+ when Array
142
+ params.map { |hash| _filter_hash(hash) }
143
+ end
144
+ end
66
145
  end
67
146
  end
68
147
  end