Skip to content

feat: Publish a singer-python and pipelinewise-singer-python replacement - #3701

Draft
edgarrmondragon wants to merge 44 commits into
mainfrom
singer-python-package
Draft

edgarrmondragon wants to merge 44 commits into
mainfrom
singer-python-package

Conversation

@edgarrmondragon

Copy link
Copy Markdown
Collaborator

No description provided.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @edgarrmondragon, your pull request is larger than the review limit of 150000 diff characters

@read-the-docs-community

read-the-docs-community Bot commented Jul 15, 2026

Copy link
Copy Markdown

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.52%. Comparing base (747fc9a) to head (7e9e70c).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3701      +/-   ##
==========================================
+ Coverage   94.35%   94.52%   +0.16%     
==========================================
  Files          74       87      +13     
  Lines        6294     6462     +168     
  Branches      770      783      +13     
==========================================
+ Hits         5939     6108     +169     
+ Misses        266      265       -1     
  Partials       89       89              
Flag Coverage Δ
core 83.39% <99.44%> (+0.45%) ⬆️
end-to-end 74.99% <75.19%> (-0.62%) ⬇️
optional-components 45.28% <56.95%> (+0.25%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed-hq

codspeed-hq Bot commented Jul 15, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 14 untouched benchmarks


Comparing singer-python-package (7e9e70c) with main (747fc9a)

Open in CodSpeed

@edgarrmondragon
edgarrmondragon force-pushed the singer-python-package branch 3 times, most recently from f696016 to 4d18542 Compare July 15, 2026 23:43
The code in singer_sdk/singerlib now lives in
packages/meltano-singer-python as the top-level `singer` package,
published as the meltano-singer-python distribution. singer-sdk now
depends on it and singer_sdk.singerlib re-exports the same objects as
a stable alias.
…er package

singer.metrics now hosts the meters, points, and exclusion filter, plus
legacy singer-python factories (record_counter(endpoint=...),
http_request_timer, job_timer). singer_sdk.metrics re-exports the core
and keeps the SDK-flavored stream-based factories.

BREAKING CHANGE: the metrics logger is now named singer.metrics instead
of singer_sdk.metrics, and metric points carry a pid tag.

singer.logging hosts ConsoleFormatter/StructuredFormatter, and
singer.get_logger configures logging from SINGER_SDK_LOG_CONFIG
(dictConfig, as generated by Meltano) or LOGGING_CONF_FILE (INI,
pipelinewise-compatible).
Adds singer.bookmarks, singer.metadata, and extends singer.utils
(now, load_json, check_config, parse_args) and singer.catalog
(Catalog.load/dump) to port the legacy singer-python API. Message
classes gain a legacy asdict() alongside to_dict(). singer.__init__
gains write_record/write_schema/write_state/write_version and
should_sync_field, matching the legacy top-level API.

The deprecated --properties CLI flag is intentionally not supported;
use --catalog instead.
singer.batch now hosts BaseBatchFileEncoding and BatchMessage.
singer_sdk.helpers._batch keeps SDKBatchMessage as an alias for
BatchMessage, plus the fsspec-coupled StorageTarget/BatchConfig and
the deprecated JSONLinesEncoding/ParquetEncoding wrappers.
BatchFileFormat (jsonl/parquet) is left untouched in the SDK, since
encoding.format is already a plain string and taps can pass
format='arrow' without any enum change.
Extends the release workflow to build, attest, and publish
meltano-singer-python alongside singer-sdk on the same tag. Adds a
migration guide for singer-python/pipelinewise-singer-python users,
and documents the singer.metrics logger rename.
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
…log.from_entries

write() had regressed to a no-op on breadcrumbs not already present in
the compiled map, silently breaking get_standard_metadata() (which
always starts from an empty mapping) and any first write to a new
stream/field. Restored legacy semantics: create the breadcrumb entry
if missing.

Catalog.from_entries() called cls({"streams": ...}), which invokes
dict.__init__ directly and does not go through from_dict — it built a
single-key mapping instead of one keyed by tap_stream_id. Fixed to
build the catalog the same way from_dict/add_stream do.
… replication-method/view-key-properties

CatalogEntry.metadata is a MetadataMapping (already compiled, keyed by
breadcrumb, with typed Metadata/StreamMetadata values), not the raw
legacy list-of-entries form. Legacy taps calling
metadata.to_map(catalog_entry.metadata) — as pipelinewise-singer-python
callers do — got a TypeError, since to_map() assumed a raw list.
to_map() now also accepts any breadcrumb-keyed mapping and compiles it
to the same raw dict-of-dicts shape, converting typed values via
to_dict() where available.

StreamMetadata had no field for 'replication-method' or
'view-key-properties' (only its own 'forced-replication-method'), so
both keys were silently dropped whenever stream metadata passed
through Catalog.load()/from_dict() or MetadataMapping.to_list() -- a
real data-loss bug for any orchestrator-set replication method. Added
replication_method and view_key_properties fields.
Legacy singer-python code (and tests written against it) constructs
CatalogEntry(metadata=[{'breadcrumb': [...], 'metadata': {...}}, ...])
directly, passing the raw list-of-entries form rather than a compiled
MetadataMapping. CatalogEntry.metadata is typed as MetadataMapping, so
this previously left .metadata as a plain list, breaking any code that
expects mapping access (e.g. .root, breadcrumb indexing). __post_init__
now coerces a raw list the same way BatchMessage/BatchConfig already
coerce their dict-shaped fields.
…ard_metadata()

Verified against singer-io/singer-python's metadata.py directly. Two
deviations found and fixed:
- new() returned a defaultdict(dict), which silently auto-vivifies
  missing breadcrumbs on any access (e.g. 'x in mdata' or mdata[k]);
  upstream returns a plain {} with normal KeyError semantics.
- get_standard_metadata() marked properties in valid_replication_keys
  as 'automatic' inclusion in addition to key_properties; upstream
  only does this for key_properties.

CompiledMetadata stays as the concrete dict[Breadcrumb, dict[str, Any]]
type: write()/delete()/get()/to_list()/new() all need dict mutation
semantics that a read-only Mapping can't provide, matching upstream's
own plain-dict design for this module.
tap-mysql, the first real consumer of meltano-singer-python, migrated
every metadata.to_map()/metadata.get() call site to direct
MetadataMapping/Metadata attribute access
(catalog_entry.metadata.root.replication_method,
catalog_entry.metadata['properties', name].inclusion), since
CatalogEntry.metadata is always a MetadataMapping already. Keeping the
functional dict-based module around as unused, untested surface added
maintenance cost without a real consumer.

BREAKING CHANGE: singer.metadata (new/to_map/to_list/write/get/delete/
get_standard_metadata) no longer exists. Use CatalogEntry.metadata
(a MetadataMapping) directly instead.
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
@edgarrmondragon
edgarrmondragon force-pushed the singer-python-package branch from 4d18542 to 20bd215 Compare July 15, 2026 23:54
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
@edgarrmondragon
edgarrmondragon force-pushed the singer-python-package branch from 141474f to 89a157a Compare July 17, 2026 01:41
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
This reverts commit 4b0e120.
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant