hanami-utils 1.3.2 → 1.3.7

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