Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit 9daaf1f

Browse files
committed
Remove example_group example metadata sub-hash
See #1490, 9ffcc38
1 parent 820227c commit 9daaf1f

File tree

8 files changed

+35
-370
lines changed

8 files changed

+35
-370
lines changed

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Breaking Changes:
1313
* Raise on usage of metadata on suite-level scopes. (Phil Pirozhkov, #2849)
1414
* Raise an error when `fail_fast` is configured with
1515
an unsupported value. (Phil Pirozhkov, #2849)
16+
* Remove deprecated access to an example group's metadata through the example.
17+
(Phil Pirozhkov, #2851)
1618

1719
Enhancements:
1820

benchmarks/module_inclusion_filtering.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def initialize(*args)
1414
end
1515

1616
def include(mod, *filters)
17-
meta = RSpec::Core::Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
17+
meta = RSpec::Core::Metadata.build_hash_from(filters)
1818
@include_extend_or_prepend_modules << [:include, mod, meta]
1919
super
2020
end

lib/rspec/core/configuration.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ def alias_it_behaves_like_to(new_name, report_label='')
11631163
#
11641164
# filter_run_including :foo # same as filter_run_including :foo => true
11651165
def filter_run_including(*args)
1166-
meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering)
1166+
meta = Metadata.build_hash_from(args)
11671167
filter_manager.include_with_low_priority meta
11681168
static_config_filter_manager.include_with_low_priority Metadata.deep_hash_dup(meta)
11691169
end
@@ -1192,7 +1192,7 @@ def filter_run_when_matching(*args)
11921192
# This overrides any inclusion filters/tags set on the command line or in
11931193
# configuration files.
11941194
def inclusion_filter=(filter)
1195-
meta = Metadata.build_hash_from([filter], :warn_about_example_group_filtering)
1195+
meta = Metadata.build_hash_from([filter])
11961196
filter_manager.include_only meta
11971197
end
11981198

@@ -1237,7 +1237,7 @@ def inclusion_filter
12371237
#
12381238
# filter_run_excluding :foo # same as filter_run_excluding :foo => true
12391239
def filter_run_excluding(*args)
1240-
meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering)
1240+
meta = Metadata.build_hash_from(args)
12411241
filter_manager.exclude_with_low_priority meta
12421242
static_config_filter_manager.exclude_with_low_priority Metadata.deep_hash_dup(meta)
12431243
end
@@ -1250,7 +1250,7 @@ def filter_run_excluding(*args)
12501250
# This overrides any exclusion filters/tags set on the command line or in
12511251
# configuration files.
12521252
def exclusion_filter=(filter)
1253-
meta = Metadata.build_hash_from([filter], :warn_about_example_group_filtering)
1253+
meta = Metadata.build_hash_from([filter])
12541254
filter_manager.exclude_only meta
12551255
end
12561256

@@ -1732,7 +1732,7 @@ def raise_errors_for_deprecations!
17321732
# end
17331733
# end
17341734
def define_derived_metadata(*filters, &block)
1735-
meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1735+
meta = Metadata.build_hash_from(filters)
17361736
@derived_metadata_blocks.append(block, meta)
17371737
end
17381738

@@ -1755,7 +1755,7 @@ def define_derived_metadata(*filters, &block)
17551755
# end
17561756
# end
17571757
def when_first_matching_example_defined(*filters)
1758-
specified_meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
1758+
specified_meta = Metadata.build_hash_from(filters)
17591759

17601760
callback = lambda do |example_or_group_meta|
17611761
# Example groups do not have `:example_group` metadata
@@ -2194,7 +2194,7 @@ def define_mixed_in_module(mod, filters, mod_list, config_method, &block)
21942194
raise TypeError, "`RSpec.configuration.#{config_method}` expects a module but got: #{mod.inspect}"
21952195
end
21962196

2197-
meta = Metadata.build_hash_from(filters, :warn_about_example_group_filtering)
2197+
meta = Metadata.build_hash_from(filters)
21982198
mod_list.append(mod, meta)
21992199
on_existing_matching_groups(meta, &block)
22002200
end

lib/rspec/core/hooks.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ def process(host, parent_groups, globals, position, scope)
571571
def scope_and_options_from(*args)
572572
return :suite if args.first == :suite
573573
scope = extract_scope_from(args)
574-
meta = Metadata.build_hash_from(args, :warn_about_example_group_filtering)
574+
meta = Metadata.build_hash_from(args)
575575
return scope, meta
576576
end
577577

lib/rspec/core/metadata.rb

Lines changed: 7 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,11 @@ def self.ascend(metadata)
7777
# Symbols are converted into hash keys with a value of `true`.
7878
# This is done to support simple tagging using a symbol, rather
7979
# than needing to do `:symbol => true`.
80-
def self.build_hash_from(args, warn_about_example_group_filtering=false)
80+
def self.build_hash_from(args)
8181
hash = args.last.is_a?(Hash) ? args.pop : {}
8282

8383
hash[args.pop] = true while args.last.is_a?(Symbol)
8484

85-
if warn_about_example_group_filtering && hash.key?(:example_group)
86-
RSpec.deprecate("Filtering by an `:example_group` subhash",
87-
:replacement => "the subhash to filter directly")
88-
end
89-
9085
hash
9186
end
9287

@@ -213,11 +208,6 @@ def ensure_valid_user_keys
213208
class ExampleHash < HashPopulator
214209
def self.create(group_metadata, user_metadata, index_provider, description, block)
215210
example_metadata = group_metadata.dup
216-
group_metadata = Hash.new(&ExampleGroupHash.backwards_compatibility_default_proc do |hash|
217-
hash[:parent_example_group]
218-
end)
219-
group_metadata.update(example_metadata)
220-
221211
example_metadata[:execution_result] = Example::ExecutionResult.new
222212
example_metadata[:example_group] = group_metadata
223213
example_metadata[:shared_group_inclusion_backtrace] = SharedExampleGroupInclusionStackFrame.current_backtrace
@@ -246,59 +236,18 @@ def full_description
246236
# @private
247237
class ExampleGroupHash < HashPopulator
248238
def self.create(parent_group_metadata, user_metadata, example_group_index, *args, &block)
249-
group_metadata = hash_with_backwards_compatibility_default_proc
250-
251-
if parent_group_metadata
252-
group_metadata.update(parent_group_metadata)
253-
group_metadata[:parent_example_group] = parent_group_metadata
254-
end
239+
group_metadata =
240+
if parent_group_metadata
241+
{ **parent_group_metadata, :parent_example_group => parent_group_metadata }
242+
else
243+
{}
244+
end
255245

256246
hash = new(group_metadata, user_metadata, example_group_index, args, block)
257247
hash.populate
258248
hash.metadata
259249
end
260250

261-
def self.hash_with_backwards_compatibility_default_proc
262-
Hash.new(&backwards_compatibility_default_proc { |hash| hash })
263-
end
264-
265-
def self.backwards_compatibility_default_proc(&example_group_selector)
266-
Proc.new do |hash, key|
267-
case key
268-
when :example_group
269-
# We commonly get here when rspec-core is applying a previously
270-
# configured filter rule, such as when a gem configures:
271-
#
272-
# RSpec.configure do |c|
273-
# c.include MyGemHelpers, :example_group => { :file_path => /spec\/my_gem_specs/ }
274-
# end
275-
#
276-
# It's confusing for a user to get a deprecation at this point in
277-
# the code, so instead we issue a deprecation from the config APIs
278-
# that take a metadata hash, and MetadataFilter sets this thread
279-
# local to silence the warning here since it would be so
280-
# confusing.
281-
unless RSpec::Support.thread_local_data[:silence_metadata_example_group_deprecations]
282-
RSpec.deprecate("The `:example_group` key in an example group's metadata hash",
283-
:replacement => "the example group's hash directly for the " \
284-
"computed keys and `:parent_example_group` to access the parent " \
285-
"example group metadata")
286-
end
287-
288-
group_hash = example_group_selector.call(hash)
289-
LegacyExampleGroupHash.new(group_hash) if group_hash
290-
when :example_group_block
291-
RSpec.deprecate("`metadata[:example_group_block]`",
292-
:replacement => "`metadata[:block]`")
293-
hash[:block]
294-
when :describes
295-
RSpec.deprecate("`metadata[:describes]`",
296-
:replacement => "`metadata[:described_class]`")
297-
hash[:described_class]
298-
end
299-
end
300-
end
301-
302251
private
303252

304253
def described_class
@@ -443,56 +392,5 @@ def attr_accessor(*names)
443392
end
444393
end
445394
end
446-
447-
# @private
448-
# Together with the example group metadata hash default block,
449-
# provides backwards compatibility for the old `:example_group`
450-
# key. In RSpec 2.x, the computed keys of a group's metadata
451-
# were exposed from a nested subhash keyed by `[:example_group]`, and
452-
# then the parent group's metadata was exposed by sub-subhash
453-
# keyed by `[:example_group][:example_group]`.
454-
#
455-
# In RSpec 3, we reorganized this to that the computed keys are
456-
# exposed directly of the group metadata hash (no nesting), and
457-
# `:parent_example_group` returns the parent group's metadata.
458-
#
459-
# Maintaining backwards compatibility was difficult: we wanted
460-
# `:example_group` to return an object that:
461-
#
462-
# * Exposes the top-level metadata keys that used to be nested
463-
# under `:example_group`.
464-
# * Supports mutation (rspec-rails, for example, assigns
465-
# `metadata[:example_group][:described_class]` when you use
466-
# anonymous controller specs) such that changes are written
467-
# back to the top-level metadata hash.
468-
# * Exposes the parent group metadata as
469-
# `[:example_group][:example_group]`.
470-
class LegacyExampleGroupHash
471-
include HashImitatable
472-
473-
def initialize(metadata)
474-
@metadata = metadata
475-
parent_group_metadata = metadata.fetch(:parent_example_group) { {} }[:example_group]
476-
self[:example_group] = parent_group_metadata if parent_group_metadata
477-
end
478-
479-
def to_h
480-
super.merge(@metadata)
481-
end
482-
483-
private
484-
485-
def directly_supports_attribute?(name)
486-
name != :example_group
487-
end
488-
489-
def get_value(name)
490-
@metadata[name]
491-
end
492-
493-
def set_value(name, value)
494-
@metadata[name] = value
495-
end
496-
end
497395
end
498396
end

lib/rspec/core/metadata_filter.rb

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,17 @@ def apply?(predicate, filters, metadata)
1414

1515
# @private
1616
def filter_applies?(key, filter_value, metadata)
17-
silence_metadata_example_group_deprecations do
18-
return location_filter_applies?(filter_value, metadata) if key == :locations
19-
return id_filter_applies?(filter_value, metadata) if key == :ids
20-
return filters_apply?(key, filter_value, metadata) if Hash === filter_value
17+
return location_filter_applies?(filter_value, metadata) if key == :locations
18+
return id_filter_applies?(filter_value, metadata) if key == :ids
19+
return filters_apply?(key, filter_value, metadata) if Hash === filter_value
2120

22-
meta_value = metadata.fetch(key) { return false }
21+
meta_value = metadata.fetch(key) { return false }
2322

24-
return true if TrueClass === filter_value && meta_value
25-
return proc_filter_applies?(key, filter_value, metadata) if Proc === filter_value
26-
return filter_applies_to_any_value?(key, filter_value, metadata) if Array === meta_value
23+
return true if TrueClass === filter_value && meta_value
24+
return proc_filter_applies?(key, filter_value, metadata) if Proc === filter_value
25+
return filter_applies_to_any_value?(key, filter_value, metadata) if Array === meta_value
2726

28-
filter_value === meta_value || filter_value.to_s == meta_value.to_s
29-
end
30-
end
31-
32-
# @private
33-
def silence_metadata_example_group_deprecations
34-
RSpec::Support.thread_local_data[:silence_metadata_example_group_deprecations] = true
35-
yield
36-
ensure
37-
RSpec::Support.thread_local_data.delete(:silence_metadata_example_group_deprecations)
27+
filter_value === meta_value || filter_value.to_s == meta_value.to_s
3828
end
3929

4030
private
@@ -72,7 +62,7 @@ def proc_filter_applies?(key, proc, metadata)
7262

7363
def filters_apply?(key, value, metadata)
7464
subhash = metadata[key]
75-
return false unless Hash === subhash || HashImitatable === subhash
65+
return false unless Hash === subhash
7666
value.all? { |k, v| filter_applies?(k, v, subhash) }
7767
end
7868
end
@@ -201,21 +191,10 @@ def handle_mutation(metadata)
201191
@memoized_lookups.clear
202192
end
203193

194+
# Ruby 2.3 and 2.4 do not have `Hash#slice`
204195
def applicable_metadata_from(metadata)
205-
MetadataFilter.silence_metadata_example_group_deprecations do
206-
@applicable_keys.inject({}) do |hash, key|
207-
# :example_group is treated special here because...
208-
# - In RSpec 2, example groups had an `:example_group` key
209-
# - In RSpec 3, that key is deprecated (it was confusing!).
210-
# - The key is not technically present in an example group metadata hash
211-
# (and thus would fail the `metadata.key?(key)` check) but a value
212-
# is provided when accessed via the hash's `default_proc`
213-
# - Thus, for backwards compatibility, we have to explicitly check
214-
# for `:example_group` here if it is one of the keys being used to
215-
# filter.
216-
hash[key] = metadata[key] if metadata.key?(key) || key == :example_group
217-
hash
218-
end
196+
@applicable_keys.each_with_object({}) do |key, hash|
197+
hash[key] = metadata[key] if metadata.key?(key)
219198
end
220199
end
221200

0 commit comments

Comments
 (0)