<#3489 perf: :zap: Speed up method `MetadataMappin...
# meltano-repo-activity
g
#3489 perf: :zap: Speed up method `MetadataMapping.from_iterable` by 87% Pull request opened by codeflash-ai[bot] on <!date^1771365698^{date_short}|2026-02-17T22:01:38Z> 📄 87% (0.87x) speedup for
MetadataMapping.fromiterable
in
singersdk/singerlib/catalog.py
⏱️ Runtime :
2.25 milliseconds
→
1.21 milliseconds
(best of
250
runs) 📝 Explanation and details I cached the dataclass field-to-key mappings per class to avoid repeated reflection via dataclasses.fields() on every from_dict call, which reduces overhead when parsing many metadata entries. I also simplified the dict-construction loop to reuse the cached key pairs, lowering temporary allocations and improving throughput while preserving all original behavior and signatures. ✅ Correctness verification report: | Test | Status | | ----------------------------- | --------------- | | ⚙️ Existing Unit Tests | ✅ 35 Passed | | 🌀 Generated Regression Tests | ✅ 110 Passed | | ⏪ Replay Tests | 🔘 None Found | | 🔎 Concolic Coverage Tests | 🔘 None Found | | 📊 Tests Coverage | 100.0% | ⚙️ Click to see Existing Unit Tests | Test File::Test Function | Original ⏱️ | Optimized ⏱️ | Speedup | | ------------------------------------------------ | ----------- | ------------ | ------- | | singerlib/test_catalog.py::test_metadata_mapping | 9.33μs | 5.46μs | 71.0%✅ | 🌀 Click to see Generated Regression Tests # imports from future import annotations import pytest # used for our unit tests # import the real classes from the module under test from singer_sdk.singerlib.catalog import MetadataMapping def test_from_iterable_single_property_metadata_creates_metadata_instance(): # A simple iterable with one metadata entry for a non-root breadcrumb iterable = [ { "breadcrumb": ["properties", "id"], # list -> tuple('properties','id') "metadata": { # note: metadata keys that correspond to dataclass fields with underscores # are expected with dashes in the source dict (selected-by-default). "selected": True, "selected-by-default": False, }, } ] codeflash_output = MetadataMapping.from_iterable(iterable) mapping = codeflash_output # 2.17μs -> 1.21μs (79.2% faster) key = ("properties", "id") # expected breadcrumb key in the mapping value = mapping[key] def test_from_iterable_empty_breadcrumb_uses_streammetadata(): # When breadcrumb is an empty list, the mapping should use StreamMetadata iterable = [ { "breadcrumb": [], # empty breadcrumb -> root stream metadata "metadata": { "selected": False, # common field also expected on StreamMetadata }, } ] codeflash_output = MetadataMapping.from_iterable(iterable) mapping = codeflash_output # 2.88μs -> 1.54μs (86.4% faster) key = () # empty tuple is used as the mapping key for stream-level metadata value = mapping[key] def test_from_iterable_overwrites_with_last_occurrence(): # If the iterable contains multiple entries with the same breadcrumb, # the later entry should overwrite the earlier one. breadcrumb = ["properties", "name"] iterable = [ {"breadcrumb": breadcrumb, "metadata": {"selected": True}}, {"breadcrumb": breadcrumb, "metadata": {"selected": False}}, ] codeflash_output = MetadataMapping.from_iterable(iterable) mapping = codeflash_output # 3.08μs -> 1.71μs (80.5% faster) key = tuple(breadcrumb) def test_from_iterable_missing_keys_raises_keyerror(): # Items missing the 'breadcrumb' or 'metadata' key should raise KeyError iterable_missing_breadcrumb = [{"metadata": {"selected": True}}] iterable_missing_metadata = [{"breadcrumb": ["x"]}] with pytest.raises(KeyError): # 'breadcrumb' missing -> KeyError when d["breadcrumb"] is accessed MetadataMapping.from_iterable( iterable_missing_breadcrumb ) # 583ns -> 583ns (0.000% faster) with pytest.raises(KeyError): # 'metadata' missing -> KeyError when d["metadata"] is accessed MetadataMapping.from_iterable( iterable_missing_metadata ) # 375ns -> 416ns (9.86% slower) def test_from_iterable_non_iterable_breadcrumb_raises_typeerror(): # If breadcrumb value is not iterable (e.g., None), tuple(None) raises TypeError iterable = [{"breadcrumb": None, "metadata": {"selected": True}}] with pytest.raises(TypeError): MetadataMapping.from_iterable(iterable) # 750ns -> 750ns (0.000% faster) def test_empty_iterable_returns_empty_mapping(): # An empty iterable should produce an empty MetadataMapping codeflash_output = MetadataMapping.from_iterable([]) mapping = codeflash_output # 291ns -> 250ns (16.4% faster) def test_hyphenated_keys_map_to_underscored_fields(): # Verify that keys with dashes map to attributes with underscores iterable = [ { "breadcrumb": ["properties", "flag"], "metadata": { "selected-by-default": True, "selected": False, # inclusion key uses no dash here; ensure it passes through unchanged "inclusion": "some-inclusion-value", }, } ] codeflash_output = MetadataMapping.from_iterable(iterable) mapping = codeflash_output # 2.29μs -> 1.29μs (77.3% faster) value = mapping["properties", "flag"] def test___missing___creates_and_stores_defaults(): # missing should populate the mapping with a default Metadata for non-root breadcrumb mapping = MetadataMapping() # access a missing non-root breadcrumb missing_key = ("a",) result = mapping[missing_key] # triggers missing # access a missing root breadcrumb -> should be StreamMetadata root_key = () result_root = mapping[root_key] from future import annotations from singer_sdk.singerlib.catalog import MetadataMapping def test_from_iterable_empty(): """Test from_iterable with an empty iterable returns an empty MetadataMapping.""" codeflash_output = MetadataMapping.from_iterable([]) result = codeflash_output # 291ns -> 291ns (0.000% faster) def test_from_iterable_single_stream_metadata(): """Test from_iterable with a single stream-level metadata (empty breadcrumb).""" iterable = [ { "breadcrumb": [], "metadata": { "inclusion": "available", "selected": True, "selected-by-default": False, }, } ] codeflash_output = MetadataMapping.from_iterable(iterable) result = codeflash_output # 3.08μs -> 1.62μs (89.7% faster) metadata = result[()] def test_from_iterable_single_property_metadata(): """Test from_iterable with a single property-level metadata (non-empty breadcrumb).""" iterable = [ { "breadcrumb": ["properties", "id"], "metadata": { "inclusion": "available", "selected": True, }, } ] codeflash_output = MetadataMapping.from_iterable(iterable) result = codeflash_output # 2.08μs -> 1.17μs (78.6% faster) metadata = result["properties", "id"] def test_from_iterable_multiple_entries(): """Test from_iterable with multiple stream and property metadata entries.""" iterable = [ {"breadcrumb": [], "metadata": {"selected": True}}, {"breadcrumb": ["properties", "id"], "metadata": {"inclusion": "available"}}, {"breadcrumb": ["properties", "name"], "metadata": {"selected": False}}, ] codeflash_output = MetadataMapping.from_iterable(iterable) result = codeflash_output # 4.50μs ->… meltano/sdk