Skip to content

perf(validation): serve the asset barrel lazily to keep pyatlan off the import path - #4795

Open
OnkarVO7 wants to merge 4 commits into
mainfrom
sdk-validation-lazy-asset-barrel
Open

OnkarVO7 wants to merge 4 commits into
mainfrom
sdk-validation-lazy-asset-barrel

Conversation

@OnkarVO7

@OnkarVO7 OnkarVO7 commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator

Linear: AUT-1240

What

application_sdk/validation/__init__.py imports validation.assets and validation.asset_rules at module scope. Both import pyatlan_v9 at module scope, which cascades into pyatlan. So importing anything from this package loads the entire typed asset model — 238 + 695 modules, ~140 MiB resident.

This serves those 13 names lazily via the package's existing lazy_getattr helper (PEP 562), the same pattern already used by handler, clients, contracts, credentials and five other packages here.

__all__ is unchanged and every name still resolves; a TYPE_CHECKING block keeps the annotations intact for type checkers.

Why it matters

The cost lands on every worker that registers activities. create_activity_from_task (execution/_temporal/activities.py:341) imports validation.interceptor, and importing any validation submodule executes the package __init__:

get_all_task_activities() -> create_activity_from_task()
  -> from application_sdk.validation.interceptor import ...
    -> validation/__init__.py   from ...validation.assets import (...)
      -> assets.py:61           from pyatlan_v9.model.assets import Asset
        -> pyatlan_v9/.../referenceable.py -> pyatlan.model.fields.atlan_fields

interceptor.py imports only validation.artifacts and validation.sources. It never touches assets. The whole 140 MiB is a barrel pulling in a sibling that nobody on this path asked for.

The import at activities.py:341 already carries a comment explaining it was pushed into function scope so the handler and server processes would not pay for pyatlan_v9. That fixed half the problem — the worker still pays, because for the worker the import does happen.

Measured

Automation Engine worker, 2x2 factorial in a single venv on one machine, 3 reps per arm, median reported. The only SDK variable is this package's __init__.py, swapped in place between the eager and lazy versions — the eager file is byte-identical to released 3.52, so there is no version drift between arms. "Full boot" = the worker's boot-path imports plus get_all_task_activities().

AE code this PR registry scan full boot modules heavy libs loaded
main no +147.3 MiB 401.0 MiB 5,260 10
main yes +0.6 MiB 261.7 MiB 4,270 8
AE #1364 no +148.0 MiB 288.9 MiB 2,906 2
AE #1364 yes +0.6 MiB 141.6 MiB 1,873 0

This change is worth ~139 MiB on its own and is independent of the Automation Engine work: it removes the registry-scan cost (147.3 -> 0.6 MiB) and leaves boot-path imports untouched, while AE #1364 does the reverse. The two compose to -259 MiB without overlapping.

get_all_task_activities() still returns the same 40 activities.

This is deferral, not removal: a caller that actually validates assets pays the same cost at that point. Most activity workers never do.

The main / no arm is the noisy one (393.8 / 401.0 / 414.1 across reps, ~+-10 MiB); every other arm varied by under 0.5 MiB.

One real behaviour change, and how it is handled

The eager imports had an incidental side effect: from .assets import X binds assets as an attribute of the package. Dropping them would make this start raising AttributeError:

import application_sdk.validation as v
v.assets.validate_transformed_dir

This is handled by passing lazy_getattr's existing submodules argument:

_SUBMODULES = ("assets", "asset_rules")

def __getattr__(name: str) -> Any:
    return lazy_getattr(__name__, name, _LAZY, globals(), _SUBMODULES)

Those two submodules are imported on access, so the attribute works and the dependency floor is unchanged — a bare import application_sdk.validation still loads no pyatlan.

Worth flagging how this was nearly missed: the first compatibility probe reported v.assets as fine. It was not. An earlier probe in the same process had imported the submodule, and importing pkg.sub anywhere binds sub on pkg — so the assertion passed for the wrong reason. Re-run in a fresh interpreter it failed. The regression test for it is subprocess-based for exactly this reason.

Consumer impact

Swept the org for every repo that touches this package (5 queries, not 1 — searching the dotted path alone misses bare-symbol imports and from application_sdk import validation). Seven non-SDK repos reference it. Every real import is one of two patterns, both unaffected:

repo pattern status
atlan-hive-app, atlan-teradata-app from application_sdk.validation import validate_transformed_dir resolves via __getattr__
atlan-workdayprismanalytics-app from application_sdk.validation.assets import validate_asset direct submodule, untouched
atlan-sapanalyticscloud-app from application_sdk.validation.ndjson import iter_ndjson_lines unaffected, and now cheaper

The remaining references (atlan-cosmosdb-app, atlan-trino-app, atlan-coalesce-app, atlan-quicksight-app, connector-pulse, marketplace-partner) are docstrings, READMEs, ADRs and log files, not code. from application_sdk import validation has zero hits org-wide. Inside this repo, every validation.assets reference is a Sphinx :func:/:mod: docstring link, not attribute access.

Caveat: code search only indexes default branches, so it cannot see feature branches or unindexed repos. That is why the _SUBMODULES guard is in rather than relying on the sweep — an unseen consumer using the attribute form keeps working regardless.

This closes a gap the package already documents

The module docstring states a standing dependency floor — nothing imports pyarrow, pandas or pandera at module scope — and test_artifact_dependency_floor.py enforces it statically. pyatlan_v9 is heavier than all three and was not covered.

ndjson.py's docstring said its deferred import of assets "buys no dependency-floor benefit — this package's __init__ imports assets at module scope, so pyatlan_v9 is already loaded by the time anything can import this module." This change makes that false, so it is corrected: the deferral does now buy the benefit.

Tests

Three tests added to test_artifact_dependency_floor.py. Each was verified to fail without its corresponding fix, so none is vacuous:

  • test_importing_the_package_does_not_load_pyatlan — subprocess, because whether pyatlan_v9 is warm in the test interpreter depends on what an earlier test imported. Fails against the eager barrel (True != False).
  • test_every_lazy_name_still_resolves — every __all__ entry is reachable, so deferral cannot silently drop a name.
  • test_the_asset_submodules_are_still_package_attributes — subprocess, loops over ("assets", "asset_rules"). Fails without _SUBMODULES.

uv run pytest tests/unit on the merged branch — 14,323 passed, 12 skipped, 5 deselected, 0 failed, 0 errors. (The 3 failures and 10 errors noted on earlier revisions of this PR were pre-existing on main and have since been fixed there.)

pre-commit (ruff check, ruff format, pyright) clean.

Scope

3 files, +140/-18: the barrel, the ndjson.py docstring the change made false, and the tests.

Downstream

Opened as a draft pending review of the consumer side. Automation Engine's matching change is atlanhq/atlan-automation-engine-app#1364, which pins this branch for end-to-end testing. With both landed its worker boot drops 401 MiB -> 142 MiB.

🤖 Generated with Claude Code

…he import path

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

📜 Docstring Coverage Report

RESULT: PASSED (minimum: 75.0%, actual: 80.0%)

Detailed Coverage Report
= Coverage for /home/runner/work/application-sdk/application-sdk/application_sdk/ =
----------------------------------- Summary ------------------------------------
| Name                                                           | Total | Miss | Cover | Cover% |
|----------------------------------------------------------------|-------|------|-------|--------|
| __init__.py                                                    |     1 |    0 |     1 |   100% |
| _build_info.py                                                 |     2 |    0 |     2 |   100% |
| _context_errors.py                                             |     7 |    3 |     4 |    57% |
| _discovery_errors.py                                           |     7 |    0 |     7 |   100% |
| _install.py                                                    |     6 |    0 |     6 |   100% |
| _logging.py                                                    |    13 |    8 |     5 |    38% |
| constants.py                                                   |    18 |   10 |     8 |    44% |
| discovery.py                                                   |    12 |    3 |     9 |    75% |
| main.py                                                        |    62 |   20 |    42 |    68% |
| main_errors.py                                                 |     5 |    0 |     5 |   100% |
| pkl_version.py                                                 |     1 |    0 |     1 |   100% |
| version.py                                                     |     1 |    0 |     1 |   100% |
| _runtime/__init__.py                                           |     1 |    0 |     1 |   100% |
| _runtime/cgroup.py                                             |     6 |    2 |     4 |    67% |
| _runtime/offload.py                                            |    65 |   17 |    48 |    74% |
| _runtime/progress.py                                           |    32 |    2 |    30 |    94% |
| app/__init__.py                                                |     1 |    0 |     1 |   100% |
| app/_artifact_schema_guard.py                                  |     8 |    0 |     8 |   100% |
| app/_ep_registration.py                                        |     6 |    0 |     6 |   100% |
| app/_generated_tree.py                                         |     1 |    0 |     1 |   100% |
| app/base.py                                                    |   104 |   23 |    81 |    78% |
| app/base_errors.py                                             |     5 |    0 |     5 |   100% |
| app/build_identity.py                                          |     1 |    0 |     1 |   100% |
| app/client.py                                                  |     1 |    0 |     1 |   100% |
| app/context.py                                                 |    42 |    2 |    40 |    95% |
| app/entrypoint.py                                              |    20 |    5 |    15 |    75% |
| app/registry.py                                                |    40 |   11 |    29 |    72% |
| app/task.py                                                    |    17 |    6 |    11 |    65% |
| clients/__init__.py                                            |     2 |    1 |     1 |    50% |
| clients/_interface.py                                          |     6 |    1 |     5 |    83% |
| clients/_sql_failure_classifier.py                             |     5 |    0 |     5 |   100% |
| clients/base.py                                                |    22 |   10 |    12 |    55% |
| clients/http_errors.py                                         |     2 |    0 |     2 |   100% |
| clients/models.py                                              |     2 |    0 |     2 |   100% |
| clients/redis.py                                               |    27 |    0 |    27 |   100% |
| clients/redis_errors.py                                        |     5 |    0 |     5 |   100% |
| clients/sql.py                                                 |    64 |   22 |    42 |    66% |
| clients/sql_errors.py                                          |    15 |    0 |    15 |   100% |
| clients/sql_typecasters.py                                     |    14 |    4 |    10 |    71% |
| clients/ssl_utils.py                                           |     8 |    0 |     8 |   100% |
| clients/azure/__init__.py                                      |     1 |    0 |     1 |   100% |
| clients/azure/auth.py                                          |     7 |    0 |     7 |   100% |
| clients/azure/azure_errors.py                                  |     8 |    0 |     8 |   100% |
| clients/azure/client.py                                        |    14 |    0 |    14 |   100% |
| common/__init__.py                                             |     1 |    0 |     1 |   100% |
| common/_env.py                                                 |     2 |    0 |     2 |   100% |
| common/_generated_tree.py                                      |     9 |    0 |     9 |   100% |
| common/_listing.py                                             |     7 |    0 |     7 |   100% |
| common/asset_serialization.py                                  |    20 |    5 |    15 |    75% |
| common/atomic.py                                               |    17 |    0 |    17 |   100% |
| common/aws_utils.py                                            |    13 |    1 |    12 |    92% |
| common/aws_utils_errors.py                                     |     8 |    0 |     8 |   100% |
| common/backoff.py                                              |     9 |    1 |     8 |    89% |
| common/build_identity.py                                       |     2 |    0 |     2 |   100% |
| common/concurrency.py                                          |     3 |    0 |     3 |   100% |
| common/dispatch.py                                             |     7 |    2 |     5 |    71% |
| common/entity_envelope.py                                      |    10 |    0 |    10 |   100% |
| common/env_warnings.py                                         |     2 |    0 |     2 |   100% |
| common/error_codes.py                                          |    15 |    3 |    12 |    80% |
| common/errors.py                                               |     8 |    0 |     8 |   100% |
| common/file_converter.py                                       |     9 |    5 |     4 |    44% |
| common/file_ops.py                                             |    16 |    1 |    15 |    94% |
| common/filter_matching.py                                      |     9 |    3 |     6 |    67% |
| common/last_sync.py                                            |     6 |    0 |     6 |   100% |
| common/logger.py                                               |     1 |    0 |     1 |   100% |
| common/models.py                                               |     4 |    2 |     2 |    50% |
| common/path.py                                                 |     2 |    1 |     1 |    50% |
| common/restart_marker.py                                       |     8 |    0 |     8 |   100% |
| common/spillable_dict.py                                       |    17 |   11 |     6 |    35% |
| common/sql_filters.py                                          |    18 |    4 |    14 |    78% |
| common/sql_filters_errors.py                                   |     2 |    0 |     2 |   100% |
| common/task_queue.py                                           |    10 |    0 |    10 |   100% |
| common/transforms.py                                           |     5 |    0 |     5 |   100% |
| common/types.py                                                |     2 |    0 |     2 |   100% |
| common/utils.py                                                |     2 |    0 |     2 |   100% |
| common/incremental/__init__.py                                 |     3 |    0 |     3 |   100% |
| common/incremental/helpers.py                                  |    13 |    0 |    13 |   100% |
| common/incremental/incremental_errors.py                       |    12 |    0 |    12 |   100% |
| common/incremental/marker.py                                   |    13 |    0 |    13 |   100% |
| common/incremental/models.py                                   |    11 |    0 |    11 |   100% |
| common/incremental/column_extraction/__init__.py               |     1 |    0 |     1 |   100% |
| common/incremental/column_extraction/analysis.py               |     4 |    0 |     4 |   100% |
| common/incremental/column_extraction/backfill.py               |     3 |    0 |     3 |   100% |
| common/incremental/state/__init__.py                           |     1 |    1 |     0 |     0% |
| common/incremental/state/incremental_diff.py                   |     8 |    0 |     8 |   100% |
| common/incremental/state/state_reader.py                       |     7 |    0 |     7 |   100% |
| common/incremental/state/state_writer.py                       |    15 |    1 |    14 |    93% |
| common/incremental/state/store.py                              |    23 |    6 |    17 |    74% |
| common/incremental/state/table_scope.py                        |     8 |    0 |     8 |   100% |
| common/incremental/storage/__init__.py                         |     1 |    1 |     0 |     0% |
| common/incremental/storage/duckdb_utils.py                     |    24 |    8 |    16 |    67% |
| common/incremental/storage/rocksdb_utils.py                    |    11 |    5 |     6 |    55% |
| contracts/__init__.py                                          |     3 |    2 |     1 |    33% |
| contracts/base.py                                              |    39 |    7 |    32 |    82% |
| contracts/cleanup.py                                           |     5 |    0 |     5 |   100% |
| contracts/compat.py                                            |     9 |    1 |     8 |    89% |
| contracts/events.py                                            |    12 |    0 |    12 |   100% |
| contracts/storage.py                                           |    12 |    2 |    10 |    83% |
| contracts/types.py                                             |    24 |    1 |    23 |    96% |
| contracts/types_errors.py                                      |     2 |    0 |     2 |   100% |
| credentials/__init__.py                                        |     3 |    2 |     1 |    33% |
| credentials/agent.py                                           |    21 |    4 |    17 |    81% |
| credentials/atlan.py                                           |    12 |    6 |     6 |    50% |
| credentials/atlan_client.py                                    |     6 |    0 |     6 |   100% |
| credentials/errors.py                                          |    20 |   12 |     8 |    40% |
| credentials/extra.py                                           |     3 |    1 |     2 |    67% |
| credentials/git.py                                             |     9 |    6 |     3 |    33% |
| credentials/ingress.py                                         |     9 |    0 |     9 |   100% |
| credentials/oauth.py                                           |    13 |    2 |    11 |    85% |
| credentials/ref.py                                             |    17 |    1 |    16 |    94% |
| credentials/registry.py                                        |    11 |    3 |     8 |    73% |
| credentials/requirements.py                                    |    19 |    7 |    12 |    63% |
| credentials/resolver.py                                        |    11 |    4 |     7 |    64% |
| credentials/routing.py                                         |    10 |    1 |     9 |    90% |
| credentials/spec.py                                            |    23 |   11 |    12 |    52% |
| credentials/types.py                                           |    35 |   17 |    18 |    51% |
| credentials/utils.py                                           |    16 |    3 |    13 |    81% |
| dev/__init__.py                                                |     1 |    0 |     1 |   100% |
| dev/_dapr.py                                                   |    17 |    3 |    14 |    82% |
| dev/_dapr_errors.py                                            |    10 |    9 |     1 |    10% |
| dev/_embedded.py                                               |     4 |    0 |     4 |   100% |
| dev/_pkl_errors.py                                             |     3 |    0 |     3 |   100% |
| dev/pkl.py                                                     |    16 |    6 |    10 |    62% |
| errors/__init__.py                                             |     4 |    1 |     3 |    75% |
| errors/base.py                                                 |    15 |    2 |    13 |    87% |
| errors/categories.py                                           |     3 |    0 |     3 |   100% |
| errors/http.py                                                 |     4 |    1 |     3 |    75% |
| errors/leaves.py                                               |    26 |    8 |    18 |    69% |
| errors/wire.py                                                 |     5 |    1 |     4 |    80% |
| execution/__init__.py                                          |     1 |    0 |     1 |   100% |
| execution/decorators.py                                        |     3 |    2 |     1 |    33% |
| execution/errors.py                                            |     2 |    0 |     2 |   100% |
| execution/heartbeat.py                                         |    26 |    4 |    22 |    85% |
| execution/progress.py                                          |     6 |    0 |     6 |   100% |
| execution/progress_telemetry.py                                |     7 |    1 |     6 |    86% |
| execution/retry.py                                             |     9 |    0 |     9 |   100% |
| execution/run_length.py                                        |     7 |    1 |     6 |    86% |
| execution/sandbox.py                                           |     4 |    0 |     4 |   100% |
| execution/settings.py                                          |    10 |    2 |     8 |    80% |
| execution/shutdown.py                                          |     4 |    0 |     4 |   100% |
| execution/_temporal/__init__.py                                |     1 |    1 |     0 |     0% |
| execution/_temporal/_activity_errors.py                        |     9 |    0 |     9 |   100% |
| execution/_temporal/_backend_errors.py                         |     6 |    4 |     2 |    33% |
| execution/_temporal/_lock_errors.py                            |     5 |    0 |     5 |   100% |
| execution/_temporal/_store_records.py                          |    17 |    3 |    14 |    82% |
| execution/_temporal/activities.py                              |    12 |    0 |    12 |   100% |
| execution/_temporal/activity_utils.py                          |     7 |    0 |     7 |   100% |
| execution/_temporal/auth.py                                    |    16 |    0 |    16 |   100% |
| execution/_temporal/backend.py                                 |    18 |    3 |    15 |    83% |
| execution/_temporal/converter.py                               |     3 |    0 |     3 |   100% |
| execution/_temporal/credential_sweep.py                        |     5 |    0 |     5 |   100% |
| execution/_temporal/eviction_retry.py                          |     4 |    0 |     4 |   100% |
| execution/_temporal/lock_activities.py                         |     5 |    0 |     5 |   100% |
| execution/_temporal/poll_state.py                              |     7 |    1 |     6 |    86% |
| execution/_temporal/preflight_gate.py                          |    93 |    8 |    85 |    91% |
| execution/_temporal/preflight_persist.py                       |    15 |    0 |    15 |   100% |
| execution/_temporal/preflight_transport.py                     |     8 |    3 |     5 |    62% |
| execution/_temporal/sdr.py                                     |    19 |    8 |    11 |    58% |
| execution/_temporal/store_assert.py                            |    25 |    4 |    21 |    84% |
| execution/_temporal/worker.py                                  |    20 |    6 |    14 |    70% |
| execution/_temporal/workflows.py                               |     3 |    0 |     3 |   100% |
| execution/_temporal/interceptors/__init__.py                   |     1 |    0 |     1 |   100% |
| execution/_temporal/interceptors/events.py                     |    28 |    3 |    25 |    89% |
| execution/_temporal/interceptors/liveness.py                   |    11 |    9 |     2 |    18% |
| execution/_temporal/interceptors/lock.py                       |    10 |    2 |     8 |    80% |
| execution/_temporal/interceptors/log.py                        |    25 |   12 |    13 |    52% |
| execution/_temporal/interceptors/metrics.py                    |    18 |   15 |     3 |    17% |
| execution/_temporal/interceptors/outputs.py                    |    22 |    9 |    13 |    59% |
| execution/_temporal/interceptors/sizing.py                     |    18 |    9 |     9 |    50% |
| execution/_temporal/interceptors/trace.py                      |     6 |    4 |     2 |    33% |
| handler/__init__.py                                            |     3 |    2 |     1 |    33% |
| handler/_dispatch.py                                           |    11 |    5 |     6 |    55% |
| handler/_preflight_outcome.py                                  |    16 |    0 |    16 |   100% |
| handler/_warmup.py                                             |    10 |    0 |    10 |   100% |
| handler/asgi.py                                                |    13 |    4 |     9 |    69% |
| handler/base.py                                                |    17 |    3 |    14 |    82% |
| handler/context.py                                             |    24 |    7 |    17 |    71% |
| handler/contracts.py                                           |    56 |   11 |    45 |    80% |
| handler/manifest.py                                            |     5 |    0 |     5 |   100% |
| handler/metadata_routes.py                                     |    29 |    5 |    24 |    83% |
| handler/object_routes.py                                       |    28 |   12 |    16 |    57% |
| handler/request_contract.py                                    |     5 |    1 |     4 |    80% |
| handler/routes.py                                              |    33 |   11 |    22 |    67% |
| handler/service.py                                             |    49 |   19 |    30 |    61% |
| handler/service_errors.py                                      |     4 |    0 |     4 |   100% |
| handler/source_probe_errors.py                                 |    13 |    0 |    13 |   100% |
| handler/source_probes.py                                       |    28 |   14 |    14 |    50% |
| infrastructure/__init__.py                                     |     1 |    0 |     1 |   100% |
| infrastructure/_secret_utils.py                                |     2 |    0 |     2 |   100% |
| infrastructure/_single_key_probe.py                            |     7 |    2 |     5 |    71% |
| infrastructure/bindings.py                                     |    16 |    3 |    13 |    81% |
| infrastructure/capacity.py                                     |    11 |    0 |    11 |   100% |
| infrastructure/context.py                                      |     8 |    0 |     8 |   100% |
| infrastructure/credential_vault.py                             |     8 |    3 |     5 |    62% |
| infrastructure/pubsub.py                                       |    13 |    3 |    10 |    77% |
| infrastructure/secrets.py                                      |    30 |    9 |    21 |    70% |
| infrastructure/state.py                                        |    10 |    7 |     3 |    30% |
| infrastructure/_dapr/__init__.py                               |     1 |    0 |     1 |   100% |
| infrastructure/_dapr/_dapr_errors.py                           |     3 |    0 |     3 |   100% |
| infrastructure/_dapr/client.py                                 |    36 |    4 |    32 |    89% |
| infrastructure/_dapr/credential_vault.py                       |    19 |    6 |    13 |    68% |
| infrastructure/_dapr/http.py                                   |    30 |   20 |    10 |    33% |
| infrastructure/_redis/__init__.py                              |     1 |    0 |     1 |   100% |
| infrastructure/_redis/capacity.py                              |     9 |    4 |     5 |    56% |
| observability/__init__.py                                      |     1 |    1 |     0 |     0% |
| observability/_objectstore_metric_exporter.py                  |    14 |    8 |     6 |    43% |
| observability/_objectstore_metric_reader.py                    |     2 |    0 |     2 |   100% |
| observability/_prometheus_enrichment.py                        |     6 |    3 |     3 |    50% |
| observability/background_loop.py                               |    26 |    6 |    20 |    77% |
| observability/cgroup.py                                        |    20 |    1 |    19 |    95% |
| observability/console_sink.py                                  |    15 |    6 |     9 |    60% |
| observability/context.py                                       |     6 |    0 |     6 |   100% |
| observability/correlation.py                                   |     6 |    0 |     6 |   100% |
| observability/dapr_log_forwarder.py                            |    17 |    4 |    13 |    76% |
| observability/events.py                                        |     1 |    0 |     1 |   100% |
| observability/logger_adaptor.py                                |    61 |   12 |    49 |    80% |
| observability/logger_adaptor_errors.py                         |     2 |    0 |     2 |   100% |
| observability/metrics.py                                       |     8 |    6 |     2 |    25% |
| observability/metrics_adaptor.py                               |    12 |    2 |    10 |    83% |
| observability/models.py                                        |     6 |    0 |     6 |   100% |
| observability/observability.py                                 |    27 |    5 |    22 |    81% |
| observability/pushgateway.py                                   |    16 |   11 |     5 |    31% |
| observability/pushgateway_errors.py                            |     3 |    0 |     3 |   100% |
| observability/resource_sampler.py                              |     6 |    0 |     6 |   100% |
| observability/segment_client.py                                |    21 |    3 |    18 |    86% |
| observability/sizing.py                                        |    16 |    7 |     9 |    56% |
| observability/sizing_census.py                                 |     8 |    3 |     5 |    62% |
| observability/sizing_inputs.py                                 |    13 |    3 |    10 |    77% |
| observability/sizing_sink.py                                   |    12 |    1 |    11 |    92% |
| observability/temporal_core_metrics.py                         |    11 |    2 |     9 |    82% |
| observability/trace_context.py                                 |     2 |    0 |     2 |   100% |
| observability/traces_adaptor.py                                |    14 |    1 |    13 |    93% |
| observability/utils.py                                         |     8 |    1 |     7 |    88% |
| observability/decorators/observability_decorator.py            |     7 |    4 |     3 |    43% |
| outputs/__init__.py                                            |     2 |    0 |     2 |   100% |
| outputs/collector.py                                           |    10 |    0 |    10 |   100% |
| outputs/models.py                                              |     3 |    0 |     3 |   100% |
| server/__init__.py                                             |     1 |    0 |     1 |   100% |
| server/health.py                                               |    24 |    0 |    24 |   100% |
| server/fastapi/models.py                                       |    21 |   17 |     4 |    19% |
| server/fastapi/utils.py                                        |     5 |    0 |     5 |   100% |
| server/mcp/__init__.py                                         |     2 |    2 |     0 |     0% |
| server/mcp/decorators.py                                       |     3 |    1 |     2 |    67% |
| server/mcp/models.py                                           |     2 |    2 |     0 |     0% |
| server/mcp/server.py                                           |     7 |    1 |     6 |    86% |
| server/middleware/__init__.py                                  |     1 |    0 |     1 |   100% |
| server/middleware/_constants.py                                |     1 |    0 |     1 |   100% |
| server/middleware/log.py                                       |     4 |    3 |     1 |    25% |
| storage/__init__.py                                            |     1 |    0 |     1 |   100% |
| storage/_budget.py                                             |    11 |    5 |     6 |    55% |
| storage/_concurrency.py                                        |     7 |    3 |     4 |    57% |
| storage/_credential_providers.py                               |     6 |    0 |     6 |   100% |
| storage/_local_marker.py                                       |    13 |    1 |    12 |    92% |
| storage/_locks.py                                              |     5 |    1 |     4 |    80% |
| storage/_manifest.py                                           |     3 |    0 |     3 |   100% |
| storage/_obstore_config.py                                     |    13 |    0 |    13 |   100% |
| storage/_telemetry.py                                          |     5 |    0 |     5 |   100% |
| storage/batch.py                                               |    31 |    5 |    26 |    84% |
| storage/binding.py                                             |    29 |    1 |    28 |    97% |
| storage/chunked.py                                             |    20 |    2 |    18 |    90% |
| storage/cloud.py                                               |    30 |    6 |    24 |    80% |
| storage/errors.py                                              |    61 |   38 |    23 |    38% |
| storage/factory.py                                             |     3 |    0 |     3 |   100% |
| storage/file_ref_sync.py                                       |    19 |    3 |    16 |    84% |
| storage/integrity.py                                           |    14 |    0 |    14 |   100% |
| storage/ops.py                                                 |    47 |    6 |    41 |    87% |
| storage/preflight.py                                           |    13 |    0 |    13 |   100% |
| storage/reference.py                                           |    34 |    3 |    31 |    91% |
| storage/rolling.py                                             |    39 |   15 |    24 |    62% |
| storage/rolling_errors.py                                      |     4 |    0 |     4 |   100% |
| storage/transfer.py                                            |    14 |    0 |    14 |   100% |
| storage/formats/__init__.py                                    |    33 |    0 |    33 |   100% |
| storage/formats/format_errors.py                               |    16 |    0 |    16 |   100% |
| storage/formats/json.py                                        |    16 |    6 |    10 |    62% |
| storage/formats/parquet.py                                     |    33 |    5 |    28 |    85% |
| storage/formats/utils.py                                       |    11 |    2 |     9 |    82% |
| templates/__init__.py                                          |     2 |    1 |     1 |    50% |
| templates/_template_errors.py                                  |    11 |    0 |    11 |   100% |
| templates/base_metadata_extractor.py                           |     4 |    1 |     3 |    75% |
| templates/incremental_sql_metadata_extractor.py                |    21 |    2 |    19 |    90% |
| templates/sql_app.py                                           |    50 |    6 |    44 |    88% |
| templates/sql_app_errors.py                                    |     9 |    0 |     9 |   100% |
| templates/sql_metadata_extractor.py                            |    14 |    1 |    13 |    93% |
| templates/sql_query_extractor.py                               |     6 |    1 |     5 |    83% |
| templates/contracts/__init__.py                                |     1 |    0 |     1 |   100% |
| templates/contracts/base_metadata_extraction.py                |     3 |    0 |     3 |   100% |
| templates/contracts/incremental_sql.py                         |    32 |    7 |    25 |    78% |
| templates/contracts/sql_metadata.py                            |    37 |    9 |    28 |    76% |
| templates/contracts/sql_query.py                               |     7 |    0 |     7 |   100% |
| test_utils/integration/__init__.py                             |     1 |    1 |     0 |     0% |
| testing/__init__.py                                            |     2 |    0 |     2 |   100% |
| testing/_errors.py                                             |     5 |    0 |     5 |   100% |
| testing/_mustache.py                                           |     2 |    0 |     2 |   100% |
| testing/fake_source.py                                         |    60 |   17 |    43 |    72% |
| testing/fixtures.py                                            |    12 |    0 |    12 |   100% |
| testing/golden.py                                              |    26 |   10 |    16 |    62% |
| testing/mocks.py                                               |    68 |   17 |    51 |    75% |
| testing/preflight.py                                           |    20 |    6 |    14 |    70% |
| testing/setup_routes.py                                        |    45 |    5 |    40 |    89% |
| testing/volatile_fields.py                                     |     1 |    0 |     1 |   100% |
| testing/warming.py                                             |    11 |    4 |     7 |    64% |
| testing/e2e/__init__.py                                        |     1 |    0 |     1 |   100% |
| testing/e2e/_errors.py                                         |    18 |    0 |    18 |   100% |
| testing/e2e/_manifest_identity.py                              |    11 |    0 |    11 |   100% |
| testing/e2e/base.py                                            |   137 |    7 |   130 |    95% |
| testing/e2e/client.py                                          |    29 |    7 |    22 |    76% |
| testing/e2e/config.py                                          |     5 |    0 |     5 |   100% |
| testing/e2e/credential.py                                      |     2 |    0 |     2 |   100% |
| testing/e2e/logs.py                                            |     9 |    1 |     8 |    89% |
| testing/e2e/payload.py                                         |    11 |    0 |    11 |   100% |
| testing/e2e/portforward.py                                     |     1 |    0 |     1 |   100% |
| testing/e2e/sql_app.py                                         |    10 |    0 |    10 |   100% |
| testing/e2e/substitutions.py                                   |     3 |    0 |     3 |   100% |
| testing/e2e/system_app.py                                      |    10 |    0 |    10 |   100% |
| testing/e2e/tenant_pool.py                                     |     3 |    0 |     3 |   100% |
| testing/e2e/workflows.py                                       |     6 |    1 |     5 |    83% |
| testing/full_dag/__init__.py                                   |     1 |    0 |     1 |   100% |
| testing/full_dag/_errors.py                                    |     1 |    0 |     1 |   100% |
| testing/full_dag/base.py                                       |    18 |    2 |    16 |    89% |
| testing/full_dag/client.py                                     |     1 |    0 |     1 |   100% |
| testing/full_dag/payload.py                                    |     8 |    0 |     8 |   100% |
| testing/full_dag/sql_app.py                                    |     6 |    1 |     5 |    83% |
| testing/harness/__init__.py                                    |     1 |    0 |     1 |   100% |
| testing/harness/_errors.py                                     |    13 |    0 |    13 |   100% |
| testing/harness/_poll.py                                       |    15 |    0 |    15 |   100% |
| testing/harness/bridge.py                                      |     5 |    0 |     5 |   100% |
| testing/harness/budgets.py                                     |     6 |    0 |     6 |   100% |
| testing/harness/evidence.py                                    |    15 |    1 |    14 |    93% |
| testing/harness/expectations.py                                |    41 |    1 |    40 |    98% |
| testing/harness/fixtures.py                                    |    43 |    4 |    39 |    91% |
| testing/harness/identity.py                                    |    11 |    1 |    10 |    91% |
| testing/harness/outcome.py                                     |    16 |    0 |    16 |   100% |
| testing/harness/preconditions.py                               |    19 |    4 |    15 |    79% |
| testing/harness/spec.py                                        |     2 |    0 |     2 |   100% |
| testing/harness/substrate.py                                   |     3 |    0 |     3 |   100% |
| testing/harness/waiting.py                                     |     8 |    0 |     8 |   100% |
| testing/harness/atlas/__init__.py                              |    29 |    6 |    23 |    79% |
| testing/harness/atlas/_errors.py                               |     2 |    0 |     2 |   100% |
| testing/harness/automation_engine/__init__.py                  |     1 |    0 |     1 |   100% |
| testing/harness/automation_engine/_errors.py                   |    10 |    0 |    10 |   100% |
| testing/harness/automation_engine/client.py                    |    39 |    4 |    35 |    90% |
| testing/harness/automation_engine/retry.py                     |    17 |    1 |    16 |    94% |
| testing/harness/automation_engine/wire.py                      |    24 |    2 |    22 |    92% |
| testing/harness/cluster/__init__.py                            |     1 |    0 |     1 |   100% |
| testing/harness/cluster/_errors.py                             |     4 |    0 |     4 |   100% |
| testing/harness/cluster/_portforward.py                        |    15 |    2 |    13 |    87% |
| testing/harness/cluster/_protocols.py                          |     9 |    0 |     9 |   100% |
| testing/harness/cluster/_states.py                             |     9 |    0 |     9 |   100% |
| testing/harness/cluster/kube.py                                |    50 |    7 |    43 |    86% |
| testing/harness/seed/__init__.py                               |     5 |    0 |     5 |   100% |
| testing/harness/seed/_errors.py                                |     7 |    0 |     7 |   100% |
| testing/harness/seed/_ndjson.py                                |     7 |    0 |     7 |   100% |
| testing/harness/seed/_publish.py                               |     8 |    0 |     8 |   100% |
| testing/harness/seed/_spec.py                                  |    11 |    0 |    11 |   100% |
| testing/harness/starters/__init__.py                           |     2 |    0 |     2 |   100% |
| testing/harness/starters/_ae.py                                |     4 |    0 |     4 |   100% |
| testing/harness/starters/_errors.py                            |     4 |    0 |     4 |   100% |
| testing/harness/starters/_queue.py                             |     3 |    0 |     3 |   100% |
| testing/harness/starters/_specs.py                             |    12 |    0 |    12 |   100% |
| testing/harness/teardown/__init__.py                           |     5 |    0 |     5 |   100% |
| testing/harness/teardown/_dag.py                               |     4 |    0 |     4 |   100% |
| testing/harness/teardown/_purge.py                             |     8 |    0 |     8 |   100% |
| testing/harness/temporal/__init__.py                           |     1 |    0 |     1 |   100% |
| testing/harness/temporal/_errors.py                            |     5 |    0 |     5 |   100% |
| testing/harness/temporal/_protocols.py                         |     4 |    0 |     4 |   100% |
| testing/harness/temporal/_states.py                            |     6 |    0 |     6 |   100% |
| testing/harness/temporal/client.py                             |    23 |    1 |    22 |    96% |
| testing/hypothesis/__init__.py                                 |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/__init__.py                      |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/sql_client.py                    |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/clients/__init__.py              |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/clients/sql.py                   |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/common/__init__.py               |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/common/logger.py                 |     3 |    0 |     3 |   100% |
| testing/hypothesis/strategies/handlers/__init__.py             |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/handlers/sql/__init__.py         |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/handlers/sql/sql_metadata.py     |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/handlers/sql/sql_preflight.py    |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/inputs/__init__.py               |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/inputs/json_input.py             |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/inputs/parquet_input.py          |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/outputs/__init__.py              |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/outputs/json_output.py           |     2 |    1 |     1 |    50% |
| testing/hypothesis/strategies/outputs/statestore.py            |     3 |    1 |     2 |    67% |
| testing/hypothesis/strategies/server/__init__.py               |     1 |    1 |     0 |     0% |
| testing/hypothesis/strategies/server/fastapi/__init__.py       |     1 |    1 |     0 |     0% |
| testing/integration/__init__.py                                |     3 |    1 |     2 |    67% |
| testing/integration/_errors.py                                 |    17 |    0 |    17 |   100% |
| testing/integration/assertions.py                              |    55 |   25 |    30 |    55% |
| testing/integration/client.py                                  |    18 |    0 |    18 |   100% |
| testing/integration/comparison.py                              |    12 |    1 |    11 |    92% |
| testing/integration/corpus.py                                  |    25 |    7 |    18 |    72% |
| testing/integration/fixtures.py                                |    26 |    1 |    25 |    96% |
| testing/integration/lazy.py                                    |    10 |    0 |    10 |   100% |
| testing/integration/models.py                                  |     9 |    0 |     9 |   100% |
| testing/integration/runner.py                                  |    27 |    2 |    25 |    93% |
| testing/integration/source.py                                  |     8 |    0 |     8 |   100% |
| testing/integration/validation.py                              |     7 |    0 |     7 |   100% |
| testing/parity/__init__.py                                     |     1 |    0 |     1 |   100% |
| testing/parity/__main__.py                                     |     2 |    1 |     1 |    50% |
| testing/parity/comparator.py                                   |     8 |    0 |     8 |   100% |
| testing/parity/models.py                                       |     5 |    1 |     4 |    80% |
| testing/parity/report.py                                       |     4 |    0 |     4 |   100% |
| testing/scale_data_generator/__init__.py                       |     1 |    0 |     1 |   100% |
| testing/scale_data_generator/config_loader.py                  |    11 |    4 |     7 |    64% |
| testing/scale_data_generator/data_generator.py                 |    10 |    3 |     7 |    70% |
| testing/scale_data_generator/driver.py                         |     3 |    3 |     0 |     0% |
| testing/scale_data_generator/output_handler/__init__.py        |     1 |    1 |     0 |     0% |
| testing/scale_data_generator/output_handler/base.py            |     7 |    3 |     4 |    57% |
| testing/scale_data_generator/output_handler/csv_handler.py     |     6 |    6 |     0 |     0% |
| testing/scale_data_generator/output_handler/json_handler.py    |     5 |    5 |     0 |     0% |
| testing/scale_data_generator/output_handler/parquet_handler.py |     6 |    6 |     0 |     0% |
| testing/sdr/__init__.py                                        |     1 |    0 |     1 |   100% |
| testing/sdr/base.py                                            |    14 |    3 |    11 |    79% |
| tools/__init__.py                                              |     1 |    1 |     0 |     0% |
| tools/provision_credentials.py                                 |     2 |    1 |     1 |    50% |
| transformers/__init__.py                                       |     4 |    2 |     2 |    50% |
| transformers/errors.py                                         |     2 |    1 |     1 |    50% |
| transformers/atlas/__init__.py                                 |     6 |    1 |     5 |    83% |
| transformers/atlas/errors.py                                   |     8 |    7 |     1 |    12% |
| transformers/atlas/sql.py                                      |    25 |    4 |    21 |    84% |
| transformers/common/__init__.py                                |     1 |    1 |     0 |     0% |
| transformers/common/last_sync.py                               |     1 |    0 |     1 |   100% |
| transformers/common/utils.py                                   |     6 |    0 |     6 |   100% |
| transformers/query/__init__.py                                 |    19 |    2 |    17 |    89% |
| transformers/query/errors.py                                   |     5 |    3 |     2 |    40% |
| validation/__init__.py                                         |     3 |    2 |     1 |    33% |
| validation/artifacts.py                                        |    28 |    2 |    26 |    93% |
| validation/asset_rules.py                                      |     3 |    0 |     3 |   100% |
| validation/assets.py                                           |    33 |    2 |    31 |    94% |
| validation/interceptor.py                                      |    17 |    0 |    17 |   100% |
| validation/ndjson.py                                           |    28 |    4 |    24 |    86% |
| validation/parquet.py                                          |    16 |    0 |    16 |   100% |
| validation/protocols.py                                        |     9 |    0 |     9 |   100% |
| validation/sources.py                                          |    15 |    0 |    15 |   100% |
| validation/wrapper.py                                          |     8 |    0 |     8 |   100% |
|----------------------------------------------------------------|-------|------|-------|--------|
| TOTAL                                                          |  5424 | 1087 |  4337 |  80.0% |
---------------- RESULT: PASSED (minimum: 0.0%, actual: 80.0%) -----------------

@atlan-app-fleet

atlan-app-fleet Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

☂️ Code Coverage

current status: ✅

Overall Coverage

Statements Covered Coverage Threshold Status
38197 36240 95% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
application_sdk/validation/init.py 84% 🟢
application_sdk/validation/ndjson.py 96% 🟢
TOTAL 90% 🟢

updated for commit: d0c4a68 by action🐍

@OnkarVO7
OnkarVO7 marked this pull request as ready for review November 10, 2026 07:23
@linear

linear Bot commented Nov 10, 2026

Copy link
Copy Markdown

AUT-1240

@OnkarVO7
OnkarVO7 marked this pull request as draft November 10, 2026 07:32
@OnkarVO7
OnkarVO7 marked this pull request as ready for review November 10, 2026 07:59

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant