activesupport 7.1.0 → 7.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +122 -943
- data/lib/active_support/array_inquirer.rb +1 -1
- data/lib/active_support/backtrace_cleaner.rb +15 -3
- data/lib/active_support/broadcast_logger.rb +33 -4
- data/lib/active_support/cache/entry.rb +7 -1
- data/lib/active_support/cache/file_store.rb +16 -11
- data/lib/active_support/cache/mem_cache_store.rb +32 -82
- data/lib/active_support/cache/memory_store.rb +17 -14
- data/lib/active_support/cache/redis_cache_store.rb +54 -36
- data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
- data/lib/active_support/cache/strategy/local_cache.rb +9 -6
- data/lib/active_support/cache.rb +98 -84
- data/lib/active_support/callbacks.rb +74 -113
- data/lib/active_support/code_generator.rb +15 -10
- data/lib/active_support/core_ext/array/conversions.rb +0 -2
- data/lib/active_support/core_ext/class/subclasses.rb +15 -35
- data/lib/active_support/core_ext/date/blank.rb +4 -0
- data/lib/active_support/core_ext/date/conversions.rb +1 -3
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +28 -1
- data/lib/active_support/core_ext/date_time/blank.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -4
- data/lib/active_support/core_ext/digest/uuid.rb +6 -0
- data/lib/active_support/core_ext/erb/util.rb +5 -0
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -148
- data/lib/active_support/core_ext/module/deprecation.rb +1 -4
- data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
- data/lib/active_support/core_ext/object/blank.rb +45 -1
- data/lib/active_support/core_ext/object/duplicable.rb +24 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
- data/lib/active_support/core_ext/object/json.rb +2 -2
- data/lib/active_support/core_ext/object/with.rb +5 -3
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/pathname/blank.rb +4 -0
- data/lib/active_support/core_ext/range/overlap.rb +1 -1
- data/lib/active_support/core_ext/securerandom.rb +8 -24
- data/lib/active_support/core_ext/string/conversions.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +0 -7
- data/lib/active_support/core_ext/time/calculations.rb +18 -28
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +0 -2
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/current_attributes.rb +33 -40
- data/lib/active_support/delegation.rb +202 -0
- data/lib/active_support/dependencies/autoload.rb +0 -12
- data/lib/active_support/deprecation/behaviors.rb +18 -16
- data/lib/active_support/deprecation/constant_accessor.rb +47 -26
- data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
- data/lib/active_support/deprecation/reporting.rb +13 -5
- data/lib/active_support/deprecation.rb +8 -5
- data/lib/active_support/descendants_tracker.rb +9 -87
- data/lib/active_support/duration/iso8601_parser.rb +2 -2
- data/lib/active_support/duration/iso8601_serializer.rb +1 -2
- data/lib/active_support/duration.rb +11 -6
- data/lib/active_support/error_reporter.rb +41 -3
- data/lib/active_support/evented_file_update_checker.rb +0 -1
- data/lib/active_support/execution_wrapper.rb +0 -1
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/fork_tracker.rb +2 -38
- data/lib/active_support/gem_version.rb +1 -1
- data/lib/active_support/hash_with_indifferent_access.rb +6 -8
- data/lib/active_support/html_safe_translation.rb +19 -6
- data/lib/active_support/inflector/methods.rb +2 -2
- data/lib/active_support/log_subscriber.rb +9 -14
- data/lib/active_support/logger.rb +15 -2
- data/lib/active_support/logger_thread_safe_level.rb +0 -8
- data/lib/active_support/message_encryptors.rb +1 -0
- data/lib/active_support/message_pack/extensions.rb +15 -2
- data/lib/active_support/message_verifier.rb +12 -0
- data/lib/active_support/message_verifiers.rb +1 -0
- data/lib/active_support/messages/codec.rb +1 -1
- data/lib/active_support/messages/metadata.rb +1 -1
- data/lib/active_support/multibyte/chars.rb +2 -2
- data/lib/active_support/notifications/fanout.rb +29 -26
- data/lib/active_support/notifications/instrumenter.rb +43 -32
- data/lib/active_support/notifications.rb +28 -27
- data/lib/active_support/number_helper/number_converter.rb +5 -3
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -2
- data/lib/active_support/number_helper.rb +379 -318
- data/lib/active_support/option_merger.rb +2 -2
- data/lib/active_support/ordered_options.rb +55 -17
- data/lib/active_support/proxy_object.rb +8 -5
- data/lib/active_support/railtie.rb +4 -11
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/syntax_error_proxy.rb +12 -1
- data/lib/active_support/tagged_logging.rb +4 -1
- data/lib/active_support/test_case.rb +3 -1
- data/lib/active_support/testing/assertions.rb +5 -5
- data/lib/active_support/testing/constant_stubbing.rb +30 -8
- data/lib/active_support/testing/deprecation.rb +5 -12
- data/lib/active_support/testing/isolation.rb +18 -8
- data/lib/active_support/testing/method_call_assertions.rb +2 -16
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/strict_warnings.rb +6 -4
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +8 -4
- data/lib/active_support/time_with_zone.rb +7 -3
- data/lib/active_support/values/time_zone.rb +10 -1
- data/lib/active_support/xml_mini.rb +11 -2
- data/lib/active_support.rb +3 -2
- metadata +35 -15
- data/lib/active_support/deprecation/instance_delegator.rb +0 -65
- data/lib/active_support/ruby_features.rb +0 -7
|
@@ -42,22 +42,18 @@ module ActiveSupport
|
|
|
42
42
|
super(key.to_sym)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
def dig(*
|
|
46
|
-
super(
|
|
45
|
+
def dig(key, *identifiers)
|
|
46
|
+
super(key.to_sym, *identifiers)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def method_missing(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
def method_missing(method, *args)
|
|
50
|
+
if method.end_with?("=")
|
|
51
|
+
self[method.name.chomp("=")] = args.first
|
|
52
|
+
elsif method.end_with?("!")
|
|
53
|
+
name_string = method.name.chomp("!")
|
|
54
|
+
self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
|
|
53
55
|
else
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if bangs
|
|
57
|
-
self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
|
|
58
|
-
else
|
|
59
|
-
self[name_string]
|
|
60
|
-
end
|
|
56
|
+
self[method.name]
|
|
61
57
|
end
|
|
62
58
|
end
|
|
63
59
|
|
|
@@ -92,18 +88,60 @@ module ActiveSupport
|
|
|
92
88
|
# h.boy # => 'John'
|
|
93
89
|
class InheritableOptions < OrderedOptions
|
|
94
90
|
def initialize(parent = nil)
|
|
95
|
-
|
|
91
|
+
@parent = parent
|
|
92
|
+
if @parent.kind_of?(OrderedOptions)
|
|
96
93
|
# use the faster _get when dealing with OrderedOptions
|
|
97
|
-
super() { |h, k| parent._get(k) }
|
|
98
|
-
elsif parent
|
|
99
|
-
super() { |h, k| parent[k] }
|
|
94
|
+
super() { |h, k| @parent._get(k) }
|
|
95
|
+
elsif @parent
|
|
96
|
+
super() { |h, k| @parent[k] }
|
|
100
97
|
else
|
|
101
98
|
super()
|
|
99
|
+
@parent = {}
|
|
102
100
|
end
|
|
103
101
|
end
|
|
104
102
|
|
|
103
|
+
def to_h
|
|
104
|
+
@parent.merge(self)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def ==(other)
|
|
108
|
+
to_h == other.to_h
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def inspect
|
|
112
|
+
"#<#{self.class.name} #{to_h.inspect}>"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def to_s
|
|
116
|
+
to_h.to_s
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def pretty_print(pp)
|
|
120
|
+
pp.pp_hash(to_h)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
alias_method :own_key?, :key?
|
|
124
|
+
private :own_key?
|
|
125
|
+
|
|
126
|
+
def key?(key)
|
|
127
|
+
super || @parent.key?(key)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def overridden?(key)
|
|
131
|
+
!!(@parent && @parent.key?(key) && own_key?(key.to_sym))
|
|
132
|
+
end
|
|
133
|
+
|
|
105
134
|
def inheritable_copy
|
|
106
135
|
self.class.new(self)
|
|
107
136
|
end
|
|
137
|
+
|
|
138
|
+
def to_a
|
|
139
|
+
entries
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def each(&block)
|
|
143
|
+
to_h.each(&block)
|
|
144
|
+
self
|
|
145
|
+
end
|
|
108
146
|
end
|
|
109
147
|
end
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveSupport
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
# A class with no predefined methods that behaves similarly to Builder's
|
|
7
|
-
# BlankSlate. Used for proxy classes.
|
|
8
|
-
class ProxyObject < ::BasicObject
|
|
4
|
+
class ProxyObject < ::BasicObject # :nodoc:
|
|
9
5
|
undef_method :==
|
|
10
6
|
undef_method :equal?
|
|
11
7
|
|
|
@@ -13,5 +9,12 @@ module ActiveSupport
|
|
|
13
9
|
def raise(*args)
|
|
14
10
|
::Object.send(:raise, *args)
|
|
15
11
|
end
|
|
12
|
+
|
|
13
|
+
def self.inherited(_subclass)
|
|
14
|
+
::ActiveSupport.deprecator.warn(<<~MSG)
|
|
15
|
+
ActiveSupport::ProxyObject is deprecated and will be removed in Rails 8.0.
|
|
16
|
+
Use Ruby's built-in BasicObject instead.
|
|
17
|
+
MSG
|
|
18
|
+
end
|
|
16
19
|
end
|
|
17
20
|
end
|
|
@@ -89,10 +89,11 @@ module ActiveSupport
|
|
|
89
89
|
begin
|
|
90
90
|
TZInfo::DataSource.get
|
|
91
91
|
rescue TZInfo::DataSourceNotFound => e
|
|
92
|
-
raise e.exception
|
|
92
|
+
raise e.exception('tzinfo-data is not present. Please add gem "tzinfo-data" to your Gemfile and run bundle install')
|
|
93
93
|
end
|
|
94
94
|
require "active_support/core_ext/time/zones"
|
|
95
95
|
Time.zone_default = Time.find_zone!(app.config.time_zone)
|
|
96
|
+
config.eager_load_namespaces << TZInfo
|
|
96
97
|
end
|
|
97
98
|
|
|
98
99
|
# Sets the default week start
|
|
@@ -117,16 +118,8 @@ module ActiveSupport
|
|
|
117
118
|
|
|
118
119
|
initializer "active_support.set_configs" do |app|
|
|
119
120
|
app.config.active_support.each do |k, v|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
elsif k == "remove_deprecated_time_with_zone_name"
|
|
123
|
-
ActiveSupport.deprecator.warn("config.active_support.remove_deprecated_time_with_zone_name is deprecated and will be removed in Rails 7.2.")
|
|
124
|
-
elsif k == "use_rfc4122_namespaced_uuids"
|
|
125
|
-
ActiveSupport.deprecator.warn("config.active_support.use_rfc4122_namespaced_uuids is deprecated and will be removed in Rails 7.2.")
|
|
126
|
-
else
|
|
127
|
-
k = "#{k}="
|
|
128
|
-
ActiveSupport.public_send(k, v) if ActiveSupport.respond_to? k
|
|
129
|
-
end
|
|
121
|
+
k = "#{k}="
|
|
122
|
+
ActiveSupport.public_send(k, v) if ActiveSupport.respond_to? k
|
|
130
123
|
end
|
|
131
124
|
end
|
|
132
125
|
|
|
@@ -32,6 +32,8 @@ module ActiveSupport
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def backtrace_locations
|
|
35
|
+
return nil if super.nil?
|
|
36
|
+
|
|
35
37
|
parse_message_for_trace.map { |trace|
|
|
36
38
|
file, line = trace.match(/^(.+?):(\d+).*$/, &:captures) || trace
|
|
37
39
|
BacktraceLocation.new(file, line.to_i, trace)
|
|
@@ -43,7 +45,16 @@ module ActiveSupport
|
|
|
43
45
|
|
|
44
46
|
private
|
|
45
47
|
def parse_message_for_trace
|
|
46
|
-
__getobj__.to_s.
|
|
48
|
+
if __getobj__.to_s.start_with?("(eval")
|
|
49
|
+
# If the exception is coming from a call to eval, we need to keep
|
|
50
|
+
# the path of the file in which eval was called to ensure we can
|
|
51
|
+
# return the right source fragment to show the location of the
|
|
52
|
+
# error
|
|
53
|
+
location = __getobj__.backtrace_locations[0]
|
|
54
|
+
["#{location.path}:#{location.lineno}: #{__getobj__}"]
|
|
55
|
+
else
|
|
56
|
+
__getobj__.to_s.split("\n")
|
|
57
|
+
end
|
|
47
58
|
end
|
|
48
59
|
end
|
|
49
60
|
end
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
require "active_support/core_ext/module/delegation"
|
|
4
4
|
require "active_support/core_ext/object/blank"
|
|
5
|
-
require "logger"
|
|
6
5
|
require "active_support/logger"
|
|
7
6
|
|
|
8
7
|
module ActiveSupport
|
|
@@ -119,6 +118,10 @@ module ActiveSupport
|
|
|
119
118
|
|
|
120
119
|
if logger.formatter
|
|
121
120
|
logger.formatter = logger.formatter.clone
|
|
121
|
+
|
|
122
|
+
# Workaround for https://bugs.ruby-lang.org/issues/20250
|
|
123
|
+
# Can be removed when Ruby 3.4 is the least supported version.
|
|
124
|
+
logger.formatter.object_id if logger.formatter.is_a?(Proc)
|
|
122
125
|
else
|
|
123
126
|
# Ensure we set a default formatter so we aren't extending nil!
|
|
124
127
|
logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "minitest"
|
|
4
4
|
require "active_support/testing/tagged_logging"
|
|
5
5
|
require "active_support/testing/setup_and_teardown"
|
|
6
|
+
require "active_support/testing/tests_without_assertions"
|
|
6
7
|
require "active_support/testing/assertions"
|
|
7
8
|
require "active_support/testing/error_reporter_assertions"
|
|
8
9
|
require "active_support/testing/deprecation"
|
|
@@ -78,7 +79,7 @@ module ActiveSupport
|
|
|
78
79
|
# number of tests to run is above the +threshold+ param. The default value is
|
|
79
80
|
# 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
|
|
80
81
|
def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
|
|
81
|
-
workers = Concurrent.
|
|
82
|
+
workers = Concurrent.processor_count if workers == :number_of_processors
|
|
82
83
|
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
|
83
84
|
|
|
84
85
|
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
|
@@ -142,6 +143,7 @@ module ActiveSupport
|
|
|
142
143
|
|
|
143
144
|
include ActiveSupport::Testing::TaggedLogging
|
|
144
145
|
prepend ActiveSupport::Testing::SetupAndTeardown
|
|
146
|
+
prepend ActiveSupport::Testing::TestsWithoutAssertions
|
|
145
147
|
include ActiveSupport::Testing::Assertions
|
|
146
148
|
include ActiveSupport::Testing::ErrorReporterAssertions
|
|
147
149
|
include ActiveSupport::Testing::Deprecation
|
|
@@ -195,7 +195,7 @@ module ActiveSupport
|
|
|
195
195
|
retval = _assert_nothing_raised_or_warn("assert_changes", &block)
|
|
196
196
|
|
|
197
197
|
unless from == UNTRACKED
|
|
198
|
-
error = "Expected change from #{from.inspect}, got #{before}"
|
|
198
|
+
error = "Expected change from #{from.inspect}, got #{before.inspect}"
|
|
199
199
|
error = "#{message}.\n#{error}" if message
|
|
200
200
|
assert from === before, error
|
|
201
201
|
end
|
|
@@ -203,12 +203,12 @@ module ActiveSupport
|
|
|
203
203
|
after = exp.call
|
|
204
204
|
|
|
205
205
|
error = "#{expression.inspect} didn't change"
|
|
206
|
-
error = "#{error}. It was already #{to}" if before == to
|
|
206
|
+
error = "#{error}. It was already #{to.inspect}" if before == to
|
|
207
207
|
error = "#{message}.\n#{error}" if message
|
|
208
208
|
refute_equal before, after, error
|
|
209
209
|
|
|
210
210
|
unless to == UNTRACKED
|
|
211
|
-
error = "Expected change to #{to}, got #{after}\n"
|
|
211
|
+
error = "Expected change to #{to.inspect}, got #{after.inspect}\n"
|
|
212
212
|
error = "#{message}.\n#{error}" if message
|
|
213
213
|
assert to === after, error
|
|
214
214
|
end
|
|
@@ -223,7 +223,7 @@ module ActiveSupport
|
|
|
223
223
|
# post :create, params: { status: { ok: true } }
|
|
224
224
|
# end
|
|
225
225
|
#
|
|
226
|
-
# Provide the optional keyword argument
|
|
226
|
+
# Provide the optional keyword argument +:from+ to specify the expected
|
|
227
227
|
# initial value.
|
|
228
228
|
#
|
|
229
229
|
# assert_no_changes -> { Status.all_good? }, from: true do
|
|
@@ -242,7 +242,7 @@ module ActiveSupport
|
|
|
242
242
|
retval = _assert_nothing_raised_or_warn("assert_no_changes", &block)
|
|
243
243
|
|
|
244
244
|
unless from == UNTRACKED
|
|
245
|
-
error = "Expected initial value of #{from.inspect}"
|
|
245
|
+
error = "Expected initial value of #{from.inspect}, got #{before.inspect}"
|
|
246
246
|
error = "#{message}.\n#{error}" if message
|
|
247
247
|
assert from === before, error
|
|
248
248
|
end
|
|
@@ -15,17 +15,39 @@ module ActiveSupport
|
|
|
15
15
|
# Using this method rather than forcing <tt>World::List::Import::LARGE_IMPORT_THRESHOLD = 5000</tt> prevents
|
|
16
16
|
# warnings from being thrown, and ensures that the old value is returned after the test has completed.
|
|
17
17
|
#
|
|
18
|
+
# If the constant doesn't already exists, but you need it set for the duration of the block
|
|
19
|
+
# you can do so by passing `exists: false`.
|
|
20
|
+
#
|
|
21
|
+
# stub_const(object, :SOME_CONST, 1, exists: false) do
|
|
22
|
+
# assert_equal 1, SOME_CONST
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
18
25
|
# Note: Stubbing a const will stub it across all threads. So if you have concurrent threads
|
|
19
26
|
# (like separate test suites running in parallel) that all depend on the same constant, it's possible
|
|
20
27
|
# divergent stubbing will trample on each other.
|
|
21
|
-
def stub_const(mod, constant, new_value)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
def stub_const(mod, constant, new_value, exists: true)
|
|
29
|
+
if exists
|
|
30
|
+
begin
|
|
31
|
+
old_value = mod.const_get(constant, false)
|
|
32
|
+
mod.send(:remove_const, constant)
|
|
33
|
+
mod.const_set(constant, new_value)
|
|
34
|
+
yield
|
|
35
|
+
ensure
|
|
36
|
+
mod.send(:remove_const, constant)
|
|
37
|
+
mod.const_set(constant, old_value)
|
|
38
|
+
end
|
|
39
|
+
else
|
|
40
|
+
if mod.const_defined?(constant)
|
|
41
|
+
raise NameError, "already defined constant #{constant} in #{mod.name}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
begin
|
|
45
|
+
mod.const_set(constant, new_value)
|
|
46
|
+
yield
|
|
47
|
+
ensure
|
|
48
|
+
mod.send(:remove_const, constant)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
29
51
|
end
|
|
30
52
|
end
|
|
31
53
|
end
|
|
@@ -29,10 +29,11 @@ module ActiveSupport
|
|
|
29
29
|
# end
|
|
30
30
|
def assert_deprecated(match = nil, deprecator = nil, &block)
|
|
31
31
|
match, deprecator = nil, match if match.is_a?(ActiveSupport::Deprecation)
|
|
32
|
+
|
|
32
33
|
unless deprecator
|
|
33
|
-
|
|
34
|
-
deprecator = ActiveSupport::Deprecation._instance
|
|
34
|
+
raise ArgumentError, "No deprecator given"
|
|
35
35
|
end
|
|
36
|
+
|
|
36
37
|
result, warnings = collect_deprecations(deprecator, &block)
|
|
37
38
|
assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
|
|
38
39
|
if match
|
|
@@ -51,11 +52,7 @@ module ActiveSupport
|
|
|
51
52
|
# assert_not_deprecated(ActiveSupport::Deprecation.new) do
|
|
52
53
|
# CustomDeprecator.warn "message" # passes assertion, different deprecator
|
|
53
54
|
# end
|
|
54
|
-
def assert_not_deprecated(deprecator
|
|
55
|
-
unless deprecator
|
|
56
|
-
ActiveSupport.deprecator.warn("assert_not_deprecated without a deprecator is deprecated")
|
|
57
|
-
deprecator = ActiveSupport::Deprecation._instance
|
|
58
|
-
end
|
|
55
|
+
def assert_not_deprecated(deprecator, &block)
|
|
59
56
|
result, deprecations = collect_deprecations(deprecator, &block)
|
|
60
57
|
assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
|
|
61
58
|
result
|
|
@@ -69,11 +66,7 @@ module ActiveSupport
|
|
|
69
66
|
# ActiveSupport::Deprecation.new.warn "other message"
|
|
70
67
|
# :result
|
|
71
68
|
# end # => [:result, ["message"]]
|
|
72
|
-
def collect_deprecations(deprecator
|
|
73
|
-
unless deprecator
|
|
74
|
-
ActiveSupport.deprecator.warn("collect_deprecations without a deprecator is deprecated")
|
|
75
|
-
deprecator = ActiveSupport::Deprecation._instance
|
|
76
|
-
end
|
|
69
|
+
def collect_deprecations(deprecator)
|
|
77
70
|
old_behavior = deprecator.behavior
|
|
78
71
|
deprecations = []
|
|
79
72
|
deprecator.behavior = Proc.new do |message, callstack|
|
|
@@ -5,9 +5,11 @@ module ActiveSupport
|
|
|
5
5
|
module Isolation
|
|
6
6
|
require "thread"
|
|
7
7
|
|
|
8
|
+
SubprocessCrashed = Class.new(StandardError)
|
|
9
|
+
|
|
8
10
|
def self.included(klass) # :nodoc:
|
|
9
11
|
klass.class_eval do
|
|
10
|
-
parallelize_me!
|
|
12
|
+
parallelize_me! unless Minitest.parallel_executor.is_a?(ActiveSupport::Testing::ParallelizeExecutor)
|
|
11
13
|
end
|
|
12
14
|
end
|
|
13
15
|
|
|
@@ -16,10 +18,17 @@ module ActiveSupport
|
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
def run
|
|
19
|
-
serialized = run_in_isolation do
|
|
21
|
+
status, serialized = run_in_isolation do
|
|
20
22
|
super
|
|
21
23
|
end
|
|
22
24
|
|
|
25
|
+
unless status&.success?
|
|
26
|
+
error = SubprocessCrashed.new("Subprocess exited with an error: #{status.inspect}\noutput: #{serialized.inspect}")
|
|
27
|
+
error.set_backtrace(caller)
|
|
28
|
+
self.failures << Minitest::UnexpectedError.new(error)
|
|
29
|
+
return defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
|
|
30
|
+
end
|
|
31
|
+
|
|
23
32
|
Marshal.load(serialized)
|
|
24
33
|
end
|
|
25
34
|
|
|
@@ -50,13 +59,13 @@ module ActiveSupport
|
|
|
50
59
|
end
|
|
51
60
|
|
|
52
61
|
write.puts [result].pack("m")
|
|
53
|
-
exit!
|
|
62
|
+
exit!(0)
|
|
54
63
|
end
|
|
55
64
|
|
|
56
65
|
write.close
|
|
57
66
|
result = read.read
|
|
58
|
-
Process.wait2(pid)
|
|
59
|
-
result.unpack1("m")
|
|
67
|
+
_, status = Process.wait2(pid)
|
|
68
|
+
return status, result.unpack1("m")
|
|
60
69
|
end
|
|
61
70
|
end
|
|
62
71
|
end
|
|
@@ -75,7 +84,7 @@ module ActiveSupport
|
|
|
75
84
|
File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
|
|
76
85
|
file.puts [Marshal.dump(test_result)].pack("m")
|
|
77
86
|
end
|
|
78
|
-
exit!
|
|
87
|
+
exit!(0)
|
|
79
88
|
else
|
|
80
89
|
Tempfile.open("isolation") do |tmpfile|
|
|
81
90
|
env = {
|
|
@@ -93,13 +102,14 @@ module ActiveSupport
|
|
|
93
102
|
|
|
94
103
|
child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
|
|
95
104
|
|
|
105
|
+
status = nil
|
|
96
106
|
begin
|
|
97
|
-
Process.
|
|
107
|
+
_, status = Process.wait2(child.pid)
|
|
98
108
|
rescue Errno::ECHILD # The child process may exit before we wait
|
|
99
109
|
nil
|
|
100
110
|
end
|
|
101
111
|
|
|
102
|
-
return tmpfile.read.unpack1("m")
|
|
112
|
+
return status, tmpfile.read.unpack1("m")
|
|
103
113
|
end
|
|
104
114
|
end
|
|
105
115
|
end
|
|
@@ -30,22 +30,8 @@ module ActiveSupport
|
|
|
30
30
|
assert_called(object, method_name, message, times: 0, &block)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# the Minitest 5.16 / Ruby 3.0 kwargs transition. It can go away
|
|
36
|
-
# when we drop support for Ruby 2.7.
|
|
37
|
-
if Minitest::Mock.instance_method(:expect).parameters.map(&:first).include?(:keyrest)
|
|
38
|
-
def expect_called_with(mock, args, returns: false, **kwargs)
|
|
39
|
-
mock.expect(:call, returns, args, **kwargs)
|
|
40
|
-
end
|
|
41
|
-
else
|
|
42
|
-
def expect_called_with(mock, args, returns: false, **kwargs)
|
|
43
|
-
if !kwargs.empty?
|
|
44
|
-
mock.expect(:call, returns, [*args, kwargs])
|
|
45
|
-
else
|
|
46
|
-
mock.expect(:call, returns, args)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
33
|
+
def expect_called_with(mock, args, returns: false, **kwargs)
|
|
34
|
+
mock.expect(:call, returns, args, **kwargs)
|
|
49
35
|
end
|
|
50
36
|
|
|
51
37
|
def assert_called_on_instance_of(klass, method_name, message = nil, times: 1, returns: nil)
|
|
@@ -5,6 +5,8 @@ Warning[:deprecated] = true
|
|
|
5
5
|
|
|
6
6
|
module ActiveSupport
|
|
7
7
|
module RaiseWarnings # :nodoc:
|
|
8
|
+
class WarningError < StandardError; end
|
|
9
|
+
|
|
8
10
|
PROJECT_ROOT = File.expand_path("../../../../", __dir__)
|
|
9
11
|
ALLOWED_WARNINGS = Regexp.union(
|
|
10
12
|
/circular require considered harmful.*delayed_job/, # Bug in delayed job.
|
|
@@ -17,21 +19,21 @@ module ActiveSupport
|
|
|
17
19
|
SUPPRESSED_WARNINGS = Regexp.union(
|
|
18
20
|
# TODO: remove if https://github.com/mikel/mail/pull/1557 or similar fix
|
|
19
21
|
%r{/lib/mail/parsers/.*statement not reached},
|
|
22
|
+
%r{/lib/mail/parsers/.*assigned but unused variable - disp_type_s},
|
|
20
23
|
%r{/lib/mail/parsers/.*assigned but unused variable - testEof}
|
|
21
24
|
)
|
|
22
25
|
|
|
23
|
-
def warn(message,
|
|
26
|
+
def warn(message, ...)
|
|
24
27
|
return if SUPPRESSED_WARNINGS.match?(message)
|
|
25
28
|
|
|
26
29
|
super
|
|
27
30
|
|
|
28
31
|
return unless message.include?(PROJECT_ROOT)
|
|
29
32
|
return if ALLOWED_WARNINGS.match?(message)
|
|
30
|
-
return unless ENV["RAILS_STRICT_WARNINGS"] || ENV["
|
|
33
|
+
return unless ENV["RAILS_STRICT_WARNINGS"] || ENV["BUILDKITE"]
|
|
31
34
|
|
|
32
|
-
raise message
|
|
35
|
+
raise WarningError.new(message)
|
|
33
36
|
end
|
|
34
|
-
ruby2_keywords :warn if respond_to?(:ruby2_keywords, true)
|
|
35
37
|
end
|
|
36
38
|
end
|
|
37
39
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
module Testing
|
|
5
|
+
# Warns when a test case does not perform any assertions.
|
|
6
|
+
#
|
|
7
|
+
# This is helpful in detecting broken tests that do not perform intended assertions.
|
|
8
|
+
module TestsWithoutAssertions # :nodoc:
|
|
9
|
+
def after_teardown
|
|
10
|
+
super
|
|
11
|
+
|
|
12
|
+
if assertions.zero? && !skipped? && !error?
|
|
13
|
+
file, line = method(name).source_location
|
|
14
|
+
warn "Test is missing assertions: `#{name}` #{file}:#{line}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -25,7 +25,7 @@ module ActiveSupport
|
|
|
25
25
|
unstub_object(stub)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
new_name = "__simple_stub__#{method_name}"
|
|
28
|
+
new_name = "__simple_stub__#{method_name}__#{object_id}"
|
|
29
29
|
|
|
30
30
|
@stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
|
|
31
31
|
|
|
@@ -163,12 +163,16 @@ module ActiveSupport
|
|
|
163
163
|
now = date_or_time.midnight.to_time
|
|
164
164
|
elsif date_or_time.is_a?(String)
|
|
165
165
|
now = Time.zone.parse(date_or_time)
|
|
166
|
-
elsif with_usec
|
|
167
|
-
now = date_or_time.to_time
|
|
168
166
|
else
|
|
169
|
-
now = date_or_time
|
|
167
|
+
now = date_or_time
|
|
168
|
+
now = now.to_time unless now.is_a?(Time)
|
|
169
|
+
now = now.change(usec: 0) unless with_usec
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
+
# +now+ must be in local system timezone, because +Time.at(now)+
|
|
173
|
+
# and +now.to_date+ (see stubs below) will use +now+'s timezone too!
|
|
174
|
+
now = now.getlocal
|
|
175
|
+
|
|
172
176
|
stubs = simple_stubs
|
|
173
177
|
stubbed_time = Time.now if stubs.stubbing(Time, :now)
|
|
174
178
|
stubs.stub_object(Time, :now) { at(now) }
|
|
@@ -332,7 +332,7 @@ module ActiveSupport
|
|
|
332
332
|
#
|
|
333
333
|
def -(other)
|
|
334
334
|
if other.acts_like?(:time)
|
|
335
|
-
|
|
335
|
+
getutc - other.getutc
|
|
336
336
|
elsif duration_of_variable_length?(other)
|
|
337
337
|
method_missing(:-, other)
|
|
338
338
|
else
|
|
@@ -375,8 +375,8 @@ module ActiveSupport
|
|
|
375
375
|
#
|
|
376
376
|
# t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15.116992711 EST -05:00
|
|
377
377
|
# t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15.116992711 EST -05:00
|
|
378
|
-
# t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00.
|
|
379
|
-
# t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00.
|
|
378
|
+
# t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00.000000000 EST -05:00
|
|
379
|
+
# t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00.000000000 EST -05:00
|
|
380
380
|
# t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
|
|
381
381
|
# t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
|
|
382
382
|
def change(options)
|
|
@@ -506,6 +506,10 @@ module ActiveSupport
|
|
|
506
506
|
false
|
|
507
507
|
end
|
|
508
508
|
|
|
509
|
+
def present? # :nodoc:
|
|
510
|
+
true
|
|
511
|
+
end
|
|
512
|
+
|
|
509
513
|
def freeze
|
|
510
514
|
# preload instance variables before freezing
|
|
511
515
|
period; utc; time; to_datetime; to_time
|
|
@@ -134,10 +134,10 @@ module ActiveSupport
|
|
|
134
134
|
"Mumbai" => "Asia/Kolkata",
|
|
135
135
|
"New Delhi" => "Asia/Kolkata",
|
|
136
136
|
"Kathmandu" => "Asia/Kathmandu",
|
|
137
|
-
"Astana" => "Asia/Dhaka",
|
|
138
137
|
"Dhaka" => "Asia/Dhaka",
|
|
139
138
|
"Sri Jayawardenepura" => "Asia/Colombo",
|
|
140
139
|
"Almaty" => "Asia/Almaty",
|
|
140
|
+
"Astana" => "Asia/Almaty",
|
|
141
141
|
"Novosibirsk" => "Asia/Novosibirsk",
|
|
142
142
|
"Rangoon" => "Asia/Rangoon",
|
|
143
143
|
"Bangkok" => "Asia/Bangkok",
|
|
@@ -208,7 +208,9 @@ module ActiveSupport
|
|
|
208
208
|
TZInfo::Timezone.get(MAPPING[name] || name)
|
|
209
209
|
end
|
|
210
210
|
|
|
211
|
+
# :stopdoc:
|
|
211
212
|
alias_method :create, :new
|
|
213
|
+
# :startdoc:
|
|
212
214
|
|
|
213
215
|
# Returns a TimeZone instance with the given name, or +nil+ if no
|
|
214
216
|
# such TimeZone instance exists. (This exists to support the use of
|
|
@@ -296,15 +298,22 @@ module ActiveSupport
|
|
|
296
298
|
attr_reader :name
|
|
297
299
|
attr_reader :tzinfo
|
|
298
300
|
|
|
301
|
+
##
|
|
302
|
+
# :singleton-method: create
|
|
303
|
+
# :call-seq: create(name, utc_offset = nil, tzinfo = nil)
|
|
304
|
+
#
|
|
299
305
|
# Create a new TimeZone object with the given name and offset. The
|
|
300
306
|
# offset is the number of seconds that this time zone is offset from UTC
|
|
301
307
|
# (GMT). Seconds were chosen as the offset unit because that is the unit
|
|
302
308
|
# that Ruby uses to represent time zone offsets (see Time#utc_offset).
|
|
309
|
+
|
|
310
|
+
# :stopdoc:
|
|
303
311
|
def initialize(name, utc_offset = nil, tzinfo = nil)
|
|
304
312
|
@name = name
|
|
305
313
|
@utc_offset = utc_offset
|
|
306
314
|
@tzinfo = tzinfo || TimeZone.find_tzinfo(name)
|
|
307
315
|
end
|
|
316
|
+
# :startdoc:
|
|
308
317
|
|
|
309
318
|
# Returns the offset of this time zone from UTC in seconds.
|
|
310
319
|
def utc_offset
|