hanami-utils 2.0.0.alpha1 → 2.0.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.
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "transproc"
3
+ require "dry/transformer"
4
4
 
5
5
  module Hanami
6
6
  module Utils
7
7
  # Hash transformations
8
8
  # @since 0.1.0
9
9
  module Hash
10
- extend Transproc::Registry
11
- import Transproc::HashTransformations
10
+ extend Dry::Transformer::Registry
11
+ import Dry::Transformer::HashTransformations
12
12
 
13
13
  # Symbolize the given hash
14
14
  #
@@ -32,7 +32,7 @@ module Hanami
32
32
  self[:symbolize_keys].call(input)
33
33
  end
34
34
 
35
- # Deep symbolize the given hash
35
+ # Performs deep symbolize on the given hash
36
36
  #
37
37
  # @param input [::Hash] the input
38
38
  #
@@ -54,7 +54,7 @@ module Hanami
54
54
  self[:deep_symbolize_keys].call(input)
55
55
  end
56
56
 
57
- # Stringify the given hash
57
+ # Stringifies the given hash
58
58
  #
59
59
  # @param input [::Hash] the input
60
60
  #
@@ -74,7 +74,7 @@ module Hanami
74
74
  self[:stringify_keys].call(input)
75
75
  end
76
76
 
77
- # Deeply stringify the given hash
77
+ # Deeply stringifies the given hash
78
78
  #
79
79
  # @param input [::Hash] the input
80
80
  #
@@ -90,31 +90,19 @@ module Hanami
90
90
  #
91
91
  # hash.class
92
92
  # # => Hash
93
- def self.deep_stringify(input) # rubocop:disable Metrics/MethodLength
94
- input.each_with_object({}) do |(key, value), output|
95
- output[key.to_s] =
96
- case value
97
- when ::Hash
98
- deep_stringify(value)
99
- when Array
100
- value.map do |item|
101
- item.is_a?(::Hash) ? deep_stringify(item) : item
102
- end
103
- else
104
- value
105
- end
106
- end
93
+ def self.deep_stringify(input)
94
+ self[:deep_stringify_keys].call(input)
107
95
  end
108
96
 
109
- # Deep duplicate hash values
97
+ # Deep duplicates hash values
110
98
  #
111
- # The output of this function is a shallow duplicate of the input.
99
+ # The output of this function is a deep duplicate of the input.
112
100
  # Any further modification on the input, won't be reflected on the output
113
101
  # and viceversa.
114
102
  #
115
103
  # @param input [::Hash] the input
116
104
  #
117
- # @return [::Hash] the shallow duplicate of input
105
+ # @return [::Hash] the deep duplicate of input
118
106
  #
119
107
  # @since 1.0.1
120
108
  #
@@ -144,17 +132,17 @@ module Hanami
144
132
  # input
145
133
  # # => {"a"=>{"b"=>{"c"=>[1,2,3,4]}}}
146
134
  def self.deep_dup(input)
147
- input.each_with_object({}) do |(k, v), result|
148
- result[k] = case v
149
- when ::Hash
150
- deep_dup(v)
151
- else
152
- v.dup
153
- end
135
+ input.transform_values do |v|
136
+ case v
137
+ when ::Hash
138
+ deep_dup(v)
139
+ else
140
+ v.dup
141
+ end
154
142
  end
155
143
  end
156
144
 
157
- # Deep serialize given object into a `Hash`
145
+ # Deep serializes given object into a `Hash`
158
146
  #
159
147
  # Please note that the returning `Hash` will use symbols as keys.
160
148
  #
@@ -178,7 +166,7 @@ module Hanami
178
166
  #
179
167
  # Hanami::Utils::Hash.deep_serialize(input)
180
168
  # # => {:foo=>"bar", :baz=>[{:hello=>"world"}]}
181
- def self.deep_serialize(input) # rubocop:disable Metrics/MethodLength
169
+ def self.deep_serialize(input)
182
170
  input.to_hash.each_with_object({}) do |(key, value), output|
183
171
  output[key.to_sym] =
184
172
  case value
@@ -35,15 +35,25 @@ module Hanami
35
35
 
36
36
  # rubocop:disable Style/ClassVars
37
37
  if defined?(MultiJson)
38
+ # @since 0.8.0
39
+ # @api private
38
40
  @@engine = MultiJsonAdapter.new
41
+
42
+ # @since 0.8.0
43
+ # @api private
39
44
  ParserError = MultiJson::ParseError
40
45
  else
46
+ # @since 0.8.0
47
+ # @api private
41
48
  @@engine = ::JSON
49
+
50
+ # @since 0.8.0
51
+ # @api private
42
52
  ParserError = ::JSON::ParserError
43
53
  end
44
54
  # rubocop:enable Style/ClassVars
45
55
 
46
- # Parse the given JSON paylod
56
+ # Parses the given JSON paylod
47
57
  #
48
58
  # @param payload [String] a JSON payload
49
59
  #
@@ -5,11 +5,12 @@ require "date"
5
5
  require "time"
6
6
  require "pathname"
7
7
  require "bigdecimal"
8
+ require "bigdecimal/util"
8
9
  require "hanami/utils"
9
10
  require "hanami/utils/string"
10
11
 
11
12
  unless defined?(Boolean)
12
- # Define top level constant Boolean, so it can be easily used by other libraries
13
+ # Defines top level constant Boolean, so it can be easily used by other libraries
13
14
  # in coercions DSLs
14
15
  #
15
16
  # @since 0.3.0
@@ -28,7 +29,7 @@ module Hanami
28
29
  # @api private
29
30
  #
30
31
  # @see Hanami::Utils::Kernel.Integer
31
- NUMERIC_MATCHER = %r{\A([\d\/\.\+iE]+|NaN|Infinity)\z}.freeze
32
+ NUMERIC_MATCHER = %r{\A([\d/.+iE]+|NaN|Infinity)\z}
32
33
 
33
34
  # @since 0.8.0
34
35
  # @api private
@@ -327,7 +328,7 @@ module Hanami
327
328
  # # big complex represented as a string
328
329
  # input = Complex(2, 3)
329
330
  # Hanami::Utils::Kernel.Integer(input) # => TypeError
330
- def self.Integer(arg) # rubocop:disable Metrics/MethodLength
331
+ def self.Integer(arg)
331
332
  super(arg)
332
333
  rescue ArgumentError, TypeError, NoMethodError
333
334
  begin
@@ -418,7 +419,6 @@ module Hanami
418
419
  # input = BasicObject.new
419
420
  # Hanami::Utils::Kernel.BigDecimal(input) # => TypeError
420
421
  #
421
- # rubocop:disable Metrics/MethodLength
422
422
  def self.BigDecimal(arg, precision = ::Float::DIG)
423
423
  case arg
424
424
  when NilClass # This is only needed by Ruby 2.6
@@ -435,7 +435,6 @@ module Hanami
435
435
  rescue NoMethodError
436
436
  raise TypeError.new "can't convert #{inspect_type_error(arg)}into BigDecimal"
437
437
  end
438
- # rubocop:enable Metrics/MethodLength
439
438
 
440
439
  # Coerces the argument to be a Float.
441
440
  #
@@ -549,7 +548,7 @@ module Hanami
549
548
  # # big complex represented as a string
550
549
  # input = Complex(2, 3)
551
550
  # Hanami::Utils::Kernel.Float(input) # => TypeError
552
- def self.Float(arg) # rubocop:disable Metrics/MethodLength
551
+ def self.Float(arg)
553
552
  super(arg)
554
553
  rescue ArgumentError, TypeError
555
554
  begin
@@ -738,7 +737,8 @@ module Hanami
738
737
  # require 'hanami/utils/kernel'
739
738
  #
740
739
  # Hanami::Utils::Kernel.DateTime(3483943)
741
- # # => Time.at(3483943).to_datetime #<DateTime: 1970-02-10T08:45:43+01:00 ((2440628j,27943s,0n),+3600s,2299161j)>
740
+ # # => Time.at(3483943).to_datetime
741
+ # # #<DateTime: 1970-02-10T08:45:43+01:00 ((2440628j,27943s,0n),+3600s,2299161j)>
742
742
  #
743
743
  # Hanami::Utils::Kernel.DateTime(DateTime.now)
744
744
  # # => #<DateTime: 2014-04-18T09:33:49+02:00 ((2456766j,27229s,690849000n),+7200s,2299161j)>
@@ -898,7 +898,7 @@ module Hanami
898
898
  # # Missing #respond_to?
899
899
  # input = BasicObject.new
900
900
  # Hanami::Utils::Kernel.Boolean(input) # => TypeError
901
- def self.Boolean(arg) # rubocop:disable Metrics/MethodLength
901
+ def self.Boolean(arg)
902
902
  case arg
903
903
  when Numeric
904
904
  arg.to_i == BOOLEAN_TRUE_INTEGER
@@ -1016,14 +1016,14 @@ module Hanami
1016
1016
  case arg
1017
1017
  when "" then raise TypeError.new "can't convert #{inspect_type_error(arg)}into Symbol"
1018
1018
  when ->(a) { a.respond_to?(:to_sym) } then arg.to_sym
1019
- else
1019
+ else # rubocop:disable Lint/DuplicateBranch
1020
1020
  raise TypeError.new "can't convert #{inspect_type_error(arg)}into Symbol"
1021
1021
  end
1022
1022
  rescue NoMethodError
1023
1023
  raise TypeError.new "can't convert #{inspect_type_error(arg)}into Symbol"
1024
1024
  end
1025
1025
 
1026
- # Check if the given argument is a string representation of a number
1026
+ # Checks if the given argument is a string representation of a number
1027
1027
  #
1028
1028
  # @param arg [Object] the input
1029
1029
  #
@@ -1044,11 +1044,11 @@ module Hanami
1044
1044
  # @since 0.4.3
1045
1045
  # @api private
1046
1046
  def self.inspect_type_error(arg)
1047
- (arg.respond_to?(:inspect) ? arg.inspect : arg.to_s) << " "
1048
- rescue NoMethodError => _
1047
+ "#{arg.respond_to?(:inspect) ? arg.inspect : arg.to_s} "
1048
+ rescue NoMethodError
1049
1049
  # missing the #respond_to? method, fall back to returning the class' name
1050
1050
  begin
1051
- arg.class.name << " instance "
1051
+ "#{arg.class.name} instance "
1052
1052
  rescue NoMethodError
1053
1053
  # missing the #class method, can't fall back to anything better than nothing
1054
1054
  # Callers will have to guess from their code
@@ -1057,7 +1057,7 @@ module Hanami
1057
1057
  end
1058
1058
 
1059
1059
  class << self
1060
- private :inspect_type_error # rubocop:disable Style/AccessModifierDeclarations
1060
+ private :inspect_type_error
1061
1061
  end
1062
1062
  end
1063
1063
  end
@@ -50,7 +50,7 @@ module Hanami
50
50
  @paths = original.instance_variable_get(:@paths).dup
51
51
  end
52
52
 
53
- # Iterates thru the collection and yields the given block.
53
+ # Iterates through the collection and yields the given block.
54
54
  # It skips duplications and raises an error in case one of the paths
55
55
  # doesn't exist.
56
56
  #
@@ -117,7 +117,7 @@ module Hanami
117
117
  self
118
118
  end
119
119
 
120
- alias << push
120
+ alias_method :<<, :push
121
121
 
122
122
  # It freezes the object by preventing further modifications.
123
123
  #
@@ -158,7 +158,7 @@ module Hanami
158
158
 
159
159
  private
160
160
 
161
- # Allow subclasses to define their own policy to discover the realpath
161
+ # Allows subclasses to define their own policy to discover the realpath
162
162
  # of the given path.
163
163
  #
164
164
  # @since 0.2.0
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hanami/utils/string"
4
3
  require "hanami/utils/kernel"
5
4
 
6
5
  module Hanami
@@ -8,7 +7,7 @@ module Hanami
8
7
  # Prefixed string
9
8
  #
10
9
  # @since 0.1.0
11
- class PathPrefix < Hanami::Utils::String
10
+ class PathPrefix
12
11
  # Path separator
13
12
  #
14
13
  # @since 0.3.1
@@ -26,7 +25,7 @@ module Hanami
26
25
  #
27
26
  # @see Hanami::Utils::PathPrefix::DEFAULT_SEPARATOR
28
27
  def initialize(string = nil, separator = DEFAULT_SEPARATOR)
29
- super(string)
28
+ @string = string.to_s
30
29
  @separator = separator
31
30
  end
32
31
 
@@ -93,6 +92,37 @@ module Hanami
93
92
  ).relative!
94
93
  end
95
94
 
95
+ # Returns the hash of the internal string
96
+ #
97
+ # @return [Integer]
98
+ #
99
+ # @since 0.3.0
100
+ def hash
101
+ @string.hash
102
+ end
103
+
104
+ # Returns a string representation
105
+ #
106
+ # @return [::String]
107
+ #
108
+ # @since 0.3.0
109
+ def to_s
110
+ @string
111
+ end
112
+
113
+ alias_method :to_str, :to_s
114
+
115
+ # Equality
116
+ #
117
+ # @return [TrueClass,FalseClass]
118
+ #
119
+ # @since 0.3.0
120
+ def ==(other)
121
+ to_s == other
122
+ end
123
+
124
+ alias_method :eql?, :==
125
+
96
126
  protected
97
127
 
98
128
  # Modifies the path prefix to have a prepended separator.
@@ -12,7 +12,7 @@ module Hanami
12
12
  # @api private
13
13
  HASH_SEPARATOR = ","
14
14
 
15
- # Serialize input into a query string
15
+ # Serializes input into a query string
16
16
  #
17
17
  # @param input [Object] the input
18
18
  #
@@ -7,33 +7,37 @@ module Hanami
7
7
  # It doesn't check if you're writing to a file or anything, so you have to
8
8
  # check that yourself before using this module.
9
9
  #
10
+ # @api public
10
11
  # @since 1.2.0
11
12
  module ShellColor
12
- # Unknown color code error
13
+ # Error raised for unknown color codes.
13
14
  #
14
15
  # @since 1.2.0
16
+ # @api public
15
17
  class UnknownColorCodeError < ::StandardError
18
+ # @since 1.2.0
19
+ # @api private
16
20
  def initialize(code)
17
21
  super("unknown color code: `#{code.inspect}'")
18
22
  end
19
23
  end
20
24
 
21
- # Escape codes for terminals to output strings in colors
25
+ # Escapes codes for terminals to output strings in colors
22
26
  #
23
27
  # @since 1.2.0
24
28
  # @api private
25
29
  COLORS = ::Hash[
26
- black: 30,
27
- red: 31,
28
- green: 32,
29
- yellow: 33,
30
- blue: 34,
30
+ black: 30,
31
+ red: 31,
32
+ green: 32,
33
+ yellow: 33,
34
+ blue: 34,
31
35
  magenta: 35,
32
- cyan: 36,
33
- gray: 37,
36
+ cyan: 36,
37
+ gray: 37,
34
38
  ].freeze
35
39
 
36
- # Colorize output
40
+ # Colorizes output
37
41
  # 8 colors available: black, red, green, yellow, blue, magenta, cyan, and gray
38
42
  #
39
43
  # @param input [#to_s] the string to colorize