From 8125426703e8c5864e21636e2a6e8b7273b8a671 Mon Sep 17 00:00:00 2001 From: Jan Kadlec Date: Wed, 16 Sep 2026 15:41:26 +0200 Subject: [PATCH] perf: cut gooddata_sdk import cost by importing only what the SDK uses `import gooddata_sdk` pulled in 2333 modules and ~0.58s on a warm cache, because three separate layers imported everything available rather than what was needed. A consumer that wants a single class (e.g. `Visualization`) paid the whole bill. 1. `gooddata_sdk/__init__.py` eagerly re-exported every public name, so touching any leaf module ran the entire SDK's import graph first. The re-exports are now resolved lazily via PEP 562 `__getattr__` (the pattern scipy/sklearn use), with `__all__` for `import *` and a `TYPE_CHECKING` block so type checkers and the griffe-based docs builder still resolve every name statically. 2. Five modules did `import gooddata_api_client.models as afm_models`, and `execution.py` did `from gooddata_api_client import models`. That aggregate imports all 1402 generated model classes; the SDK references 58. The generated header of that file says as much ("import only the models that you directly need"), and it is safe because openapi-generator emits a per-model `lazy_import()`, so leaf imports do not cascade. The 58 now live in `gooddata_sdk/_models.py`, which keeps the `afm_models.X` spelling at the call sites and gives a single list to maintain. 3. `client.py` and `catalog_service_base.py` did `from gooddata_api_client import apis`, importing all ~130 generated API classes (and transitively most models) to instantiate six. Those six now come from `gooddata_sdk/_apis.py`. Measured on py3.14, warm .pyc, best of 7 with the two versions interleaved: import gooddata_sdk 0.58s / 2333 mods -> 0.04s / 160 mods from gooddata_sdk.visualization import Visualization 0.54s / 2333 mods -> 0.19s / 991 mods from gooddata_sdk import GoodDataSdk 0.65s / 2333 mods -> 0.33s / 1402 mods The module counts are the stable figure; the wall times are this machine and move with load, so they are interleaved rather than compared across runs. Keeping attribute access working -------------------------------- The eager `__init__` used to populate the whole module tree as a side effect, so `import gooddata_sdk` then `gooddata_sdk.catalog.workspace` resolved. Dropping it broke that, so every subpackage now gets a lazy submodule `__getattr__` built by `gooddata_sdk/_lazy.py`. It deliberately does not translate a `ModuleNotFoundError` raised *inside* an existing submodule into `AttributeError`, so a genuinely missing dependency still reports itself rather than looking like a typo. Two intentional differences remain. `dir(gooddata_sdk)` now lists the public API plus every submodule (previously only the ones that happened to be imported), and `from gooddata_sdk import *` no longer leaks the `logging` module or the submodule names, since `__all__` now states the public API explicitly. Maintaining the lazy-import tables ---------------------------------- PEP 562 needs the name -> module mapping as data, and hand-maintaining ~260 string pairs would drift from the real imports invisibly: a missing entry means `from gooddata_sdk import NewThing` raises AttributeError at runtime, and a stale module path is just a wrong string. So the `TYPE_CHECKING` block is the single source of truth. It holds ordinary `from x import Y` statements that IDEs autocomplete, refactorings rewrite and `ty`/pyright verify, and `scripts/sync_lazy_imports.py` derives `_LAZY_IMPORTS` and `__all__` from it by AST into a marker-delimited region that is never edited by hand. Adding a public export is one normal import plus `--update`. Drift is caught in two independent places, verified against three scenarios (export added, module renamed, export removed): - the script with no flags reports drift and exits non-zero, and `test_lazy_imports_map_matches_type_checking_block` runs it, so CI fails with the command to fix it; - `test_all_lazy_exports_resolve` covers the other half -- a module that moved without the `TYPE_CHECKING` block being updated. The rest of `tests/sdk/test_lazy_imports.py` guards the module savings themselves, since one convenience import silently undoes them. The attribute-access cases each run in their own interpreter: a missing lazy hook in a subpackage is masked as soon as anything else has imported the tree. gooddata-pandas used the models aggregate for one class; it now imports it directly, and the test that patched `gooddata_pandas.dataframe.models.X` patches `gooddata_pandas.dataframe.X`. Its `[tool.ty.analysis]` allowed-unresolved-imports needed the `.**` glob that gooddata-sdk already uses: the bare `gooddata_api_client` entry covered the old aggregate import but not a leaf `gooddata_api_client.model.*` module. --- packages/gooddata-pandas/pyproject.toml | 4 +- .../src/gooddata_pandas/dataframe.py | 10 +- .../test_dataframe_for_exec_def_arrow.py | 2 +- .../gooddata-sdk/src/gooddata_sdk/__init__.py | 1263 ++++++++++++----- .../gooddata-sdk/src/gooddata_sdk/_apis.py | 23 + .../gooddata-sdk/src/gooddata_sdk/_lazy.py | 34 + .../gooddata-sdk/src/gooddata_sdk/_models.py | 133 ++ .../src/gooddata_sdk/catalog/__init__.py | 4 + .../gooddata_sdk/catalog/ai_lake/__init__.py | 4 + .../catalog/appearance/__init__.py | 4 + .../appearance/entity_model/__init__.py | 4 + .../catalog/catalog_service_base.py | 2 +- .../catalog/data_source/__init__.py | 4 + .../data_source/action_model/__init__.py | 4 + .../action_model/requests/__init__.py | 4 + .../action_model/responses/__init__.py | 4 + .../data_source/declarative_model/__init__.py | 4 + .../physical_model/__init__.py | 4 + .../data_source/entity_model/__init__.py | 4 + .../entity_model/content_objects/__init__.py | 4 + .../data_source/validation/__init__.py | 4 + .../gooddata_sdk/catalog/export/__init__.py | 4 + .../catalog/organization/__init__.py | 4 + .../catalog/organization/common/__init__.py | 4 + .../organization/entity_model/__init__.py | 4 + .../catalog/organization/layout/__init__.py | 4 + .../catalog/permission/__init__.py | 4 + .../permission/declarative_model/__init__.py | 4 + .../src/gooddata_sdk/catalog/user/__init__.py | 4 + .../user/declarative_model/__init__.py | 4 + .../catalog/user/entity_model/__init__.py | 4 + .../catalog/user/management_model/__init__.py | 4 + .../catalog/workspace/__init__.py | 4 + .../catalog/workspace/content_service.py | 2 +- .../workspace/declarative_model/__init__.py | 4 + .../declarative_model/workspace/__init__.py | 4 + .../workspace/analytics_model/__init__.py | 4 + .../workspace/logical_model/__init__.py | 4 + .../logical_model/dataset/__init__.py | 4 + .../dataset_extensions/__init__.py | 4 + .../logical_model/date_dataset/__init__.py | 4 + .../workspace/entity_model/__init__.py | 4 + .../entity_model/content_objects/__init__.py | 4 + .../entity_model/graph_objects/__init__.py | 4 + .../src/gooddata_sdk/cli/__init__.py | 4 + .../gooddata-sdk/src/gooddata_sdk/client.py | 2 +- .../src/gooddata_sdk/compute/__init__.py | 4 + .../gooddata_sdk/compute/model/__init__.py | 4 + .../gooddata_sdk/compute/model/attribute.py | 3 +- .../src/gooddata_sdk/compute/model/base.py | 3 +- .../gooddata_sdk/compute/model/execution.py | 3 +- .../src/gooddata_sdk/compute/model/filter.py | 38 +- .../src/gooddata_sdk/compute/model/metric.py | 2 +- .../tests/sdk/test_lazy_imports.py | 121 ++ scripts/sync_lazy_imports.py | 133 ++ 55 files changed, 1559 insertions(+), 371 deletions(-) create mode 100644 packages/gooddata-sdk/src/gooddata_sdk/_apis.py create mode 100644 packages/gooddata-sdk/src/gooddata_sdk/_lazy.py create mode 100644 packages/gooddata-sdk/src/gooddata_sdk/_models.py create mode 100644 packages/gooddata-sdk/tests/sdk/test_lazy_imports.py create mode 100755 scripts/sync_lazy_imports.py diff --git a/packages/gooddata-pandas/pyproject.toml b/packages/gooddata-pandas/pyproject.toml index 581322e57..8f5f26e5b 100644 --- a/packages/gooddata-pandas/pyproject.toml +++ b/packages/gooddata-pandas/pyproject.toml @@ -69,7 +69,9 @@ test = [ ] [tool.ty.analysis] -allowed-unresolved-imports = ["gooddata_api_client"] +# The `.**` glob matches gooddata-sdk: leaf model modules are imported directly rather than +# through the `gooddata_api_client.models` aggregate, and ty cannot resolve the generated code. +allowed-unresolved-imports = ["gooddata_api_client.**"] [tool.hatch.build.targets.wheel] packages = ["src/gooddata_pandas"] diff --git a/packages/gooddata-pandas/src/gooddata_pandas/dataframe.py b/packages/gooddata-pandas/src/gooddata_pandas/dataframe.py index aa3b37cf8..b9428c187 100644 --- a/packages/gooddata-pandas/src/gooddata_pandas/dataframe.py +++ b/packages/gooddata-pandas/src/gooddata_pandas/dataframe.py @@ -8,7 +8,7 @@ import pyarrow as pa import pandas -from gooddata_api_client import models +from gooddata_api_client.model.afm_execution_response import AfmExecutionResponse from gooddata_sdk import ( Attribute, BareExecutionResponse, @@ -691,9 +691,7 @@ def for_exec_result_id( exec_response = BareExecutionResponse( api_client=self._sdk.client, workspace_id=self._workspace_id, - execution_response=models.AfmExecutionResponse( - result_cache_metadata.execution_response, _check_type=False - ), + execution_response=AfmExecutionResponse(result_cache_metadata.execution_response, _check_type=False), ) table = exec_response.read_result_arrow(max_bytes=self._arrow_config.max_bytes) return self._table_to_df_and_metadata(table, exec_response, label_overrides, grand_totals_position) @@ -702,9 +700,7 @@ def for_exec_result_id( execution_response=BareExecutionResponse( api_client=self._sdk.client, workspace_id=self._workspace_id, - execution_response=models.AfmExecutionResponse( - result_cache_metadata.execution_response, _check_type=False - ), + execution_response=AfmExecutionResponse(result_cache_metadata.execution_response, _check_type=False), ), result_cache_metadata=result_cache_metadata, label_overrides=label_overrides, diff --git a/packages/gooddata-pandas/tests/dataframe/test_dataframe_for_exec_def_arrow.py b/packages/gooddata-pandas/tests/dataframe/test_dataframe_for_exec_def_arrow.py index 8fefed48a..fcf91c298 100644 --- a/packages/gooddata-pandas/tests/dataframe/test_dataframe_for_exec_def_arrow.py +++ b/packages/gooddata-pandas/tests/dataframe/test_dataframe_for_exec_def_arrow.py @@ -1400,7 +1400,7 @@ def test_for_exec_result_id_arrow_types_mapper(tmp_path: Path) -> None: with ( patch("gooddata_pandas.dataframe.BareExecutionResponse") as MockBareExec, - patch("gooddata_pandas.dataframe.models.AfmExecutionResponse"), + patch("gooddata_pandas.dataframe.AfmExecutionResponse"), ): mock_bare = MagicMock() mock_bare.read_result_arrow.return_value = table diff --git a/packages/gooddata-sdk/src/gooddata_sdk/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/__init__.py index f33e24a5a..eb049fcb5 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/__init__.py @@ -5,350 +5,929 @@ """ import logging +import pkgutil +from importlib import import_module +from typing import TYPE_CHECKING, Any +from gooddata_sdk._lazy import submodule_getattr from gooddata_sdk._version import __version__ -from gooddata_sdk.catalog.ai_lake.service import ( - CatalogAILakeOperation, - CatalogAILakeOperationError, - CatalogAILakeService, -) -from gooddata_sdk.catalog.appearance.entity_model.color_palette import ( - CatalogColorPalette, - CatalogColorPaletteAttributes, -) -from gooddata_sdk.catalog.appearance.entity_model.theme import ( - CatalogTheme, - CatalogThemeAttributes, -) -from gooddata_sdk.catalog.appearance.service import CatalogAppearanceService -from gooddata_sdk.catalog.data_source.action_model.requests.ldm_request import ( - CatalogGenerateLdmRequest, - CatalogPdmLdmRequest, - CatalogPdmSql, -) -from gooddata_sdk.catalog.data_source.action_model.requests.scan_model_request import CatalogScanModelRequest -from gooddata_sdk.catalog.data_source.action_model.requests.scan_sql_request import ScanSqlRequest -from gooddata_sdk.catalog.data_source.action_model.responses.scan_sql_response import ScanSqlResponse -from gooddata_sdk.catalog.data_source.action_model.sql_column import SqlColumn -from gooddata_sdk.catalog.data_source.declarative_model.data_source import ( - CatalogDeclarativeDataSource, - CatalogDeclarativeDataSources, -) -from gooddata_sdk.catalog.data_source.declarative_model.physical_model.pdm import CatalogDeclarativeTables -from gooddata_sdk.catalog.data_source.declarative_model.physical_model.table import ( - CatalogDeclarativeColumn, - CatalogDeclarativeTable, -) -from gooddata_sdk.catalog.data_source.entity_model.data_source import ( - CatalogDataSource, - CatalogDataSourceBigQuery, - CatalogDataSourceDatabricks, - CatalogDataSourceGdStorage, - CatalogDataSourceMariaDb, - CatalogDataSourceMotherDuck, - CatalogDataSourceMsSql, - CatalogDataSourceMySql, - CatalogDataSourcePostgres, - CatalogDataSourceRedshift, - CatalogDataSourceSnowflake, - CatalogDataSourceVertica, - DatabricksAttributes, - MariaDbAttributes, - MotherDuckAttributes, - MsSqlAttributes, - MySqlAttributes, - PostgresAttributes, - RedshiftAttributes, - SnowflakeAttributes, - VerticaAttributes, -) -from gooddata_sdk.catalog.data_source.service import CatalogDataSourceService -from gooddata_sdk.catalog.data_source.validation.data_source import DataSourceValidator -from gooddata_sdk.catalog.depends_on import CatalogDependsOn, CatalogDependsOnDateFilter -from gooddata_sdk.catalog.entity import ( - AttrCatalogEntity, - BasicCredentials, - ClientSecretCredentials, - KeyPairCredentials, - TokenCredentialsFromEnvVar, - TokenCredentialsFromFile, -) -from gooddata_sdk.catalog.export.request import ( - ExportCustomLabel, - ExportCustomMetric, - ExportCustomOverride, - ExportRequest, - ExportSettings, - GrandTotalsPosition, - SlidesExportRequest, - VisualExportRequest, -) -from gooddata_sdk.catalog.filter_by import CatalogFilterBy -from gooddata_sdk.catalog.identifier import ( - CatalogAssigneeIdentifier, - CatalogDatasetWorkspaceDataFilterIdentifier, - CatalogDeclarativeAnalyticalDashboardIdentifier, - CatalogExportDefinitionIdentifier, - CatalogNotificationChannelIdentifier, - CatalogUserIdentifier, - CatalogWorkspaceIdentifier, -) -from gooddata_sdk.catalog.organization.common.dashboard_slides_template import CatalogDashboardSlidesTemplate -from gooddata_sdk.catalog.organization.common.running_section import CatalogRunningSection -from gooddata_sdk.catalog.organization.common.slide_template import ( - CatalogContentSlideTemplate, - CatalogCoverSlideTemplate, - CatalogIntroSlideTemplate, - CatalogSectionSlideTemplate, -) -from gooddata_sdk.catalog.organization.common.widget_slides_template import CatalogWidgetSlidesTemplate -from gooddata_sdk.catalog.organization.entity_model.directive import CatalogCspDirective -from gooddata_sdk.catalog.organization.entity_model.export_template import ( - CatalogExportTemplate, - CatalogExportTemplateAttributes, -) -from gooddata_sdk.catalog.organization.entity_model.ip_allowlist_policy import ( - CatalogIpAllowlistPolicy, - CatalogIpAllowlistPolicyTargets, -) -from gooddata_sdk.catalog.organization.entity_model.jwk import ( - CatalogJwk, - CatalogJwkAttributes, - CatalogJwkDocument, - CatalogRsaSpecification, -) -from gooddata_sdk.catalog.organization.entity_model.llm_provider import ( - CatalogAwsBedrockProviderConfig, - CatalogAzureFoundryApiKeyAuth, - CatalogAzureFoundryProviderConfig, - CatalogBedrockAccessKeyAuth, - CatalogLlmProvider, - CatalogLlmProviderDocument, - CatalogLlmProviderModel, - CatalogLlmProviderModelsResult, - CatalogLlmProviderPatch, - CatalogLlmProviderPatchDocument, - CatalogLlmProviderTestResult, - CatalogModelTestResult, - CatalogOpenAiApiKeyAuth, - CatalogOpenAiProviderConfig, -) -from gooddata_sdk.catalog.organization.entity_model.organization import CatalogOrganization -from gooddata_sdk.catalog.organization.entity_model.setting import CatalogOrganizationSetting -from gooddata_sdk.catalog.organization.layout.export_template import ( - CatalogDeclarativeExportTemplate, -) -from gooddata_sdk.catalog.organization.layout.notification_channel import ( - CatalogDeclarativeNotificationChannel, - CatalogDefaultSmtp, - CatalogInPlatform, - CatalogNotificationChannelDestination, - CatalogSmtp, - CatalogWebhook, -) -from gooddata_sdk.catalog.organization.service import ( - HLL_TYPE_SETTING_ID, - HLL_TYPE_SETTING_TYPE, - CatalogOrganizationService, - HLLType, -) -from gooddata_sdk.catalog.permission.declarative_model.dashboard_assignees import ( - CatalogAvailableAssignees, - CatalogUserAssignee, - CatalogUserGroupAssignee, -) -from gooddata_sdk.catalog.permission.declarative_model.dashboard_permissions import ( - CatalogDashboardPermissions, - CatalogGrantedPermission, - CatalogUserGroupPermission, - CatalogUserPermission, -) -from gooddata_sdk.catalog.permission.declarative_model.manage_dashboard_permissions import ( - CatalogDashboardAssigneeIdentifier, - CatalogPermissionsForAssigneeIdentifier, - CatalogPermissionsForAssigneeRule, -) -from gooddata_sdk.catalog.permission.declarative_model.permission import ( - CatalogDeclarativeDashboardPermissionsForAssignee, - CatalogDeclarativeDashboardPermissionsForAssigneeRule, - CatalogDeclarativeDataSourcePermission, - CatalogDeclarativeOrganizationPermission, - CatalogDeclarativeSingleWorkspacePermission, - CatalogDeclarativeWorkspaceHierarchyPermission, - CatalogDeclarativeWorkspacePermissions, - CatalogOrganizationPermissionAssignment, -) -from gooddata_sdk.catalog.rule import CatalogAssigneeRule -from gooddata_sdk.catalog.types import UpsertOutcome -from gooddata_sdk.catalog.user.declarative_model.user import ( - CatalogDeclarativeUser, - CatalogDeclarativeUserPermission, - CatalogDeclarativeUsers, -) -from gooddata_sdk.catalog.user.declarative_model.user_and_user_groups import CatalogDeclarativeUsersUserGroups -from gooddata_sdk.catalog.user.declarative_model.user_group import ( - CatalogDeclarativeUserGroup, - CatalogDeclarativeUserGroupPermission, - CatalogDeclarativeUserGroups, -) -from gooddata_sdk.catalog.user.entity_model.user import CatalogUser -from gooddata_sdk.catalog.user.entity_model.user_group import CatalogUserGroup -from gooddata_sdk.catalog.user.management_model.management import ( - CatalogDataSourcePermissionAssignment, - CatalogPermissionAssignments, - CatalogPermissionsAssignment, - CatalogWorkspacePermissionAssignment, -) -from gooddata_sdk.catalog.validate_by_item import CatalogValidateByItem -from gooddata_sdk.catalog.workspace.aac import ( - aac_attribute_hierarchy_to_declarative, - aac_dashboard_to_declarative, - aac_dataset_to_declarative, - aac_date_dataset_to_declarative, - aac_metric_to_declarative, - aac_plugin_to_declarative, - aac_visualization_to_declarative, - declarative_attribute_hierarchy_to_aac, - declarative_dashboard_to_aac, - declarative_dataset_to_aac, - declarative_date_instance_to_aac, - declarative_metric_to_aac, - declarative_plugin_to_aac, - declarative_visualization_to_aac, - detect_yaml_format, - load_aac_workspace_from_disk, - store_aac_workspace_to_disk, -) -from gooddata_sdk.catalog.workspace.content_service import CatalogWorkspaceContent, CatalogWorkspaceContentService -from gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.analytics_model import ( - CatalogDeclarativeAnalytics, - CatalogDeclarativeMemoryItem, - CatalogDeclarativeMetric, - CatalogDeclarativeParameter, -) -from gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.export_definition import ( - CatalogDeclarativeExportDefinition, - CatalogDeclarativeExportDefinitionRequestPayload, -) -from gooddata_sdk.catalog.workspace.declarative_model.workspace.automation import ( - CatalogAutomationSchedule, - CatalogDeclarativeAutomation, -) -from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.data_filter_references import ( - CatalogDeclarativeWorkspaceDataFilterReferences, -) -from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset import ( - CatalogDataSourceTableIdentifier, - CatalogDeclarativeAggregatedFact, - CatalogDeclarativeAttribute, - CatalogDeclarativeDataset, - CatalogDeclarativeDatasetSql, - CatalogDeclarativeFact, - CatalogDeclarativeLabel, - CatalogDeclarativeReference, - CatalogDeclarativeWorkspaceDataFilterColumn, -) -from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset_extensions.dataset_extension import ( # noqa: E501 - CatalogDeclarativeDatasetExtension, -) -from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.date_dataset.date_dataset import ( - CatalogDeclarativeDateDataset, - CatalogGranularitiesFormatting, -) -from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.ldm import ( - CatalogDeclarativeLdm, - CatalogDeclarativeModel, -) -from gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace import ( - CatalogDeclarativeFilterView, - CatalogDeclarativeUserDataFilter, - CatalogDeclarativeUserDataFilters, - CatalogDeclarativeWorkspace, - CatalogDeclarativeWorkspaceDataFilter, - CatalogDeclarativeWorkspaceDataFilters, - CatalogDeclarativeWorkspaceDataFilterSetting, - CatalogDeclarativeWorkspaceModel, - CatalogDeclarativeWorkspaces, -) -from gooddata_sdk.catalog.workspace.entity_model.content_objects.dataset import ( - CatalogAttribute, - CatalogDataset, - CatalogFact, - CatalogLabel, -) -from gooddata_sdk.catalog.workspace.entity_model.content_objects.metric import CatalogMetric -from gooddata_sdk.catalog.workspace.entity_model.content_objects.workspace_setting import CatalogWorkspaceSetting -from gooddata_sdk.catalog.workspace.entity_model.graph_objects.graph import ( - CatalogDependentEntitiesGraph, - CatalogDependentEntitiesNode, - CatalogDependentEntitiesRequest, - CatalogDependentEntitiesResponse, - CatalogEntityIdentifier, -) -from gooddata_sdk.catalog.workspace.entity_model.user_data_filter import ( - CatalogUserDataFilter, - CatalogUserDataFilterAttributes, - CatalogUserDataFilterRelationships, -) -from gooddata_sdk.catalog.workspace.entity_model.workspace import CatalogWorkspace -from gooddata_sdk.client import GoodDataApiClient, GoodDataApiClientRetryConfig -from gooddata_sdk.compute.compute_to_sdk_converter import ComputeToSdkConverter -from gooddata_sdk.compute.model.attribute import Attribute -from gooddata_sdk.compute.model.base import ExecModelEntity, ObjId -from gooddata_sdk.compute.model.execution import ( - BareExecutionResponse, - Execution, - ExecutionDefinition, - ExecutionResponse, - ExecutionResult, - ResultCacheMetadata, - ResultSizeBytesLimitExceeded, - ResultSizeDimensions, - ResultSizeDimensionsLimitsExceeded, - TableDimension, - TotalDefinition, - TotalDimension, -) -from gooddata_sdk.compute.model.filter import ( - AbsoluteDateFilter, - AllMetricValueFilter, - AllTimeDateFilter, - AttributeFilter, - BoundedFilter, - CompoundMetricValueFilter, - Filter, - InlineFilter, - MatchAttributeFilter, - MetricValueComparisonCondition, - MetricValueFilter, - MetricValueRangeCondition, - NegativeAttributeFilter, - PositiveAttributeFilter, - RankingFilter, - RelativeDateFilter, -) -from gooddata_sdk.compute.model.metric import ( - ArithmeticMetric, - InlineMetric, - Metric, - PopDate, - PopDateDataset, - PopDateMetric, - PopDatesetMetric, - SimpleMetric, -) -from gooddata_sdk.compute.service import ComputeService -from gooddata_sdk.sdk import GoodDataSdk -from gooddata_sdk.table import ExecutionTable, TableService -from gooddata_sdk.utils import SideLoads -from gooddata_sdk.visualization import ( - Visualization, - VisualizationAttribute, - VisualizationBucket, - VisualizationFilter, - VisualizationMetric, - VisualizationService, -) + +if TYPE_CHECKING: + # Re-stated eagerly so that type checkers and IDEs resolve the lazy re-exports below. + from gooddata_sdk.catalog.ai_lake.service import ( + CatalogAILakeOperation, + CatalogAILakeOperationError, + CatalogAILakeService, + ) + from gooddata_sdk.catalog.appearance.entity_model.color_palette import ( + CatalogColorPalette, + CatalogColorPaletteAttributes, + ) + from gooddata_sdk.catalog.appearance.entity_model.theme import ( + CatalogTheme, + CatalogThemeAttributes, + ) + from gooddata_sdk.catalog.appearance.service import CatalogAppearanceService + from gooddata_sdk.catalog.data_source.action_model.requests.ldm_request import ( + CatalogGenerateLdmRequest, + CatalogPdmLdmRequest, + CatalogPdmSql, + ) + from gooddata_sdk.catalog.data_source.action_model.requests.scan_model_request import CatalogScanModelRequest + from gooddata_sdk.catalog.data_source.action_model.requests.scan_sql_request import ScanSqlRequest + from gooddata_sdk.catalog.data_source.action_model.responses.scan_sql_response import ScanSqlResponse + from gooddata_sdk.catalog.data_source.action_model.sql_column import SqlColumn + from gooddata_sdk.catalog.data_source.declarative_model.data_source import ( + CatalogDeclarativeDataSource, + CatalogDeclarativeDataSources, + ) + from gooddata_sdk.catalog.data_source.declarative_model.physical_model.pdm import CatalogDeclarativeTables + from gooddata_sdk.catalog.data_source.declarative_model.physical_model.table import ( + CatalogDeclarativeColumn, + CatalogDeclarativeTable, + ) + from gooddata_sdk.catalog.data_source.entity_model.data_source import ( + CatalogDataSource, + CatalogDataSourceBigQuery, + CatalogDataSourceDatabricks, + CatalogDataSourceGdStorage, + CatalogDataSourceMariaDb, + CatalogDataSourceMotherDuck, + CatalogDataSourceMsSql, + CatalogDataSourceMySql, + CatalogDataSourcePostgres, + CatalogDataSourceRedshift, + CatalogDataSourceSnowflake, + CatalogDataSourceVertica, + DatabricksAttributes, + MariaDbAttributes, + MotherDuckAttributes, + MsSqlAttributes, + MySqlAttributes, + PostgresAttributes, + RedshiftAttributes, + SnowflakeAttributes, + VerticaAttributes, + ) + from gooddata_sdk.catalog.data_source.service import CatalogDataSourceService + from gooddata_sdk.catalog.data_source.validation.data_source import DataSourceValidator + from gooddata_sdk.catalog.depends_on import ( + CatalogDependsOn, + CatalogDependsOnDateFilter, + ) + from gooddata_sdk.catalog.entity import ( + AttrCatalogEntity, + BasicCredentials, + ClientSecretCredentials, + KeyPairCredentials, + TokenCredentialsFromEnvVar, + TokenCredentialsFromFile, + ) + from gooddata_sdk.catalog.export.request import ( + ExportCustomLabel, + ExportCustomMetric, + ExportCustomOverride, + ExportRequest, + ExportSettings, + GrandTotalsPosition, + SlidesExportRequest, + VisualExportRequest, + ) + from gooddata_sdk.catalog.filter_by import CatalogFilterBy + from gooddata_sdk.catalog.identifier import ( + CatalogAssigneeIdentifier, + CatalogDatasetWorkspaceDataFilterIdentifier, + CatalogDeclarativeAnalyticalDashboardIdentifier, + CatalogExportDefinitionIdentifier, + CatalogNotificationChannelIdentifier, + CatalogUserIdentifier, + CatalogWorkspaceIdentifier, + ) + from gooddata_sdk.catalog.organization.common.dashboard_slides_template import CatalogDashboardSlidesTemplate + from gooddata_sdk.catalog.organization.common.running_section import CatalogRunningSection + from gooddata_sdk.catalog.organization.common.slide_template import ( + CatalogContentSlideTemplate, + CatalogCoverSlideTemplate, + CatalogIntroSlideTemplate, + CatalogSectionSlideTemplate, + ) + from gooddata_sdk.catalog.organization.common.widget_slides_template import CatalogWidgetSlidesTemplate + from gooddata_sdk.catalog.organization.entity_model.directive import CatalogCspDirective + from gooddata_sdk.catalog.organization.entity_model.export_template import ( + CatalogExportTemplate, + CatalogExportTemplateAttributes, + ) + from gooddata_sdk.catalog.organization.entity_model.ip_allowlist_policy import ( + CatalogIpAllowlistPolicy, + CatalogIpAllowlistPolicyTargets, + ) + from gooddata_sdk.catalog.organization.entity_model.jwk import ( + CatalogJwk, + CatalogJwkAttributes, + CatalogJwkDocument, + CatalogRsaSpecification, + ) + from gooddata_sdk.catalog.organization.entity_model.llm_provider import ( + CatalogAwsBedrockProviderConfig, + CatalogAzureFoundryApiKeyAuth, + CatalogAzureFoundryProviderConfig, + CatalogBedrockAccessKeyAuth, + CatalogLlmProvider, + CatalogLlmProviderDocument, + CatalogLlmProviderModel, + CatalogLlmProviderModelsResult, + CatalogLlmProviderPatch, + CatalogLlmProviderPatchDocument, + CatalogLlmProviderTestResult, + CatalogModelTestResult, + CatalogOpenAiApiKeyAuth, + CatalogOpenAiProviderConfig, + ) + from gooddata_sdk.catalog.organization.entity_model.organization import CatalogOrganization + from gooddata_sdk.catalog.organization.entity_model.setting import CatalogOrganizationSetting + from gooddata_sdk.catalog.organization.layout.export_template import CatalogDeclarativeExportTemplate + from gooddata_sdk.catalog.organization.layout.notification_channel import ( + CatalogDeclarativeNotificationChannel, + CatalogDefaultSmtp, + CatalogInPlatform, + CatalogNotificationChannelDestination, + CatalogSmtp, + CatalogWebhook, + ) + from gooddata_sdk.catalog.organization.service import ( + HLL_TYPE_SETTING_ID, + HLL_TYPE_SETTING_TYPE, + CatalogOrganizationService, + HLLType, + ) + from gooddata_sdk.catalog.permission.declarative_model.dashboard_assignees import ( + CatalogAvailableAssignees, + CatalogUserAssignee, + CatalogUserGroupAssignee, + ) + from gooddata_sdk.catalog.permission.declarative_model.dashboard_permissions import ( + CatalogDashboardPermissions, + CatalogGrantedPermission, + CatalogUserGroupPermission, + CatalogUserPermission, + ) + from gooddata_sdk.catalog.permission.declarative_model.manage_dashboard_permissions import ( + CatalogDashboardAssigneeIdentifier, + CatalogPermissionsForAssigneeIdentifier, + CatalogPermissionsForAssigneeRule, + ) + from gooddata_sdk.catalog.permission.declarative_model.permission import ( + CatalogDeclarativeDashboardPermissionsForAssignee, + CatalogDeclarativeDashboardPermissionsForAssigneeRule, + CatalogDeclarativeDataSourcePermission, + CatalogDeclarativeOrganizationPermission, + CatalogDeclarativeSingleWorkspacePermission, + CatalogDeclarativeWorkspaceHierarchyPermission, + CatalogDeclarativeWorkspacePermissions, + CatalogOrganizationPermissionAssignment, + ) + from gooddata_sdk.catalog.rule import CatalogAssigneeRule + from gooddata_sdk.catalog.types import UpsertOutcome + from gooddata_sdk.catalog.user.declarative_model.user import ( + CatalogDeclarativeUser, + CatalogDeclarativeUserPermission, + CatalogDeclarativeUsers, + ) + from gooddata_sdk.catalog.user.declarative_model.user_and_user_groups import CatalogDeclarativeUsersUserGroups + from gooddata_sdk.catalog.user.declarative_model.user_group import ( + CatalogDeclarativeUserGroup, + CatalogDeclarativeUserGroupPermission, + CatalogDeclarativeUserGroups, + ) + from gooddata_sdk.catalog.user.entity_model.user import CatalogUser + from gooddata_sdk.catalog.user.entity_model.user_group import CatalogUserGroup + from gooddata_sdk.catalog.user.management_model.management import ( + CatalogDataSourcePermissionAssignment, + CatalogPermissionAssignments, + CatalogPermissionsAssignment, + CatalogWorkspacePermissionAssignment, + ) + from gooddata_sdk.catalog.validate_by_item import CatalogValidateByItem + from gooddata_sdk.catalog.workspace.aac import ( + aac_attribute_hierarchy_to_declarative, + aac_dashboard_to_declarative, + aac_dataset_to_declarative, + aac_date_dataset_to_declarative, + aac_metric_to_declarative, + aac_plugin_to_declarative, + aac_visualization_to_declarative, + declarative_attribute_hierarchy_to_aac, + declarative_dashboard_to_aac, + declarative_dataset_to_aac, + declarative_date_instance_to_aac, + declarative_metric_to_aac, + declarative_plugin_to_aac, + declarative_visualization_to_aac, + detect_yaml_format, + load_aac_workspace_from_disk, + store_aac_workspace_to_disk, + ) + from gooddata_sdk.catalog.workspace.content_service import ( + CatalogWorkspaceContent, + CatalogWorkspaceContentService, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.analytics_model import ( + CatalogDeclarativeAnalytics, + CatalogDeclarativeMemoryItem, + CatalogDeclarativeMetric, + CatalogDeclarativeParameter, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.export_definition import ( + CatalogDeclarativeExportDefinition, + CatalogDeclarativeExportDefinitionRequestPayload, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.automation import ( + CatalogAutomationSchedule, + CatalogDeclarativeAutomation, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.data_filter_references import ( + CatalogDeclarativeWorkspaceDataFilterReferences, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset import ( + CatalogDataSourceTableIdentifier, + CatalogDeclarativeAggregatedFact, + CatalogDeclarativeAttribute, + CatalogDeclarativeDataset, + CatalogDeclarativeDatasetSql, + CatalogDeclarativeFact, + CatalogDeclarativeLabel, + CatalogDeclarativeReference, + CatalogDeclarativeWorkspaceDataFilterColumn, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset_extensions.dataset_extension import ( + CatalogDeclarativeDatasetExtension, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.date_dataset.date_dataset import ( + CatalogDeclarativeDateDataset, + CatalogGranularitiesFormatting, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.ldm import ( + CatalogDeclarativeLdm, + CatalogDeclarativeModel, + ) + from gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace import ( + CatalogDeclarativeFilterView, + CatalogDeclarativeUserDataFilter, + CatalogDeclarativeUserDataFilters, + CatalogDeclarativeWorkspace, + CatalogDeclarativeWorkspaceDataFilter, + CatalogDeclarativeWorkspaceDataFilters, + CatalogDeclarativeWorkspaceDataFilterSetting, + CatalogDeclarativeWorkspaceModel, + CatalogDeclarativeWorkspaces, + ) + from gooddata_sdk.catalog.workspace.entity_model.content_objects.dataset import ( + CatalogAttribute, + CatalogDataset, + CatalogFact, + CatalogLabel, + ) + from gooddata_sdk.catalog.workspace.entity_model.content_objects.metric import CatalogMetric + from gooddata_sdk.catalog.workspace.entity_model.content_objects.workspace_setting import CatalogWorkspaceSetting + from gooddata_sdk.catalog.workspace.entity_model.graph_objects.graph import ( + CatalogDependentEntitiesGraph, + CatalogDependentEntitiesNode, + CatalogDependentEntitiesRequest, + CatalogDependentEntitiesResponse, + CatalogEntityIdentifier, + ) + from gooddata_sdk.catalog.workspace.entity_model.user_data_filter import ( + CatalogUserDataFilter, + CatalogUserDataFilterAttributes, + CatalogUserDataFilterRelationships, + ) + from gooddata_sdk.catalog.workspace.entity_model.workspace import CatalogWorkspace + from gooddata_sdk.client import ( + GoodDataApiClient, + GoodDataApiClientRetryConfig, + ) + from gooddata_sdk.compute.compute_to_sdk_converter import ComputeToSdkConverter + from gooddata_sdk.compute.model.attribute import Attribute + from gooddata_sdk.compute.model.base import ( + ExecModelEntity, + ObjId, + ) + from gooddata_sdk.compute.model.execution import ( + BareExecutionResponse, + Execution, + ExecutionDefinition, + ExecutionResponse, + ExecutionResult, + ResultCacheMetadata, + ResultSizeBytesLimitExceeded, + ResultSizeDimensions, + ResultSizeDimensionsLimitsExceeded, + TableDimension, + TotalDefinition, + TotalDimension, + ) + from gooddata_sdk.compute.model.filter import ( + AbsoluteDateFilter, + AllMetricValueFilter, + AllTimeDateFilter, + AttributeFilter, + BoundedFilter, + CompoundMetricValueFilter, + Filter, + InlineFilter, + MatchAttributeFilter, + MetricValueComparisonCondition, + MetricValueFilter, + MetricValueRangeCondition, + NegativeAttributeFilter, + PositiveAttributeFilter, + RankingFilter, + RelativeDateFilter, + ) + from gooddata_sdk.compute.model.metric import ( + ArithmeticMetric, + InlineMetric, + Metric, + PopDate, + PopDateDataset, + PopDateMetric, + PopDatesetMetric, + SimpleMetric, + ) + from gooddata_sdk.compute.service import ComputeService + from gooddata_sdk.sdk import GoodDataSdk + from gooddata_sdk.table import ( + ExecutionTable, + TableService, + ) + from gooddata_sdk.utils import SideLoads + from gooddata_sdk.visualization import ( + Visualization, + VisualizationAttribute, + VisualizationBucket, + VisualizationFilter, + VisualizationMetric, + VisualizationService, + ) + +# --- begin generated by scripts/sync_lazy_imports.py --- +# Public name -> module that defines it, generated from the ``TYPE_CHECKING`` block above. +# Importing all of these at module level pulls in the whole SDK (every catalog service, +# declarative model and generated API model) even when the caller wants a single class, so they +# are resolved on first access instead (PEP 562). Do not edit by hand -- see the script. +_LAZY_IMPORTS: dict[str, str] = { + "AbsoluteDateFilter": "gooddata_sdk.compute.model.filter", + "AllMetricValueFilter": "gooddata_sdk.compute.model.filter", + "AllTimeDateFilter": "gooddata_sdk.compute.model.filter", + "ArithmeticMetric": "gooddata_sdk.compute.model.metric", + "AttrCatalogEntity": "gooddata_sdk.catalog.entity", + "Attribute": "gooddata_sdk.compute.model.attribute", + "AttributeFilter": "gooddata_sdk.compute.model.filter", + "BareExecutionResponse": "gooddata_sdk.compute.model.execution", + "BasicCredentials": "gooddata_sdk.catalog.entity", + "BoundedFilter": "gooddata_sdk.compute.model.filter", + "CatalogAILakeOperation": "gooddata_sdk.catalog.ai_lake.service", + "CatalogAILakeOperationError": "gooddata_sdk.catalog.ai_lake.service", + "CatalogAILakeService": "gooddata_sdk.catalog.ai_lake.service", + "CatalogAppearanceService": "gooddata_sdk.catalog.appearance.service", + "CatalogAssigneeIdentifier": "gooddata_sdk.catalog.identifier", + "CatalogAssigneeRule": "gooddata_sdk.catalog.rule", + "CatalogAttribute": "gooddata_sdk.catalog.workspace.entity_model.content_objects.dataset", + "CatalogAutomationSchedule": "gooddata_sdk.catalog.workspace.declarative_model.workspace.automation", + "CatalogAvailableAssignees": "gooddata_sdk.catalog.permission.declarative_model.dashboard_assignees", + "CatalogAwsBedrockProviderConfig": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogAzureFoundryApiKeyAuth": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogAzureFoundryProviderConfig": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogBedrockAccessKeyAuth": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogColorPalette": "gooddata_sdk.catalog.appearance.entity_model.color_palette", + "CatalogColorPaletteAttributes": "gooddata_sdk.catalog.appearance.entity_model.color_palette", + "CatalogContentSlideTemplate": "gooddata_sdk.catalog.organization.common.slide_template", + "CatalogCoverSlideTemplate": "gooddata_sdk.catalog.organization.common.slide_template", + "CatalogCspDirective": "gooddata_sdk.catalog.organization.entity_model.directive", + "CatalogDashboardAssigneeIdentifier": "gooddata_sdk.catalog.permission.declarative_model.manage_dashboard_permissions", + "CatalogDashboardPermissions": "gooddata_sdk.catalog.permission.declarative_model.dashboard_permissions", + "CatalogDashboardSlidesTemplate": "gooddata_sdk.catalog.organization.common.dashboard_slides_template", + "CatalogDataSource": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceBigQuery": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceDatabricks": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceGdStorage": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceMariaDb": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceMotherDuck": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceMsSql": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceMySql": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourcePermissionAssignment": "gooddata_sdk.catalog.user.management_model.management", + "CatalogDataSourcePostgres": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceRedshift": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceService": "gooddata_sdk.catalog.data_source.service", + "CatalogDataSourceSnowflake": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataSourceTableIdentifier": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDataSourceVertica": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "CatalogDataset": "gooddata_sdk.catalog.workspace.entity_model.content_objects.dataset", + "CatalogDatasetWorkspaceDataFilterIdentifier": "gooddata_sdk.catalog.identifier", + "CatalogDeclarativeAggregatedFact": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDeclarativeAnalyticalDashboardIdentifier": "gooddata_sdk.catalog.identifier", + "CatalogDeclarativeAnalytics": "gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.analytics_model", + "CatalogDeclarativeAttribute": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDeclarativeAutomation": "gooddata_sdk.catalog.workspace.declarative_model.workspace.automation", + "CatalogDeclarativeColumn": "gooddata_sdk.catalog.data_source.declarative_model.physical_model.table", + "CatalogDeclarativeDashboardPermissionsForAssignee": "gooddata_sdk.catalog.permission.declarative_model.permission", + "CatalogDeclarativeDashboardPermissionsForAssigneeRule": "gooddata_sdk.catalog.permission.declarative_model.permission", + "CatalogDeclarativeDataSource": "gooddata_sdk.catalog.data_source.declarative_model.data_source", + "CatalogDeclarativeDataSourcePermission": "gooddata_sdk.catalog.permission.declarative_model.permission", + "CatalogDeclarativeDataSources": "gooddata_sdk.catalog.data_source.declarative_model.data_source", + "CatalogDeclarativeDataset": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDeclarativeDatasetExtension": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset_extensions.dataset_extension", + "CatalogDeclarativeDatasetSql": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDeclarativeDateDataset": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.date_dataset.date_dataset", + "CatalogDeclarativeExportDefinition": "gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.export_definition", + "CatalogDeclarativeExportDefinitionRequestPayload": "gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.export_definition", + "CatalogDeclarativeExportTemplate": "gooddata_sdk.catalog.organization.layout.export_template", + "CatalogDeclarativeFact": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDeclarativeFilterView": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDeclarativeLabel": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDeclarativeLdm": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.ldm", + "CatalogDeclarativeMemoryItem": "gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.analytics_model", + "CatalogDeclarativeMetric": "gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.analytics_model", + "CatalogDeclarativeModel": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.ldm", + "CatalogDeclarativeNotificationChannel": "gooddata_sdk.catalog.organization.layout.notification_channel", + "CatalogDeclarativeOrganizationPermission": "gooddata_sdk.catalog.permission.declarative_model.permission", + "CatalogDeclarativeParameter": "gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.analytics_model", + "CatalogDeclarativeReference": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDeclarativeSingleWorkspacePermission": "gooddata_sdk.catalog.permission.declarative_model.permission", + "CatalogDeclarativeTable": "gooddata_sdk.catalog.data_source.declarative_model.physical_model.table", + "CatalogDeclarativeTables": "gooddata_sdk.catalog.data_source.declarative_model.physical_model.pdm", + "CatalogDeclarativeUser": "gooddata_sdk.catalog.user.declarative_model.user", + "CatalogDeclarativeUserDataFilter": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDeclarativeUserDataFilters": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDeclarativeUserGroup": "gooddata_sdk.catalog.user.declarative_model.user_group", + "CatalogDeclarativeUserGroupPermission": "gooddata_sdk.catalog.user.declarative_model.user_group", + "CatalogDeclarativeUserGroups": "gooddata_sdk.catalog.user.declarative_model.user_group", + "CatalogDeclarativeUserPermission": "gooddata_sdk.catalog.user.declarative_model.user", + "CatalogDeclarativeUsers": "gooddata_sdk.catalog.user.declarative_model.user", + "CatalogDeclarativeUsersUserGroups": "gooddata_sdk.catalog.user.declarative_model.user_and_user_groups", + "CatalogDeclarativeWorkspace": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDeclarativeWorkspaceDataFilter": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDeclarativeWorkspaceDataFilterColumn": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.dataset.dataset", + "CatalogDeclarativeWorkspaceDataFilterReferences": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.data_filter_references", + "CatalogDeclarativeWorkspaceDataFilterSetting": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDeclarativeWorkspaceDataFilters": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDeclarativeWorkspaceHierarchyPermission": "gooddata_sdk.catalog.permission.declarative_model.permission", + "CatalogDeclarativeWorkspaceModel": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDeclarativeWorkspacePermissions": "gooddata_sdk.catalog.permission.declarative_model.permission", + "CatalogDeclarativeWorkspaces": "gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace", + "CatalogDefaultSmtp": "gooddata_sdk.catalog.organization.layout.notification_channel", + "CatalogDependentEntitiesGraph": "gooddata_sdk.catalog.workspace.entity_model.graph_objects.graph", + "CatalogDependentEntitiesNode": "gooddata_sdk.catalog.workspace.entity_model.graph_objects.graph", + "CatalogDependentEntitiesRequest": "gooddata_sdk.catalog.workspace.entity_model.graph_objects.graph", + "CatalogDependentEntitiesResponse": "gooddata_sdk.catalog.workspace.entity_model.graph_objects.graph", + "CatalogDependsOn": "gooddata_sdk.catalog.depends_on", + "CatalogDependsOnDateFilter": "gooddata_sdk.catalog.depends_on", + "CatalogEntityIdentifier": "gooddata_sdk.catalog.workspace.entity_model.graph_objects.graph", + "CatalogExportDefinitionIdentifier": "gooddata_sdk.catalog.identifier", + "CatalogExportTemplate": "gooddata_sdk.catalog.organization.entity_model.export_template", + "CatalogExportTemplateAttributes": "gooddata_sdk.catalog.organization.entity_model.export_template", + "CatalogFact": "gooddata_sdk.catalog.workspace.entity_model.content_objects.dataset", + "CatalogFilterBy": "gooddata_sdk.catalog.filter_by", + "CatalogGenerateLdmRequest": "gooddata_sdk.catalog.data_source.action_model.requests.ldm_request", + "CatalogGrantedPermission": "gooddata_sdk.catalog.permission.declarative_model.dashboard_permissions", + "CatalogGranularitiesFormatting": "gooddata_sdk.catalog.workspace.declarative_model.workspace.logical_model.date_dataset.date_dataset", + "CatalogInPlatform": "gooddata_sdk.catalog.organization.layout.notification_channel", + "CatalogIntroSlideTemplate": "gooddata_sdk.catalog.organization.common.slide_template", + "CatalogIpAllowlistPolicy": "gooddata_sdk.catalog.organization.entity_model.ip_allowlist_policy", + "CatalogIpAllowlistPolicyTargets": "gooddata_sdk.catalog.organization.entity_model.ip_allowlist_policy", + "CatalogJwk": "gooddata_sdk.catalog.organization.entity_model.jwk", + "CatalogJwkAttributes": "gooddata_sdk.catalog.organization.entity_model.jwk", + "CatalogJwkDocument": "gooddata_sdk.catalog.organization.entity_model.jwk", + "CatalogLabel": "gooddata_sdk.catalog.workspace.entity_model.content_objects.dataset", + "CatalogLlmProvider": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogLlmProviderDocument": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogLlmProviderModel": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogLlmProviderModelsResult": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogLlmProviderPatch": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogLlmProviderPatchDocument": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogLlmProviderTestResult": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogMetric": "gooddata_sdk.catalog.workspace.entity_model.content_objects.metric", + "CatalogModelTestResult": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogNotificationChannelDestination": "gooddata_sdk.catalog.organization.layout.notification_channel", + "CatalogNotificationChannelIdentifier": "gooddata_sdk.catalog.identifier", + "CatalogOpenAiApiKeyAuth": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogOpenAiProviderConfig": "gooddata_sdk.catalog.organization.entity_model.llm_provider", + "CatalogOrganization": "gooddata_sdk.catalog.organization.entity_model.organization", + "CatalogOrganizationPermissionAssignment": "gooddata_sdk.catalog.permission.declarative_model.permission", + "CatalogOrganizationService": "gooddata_sdk.catalog.organization.service", + "CatalogOrganizationSetting": "gooddata_sdk.catalog.organization.entity_model.setting", + "CatalogPdmLdmRequest": "gooddata_sdk.catalog.data_source.action_model.requests.ldm_request", + "CatalogPdmSql": "gooddata_sdk.catalog.data_source.action_model.requests.ldm_request", + "CatalogPermissionAssignments": "gooddata_sdk.catalog.user.management_model.management", + "CatalogPermissionsAssignment": "gooddata_sdk.catalog.user.management_model.management", + "CatalogPermissionsForAssigneeIdentifier": "gooddata_sdk.catalog.permission.declarative_model.manage_dashboard_permissions", + "CatalogPermissionsForAssigneeRule": "gooddata_sdk.catalog.permission.declarative_model.manage_dashboard_permissions", + "CatalogRsaSpecification": "gooddata_sdk.catalog.organization.entity_model.jwk", + "CatalogRunningSection": "gooddata_sdk.catalog.organization.common.running_section", + "CatalogScanModelRequest": "gooddata_sdk.catalog.data_source.action_model.requests.scan_model_request", + "CatalogSectionSlideTemplate": "gooddata_sdk.catalog.organization.common.slide_template", + "CatalogSmtp": "gooddata_sdk.catalog.organization.layout.notification_channel", + "CatalogTheme": "gooddata_sdk.catalog.appearance.entity_model.theme", + "CatalogThemeAttributes": "gooddata_sdk.catalog.appearance.entity_model.theme", + "CatalogUser": "gooddata_sdk.catalog.user.entity_model.user", + "CatalogUserAssignee": "gooddata_sdk.catalog.permission.declarative_model.dashboard_assignees", + "CatalogUserDataFilter": "gooddata_sdk.catalog.workspace.entity_model.user_data_filter", + "CatalogUserDataFilterAttributes": "gooddata_sdk.catalog.workspace.entity_model.user_data_filter", + "CatalogUserDataFilterRelationships": "gooddata_sdk.catalog.workspace.entity_model.user_data_filter", + "CatalogUserGroup": "gooddata_sdk.catalog.user.entity_model.user_group", + "CatalogUserGroupAssignee": "gooddata_sdk.catalog.permission.declarative_model.dashboard_assignees", + "CatalogUserGroupPermission": "gooddata_sdk.catalog.permission.declarative_model.dashboard_permissions", + "CatalogUserIdentifier": "gooddata_sdk.catalog.identifier", + "CatalogUserPermission": "gooddata_sdk.catalog.permission.declarative_model.dashboard_permissions", + "CatalogValidateByItem": "gooddata_sdk.catalog.validate_by_item", + "CatalogWebhook": "gooddata_sdk.catalog.organization.layout.notification_channel", + "CatalogWidgetSlidesTemplate": "gooddata_sdk.catalog.organization.common.widget_slides_template", + "CatalogWorkspace": "gooddata_sdk.catalog.workspace.entity_model.workspace", + "CatalogWorkspaceContent": "gooddata_sdk.catalog.workspace.content_service", + "CatalogWorkspaceContentService": "gooddata_sdk.catalog.workspace.content_service", + "CatalogWorkspaceIdentifier": "gooddata_sdk.catalog.identifier", + "CatalogWorkspacePermissionAssignment": "gooddata_sdk.catalog.user.management_model.management", + "CatalogWorkspaceSetting": "gooddata_sdk.catalog.workspace.entity_model.content_objects.workspace_setting", + "ClientSecretCredentials": "gooddata_sdk.catalog.entity", + "CompoundMetricValueFilter": "gooddata_sdk.compute.model.filter", + "ComputeService": "gooddata_sdk.compute.service", + "ComputeToSdkConverter": "gooddata_sdk.compute.compute_to_sdk_converter", + "DataSourceValidator": "gooddata_sdk.catalog.data_source.validation.data_source", + "DatabricksAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "ExecModelEntity": "gooddata_sdk.compute.model.base", + "Execution": "gooddata_sdk.compute.model.execution", + "ExecutionDefinition": "gooddata_sdk.compute.model.execution", + "ExecutionResponse": "gooddata_sdk.compute.model.execution", + "ExecutionResult": "gooddata_sdk.compute.model.execution", + "ExecutionTable": "gooddata_sdk.table", + "ExportCustomLabel": "gooddata_sdk.catalog.export.request", + "ExportCustomMetric": "gooddata_sdk.catalog.export.request", + "ExportCustomOverride": "gooddata_sdk.catalog.export.request", + "ExportRequest": "gooddata_sdk.catalog.export.request", + "ExportSettings": "gooddata_sdk.catalog.export.request", + "Filter": "gooddata_sdk.compute.model.filter", + "GoodDataApiClient": "gooddata_sdk.client", + "GoodDataApiClientRetryConfig": "gooddata_sdk.client", + "GoodDataSdk": "gooddata_sdk.sdk", + "GrandTotalsPosition": "gooddata_sdk.catalog.export.request", + "HLLType": "gooddata_sdk.catalog.organization.service", + "HLL_TYPE_SETTING_ID": "gooddata_sdk.catalog.organization.service", + "HLL_TYPE_SETTING_TYPE": "gooddata_sdk.catalog.organization.service", + "InlineFilter": "gooddata_sdk.compute.model.filter", + "InlineMetric": "gooddata_sdk.compute.model.metric", + "KeyPairCredentials": "gooddata_sdk.catalog.entity", + "MariaDbAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "MatchAttributeFilter": "gooddata_sdk.compute.model.filter", + "Metric": "gooddata_sdk.compute.model.metric", + "MetricValueComparisonCondition": "gooddata_sdk.compute.model.filter", + "MetricValueFilter": "gooddata_sdk.compute.model.filter", + "MetricValueRangeCondition": "gooddata_sdk.compute.model.filter", + "MotherDuckAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "MsSqlAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "MySqlAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "NegativeAttributeFilter": "gooddata_sdk.compute.model.filter", + "ObjId": "gooddata_sdk.compute.model.base", + "PopDate": "gooddata_sdk.compute.model.metric", + "PopDateDataset": "gooddata_sdk.compute.model.metric", + "PopDateMetric": "gooddata_sdk.compute.model.metric", + "PopDatesetMetric": "gooddata_sdk.compute.model.metric", + "PositiveAttributeFilter": "gooddata_sdk.compute.model.filter", + "PostgresAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "RankingFilter": "gooddata_sdk.compute.model.filter", + "RedshiftAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "RelativeDateFilter": "gooddata_sdk.compute.model.filter", + "ResultCacheMetadata": "gooddata_sdk.compute.model.execution", + "ResultSizeBytesLimitExceeded": "gooddata_sdk.compute.model.execution", + "ResultSizeDimensions": "gooddata_sdk.compute.model.execution", + "ResultSizeDimensionsLimitsExceeded": "gooddata_sdk.compute.model.execution", + "ScanSqlRequest": "gooddata_sdk.catalog.data_source.action_model.requests.scan_sql_request", + "ScanSqlResponse": "gooddata_sdk.catalog.data_source.action_model.responses.scan_sql_response", + "SideLoads": "gooddata_sdk.utils", + "SimpleMetric": "gooddata_sdk.compute.model.metric", + "SlidesExportRequest": "gooddata_sdk.catalog.export.request", + "SnowflakeAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "SqlColumn": "gooddata_sdk.catalog.data_source.action_model.sql_column", + "TableDimension": "gooddata_sdk.compute.model.execution", + "TableService": "gooddata_sdk.table", + "TokenCredentialsFromEnvVar": "gooddata_sdk.catalog.entity", + "TokenCredentialsFromFile": "gooddata_sdk.catalog.entity", + "TotalDefinition": "gooddata_sdk.compute.model.execution", + "TotalDimension": "gooddata_sdk.compute.model.execution", + "UpsertOutcome": "gooddata_sdk.catalog.types", + "VerticaAttributes": "gooddata_sdk.catalog.data_source.entity_model.data_source", + "VisualExportRequest": "gooddata_sdk.catalog.export.request", + "Visualization": "gooddata_sdk.visualization", + "VisualizationAttribute": "gooddata_sdk.visualization", + "VisualizationBucket": "gooddata_sdk.visualization", + "VisualizationFilter": "gooddata_sdk.visualization", + "VisualizationMetric": "gooddata_sdk.visualization", + "VisualizationService": "gooddata_sdk.visualization", + "aac_attribute_hierarchy_to_declarative": "gooddata_sdk.catalog.workspace.aac", + "aac_dashboard_to_declarative": "gooddata_sdk.catalog.workspace.aac", + "aac_dataset_to_declarative": "gooddata_sdk.catalog.workspace.aac", + "aac_date_dataset_to_declarative": "gooddata_sdk.catalog.workspace.aac", + "aac_metric_to_declarative": "gooddata_sdk.catalog.workspace.aac", + "aac_plugin_to_declarative": "gooddata_sdk.catalog.workspace.aac", + "aac_visualization_to_declarative": "gooddata_sdk.catalog.workspace.aac", + "declarative_attribute_hierarchy_to_aac": "gooddata_sdk.catalog.workspace.aac", + "declarative_dashboard_to_aac": "gooddata_sdk.catalog.workspace.aac", + "declarative_dataset_to_aac": "gooddata_sdk.catalog.workspace.aac", + "declarative_date_instance_to_aac": "gooddata_sdk.catalog.workspace.aac", + "declarative_metric_to_aac": "gooddata_sdk.catalog.workspace.aac", + "declarative_plugin_to_aac": "gooddata_sdk.catalog.workspace.aac", + "declarative_visualization_to_aac": "gooddata_sdk.catalog.workspace.aac", + "detect_yaml_format": "gooddata_sdk.catalog.workspace.aac", + "load_aac_workspace_from_disk": "gooddata_sdk.catalog.workspace.aac", + "store_aac_workspace_to_disk": "gooddata_sdk.catalog.workspace.aac", +} + +__all__ = [ + "__version__", + "AbsoluteDateFilter", + "AllMetricValueFilter", + "AllTimeDateFilter", + "ArithmeticMetric", + "AttrCatalogEntity", + "Attribute", + "AttributeFilter", + "BareExecutionResponse", + "BasicCredentials", + "BoundedFilter", + "CatalogAILakeOperation", + "CatalogAILakeOperationError", + "CatalogAILakeService", + "CatalogAppearanceService", + "CatalogAssigneeIdentifier", + "CatalogAssigneeRule", + "CatalogAttribute", + "CatalogAutomationSchedule", + "CatalogAvailableAssignees", + "CatalogAwsBedrockProviderConfig", + "CatalogAzureFoundryApiKeyAuth", + "CatalogAzureFoundryProviderConfig", + "CatalogBedrockAccessKeyAuth", + "CatalogColorPalette", + "CatalogColorPaletteAttributes", + "CatalogContentSlideTemplate", + "CatalogCoverSlideTemplate", + "CatalogCspDirective", + "CatalogDashboardAssigneeIdentifier", + "CatalogDashboardPermissions", + "CatalogDashboardSlidesTemplate", + "CatalogDataSource", + "CatalogDataSourceBigQuery", + "CatalogDataSourceDatabricks", + "CatalogDataSourceGdStorage", + "CatalogDataSourceMariaDb", + "CatalogDataSourceMotherDuck", + "CatalogDataSourceMsSql", + "CatalogDataSourceMySql", + "CatalogDataSourcePermissionAssignment", + "CatalogDataSourcePostgres", + "CatalogDataSourceRedshift", + "CatalogDataSourceService", + "CatalogDataSourceSnowflake", + "CatalogDataSourceTableIdentifier", + "CatalogDataSourceVertica", + "CatalogDataset", + "CatalogDatasetWorkspaceDataFilterIdentifier", + "CatalogDeclarativeAggregatedFact", + "CatalogDeclarativeAnalyticalDashboardIdentifier", + "CatalogDeclarativeAnalytics", + "CatalogDeclarativeAttribute", + "CatalogDeclarativeAutomation", + "CatalogDeclarativeColumn", + "CatalogDeclarativeDashboardPermissionsForAssignee", + "CatalogDeclarativeDashboardPermissionsForAssigneeRule", + "CatalogDeclarativeDataSource", + "CatalogDeclarativeDataSourcePermission", + "CatalogDeclarativeDataSources", + "CatalogDeclarativeDataset", + "CatalogDeclarativeDatasetExtension", + "CatalogDeclarativeDatasetSql", + "CatalogDeclarativeDateDataset", + "CatalogDeclarativeExportDefinition", + "CatalogDeclarativeExportDefinitionRequestPayload", + "CatalogDeclarativeExportTemplate", + "CatalogDeclarativeFact", + "CatalogDeclarativeFilterView", + "CatalogDeclarativeLabel", + "CatalogDeclarativeLdm", + "CatalogDeclarativeMemoryItem", + "CatalogDeclarativeMetric", + "CatalogDeclarativeModel", + "CatalogDeclarativeNotificationChannel", + "CatalogDeclarativeOrganizationPermission", + "CatalogDeclarativeParameter", + "CatalogDeclarativeReference", + "CatalogDeclarativeSingleWorkspacePermission", + "CatalogDeclarativeTable", + "CatalogDeclarativeTables", + "CatalogDeclarativeUser", + "CatalogDeclarativeUserDataFilter", + "CatalogDeclarativeUserDataFilters", + "CatalogDeclarativeUserGroup", + "CatalogDeclarativeUserGroupPermission", + "CatalogDeclarativeUserGroups", + "CatalogDeclarativeUserPermission", + "CatalogDeclarativeUsers", + "CatalogDeclarativeUsersUserGroups", + "CatalogDeclarativeWorkspace", + "CatalogDeclarativeWorkspaceDataFilter", + "CatalogDeclarativeWorkspaceDataFilterColumn", + "CatalogDeclarativeWorkspaceDataFilterReferences", + "CatalogDeclarativeWorkspaceDataFilterSetting", + "CatalogDeclarativeWorkspaceDataFilters", + "CatalogDeclarativeWorkspaceHierarchyPermission", + "CatalogDeclarativeWorkspaceModel", + "CatalogDeclarativeWorkspacePermissions", + "CatalogDeclarativeWorkspaces", + "CatalogDefaultSmtp", + "CatalogDependentEntitiesGraph", + "CatalogDependentEntitiesNode", + "CatalogDependentEntitiesRequest", + "CatalogDependentEntitiesResponse", + "CatalogDependsOn", + "CatalogDependsOnDateFilter", + "CatalogEntityIdentifier", + "CatalogExportDefinitionIdentifier", + "CatalogExportTemplate", + "CatalogExportTemplateAttributes", + "CatalogFact", + "CatalogFilterBy", + "CatalogGenerateLdmRequest", + "CatalogGrantedPermission", + "CatalogGranularitiesFormatting", + "CatalogInPlatform", + "CatalogIntroSlideTemplate", + "CatalogIpAllowlistPolicy", + "CatalogIpAllowlistPolicyTargets", + "CatalogJwk", + "CatalogJwkAttributes", + "CatalogJwkDocument", + "CatalogLabel", + "CatalogLlmProvider", + "CatalogLlmProviderDocument", + "CatalogLlmProviderModel", + "CatalogLlmProviderModelsResult", + "CatalogLlmProviderPatch", + "CatalogLlmProviderPatchDocument", + "CatalogLlmProviderTestResult", + "CatalogMetric", + "CatalogModelTestResult", + "CatalogNotificationChannelDestination", + "CatalogNotificationChannelIdentifier", + "CatalogOpenAiApiKeyAuth", + "CatalogOpenAiProviderConfig", + "CatalogOrganization", + "CatalogOrganizationPermissionAssignment", + "CatalogOrganizationService", + "CatalogOrganizationSetting", + "CatalogPdmLdmRequest", + "CatalogPdmSql", + "CatalogPermissionAssignments", + "CatalogPermissionsAssignment", + "CatalogPermissionsForAssigneeIdentifier", + "CatalogPermissionsForAssigneeRule", + "CatalogRsaSpecification", + "CatalogRunningSection", + "CatalogScanModelRequest", + "CatalogSectionSlideTemplate", + "CatalogSmtp", + "CatalogTheme", + "CatalogThemeAttributes", + "CatalogUser", + "CatalogUserAssignee", + "CatalogUserDataFilter", + "CatalogUserDataFilterAttributes", + "CatalogUserDataFilterRelationships", + "CatalogUserGroup", + "CatalogUserGroupAssignee", + "CatalogUserGroupPermission", + "CatalogUserIdentifier", + "CatalogUserPermission", + "CatalogValidateByItem", + "CatalogWebhook", + "CatalogWidgetSlidesTemplate", + "CatalogWorkspace", + "CatalogWorkspaceContent", + "CatalogWorkspaceContentService", + "CatalogWorkspaceIdentifier", + "CatalogWorkspacePermissionAssignment", + "CatalogWorkspaceSetting", + "ClientSecretCredentials", + "CompoundMetricValueFilter", + "ComputeService", + "ComputeToSdkConverter", + "DataSourceValidator", + "DatabricksAttributes", + "ExecModelEntity", + "Execution", + "ExecutionDefinition", + "ExecutionResponse", + "ExecutionResult", + "ExecutionTable", + "ExportCustomLabel", + "ExportCustomMetric", + "ExportCustomOverride", + "ExportRequest", + "ExportSettings", + "Filter", + "GoodDataApiClient", + "GoodDataApiClientRetryConfig", + "GoodDataSdk", + "GrandTotalsPosition", + "HLLType", + "HLL_TYPE_SETTING_ID", + "HLL_TYPE_SETTING_TYPE", + "InlineFilter", + "InlineMetric", + "KeyPairCredentials", + "MariaDbAttributes", + "MatchAttributeFilter", + "Metric", + "MetricValueComparisonCondition", + "MetricValueFilter", + "MetricValueRangeCondition", + "MotherDuckAttributes", + "MsSqlAttributes", + "MySqlAttributes", + "NegativeAttributeFilter", + "ObjId", + "PopDate", + "PopDateDataset", + "PopDateMetric", + "PopDatesetMetric", + "PositiveAttributeFilter", + "PostgresAttributes", + "RankingFilter", + "RedshiftAttributes", + "RelativeDateFilter", + "ResultCacheMetadata", + "ResultSizeBytesLimitExceeded", + "ResultSizeDimensions", + "ResultSizeDimensionsLimitsExceeded", + "ScanSqlRequest", + "ScanSqlResponse", + "SideLoads", + "SimpleMetric", + "SlidesExportRequest", + "SnowflakeAttributes", + "SqlColumn", + "TableDimension", + "TableService", + "TokenCredentialsFromEnvVar", + "TokenCredentialsFromFile", + "TotalDefinition", + "TotalDimension", + "UpsertOutcome", + "VerticaAttributes", + "VisualExportRequest", + "Visualization", + "VisualizationAttribute", + "VisualizationBucket", + "VisualizationFilter", + "VisualizationMetric", + "VisualizationService", + "aac_attribute_hierarchy_to_declarative", + "aac_dashboard_to_declarative", + "aac_dataset_to_declarative", + "aac_date_dataset_to_declarative", + "aac_metric_to_declarative", + "aac_plugin_to_declarative", + "aac_visualization_to_declarative", + "declarative_attribute_hierarchy_to_aac", + "declarative_dashboard_to_aac", + "declarative_dataset_to_aac", + "declarative_date_instance_to_aac", + "declarative_metric_to_aac", + "declarative_plugin_to_aac", + "declarative_visualization_to_aac", + "detect_yaml_format", + "load_aac_workspace_from_disk", + "store_aac_workspace_to_disk", +] +# --- end generated by scripts/sync_lazy_imports.py --- + + +_submodule_getattr = submodule_getattr(__name__) + + +def __getattr__(name: str) -> Any: + """Resolve a public re-export (or a submodule) on first access.""" + module_name = _LAZY_IMPORTS.get(name) + if module_name is None: + return _submodule_getattr(name) + value = getattr(import_module(module_name), name) + globals()[name] = value + return value + + +def __dir__() -> list[str]: + """List the public API plus the submodules, so REPL completion still finds both.""" + submodules = (info.name for info in pkgutil.iter_modules(__path__) if not info.name.startswith("_")) + return sorted(set(__all__) | set(submodules)) + # by default don't log anything logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/_apis.py b/packages/gooddata-sdk/src/gooddata_sdk/_apis.py new file mode 100644 index 000000000..edc82e77a --- /dev/null +++ b/packages/gooddata-sdk/src/gooddata_sdk/_apis.py @@ -0,0 +1,23 @@ +# (C) 2025 GoodData Corporation +"""Direct imports of the generated API classes used by the SDK. + +``gooddata_api_client.apis`` eagerly imports all ~130 generated API classes, which in turn +pulls in nearly every generated model. The SDK only ever instantiates the six classes +re-exported here, so importing their leaf modules keeps ``import gooddata_sdk`` cheap. +""" + +from gooddata_api_client.api.actions_api import ActionsApi +from gooddata_api_client.api.ai_lake_api import AILakeApi +from gooddata_api_client.api.appearance_api import AppearanceApi +from gooddata_api_client.api.entities_api import EntitiesApi +from gooddata_api_client.api.layout_api import LayoutApi +from gooddata_api_client.api.user_management_api import UserManagementApi + +__all__ = [ + "ActionsApi", + "AILakeApi", + "AppearanceApi", + "EntitiesApi", + "LayoutApi", + "UserManagementApi", +] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/_lazy.py b/packages/gooddata-sdk/src/gooddata_sdk/_lazy.py new file mode 100644 index 000000000..e290d499d --- /dev/null +++ b/packages/gooddata-sdk/src/gooddata_sdk/_lazy.py @@ -0,0 +1,34 @@ +# (C) 2025 GoodData Corporation +"""Helper for exposing subpackage contents as attributes without importing them eagerly.""" + +from collections.abc import Callable +from importlib import import_module +from types import ModuleType + + +def submodule_getattr(package: str) -> Callable[[str], ModuleType]: + """Build a PEP 562 ``__getattr__`` that imports ``.`` on first access. + + The SDK no longer imports its whole module tree at startup, so subpackages are no longer + populated as a side effect of ``import gooddata_sdk``. Without this, attribute access such + as ``gooddata_sdk.catalog.workspace`` would raise ``AttributeError`` unless that submodule + happened to have been imported already by something else. + + Args: + package (str): Dotted name of the package the ``__getattr__`` belongs to (``__name__``). + + Returns: + Callable[[str], ModuleType]: Function to assign to the package's ``__getattr__``. + """ + + def __getattr__(name: str) -> ModuleType: + try: + return import_module(f"{package}.{name}") + except ModuleNotFoundError as e: + # Only translate "this submodule does not exist"; a missing dependency *inside* an + # existing submodule must keep its original error rather than look like a typo. + if e.name != f"{package}.{name}": + raise + raise AttributeError(f"module {package!r} has no attribute {name!r}") from None + + return __getattr__ diff --git a/packages/gooddata-sdk/src/gooddata_sdk/_models.py b/packages/gooddata-sdk/src/gooddata_sdk/_models.py new file mode 100644 index 000000000..52ea7caf0 --- /dev/null +++ b/packages/gooddata-sdk/src/gooddata_sdk/_models.py @@ -0,0 +1,133 @@ +# (C) 2025 GoodData Corporation +"""Direct imports of the generated API models used by the SDK. + +``gooddata_api_client.models`` eagerly imports all ~1400 generated model classes, of which +the SDK uses only the few dozen re-exported here. Importing the leaf modules instead keeps +``import gooddata_sdk`` cheap. Keep this list in sync with the models the SDK references. +""" + +from gooddata_api_client.model.absolute_date_filter import AbsoluteDateFilter +from gooddata_api_client.model.afm import AFM +from gooddata_api_client.model.afm_execution import AfmExecution +from gooddata_api_client.model.afm_execution_response import AfmExecutionResponse +from gooddata_api_client.model.afm_identifier import AfmIdentifier +from gooddata_api_client.model.afm_local_identifier import AfmLocalIdentifier +from gooddata_api_client.model.afm_object_identifier import AfmObjectIdentifier +from gooddata_api_client.model.afm_object_identifier_attribute import AfmObjectIdentifierAttribute +from gooddata_api_client.model.afm_object_identifier_attribute_identifier import AfmObjectIdentifierAttributeIdentifier +from gooddata_api_client.model.afm_object_identifier_dataset import AfmObjectIdentifierDataset +from gooddata_api_client.model.afm_object_identifier_dataset_identifier import AfmObjectIdentifierDatasetIdentifier +from gooddata_api_client.model.afm_object_identifier_identifier import AfmObjectIdentifierIdentifier +from gooddata_api_client.model.afm_object_identifier_label import AfmObjectIdentifierLabel +from gooddata_api_client.model.afm_object_identifier_label_identifier import AfmObjectIdentifierLabelIdentifier +from gooddata_api_client.model.afm_valid_objects_query import AfmValidObjectsQuery +from gooddata_api_client.model.all_time_date_filter import AllTimeDateFilter +from gooddata_api_client.model.arithmetic_measure_definition import ArithmeticMeasureDefinition +from gooddata_api_client.model.arithmetic_measure_definition_arithmetic_measure import ( + ArithmeticMeasureDefinitionArithmeticMeasure, +) +from gooddata_api_client.model.attribute_filter_elements import AttributeFilterElements +from gooddata_api_client.model.attribute_item import AttributeItem +from gooddata_api_client.model.bounded_filter import BoundedFilter +from gooddata_api_client.model.comparison_condition_comparison import ComparisonConditionComparison +from gooddata_api_client.model.comparison_measure_value_filter import ComparisonMeasureValueFilter +from gooddata_api_client.model.compound_measure_value_filter import CompoundMeasureValueFilter +from gooddata_api_client.model.dimension import Dimension +from gooddata_api_client.model.dimension_header import DimensionHeader +from gooddata_api_client.model.execution_response import ExecutionResponse +from gooddata_api_client.model.execution_result import ExecutionResult +from gooddata_api_client.model.execution_result_grand_total import ExecutionResultGrandTotal +from gooddata_api_client.model.execution_result_metadata import ExecutionResultMetadata +from gooddata_api_client.model.execution_result_paging import ExecutionResultPaging +from gooddata_api_client.model.inline_filter_definition import InlineFilterDefinition +from gooddata_api_client.model.inline_measure_definition import InlineMeasureDefinition +from gooddata_api_client.model.inline_measure_definition_inline import InlineMeasureDefinitionInline +from gooddata_api_client.model.match_attribute_filter import MatchAttributeFilter +from gooddata_api_client.model.measure_item import MeasureItem +from gooddata_api_client.model.measure_value_condition import MeasureValueCondition +from gooddata_api_client.model.negative_attribute_filter import NegativeAttributeFilter +from gooddata_api_client.model.pop_dataset import PopDataset +from gooddata_api_client.model.pop_dataset_measure_definition import PopDatasetMeasureDefinition +from gooddata_api_client.model.pop_dataset_measure_definition_previous_period_measure import ( + PopDatasetMeasureDefinitionPreviousPeriodMeasure, +) +from gooddata_api_client.model.pop_date import PopDate +from gooddata_api_client.model.pop_date_measure_definition import PopDateMeasureDefinition +from gooddata_api_client.model.pop_date_measure_definition_over_period_measure import ( + PopDateMeasureDefinitionOverPeriodMeasure, +) +from gooddata_api_client.model.positive_attribute_filter import PositiveAttributeFilter +from gooddata_api_client.model.range_condition_range import RangeConditionRange +from gooddata_api_client.model.range_measure_value_filter import RangeMeasureValueFilter +from gooddata_api_client.model.ranking_filter import RankingFilter +from gooddata_api_client.model.relative_date_filter import RelativeDateFilter +from gooddata_api_client.model.result_cache_metadata import ResultCacheMetadata +from gooddata_api_client.model.result_spec import ResultSpec +from gooddata_api_client.model.simple_measure_definition import SimpleMeasureDefinition +from gooddata_api_client.model.simple_measure_definition_measure import SimpleMeasureDefinitionMeasure +from gooddata_api_client.model.sort_key import SortKey +from gooddata_api_client.model.sort_key_attribute_attribute import SortKeyAttributeAttribute +from gooddata_api_client.model.sort_key_value_value import SortKeyValueValue +from gooddata_api_client.model.total import Total +from gooddata_api_client.model.total_dimension import TotalDimension + +__all__ = [ + "AFM", + "AbsoluteDateFilter", + "AfmExecution", + "AfmExecutionResponse", + "AfmIdentifier", + "AfmLocalIdentifier", + "AfmObjectIdentifier", + "AfmObjectIdentifierAttribute", + "AfmObjectIdentifierAttributeIdentifier", + "AfmObjectIdentifierDataset", + "AfmObjectIdentifierDatasetIdentifier", + "AfmObjectIdentifierIdentifier", + "AfmObjectIdentifierLabel", + "AfmObjectIdentifierLabelIdentifier", + "AfmValidObjectsQuery", + "AllTimeDateFilter", + "ArithmeticMeasureDefinition", + "ArithmeticMeasureDefinitionArithmeticMeasure", + "AttributeFilterElements", + "AttributeItem", + "BoundedFilter", + "ComparisonConditionComparison", + "ComparisonMeasureValueFilter", + "CompoundMeasureValueFilter", + "Dimension", + "DimensionHeader", + "ExecutionResponse", + "ExecutionResult", + "ExecutionResultGrandTotal", + "ExecutionResultMetadata", + "ExecutionResultPaging", + "InlineFilterDefinition", + "InlineMeasureDefinition", + "InlineMeasureDefinitionInline", + "MatchAttributeFilter", + "MeasureItem", + "MeasureValueCondition", + "NegativeAttributeFilter", + "PopDataset", + "PopDatasetMeasureDefinition", + "PopDatasetMeasureDefinitionPreviousPeriodMeasure", + "PopDate", + "PopDateMeasureDefinition", + "PopDateMeasureDefinitionOverPeriodMeasure", + "PositiveAttributeFilter", + "RangeConditionRange", + "RangeMeasureValueFilter", + "RankingFilter", + "RelativeDateFilter", + "ResultCacheMetadata", + "ResultSpec", + "SimpleMeasureDefinition", + "SimpleMeasureDefinitionMeasure", + "SortKey", + "SortKeyAttributeAttribute", + "SortKeyValueValue", + "Total", + "TotalDimension", +] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/ai_lake/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/ai_lake/__init__.py index efe7c60c8..a136e7d5e 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/ai_lake/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/ai_lake/__init__.py @@ -1 +1,5 @@ # (C) 2026 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/appearance/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/appearance/__init__.py index efe7c60c8..a136e7d5e 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/appearance/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/appearance/__init__.py @@ -1 +1,5 @@ # (C) 2026 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/appearance/entity_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/appearance/entity_model/__init__.py index efe7c60c8..a136e7d5e 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/appearance/entity_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/appearance/entity_model/__init__.py @@ -1 +1,5 @@ # (C) 2026 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/catalog_service_base.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/catalog_service_base.py index 3da72a6b4..28b6049f5 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/catalog_service_base.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/catalog_service_base.py @@ -3,9 +3,9 @@ from pathlib import Path -from gooddata_api_client import apis from gooddata_api_client.model.json_api_organization_out_document import JsonApiOrganizationOutDocument +from gooddata_sdk import _apis as apis from gooddata_sdk.catalog.organization.entity_model.organization import CatalogOrganization from gooddata_sdk.client import GoodDataApiClient diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/__init__.py index 332df8193..f44f87a24 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/__init__.py @@ -1 +1,5 @@ # (C) 2023 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/__init__.py index 332df8193..f44f87a24 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/__init__.py @@ -1 +1,5 @@ # (C) 2023 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/responses/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/responses/__init__.py index 332df8193..f44f87a24 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/responses/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/responses/__init__.py @@ -1 +1,5 @@ # (C) 2023 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/content_objects/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/content_objects/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/content_objects/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/content_objects/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/validation/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/validation/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/validation/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/validation/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/__init__.py index 332df8193..f44f87a24 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/__init__.py @@ -1 +1,5 @@ # (C) 2023 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/__init__.py index 37d863d60..d160d7a93 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/__init__.py @@ -1 +1,5 @@ # (C) 2025 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/__init__.py index 06549c73b..ed0674d66 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/__init__.py @@ -1 +1,5 @@ # (C) 2024 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/management_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/management_model/__init__.py index 06549c73b..ed0674d66 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/management_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/management_model/__init__.py @@ -1 +1,5 @@ # (C) 2024 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/content_service.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/content_service.py index 7be97bee2..047316f73 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/content_service.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/content_service.py @@ -6,9 +6,9 @@ from pathlib import Path from typing import Literal, Union, cast -import gooddata_api_client.models as afm_models from gooddata_api_client.model.elements_request import ElementsRequest +from gooddata_sdk import _models as afm_models from gooddata_sdk.catalog.catalog_service_base import CatalogServiceBase from gooddata_sdk.catalog.data_source.validation.data_source import DataSourceValidator from gooddata_sdk.catalog.depends_on import CatalogDependsOn, CatalogDependsOnDateFilter diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset_extensions/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset_extensions/__init__.py index 332df8193..f44f87a24 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset_extensions/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset_extensions/__init__.py @@ -1 +1,5 @@ # (C) 2023 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/date_dataset/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/date_dataset/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/date_dataset/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/date_dataset/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/graph_objects/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/graph_objects/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/graph_objects/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/graph_objects/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/cli/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/cli/__init__.py index 06549c73b..ed0674d66 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/cli/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/cli/__init__.py @@ -1 +1,5 @@ # (C) 2024 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/client.py b/packages/gooddata-sdk/src/gooddata_sdk/client.py index 5af707cfc..8a17cbfe6 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/client.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/client.py @@ -10,12 +10,12 @@ import gooddata_api_client as api_client import requests -from gooddata_api_client import apis from requests.adapters import HTTPAdapter from urllib3.exceptions import MaxRetryError from urllib3.util.retry import Retry from gooddata_sdk import __version__ +from gooddata_sdk import _apis as apis from gooddata_sdk.utils import HttpMethod logger = logging.getLogger(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/__init__.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/__init__.py index 67106a19b..5af201b85 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/__init__.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/__init__.py @@ -1 +1,5 @@ # (C) 2022 GoodData Corporation +from gooddata_sdk._lazy import submodule_getattr + +# Expose submodules as attributes without importing them eagerly. +__getattr__ = submodule_getattr(__name__) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/attribute.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/attribute.py index 595226d13..79503f9c0 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/attribute.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/attribute.py @@ -3,8 +3,7 @@ from typing import Union -import gooddata_api_client.models as afm_models - +from gooddata_sdk import _models as afm_models from gooddata_sdk.compute.model.base import ExecModelEntity, ObjId diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/base.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/base.py index 1804cb9bf..27915393a 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/base.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/base.py @@ -3,9 +3,10 @@ from typing import Union -import gooddata_api_client.models as afm_models from gooddata_api_client.model_utils import OpenApiModel +from gooddata_sdk import _models as afm_models + class ObjId: def __init__(self, id: str, type: str) -> None: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py index ec3598983..b0474c987 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py @@ -10,11 +10,12 @@ from attrs import define, field from attrs.setters import frozen as frozen_attr -from gooddata_api_client import models from gooddata_api_client.model.afm import AFM from gooddata_api_client.model.afm_cancel_tokens import AfmCancelTokens from gooddata_api_client.model.result_spec import ResultSpec +from gooddata_sdk import _models as models + try: import pyarrow as _pyarrow from pyarrow import ipc as _ipc diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/filter.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/filter.py index 594723aa9..203b393fb 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/filter.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/filter.py @@ -11,23 +11,37 @@ if find_spec("icu") is not None: from icu import Locale, SimpleDateFormat # type: ignore -import gooddata_api_client.models as afm_models -from gooddata_api_client.model_utils import OpenApiModel -from gooddata_api_client.models import AbsoluteDateFilterAbsoluteDateFilter as AbsoluteDateFilterBody -from gooddata_api_client.models import AllTimeDateFilterAllTimeDateFilter as AllTimeDateFilterBody -from gooddata_api_client.models import ( +from gooddata_api_client.model.absolute_date_filter_absolute_date_filter import ( + AbsoluteDateFilterAbsoluteDateFilter as AbsoluteDateFilterBody, +) +from gooddata_api_client.model.all_time_date_filter_all_time_date_filter import ( + AllTimeDateFilterAllTimeDateFilter as AllTimeDateFilterBody, +) +from gooddata_api_client.model.comparison_measure_value_filter_comparison_measure_value_filter import ( ComparisonMeasureValueFilterComparisonMeasureValueFilter as ComparisonMeasureValueFilterBody, ) -from gooddata_api_client.models import ( +from gooddata_api_client.model.compound_measure_value_filter_compound_measure_value_filter import ( CompoundMeasureValueFilterCompoundMeasureValueFilter as CompoundMeasureValueFilterBody, ) -from gooddata_api_client.models import MatchAttributeFilterMatchAttributeFilter as MatchAttributeFilterBody -from gooddata_api_client.models import NegativeAttributeFilterNegativeAttributeFilter as NegativeAttributeFilterBody -from gooddata_api_client.models import PositiveAttributeFilterPositiveAttributeFilter as PositiveAttributeFilterBody -from gooddata_api_client.models import RangeMeasureValueFilterRangeMeasureValueFilter as RangeMeasureValueFilterBody -from gooddata_api_client.models import RankingFilterRankingFilter as RankingFilterBody -from gooddata_api_client.models import RelativeDateFilterRelativeDateFilter as RelativeDateFilterBody +from gooddata_api_client.model.match_attribute_filter_match_attribute_filter import ( + MatchAttributeFilterMatchAttributeFilter as MatchAttributeFilterBody, +) +from gooddata_api_client.model.negative_attribute_filter_negative_attribute_filter import ( + NegativeAttributeFilterNegativeAttributeFilter as NegativeAttributeFilterBody, +) +from gooddata_api_client.model.positive_attribute_filter_positive_attribute_filter import ( + PositiveAttributeFilterPositiveAttributeFilter as PositiveAttributeFilterBody, +) +from gooddata_api_client.model.range_measure_value_filter_range_measure_value_filter import ( + RangeMeasureValueFilterRangeMeasureValueFilter as RangeMeasureValueFilterBody, +) +from gooddata_api_client.model.ranking_filter_ranking_filter import RankingFilterRankingFilter as RankingFilterBody +from gooddata_api_client.model.relative_date_filter_relative_date_filter import ( + RelativeDateFilterRelativeDateFilter as RelativeDateFilterBody, +) +from gooddata_api_client.model_utils import OpenApiModel +from gooddata_sdk import _models as afm_models from gooddata_sdk.compute.model.attribute import Attribute from gooddata_sdk.compute.model.base import Filter, ObjId from gooddata_sdk.compute.model.metric import Metric diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/metric.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/metric.py index 3e671f4ca..8b06f06cb 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/metric.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/metric.py @@ -3,9 +3,9 @@ from typing import Union -import gooddata_api_client.models as afm_models from gooddata_api_client.model_utils import OpenApiModel +from gooddata_sdk import _models as afm_models from gooddata_sdk.compute.model.attribute import Attribute from gooddata_sdk.compute.model.base import ExecModelEntity, Filter, ObjId diff --git a/packages/gooddata-sdk/tests/sdk/test_lazy_imports.py b/packages/gooddata-sdk/tests/sdk/test_lazy_imports.py new file mode 100644 index 000000000..72a82b3b7 --- /dev/null +++ b/packages/gooddata-sdk/tests/sdk/test_lazy_imports.py @@ -0,0 +1,121 @@ +# (C) 2025 GoodData Corporation +"""Guards for the lazy import layout of ``gooddata_sdk``. + +``gooddata_sdk/__init__.py`` re-exports its public API lazily (PEP 562) and the SDK imports +individual generated model/API modules instead of the ``gooddata_api_client.models`` and +``gooddata_api_client.apis`` aggregates. Both are easy to undo by accident with a single +convenience import, so they are asserted here. +""" + +import subprocess +import sys +from pathlib import Path + +import gooddata_sdk +import pytest +from gooddata_sdk import _apis, _models + +REPO_ROOT = Path(__file__).resolve().parents[4] + + +def test_all_lazy_exports_resolve(): + """Catches a stale module path -- the strings are data, so a moved module fails only here.""" + for name in gooddata_sdk.__all__: + assert getattr(gooddata_sdk, name) is not None, name + + +def test_lazy_import_tables_are_in_sync_with_the_type_checking_block(): + """The generated tables must match their source of truth, or a new export silently vanishes. + + ``test_all_lazy_exports_resolve`` only checks names that made it into the map; this checks + that the map itself still matches the ``TYPE_CHECKING`` imports it is generated from. + """ + script = REPO_ROOT / "scripts/sync_lazy_imports.py" + result = subprocess.run([sys.executable, str(script)], capture_output=True, text=True) + assert result.returncode == 0, result.stderr + + +def test_unknown_attribute_raises_attribute_error(): + with pytest.raises(AttributeError): + gooddata_sdk.ThisDoesNotExist + + +@pytest.mark.parametrize( + "expression", + [ + "gooddata_sdk.utils", + "gooddata_sdk.sdk", + "gooddata_sdk.catalog", + "gooddata_sdk.catalog.workspace", + "gooddata_sdk.catalog.workspace.entity_model", + "gooddata_sdk.compute", + "gooddata_sdk.compute.model", + "gooddata_sdk.compute.model.filter", + "gooddata_sdk.visualization", + "gooddata_sdk.table", + ], +) +def test_submodules_are_still_reachable_as_attributes(expression): + """``import gooddata_sdk`` used to populate the whole tree; attribute access must still work. + + Each expression runs in a fresh interpreter on purpose -- sharing one would let an earlier + expression import the tree and mask a missing lazy hook in a subpackage. + """ + subprocess.run([sys.executable, "-c", f"import gooddata_sdk\n{expression}\n"], check=True) + + +def test_missing_dependency_inside_a_submodule_is_not_masked_as_attribute_error(): + """A broken submodule must keep its ModuleNotFoundError, not look like a typo.""" + code = ( + "import sys, types\n" + "import gooddata_sdk\n" + "broken = types.ModuleType('gooddata_sdk.catalog.broken')\n" + "class Finder:\n" + " def find_spec(self, name, path=None, target=None):\n" + " if name == 'gooddata_sdk.catalog.broken':\n" + " raise ModuleNotFoundError('No module named nonexistent_dep'," + " name='nonexistent_dep')\n" + " return None\n" + "sys.meta_path.insert(0, Finder())\n" + "try:\n" + " gooddata_sdk.catalog.broken\n" + "except ModuleNotFoundError as e:\n" + " assert e.name == 'nonexistent_dep', e.name\n" + "else:\n" + " raise AssertionError('ModuleNotFoundError was swallowed')\n" + ) + subprocess.run([sys.executable, "-c", code], check=True) + + +@pytest.mark.parametrize( + "statement", + [ + "import gooddata_sdk", + "from gooddata_sdk import GoodDataSdk", + "from gooddata_sdk.visualization import Visualization", + ], +) +def test_aggregate_api_client_modules_are_not_imported(statement): + """The aggregates import ~1400 model classes / ~130 API classes; the SDK needs a few dozen.""" + code = ( + f"{statement}\n" + "import sys\n" + "assert 'gooddata_api_client.models' not in sys.modules, 'models aggregate imported'\n" + "assert 'gooddata_api_client.apis' not in sys.modules, 'apis aggregate imported'\n" + ) + subprocess.run([sys.executable, "-c", code], check=True) + + +def test_importing_gooddata_sdk_does_not_import_the_whole_sdk(): + code = ( + "import sys\n" + "import gooddata_sdk\n" + "assert 'gooddata_sdk.sdk' not in sys.modules, 'gooddata_sdk.sdk imported eagerly'\n" + ) + subprocess.run([sys.executable, "-c", code], check=True) + + +def test_reexport_modules_expose_exactly_their_all(): + for module in (_models, _apis): + for name in module.__all__: + assert hasattr(module, name), f"{module.__name__}.{name}" diff --git a/scripts/sync_lazy_imports.py b/scripts/sync_lazy_imports.py new file mode 100755 index 000000000..bfd10ea27 --- /dev/null +++ b/scripts/sync_lazy_imports.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +# (C) 2025 GoodData Corporation +"""Keep ``gooddata_sdk.__init__``'s lazy-import tables in sync with its ``TYPE_CHECKING`` block. + +``gooddata_sdk/__init__.py`` re-exports its public API lazily (PEP 562), which needs a +name -> module mapping as data. Hand-maintaining ~250 string pairs alongside the real imports +would drift, and the drift would only show up at runtime. + +So the ``if TYPE_CHECKING:`` block is the single source of truth: it holds ordinary +``from x import Y`` statements that IDEs autocomplete, refactorings rewrite and type checkers +verify. ``_LAZY_IMPORTS`` and ``__all__`` are generated from it by this script and must never be +edited by hand. Adding a public export therefore means adding one normal import, then running +``scripts/sync_lazy_imports.py --update``. + +Without ``--update`` the script only reports drift and leaves the file alone. That is what +``tests/sdk/test_lazy_imports.py`` runs, so forgetting to regenerate fails CI with the command +to fix it rather than shipping an export that raises ``AttributeError`` at runtime. +""" + +from __future__ import annotations + +import argparse +import ast +import sys +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parent.parent +TARGET = REPO_ROOT / "packages/gooddata-sdk/src/gooddata_sdk/__init__.py" + +BEGIN = "# --- begin generated by scripts/sync_lazy_imports.py ---" +END = "# --- end generated by scripts/sync_lazy_imports.py ---" + +PREAMBLE = """# Public name -> module that defines it, generated from the ``TYPE_CHECKING`` block above. +# Importing all of these at module level pulls in the whole SDK (every catalog service, +# declarative model and generated API model) even when the caller wants a single class, so they +# are resolved on first access instead (PEP 562). Do not edit by hand -- see the script. +""" + + +def collect_exports(source: str) -> dict[str, str]: + """Read the public name -> module mapping out of the ``TYPE_CHECKING`` block. + + Args: + source (str): Contents of ``gooddata_sdk/__init__.py``. + + Returns: + dict[str, str]: Exported name mapped to the module it is imported from. + + Raises: + SystemExit: If the ``TYPE_CHECKING`` block is missing, or an import cannot be represented. + """ + tree = ast.parse(source) + block = next( + ( + node + for node in tree.body + if isinstance(node, ast.If) and isinstance(node.test, ast.Name) and node.test.id == "TYPE_CHECKING" + ), + None, + ) + if block is None: + sys.exit(f"{TARGET}: no `if TYPE_CHECKING:` block found") + + exports: dict[str, str] = {} + for node in block.body: + if not isinstance(node, ast.ImportFrom) or node.module is None: + sys.exit(f"{TARGET}:{getattr(node, 'lineno', '?')}: only `from X import Y` is supported here") + for alias in node.names: + if alias.asname is not None: + sys.exit(f"{TARGET}:{node.lineno}: aliased imports are not supported ({alias.name})") + if alias.name in exports: + sys.exit(f"{TARGET}:{node.lineno}: duplicate export {alias.name}") + exports[alias.name] = node.module + return exports + + +def render(exports: dict[str, str]) -> str: + """Render the generated block for the given exports. + + Args: + exports (dict[str, str]): Exported name mapped to its defining module. + + Returns: + str: The block to place between the begin/end markers, markers included. + """ + names = sorted(exports) + mapping = "\n".join(f' "{n}": "{exports[n]}",' for n in names) + all_names = "\n".join(f' "{n}",' for n in ["__version__", *names]) + return f"{BEGIN}\n{PREAMBLE}_LAZY_IMPORTS: dict[str, str] = {{\n{mapping}\n}}\n\n__all__ = [\n{all_names}\n]\n{END}" + + +def splice(source: str, block: str) -> str: + """Replace the generated region of ``source`` with ``block``. + + Args: + source (str): Current file contents. + block (str): Rendered replacement, markers included. + + Returns: + str: Updated file contents. + + Raises: + SystemExit: If the begin/end markers are missing or out of order. + """ + start, end = source.find(BEGIN), source.find(END) + if start == -1 or end == -1 or end < start: + sys.exit(f"{TARGET}: generated-block markers not found") + return source[:start] + block + source[end + len(END) :] + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("--update", action="store_true", help="rewrite the file instead of only reporting drift") + args = parser.parse_args() + + source = TARGET.read_text() + updated = splice(source, render(collect_exports(source))) + if source == updated: + return 0 + if not args.update: + print( + f"{TARGET}: _LAZY_IMPORTS/__all__ are out of sync with the TYPE_CHECKING block.\n" + f"Run `scripts/sync_lazy_imports.py --update`.", + file=sys.stderr, + ) + return 1 + TARGET.write_text(updated) + print(f"{TARGET}: regenerated _LAZY_IMPORTS/__all__") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())