feat: add creator() factories for the Metabase asset family#975
Conversation
MetabaseCollection, MetabaseDashboard, and MetabaseQuestion shipped without a
.creator()/.create() factory, so connectors hand-build their qualifiedNames with
f-strings — duplicating Atlan's QN grammar per connector (the exact anti-pattern
the application-sdk conformance rule P028 flags).
Add creators that own the grammar centrally:
- MetabaseCollection.creator(name, connection_qualified_name, metabase_id)
-> {connection_qualified_name}/collections/{metabase_id}
- MetabaseDashboard.creator(...) -> {connection_qualified_name}/dashboards/{metabase_id}
- MetabaseQuestion.creator(...) -> {connection_qualified_name}/questions/{metabase_id}
The grammar is id-based (a Metabase system id in a typed segment) to match the
qualifiedNames connectors already write in production; a name-based grammar would
not match existing assets. This is a departure from the name-based house
convention and is called out for maintainer review.
Adds the generator method templates (methods/asset + methods/attribute) as the
source of truth, the regenerated asset methods, and parametrized creator tests
(creator, deprecated create warning, missing-param validation, modification).
Mirror the pyatlan Metabase creators into pyatlan_v9 (the package the metabase
connector actually imports). v9 uses the _overlays mechanism + flat asset
classes, so this adds:
- _overlays/metabase_{collection,dashboard,question}.py (creator source of truth)
- the merged creator/create/create_for_modification on the three flat asset
classes, importing init_guid/validate_required_fields from pyatlan_v9.utils
Same id-based, production-matching grammar as the pyatlan side
({connection_qualified_name}/collections/{metabase_id}, etc.). connector_name is
derived by splitting the connection qualified name, matching the v9 house pattern
(e.g. PresetWorkspace).
Update: mirrored into
|
Running the SDK generator against a live tenant reproduces the three Metabase creator files byte-identically from the jinja2 templates, except for one stray blank line between the atlan_fields import block and the pyatlan.utils import in metabase_collection.py that the generator does not emit. Drop it so the committed file matches true generator output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Connection-rooted integration coverage for MetabaseCollection/Dashboard/
Question .creator() factories: seeds one of each under a live Metabase
connection, asserts the id-based qualifiedName grammar
({connection_qualified_name}/{collections,dashboards,questions}/{metabase_id})
and connector_name, then exercises certificate/announcement update,
retrieve, delete and restore. Verified green against a real tenant
(7 passed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Verified against a real tenantGenerator (source-of-truth check). Ran
All creator / Integration tests ( Confirms the assets actually seed and round-trip on a real tenant. |
Problem
MetabaseCollection,MetabaseDashboard, andMetabaseQuestionship without a.creator()/.create()factory (they only havecreate_for_modification). Because there's no factory that owns the qualifiedName grammar, connectors hand-build MetabasequalifiedNames with f-strings — duplicating Atlan's QN grammar per connector. That's exactly the anti-pattern the application-sdk conformance rule P028ManualQualifiedNameFStringflags (11 live warnings on one connector today, unresolvable in the app because no upstream factory exists).Change
Adds creators that own the grammar centrally:
creator(...)MetabaseCollectionname, connection_qualified_name, metabase_id{connection_qualified_name}/collections/{metabase_id}MetabaseDashboardname, connection_qualified_name, metabase_id{connection_qualified_name}/dashboards/{metabase_id}MetabaseQuestionname, connection_qualified_name, metabase_id{connection_qualified_name}/questions/{metabase_id}Each follows the standard pattern:
creator()+ a deprecatedcreate()alias on the asset, and anAttributes.create()that builds the QN and derivesconnector_name.Design note — id-based grammar (for maintainer review)
The house convention builds QN from the name (
{connection_qualified_name}/{name}). The Metabase creators instead use an id-based grammar with a typed segment (/collections/{metabase_id}), because that is the qualifiedName connectors already write in production — a name-based grammar would not match existing assets and would break dedup/lineage on adoption. This PR effectively establishes the canonical Metabase QN grammar; flagging it explicitly in case maintainers prefer a different shape.What's included
methods/asset/metabase_{collection,dashboard,question}.jinja2+methods/attribute/....creator, deprecated-createwarning, missing-parameter validation, andcreate_for_modification/trim_to_required. 24 tests, all passing;ruff checkclean;black-formatted.Notes
metabase_idis typedstr(callers stringify the Metabase system id).HISTORY.mduntouched — it looks release-curated; happy to add an entry in whatever form you prefer.