Skip to content

feat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py#1980

Open
cmgrote wants to merge 8 commits into
mainfrom
fix/toolkit-codegen
Open

feat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py#1980
cmgrote wants to merge 8 commits into
mainfrom
fix/toolkit-codegen

Conversation

@cmgrote
Copy link
Copy Markdown
Collaborator

@cmgrote cmgrote commented Jun 3, 2026

Summary

  • Adds three generator functions to App.pkl so pkl eval -m . contract/app.pkl now produces the e2e test harness files that were previously hand-authored (with misleading "Generated from contract/app.pkl" banners that weren't true)
  • Adds three overridable contract fields — argoPackageName, argoTemplateName, appServiceUrl — with defaults derived from name; 95% of connectors never override
  • Extends scripts/test-sdk-import.py to import-test all generated _e2e_*.py files (was only testing _input.py)
  • Updates docstrings in testing/e2e/credential.py and testing/e2e/substitutions.py to reference the actual codegen functions instead of the never-created E2EOutput.pkl

What's generated

File Emitted when
_e2e_base.py Always
_e2e_credential.py hasCredentialConfig = true and at least one auth option defined
_e2e_substitutions.py uiConfig has fields beyond what the parent class already provides

Base class routing: warehouse/database/lake/queryengine connectors → SQLAppE2ETest / SQLMustacheSubstitutions; others → BaseE2ETest / MustacheSubstitutions.

Widget-type-aware substitution typing: Literal[...] for bounded Radio/DropDown, bool for BooleanInput, int for NumericInput, dict[str, Any] | None for SqlTree/NestedInput — so import_type="HTTP" against the OpenAPI connector (valid values: "URL", "CLOUD") fails at type-check time, not at runtime.

Credential body: all auth options unioned into one model; auth-specific-only fields get empty-string defaults; ConditionalFieldSpecs become str | None.

Verification

bash scripts/regenerate-all.sh   # all 7 examples regenerate cleanly
bash scripts/check-invariants.sh # all invariant checks pass
pkl test tests/*.pkl             # 78/78 tests pass
uv run python scripts/test-sdk-import.py  # 25/25 files import (8 _input.py + 17 _e2e_*.py)

Follow-up (separate PRs in consumer repos, after toolkit version bump)

  • atlan-openapi-app: regenerate to replace AtlanConnectorType.API.value indirection with connection_type = "api"
  • atlan-mysql-app: regenerate to gain iam_user/iam_role union'd fields and the missing banner header

🤖 Generated with Claude Code

…e_substitutions.py

Adds three new generator functions to App.pkl so that `pkl eval -m . contract/app.pkl`
now produces the e2e test harness files that were previously hand-authored (and had
already drifted — mysql's _e2e_credential.py silently dropped iam_user/iam_role fields).

Changes:
- App.pkl: new contract fields `argoPackageName`, `argoTemplateName`, `appServiceUrl`
  (defaults derived from `name`; 95% of connectors never override)
- App.pkl: `generateE2EBasePy()` — always emits `_e2e_base.py` with required harness
  attrs; routes to SQLAppE2ETest for warehouse/database/lake/queryengine connectors
- App.pkl: `generateE2ECredentialPy()` — emits `_e2e_credential.py` when credential
  config is present; unions all auth options into one model (auth-specific fields get
  empty defaults); extraFields from the URL group become Optional fields
- App.pkl: `generateE2ESubstitutionsPy()` — emits `_e2e_substitutions.py` when
  uiConfig has fields beyond the parent class; widget-type-aware typing
  (Literal[...] for bounded Radio/DropDown, bool for BooleanInput, int for NumericInput,
  dict[str,Any]|None for SqlTree/NestedInput)
- scripts/test-sdk-import.py: extended to also import-test all generated _e2e_*.py files
- testing/e2e/credential.py + substitutions.py: docstrings updated from aspirational
  (E2EOutput.pkl) to descriptive (generateE2ECredentialPy / generateE2ESubstitutionsPy)
- examples/*/app/generated/_e2e_*.py: golden fixtures for all 7 examples
Copilot AI review requested due to automatic review settings June 3, 2026 12:10
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

Docs reminder: contract-toolkit/src/ changed, but these docs were not updated:

  • contract-toolkit/README.md
  • contract-toolkit/docs/reference.md

Per toolkit convention, public PKL changes should update:

  • contract-toolkit/README.md
  • contract-toolkit/docs/reference.md

Ignore this reminder only when the source change is internal and has no author-facing impact.

@snykgituser
Copy link
Copy Markdown

snykgituser commented Jun 3, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

📜 Docstring Coverage Report

RESULT: PASSED (minimum: 30.0%, actual: 77.6%)

Detailed Coverage Report
======= Coverage for /home/runner/work/application-sdk/application-sdk/ ========
----------------------------------- Summary ------------------------------------
| Name                                                                           | Total | Miss | Cover | Cover% |
|--------------------------------------------------------------------------------|-------|------|-------|--------|
| .claude/skills/capability-manifest/references/extractor.py                     |    21 |    2 |    19 |    90% |
| .mothership/sdk-evolution/scripts/update_index.py                              |    10 |    2 |     8 |    80% |
| application_sdk/__init__.py                                                    |     1 |    0 |     1 |   100% |
| application_sdk/_discovery_errors.py                                           |     7 |    0 |     7 |   100% |
| application_sdk/constants.py                                                   |     3 |    1 |     2 |    67% |
| application_sdk/discovery.py                                                   |    12 |    3 |     9 |    75% |
| application_sdk/main.py                                                        |    31 |    6 |    25 |    81% |
| application_sdk/main_errors.py                                                 |     5 |    0 |     5 |   100% |
| application_sdk/version.py                                                     |     1 |    0 |     1 |   100% |
| application_sdk/app/__init__.py                                                |     1 |    0 |     1 |   100% |
| application_sdk/app/base.py                                                    |    75 |   18 |    57 |    76% |
| application_sdk/app/base_errors.py                                             |     5 |    0 |     5 |   100% |
| application_sdk/app/client.py                                                  |     1 |    0 |     1 |   100% |
| application_sdk/app/context.py                                                 |    39 |    2 |    37 |    95% |
| application_sdk/app/entrypoint.py                                              |    13 |    4 |     9 |    69% |
| application_sdk/app/registry.py                                                |    37 |   11 |    26 |    70% |
| application_sdk/app/task.py                                                    |    14 |    6 |     8 |    57% |
| application_sdk/clients/__init__.py                                            |     2 |    1 |     1 |    50% |
| application_sdk/clients/_interface.py                                          |     4 |    1 |     3 |    75% |
| application_sdk/clients/base.py                                                |     6 |    1 |     5 |    83% |
| application_sdk/clients/models.py                                              |     2 |    0 |     2 |   100% |
| application_sdk/clients/redis.py                                               |    27 |    0 |    27 |   100% |
| application_sdk/clients/redis_errors.py                                        |     5 |    0 |     5 |   100% |
| application_sdk/clients/sql.py                                                 |    23 |    1 |    22 |    96% |
| application_sdk/clients/sql_errors.py                                          |    11 |    0 |    11 |   100% |
| application_sdk/clients/sql_typecasters.py                                     |    10 |    4 |     6 |    60% |
| application_sdk/clients/ssl_utils.py                                           |     8 |    0 |     8 |   100% |
| application_sdk/clients/azure/__init__.py                                      |     1 |    0 |     1 |   100% |
| application_sdk/clients/azure/auth.py                                          |     7 |    0 |     7 |   100% |
| application_sdk/clients/azure/azure_errors.py                                  |     8 |    0 |     8 |   100% |
| application_sdk/clients/azure/client.py                                        |    13 |    0 |    13 |   100% |
| application_sdk/common/__init__.py                                             |     1 |    0 |     1 |   100% |
| application_sdk/common/_env.py                                                 |     2 |    0 |     2 |   100% |
| application_sdk/common/aws_utils.py                                            |    10 |    1 |     9 |    90% |
| application_sdk/common/aws_utils_errors.py                                     |     7 |    0 |     7 |   100% |
| application_sdk/common/concurrency.py                                          |     3 |    0 |     3 |   100% |
| application_sdk/common/env_warnings.py                                         |     2 |    0 |     2 |   100% |
| application_sdk/common/error_codes.py                                          |    15 |    3 |    12 |    80% |
| application_sdk/common/errors.py                                               |     6 |    0 |     6 |   100% |
| application_sdk/common/file_converter.py                                       |     9 |    5 |     4 |    44% |
| application_sdk/common/file_ops.py                                             |    16 |    1 |    15 |    94% |
| application_sdk/common/models.py                                               |     4 |    2 |     2 |    50% |
| application_sdk/common/path.py                                                 |     2 |    1 |     1 |    50% |
| application_sdk/common/spillable_dict.py                                       |    17 |   11 |     6 |    35% |
| application_sdk/common/sql_filters.py                                          |    13 |    1 |    12 |    92% |
| application_sdk/common/sql_filters_errors.py                                   |     2 |    0 |     2 |   100% |
| application_sdk/common/transforms.py                                           |     5 |    0 |     5 |   100% |
| application_sdk/common/types.py                                                |     2 |    1 |     1 |    50% |
| application_sdk/common/utils.py                                                |     2 |    0 |     2 |   100% |
| application_sdk/common/incremental/__init__.py                                 |     1 |    1 |     0 |     0% |
| application_sdk/common/incremental/helpers.py                                  |    12 |    1 |    11 |    92% |
| application_sdk/common/incremental/incremental_errors.py                       |    11 |    0 |    11 |   100% |
| application_sdk/common/incremental/marker.py                                   |     5 |    0 |     5 |   100% |
| application_sdk/common/incremental/models.py                                   |    10 |    0 |    10 |   100% |
| application_sdk/common/incremental/column_extraction/__init__.py               |     1 |    0 |     1 |   100% |
| application_sdk/common/incremental/column_extraction/analysis.py               |     3 |    0 |     3 |   100% |
| application_sdk/common/incremental/column_extraction/backfill.py               |     3 |    0 |     3 |   100% |
| application_sdk/common/incremental/state/__init__.py                           |     1 |    1 |     0 |     0% |
| application_sdk/common/incremental/state/incremental_diff.py                   |     8 |    0 |     8 |   100% |
| application_sdk/common/incremental/state/state_reader.py                       |     2 |    0 |     2 |   100% |
| application_sdk/common/incremental/state/state_writer.py                       |    10 |    0 |    10 |   100% |
| application_sdk/common/incremental/state/table_scope.py                        |     8 |    0 |     8 |   100% |
| application_sdk/common/incremental/storage/__init__.py                         |     1 |    1 |     0 |     0% |
| application_sdk/common/incremental/storage/duckdb_utils.py                     |    12 |    2 |    10 |    83% |
| application_sdk/common/incremental/storage/rocksdb_utils.py                    |     3 |    0 |     3 |   100% |
| application_sdk/contracts/__init__.py                                          |     1 |    0 |     1 |   100% |
| application_sdk/contracts/base.py                                              |    37 |    7 |    30 |    81% |
| application_sdk/contracts/cleanup.py                                           |     5 |    0 |     5 |   100% |
| application_sdk/contracts/events.py                                            |    12 |    0 |    12 |   100% |
| application_sdk/contracts/storage.py                                           |     6 |    1 |     5 |    83% |
| application_sdk/contracts/types.py                                             |    15 |    0 |    15 |   100% |
| application_sdk/contracts/types_errors.py                                      |     2 |    0 |     2 |   100% |
| application_sdk/credentials/__init__.py                                        |     1 |    0 |     1 |   100% |
| application_sdk/credentials/agent.py                                           |     7 |    1 |     6 |    86% |
| application_sdk/credentials/atlan.py                                           |    12 |    6 |     6 |    50% |
| application_sdk/credentials/atlan_client.py                                    |     6 |    0 |     6 |   100% |
| application_sdk/credentials/errors.py                                          |    20 |   12 |     8 |    40% |
| application_sdk/credentials/git.py                                             |     9 |    6 |     3 |    33% |
| application_sdk/credentials/oauth.py                                           |    13 |    2 |    11 |    85% |
| application_sdk/credentials/ref.py                                             |    16 |    1 |    15 |    94% |
| application_sdk/credentials/registry.py                                        |    11 |    3 |     8 |    73% |
| application_sdk/credentials/resolver.py                                        |    11 |    4 |     7 |    64% |
| application_sdk/credentials/spec.py                                            |     6 |    1 |     5 |    83% |
| application_sdk/credentials/types.py                                           |    35 |   17 |    18 |    51% |
| application_sdk/credentials/utils.py                                           |     3 |    0 |     3 |   100% |
| application_sdk/dev/__init__.py                                                |     1 |    0 |     1 |   100% |
| application_sdk/dev/_dapr.py                                                   |    11 |    2 |     9 |    82% |
| application_sdk/dev/_dapr_errors.py                                            |     5 |    4 |     1 |    20% |
| application_sdk/dev/_embedded.py                                               |     3 |    0 |     3 |   100% |
| application_sdk/errors/__init__.py                                             |     4 |    1 |     3 |    75% |
| application_sdk/errors/base.py                                                 |     8 |    2 |     6 |    75% |
| application_sdk/errors/categories.py                                           |     3 |    0 |     3 |   100% |
| application_sdk/errors/leaves.py                                               |    15 |    8 |     7 |    47% |
| application_sdk/errors/wire.py                                                 |     3 |    1 |     2 |    67% |
| application_sdk/execution/__init__.py                                          |     1 |    0 |     1 |   100% |
| application_sdk/execution/decorators.py                                        |     3 |    2 |     1 |    33% |
| application_sdk/execution/errors.py                                            |     2 |    0 |     2 |   100% |
| application_sdk/execution/heartbeat.py                                         |    17 |    2 |    15 |    88% |
| application_sdk/execution/retry.py                                             |     7 |    0 |     7 |   100% |
| application_sdk/execution/sandbox.py                                           |     4 |    0 |     4 |   100% |
| application_sdk/execution/settings.py                                          |     6 |    1 |     5 |    83% |
| application_sdk/execution/shutdown.py                                          |     4 |    0 |     4 |   100% |
| application_sdk/execution/_temporal/__init__.py                                |     1 |    1 |     0 |     0% |
| application_sdk/execution/_temporal/_activity_errors.py                        |     7 |    0 |     7 |   100% |
| application_sdk/execution/_temporal/_backend_errors.py                         |     5 |    4 |     1 |    20% |
| application_sdk/execution/_temporal/_lock_errors.py                            |     5 |    0 |     5 |   100% |
| application_sdk/execution/_temporal/activities.py                              |     7 |    0 |     7 |   100% |
| application_sdk/execution/_temporal/activity_utils.py                          |     6 |    0 |     6 |   100% |
| application_sdk/execution/_temporal/auth.py                                    |    12 |    0 |    12 |   100% |
| application_sdk/execution/_temporal/backend.py                                 |    12 |    1 |    11 |    92% |
| application_sdk/execution/_temporal/converter.py                               |     3 |    0 |     3 |   100% |
| application_sdk/execution/_temporal/eviction_retry.py                          |     3 |    0 |     3 |   100% |
| application_sdk/execution/_temporal/lock_activities.py                         |     3 |    0 |     3 |   100% |
| application_sdk/execution/_temporal/sdr.py                                     |    13 |    7 |     6 |    46% |
| application_sdk/execution/_temporal/worker.py                                  |    10 |    5 |     5 |    50% |
| application_sdk/execution/_temporal/workflows.py                               |     2 |    0 |     2 |   100% |
| application_sdk/execution/_temporal/interceptors/__init__.py                   |     1 |    0 |     1 |   100% |
| application_sdk/execution/_temporal/interceptors/events.py                     |    13 |    0 |    13 |   100% |
| application_sdk/execution/_temporal/interceptors/lock.py                       |    10 |    2 |     8 |    80% |
| application_sdk/execution/_temporal/interceptors/log.py                        |    19 |   12 |     7 |    37% |
| application_sdk/execution/_temporal/interceptors/metrics.py                    |    16 |   13 |     3 |    19% |
| application_sdk/execution/_temporal/interceptors/outputs.py                    |     9 |    0 |     9 |   100% |
| application_sdk/execution/_temporal/interceptors/trace.py                      |     6 |    4 |     2 |    33% |
| application_sdk/handler/__init__.py                                            |     1 |    0 |     1 |   100% |
| application_sdk/handler/base.py                                                |    14 |    3 |    11 |    79% |
| application_sdk/handler/context.py                                             |    17 |    5 |    12 |    71% |
| application_sdk/handler/contracts.py                                           |    32 |    3 |    29 |    91% |
| application_sdk/handler/manifest.py                                            |     5 |    0 |     5 |   100% |
| application_sdk/handler/service.py                                             |    44 |   23 |    21 |    48% |
| application_sdk/handler/service_errors.py                                      |     4 |    0 |     4 |   100% |
| application_sdk/infrastructure/__init__.py                                     |     1 |    0 |     1 |   100% |
| application_sdk/infrastructure/_secret_utils.py                                |     2 |    0 |     2 |   100% |
| application_sdk/infrastructure/bindings.py                                     |    16 |    3 |    13 |    81% |
| application_sdk/infrastructure/capacity.py                                     |    11 |    0 |    11 |   100% |
| application_sdk/infrastructure/context.py                                      |     6 |    0 |     6 |   100% |
| application_sdk/infrastructure/credential_vault.py                             |     7 |    3 |     4 |    57% |
| application_sdk/infrastructure/pubsub.py                                       |    13 |    3 |    10 |    77% |
| application_sdk/infrastructure/secrets.py                                      |    21 |    6 |    15 |    71% |
| application_sdk/infrastructure/state.py                                        |    10 |    7 |     3 |    30% |
| application_sdk/infrastructure/_dapr/__init__.py                               |     1 |    0 |     1 |   100% |
| application_sdk/infrastructure/_dapr/_dapr_errors.py                           |     3 |    0 |     3 |   100% |
| application_sdk/infrastructure/_dapr/client.py                                 |    28 |    4 |    24 |    86% |
| application_sdk/infrastructure/_dapr/credential_vault.py                       |    13 |    4 |     9 |    69% |
| application_sdk/infrastructure/_dapr/http.py                                   |    17 |   12 |     5 |    29% |
| application_sdk/infrastructure/_redis/__init__.py                              |     1 |    0 |     1 |   100% |
| application_sdk/infrastructure/_redis/capacity.py                              |     9 |    4 |     5 |    56% |
| application_sdk/observability/__init__.py                                      |     1 |    1 |     0 |     0% |
| application_sdk/observability/_objectstore_metric_exporter.py                  |    13 |    8 |     5 |    38% |
| application_sdk/observability/_objectstore_metric_reader.py                    |     2 |    0 |     2 |   100% |
| application_sdk/observability/_prometheus_enrichment.py                        |     6 |    3 |     3 |    50% |
| application_sdk/observability/context.py                                       |     4 |    0 |     4 |   100% |
| application_sdk/observability/correlation.py                                   |     6 |    0 |     6 |   100% |
| application_sdk/observability/logger_adaptor.py                                |    46 |    8 |    38 |    83% |
| application_sdk/observability/logger_adaptor_errors.py                         |     2 |    0 |     2 |   100% |
| application_sdk/observability/metrics.py                                       |     8 |    6 |     2 |    25% |
| application_sdk/observability/metrics_adaptor.py                               |    13 |    2 |    11 |    85% |
| application_sdk/observability/models.py                                        |     6 |    0 |     6 |   100% |
| application_sdk/observability/observability.py                                 |    19 |    4 |    15 |    79% |
| application_sdk/observability/pushgateway.py                                   |    16 |   11 |     5 |    31% |
| application_sdk/observability/pushgateway_errors.py                            |     3 |    0 |     3 |   100% |
| application_sdk/observability/resource_sampler.py                              |     5 |    0 |     5 |   100% |
| application_sdk/observability/segment_client.py                                |    15 |    1 |    14 |    93% |
| application_sdk/observability/trace_context.py                                 |     2 |    0 |     2 |   100% |
| application_sdk/observability/traces_adaptor.py                                |    15 |    1 |    14 |    93% |
| application_sdk/observability/utils.py                                         |     7 |    1 |     6 |    86% |
| application_sdk/observability/decorators/observability_decorator.py            |     7 |    4 |     3 |    43% |
| application_sdk/outputs/__init__.py                                            |     2 |    0 |     2 |   100% |
| application_sdk/outputs/collector.py                                           |     9 |    0 |     9 |   100% |
| application_sdk/outputs/models.py                                              |     3 |    0 |     3 |   100% |
| application_sdk/server/health.py                                               |    20 |    0 |    20 |   100% |
| application_sdk/server/fastapi/models.py                                       |    21 |   17 |     4 |    19% |
| application_sdk/server/fastapi/utils.py                                        |     5 |    0 |     5 |   100% |
| application_sdk/server/mcp/__init__.py                                         |     2 |    2 |     0 |     0% |
| application_sdk/server/mcp/decorators.py                                       |     3 |    1 |     2 |    67% |
| application_sdk/server/mcp/models.py                                           |     2 |    2 |     0 |     0% |
| application_sdk/server/mcp/server.py                                           |     5 |    0 |     5 |   100% |
| application_sdk/server/middleware/__init__.py                                  |     1 |    0 |     1 |   100% |
| application_sdk/server/middleware/_constants.py                                |     1 |    0 |     1 |   100% |
| application_sdk/server/middleware/log.py                                       |     4 |    3 |     1 |    25% |
| application_sdk/storage/__init__.py                                            |     1 |    0 |     1 |   100% |
| application_sdk/storage/_concurrency.py                                        |     3 |    1 |     2 |    67% |
| application_sdk/storage/_credential_providers.py                               |     3 |    0 |     3 |   100% |
| application_sdk/storage/_obstore_config.py                                     |     8 |    0 |     8 |   100% |
| application_sdk/storage/batch.py                                               |     8 |    2 |     6 |    75% |
| application_sdk/storage/binding.py                                             |    13 |    1 |    12 |    92% |
| application_sdk/storage/cloud.py                                               |    22 |    5 |    17 |    77% |
| application_sdk/storage/errors.py                                              |    29 |   19 |    10 |    34% |
| application_sdk/storage/factory.py                                             |     3 |    0 |     3 |   100% |
| application_sdk/storage/file_ref_sync.py                                       |    13 |    3 |    10 |    77% |
| application_sdk/storage/ops.py                                                 |    21 |    1 |    20 |    95% |
| application_sdk/storage/reference.py                                           |    11 |    1 |    10 |    91% |
| application_sdk/storage/rolling.py                                             |    31 |   12 |    19 |    61% |
| application_sdk/storage/rolling_errors.py                                      |     4 |    0 |     4 |   100% |
| application_sdk/storage/transfer.py                                            |    13 |    3 |    10 |    77% |
| application_sdk/storage/formats/__init__.py                                    |    29 |    0 |    29 |   100% |
| application_sdk/storage/formats/format_errors.py                               |    19 |    0 |    19 |   100% |
| application_sdk/storage/formats/json.py                                        |    15 |    1 |    14 |    93% |
| application_sdk/storage/formats/parquet.py                                     |    28 |    1 |    27 |    96% |
| application_sdk/storage/formats/utils.py                                       |     9 |    2 |     7 |    78% |
| application_sdk/templates/__init__.py                                          |     2 |    1 |     1 |    50% |
| application_sdk/templates/_template_errors.py                                  |     4 |    0 |     4 |   100% |
| application_sdk/templates/base_metadata_extractor.py                           |     4 |    1 |     3 |    75% |
| application_sdk/templates/incremental_sql_metadata_extractor.py                |    18 |    1 |    17 |    94% |
| application_sdk/templates/sql_app.py                                           |    31 |    0 |    31 |   100% |
| application_sdk/templates/sql_app_errors.py                                    |     7 |    0 |     7 |   100% |
| application_sdk/templates/sql_metadata_extractor.py                            |    14 |    1 |    13 |    93% |
| application_sdk/templates/sql_query_extractor.py                               |     6 |    1 |     5 |    83% |
| application_sdk/templates/contracts/__init__.py                                |     1 |    0 |     1 |   100% |
| application_sdk/templates/contracts/base_metadata_extraction.py                |     3 |    0 |     3 |   100% |
| application_sdk/templates/contracts/incremental_sql.py                         |    26 |    5 |    21 |    81% |
| application_sdk/templates/contracts/sql_metadata.py                            |    31 |    8 |    23 |    74% |
| application_sdk/templates/contracts/sql_query.py                               |     7 |    0 |     7 |   100% |
| application_sdk/test_utils/integration/__init__.py                             |     1 |    1 |     0 |     0% |
| application_sdk/testing/__init__.py                                            |     1 |    0 |     1 |   100% |
| application_sdk/testing/fixtures.py                                            |    10 |    0 |    10 |   100% |
| application_sdk/testing/mocks.py                                               |    68 |   17 |    51 |    75% |
| application_sdk/testing/e2e/__init__.py                                        |     1 |    0 |     1 |   100% |
| application_sdk/testing/e2e/_errors.py                                         |    10 |    0 |    10 |   100% |
| application_sdk/testing/e2e/base.py                                            |    18 |    1 |    17 |    94% |
| application_sdk/testing/e2e/client.py                                          |    32 |    6 |    26 |    81% |
| application_sdk/testing/e2e/config.py                                          |     2 |    0 |     2 |   100% |
| application_sdk/testing/e2e/credential.py                                      |     2 |    0 |     2 |   100% |
| application_sdk/testing/e2e/logs.py                                            |     6 |    1 |     5 |    83% |
| application_sdk/testing/e2e/payload.py                                         |     9 |    0 |     9 |   100% |
| application_sdk/testing/e2e/pods.py                                            |     5 |    1 |     4 |    80% |
| application_sdk/testing/e2e/portforward.py                                     |     4 |    0 |     4 |   100% |
| application_sdk/testing/e2e/sql_app.py                                         |     9 |    0 |     9 |   100% |
| application_sdk/testing/e2e/substitutions.py                                   |     3 |    0 |     3 |   100% |
| application_sdk/testing/e2e/workflows.py                                       |     3 |    0 |     3 |   100% |
| application_sdk/testing/full_dag/__init__.py                                   |     1 |    0 |     1 |   100% |
| application_sdk/testing/full_dag/_errors.py                                    |     1 |    0 |     1 |   100% |
| application_sdk/testing/full_dag/base.py                                       |    15 |    1 |    14 |    93% |
| application_sdk/testing/full_dag/client.py                                     |     1 |    0 |     1 |   100% |
| application_sdk/testing/full_dag/payload.py                                    |     8 |    0 |     8 |   100% |
| application_sdk/testing/full_dag/sql_app.py                                    |     5 |    0 |     5 |   100% |
| application_sdk/testing/hypothesis/__init__.py                                 |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/__init__.py                      |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/sql_client.py                    |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/clients/__init__.py              |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/clients/sql.py                   |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/common/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/common/logger.py                 |     3 |    0 |     3 |   100% |
| application_sdk/testing/hypothesis/strategies/handlers/__init__.py             |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/handlers/sql/__init__.py         |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/handlers/sql/sql_metadata.py     |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/handlers/sql/sql_preflight.py    |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/inputs/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/inputs/json_input.py             |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/inputs/parquet_input.py          |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/outputs/__init__.py              |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/outputs/json_output.py           |     2 |    1 |     1 |    50% |
| application_sdk/testing/hypothesis/strategies/outputs/statestore.py            |     3 |    1 |     2 |    67% |
| application_sdk/testing/hypothesis/strategies/server/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/server/fastapi/__init__.py       |     1 |    1 |     0 |     0% |
| application_sdk/testing/integration/__init__.py                                |     1 |    0 |     1 |   100% |
| application_sdk/testing/integration/_errors.py                                 |     4 |    0 |     4 |   100% |
| application_sdk/testing/integration/assertions.py                              |    55 |   25 |    30 |    55% |
| application_sdk/testing/integration/client.py                                  |    18 |    0 |    18 |   100% |
| application_sdk/testing/integration/comparison.py                              |    12 |    1 |    11 |    92% |
| application_sdk/testing/integration/lazy.py                                    |    10 |    0 |    10 |   100% |
| application_sdk/testing/integration/models.py                                  |     9 |    0 |     9 |   100% |
| application_sdk/testing/integration/runner.py                                  |    24 |    2 |    22 |    92% |
| application_sdk/testing/integration/validation.py                              |     7 |    0 |     7 |   100% |
| application_sdk/testing/parity/__init__.py                                     |     1 |    0 |     1 |   100% |
| application_sdk/testing/parity/__main__.py                                     |     2 |    1 |     1 |    50% |
| application_sdk/testing/parity/comparator.py                                   |     8 |    0 |     8 |   100% |
| application_sdk/testing/parity/models.py                                       |     5 |    1 |     4 |    80% |
| application_sdk/testing/parity/report.py                                       |     4 |    0 |     4 |   100% |
| application_sdk/testing/scale_data_generator/__init__.py                       |     1 |    0 |     1 |   100% |
| application_sdk/testing/scale_data_generator/config_loader.py                  |    11 |    4 |     7 |    64% |
| application_sdk/testing/scale_data_generator/data_generator.py                 |    10 |    3 |     7 |    70% |
| application_sdk/testing/scale_data_generator/driver.py                         |     3 |    3 |     0 |     0% |
| application_sdk/testing/scale_data_generator/output_handler/__init__.py        |     1 |    1 |     0 |     0% |
| application_sdk/testing/scale_data_generator/output_handler/base.py            |     7 |    3 |     4 |    57% |
| application_sdk/testing/scale_data_generator/output_handler/csv_handler.py     |     6 |    6 |     0 |     0% |
| application_sdk/testing/scale_data_generator/output_handler/json_handler.py    |     5 |    5 |     0 |     0% |
| application_sdk/testing/scale_data_generator/output_handler/parquet_handler.py |     6 |    6 |     0 |     0% |
| application_sdk/testing/sdr/__init__.py                                        |     1 |    0 |     1 |   100% |
| application_sdk/testing/sdr/base.py                                            |     5 |    2 |     3 |    60% |
| application_sdk/tools/__init__.py                                              |     1 |    1 |     0 |     0% |
| application_sdk/tools/provision_credentials.py                                 |     2 |    1 |     1 |    50% |
| application_sdk/transformers/__init__.py                                       |     3 |    1 |     2 |    67% |
| application_sdk/transformers/errors.py                                         |     2 |    1 |     1 |    50% |
| application_sdk/transformers/atlas/__init__.py                                 |     6 |    1 |     5 |    83% |
| application_sdk/transformers/atlas/errors.py                                   |     8 |    7 |     1 |    12% |
| application_sdk/transformers/atlas/sql.py                                      |    25 |    4 |    21 |    84% |
| application_sdk/transformers/common/__init__.py                                |     1 |    1 |     0 |     0% |
| application_sdk/transformers/common/last_sync.py                               |     5 |    0 |     5 |   100% |
| application_sdk/transformers/common/utils.py                                   |     6 |    0 |     6 |   100% |
| application_sdk/transformers/query/__init__.py                                 |    11 |    2 |     9 |    82% |
| application_sdk/transformers/query/errors.py                                   |     4 |    3 |     1 |    25% |
| contract-toolkit/examples/bundle/app/generated/crawler/__init__.py             |     1 |    1 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/crawler/_e2e_base.py            |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/crawler/_e2e_credential.py      |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/crawler/_input.py               |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/miner/__init__.py               |     1 |    1 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/miner/_e2e_base.py              |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/miner/_e2e_substitutions.py     |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/miner/_input.py                 |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/connection-ref/app/generated/__init__.py             |     1 |    1 |     0 |     0% |
| contract-toolkit/examples/connection-ref/app/generated/_e2e_base.py            |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/connection-ref/app/generated/_input.py               |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/deploy/app/generated/__init__.py                     |     1 |    1 |     0 |     0% |
| contract-toolkit/examples/deploy/app/generated/_e2e_base.py                    |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/deploy/app/generated/_e2e_substitutions.py           |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/deploy/app/generated/_input.py                       |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/fanin/app/generated/__init__.py                      |     1 |    1 |     0 |     0% |
| contract-toolkit/examples/fanin/app/generated/_e2e_base.py                     |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/fanin/app/generated/_e2e_credential.py               |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/fanin/app/generated/_input.py                        |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/__init__.py                       |     1 |    1 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/_e2e_base.py                      |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/_e2e_credential.py                |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/_e2e_substitutions.py             |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/_input.py                         |     3 |    3 |     0 |     0% |
| contract-toolkit/examples/minimal/app/generated/__init__.py                    |     1 |    1 |     0 |     0% |
| contract-toolkit/examples/minimal/app/generated/_e2e_base.py                   |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/minimal/app/generated/_e2e_substitutions.py          |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/minimal/app/generated/_input.py                      |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/__init__.py           |     1 |    1 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/_e2e_base.py          |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/_e2e_credential.py    |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/_e2e_substitutions.py |     2 |    2 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/_input.py             |     2 |    2 |     0 |     0% |
| contract-toolkit/scripts/test-sdk-import.py                                    |     5 |    1 |     4 |    80% |
| examples/application_custom_fastapi.py                                         |    10 |    5 |     5 |    50% |
| examples/application_fastapi.py                                                |    10 |    1 |     9 |    90% |
| examples/application_hello_world.py                                            |     6 |    0 |     6 |   100% |
| examples/application_sql.py                                                    |    11 |    3 |     8 |    73% |
| examples/application_sql_miner.py                                              |     9 |    3 |     6 |    67% |
| examples/application_sql_with_custom_transformer.py                            |    12 |    7 |     5 |    42% |
| examples/run_examples.py                                                       |    13 |   12 |     1 |     8% |
| tests/__init__.py                                                              |     1 |    1 |     0 |     0% |
| tests/conftest.py                                                              |     1 |    0 |     1 |   100% |
| tests/e2e/__init__.py                                                          |     1 |    1 |     0 |     0% |
| tests/e2e/conftest.py                                                          |     4 |    1 |     3 |    75% |
| tests/integration/__init__.py                                                  |     1 |    0 |     1 |   100% |
| tests/integration/conftest.py                                                  |    14 |    2 |    12 |    86% |
| tests/integration/test_cloud_store.py                                          |    15 |   12 |     3 |    20% |
| tests/integration/test_core_execution.py                                       |    29 |   24 |     5 |    17% |
| tests/integration/test_dapr_http.py                                            |    22 |    0 |    22 |   100% |
| tests/integration/test_error_and_retry.py                                      |    19 |   15 |     4 |    21% |
| tests/integration/test_events_serde.py                                         |    15 |    5 |    10 |    67% |
| tests/integration/test_handler_service.py                                      |    60 |   31 |    29 |    48% |
| tests/integration/test_heartbeat.py                                            |    13 |   10 |     3 |    23% |
| tests/integration/test_incremental_pipeline.py                                 |    14 |    3 |    11 |    79% |
| tests/integration/test_lifecycle.py                                            |    21 |   17 |     4 |    19% |
| tests/integration/test_multi_entrypoint.py                                     |    26 |   19 |     7 |    27% |
| tests/integration/test_output_e2e.py                                           |    16 |    0 |    16 |   100% |
| tests/integration/test_sql_app_file_reference.py                               |    19 |    9 |    10 |    53% |
| tests/integration/test_sql_app_prime_auth.py                                   |    16 |   11 |     5 |    31% |
| tests/integration/test_storage_io.py                                           |    19 |    0 |    19 |   100% |
| tests/integration/test_storage_writers.py                                      |     9 |    2 |     7 |    78% |
| tests/integration/test_temporal_docker_auth.py                                 |    21 |    8 |    13 |    62% |
| tests/integration/test_timeout.py                                              |     7 |    5 |     2 |    29% |
| tests/integration/test_workflow_interaction_cookbook.py                        |    44 |   37 |     7 |    16% |
| tests/integration/test_workflow_interaction_relay.py                           |    17 |   11 |     6 |    35% |
| tests/integration/_example/__init__.py                                         |     1 |    0 |     1 |   100% |
| tests/integration/_example/conftest.py                                         |     6 |    0 |     6 |   100% |
| tests/integration/_example/scenarios.py                                        |     1 |    0 |     1 |   100% |
| tests/integration/_example/test_integration.py                                 |     2 |    0 |     2 |   100% |
| tests/integration/storage/__init__.py                                          |     1 |    1 |     0 |     0% |
| tests/integration/storage/conftest.py                                          |     5 |    0 |     5 |   100% |
| tests/integration/storage/test_binding_azure.py                                |     6 |    0 |     6 |   100% |
| tests/integration/storage/test_binding_gcs.py                                  |     6 |    0 |     6 |   100% |
| tests/integration/storage/test_binding_s3.py                                   |     7 |    0 |     7 |   100% |
| tests/unit/__init__.py                                                         |     1 |    1 |     0 |     0% |
| tests/unit/conftest.py                                                         |     6 |    1 |     5 |    83% |
| tests/unit/test_app_config.py                                                  |    82 |   45 |    37 |    45% |
| tests/unit/test_discovery.py                                                   |    75 |   69 |     6 |     8% |
| tests/unit/test_imports.py                                                     |     4 |    0 |     4 |   100% |
| tests/unit/test_main.py                                                        |   144 |   64 |    80 |    56% |
| tests/unit/test_parse_atlan_yaml.py                                            |    29 |   25 |     4 |    14% |
| tests/unit/app/__init__.py                                                     |     1 |    1 |     0 |     0% |
| tests/unit/app/test_base.py                                                    |   271 |  218 |    53 |    20% |
| tests/unit/app/test_cleanup_files.py                                           |    15 |   14 |     1 |     7% |
| tests/unit/app/test_cleanup_storage.py                                         |    29 |   26 |     3 |    10% |
| tests/unit/app/test_client.py                                                  |    19 |    1 |    18 |    95% |
| tests/unit/app/test_context.py                                                 |    86 |   72 |    14 |    16% |
| tests/unit/app/test_entrypoint.py                                              |    65 |   38 |    27 |    42% |
| tests/unit/app/test_on_complete.py                                             |    35 |   32 |     3 |     9% |
| tests/unit/app/test_registry.py                                                |    34 |    4 |    30 |    88% |
| tests/unit/app/test_task.py                                                    |    88 |   53 |    35 |    40% |
| tests/unit/clients/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/clients/test_async_sql_client.py                                    |    11 |   10 |     1 |     9% |
| tests/unit/clients/test_azure_auth.py                                          |    33 |    0 |    33 |   100% |
| tests/unit/clients/test_azure_client.py                                        |    19 |    0 |    19 |   100% |
| tests/unit/clients/test_azure_client_contracts.py                              |    52 |   46 |     6 |    12% |
| tests/unit/clients/test_base_client.py                                         |    23 |    1 |    22 |    96% |
| tests/unit/clients/test_clienterror_preservation.py                            |    13 |    8 |     5 |    38% |
| tests/unit/clients/test_redis_client.py                                        |    40 |    0 |    40 |   100% |
| tests/unit/clients/test_redis_client_contracts.py                              |    56 |   36 |    20 |    36% |
| tests/unit/clients/test_sql_client.py                                          |    63 |   26 |    37 |    59% |
| tests/unit/clients/test_sql_typecasters.py                                     |    22 |   16 |     6 |    27% |
| tests/unit/clients/test_ssl_utils.py                                           |    41 |    4 |    37 |    90% |
| tests/unit/common/test_aws_utils.py                                            |    32 |    1 |    31 |    97% |
| tests/unit/common/test_column_extraction.py                                    |    11 |    0 |    11 |   100% |
| tests/unit/common/test_env_warnings.py                                         |    10 |    7 |     3 |    30% |
| tests/unit/common/test_file_converter.py                                       |    29 |    0 |    29 |   100% |
| tests/unit/common/test_file_ops.py                                             |    21 |    0 |    21 |   100% |
| tests/unit/common/test_path.py                                                 |     6 |    0 |     6 |   100% |
| tests/unit/common/test_spillable_dict.py                                       |    28 |   18 |    10 |    36% |
| tests/unit/common/test_sql_filters_injection.py                                |    30 |   29 |     1 |     3% |
| tests/unit/common/test_transforms.py                                           |    34 |   31 |     3 |     9% |
| tests/unit/common/test_utils.py                                                |    82 |   11 |    71 |    87% |
| tests/unit/common/test_utils_file_discovery.py                                 |    13 |    0 |    13 |   100% |
| tests/unit/common/incremental/__init__.py                                      |     1 |    1 |     0 |     0% |
| tests/unit/common/incremental/test_helpers.py                                  |    37 |    1 |    36 |    97% |
| tests/unit/common/incremental/test_incremental_diff.py                         |    24 |   15 |     9 |    38% |
| tests/unit/common/incremental/test_marker.py                                   |    16 |    0 |    16 |   100% |
| tests/unit/common/incremental/test_models.py                                   |    15 |    0 |    15 |   100% |
| tests/unit/common/incremental/test_state_reader.py                             |     7 |    1 |     6 |    86% |
| tests/unit/common/incremental/test_state_writer.py                             |    32 |    2 |    30 |    94% |
| tests/unit/common/incremental/column_extraction/__init__.py                    |     1 |    1 |     0 |     0% |
| tests/unit/common/incremental/column_extraction/test_analysis.py               |    16 |   10 |     6 |    38% |
| tests/unit/common/incremental/column_extraction/test_backfill.py               |    24 |    5 |    19 |    79% |
| tests/unit/common/incremental/state/__init__.py                                |     1 |    1 |     0 |     0% |
| tests/unit/common/incremental/state/test_table_scope.py                        |    36 |   26 |    10 |    28% |
| tests/unit/contracts/__init__.py                                               |     1 |    1 |     0 |     0% |
| tests/unit/contracts/test_base.py                                              |   136 |  133 |     3 |     2% |
| tests/unit/contracts/test_connection_ref.py                                    |    31 |   29 |     2 |     6% |
| tests/unit/contracts/test_git_reference.py                                     |    23 |   22 |     1 |     4% |
| tests/unit/contracts/test_storage_tier_temporal_serde.py                       |     9 |    1 |     8 |    89% |
| tests/unit/contracts/test_types.py                                             |    25 |   24 |     1 |     4% |
| tests/unit/credentials/__init__.py                                             |     1 |    1 |     0 |     0% |
| tests/unit/credentials/test_agent.py                                           |    88 |   59 |    29 |    33% |
| tests/unit/credentials/test_atlan.py                                           |    41 |   31 |    10 |    24% |
| tests/unit/credentials/test_atlan_client.py                                    |    29 |   22 |     7 |    24% |
| tests/unit/credentials/test_mock_store.py                                      |    17 |   15 |     2 |    12% |
| tests/unit/credentials/test_oauth.py                                           |    28 |   16 |    12 |    43% |
| tests/unit/credentials/test_ref.py                                             |    26 |   23 |     3 |    12% |
| tests/unit/credentials/test_registry.py                                        |    20 |   18 |     2 |    10% |
| tests/unit/credentials/test_resolver.py                                        |    21 |    9 |    12 |    57% |
| tests/unit/credentials/test_types.py                                           |    42 |   41 |     1 |     2% |
| tests/unit/credentials/test_utils.py                                           |    18 |    1 |    17 |    94% |
| tests/unit/decorators/__init__.py                                              |     1 |    1 |     0 |     0% |
| tests/unit/decorators/test_mcp_tool.py                                         |    56 |    4 |    52 |    93% |
| tests/unit/dev/__init__.py                                                     |     1 |    1 |     0 |     0% |
| tests/unit/dev/test_dapr.py                                                    |    22 |   17 |     5 |    23% |
| tests/unit/dev/test_embedded.py                                                |     6 |    1 |     5 |    83% |
| tests/unit/errors/__init__.py                                                  |     1 |    1 |     0 |     0% |
| tests/unit/errors/test_app_subclassing.py                                      |     9 |    8 |     1 |    11% |
| tests/unit/errors/test_back_compat.py                                          |   102 |  101 |     1 |     1% |
| tests/unit/errors/test_base.py                                                 |    21 |   20 |     1 |     5% |
| tests/unit/errors/test_categorical.py                                          |     7 |    6 |     1 |    14% |
| tests/unit/errors/test_domain_evidence.py                                      |    12 |   10 |     2 |    17% |
| tests/unit/execution/__init__.py                                               |     1 |    1 |     0 |     0% |
| tests/unit/execution/conftest.py                                               |     4 |    2 |     2 |    50% |
| tests/unit/execution/test_activities.py                                        |   119 |  105 |    14 |    12% |
| tests/unit/execution/test_activities_tracking.py                               |    18 |   12 |     6 |    33% |
| tests/unit/execution/test_auth_token_refresh_event.py                          |    62 |   36 |    26 |    42% |
| tests/unit/execution/test_backend.py                                           |    59 |   49 |    10 |    17% |
| tests/unit/execution/test_converter.py                                         |    15 |   12 |     3 |    20% |
| tests/unit/execution/test_eviction.py                                          |    31 |   27 |     4 |    13% |
| tests/unit/execution/test_heartbeat.py                                         |    32 |   18 |    14 |    44% |
| tests/unit/execution/test_lock_interceptor.py                                  |    33 |   13 |    20 |    61% |
| tests/unit/execution/test_run_in_thread.py                                     |     6 |    1 |     5 |    83% |
| tests/unit/execution/test_sdr.py                                               |    31 |   25 |     6 |    19% |
| tests/unit/execution/test_settings.py                                          |    28 |   23 |     5 |    18% |
| tests/unit/execution/test_temporal_prometheus.py                               |     7 |    0 |     7 |   100% |
| tests/unit/execution/test_worker.py                                            |    83 |   64 |    19 |    23% |
| tests/unit/execution/test_workflows.py                                         |    44 |   37 |     7 |    16% |
| tests/unit/handler/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/handler/test_base.py                                                |    18 |   17 |     1 |     6% |
| tests/unit/handler/test_contracts.py                                           |    63 |   44 |    19 |    30% |
| tests/unit/handler/test_service.py                                             |   356 |  237 |   119 |    33% |
| tests/unit/infrastructure/__init__.py                                          |     1 |    1 |     0 |     0% |
| tests/unit/infrastructure/test_bindings.py                                     |    18 |   14 |     4 |    22% |
| tests/unit/infrastructure/test_capacity.py                                     |    20 |   16 |     4 |    20% |
| tests/unit/infrastructure/test_connection_pool_config.py                       |    13 |    1 |    12 |    92% |
| tests/unit/infrastructure/test_credential_state_store.py                       |    19 |   12 |     7 |    37% |
| tests/unit/infrastructure/test_credential_vault.py                             |    36 |   17 |    19 |    53% |
| tests/unit/infrastructure/test_dapr_http.py                                    |    45 |   27 |    18 |    40% |
| tests/unit/infrastructure/test_dapr_wrappers.py                                |    46 |   44 |     2 |     4% |
| tests/unit/infrastructure/test_pubsub.py                                       |    30 |   10 |    20 |    67% |
| tests/unit/infrastructure/test_secrets.py                                      |    36 |    0 |    36 |   100% |
| tests/unit/infrastructure/test_state.py                                        |    20 |    0 |    20 |   100% |
| tests/unit/interceptors/__init__.py                                            |     1 |    1 |     0 |     0% |
| tests/unit/interceptors/test_events.py                                         |    42 |   29 |    13 |    31% |
| tests/unit/interceptors/test_log_interceptor.py                                |    84 |   79 |     5 |     6% |
| tests/unit/interceptors/test_metrics_interceptor.py                            |    43 |   41 |     2 |     5% |
| tests/unit/interceptors/test_output_interceptor.py                             |    35 |    3 |    32 |    91% |
| tests/unit/interceptors/test_trace_interceptor.py                              |    17 |   16 |     1 |     6% |
| tests/unit/observability/__init__.py                                           |     1 |    1 |     0 |     0% |
| tests/unit/observability/test_execution_context.py                             |    11 |    0 |    11 |   100% |
| tests/unit/observability/test_logger_adaptor.py                                |   145 |   62 |    83 |    57% |
| tests/unit/observability/test_metrics.py                                       |    11 |   10 |     1 |     9% |
| tests/unit/observability/test_metrics_adaptor.py                               |    29 |    6 |    23 |    79% |
| tests/unit/observability/test_objectstore_metric_exporter.py                   |    17 |   13 |     4 |    24% |
| tests/unit/observability/test_observability_decorator.py                       |    31 |   27 |     4 |    13% |
| tests/unit/observability/test_prometheus_enrichment.py                         |    13 |    8 |     5 |    38% |
| tests/unit/observability/test_pushgateway.py                                   |    50 |   42 |     8 |    16% |
| tests/unit/observability/test_resource_sampler.py                              |    12 |    7 |     5 |    42% |
| tests/unit/observability/test_segment_client.py                                |    70 |   50 |    20 |    29% |
| tests/unit/observability/test_traces_adaptor.py                                |    13 |    1 |    12 |    92% |
| tests/unit/observability/test_traces_adaptor_contracts.py                      |    27 |   22 |     5 |    19% |
| tests/unit/outputs/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/outputs/test_outputs.py                                             |    33 |   24 |     9 |    27% |
| tests/unit/server/__init__.py                                                  |     1 |    1 |     0 |     0% |
| tests/unit/server/test_health.py                                               |    24 |   21 |     3 |    12% |
| tests/unit/server/fastapi/test_fastapi_utils.py                                |    36 |    0 |    36 |   100% |
| tests/unit/server/mcp/__init__.py                                              |     1 |    1 |     0 |     0% |
| tests/unit/server/mcp/test_mcp_server_v3.py                                    |    14 |    9 |     5 |    36% |
| tests/unit/server/middleware/__init__.py                                       |     1 |    1 |     0 |     0% |
| tests/unit/server/middleware/test_log.py                                       |    13 |    9 |     4 |    31% |
| tests/unit/storage/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/storage/test_batch.py                                               |    36 |   26 |    10 |    28% |
| tests/unit/storage/test_binding.py                                             |    99 |   73 |    26 |    26% |
| tests/unit/storage/test_cloud.py                                               |    45 |   35 |    10 |    22% |
| tests/unit/storage/test_credential_providers.py                                |    11 |   10 |     1 |     9% |
| tests/unit/storage/test_file_ref_sync.py                                       |    37 |   28 |     9 |    24% |
| tests/unit/storage/test_obstore_config.py                                      |    19 |   15 |     4 |    21% |
| tests/unit/storage/test_ops.py                                                 |    98 |   78 |    20 |    20% |
| tests/unit/storage/test_path_separators.py                                     |    13 |    0 |    13 |   100% |
| tests/unit/storage/test_reference.py                                           |    51 |   31 |    20 |    39% |
| tests/unit/storage/test_rolling.py                                             |    68 |   53 |    15 |    22% |
| tests/unit/storage/test_transfer.py                                            |    44 |   34 |    10 |    23% |
| tests/unit/storage/formats/__init__.py                                         |     1 |    1 |     0 |     0% |
| tests/unit/storage/formats/test_base_io.py                                     |    60 |   53 |     7 |    12% |
| tests/unit/storage/formats/test_reader_isolation.py                            |     8 |    2 |     6 |    75% |
| tests/unit/storage/formats/test_utils.py                                       |     2 |    2 |     0 |     0% |
| tests/unit/storage/formats/test_writer_data_integrity.py                       |    26 |    6 |    20 |    77% |
| tests/unit/storage/formats/readers/__init__.py                                 |     1 |    1 |     0 |     0% |
| tests/unit/storage/formats/readers/test_json_reader.py                         |    38 |   18 |    20 |    53% |
| tests/unit/storage/formats/readers/test_parquet_reader.py                      |    68 |   43 |    25 |    37% |
| tests/unit/storage/formats/writers/__init__.py                                 |     1 |    1 |     0 |     0% |
| tests/unit/storage/formats/writers/test_json_writer.py                         |     7 |    6 |     1 |    14% |
| tests/unit/storage/formats/writers/test_parquet_writer.py                      |    74 |   11 |    63 |    85% |
| tests/unit/templates/__init__.py                                               |     1 |    1 |     0 |     0% |
| tests/unit/templates/conftest.py                                               |     2 |    0 |     2 |   100% |
| tests/unit/templates/test_base_metadata_extractor.py                           |    14 |   12 |     2 |    14% |
| tests/unit/templates/test_extraction_input_ae_payload.py                       |    12 |   11 |     1 |     8% |
| tests/unit/templates/test_extraction_input_filters.py                          |    41 |   25 |    16 |    39% |
| tests/unit/templates/test_incremental_sql_metadata_extractor.py                |    89 |   56 |    33 |    37% |
| tests/unit/templates/test_sql_app.py                                           |   117 |   51 |    66 |    56% |
| tests/unit/templates/test_sql_metadata_extractor.py                            |   131 |   99 |    32 |    24% |
| tests/unit/templates/test_sql_query_extractor.py                               |    15 |   12 |     3 |    20% |
| tests/unit/templates/contracts/test_incremental_sql_marker.py                  |    16 |   15 |     1 |     6% |
| tests/unit/testing/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/testing/test_fixtures.py                                            |    16 |   15 |     1 |     6% |
| tests/unit/testing/test_mocks.py                                               |    29 |   28 |     1 |     3% |
| tests/unit/testing/test_parity.py                                              |    35 |   34 |     1 |     3% |
| tests/unit/testing/e2e/__init__.py                                             |     1 |    1 |     0 |     0% |
| tests/unit/testing/e2e/test_base_e2e.py                                        |    27 |   23 |     4 |    15% |
| tests/unit/testing/e2e/test_client.py                                          |     9 |    3 |     6 |    67% |
| tests/unit/testing/e2e/test_harness_payload.py                                 |    19 |   16 |     3 |    16% |
| tests/unit/testing/e2e/test_logs.py                                            |    10 |    8 |     2 |    20% |
| tests/unit/testing/e2e/test_portforward.py                                     |     7 |    1 |     6 |    86% |
| tests/unit/testing/e2e/test_sql_app_e2e.py                                     |    35 |   34 |     1 |     3% |
| tests/unit/testing/e2e/test_substitutions.py                                   |    16 |   13 |     3 |    19% |
| tests/unit/testing/full_dag/__init__.py                                        |     1 |    1 |     0 |     0% |
| tests/unit/testing/full_dag/test_base.py                                       |    22 |    3 |    19 |    86% |
| tests/unit/testing/full_dag/test_client.py                                     |    14 |   10 |     4 |    29% |
| tests/unit/testing/full_dag/test_payload.py                                    |    11 |    3 |     8 |    73% |
| tests/unit/testing/full_dag/test_sql_app.py                                    |    12 |    4 |     8 |    67% |
| tests/unit/testing/integration/__init__.py                                     |     1 |    1 |     0 |     0% |
| tests/unit/testing/integration/test_client.py                                  |    25 |   14 |    11 |    44% |
| tests/unit/testing/integration/test_comparison.py                              |    29 |    0 |    29 |   100% |
| tests/unit/testing/integration/test_lazy_pandas.py                             |     5 |    0 |     5 |   100% |
| tests/unit/testing/sdr/__init__.py                                             |     1 |    1 |     0 |     0% |
| tests/unit/testing/sdr/test_base.py                                            |    13 |   11 |     2 |    15% |
| tests/unit/tools/__init__.py                                                   |     1 |    1 |     0 |     0% |
| tests/unit/tools/test_check_migration.py                                       |    65 |   44 |    21 |    32% |
| tests/unit/tools/test_codemod_roundtrip.py                                     |    32 |   31 |     1 |     3% |
| tests/unit/tools/test_extract_context.py                                       |    50 |   48 |     2 |     4% |
| tests/unit/tools/test_fingerprint.py                                           |    23 |   21 |     2 |     9% |
| tests/unit/tools/test_provision_credentials.py                                 |    11 |    0 |    11 |   100% |
| tests/unit/tools/test_rewrite_imports.py                                       |    41 |   31 |    10 |    24% |
| tests/unit/tools/test_run_codemods.py                                          |    16 |   15 |     1 |     6% |
| tests/unit/tools/test_codemods/__init__.py                                     |     1 |    1 |     0 |     0% |
| tests/unit/tools/test_codemods/conftest.py                                     |     2 |    0 |     2 |   100% |
| tests/unit/tools/test_codemods/test_remove_activities_cls.py                   |    15 |   11 |     4 |    27% |
| tests/unit/tools/test_codemods/test_remove_decorators.py                       |    17 |   16 |     1 |     6% |
| tests/unit/tools/test_codemods/test_rewrite_activity_calls.py                  |    16 |   11 |     5 |    31% |
| tests/unit/tools/test_codemods/test_rewrite_entry_point.py                     |    19 |   16 |     3 |    16% |
| tests/unit/tools/test_codemods/test_rewrite_handlers.py                        |    13 |   12 |     1 |     8% |
| tests/unit/tools/test_codemods/test_rewrite_returns.py                         |    12 |   10 |     2 |    17% |
| tests/unit/tools/test_codemods/test_rewrite_signatures.py                      |    19 |   18 |     1 |     5% |
| tests/unit/transformers/__init__.py                                            |     1 |    1 |     0 |     0% |
| tests/unit/transformers/atlas/__init__.py                                      |     1 |    1 |     0 |     0% |
| tests/unit/transformers/atlas/test_atlas_transformer.py                        |    28 |   15 |    13 |    46% |
| tests/unit/transformers/atlas/test_column.py                                   |    17 |    6 |    11 |    65% |
| tests/unit/transformers/atlas/test_database.py                                 |     8 |    6 |     2 |    25% |
| tests/unit/transformers/atlas/test_function.py                                 |    11 |    5 |     6 |    55% |
| tests/unit/transformers/atlas/test_procedure.py                                |     7 |    6 |     1 |    14% |
| tests/unit/transformers/atlas/test_schema.py                                   |     8 |    6 |     2 |    25% |
| tests/unit/transformers/atlas/test_sql_extra.py                                |    42 |   39 |     3 |     7% |
| tests/unit/transformers/atlas/test_table.py                                    |    15 |    6 |     9 |    60% |
| tests/unit/transformers/common/__init__.py                                     |     1 |    1 |     0 |     0% |
| tests/unit/transformers/common/test_last_sync.py                               |    13 |    6 |     7 |    54% |
| tests/unit/transformers/query/test_sql_transformer.py                          |    20 |    4 |    16 |    80% |
| tests/unit/transformers/query/test_sql_transformer_output_validation.py        |     5 |    2 |     3 |    60% |
| tools/migrate_v3/__init__.py                                                   |     1 |    0 |     1 |   100% |
| tools/migrate_v3/check_migration.py                                            |    11 |    6 |     5 |    45% |
| tools/migrate_v3/contract_mapping.py                                           |     3 |    1 |     2 |    67% |
| tools/migrate_v3/extract_context.py                                            |    21 |   16 |     5 |    24% |
| tools/migrate_v3/fingerprint.py                                                |     3 |    1 |     2 |    67% |
| tools/migrate_v3/import_mapping.py                                             |     2 |    0 |     2 |   100% |
| tools/migrate_v3/rewrite_imports.py                                            |    19 |    8 |    11 |    58% |
| tools/migrate_v3/run_codemods.py                                               |    14 |    5 |     9 |    64% |
| tools/migrate_v3/codemods/__init__.py                                          |    11 |    4 |     7 |    64% |
| tools/migrate_v3/codemods/remove_activities_cls.py                             |    12 |    7 |     5 |    42% |
| tools/migrate_v3/codemods/remove_decorators.py                                 |    11 |    8 |     3 |    27% |
| tools/migrate_v3/codemods/rewrite_activity_calls.py                            |     6 |    1 |     5 |    83% |
| tools/migrate_v3/codemods/rewrite_entry_point.py                               |    10 |    3 |     7 |    70% |
| tools/migrate_v3/codemods/rewrite_handlers.py                                  |     8 |    5 |     3 |    38% |
| tools/migrate_v3/codemods/rewrite_returns.py                                   |     7 |    5 |     2 |    29% |
| tools/migrate_v3/codemods/rewrite_signatures.py                                |     8 |    4 |     4 |    50% |
|--------------------------------------------------------------------------------|-------|------|-------|--------|
| TOTAL                                                                          | 10201 | 5338 |  4863 |  47.7% |
---------------- RESULT: PASSED (minimum: 30.0%, actual: 47.7%) ----------------

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

📦 Trivy Vulnerability Scan Results

Schema Version Created At Artifact Type
2 2026-06-03T14:27:35.486927326Z . repository

Report Summary

Could not generate summary table (data length mismatch: 9 vs 8).

Scan Result Details

requirements.txt
uv.lock

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

📦 Trivy Secret Scan Results

Schema Version Created At Artifact Type
2 2026-06-03T14:27:55.732115917Z . repository

Report Summary

Could not generate summary table (data length mismatch: 9 vs 8).

Scan Result Details

requirements.txt
uv.lock

…ate-all.sh ruff

Pre-commit ruff wrapped two long Literal Field lines to multi-line; the ruff
bundled in regenerate-all.sh leaves them single-line. Commit the script's output
so the stale-check in CI passes.
@atlan-ci
Copy link
Copy Markdown
Collaborator

atlan-ci commented Jun 3, 2026

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
17640 16037 91% 0% 🟢

New Files

No new covered files...

Modified Files

No covered modified files...

updated for commit: 2d0dc8b by action🐍

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

🛠 Full Test Coverage Report: https://k.atlan.dev/coverage/application-sdk/pr/1980

@atlan-ci
Copy link
Copy Markdown
Collaborator

atlan-ci commented Jun 3, 2026

🧪 Connector Tests — atlan-mysql-app

Status: Passed ✅
Dispatched run: 26891387158

Cross-repo dispatch from this SDK PR. Detailed report unavailable — the dispatched run did not produce a results artifact.

@atlan-ci
Copy link
Copy Markdown
Collaborator

atlan-ci commented Jun 3, 2026

🧪 Connector Tests — atlan-openapi-app

Status: Passed ✅
Dispatched run: 26891388921

Cross-repo dispatch from this SDK PR. Detailed report unavailable — the dispatched run did not produce a results artifact.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the contract-toolkit’s PKL-driven code generation to emit the Python e2e harness artifacts (_e2e_base.py, _e2e_credential.py, _e2e_substitutions.py) directly from contract/app.pkl, and updates the SDK docs + import-test script to match the new generation source of truth.

Changes:

  • Adds E2E harness codegen functions + new overridable contract fields (argoPackageName, argoTemplateName, appServiceUrl) in contract-toolkit/src/App.pkl.
  • Extends scripts/test-sdk-import.py to import-test all generated _e2e_*.py files in addition to _input.py.
  • Updates SDK e2e docstrings and refreshes example generated e2e files.

Reviewed changes

Copilot reviewed 4 out of 21 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
contract-toolkit/src/App.pkl Adds new E2E harness contract fields and PKL codegen for _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py.
contract-toolkit/scripts/test-sdk-import.py Expands import validation to cover _e2e_*.py outputs.
contract-toolkit/examples/publish-controls/app/generated/_e2e_substitutions.py Adds generated mustache substitutions model for the example.
contract-toolkit/examples/publish-controls/app/generated/_e2e_credential.py Adds generated credential body model for the example.
contract-toolkit/examples/publish-controls/app/generated/_e2e_base.py Adds generated e2e base harness class for the example.
contract-toolkit/examples/minimal/app/generated/_e2e_substitutions.py Adds generated mustache substitutions model for the example.
contract-toolkit/examples/minimal/app/generated/_e2e_base.py Adds generated e2e base harness class for the example.
contract-toolkit/examples/full/app/generated/_e2e_substitutions.py Adds generated mustache substitutions model for the example (incl. Literal/Any typing).
contract-toolkit/examples/full/app/generated/_e2e_credential.py Adds generated credential body model for the example (incl. optional fields).
contract-toolkit/examples/full/app/generated/_e2e_base.py Adds generated e2e base harness class for the example.
contract-toolkit/examples/fanin/app/generated/_e2e_credential.py Adds generated credential body model for the example.
contract-toolkit/examples/fanin/app/generated/_e2e_base.py Adds generated e2e base harness class for the example.
contract-toolkit/examples/deploy/app/generated/_e2e_substitutions.py Adds generated mustache substitutions model for the example.
contract-toolkit/examples/deploy/app/generated/_e2e_base.py Adds generated e2e base harness class for the example.
contract-toolkit/examples/connection-ref/app/generated/_e2e_base.py Adds generated e2e base harness class for the example.
contract-toolkit/examples/bundle/app/generated/miner/_e2e_substitutions.py Adds generated mustache substitutions model for the miner example.
contract-toolkit/examples/bundle/app/generated/miner/_e2e_base.py Adds generated e2e base harness class for the miner example.
contract-toolkit/examples/bundle/app/generated/crawler/_e2e_credential.py Adds generated credential body model for the crawler example.
contract-toolkit/examples/bundle/app/generated/crawler/_e2e_base.py Adds generated e2e base harness class for the crawler example.
application_sdk/testing/e2e/substitutions.py Updates module docstring to point at the new generator function in App.pkl.
application_sdk/testing/e2e/credential.py Updates module docstring to point at the new generator function in App.pkl.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread application_sdk/testing/e2e/credential.py Outdated
Comment thread contract-toolkit/scripts/test-sdk-import.py Outdated
Comment thread contract-toolkit/src/App.pkl
cmgrote added 2 commits June 3, 2026 13:18
fmtSubsField helper wraps Field() calls that exceed 88 chars (matching ruff's
default), so regenerate-all.sh and pre-commit ruff-format always agree on output.
- App.pkl: auth_type default now uses credentialAuthDefault when set,
  falls back to first credentialAuthOptions key (matches credential
  config generation at L1890)
- test-sdk-import.py: remove unused _E2E_CLASSES dict
- testing/e2e/credential.py: expand docstring to accurately list all
  field sources (credentialUrlGroup, credentialSharedExtraFields,
  credentialCommonFields, auth option fields, auth option extraFields)
@cmgrote
Copy link
Copy Markdown
Collaborator Author

cmgrote commented Jun 3, 2026

@sdk-review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

Earlier @sdk-review trigger (click to expand)

🔍 SDK Review (mothership) triggered by @cmgrote at 2026-06-03T12:25:53.743Z.

Watch the workflow run live — the review summary will appear as a separate comment when complete (typical: 5–30 min, hard cap 2h).


🟥 Run ended without a clean completion — status error, cost $unknown, duration 25m 11s.
Error: sandbox_error — SSE stream dropped while Claude was still running (session=20c3a60e-c1a7-4743-8815-1d0dc909ab2e). Connection lost after 76 events.

@cmgrote
Copy link
Copy Markdown
Collaborator Author

cmgrote commented Jun 3, 2026

@sdk-review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

Earlier @sdk-review trigger (click to expand)

🔍 SDK Review (mothership) triggered by @cmgrote at 2026-06-03T12:52:19.083Z.

Watch the workflow run live — the review summary will appear as a separate comment when complete (typical: 5–30 min, hard cap 2h).


Completed — status completed, cost $6.07520275, duration 36m 35s.

@mothership-ai
Copy link
Copy Markdown
Contributor

mothership-ai Bot commented Jun 3, 2026

SDK Review (mothership): PR #1980 — feat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py

Verdict: NEEDS FIXES

Solid CAUSES-not-symptoms PR — closes the contract leak between the "Generated from contract/app.pkl" banners on the e2e harness files and the reality (they were hand-authored). Three new public toolkit fields and three codegen functions land cleanly with widget-type-aware Pydantic field typing. Blocks merge on one Important: the new argoPackageName / argoTemplateName / appServiceUrl fields aren't documented in contract-toolkit/docs/reference.md or the README, so connector authors won't discover the override path.


PR Title Check

  • Aligned — title feat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py matches the file scope (touches application_sdk/ + contract-toolkit/ → §2f-bis Row 1: feat() with any scope satisfies the SDK release-walker).

Findings

application_sdk/testing/e2e/credential.py

  • Nit [QUAL] L7-8 — Docstring claims credentialAuthOptions[*].fields "(auth-specific fields become Optional)" but the codegen (credFieldLine at App.pkl:2638) emits non-Optional types with sentinel defaults (str = "", int = 0) for auth-specific fields. The actual Optional emission path is for ConditionalFieldSpec entries in the common group, not auth-specific. Path: immediate fix — either change codegen to emit str | None = None / int | None = None for authSpecific=true, OR rewrite the docstring to say "conditional common fields become Optional; auth-specific fields keep their type with a sentinel default".

application_sdk/testing/e2e/substitutions.py

  • Nit [QUAL] L59 — SQLMustacheSubstitutions docstring still says see contract-toolkit/src/E2EOutput.pkl — the never-created file the rest of this PR is replacing references to. Top-level MustacheSubstitutions docstring (L13-14) was updated but this one was missed. Path: immediate fix — replace with (driven by the connector's app.pkl via codegen — see generateE2ESubstitutionsPy() in contract-toolkit/src/App.pkl).

contract-toolkit/scripts/test-sdk-import.py

  • Nit [TEST] L46-52 — test_e2e() only verifies "imports without error", much weaker than test_input() which asserts AppInputContract exists and is a Pydantic model. The expected class names are deterministic — <PascalCase(name)>GeneratedE2EBase, <PascalCase(name)>MustacheSubstitutions, <PascalCase(name)>CredentialBody — so the same shape check is feasible and would catch silent codegen regressions. Path: follow-up — add an expected-class lookup keyed by file stem and assert hasattr(mod, expected_class) plus model_fields/MRO checks where applicable.

contract-toolkit/src/App.pkl

  • Important [DX] L173-186 — Three new public overridable fields (argoPackageName, argoTemplateName, appServiceUrl) added with default conventions, but contract-toolkit/docs/reference.md and contract-toolkit/README.md are not updated. reference.md already documents related deploy-block fields (e.g. argoPackageNames {…} plural at L468); the new singular fields belong in the same surface. Connector authors won't discover the override path without reading App.pkl source. Path: immediate fix — add a subsection (probably under "App Metadata" or a new "E2E Test Harness" subsection) documenting each field's purpose, default, and when to override.
  • Nit [TEST] L2488-2804 — Three new codegen functions (generateE2EBasePy, generateE2ESubstitutionsPy, generateE2ECredentialPy) plus helpers (pascalCase, fmtSubsField, getSubsFieldLine, credFieldLine) added with no tests/*.pkl golden-snapshot tests. PR claims pkl test 78/78 pass but those cover generateInputClassPy only. The widget-type-aware dispatch in getSubsFieldLine (BooleanInput / Switcher / NumericInput / Radio / DropDown / ConditionalInput / SqlTree-family / TextInput-fallback, ~10 branches) is exactly the surface that benefits most from golden tests. Path: follow-up — add tests/e2e_*.pkl snapshot tests for each generator covering the widget-type matrix; the import test in scripts/test-sdk-import.py is the runtime safety net but won't catch shape drift.
  • Nit [BUG] L2592-2594 — argoPackageName / argoTemplateName / appServiceUrl are interpolated directly into generated Python source (" argo_package_name = \"\(argoPackageName)\"\n") without escaping. Defaults are safe, but a connector author override containing ", \, or \n would produce malformed Python. Currently no input vector beyond connector-author-controlled Pkl, so it's a footgun rather than a vulnerability. Path: follow-up — emit via JSON.encode(value) style escape or guard with a Pkl-side Regex check that rejects values containing " / \ / control chars.
  • Nit [BUG] L2495 — pascalCase splits on [\-_]+ only. Inputs containing ., /, digits-with-mixed-separators, or non-ASCII would yield invalid Python identifiers. Conventions today keep name as lowercase-with-dashes so it's safe in practice — but no guard against drift if a future connector uses app.foo or unicode. Path: optional cleanup — either tighten the splitter ([^A-Za-z0-9]+) or assert valid identifier on the result.
  • Nit [BUG] L2780-2783 — Generated <Connector>CredentialBodyExtra(BaseModel) sets ConfigDict(populate_by_name=True, serialize_by_alias=True) but omits frozen=True, while the base CredentialBody (and the inheriting main subclass) is frozen. None of the current example connectors trigger the hasExtraModel path so this is latent, but it's a contract-consistency drift waiting to bite. Path: optional cleanup — add frozen=True (and extra="allow" for parity) to the generated Extra model's ConfigDict.
  • Nit [STRUCT] (file-level) — App.pkl is now ~3061 lines with all four codegen flows (input, e2e base, e2e substitutions, e2e credential) in the same module. Functional today; getting unwieldy. Path: design follow-up — consider extracting codegen helpers into src/codegen/*.pkl modules in a future refactor; not blocking this PR.

Holistic Recommendations

  • This PR is fixing a cause (banners lying about provenance), not a symptom — the previous hand-authored e2e files would silently drift from app.pkl truth. Codegen + import smoke test closes that loop. ✅
  • The widget-type → Pydantic-field-type table in getSubsFieldLine is the implicit toolkit contract. Worth documenting (per the [DX] finding) and golden-testing (per the [TEST] finding) so future widget additions don't silently fall through to the str default.
  • Consider whether argoPackageName / appServiceUrl defaults baking the in-cluster naming convention into the public toolkit creates a cross-repo upgrade pin: if the cluster pattern ever changes, every connector's codegen drifts and a toolkit version bump becomes mandatory. Not a blocker, but worth noting in the new docs subsection ("override if your deployment differs").

Strengths

  • Replaces hand-authored e2e harness files with pkl eval codegen — banners no longer lie, drift is mechanically prevented.
  • Widget-type-aware substitution typing (Literal for bounded Radio/DropDown, dict|None for tree/nested, bool/int for primitives) is more precise than the all-str previous-generation hand-authored equivalents.
  • Auth-specific FieldSpec deduplication in generateE2ECredentialPy (skip names already in commons, dedup across auth options) handles the common-vs-auth-specific overlap correctly.
  • Conservative scope — three additive Pkl fields with defaults, two SDK file docstring updates, one extension to test-sdk-import.py. No public symbol removed; no BaseE2ETest/SQLAppE2ETest/MustacheSubstitutions/CredentialBody API touched.
  • PR title and Conventional-Commits scope match the file-bucket rule cleanly — release walker stays honest.

CI: all passing | check via gh pr checks 1980 --repo atlanhq/application-sdk (sandbox-side)
Models: Claude Opus 4.7 (review) + GPT-5.3-codex (adversarial)
Cross-model agreement: 8/9 confirmed by both (1 dropped: hallucinated CHANGELOG.md edit not in diff)
Run: view workflow logs + cost

Comment thread contract-toolkit/src/App.pkl
Comment thread application_sdk/testing/e2e/credential.py
Comment thread contract-toolkit/src/App.pkl Outdated
Comment thread contract-toolkit/src/App.pkl Outdated
Comment thread contract-toolkit/scripts/test-sdk-import.py
Signed-off-by: Chris (He/Him) <cgrote@gmail.com>
Comment thread contract-toolkit/src/App.pkl
Comment thread contract-toolkit/src/App.pkl Outdated
cmgrote added 2 commits June 3, 2026 14:30
- App.pkl: add escapePyStr() helper; use it for all string class attrs in
  _e2e_base.py codegen so quote/backslash/newline chars in overrides produce
  valid Python rather than broken literals
- App.pkl: widen pascalCase splitter from [-_]+ to [^A-Za-z0-9]+ so dots,
  slashes, and other non-alphanumeric chars are handled consistently
- App.pkl: add frozen=True to generated CredentialBodyExtra ConfigDict,
  matching the immutability of the CredentialBody base class
- credential.py: fix docstring — auth-specific fields use sentinel defaults
  (str='', int=0), not Optional; conditional common fields become Optional
- test-sdk-import.py: test_e2e() now verifies expected class suffix exists
  and checks harness attrs for _e2e_base / model_fields for credential+subs
- docs/reference.md: add E2E Test Harness subsection documenting the three
  new overridable fields (argoPackageName, argoTemplateName, appServiceUrl)
47 test cases covering generateE2EBasePy, generateE2ESubstitutionsPy,
generateE2ECredentialPy, pascalCase, fmtSubsField, and getSubsFieldLine.
Also moves _e2e_*.py output outside the uiConfig!=null guard so the test
harness files are emitted in all single-entrypoint contracts regardless of
whether uiConfig is set.
@cmgrote
Copy link
Copy Markdown
Collaborator Author

cmgrote commented Jun 3, 2026

@sdk-review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

Earlier @sdk-review trigger (click to expand)

🔍 SDK Review (mothership) triggered by @cmgrote at 2026-06-03T13:53:26.635Z.

Watch the workflow run live — the review summary will appear as a separate comment when complete (typical: 5–30 min, hard cap 2h).


🟥 Run ended without a clean completion — status unknown, cost $unknown, duration 20m 55s.

@mothership-ai
Copy link
Copy Markdown
Contributor

mothership-ai Bot commented Jun 3, 2026

SDK Re-review (mothership): PR #1980 — feat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py

Verdict: READY TO MERGE

Iteration delta is clean. The previous Important [DX] blocker (undocumented argoPackageName / argoTemplateName / appServiceUrl) is closed via a new "E2E Test Harness" subsection in contract-toolkit/docs/reference.md, and the bulk of the prior nit list landed in this round: a 572-line tests/e2e_codegen_test.pkl golden-snapshot suite, an escapePyStr helper applied at every interpolation site, a tightened pascalCase splitter ([^A-Za-z0-9]+), frozen=True on the generated CredentialBodyExtra ConfigDict, and a strengthened test-sdk-import.py that asserts expected class names + harness attrs + Pydantic model_fields. One carry-forward nit remains (a stale E2EOutput.pkl reference in a sibling docstring missed during the file-level update); not blocking. Approving.


PR Title Check

  • Alignedfeat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py matches §2f-bis Row 1 (SDK files touched + feat() with any scope satisfies the release walker).

Affected Toolkit Surfaces

  • contract-toolkit/src/App.pkl — three new public fields + four codegen entry points (generateE2EBasePy, generateE2ESubstitutionsPy, generateE2ECredentialPy + helpers).
  • contract-toolkit/docs/reference.md — new "E2E Test Harness" subsection.
  • contract-toolkit/scripts/test-sdk-import.py — split into _load_module() + test_input() + test_e2e().
  • contract-toolkit/tests/e2e_codegen_test.pkl — new golden-snapshot suite (~50 facts, 12 fixtures).
  • contract-toolkit/examples/*/app/generated/_e2e_*.py — regenerated outputs across all 17 example artifacts.
  • application_sdk/testing/e2e/credential.py, substitutions.py — file-level docstrings refreshed.

Cross-Repo Validation

  • Generated SDK input contract: validated — "Generated Python lint and SDK imports" (pass) + "PKL tests and invariants" (pass) on HEAD 06d9a13.
  • UI rendering compatibility: not applicable (no widget catalog or UI schema changes).
  • Manifest substitution compatibility: not applicable (no manifest.json shape changes; the substitution model only changes the generation of _e2e_substitutions.py, not what Heracles substitutes).
  • Workflow execution contract: not applicable (no AE DAG / manifest.json field changes).
  • Representative app pattern: not applicable (toolkit-internal codegen; example regeneration is in-tree).

Delta from previous review

  • Resolved (8/9):
    • ✅ Important [DX] App.pkl L173-186 — argoPackageName / argoTemplateName / appServiceUrl now documented in docs/reference.md "E2E Test Harness" subsection with defaults + override guidance.
    • ✅ Nit [QUAL] credential.py L7-8 — file-level docstring rewritten: now correctly says "auth-specific fields keep their type with a sentinel default — \"\" for str, 0 for int; conditional common fields become Optional".
    • ✅ Nit [TEST] test-sdk-import.py L46-52 — test_e2e() now asserts _E2E_CLASS_SUFFIX lookup (<PascalCase>GeneratedE2EBase / MustacheSubstitutions / CredentialBody), harness attrs, and model_fields for Pydantic models.
    • ✅ Nit [TEST] App.pkl codegen — new tests/e2e_codegen_test.pkl (572 lines, ~50 facts) covers the widget-type matrix (Boolean / Numeric / Radio / DropDown / SqlTree / TextInput-fallback / ConditionalInput), Literal/Any imports, alias preservation, common-vs-auth-specific dedup, and frozen-config invariants.
    • ✅ Nit [BUG] App.pkl interpolation escaping — escapePyStr helper added and applied at every site emitting Python source from connector-controlled Pkl values (name, argoPackageName, argoTemplateName, appServiceUrl, connector.value, connector.category).
    • ✅ Nit [BUG] App.pkl pascalCase splitter — broadened to [^A-Za-z0-9]+, so non-conventional names (digits-with-mixed-separators, future drift) yield a valid Python identifier.
    • ✅ Nit [BUG] App.pkl CredentialBodyExtra ConfigDict — generated ConfigDict now sets frozen=True for parity with the inheriting main subclass.
    • ✅ Nit [STRUCT] App.pkl size — explicitly deferred in the prior review as design follow-up; not iteration-blocking.
  • Still present (1/9):
    • 🟡 Nit [QUAL] application_sdk/testing/e2e/substitutions.py:59 — file-level docstring (L13-15) was correctly updated this PR, but the SQLMustacheSubstitutions class docstring at L53-60 still references the never-created contract-toolkit/src/E2EOutput.pkl. Fix: same swap the file-level docstring received — (driven by the connector's app.pkl via codegen — see generateE2ESubstitutionsPy() in contract-toolkit/src/App.pkl). Posted as an inline nit.
  • New / Downgraded: none.

Findings

application_sdk/testing/e2e/substitutions.py

  • Nit [QUAL] L59 — Carry-forward from prior review. The file-level docstring was rewritten correctly, but the SQLMustacheSubstitutions class docstring still cites contract-toolkit/src/E2EOutput.pkl — a path that does not exist in this repo and that this PR's whole premise is replacing. Path: follow-up — replace with (driven by the connector's app.pkl via codegen — see generateE2ESubstitutionsPy() in contract-toolkit/src/App.pkl). Trivial, not iteration-blocking.

Holistic Recommendations

  • The widget-type → Pydantic-field-type table in getSubsFieldLine is now exercised by tests/e2e_codegen_test.pkl's widget matrix. That closes the implicit-contract gap flagged in the prior review and should make future widget additions either light up a missing test or fall through to the str default with a visible diff in the regenerated examples. Worth keeping the test file as the authoritative golden when reviewing future widget PRs.
  • escapePyStr is the right shape for the trust boundary here (connector-author-controlled Pkl → emitted as Python source). The default values for the three new fields (@atlan/{name}, atlan-{name}, http://{name}.{name}-app.svc.cluster.local) bake the in-cluster naming convention into the toolkit; the new docs subsection correctly flags this as override-able. If the cluster pattern ever changes, every connector picks it up via toolkit version bump rather than per-connector overrides — a defensible default.
  • The CredentialBodyExtra frozen=True parity fix is currently latent (no example connector triggers hasExtraModel) but the Pkl test asserts it now, so the contract drift can't silently re-open.

Strengths

  • Closes the previous Important blocker cleanly — the new "E2E Test Harness" subsection in docs/reference.md documents purpose, default, and when-to-override for all three fields exactly where readers expect them.
  • Adds the tests that were the largest gaptests/e2e_codegen_test.pkl is a 572-line golden-snapshot suite over 12 fixtures, exercising the widget-type dispatch matrix, parent-class routing (BaseE2ETest vs SQLAppE2ETest), pascalCase identifier generation, alias preservation, conditional Optional emission, and the frozen=True Extra-model contract — exactly the surface flagged.
  • Hardens the toolkit's trust boundary at the right layerescapePyStr applied at every source-emission site means a connector-author-controlled string with ", \, or control chars no longer produces malformed Python. Belt-and-suspenders with the tightened pascalCase regex.
  • Strengthens import smoke test from "imports without error" to a shape assertiontest_e2e() now asserts the deterministic class names + Pydantic model_fields + harness attrs, catching silent codegen regressions that the prior version would have missed.
  • Conservative iteration — three additive Pkl fields, four codegen entry points, no public symbol removed, no BaseE2ETest/SQLAppE2ETest/MustacheSubstitutions/CredentialBody API touched. Release walker stays honest.

CI: all required checks passing (sdk-review pending = this run) | check via gh pr checks 1980 --repo atlanhq/application-sdk
Run: view workflow logs + cost

atlan-ci
atlan-ci previously approved these changes Jun 3, 2026
Copy link
Copy Markdown
Collaborator

@atlan-ci atlan-ci left a comment

Choose a reason for hiding this comment

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

SDK reviewer's verdict: READY TO MERGE.

Full review summary is in the comment posted on this PR.

…ons docstring

Points to generateE2ESubstitutionsPy() in App.pkl, matching the
correction already applied to the file-level docstring.
@cmgrote
Copy link
Copy Markdown
Collaborator Author

cmgrote commented Jun 3, 2026

@sdk-review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 3, 2026

🔍 SDK Review (mothership) triggered by @cmgrote at 2026-06-03T15:00:37.893Z.

Watch the workflow run live — the review summary will appear as a separate comment when complete (typical: 5–30 min, hard cap 2h).


Completed — status completed, cost $2.512189, duration 9m 56s.
Error: unknown

@mothership-ai
Copy link
Copy Markdown
Contributor

mothership-ai Bot commented Jun 3, 2026

Contract Toolkit Re-review (mothership): PR #1980 — feat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py

Verdict: READY TO MERGE

Single-commit delta since the prior approval. The one carry-forward Nit — the SQLMustacheSubstitutions class docstring still pointing at the never-created E2EOutput.pkl — is now fixed exactly as recommended (generateE2ESubstitutionsPy() in contract-toolkit/src/App.pkl), and a grep for E2EOutput.pkl across application_sdk/ and contract-toolkit/ returns zero hits. No other code, generated artifacts, or tests changed; all toolkit local checks pass on this HEAD. Approving.


PR Title Check

  • Alignedfeat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py matches §2f-bis Row 1 (SDK files touched + feat() with any scope satisfies the release walker).

Affected Toolkit Surfaces

  • contract-toolkit/src/App.pkl — three new public fields + four codegen entry points (carried forward from prior review; unchanged this iteration).
  • contract-toolkit/docs/reference.md — "E2E Test Harness" subsection (carried forward).
  • contract-toolkit/scripts/test-sdk-import.py_load_module() / test_input() / test_e2e() split (carried forward).
  • contract-toolkit/tests/e2e_codegen_test.pkl — golden-snapshot suite (carried forward).
  • contract-toolkit/examples/*/app/generated/_e2e_*.py — regenerated outputs across all example artifacts (carried forward).
  • application_sdk/testing/e2e/credential.py — file-level docstring (carried forward, correct).
  • application_sdk/testing/e2e/substitutions.py — file-level docstring (carried forward) + SQLMustacheSubstitutions class docstring updated this iteration (the only delta in 2d0dc8b).

Cross-Repo Validation

  • UI rendering compatibility: not applicable
  • Manifest substitution compatibility: not applicable
  • Workflow execution contract: not applicable
  • Generated SDK input contract: validated
  • Representative app pattern: not applicable

Delta from previous review

  • Resolved (1):
    • ✅ Nit [QUAL] application_sdk/testing/e2e/substitutions.py:59SQLMustacheSubstitutions class docstring now reads (driven by the connector's app.pkl via codegen — see generateE2ESubstitutionsPy() in contract-toolkit/src/App.pkl). Matches the file-level docstring style and the recommendation from the prior review.
  • Still present (0): none.
  • New (0): none.
  • Downgraded (0): none.

Findings

No findings.

Holistic Recommendations

  • This iteration is the textbook small-delta re-review: a single trivial docstring change that closes the only carry-forward Nit. The release walker sees feat(contract-toolkit): codegen _e2e_base.py, ... as the squash subject, which correctly drives a feat-level bump for the codegen surface introduced in this PR (the docs(e2e): ... commit subject is consumed by squash and does not under-bump the release).

Strengths

  • Closes the last carry-forward Nit cleanly — same wording shape as the file-level docstring fix that was already accepted, so the two related class docstrings now agree on what generates the per-connector subclasses.
  • Zero scope creep — the new commit touches only application_sdk/testing/e2e/substitutions.py:53-60. No code, no contracts, no generated artifacts, no tests changed; the prior approval's substantive surface area is bit-identical.
  • PR-bound generated-input validation re-confirmed on this HEADregenerate-all.sh, check-invariants.sh, pkl test tests/*.pkl (125/125), and test-sdk-import.py (25/25) all pass.

CI: all required checks passing (sdk-review pending = this run)
Models: Claude Opus 4.7 (review)
Cross-model agreement: N/A (single-commit re-review, no Wave 2 needed)
Run: view workflow logs + cost

Copy link
Copy Markdown
Collaborator

@atlan-ci atlan-ci left a comment

Choose a reason for hiding this comment

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

SDK reviewer's verdict: READY TO MERGE.

Full review summary is in the comment posted on this PR.

@mothership-ai
Copy link
Copy Markdown
Contributor

mothership-ai Bot commented Jun 3, 2026

Contract Toolkit Re-review (mothership): PR #1980 — feat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py

Verdict: READY TO MERGE

Single-commit delta since the previous approval (06d9a132d0dc8b, +2/-1 in application_sdk/testing/e2e/substitutions.py) closes the one carry-forward Nit verbatim — the SQLMustacheSubstitutions class docstring at L59 now points at generateE2ESubstitutionsPy() in contract-toolkit/src/App.pkl instead of the never-created E2EOutput.pkl, matching the file-level docstring fix already in the prior round. No toolkit/codegen surface changed; CI "PKL tests and invariants", "Verify generated output", "Toolkit docs update check", and the full unit-test matrix are all green at HEAD. Re-approving.


PR Title Check

  • Alignedfeat(contract-toolkit): codegen _e2e_base.py, _e2e_credential.py, _e2e_substitutions.py matches §2f-bis Row 1 (SDK files touched + feat() with any scope satisfies the release walker; the (contract-toolkit) scope is informative, not required, when SDK files are in the bucket).

Affected Toolkit Surfaces

  • application_sdk/testing/e2e/substitutions.py — class-level docstring on SQLMustacheSubstitutions updated to reference the live codegen entry point (generateE2ESubstitutionsPy() in App.pkl) instead of the stale E2EOutput.pkl path.
  • All other toolkit surfaces (App.pkl fields, codegen entry points, generated examples, golden-snapshot suite, docs reference, test-sdk-import.py) are unchanged from the previously-approved HEAD.

Cross-Repo Validation

  • UI rendering compatibility: not applicable
  • Manifest substitution compatibility: not applicable
  • Workflow execution contract: not applicable
  • Generated SDK input contract: validated
  • Representative app pattern: not applicable

Delta from previous review

  • Resolved (1):
    • ✅ Nit [QUAL] application_sdk/testing/e2e/substitutions.py:59SQLMustacheSubstitutions class docstring now reads (driven by the connector's app.pkl via codegen — see generateE2ESubstitutionsPy() in contract-toolkit/src/App.pkl), matching the prior review's recommended fix and the file-level docstring already corrected in the previous round.
  • Still present (0): none.
  • New (0): none.
  • Downgraded (0): none.

Findings

No findings. The single-commit delta is a docstring correction that resolves the only outstanding nit; no new code, no contract changes, no public-API surface touched.

Holistic Recommendations

  • The class-docstring/file-docstring symmetry is now restored. Worth keeping in mind for future application_sdk/testing/e2e/*.py edits: when the file-level docstring cites the codegen entry point, every class docstring in the file should cite the same entry point — a stale reference inside one class survived a file-level rewrite this round, and would have been easy to miss again without the prior review carrying it forward.

Strengths

  • Surgical fix — single file, single class docstring, +2/-1 lines. Exactly the change the prior review asked for, no scope creep.
  • Conventional Commits hygienedocs(e2e): is the right type/scope for a docstring-only change; the SDK release walker still gets its feat(contract-toolkit) PR-title bump when this squash-merges, and individual commit history stays parseable.
  • Closes the iteration cleanly — every finding from the original review is now either resolved or explicitly deferred-as-design; nothing is silently in flight.

CI: all required checks passing (sdk-review pending = this run)
Models: Claude Opus 4.6 (review)
Cross-model agreement: n/a (trivial delta, adversarial skipped per ORCHESTRATION §2b)
Run: view workflow logs + cost

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.

4 participants