diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/base.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/base.py index dc6c73a3d..ffcf495e4 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/base.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/base.py @@ -2,9 +2,9 @@ from __future__ import annotations import builtins -from typing import Any, Optional, TypeVar +from typing import Any, TypeVar -import attr +from attrs import Attribute, asdict, define, field from cattrs import structure from gooddata_sdk.utils import AllPagedEntities @@ -13,9 +13,7 @@ U = TypeVar("U", bound="JsonApiEntityBase") -def value_in_allowed( - instance: type[Base], attribute: attr.Attribute, value: str, client_class: Optional[Any] = None -) -> None: +def value_in_allowed(instance: type[Base], attribute: Attribute, value: str, client_class: Any | None = None) -> None: if client_class is None: client_class = instance.client_class() allowed_values = client_class.allowed_values.get((attribute.name,)) @@ -26,7 +24,7 @@ def value_in_allowed( ) -@attr.s +@define class Base: @classmethod def from_api(cls: type[T], entity: dict[str, Any]) -> T: @@ -55,11 +53,11 @@ def to_dict(self, camel_case: bool = True) -> dict[str, Any]: return self.to_api().to_dict(camel_case) @staticmethod - def _is_attribute_private(attribute: attr.Attribute) -> bool: + def _is_attribute_private(attribute: Attribute) -> bool: return attribute.name.startswith("_") def _get_snake_dict(self) -> dict[str, Any]: - return attr.asdict( + return asdict( self, filter=lambda attribute, value: value is not None and not self._is_attribute_private(attribute) ) @@ -72,24 +70,24 @@ def to_api(self) -> Any: return self.client_class().from_dict(dictionary, camel_case=False) -@attr.s(auto_attribs=True) +@define class JsonApiEntityBase: id: str type: str - attributes: dict[str, Any] = attr.field(repr=False) - relationships: Optional[dict[str, Any]] = attr.field(repr=False, default=None) - meta: Optional[dict[str, Any]] = attr.field(repr=False, default=None) - links: Optional[dict[str, Any]] = attr.field(repr=False, default=None) - related_entities_data: list[dict[str, Any]] = attr.field(repr=False, factory=list) - related_entities_side_loads: list[dict[str, Any]] = attr.field(repr=False, factory=list) - side_loads: list[dict[str, Any]] = attr.field(repr=False, factory=list) + attributes: dict[str, Any] = field(repr=False) + relationships: dict[str, Any] | None = field(repr=False, default=None) + meta: dict[str, Any] | None = field(repr=False, default=None) + links: dict[str, Any] | None = field(repr=False, default=None) + related_entities_data: list[dict[str, Any]] = field(repr=False, factory=list) + related_entities_side_loads: list[dict[str, Any]] = field(repr=False, factory=list) + side_loads: list[dict[str, Any]] = field(repr=False, factory=list) @classmethod def from_api( cls, entity: dict[str, Any], - side_loads: Optional[list[Any]] = None, - related_entities: Optional[AllPagedEntities] = None, + side_loads: list[Any] | None = None, + related_entities: AllPagedEntities | None = None, ) -> JsonApiEntityBase: """ Creates object from entity passed by client class, which represents it as dictionary. diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/ldm_request.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/ldm_request.py index 67053621d..d884967c4 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/ldm_request.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/ldm_request.py @@ -1,9 +1,7 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Optional - -import attr +from attrs import define from gooddata_api_client.model.generate_ldm_request import GenerateLdmRequest from gooddata_api_client.model.pdm_ldm_request import PdmLdmRequest from gooddata_api_client.model.pdm_sql import PdmSql @@ -13,7 +11,7 @@ from gooddata_sdk.catalog.data_source.declarative_model.physical_model.table import CatalogDeclarativeTable -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogPdmSql(Base): statement: str title: str @@ -24,34 +22,34 @@ def client_class() -> type[PdmSql]: return PdmSql -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogPdmLdmRequest(Base): - sqls: Optional[list[CatalogPdmSql]] = None - tables: Optional[list[CatalogDeclarativeTable]] = None + sqls: list[CatalogPdmSql] | None = None + tables: list[CatalogDeclarativeTable] | None = None @staticmethod def client_class() -> type[PdmLdmRequest]: return PdmLdmRequest -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogGenerateLdmRequest(Base): separator: str = "__" - generate_long_ids: Optional[bool] = None - table_prefix: Optional[str] = None - view_prefix: Optional[str] = None - primary_label_prefix: Optional[str] = None - secondary_label_prefix: Optional[str] = None - fact_prefix: Optional[str] = None - date_granularities: Optional[str] = None - grain_prefix: Optional[str] = None - reference_prefix: Optional[str] = None - grain_reference_prefix: Optional[str] = None - denorm_prefix: Optional[str] = None - wdf_prefix: Optional[str] = None - pdm: Optional[CatalogPdmLdmRequest] = None - workspace_id: Optional[str] = None - translation_prefix: Optional[str] = None + generate_long_ids: bool | None = None + table_prefix: str | None = None + view_prefix: str | None = None + primary_label_prefix: str | None = None + secondary_label_prefix: str | None = None + fact_prefix: str | None = None + date_granularities: str | None = None + grain_prefix: str | None = None + reference_prefix: str | None = None + grain_reference_prefix: str | None = None + denorm_prefix: str | None = None + wdf_prefix: str | None = None + pdm: CatalogPdmLdmRequest | None = None + workspace_id: str | None = None + translation_prefix: str | None = None @staticmethod def client_class() -> type[GenerateLdmRequest]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/scan_model_request.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/scan_model_request.py index 38cdf0e7e..6e835b723 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/scan_model_request.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/scan_model_request.py @@ -1,10 +1,9 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Any, Optional +from typing import Any -import attr -from attr import field +from attrs import define, field from gooddata_api_client.model.scan_request import ScanRequest from gooddata_sdk.catalog.base import Base @@ -15,14 +14,14 @@ def one_scan_true(instance: CatalogScanModelRequest, *args: Any) -> None: raise ValueError("Either scan_tables or scan_views must be True in CatalogScanModelRequest.") -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogScanModelRequest(Base): separator: str = "__" scan_tables: bool = field(default=True, validator=one_scan_true) scan_views: bool = field(default=False, validator=one_scan_true) - table_prefix: Optional[str] = None - view_prefix: Optional[str] = None - schemata: Optional[list[str]] = None + table_prefix: str | None = None + view_prefix: str | None = None + schemata: list[str] | None = None @staticmethod def client_class() -> type[ScanRequest]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/scan_sql_request.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/scan_sql_request.py index cb1a7dd2b..38105c137 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/scan_sql_request.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/requests/scan_sql_request.py @@ -1,13 +1,13 @@ # (C) 2023 GoodData Corporation from __future__ import annotations -import attr +from attrs import define from gooddata_api_client.model.scan_sql_request import ScanSqlRequest as ApiScanSqlRequest from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ScanSqlRequest(Base): sql: str diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/responses/scan_sql_response.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/responses/scan_sql_response.py index 1dbcb0be9..9dfc8f433 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/responses/scan_sql_response.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/responses/scan_sql_response.py @@ -1,19 +1,17 @@ # (C) 2023 GoodData Corporation from __future__ import annotations -from typing import Optional - -import attr +from attrs import define from gooddata_api_client.model.scan_sql_response import ScanSqlResponse as ApiScanSqlResponse from gooddata_sdk.catalog.base import Base from gooddata_sdk.catalog.data_source.action_model.sql_column import SqlColumn -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ScanSqlResponse(Base): columns: list[SqlColumn] - data_preview: Optional[list[list[Optional[str]]]] = None + data_preview: list[list[str | None]] | None = None @staticmethod def client_class() -> type[ApiScanSqlResponse]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/sql_column.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/sql_column.py index 92e865d6a..781273509 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/sql_column.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/action_model/sql_column.py @@ -1,13 +1,13 @@ # (C) 2023 GoodData Corporation from __future__ import annotations -import attr +from attrs import define from gooddata_api_client.model.sql_column import SqlColumn as ApiSqlColumn from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class SqlColumn(Base): data_type: str name: str diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/data_source.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/data_source.py index c5a805cfd..b67d52b37 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/data_source.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/data_source.py @@ -3,10 +3,10 @@ import builtins from pathlib import Path -from typing import Any, Optional, Union +from typing import Any, Union from warnings import warn -import attr +from attrs import define, field from gooddata_api_client.model.declarative_data_source import DeclarativeDataSource from gooddata_api_client.model.declarative_data_sources import DeclarativeDataSources from gooddata_api_client.model.test_definition_request import TestDefinitionRequest @@ -25,7 +25,7 @@ LAYOUT_DATA_SOURCES_DIR = "data_sources" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDataSources(Base): data_sources: list[CatalogDeclarativeDataSource] @@ -90,7 +90,7 @@ def _inject_credentials_aac(self, config_file: Union[str, Path]) -> DeclarativeD return self._inject_base(credentials) def to_api( - self, credentials: Optional[dict[str, Any]] = None, config_file: Optional[Union[str, Path]] = None + self, credentials: dict[str, Any] | None = None, config_file: Union[str, Path] | None = None ) -> DeclarativeDataSources: client_class = self.client_class() if credentials is not None and config_file is not None: @@ -127,29 +127,29 @@ def load_from_disk(cls, layout_organization_folder: Path) -> CatalogDeclarativeD return cls(data_sources=data_sources) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDataSource(Base): id: str name: str - type: str = attr.field(validator=value_in_allowed) - url: Optional[str] = None + type: str = field(validator=value_in_allowed) + url: str | None = None schema: str - cache_strategy: Optional[str] = None - username: Optional[str] = None - parameters: Optional[list[CatalogParameter]] = None - decoded_parameters: Optional[list[CatalogParameter]] = None - permissions: list[CatalogDeclarativeDataSourcePermission] = attr.field(factory=list) - client_id: Optional[str] = None - authentication_type: Optional[str] = None - alternative_data_source_id: Optional[str] = None + cache_strategy: str | None = None + username: str | None = None + parameters: list[CatalogParameter] | None = None + decoded_parameters: list[CatalogParameter] | None = None + permissions: list[CatalogDeclarativeDataSourcePermission] = field(factory=list) + client_id: str | None = None + authentication_type: str | None = None + alternative_data_source_id: str | None = None def to_test_request( self, - password: Optional[str] = None, - token: Optional[str] = None, - private_key: Optional[str] = None, - private_key_passphrase: Optional[str] = None, - client_secret: Optional[str] = None, + password: str | None = None, + token: str | None = None, + private_key: str | None = None, + private_key_passphrase: str | None = None, + client_secret: str | None = None, ) -> TestDefinitionRequest: kwargs: dict[str, Any] = {"schema": self.schema} if password is not None: @@ -183,11 +183,11 @@ def data_source_folder(data_sources_folder: Path, data_source_id: str) -> Path: def to_api( self, - password: Optional[str] = None, - token: Optional[str] = None, - private_key: Optional[str] = None, - private_key_passphrase: Optional[str] = None, - client_secret: Optional[str] = None, + password: str | None = None, + token: str | None = None, + private_key: str | None = None, + private_key_passphrase: str | None = None, + client_secret: str | None = None, ) -> DeclarativeDataSource: dictionary = self._get_snake_dict() if password is not None: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/column.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/column.py index 45ccb6a15..ded708837 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/column.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/column.py @@ -1,23 +1,21 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Optional - -import attr +from attrs import define from gooddata_api_client.model.declarative_column import DeclarativeColumn from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeColumn(Base): name: str data_type: str - is_primary_key: Optional[bool] = None - referenced_table_id: Optional[str] = None - referenced_table_column: Optional[str] = None - is_nullable: Optional[bool] = None - null_value: Optional[str] = None + is_primary_key: bool | None = None + referenced_table_id: str | None = None + referenced_table_column: str | None = None + is_nullable: bool | None = None + null_value: str | None = None @staticmethod def client_class() -> type[DeclarativeColumn]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/pdm.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/pdm.py index ce7bb4b69..6ec3b03aa 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/pdm.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/pdm.py @@ -3,7 +3,7 @@ from pathlib import Path -import attr +from attrs import define, field from gooddata_api_client.model.declarative_tables import DeclarativeTables from gooddata_sdk.catalog.base import Base @@ -17,9 +17,9 @@ def get_pdm_folder(data_source_folder: Path) -> Path: return data_source_folder / LAYOUT_PDM_DIR -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeTables(Base): - tables: list[CatalogDeclarativeTable] = attr.field(factory=list) + tables: list[CatalogDeclarativeTable] = field(factory=list) @staticmethod def client_class() -> type[DeclarativeTables]: @@ -39,8 +39,8 @@ def load_from_disk(cls, data_source_folder: Path) -> CatalogDeclarativeTables: return cls(tables=tables) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogScanResultPdm(Base): pdm: CatalogDeclarativeTables = CatalogDeclarativeTables() # Just informative hints. Create appropriate classes later if needed. - warnings: list[dict] = attr.field(factory=list) + warnings: list[dict] = field(factory=list) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/table.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/table.py index ea80d4a15..27fcf9efb 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/table.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/declarative_model/physical_model/table.py @@ -3,9 +3,8 @@ import builtins from pathlib import Path -from typing import Optional -import attr +from attrs import define from gooddata_api_client.model.declarative_table import DeclarativeTable from gooddata_sdk.catalog.base import Base @@ -13,13 +12,13 @@ from gooddata_sdk.utils import read_layout_from_file, write_layout_to_file -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeTable(Base): id: str type: str path: list[str] columns: list[CatalogDeclarativeColumn] - name_prefix: Optional[str] = None + name_prefix: str | None = None @staticmethod def client_class() -> builtins.type[DeclarativeTable]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/data_source.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/data_source.py index 84f4f0272..c17201fe4 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/data_source.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/entity_model/data_source.py @@ -2,9 +2,9 @@ from __future__ import annotations import builtins -from typing import Any, ClassVar, Optional, TypeVar +from typing import Any, ClassVar, TypeVar -import attr +from attrs import Attribute, asdict, define, field from cattrs import structure from gooddata_api_client.model.json_api_data_source_in import JsonApiDataSourceIn from gooddata_api_client.model.json_api_data_source_in_attributes import JsonApiDataSourceInAttributes @@ -31,7 +31,7 @@ def db_attrs_with_template(instance: CatalogDataSource, *args: Any) -> None: raise ValueError("_URL_TMPL needs to be set when db_specific_attributes is not None.") -@attr.s(auto_attribs=True, kw_only=True, eq=False) +@define(kw_only=True, eq=False) class CatalogDataSourceBase(Base): _SUPPORTED_CREDENTIALS: ClassVar[list[builtins.type[Credentials]]] = [ BasicCredentials, @@ -53,22 +53,22 @@ class CatalogDataSourceBase(Base): id: str name: str - type: str = attr.field() + type: str = field() schema: str - url: Optional[str] = None - cache_strategy: Optional[str] = None - parameters: Optional[list[dict[str, str]]] = None - decoded_parameters: Optional[list[dict[str, str]]] = None - credentials: Credentials = attr.field(repr=False) - alternative_data_source_id: Optional[str] = None + url: str | None = None + cache_strategy: str | None = None + parameters: list[dict[str, str]] | None = None + decoded_parameters: list[dict[str, str]] | None = None + credentials: Credentials = field(repr=False) + alternative_data_source_id: str | None = None @type.validator # type: ignore[attr-defined] - def _check_allowed_values(self, attribute: attr.Attribute, value: str) -> None: + def _check_allowed_values(self, attribute: Attribute, value: str) -> None: value_in_allowed(self.__class__, attribute, value, JsonApiDataSourceInAttributes) def to_api(self) -> Any: kwargs = self.credentials.to_api_args() - attributes = attr.asdict( + attributes = asdict( self, filter=lambda attribute, value: attribute.name in self._ATTRIBUTES and value is not None ) kwargs = {**kwargs, **attributes} @@ -103,20 +103,20 @@ def __eq__(self, other: Any) -> bool: ) -@attr.s(auto_attribs=True, kw_only=True, eq=False) +@define(kw_only=True, eq=False) class CatalogDataSource(CatalogDataSourceBase): - _URL_TMPL: ClassVar[Optional[str]] = None - _DATA_SOURCE_TYPE: ClassVar[Optional[str]] = None + _URL_TMPL: ClassVar[str | None] = None + _DATA_SOURCE_TYPE: ClassVar[str | None] = None - db_vendor: Optional[str] = attr.field(default=None, init=False) - db_specific_attributes: Optional[DatabaseAttributes] = attr.field(default=None, validator=db_attrs_with_template) - url_params: Optional[list[tuple[str, str]]] = None + db_vendor: str | None = field(default=None, init=False) + db_specific_attributes: DatabaseAttributes | None = field(default=None, validator=db_attrs_with_template) + url_params: list[tuple[str, str]] | None = None def __attrs_post_init__(self) -> None: self.db_vendor = self.db_vendor or self.type.lower() self.url = self._make_url() - def _make_url(self) -> Optional[str]: + def _make_url(self) -> str | None: parameters = self._join_params() if self.url: return f"{self.url}?{parameters}" if parameters else self.url @@ -132,73 +132,73 @@ def _make_url(self) -> Optional[str]: else: return None - def _join_params(self) -> Optional[str]: + def _join_params(self) -> str | None: if self.url_params: return self._DELIMITER.join([f"{p[0]}={p[1]}" for p in self.url_params]) return None @property - def url_template(self) -> Optional[str]: + def url_template(self) -> str | None: return self._URL_TMPL -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class DatabaseAttributes: @property def str_attributes(self) -> dict[str, str]: - return attr.asdict(self) + return asdict(self) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class PostgresAttributes(DatabaseAttributes): host: str db_name: str port: str = "5432" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class RedshiftAttributes(PostgresAttributes): port: str = "5439" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class VerticaAttributes(PostgresAttributes): port: str = "5433" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class GreenplumAttributes(PostgresAttributes): pass -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class MySqlAttributes(DatabaseAttributes): host: str port: str = "3306" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class MariaDbAttributes(MySqlAttributes): pass -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourcePostgres(CatalogDataSource): _URL_TMPL: ClassVar[str] = "jdbc:{db_vendor}://{host}:{port}/{db_name}" type: str = "POSTGRESQL" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceRedshift(CatalogDataSourcePostgres): type: str = "REDSHIFT" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceVertica(CatalogDataSourcePostgres): type: str = "VERTICA" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class SnowflakeAttributes(DatabaseAttributes): account: str warehouse: str @@ -206,7 +206,7 @@ class SnowflakeAttributes(DatabaseAttributes): port: str = "443" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceSnowflake(CatalogDataSource): _URL_TMPL: ClassVar[str] = ( "jdbc:{db_vendor}://{account}.snowflakecomputing.com:{port}?warehouse={warehouse}&db={db_name}" @@ -225,25 +225,25 @@ def _make_url(self) -> str: return f"{base_url}{self._DELIMITER}{parameters}" if parameters else base_url -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceBigQuery(CatalogDataSource): type: str = "BIGQUERY" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceGreenplum(CatalogDataSourcePostgres): type: str = "GREENPLUM" db_vendor: str = "postgresql" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class MsSqlAttributes(DatabaseAttributes): host: str db_name: str port: str = "1433" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceMsSql(CatalogDataSource): _URL_TMPL: ClassVar[str] = "jdbc:{db_vendor}://{host}:{port};databaseName={db_name}" type: str = "MSSQL" @@ -251,14 +251,14 @@ class CatalogDataSourceMsSql(CatalogDataSource): db_specific_attributes: MsSqlAttributes -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class DatabricksAttributes(DatabaseAttributes): host: str http_path: str port: str = "443" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceDatabricks(CatalogDataSource): _URL_TMPL: ClassVar[str] = "jdbc:{db_vendor}://{host}:{port}/default;httpPath={http_path}" type: str = "DATABRICKS" @@ -274,25 +274,25 @@ def __attrs_post_init__(self) -> None: self.url = self._make_url() -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceMySql(CatalogDataSource): _URL_TMPL: ClassVar[str] = "jdbc:{db_vendor}://{host}:{port}/{schema}" type: str = "MYSQL" db_vendor: str = "mysql" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceMariaDb(CatalogDataSourceMySql): type: str = "MARIADB" db_vendor: str = "mariadb" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class MotherDuckAttributes(DatabaseAttributes): db_name: str -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceMotherDuck(CatalogDataSource): _URL_TMPL: ClassVar[str] = "jdbc:duckdb:md:{db_name}" type: str = "MOTHERDUCK" diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/service.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/service.py index e3e0b88fb..9be59722e 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/service.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/data_source/service.py @@ -3,7 +3,7 @@ import functools from pathlib import Path -from typing import Any, Optional, Union +from typing import Any, Union from gooddata_api_client.exceptions import NotFoundException @@ -153,8 +153,8 @@ def get_declarative_data_sources(self) -> CatalogDeclarativeDataSources: def put_declarative_data_sources( self, declarative_data_sources: CatalogDeclarativeDataSources, - credentials_path: Optional[Path] = None, - config_file: Optional[Union[str, Path]] = None, + credentials_path: Path | None = None, + config_file: Union[str, Path] | None = None, test_data_sources: bool = False, ) -> None: """Set all data sources, including their related physical data model. @@ -221,8 +221,8 @@ def load_declarative_data_sources(self, layout_root_path: Path = Path.cwd()) -> def load_and_put_declarative_data_sources( self, layout_root_path: Path = Path.cwd(), - credentials_path: Optional[Path] = None, - config_file: Optional[Union[str, Path]] = None, + credentials_path: Path | None = None, + config_file: Union[str, Path] | None = None, test_data_sources: bool = False, ) -> None: """Loads and sets layouts stored using `store_declarative_data_sources`. @@ -307,7 +307,7 @@ def generate_logical_model( def scan_pdm_and_generate_logical_model( self, data_source_id: str, - generate_ldm_request: Optional[CatalogGenerateLdmRequest] = None, + generate_ldm_request: CatalogGenerateLdmRequest | None = None, scan_request: CatalogScanModelRequest = CatalogScanModelRequest(), report_warnings: bool = False, ) -> tuple[CatalogDeclarativeModel, CatalogScanResultPdm]: @@ -432,8 +432,8 @@ def scan_sql(self, data_source_id: str, sql_request: ScanSqlRequest) -> ScanSqlR def test_data_sources_connection( self, declarative_data_sources: CatalogDeclarativeDataSources, - credentials_path: Optional[Path] = None, - config_file: Optional[Union[str, Path]] = None, + credentials_path: Path | None = None, + config_file: Union[str, Path] | None = None, ) -> None: """Tests connection to declarative data sources. diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/depends_on.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/depends_on.py index a31bfdaa4..ca98e963e 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/depends_on.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/depends_on.py @@ -3,7 +3,7 @@ from typing import Union -import attr +from attrs import define from gooddata_api_client.model.absolute_date_filter import AbsoluteDateFilter as AbsoluteDateFilterAPI from gooddata_api_client.model.elements_request_depends_on_inner import ElementsRequestDependsOnInner from gooddata_api_client.model.relative_date_filter import RelativeDateFilter as RelativeDateFilterAPI @@ -12,7 +12,7 @@ from gooddata_sdk.compute.model.filter import AbsoluteDateFilter, RelativeDateFilter -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDependsOn(Base): label: str values: list[str] @@ -23,7 +23,7 @@ def client_class() -> type[ElementsRequestDependsOnInner]: return ElementsRequestDependsOnInner -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDependsOnDateFilter: date_filter: Union[AbsoluteDateFilter, RelativeDateFilter] @@ -31,7 +31,7 @@ def to_api(self) -> type[ElementsRequestDependsOnInner]: return CatalogDependsOnDateFilterItem(date_filter=self.date_filter.as_api_model()).to_api() -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDependsOnDateFilterItem(Base): date_filter: Union[AbsoluteDateFilterAPI, RelativeDateFilterAPI] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/entity.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/entity.py index e9067d51f..88efa82d5 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/entity.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/entity.py @@ -5,9 +5,9 @@ import builtins import os from pathlib import Path -from typing import Any, ClassVar, Optional, TypeVar, Union +from typing import Any, ClassVar, TypeVar, Union -import attr +from attrs import Factory, asdict, define, field from gooddata_sdk.catalog.base import Base, JsonApiEntityBase from gooddata_sdk.compute.model.base import ObjId @@ -16,11 +16,11 @@ T = TypeVar("T", bound="AttrCatalogEntity") -@attr.s(auto_attribs=True) +@define class AttrCatalogEntity: id: str - type: str = attr.field(default=attr.Factory(lambda self: self._get_type(), takes_self=True)) + type: str = field(default=Factory(lambda self: self._get_type(), takes_self=True)) def _get_type(self) -> str: allowed_values = getattr(self.client_class(), "allowed_values") @@ -32,10 +32,10 @@ def _get_type(self) -> str: # Optional, because write use case - # we need to pass only ID and some properties in attributes when creating an instance of this class - json_api_entity: Optional[JsonApiEntityBase] = None - title: Optional[str] = None - description: Optional[str] = None - tags: Optional[list[str]] = None + json_api_entity: JsonApiEntityBase | None = None + title: str | None = None + description: str | None = None + tags: list[str] | None = None @property def json_api_attributes(self) -> dict[str, Any]: @@ -65,8 +65,8 @@ def obj_id(self) -> ObjId: def from_api( cls: builtins.type[T], entity: dict[str, Any], - side_loads: Optional[list[Any]] = None, - related_entities: Optional[AllPagedEntities] = None, + side_loads: list[Any] | None = None, + related_entities: AllPagedEntities | None = None, ) -> T: """ Creates GoodData object from AttrCatalogEntityJsonApi. @@ -104,12 +104,12 @@ def type(self) -> str: return self._entity["type"] @property - def title(self) -> Optional[str]: + def title(self) -> str | None: # Optional, not all metadata objects contain title return self._e.get("title") @property - def description(self) -> Optional[str]: + def description(self) -> str | None: # Optional, not all metadata objects contain description return self._e.get("description") @@ -118,7 +118,7 @@ def obj_id(self) -> ObjId: return self._obj_id -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class Credentials(Base): TOKEN_KEY: ClassVar[str] = "token" USER_KEY: ClassVar[str] = "username" @@ -129,7 +129,7 @@ class Credentials(Base): CLIENT_SECRET: ClassVar[str] = "client_secret" def to_api_args(self) -> dict[str, Any]: - return attr.asdict(self) + return asdict(self) @classmethod def is_part_of_api(cls, entity: dict[str, Any]) -> bool: @@ -151,9 +151,9 @@ def validate_instance(cls, creds_classes: list[type[Credentials]], instance: Cre raise ValueError(f"Unsupported credentials type. Pick one of {classes_as_str}") -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class TokenCredentials(Credentials): - token: str = attr.field(repr=lambda value: "***") + token: str = field(repr=lambda value: "***") @classmethod def is_part_of_api(cls, entity: dict[str, Any]) -> bool: @@ -165,10 +165,10 @@ def from_api(cls, entity: dict[str, Any]) -> TokenCredentials: return cls(token="") -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class TokenCredentialsFromFile(Credentials): file_path: Path - token: str = attr.field(init=False, repr=lambda value: "***") + token: str = field(init=False, repr=lambda value: "***") def __attrs_post_init__(self) -> None: self.token = self.token_from_file(self.file_path) @@ -205,10 +205,10 @@ def token_from_file(file_path: Union[str, Path], base64_encode: bool = True) -> return base64.b64encode(content).decode("utf-8") if base64_encode else content.decode("utf-8") -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class TokenCredentialsFromEnvVar(Credentials): env_var_name: str - token: str = attr.field(init=False, repr=lambda value: "***") + token: str = field(init=False, repr=lambda value: "***") def __attrs_post_init__(self) -> None: self.token = self.token_from_env_var(self.env_var_name) @@ -246,10 +246,10 @@ def token_from_env_var(env_var_name: str, base64_encode: bool = True) -> str: return base64.b64encode(token.encode("utf-8")).decode("utf-8") if base64_encode else token -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class BasicCredentials(Credentials): username: str - password: str = attr.field(repr=lambda value: "***") + password: str = field(repr=lambda value: "***") @classmethod def is_part_of_api(cls, entity: dict[str, Any]) -> bool: @@ -266,11 +266,11 @@ def from_api(cls, attributes: dict[str, Any]) -> BasicCredentials: # type: igno ) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class KeyPairCredentials(Credentials): username: str - private_key: str = attr.field(repr=lambda value: "***") - private_key_passphrase: Optional[str] = attr.field(repr=lambda value: "***", default=None) + private_key: str = field(repr=lambda value: "***") + private_key_passphrase: str | None = field(repr=lambda value: "***", default=None) @classmethod def is_part_of_api(cls, entity: dict[str, Any]) -> bool: @@ -287,10 +287,10 @@ def from_api(cls, attributes: dict[str, Any]) -> KeyPairCredentials: # type: ig ) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ClientSecretCredentials(Credentials): client_id: str - client_secret: str = attr.field(repr=lambda value: "***") + client_secret: str = field(repr=lambda value: "***") @classmethod def is_part_of_api(cls, entity: dict[str, Any]) -> bool: @@ -307,10 +307,10 @@ def from_api(cls, attributes: dict[str, Any]) -> ClientSecretCredentials: # typ ) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ClientSecretCredentialsFromFile(Credentials): file_path: Path - client_secret: str = attr.field(init=False, repr=lambda value: "***") + client_secret: str = field(init=False, repr=lambda value: "***") def __attrs_post_init__(self) -> None: self.client_secret = self.client_secret_from_file(self.file_path) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/request.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/request.py index d2a2a783f..35ea2d6d2 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/request.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/request.py @@ -1,5 +1,5 @@ # (C) 2023 GoodData Corporation -from typing import Literal, Optional +from typing import Literal from attrs import define from gooddata_api_client.model.custom_label import CustomLabel as ApiCustomLabel @@ -13,7 +13,7 @@ from gooddata_sdk.catalog.base import Base -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ExportCustomLabel(Base): title: str @@ -22,7 +22,7 @@ def client_class() -> type[ApiCustomLabel]: return ApiCustomLabel -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ExportCustomMetric(Base): title: str format: str @@ -32,17 +32,17 @@ def client_class() -> type[ApiCustomMetric]: return ApiCustomMetric -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ExportCustomOverride(Base): - labels: Optional[dict[str, ExportCustomLabel]] = None - metrics: Optional[dict[str, ExportCustomMetric]] = None + labels: dict[str, ExportCustomLabel] | None = None + metrics: dict[str, ExportCustomMetric] | None = None @staticmethod def client_class() -> type[ApiCustomOverride]: return ApiCustomOverride -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ExportSettings(Base): merge_headers: bool show_filters: bool @@ -52,7 +52,7 @@ def client_class() -> type[ApiSettings]: return ApiSettings -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class ExportRequest(Base): """ ExportRequest class is used to create an export request in the desired format, filename, and settings. @@ -66,10 +66,10 @@ class ExportRequest(Base): format: str file_name: str - execution_result: Optional[str] = None - visualization_object: Optional[str] = None - settings: Optional[ExportSettings] = None - custom_override: Optional[ExportCustomOverride] = None + execution_result: str | None = None + visualization_object: str | None = None + settings: ExportSettings | None = None + custom_override: ExportCustomOverride | None = None def __attrs_post_init__(self) -> None: """ @@ -100,7 +100,7 @@ def file(self) -> str: return f"{self.file_name}.{self.format.lower()}" -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class VisualExportRequest(Base): """ ExportRequest class is used to create an export request in the desired format, filename, and settings. @@ -112,7 +112,7 @@ class VisualExportRequest(Base): dashboard_id: str file_name: str - metadata: Optional[dict] = None + metadata: dict | None = None @staticmethod def client_class() -> type[VisualExportRequestApi]: @@ -124,7 +124,7 @@ def client_class() -> type[VisualExportRequestApi]: return VisualExportRequestApi -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class SlidesExportRequest(Base): """ SlidesExportRequest class is used to create a slide export request in the desired format, filename, and settings. @@ -136,11 +136,11 @@ class SlidesExportRequest(Base): file_name: str format: Literal["PDF", "PPTX"] - dashboard_id: Optional[str] = None - widget_ids: Optional[list[str]] = None - visualization_ids: Optional[list[str]] = None - metadata: Optional[dict] = None - templateId: Optional[str] = None + dashboard_id: str | None = None + widget_ids: list[str] | None = None + visualization_ids: list[str] | None = None + metadata: dict | None = None + templateId: str | None = None @staticmethod def client_class() -> type[SlidesExportRequestApi]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/service.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/service.py index 8774b3c98..0207fc1a7 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/service.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/export/service.py @@ -1,7 +1,7 @@ # (C) 2023 GoodData Corporation import time from pathlib import Path -from typing import Any, Callable, Optional, Union +from typing import Any, Callable, Union from gooddata_api_client.exceptions import NotFoundException from gooddata_api_client.model.slides_export_request import SlidesExportRequest as SlidesExportRequestApi @@ -186,7 +186,7 @@ def export_pdf( timeout: float = 60.0, retry: float = 0.2, max_retry: float = 5.0, - metadata: Optional[dict[str, Any]] = None, + metadata: dict[str, Any] | None = None, ) -> None: """ Export a PDF of the specified GoodData Dashboard and save it to the specified file path. @@ -275,8 +275,8 @@ def export_tabular_by_visualization_id( workspace_id: str, visualization_id: str, file_format: str, - file_name: Optional[str] = None, - settings: Optional[ExportSettings] = None, + file_name: str | None = None, + settings: ExportSettings | None = None, store_path: Union[str, Path] = Path.cwd(), timeout: float = 60.0, retry: float = 0.2, diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/filter_by.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/filter_by.py index c6961c7c6..4985fdcec 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/filter_by.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/filter_by.py @@ -1,17 +1,15 @@ # (C) 2024 GoodData Corporation from __future__ import annotations -from typing import Optional - -import attr +from attrs import define from gooddata_api_client.model.filter_by import FilterBy from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogFilterBy(Base): - label_type: Optional[str] + label_type: str | None @staticmethod def client_class() -> type[FilterBy]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/identifier.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/identifier.py index 9e7472df2..74ce352b6 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/identifier.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/identifier.py @@ -3,8 +3,7 @@ import builtins -import attr -from attrs import define +from attrs import define, field from gooddata_api_client.model.assignee_identifier import AssigneeIdentifier from gooddata_api_client.model.dataset_workspace_data_filter_identifier import DatasetWorkspaceDataFilterIdentifier from gooddata_api_client.model.declarative_analytical_dashboard_identifier import ( @@ -25,7 +24,7 @@ from gooddata_sdk.catalog.base import Base, value_in_allowed -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogWorkspaceIdentifier(Base): id: str @@ -34,7 +33,7 @@ def client_class() -> builtins.type[WorkspaceIdentifier]: return WorkspaceIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogReferenceIdentifier(Base): id: str @@ -43,67 +42,67 @@ def client_class() -> builtins.type[ReferenceIdentifier]: return ReferenceIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogGrainIdentifier(Base): id: str - type: str = attr.field(validator=value_in_allowed) + type: str = field(validator=value_in_allowed) @staticmethod def client_class() -> builtins.type[GrainIdentifier]: return GrainIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAssigneeIdentifier(Base): id: str - type: str = attr.field(validator=value_in_allowed) + type: str = field(validator=value_in_allowed) @staticmethod def client_class() -> builtins.type[AssigneeIdentifier]: return AssigneeIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUserGroupIdentifier(Base): id: str - type: str = attr.field(validator=value_in_allowed) + type: str = field(validator=value_in_allowed) @staticmethod def client_class() -> builtins.type[DeclarativeUserGroupIdentifier]: return DeclarativeUserGroupIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserIdentifier(Base): id: str - type: str = attr.field(validator=value_in_allowed) + type: str = field(validator=value_in_allowed) @staticmethod def client_class() -> builtins.type[DeclarativeUserIdentifier]: return DeclarativeUserIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogFactIdentifier(Base): id: str - type: str = attr.field(validator=value_in_allowed) + type: str = field(validator=value_in_allowed) @staticmethod def client_class() -> builtins.type[FactIdentifier]: return FactIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogLabelIdentifier(Base): id: str - type: str = attr.field(validator=value_in_allowed) + type: str = field(validator=value_in_allowed) @staticmethod def client_class() -> builtins.type[LabelIdentifier]: return LabelIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDatasetWorkspaceDataFilterIdentifier(Base): id: str @@ -112,7 +111,7 @@ def client_class() -> builtins.type[DatasetWorkspaceDataFilterIdentifier]: return DatasetWorkspaceDataFilterIdentifier -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogExportDefinitionIdentifier(Base): id: str @@ -121,7 +120,7 @@ def client_class() -> builtins.type[DeclarativeExportDefinitionIdentifier]: return DeclarativeExportDefinitionIdentifier -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogNotificationChannelIdentifier(Base): id: str @@ -130,10 +129,10 @@ def client_class() -> builtins.type[DeclarativeNotificationChannelIdentifier]: return DeclarativeNotificationChannelIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAnalyticalDashboardIdentifier(Base): id: str - type: str = attr.field(validator=value_in_allowed) + type: str = field(validator=value_in_allowed) @staticmethod def client_class() -> builtins.type[DeclarativeAnalyticalDashboardIdentifier]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/dashboard_slides_template.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/dashboard_slides_template.py index 726aca216..2a4fc7503 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/dashboard_slides_template.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/dashboard_slides_template.py @@ -1,5 +1,5 @@ # (C) 2025 GoodData Corporation -from typing import Literal, Optional +from typing import Literal from attrs import define @@ -14,7 +14,7 @@ @define class CatalogDashboardSlidesTemplate: applied_on: list[Literal["PDF", "PPTX"]] - cover_slide: Optional[CatalogCoverSlideTemplate] = None - intro_slide: Optional[CatalogIntroSlideTemplate] = None - section_slide: Optional[CatalogSectionSlideTemplate] = None - content_slide: Optional[CatalogContentSlideTemplate] = None + cover_slide: CatalogCoverSlideTemplate | None = None + intro_slide: CatalogIntroSlideTemplate | None = None + section_slide: CatalogSectionSlideTemplate | None = None + content_slide: CatalogContentSlideTemplate | None = None diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/running_section.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/running_section.py index 1fdfd65e7..d00b54b6a 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/running_section.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/running_section.py @@ -1,10 +1,9 @@ # (C) 2025 GoodData Corporation -from typing import Optional from attrs import define @define class CatalogRunningSection: - left: Optional[str] = None - right: Optional[str] = None + left: str | None = None + right: str | None = None diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/slide_template.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/slide_template.py index 42af27bfa..6df7545e5 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/slide_template.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/slide_template.py @@ -1,5 +1,4 @@ # (C) 2025 GoodData Corporation -from typing import Optional from attrs import define @@ -10,29 +9,29 @@ @define class CatalogCoverSlideTemplate(Base): background_image: bool - description_field: Optional[str] = None - header: Optional[CatalogRunningSection] = None - footer: Optional[CatalogRunningSection] = None + description_field: str | None = None + header: CatalogRunningSection | None = None + footer: CatalogRunningSection | None = None @define class CatalogIntroSlideTemplate(Base): background_image: bool - title_field: Optional[str] = None - description_field: Optional[str] = None - header: Optional[CatalogRunningSection] = None - footer: Optional[CatalogRunningSection] = None + title_field: str | None = None + description_field: str | None = None + header: CatalogRunningSection | None = None + footer: CatalogRunningSection | None = None @define class CatalogSectionSlideTemplate(Base): background_image: bool - header: Optional[CatalogRunningSection] = None - footer: Optional[CatalogRunningSection] = None + header: CatalogRunningSection | None = None + footer: CatalogRunningSection | None = None @define class CatalogContentSlideTemplate(Base): - description_field: Optional[str] = None - header: Optional[CatalogRunningSection] = None - footer: Optional[CatalogRunningSection] = None + description_field: str | None = None + header: CatalogRunningSection | None = None + footer: CatalogRunningSection | None = None diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/widget_slides_template.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/widget_slides_template.py index 0db000922..14a073fc6 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/widget_slides_template.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/common/widget_slides_template.py @@ -1,5 +1,5 @@ # (C) 2025 GoodData Corporation -from typing import Literal, Optional +from typing import Literal from attrs import define @@ -9,4 +9,4 @@ @define class CatalogWidgetSlidesTemplate: applied_on: list[Literal["PDF", "PPTX"]] - content_slide: Optional[CatalogContentSlideTemplate] = None + content_slide: CatalogContentSlideTemplate | None = None diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/directive.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/directive.py index 8ca43a226..b0bc56cbb 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/directive.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/directive.py @@ -1,14 +1,14 @@ # (C) 2023 GoodData Corporation from __future__ import annotations -import attr +from attrs import define from gooddata_api_client.model.json_api_csp_directive_in import JsonApiCspDirectiveIn from gooddata_api_client.model.json_api_csp_directive_in_attributes import JsonApiCspDirectiveInAttributes from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogCspDirective(Base): id: str attributes: CatalogCspDirectiveAttributes @@ -22,7 +22,7 @@ def client_class() -> type[JsonApiCspDirectiveIn]: return JsonApiCspDirectiveIn -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogCspDirectiveAttributes(Base): sources: list[str] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/export_template.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/export_template.py index f66734682..5ed6f9ea5 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/export_template.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/export_template.py @@ -2,7 +2,6 @@ from __future__ import annotations import builtins -from typing import Optional from attrs import define from gooddata_api_client.model.json_api_export_template_in_attributes import JsonApiExportTemplateInAttributes @@ -13,21 +12,21 @@ from gooddata_sdk.catalog.organization.common.widget_slides_template import CatalogWidgetSlidesTemplate -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogExportTemplate(Base): id: str - attributes: Optional[CatalogExportTemplateAttributes] = None + attributes: CatalogExportTemplateAttributes | None = None @staticmethod def client_class() -> builtins.type[JsonApiExportTemplatePostOptionalId]: return JsonApiExportTemplatePostOptionalId -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogExportTemplateAttributes(Base): name: str - dashboard_slides_template: Optional[CatalogDashboardSlidesTemplate] = None - widget_slides_template: Optional[CatalogWidgetSlidesTemplate] = None + dashboard_slides_template: CatalogDashboardSlidesTemplate | None = None + widget_slides_template: CatalogWidgetSlidesTemplate | None = None @staticmethod def client_class() -> builtins.type[JsonApiExportTemplateInAttributes]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/identity_provider.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/identity_provider.py index 0e850ff3e..18e5b7bbe 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/identity_provider.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/identity_provider.py @@ -1,9 +1,9 @@ # (C) 2024 GoodData Corporation from __future__ import annotations -from typing import Any, Optional +from typing import Any -import attr +from attrs import define from gooddata_api_client.model.json_api_identity_provider_in import JsonApiIdentityProviderIn from gooddata_api_client.model.json_api_identity_provider_in_attributes import JsonApiIdentityProviderInAttributes from gooddata_api_client.model.json_api_identity_provider_in_document import JsonApiIdentityProviderInDocument @@ -14,7 +14,7 @@ from gooddata_sdk.utils import safeget -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogIdentityProviderDocument(Base): data: CatalogIdentityProvider @@ -23,10 +23,10 @@ def client_class() -> type[JsonApiIdentityProviderInDocument]: return JsonApiIdentityProviderInDocument -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogIdentityProvider(Base): id: str - attributes: Optional[CatalogIdentityProviderAttributes] = None + attributes: CatalogIdentityProviderAttributes | None = None @staticmethod def client_class() -> type[JsonApiIdentityProviderIn]: @@ -36,17 +36,17 @@ def client_class() -> type[JsonApiIdentityProviderIn]: def init( cls, identity_provider_id: str, - custom_claim_mapping: Optional[dict[str, str]] = None, - identifiers: Optional[list[str]] = None, - oauth_client_id: Optional[str] = None, - oauth_client_secret: Optional[str] = None, - oauth_issuer_location: Optional[str] = None, - saml_metadata: Optional[str] = None, - idp_type: Optional[str] = None, - oauth_issuer_id: Optional[str] = None, - oauth_subject_id_claim: Optional[str] = None, - oauth_custom_auth_attributes: Optional[dict[str, str]] = None, - oauth_custom_scopes: Optional[list[str]] = None, + custom_claim_mapping: dict[str, str] | None = None, + identifiers: list[str] | None = None, + oauth_client_id: str | None = None, + oauth_client_secret: str | None = None, + oauth_issuer_location: str | None = None, + saml_metadata: str | None = None, + idp_type: str | None = None, + oauth_issuer_id: str | None = None, + oauth_subject_id_claim: str | None = None, + oauth_custom_auth_attributes: dict[str, str] | None = None, + oauth_custom_scopes: list[str] | None = None, ) -> CatalogIdentityProvider: return cls( id=identity_provider_id, @@ -95,19 +95,19 @@ def to_api_patch(cls, identity_provider_id: str, attributes: dict) -> JsonApiIde ) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogIdentityProviderAttributes(Base): - custom_claim_mapping: Optional[dict[str, str]] = None - identifiers: Optional[list[str]] = None - oauth_client_id: Optional[str] = None - oauth_client_secret: Optional[str] = None - oauth_issuer_location: Optional[str] = None - saml_metadata: Optional[str] = None - idp_type: Optional[str] = None - oauth_issuer_id: Optional[str] = None - oauth_subject_id_claim: Optional[str] = None - oauth_custom_auth_attributes: Optional[dict[str, str]] = None - oauth_custom_scopes: Optional[list[str]] = None + custom_claim_mapping: dict[str, str] | None = None + identifiers: list[str] | None = None + oauth_client_id: str | None = None + oauth_client_secret: str | None = None + oauth_issuer_location: str | None = None + saml_metadata: str | None = None + idp_type: str | None = None + oauth_issuer_id: str | None = None + oauth_subject_id_claim: str | None = None + oauth_custom_auth_attributes: dict[str, str] | None = None + oauth_custom_scopes: list[str] | None = None @staticmethod def client_class() -> type[JsonApiIdentityProviderInAttributes]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/jwk.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/jwk.py index bf93c4b71..7fbb3c121 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/jwk.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/jwk.py @@ -1,9 +1,7 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Optional - -import attr +from attrs import define from gooddata_api_client.model.json_api_jwk_in import JsonApiJwkIn from gooddata_api_client.model.json_api_jwk_in_attributes import JsonApiJwkInAttributes from gooddata_api_client.model.json_api_jwk_in_attributes_content import JsonApiJwkInAttributesContent @@ -12,7 +10,7 @@ from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogJwkDocument(Base): data: CatalogJwk @@ -21,10 +19,10 @@ def client_class() -> type[JsonApiJwkInDocument]: return JsonApiJwkInDocument -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogJwk(Base): id: str - attributes: Optional[CatalogJwkAttributes] = None + attributes: CatalogJwkAttributes | None = None @staticmethod def client_class() -> type[JsonApiJwkIn]: @@ -34,21 +32,21 @@ def client_class() -> type[JsonApiJwkIn]: def init( cls, jwk_id: str, - rsa_spec: Optional[CatalogRsaSpecification] = None, + rsa_spec: CatalogRsaSpecification | None = None, ) -> CatalogJwk: return cls(id=jwk_id, attributes=CatalogJwkAttributes(content=rsa_spec)) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogJwkAttributes(Base): - content: Optional[CatalogRsaSpecification] = None + content: CatalogRsaSpecification | None = None @staticmethod def client_class() -> type[JsonApiJwkInAttributes]: return JsonApiJwkInAttributes -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogRsaSpecification(Base): alg: str e: str diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/llm_endpoint.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/llm_endpoint.py index 24dbd9295..2d4297a21 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/llm_endpoint.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/llm_endpoint.py @@ -1,7 +1,7 @@ # (C) 2024 GoodData Corporation from __future__ import annotations -from typing import Any, Optional +from typing import Any from attr import define from gooddata_api_client.model.json_api_llm_endpoint_in import JsonApiLlmEndpointIn @@ -36,7 +36,7 @@ def client_class() -> type[JsonApiLlmEndpointPatchDocument]: @define(kw_only=True) class CatalogLlmEndpoint(Base): id: str - attributes: Optional[CatalogLlmEndpointAttributes] = None + attributes: CatalogLlmEndpointAttributes | None = None @staticmethod def client_class() -> type[JsonApiLlmEndpointIn]: @@ -48,10 +48,10 @@ def init( id: str, title: str, token: str, - provider: Optional[str] = None, - base_url: Optional[str] = None, - llm_organization: Optional[str] = None, - llm_model: Optional[str] = None, + provider: str | None = None, + base_url: str | None = None, + llm_organization: str | None = None, + llm_model: str | None = None, ) -> CatalogLlmEndpoint: return cls( id=id, @@ -85,7 +85,7 @@ def from_api(cls, entity: dict[str, Any]) -> CatalogLlmEndpoint: @define(kw_only=True) class CatalogLlmEndpointPatch(Base): id: str - attributes: Optional[CatalogLlmEndpointPatchAttributes] = None + attributes: CatalogLlmEndpointPatchAttributes | None = None @staticmethod def client_class() -> type[JsonApiLlmEndpointPatch]: @@ -95,12 +95,12 @@ def client_class() -> type[JsonApiLlmEndpointPatch]: def init( cls, id: str, - title: Optional[str] = None, - token: Optional[str] = None, - provider: Optional[str] = None, - base_url: Optional[str] = None, - llm_organization: Optional[str] = None, - llm_model: Optional[str] = None, + title: str | None = None, + token: str | None = None, + provider: str | None = None, + base_url: str | None = None, + llm_organization: str | None = None, + llm_model: str | None = None, ) -> CatalogLlmEndpointPatch: return cls( id=id, @@ -119,10 +119,10 @@ def init( class CatalogLlmEndpointAttributes(Base): title: str token: str - provider: Optional[str] = None - base_url: Optional[str] = None - llm_organization: Optional[str] = None - llm_model: Optional[str] = None + provider: str | None = None + base_url: str | None = None + llm_organization: str | None = None + llm_model: str | None = None @staticmethod def client_class() -> type[JsonApiLlmEndpointInAttributes]: @@ -131,12 +131,12 @@ def client_class() -> type[JsonApiLlmEndpointInAttributes]: @define(kw_only=True) class CatalogLlmEndpointPatchAttributes(Base): - title: Optional[str] = None - token: Optional[str] = None - provider: Optional[str] = None - base_url: Optional[str] = None - llm_organization: Optional[str] = None - llm_model: Optional[str] = None + title: str | None = None + token: str | None = None + provider: str | None = None + base_url: str | None = None + llm_organization: str | None = None + llm_model: str | None = None @staticmethod def client_class() -> type[JsonApiLlmEndpointPatchAttributes]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/organization.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/organization.py index 765afc3fc..10eff128f 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/organization.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/organization.py @@ -1,9 +1,9 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Any, Optional +from typing import Any -import attr +from attrs import define from gooddata_api_client.model.json_api_identity_provider_to_one_linkage import JsonApiIdentityProviderToOneLinkage from gooddata_api_client.model.json_api_organization_in import JsonApiOrganizationIn from gooddata_api_client.model.json_api_organization_in_attributes import JsonApiOrganizationInAttributes @@ -17,7 +17,7 @@ from gooddata_sdk.utils import safeget -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogOrganizationDocument(Base): data: CatalogOrganization @@ -25,18 +25,18 @@ class CatalogOrganizationDocument(Base): def client_class() -> type[JsonApiOrganizationInDocument]: return JsonApiOrganizationInDocument - def to_api(self, oauth_client_secret: Optional[str] = None) -> JsonApiOrganizationInDocument: + def to_api(self, oauth_client_secret: str | None = None) -> JsonApiOrganizationInDocument: dictionary = self._get_snake_dict() if oauth_client_secret is not None: dictionary["data"]["attributes"]["oauth_client_secret"] = oauth_client_secret return self.client_class().from_dict(dictionary, camel_case=False) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogOrganization(Base): id: str attributes: CatalogOrganizationAttributes - identity_provider_id: Optional[str] = None + identity_provider_id: str | None = None @staticmethod def client_class() -> type[JsonApiOrganizationIn]: @@ -80,13 +80,13 @@ def to_api(self) -> JsonApiOrganizationIn: ) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogOrganizationAttributes(Base): - name: Optional[str] = None - hostname: Optional[str] = None - allowed_origins: Optional[list[str]] = None - oauth_issuer_location: Optional[str] = None - oauth_client_id: Optional[str] = None + name: str | None = None + hostname: str | None = None + allowed_origins: list[str] | None = None + oauth_issuer_location: str | None = None + oauth_client_id: str | None = None @staticmethod def client_class() -> type[JsonApiOrganizationInAttributes]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/setting.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/setting.py index fa4fc8f23..dc80b971e 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/setting.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/entity_model/setting.py @@ -2,16 +2,16 @@ from __future__ import annotations import builtins -from typing import Any, Optional +from typing import Any -import attr +from attrs import define from gooddata_api_client.model.json_api_organization_setting_in import JsonApiOrganizationSettingIn from gooddata_api_client.model.json_api_organization_setting_in_attributes import JsonApiOrganizationSettingInAttributes from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogOrganizationSetting(Base): id: str attributes: CatalogOrganizationSettingAttributes @@ -25,9 +25,9 @@ def client_class() -> type[JsonApiOrganizationSettingIn]: return JsonApiOrganizationSettingIn -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogOrganizationSettingAttributes(Base): - type: Optional[str] + type: str | None content: dict[str, Any] @staticmethod diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/export_template.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/export_template.py index ae1fb57dd..8a9ac3217 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/export_template.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/export_template.py @@ -1,6 +1,5 @@ # (C) 2025 GoodData Corporation import builtins -from typing import Optional from attrs import define from gooddata_api_client.model.declarative_export_template import DeclarativeExportTemplate @@ -14,8 +13,8 @@ class CatalogDeclarativeExportTemplate(Base): id: str name: str - dashboard_slides_template: Optional[CatalogDashboardSlidesTemplate] = None - widget_slides_template: Optional[CatalogWidgetSlidesTemplate] = None + dashboard_slides_template: CatalogDashboardSlidesTemplate | None = None + widget_slides_template: CatalogWidgetSlidesTemplate | None = None @staticmethod def client_class() -> builtins.type[DeclarativeExportTemplate]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/identity_provider.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/identity_provider.py index 1a403e7e5..e7e4d6235 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/identity_provider.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/identity_provider.py @@ -1,27 +1,26 @@ # (C) 2024 GoodData Corporation import builtins -from typing import Optional -import attr +from attrs import define from gooddata_api_client.model.declarative_identity_provider import DeclarativeIdentityProvider from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeIdentityProvider(Base): id: str - custom_claim_mapping: Optional[dict[str, str]] = None - identifiers: Optional[list[str]] = None - oauth_client_id: Optional[str] = None - oauth_client_secret: Optional[str] = None - oauth_issuer_location: Optional[str] = None - saml_metadata: Optional[str] = None - idp_type: Optional[str] = None - oauth_issuer_id: Optional[str] = None - oauth_subject_id_claim: Optional[str] = None - oauth_custom_auth_attributes: Optional[dict[str, str]] = None - oauth_custom_scopes: Optional[list[str]] = None + custom_claim_mapping: dict[str, str] | None = None + identifiers: list[str] | None = None + oauth_client_id: str | None = None + oauth_client_secret: str | None = None + oauth_issuer_location: str | None = None + saml_metadata: str | None = None + idp_type: str | None = None + oauth_issuer_id: str | None = None + oauth_subject_id_claim: str | None = None + oauth_custom_auth_attributes: dict[str, str] | None = None + oauth_custom_scopes: list[str] | None = None @staticmethod def client_class() -> builtins.type[DeclarativeIdentityProvider]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/notification_channel.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/notification_channel.py index a74e8d0b1..d169d3167 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/notification_channel.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/layout/notification_channel.py @@ -1,6 +1,5 @@ # (C) 2024 GoodData Corporation import builtins -from typing import Optional from attrs import define, field from gooddata_api_client.model.declarative_notification_channel import DeclarativeNotificationChannel @@ -10,7 +9,7 @@ # TODO: there is an issue with generated client which causes these two classes to fail # type in gooddata_api_client/model/declarative_notification_channel_destination.py contains only WEBHOOK as valid value -# @define(auto_attribs=True, kw_only=True) +# @define(kw_only=True) # class CatalogDefaultSmtp(Base): # from_email: Optional[str] = None # from_email_name: Optional[str] = None @@ -20,7 +19,7 @@ # return DefaultSmtp # # -# @define(auto_attribs=True, kw_only=True) +# @define(kw_only=True) # class CatalogSmtp(Base): # from_email: Optional[str] = None # from_email_name: Optional[str] = None @@ -34,28 +33,28 @@ # return Smtp -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogWebhook(Base): type: str = field(default="WEBHOOK", init=False) url: str - token: Optional[str] = field(default=None, eq=False) - has_token: Optional[bool] = field(default=None, eq=False) + token: str | None = field(default=None, eq=False) + has_token: bool | None = field(default=None, eq=False) @staticmethod def client_class() -> builtins.type[Webhook]: return Webhook -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeNotificationChannel(Base): id: str - name: Optional[str] = None - description: Optional[str] = None - destination_type: Optional[str] = None - custom_dashboard_url: Optional[str] = None - allowed_recipients: Optional[str] = None + name: str | None = None + description: str | None = None + destination_type: str | None = None + custom_dashboard_url: str | None = None + allowed_recipients: str | None = None # destination: Optional[Union[CatalogDefaultSmtp, CatalogSmtp, CatalogWebhook]] = None - destination: Optional[CatalogWebhook] = None + destination: CatalogWebhook | None = None @staticmethod def client_class() -> builtins.type[DeclarativeNotificationChannel]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/service.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/service.py index eedc3dc92..615ef4529 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/service.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/organization/service.py @@ -2,7 +2,7 @@ from __future__ import annotations import functools -from typing import Any, Optional +from typing import Any from gooddata_api_client.exceptions import NotFoundException from gooddata_api_client.model.declarative_export_templates import DeclarativeExportTemplates @@ -513,11 +513,11 @@ def get_llm_endpoint(self, id: str) -> CatalogLlmEndpoint: def list_llm_endpoints( self, - filter: Optional[str] = None, - page: Optional[int] = None, - size: Optional[int] = None, - sort: Optional[list[str]] = None, - meta_include: Optional[list[str]] = None, + filter: str | None = None, + page: int | None = None, + size: int | None = None, + sort: list[str] | None = None, + meta_include: list[str] | None = None, ) -> list[CatalogLlmEndpoint]: """ List all LLM endpoints. @@ -556,10 +556,10 @@ def create_llm_endpoint( id: str, title: str, token: str, - provider: Optional[str] = None, - base_url: Optional[str] = None, - llm_organization: Optional[str] = None, - llm_model: Optional[str] = None, + provider: str | None = None, + base_url: str | None = None, + llm_organization: str | None = None, + llm_model: str | None = None, ) -> CatalogLlmEndpoint: """ Create a new LLM endpoint. @@ -594,12 +594,12 @@ def create_llm_endpoint( def update_llm_endpoint( self, id: str, - title: Optional[str] = None, - token: Optional[str] = None, - provider: Optional[str] = None, - base_url: Optional[str] = None, - llm_organization: Optional[str] = None, - llm_model: Optional[str] = None, + title: str | None = None, + token: str | None = None, + provider: str | None = None, + base_url: str | None = None, + llm_organization: str | None = None, + llm_model: str | None = None, ) -> CatalogLlmEndpoint: """ Update an existing LLM endpoint. diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/parameter.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/parameter.py index ff02ce4a7..4d2d52ef2 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/parameter.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/parameter.py @@ -1,12 +1,12 @@ # (C) 2022 GoodData Corporation -import attr +from attrs import define from gooddata_api_client.model.data_source_parameter import DataSourceParameter from gooddata_api_client.model.parameter import Parameter from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogParameter(Base): name: str value: str diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/dashboard_assignees.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/dashboard_assignees.py index d3cd217d6..0cd38583c 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/dashboard_assignees.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/dashboard_assignees.py @@ -1,7 +1,6 @@ # (C) 2023 GoodData Corporation -from typing import Optional -import attr +from attrs import define from gooddata_api_client.model.available_assignees import AvailableAssignees from gooddata_api_client.model.user_assignee import UserAssignee from gooddata_api_client.model.user_group_assignee import UserGroupAssignee @@ -9,28 +8,28 @@ from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserAssignee(Base): id: str - name: Optional[str] = None - email: Optional[str] = None + name: str | None = None + email: str | None = None @staticmethod def client_class() -> type[UserAssignee]: return UserAssignee -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserGroupAssignee(Base): id: str - name: Optional[str] = None + name: str | None = None @staticmethod def client_class() -> type[UserGroupAssignee]: return UserGroupAssignee -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAvailableAssignees(Base): user_groups: list[CatalogUserGroupAssignee] users: list[CatalogUserAssignee] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/dashboard_permissions.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/dashboard_permissions.py index 1dac059bc..4c15ad261 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/dashboard_permissions.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/dashboard_permissions.py @@ -1,8 +1,7 @@ # (C) 2023 GoodData Corporation import builtins -from typing import Optional -import attr +from attrs import define from gooddata_api_client.model.dashboard_permissions import DashboardPermissions from gooddata_api_client.model.granted_permission import GrantedPermission from gooddata_api_client.model.rule_permission import RulePermission @@ -12,7 +11,7 @@ from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogGrantedPermission(Base): level: str source: str @@ -22,40 +21,40 @@ def client_class() -> type[GrantedPermission]: return GrantedPermission -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserPermission(Base): id: str - name: Optional[str] = None - email: Optional[str] = None - permissions: Optional[list[CatalogGrantedPermission]] = None + name: str | None = None + email: str | None = None + permissions: list[CatalogGrantedPermission] | None = None @staticmethod def client_class() -> type[UserPermission]: return UserPermission -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserGroupPermission(Base): id: str - name: Optional[str] = None - permissions: Optional[list[CatalogGrantedPermission]] = None + name: str | None = None + permissions: list[CatalogGrantedPermission] | None = None @staticmethod def client_class() -> type[UserGroupPermission]: return UserGroupPermission -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogRulePermission(Base): type: str - permissions: Optional[list[str]] = None + permissions: list[str] | None = None @staticmethod def client_class() -> builtins.type[RulePermission]: # noqa: UP006 return RulePermission -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDashboardPermissions(Base): rules: list[CatalogRulePermission] user_groups: list[CatalogUserGroupPermission] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/manage_dashboard_permissions.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/manage_dashboard_permissions.py index 8b2194280..db136ff52 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/manage_dashboard_permissions.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/manage_dashboard_permissions.py @@ -1,5 +1,5 @@ # (C) 2023 GoodData Corporation -import attr +from attrs import define, field from gooddata_api_client.model.manage_dashboard_permissions_request_inner import ManageDashboardPermissionsRequestInner from gooddata_sdk.catalog.base import Base @@ -8,14 +8,14 @@ # Kept for backward compatibility only -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDashboardAssigneeIdentifier(CatalogAssigneeIdentifier): pass -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogPermissionsForAssigneeIdentifier(Base): - permissions: list[str] = attr.field(factory=list) + permissions: list[str] = field(factory=list) assignee_identifier: CatalogAssigneeIdentifier @staticmethod @@ -23,9 +23,9 @@ def client_class() -> type[ManageDashboardPermissionsRequestInner]: return ManageDashboardPermissionsRequestInner -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogPermissionsForAssigneeRule(Base): - permissions: list[str] = attr.field(factory=list) + permissions: list[str] = field(factory=list) assignee_rule: CatalogAssigneeRule @staticmethod diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/permission.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/permission.py index c6dcbebef..89c1362ed 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/permission.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/permission/declarative_model/permission.py @@ -1,7 +1,7 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -import attr +from attrs import define, field from gooddata_api_client.model.declarative_analytical_dashboard_permission_for_assignee import ( DeclarativeAnalyticalDashboardPermissionForAssignee, ) @@ -20,9 +20,9 @@ from gooddata_sdk.catalog.rule import CatalogAssigneeRule -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeSingleWorkspacePermission(Base): - name: str = attr.field(validator=value_in_allowed) + name: str = field(validator=value_in_allowed) assignee: CatalogAssigneeIdentifier @staticmethod @@ -30,9 +30,9 @@ def client_class() -> type[DeclarativeSingleWorkspacePermission]: return DeclarativeSingleWorkspacePermission -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspaceHierarchyPermission(Base): - name: str = attr.field(validator=value_in_allowed) + name: str = field(validator=value_in_allowed) assignee: CatalogAssigneeIdentifier @staticmethod @@ -40,9 +40,9 @@ def client_class() -> type[DeclarativeWorkspaceHierarchyPermission]: return DeclarativeWorkspaceHierarchyPermission -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDataSourcePermission(Base): - name: str = attr.field(validator=value_in_allowed) + name: str = field(validator=value_in_allowed) assignee: CatalogAssigneeIdentifier @staticmethod @@ -50,19 +50,19 @@ def client_class() -> type[DeclarativeDataSourcePermission]: return DeclarativeDataSourcePermission -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspacePermissions(Base): - permissions: list[CatalogDeclarativeSingleWorkspacePermission] = attr.field(factory=list) - hierarchy_permissions: list[CatalogDeclarativeWorkspaceHierarchyPermission] = attr.field(factory=list) + permissions: list[CatalogDeclarativeSingleWorkspacePermission] = field(factory=list) + hierarchy_permissions: list[CatalogDeclarativeWorkspaceHierarchyPermission] = field(factory=list) @staticmethod def client_class() -> type[DeclarativeWorkspacePermissions]: return DeclarativeWorkspacePermissions -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDashboardPermissionsForAssignee(Base): - name: str = attr.field(validator=value_in_allowed) + name: str = field(validator=value_in_allowed) assignee: CatalogAssigneeIdentifier @staticmethod @@ -70,9 +70,9 @@ def client_class() -> type[DeclarativeAnalyticalDashboardPermissionForAssignee]: return DeclarativeAnalyticalDashboardPermissionForAssignee -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDashboardPermissionsForAssigneeRule(Base): - name: str = attr.field(validator=value_in_allowed) + name: str = field(validator=value_in_allowed) assignee_rule: CatalogAssigneeRule @staticmethod @@ -80,9 +80,9 @@ def client_class() -> type[DeclarativeAnalyticalDashboardPermissionForAssigneeRu return DeclarativeAnalyticalDashboardPermissionForAssigneeRule -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeOrganizationPermission(Base): - name: str = attr.field(validator=value_in_allowed) + name: str = field(validator=value_in_allowed) assignee: CatalogAssigneeIdentifier @staticmethod @@ -90,10 +90,10 @@ def client_class() -> type[DeclarativeOrganizationPermission]: return DeclarativeOrganizationPermission -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogOrganizationPermissionAssignment(Base): assignee_identifier: CatalogAssigneeIdentifier - permissions: list[str] = attr.field(factory=list) + permissions: list[str] = field(factory=list) @staticmethod def client_class() -> type[OrganizationPermissionAssignment]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/rule.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/rule.py index 086b8fa5f..c878582b9 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/rule.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/rule.py @@ -3,15 +3,15 @@ import builtins -import attr +from attrs import define, field from gooddata_api_client.model.assignee_rule import AssigneeRule from gooddata_sdk.catalog.base import Base, value_in_allowed -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAssigneeRule(Base): - type: str = attr.field(validator=value_in_allowed) + type: str = field(validator=value_in_allowed) @staticmethod def client_class() -> builtins.type[AssigneeRule]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/setting.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/setting.py index eda818e14..cf8072de2 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/setting.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/setting.py @@ -2,27 +2,27 @@ from __future__ import annotations import builtins -from typing import Any, Optional +from typing import Any -import attr +from attrs import define, field from gooddata_api_client.model.declarative_custom_application_setting import DeclarativeCustomApplicationSetting from gooddata_api_client.model.declarative_setting import DeclarativeSetting from gooddata_sdk.catalog.base import Base, value_in_allowed -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeSetting(Base): id: str - type: str = attr.field(validator=value_in_allowed) - content: Optional[dict[str, Any]] = None + type: str = field(validator=value_in_allowed) + content: dict[str, Any] | None = None @staticmethod def client_class() -> builtins.type[DeclarativeSetting]: return DeclarativeSetting -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeCustomApplicationSetting(Base): id: str content: dict[str, Any] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user.py index ebabafd0b..f6c9cd3e4 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user.py @@ -2,9 +2,8 @@ from __future__ import annotations from pathlib import Path -from typing import Optional -import attr +from attrs import define, field from gooddata_api_client.model.declarative_user import DeclarativeUser from gooddata_api_client.model.declarative_user_permission import DeclarativeUserPermission from gooddata_api_client.model.declarative_users import DeclarativeUsers @@ -18,7 +17,7 @@ LAYOUT_USERS_FILE = "users.yaml" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUsers(Base): users: list[CatalogDeclarativeUser] @@ -42,25 +41,25 @@ def store_to_disk(self, layout_organization_folder: Path, sort: bool = False) -> write_layout_to_file(users_file, users, sort=sort) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUser(Base): id: str - email: Optional[str] = None - firstname: Optional[str] = None - lastname: Optional[str] = None - auth_id: Optional[str] = None - user_groups: list[CatalogDeclarativeUserGroupIdentifier] = attr.field(factory=list) - settings: list[CatalogDeclarativeSetting] = attr.field(factory=list) - permissions: list[CatalogDeclarativeUserPermission] = attr.field(factory=list) + email: str | None = None + firstname: str | None = None + lastname: str | None = None + auth_id: str | None = None + user_groups: list[CatalogDeclarativeUserGroupIdentifier] = field(factory=list) + settings: list[CatalogDeclarativeSetting] = field(factory=list) + permissions: list[CatalogDeclarativeUserPermission] = field(factory=list) @staticmethod def client_class() -> type[DeclarativeUser]: return DeclarativeUser -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUserPermission(Base): - name: str = attr.field(validator=value_in_allowed) + name: str = field(validator=value_in_allowed) assignee: CatalogAssigneeIdentifier @staticmethod diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user_and_user_groups.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user_and_user_groups.py index 7222b425e..ea9eecc0a 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user_and_user_groups.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user_and_user_groups.py @@ -3,7 +3,7 @@ from pathlib import Path -import attr +from attrs import define from gooddata_api_client.model.declarative_users_user_groups import DeclarativeUsersUserGroups from gooddata_sdk.catalog.base import Base @@ -14,7 +14,7 @@ ) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUsersUserGroups(Base): users: list[CatalogDeclarativeUser] user_groups: list[CatalogDeclarativeUserGroup] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user_group.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user_group.py index da514ca8d..4cc0524b7 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user_group.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/declarative_model/user_group.py @@ -2,9 +2,8 @@ from __future__ import annotations from pathlib import Path -from typing import Optional -import attr +from attrs import define, field from gooddata_api_client.model.declarative_user_group import DeclarativeUserGroup from gooddata_api_client.model.declarative_user_group_permission import DeclarativeUserGroupPermission from gooddata_api_client.model.declarative_user_groups import DeclarativeUserGroups @@ -17,9 +16,9 @@ LAYOUT_USER_GROUPS_FILE = "user_groups.yaml" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUserGroups(Base): - user_groups: list[CatalogDeclarativeUserGroup] = attr.field(factory=list) + user_groups: list[CatalogDeclarativeUserGroup] = field(factory=list) @staticmethod def client_class() -> type[DeclarativeUserGroups]: @@ -41,21 +40,21 @@ def store_to_disk(self, layout_organization_folder: Path, sort: bool = False) -> write_layout_to_file(user_groups_file, user_groups, sort=sort) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUserGroup(Base): id: str - name: Optional[str] = None - parents: Optional[list[CatalogDeclarativeUserGroupIdentifier]] = None - permissions: list[CatalogDeclarativeUserGroupPermission] = attr.field(factory=list) + name: str | None = None + parents: list[CatalogDeclarativeUserGroupIdentifier] | None = None + permissions: list[CatalogDeclarativeUserGroupPermission] = field(factory=list) @staticmethod def client_class() -> type[DeclarativeUserGroup]: return DeclarativeUserGroup -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUserGroupPermission(Base): - name: str = attr.field(validator=value_in_allowed) + name: str = field(validator=value_in_allowed) assignee: CatalogAssigneeIdentifier @staticmethod diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/api_token.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/api_token.py index 9fcac8f5f..7b62fa20a 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/api_token.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/api_token.py @@ -1,12 +1,11 @@ # (C) 2024 GoodData Corporation -from typing import Optional from attrs import define from gooddata_sdk.catalog.base import Base -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogApiToken(Base): id: str - bearer_token: Optional[str] = None + bearer_token: str | None = None diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/user.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/user.py index cd35fa770..aae4e2547 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/user.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/user.py @@ -1,9 +1,7 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Optional - -import attr +from attrs import define, field from gooddata_api_client.model.json_api_user_in import JsonApiUserIn from gooddata_api_client.model.json_api_user_in_document import JsonApiUserInDocument @@ -11,7 +9,7 @@ from gooddata_sdk.catalog.user.entity_model.user_group import CatalogUserGroup -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserDocument(Base): data: CatalogUser @@ -23,11 +21,11 @@ def client_class() -> type[JsonApiUserInDocument]: def init( cls, user_id: str, - firstname: Optional[str] = None, - lastname: Optional[str] = None, - email: Optional[str] = None, - authentication_id: Optional[str] = None, - user_group_ids: Optional[list[str]] = None, + firstname: str | None = None, + lastname: str | None = None, + email: str | None = None, + authentication_id: str | None = None, + user_group_ids: list[str] | None = None, ) -> CatalogUserDocument: user = CatalogUser.init( user_id=user_id, @@ -42,11 +40,11 @@ def init( def update_user( self, - firstname: Optional[str] = None, - lastname: Optional[str] = None, - email: Optional[str] = None, - authentication_id: Optional[str] = None, - user_group_ids: Optional[list[str]] = None, + firstname: str | None = None, + lastname: str | None = None, + email: str | None = None, + authentication_id: str | None = None, + user_group_ids: list[str] | None = None, ) -> None: attributes = CatalogUserAttributes( firstname=firstname, lastname=lastname, email=email, authentication_id=authentication_id @@ -56,11 +54,11 @@ def update_user( self.data.relationships = relationships -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUser(Base): id: str - attributes: Optional[CatalogUserAttributes] = None - relationships: Optional[CatalogUserRelationships] = None + attributes: CatalogUserAttributes | None = None + relationships: CatalogUserRelationships | None = None @staticmethod def client_class() -> type[JsonApiUserIn]: @@ -70,11 +68,11 @@ def client_class() -> type[JsonApiUserIn]: def init( cls, user_id: str, - firstname: Optional[str] = None, - lastname: Optional[str] = None, - email: Optional[str] = None, - authentication_id: Optional[str] = None, - user_group_ids: Optional[list[str]] = None, + firstname: str | None = None, + lastname: str | None = None, + email: str | None = None, + authentication_id: str | None = None, + user_group_ids: list[str] | None = None, ) -> CatalogUser: attributes = CatalogUserAttributes( firstname=firstname, lastname=lastname, email=email, authentication_id=authentication_id @@ -146,17 +144,17 @@ def replace_user_groups(self, user_groups: list[CatalogUserGroup]) -> None: self.relationships.replace_user_groups(user_groups) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserAttributes(Base): - firstname: Optional[str] = None - lastname: Optional[str] = None - email: Optional[str] = None - authentication_id: Optional[str] = None + firstname: str | None = None + lastname: str | None = None + email: str | None = None + authentication_id: str | None = None -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserRelationships(Base): - user_groups: Optional[CatalogUserGroupsData] = None + user_groups: CatalogUserGroupsData | None = None def add_user_groups(self, user_groups: list[CatalogUserGroup]) -> None: """Appends the User Groups to the existing list. @@ -187,7 +185,7 @@ def replace_user_groups(self, user_groups: list[CatalogUserGroup]) -> None: self.user_groups.data = user_groups @classmethod - def create_user_relationships(cls, user_group_ids: Optional[list[str]]) -> CatalogUserRelationships: + def create_user_relationships(cls, user_group_ids: list[str] | None) -> CatalogUserRelationships: user_groups = None if user_group_ids is not None: user_groups = CatalogUserGroupsData( @@ -196,6 +194,6 @@ def create_user_relationships(cls, user_group_ids: Optional[list[str]]) -> Catal return cls(user_groups=user_groups) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserGroupsData(Base): - data: list[CatalogUserGroup] = attr.field(factory=list) + data: list[CatalogUserGroup] = field(factory=list) diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/user_group.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/user_group.py index 03dd40e03..ce801f7d6 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/user_group.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/entity_model/user_group.py @@ -1,16 +1,14 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Optional - -import attr +from attrs import define from gooddata_api_client.model.json_api_user_group_in import JsonApiUserGroupIn from gooddata_api_client.model.json_api_user_group_in_document import JsonApiUserGroupInDocument from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserGroupDocument(Base): data: CatalogUserGroup @@ -19,19 +17,19 @@ def client_class() -> type[JsonApiUserGroupInDocument]: return JsonApiUserGroupInDocument @classmethod - def init(cls, user_group_id: str, user_group_parent_ids: Optional[list[str]] = None) -> CatalogUserGroupDocument: + def init(cls, user_group_id: str, user_group_parent_ids: list[str] | None = None) -> CatalogUserGroupDocument: return cls(data=CatalogUserGroup.init(user_group_id=user_group_id, user_group_parent_ids=user_group_parent_ids)) - def update_user_group(self, user_group_parents_id: Optional[list[str]] = None) -> None: + def update_user_group(self, user_group_parents_id: list[str] | None = None) -> None: relationships = CatalogUserGroupRelationships.create_user_group_relationships(user_group_parents_id) self.data.relationships = relationships -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserGroup(Base): id: str - attributes: Optional[CatalogUserGroupAttributes] = None - relationships: Optional[CatalogUserGroupRelationships] = None + attributes: CatalogUserGroupAttributes | None = None + relationships: CatalogUserGroupRelationships | None = None @staticmethod def client_class() -> type[JsonApiUserGroupIn]: @@ -41,8 +39,8 @@ def client_class() -> type[JsonApiUserGroupIn]: def init( cls, user_group_id: str, - user_group_name: Optional[str] = None, - user_group_parent_ids: Optional[list[str]] = None, + user_group_name: str | None = None, + user_group_parent_ids: list[str] | None = None, ) -> CatalogUserGroup: attributes = CatalogUserGroupAttributes(name=user_group_name) relationships = CatalogUserGroupRelationships.create_user_group_relationships(user_group_parent_ids) @@ -53,20 +51,18 @@ def get_parents(self) -> list[str]: return self.relationships.get_parents if self.relationships is not None else [] @property - def name(self) -> Optional[str]: + def name(self) -> str | None: if self.attributes is not None: return self.attributes.name return None -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserGroupRelationships(Base): - parents: Optional[CatalogUserGroupParents] = None + parents: CatalogUserGroupParents | None = None @classmethod - def create_user_group_relationships( - cls, user_group_parent_ids: Optional[list[str]] - ) -> CatalogUserGroupRelationships: + def create_user_group_relationships(cls, user_group_parent_ids: list[str] | None) -> CatalogUserGroupRelationships: parents = None if user_group_parent_ids is not None: parents = CatalogUserGroupParents( @@ -79,14 +75,14 @@ def get_parents(self) -> list[str]: return self.parents.get_parents if self.parents is not None else [] -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserGroupAttributes(Base): - name: Optional[str] = None + name: str | None = None -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserGroupParents(Base): - data: Optional[list[CatalogUserGroup]] = None + data: list[CatalogUserGroup] | None = None @property def get_parents(self) -> list[str]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/management_model/management.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/management_model/management.py index 24ff3f6b1..4082d8d20 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/management_model/management.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/user/management_model/management.py @@ -1,8 +1,7 @@ # (C) 2024 GoodData Corporation -from typing import Optional -import attrs +from attrs import define, field from gooddata_api_client.model.permissions_assignment import PermissionsAssignment from gooddata_api_client.model.user_management_data_source_permission_assignment import ( UserManagementDataSourcePermissionAssignment, @@ -16,44 +15,44 @@ from gooddata_sdk.catalog.identifier import CatalogAssigneeIdentifier -@attrs.define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourcePermissionAssignment(Base): id: str - permissions: list[str] = attrs.field(factory=list) - name: Optional[str] = None + permissions: list[str] = field(factory=list) + name: str | None = None @staticmethod def client_class() -> type[UserManagementDataSourcePermissionAssignment]: return UserManagementDataSourcePermissionAssignment -@attrs.define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogWorkspacePermissionAssignment(Base): id: str - permissions: list[str] = attrs.field(factory=list) - hierarchy_permissions: list[str] = attrs.field(factory=list) - name: Optional[str] = None + permissions: list[str] = field(factory=list) + hierarchy_permissions: list[str] = field(factory=list) + name: str | None = None @staticmethod def client_class() -> type[UserManagementWorkspacePermissionAssignment]: return UserManagementWorkspacePermissionAssignment -@attrs.define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogPermissionAssignments(Base): - workspaces: list[CatalogWorkspacePermissionAssignment] = attrs.field(factory=list) - data_sources: list[CatalogDataSourcePermissionAssignment] = attrs.field(factory=list) + workspaces: list[CatalogWorkspacePermissionAssignment] = field(factory=list) + data_sources: list[CatalogDataSourcePermissionAssignment] = field(factory=list) @staticmethod def client_class() -> type[UserManagementPermissionAssignments]: return UserManagementPermissionAssignments -@attrs.define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogPermissionsAssignment(Base): assignees: list[CatalogAssigneeIdentifier] - workspaces: list[CatalogWorkspacePermissionAssignment] = attrs.field(factory=list) - data_sources: list[CatalogDataSourcePermissionAssignment] = attrs.field(factory=list) + workspaces: list[CatalogWorkspacePermissionAssignment] = field(factory=list) + data_sources: list[CatalogDataSourcePermissionAssignment] = field(factory=list) @staticmethod def client_class() -> type[PermissionsAssignment]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/validate_by_item.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/validate_by_item.py index defc7f3cd..35fac15cc 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/validate_by_item.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/validate_by_item.py @@ -3,13 +3,13 @@ import builtins -import attr +from attrs import define from gooddata_api_client.model.validate_by_item import ValidateByItem from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogValidateByItem(Base): id: str type: str 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 3ef308bfe..7be97bee2 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 @@ -4,7 +4,7 @@ import copy import functools from pathlib import Path -from typing import Literal, Optional, Union, cast +from typing import Literal, Union, cast import gooddata_api_client.models as afm_models from gooddata_api_client.model.elements_request import ElementsRequest @@ -105,7 +105,7 @@ def get_full_catalog(self, workspace_id: str, inject_valid_objects_func: bool = return CatalogWorkspaceContent.create_workspace_content_catalog(valid_obj_fun, datasets, attributes, metrics) def get_attributes_catalog( - self, workspace_id: str, include: Optional[list[str]] = None, rsql_filter: Optional[str] = None + self, workspace_id: str, include: list[str] | None = None, rsql_filter: str | None = None ) -> list[CatalogAttribute]: """Retrieve all attributes in a given workspace. @@ -270,7 +270,7 @@ def put_declarative_ldm( self, workspace_id: str, ldm: CatalogDeclarativeModel, - validator: Optional[DataSourceValidator] = None, + validator: DataSourceValidator | None = None, standalone_copy: bool = False, ) -> None: """Set declarative logical data model for a given workspace. @@ -334,7 +334,7 @@ def load_and_put_declarative_ldm( self, workspace_id: str, layout_root_path: Path = Path.cwd(), - validator: Optional[DataSourceValidator] = None, + validator: DataSourceValidator | None = None, standalone_copy: bool = False, ) -> None: """This method combines load_declarative_ldm and put_declarative_ldm @@ -393,7 +393,7 @@ def load_ldm_from_disk(path: Path = Path.cwd()) -> CatalogDeclarativeModel: # Declarative methods for analytics model def get_declarative_analytics_model( - self, workspace_id: str, exclude: Optional[list[str]] = None + self, workspace_id: str, exclude: list[str] | None = None ) -> CatalogDeclarativeAnalytics: """Retrieves declarative analytics model. The model is tied to the workspace and organization. @@ -481,7 +481,7 @@ def load_and_put_declarative_analytics_model(self, workspace_id: str, layout_roo self.put_declarative_analytics_model(workspace_id, declarative_analytics_model) def store_analytics_model_to_disk( - self, workspace_id: str, path: Path = Path.cwd(), exclude: Optional[list[str]] = None, sort: bool = False + self, workspace_id: str, path: Path = Path.cwd(), exclude: list[str] | None = None, sort: bool = False ) -> None: """Store analytics model for a given workspace in directory hierarchy.This method does not tie the declarative analytics model to the workspace and organization, thus it is recommended for migration between workspaces. @@ -600,15 +600,15 @@ def get_label_elements( self, workspace_id: str, label_id: LabelElementsInputType, - depends_on: Optional[list[DependsOnItem]] = None, - validate_by: Optional[list[CatalogValidateByItem]] = None, - exact_filter: Optional[list[str]] = None, - filter_by: Optional[CatalogFilterBy] = None, - pattern_filter: Optional[str] = None, - complement_filter: Optional[bool] = False, - sort_order: Optional[Literal["ASC", "DESC"]] = None, - offset: Optional[int] = None, - limit: Optional[int] = None, + depends_on: list[DependsOnItem] | None = None, + validate_by: list[CatalogValidateByItem] | None = None, + exact_filter: list[str] | None = None, + filter_by: CatalogFilterBy | None = None, + pattern_filter: str | None = None, + complement_filter: bool | None = False, + sort_order: Literal["ASC", "DESC"] | None = None, + offset: int | None = None, + limit: int | None = None, ) -> list[str]: """ Get existing values for a label. diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/analytics_model.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/analytics_model.py index 879f08a57..43b420966 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/analytics_model.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/analytics_model.py @@ -2,10 +2,9 @@ from __future__ import annotations from pathlib import Path -from typing import Any, Optional, Union +from typing import Any, Union -import attr -from attrs import define +from attrs import define, field from cattrs import global_converter, structure from gooddata_api_client.model.declarative_analytical_dashboard import DeclarativeAnalyticalDashboard from gooddata_api_client.model.declarative_analytical_dashboard_extension import DeclarativeAnalyticalDashboardExtension @@ -53,9 +52,9 @@ MEMORY_ITEMS_DIR = "memory_items" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAnalytics(Base): - analytics: Optional[CatalogDeclarativeAnalyticsLayer] = None + analytics: CatalogDeclarativeAnalyticsLayer | None = None @staticmethod def client_class() -> type[DeclarativeAnalytics]: @@ -71,17 +70,17 @@ def load_from_disk(cls, workspace_folder: Path) -> CatalogDeclarativeAnalytics: return cls(analytics=analytics) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAnalyticsLayer(Base): - analytical_dashboards: list[CatalogDeclarativeAnalyticalDashboard] = attr.field(factory=list) - analytical_dashboard_extensions: list[CatalogDeclarativeAnalyticalDashboardExtension] = attr.field(factory=list) - attribute_hierarchies: list[CatalogDeclarativeAttributeHierarchy] = attr.field(factory=list) - dashboard_plugins: list[CatalogDeclarativeDashboardPlugin] = attr.field(factory=list) - filter_contexts: list[CatalogDeclarativeFilterContext] = attr.field(factory=list) - metrics: list[CatalogDeclarativeMetric] = attr.field(factory=list) - visualization_objects: list[CatalogDeclarativeVisualizationObject] = attr.field(factory=list) - export_definitions: list[CatalogDeclarativeExportDefinition] = attr.field(factory=list) - memory_items: list[CatalogDeclarativeMemoryItem] = attr.field(factory=list) + analytical_dashboards: list[CatalogDeclarativeAnalyticalDashboard] = field(factory=list) + analytical_dashboard_extensions: list[CatalogDeclarativeAnalyticalDashboardExtension] = field(factory=list) + attribute_hierarchies: list[CatalogDeclarativeAttributeHierarchy] = field(factory=list) + dashboard_plugins: list[CatalogDeclarativeDashboardPlugin] = field(factory=list) + filter_contexts: list[CatalogDeclarativeFilterContext] = field(factory=list) + metrics: list[CatalogDeclarativeMetric] = field(factory=list) + visualization_objects: list[CatalogDeclarativeVisualizationObject] = field(factory=list) + export_definitions: list[CatalogDeclarativeExportDefinition] = field(factory=list) + memory_items: list[CatalogDeclarativeMemoryItem] = field(factory=list) @staticmethod def client_class() -> type[DeclarativeAnalyticsLayer]: @@ -255,15 +254,16 @@ def load_from_disk(cls, workspace_folder: Path) -> CatalogDeclarativeAnalyticsLa ) -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAnalyticalDashboard(CatalogAnalyticsBase): - permissions: Optional[ + permissions: ( list[ Union[ CatalogDeclarativeDashboardPermissionsForAssignee, CatalogDeclarativeDashboardPermissionsForAssigneeRule ] ] - ] = None + | None + ) = None @staticmethod def client_class() -> type[DeclarativeAnalyticalDashboard]: @@ -287,14 +287,14 @@ def structure_permissions( ) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDashboardPlugin(CatalogAnalyticsBase): @staticmethod def client_class() -> type[DeclarativeDashboardPlugin]: return DeclarativeDashboardPlugin -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAnalyticalDashboardExtension(CatalogAnalyticsObjectBase): permissions: list[ Union[CatalogDeclarativeDashboardPermissionsForAssignee, CatalogDeclarativeDashboardPermissionsForAssigneeRule] @@ -305,35 +305,35 @@ def client_class() -> type[DeclarativeAnalyticalDashboardExtension]: return DeclarativeAnalyticalDashboardExtension -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeFilterContext(CatalogAnalyticsBase): @staticmethod def client_class() -> type[DeclarativeFilterContext]: return DeclarativeFilterContext -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeMetric(CatalogAnalyticsBase): @staticmethod def client_class() -> type[DeclarativeMetric]: return DeclarativeMetric -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeVisualizationObject(CatalogAnalyticsBase): @staticmethod def client_class() -> type[DeclarativeVisualizationObject]: return DeclarativeVisualizationObject -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAttributeHierarchy(CatalogAnalyticsBase): @staticmethod def client_class() -> type[DeclarativeAttributeHierarchy]: return DeclarativeAttributeHierarchy -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeMemoryItem(CatalogAnalyticsBaseMeta): instruction: str strategy: str diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/base.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/base.py index d5e9fd9f7..5c1ee63a9 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/base.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/base.py @@ -1,6 +1,6 @@ # (C) 2024 GoodData Corporation from pathlib import Path -from typing import Any, Optional, TypeVar +from typing import Any, TypeVar from attrs import define @@ -11,7 +11,7 @@ T = TypeVar("T", bound="CatalogAnalyticsObjectBase") -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAnalyticsObjectBase(Base): id: str @@ -25,18 +25,18 @@ def load_from_disk(cls: type[T], analytics_file: Path) -> T: return cls.from_dict(analytics_layout) -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAnalyticsBaseMeta(CatalogAnalyticsObjectBase): - created_at: Optional[str] = None - created_by: Optional[CatalogUserIdentifier] = None - modified_at: Optional[str] = None - modified_by: Optional[CatalogUserIdentifier] = None + created_at: str | None = None + created_by: CatalogUserIdentifier | None = None + modified_at: str | None = None + modified_by: CatalogUserIdentifier | None = None -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAnalyticsBase(CatalogAnalyticsBaseMeta): title: str content: dict[str, Any] - description: Optional[str] = None - tags: Optional[list[str]] = None - is_hidden: Optional[bool] = None + description: str | None = None + tags: list[str] | None = None + is_hidden: bool | None = None diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/export_definition.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/export_definition.py index 2baf7862a..b37756662 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/export_definition.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/analytics_model/export_definition.py @@ -1,5 +1,4 @@ # (C) 2024 GoodData Corporation -from typing import Optional from attrs import define from gooddata_api_client.model.declarative_export_definition import DeclarativeExportDefinition @@ -12,31 +11,31 @@ from gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.base import CatalogAnalyticsBaseMeta -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeExportDefinitionRequestPayload(Base): - custom_override: Optional[ExportCustomOverride] = None - execution_result: Optional[str] = None - metadata: Optional[dict] = None - related_dashboard_id: Optional[str] = None - settings: Optional[ExportSettings] = None - visualization_object: Optional[str] = None - visualization_object_custom_filters: Optional[list[dict]] = None - file_name: Optional[str] = None - format: Optional[str] = None - dashboard_id: Optional[str] = None + custom_override: ExportCustomOverride | None = None + execution_result: str | None = None + metadata: dict | None = None + related_dashboard_id: str | None = None + settings: ExportSettings | None = None + visualization_object: str | None = None + visualization_object_custom_filters: list[dict] | None = None + file_name: str | None = None + format: str | None = None + dashboard_id: str | None = None @staticmethod def client_class() -> type[DeclarativeExportDefinitionRequestPayload]: return DeclarativeExportDefinitionRequestPayload -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeExportDefinition(CatalogAnalyticsBaseMeta): id: str title: str request_payload: CatalogDeclarativeExportDefinitionRequestPayload - description: Optional[str] = None - tags: Optional[list[str]] = None + description: str | None = None + tags: list[str] | None = None @staticmethod def client_class() -> type[DeclarativeExportDefinition]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/automation.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/automation.py index c837cf10b..079fd90a8 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/automation.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/automation.py @@ -1,6 +1,6 @@ # (C) 2024 GoodData Corporation import builtins -from typing import Any, Optional +from typing import Any from attrs import define, field from gooddata_api_client.model.automation_schedule import AutomationSchedule @@ -21,19 +21,19 @@ from gooddata_sdk.catalog.workspace.declarative_model.workspace.analytics_model.base import CatalogAnalyticsBaseMeta -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAutomationSchedule(Base): cron: str - cron_description: Optional[str] = field(default=None, eq=False) - first_run: Optional[str] = None - timezone: Optional[str] = "UTC" + cron_description: str | None = field(default=None, eq=False) + first_run: str | None = None + timezone: str | None = "UTC" @staticmethod def client_class() -> builtins.type[AutomationSchedule]: return AutomationSchedule -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAutomationTabularExport(Base): request_payload: ExportRequest @@ -42,7 +42,7 @@ def client_class() -> builtins.type[AutomationTabularExport]: return AutomationTabularExport -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAutomationVisualExport(Base): request_payload: VisualExportRequest @@ -51,20 +51,20 @@ def client_class() -> builtins.type[AutomationVisualExport]: return AutomationVisualExport -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAutomation(CatalogAnalyticsBaseMeta): - description: Optional[str] = None - details: Optional[dict[str, Any]] = None - state: Optional[str] = None - tags: Optional[list[str]] = None - title: Optional[str] = None - recipients: Optional[list[CatalogUserIdentifier]] = None - metadata: Optional[dict] = None - export_definitions: Optional[list[CatalogExportDefinitionIdentifier]] = None - notification_channel: Optional[CatalogNotificationChannelIdentifier] = None - schedule: Optional[CatalogAutomationSchedule] = None - tabular_exports: Optional[list[CatalogAutomationTabularExport]] = None - visual_exports: Optional[list[CatalogAutomationVisualExport]] = None + description: str | None = None + details: dict[str, Any] | None = None + state: str | None = None + tags: list[str] | None = None + title: str | None = None + recipients: list[CatalogUserIdentifier] | None = None + metadata: dict | None = None + export_definitions: list[CatalogExportDefinitionIdentifier] | None = None + notification_channel: CatalogNotificationChannelIdentifier | None = None + schedule: CatalogAutomationSchedule | None = None + tabular_exports: list[CatalogAutomationTabularExport] | None = None + visual_exports: list[CatalogAutomationVisualExport] | None = None @staticmethod def client_class() -> builtins.type[DeclarativeAutomation]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/data_filter_references.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/data_filter_references.py index ab4a3678f..fb93d58ca 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/data_filter_references.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/data_filter_references.py @@ -1,5 +1,5 @@ # (C) 2023 GoodData Corporation -import attr +from attrs import define from gooddata_api_client.model.declarative_workspace_data_filter_references import ( DeclarativeWorkspaceDataFilterReferences, ) @@ -8,7 +8,7 @@ from gooddata_sdk.catalog.identifier import CatalogDatasetWorkspaceDataFilterIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspaceDataFilterReferences(Base): filter_id: CatalogDatasetWorkspaceDataFilterIdentifier filter_column: str diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset/dataset.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset/dataset.py index be37191c2..7354c579a 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset/dataset.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset/dataset.py @@ -2,11 +2,8 @@ from __future__ import annotations from pathlib import Path -from typing import Optional -import attr -import attrs -from attrs import define +from attrs import define, field from gooddata_api_client.model.data_source_table_identifier import DataSourceTableIdentifier from gooddata_api_client.model.declarative_aggregated_fact import DeclarativeAggregatedFact from gooddata_api_client.model.declarative_attribute import DeclarativeAttribute @@ -37,22 +34,22 @@ LAYOUT_DATASETS_DIR = "datasets" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDataset(Base): id: str title: str grain: list[CatalogGrainIdentifier] references: list[CatalogDeclarativeReference] - description: Optional[str] = None - attributes: Optional[list[CatalogDeclarativeAttribute]] = None - facts: Optional[list[CatalogDeclarativeFact]] = None - aggregated_facts: Optional[list[CatalogDeclarativeAggregatedFact]] = attrs.field(factory=list) - precedence: Optional[int] = None - data_source_table_id: Optional[CatalogDataSourceTableIdentifier] = None - sql: Optional[CatalogDeclarativeDatasetSql] = None - tags: Optional[list[str]] = None - workspace_data_filter_columns: Optional[list[CatalogDeclarativeWorkspaceDataFilterColumn]] = None - workspace_data_filter_references: Optional[list[CatalogDeclarativeWorkspaceDataFilterReferences]] = None + description: str | None = None + attributes: list[CatalogDeclarativeAttribute] | None = None + facts: list[CatalogDeclarativeFact] | None = None + aggregated_facts: list[CatalogDeclarativeAggregatedFact] | None = field(factory=list) + precedence: int | None = None + data_source_table_id: CatalogDataSourceTableIdentifier | None = None + sql: CatalogDeclarativeDatasetSql | None = None + tags: list[str] | None = None + workspace_data_filter_columns: list[CatalogDeclarativeWorkspaceDataFilterColumn] | None = None + workspace_data_filter_references: list[CatalogDeclarativeWorkspaceDataFilterReferences] | None = None @staticmethod def client_class() -> type[DeclarativeDataset]: @@ -68,46 +65,46 @@ def load_from_disk(cls, dataset_file: Path) -> CatalogDeclarativeDataset: return cls.from_dict(dataset_layout, camel_case=True) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAttribute(Base): id: str title: str source_column: str labels: list[CatalogDeclarativeLabel] - source_column_data_type: Optional[str] = None - default_view: Optional[CatalogLabelIdentifier] = None - sort_column: Optional[str] = None - sort_direction: Optional[str] = None - description: Optional[str] = None - tags: Optional[list[str]] = None - is_hidden: Optional[bool] = None - locale: Optional[str] = None - is_nullable: Optional[bool] = None - null_value: Optional[str] = None + source_column_data_type: str | None = None + default_view: CatalogLabelIdentifier | None = None + sort_column: str | None = None + sort_direction: str | None = None + description: str | None = None + tags: list[str] | None = None + is_hidden: bool | None = None + locale: str | None = None + is_nullable: bool | None = None + null_value: str | None = None @staticmethod def client_class() -> type[DeclarativeAttribute]: return DeclarativeAttribute -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeFact(Base): id: str title: str source_column: str - source_column_data_type: Optional[str] = None - description: Optional[str] = None - tags: Optional[list[str]] = None - is_hidden: Optional[bool] = None - is_nullable: Optional[bool] = None - null_value: Optional[str] = None + source_column_data_type: str | None = None + description: str | None = None + tags: list[str] | None = None + is_hidden: bool | None = None + is_nullable: bool | None = None + null_value: str | None = None @staticmethod def client_class() -> type[DeclarativeFact]: return DeclarativeFact -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeSourceFactReference(Base): operation: str reference: CatalogFactIdentifier @@ -117,34 +114,34 @@ def client_class() -> type[DeclarativeSourceFactReference]: return DeclarativeSourceFactReference -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeAggregatedFact(Base): id: str source_column: str - source_fact_reference: Optional[CatalogDeclarativeSourceFactReference] = None - source_column_data_type: Optional[str] = None - description: Optional[str] = None - tags: Optional[list[str]] = None - is_nullable: Optional[bool] = None - null_value: Optional[str] = None + source_fact_reference: CatalogDeclarativeSourceFactReference | None = None + source_column_data_type: str | None = None + description: str | None = None + tags: list[str] | None = None + is_nullable: bool | None = None + null_value: str | None = None @staticmethod def client_class() -> type[DeclarativeAggregatedFact]: return DeclarativeAggregatedFact -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataSourceTableIdentifier(Base): id: str data_source_id: str - path: Optional[list[str]] = None + path: list[str] | None = None @staticmethod def client_class() -> type[DataSourceTableIdentifier]: return DataSourceTableIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDatasetSql(Base): statement: str data_source_id: str @@ -154,7 +151,7 @@ def client_class() -> type[DeclarativeDatasetSql]: return DeclarativeDatasetSql -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeLabelTranslation(Base): locale: str source_column: str @@ -164,28 +161,28 @@ def client_class() -> type[DeclarativeLabelTranslation]: return DeclarativeLabelTranslation -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeLabel(Base): id: str title: str source_column: str - source_column_data_type: Optional[str] = None - description: Optional[str] = None - tags: Optional[list[str]] = None - value_type: Optional[str] = None - is_hidden: Optional[bool] = None - locale: Optional[str] = None - translations: Optional[list[CatalogDeclarativeLabelTranslation]] = None - geo_area_config: Optional[CatalogGeoAreaConfig] = None - is_nullable: Optional[bool] = None - null_value: Optional[str] = None + source_column_data_type: str | None = None + description: str | None = None + tags: list[str] | None = None + value_type: str | None = None + is_hidden: bool | None = None + locale: str | None = None + translations: list[CatalogDeclarativeLabelTranslation] | None = None + geo_area_config: CatalogGeoAreaConfig | None = None + is_nullable: bool | None = None + null_value: str | None = None @staticmethod def client_class() -> type[DeclarativeLabel]: return DeclarativeLabel -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogGeoAreaConfig(Base): collection: CatalogGeoCollectionIdentifier @@ -194,32 +191,32 @@ def client_class() -> type[GeoAreaConfig]: return GeoAreaConfig -@define(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogGeoCollectionIdentifier(Base): id: str - kind: Optional[str] = None + kind: str | None = None @staticmethod def client_class() -> type[GeoCollectionIdentifier]: return GeoCollectionIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeReference(Base): identifier: CatalogReferenceIdentifier multivalue: bool - source_columns: Optional[list[str]] = None - source_column_data_types: Optional[list[str]] = None - sources: Optional[list[CatalogDeclarativeReferenceSource]] = None - is_nullable: Optional[bool] = None - null_value: Optional[str] = None + source_columns: list[str] | None = None + source_column_data_types: list[str] | None = None + sources: list[CatalogDeclarativeReferenceSource] | None = None + is_nullable: bool | None = None + null_value: str | None = None @staticmethod def client_class() -> type[DeclarativeReference]: return DeclarativeReference -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspaceDataFilterColumn(Base): name: str data_type: str @@ -229,11 +226,11 @@ def client_class() -> type[DeclarativeWorkspaceDataFilterColumn]: return DeclarativeWorkspaceDataFilterColumn -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeReferenceSource(Base): column: str target: CatalogGrainIdentifier - data_type: Optional[str] = None + data_type: str | None = None @staticmethod def client_class() -> type[DeclarativeReferenceSource]: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset_extensions/dataset_extension.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset_extensions/dataset_extension.py index d33f1590c..2c4a3fec4 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset_extensions/dataset_extension.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/dataset_extensions/dataset_extension.py @@ -1,7 +1,7 @@ # (C) 2023 GoodData Corporation from pathlib import Path -import attr +from attrs import define from gooddata_api_client.model.declarative_dataset_extension import DeclarativeDatasetExtension from gooddata_sdk.catalog.base import Base @@ -13,7 +13,7 @@ LAYOUT_DATASET_EXTENSIONS_DIR = "dataset_extensions" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDatasetExtension(Base): id: str workspace_data_filter_references: list[CatalogDeclarativeWorkspaceDataFilterReferences] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/date_dataset/date_dataset.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/date_dataset/date_dataset.py index 7a2270581..0cfb0e0b7 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/date_dataset/date_dataset.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/date_dataset/date_dataset.py @@ -2,9 +2,8 @@ from __future__ import annotations from pathlib import Path -from typing import Optional -import attr +from attrs import define from gooddata_api_client.model.declarative_date_dataset import DeclarativeDateDataset from gooddata_api_client.model.granularities_formatting import GranularitiesFormatting @@ -14,14 +13,14 @@ LAYOUT_DATE_INSTANCES_DIR = "date_instances" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeDateDataset(Base): id: str title: str granularities_formatting: CatalogGranularitiesFormatting granularities: list[str] - description: Optional[str] = None - tags: Optional[list[str]] = None + description: str | None = None + tags: list[str] | None = None @staticmethod def client_class() -> type[DeclarativeDateDataset]: @@ -37,7 +36,7 @@ def load_from_disk(cls, date_instance_file: Path) -> CatalogDeclarativeDateDatas return cls.from_dict(date_instance_layout, camel_case=True) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogGranularitiesFormatting(Base): title_base: str title_pattern: str diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/ldm.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/ldm.py index 2436c9939..3bd060b5b 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/ldm.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/logical_model/ldm.py @@ -2,9 +2,8 @@ from __future__ import annotations from pathlib import Path -from typing import Optional -import attr +from attrs import define, field from gooddata_api_client.model.declarative_ldm import DeclarativeLdm from gooddata_api_client.model.declarative_model import DeclarativeModel @@ -26,9 +25,9 @@ LAYOUT_LDM_DIR = "ldm" -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeModel(Base): - ldm: Optional[CatalogDeclarativeLdm] = None + ldm: CatalogDeclarativeLdm | None = None @staticmethod def client_class() -> type[DeclarativeModel]: @@ -52,11 +51,11 @@ def change_wdf_refs_id(self, mapping: dict[str, str]) -> None: self.ldm.change_wdf_refs_id(mapping) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeLdm(Base): - datasets: list[CatalogDeclarativeDataset] = attr.field(factory=list) - date_instances: list[CatalogDeclarativeDateDataset] = attr.field(factory=list) - dataset_extensions: Optional[list[CatalogDeclarativeDatasetExtension]] = None + datasets: list[CatalogDeclarativeDataset] = field(factory=list) + date_instances: list[CatalogDeclarativeDateDataset] = field(factory=list) + dataset_extensions: list[CatalogDeclarativeDatasetExtension] | None = None @staticmethod def client_class() -> type[DeclarativeLdm]: @@ -147,7 +146,7 @@ def load_from_disk(cls, workspace_folder: Path) -> CatalogDeclarativeLdm: ) return cls(datasets=datasets, date_instances=date_instances, dataset_extensions=dataset_extensions) - def modify_mapped_data_source(self, data_source_mapping: Optional[dict]) -> CatalogDeclarativeLdm: + def modify_mapped_data_source(self, data_source_mapping: dict | None) -> CatalogDeclarativeLdm: """LDM contains data source ID - is mapped to this data source. You may decide to migrate to different data source containing the same physical data model (e.g. change the DB engine, but keep the model). @@ -201,7 +200,7 @@ def _change_case(object_name: str, upper_case: bool) -> str: else: return object_name.lower() - def change_tables_columns_case(self, upper_case: Optional[bool] = None) -> CatalogDeclarativeLdm: + def change_tables_columns_case(self, upper_case: bool | None = None) -> CatalogDeclarativeLdm: """Change case (to lower/upper-case) of all physical objects mapped in the LDM. Namely mapped table names and column names. Default is to change everything to upper-case. diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/workspace.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/workspace.py index d131fa8fb..ad82c2151 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/workspace.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/declarative_model/workspace/workspace.py @@ -3,9 +3,9 @@ import copy from pathlib import Path -from typing import Any, Optional +from typing import Any -import attr +from attrs import define, field from gooddata_api_client.model.declarative_filter_view import DeclarativeFilterView from gooddata_api_client.model.declarative_user_data_filter import DeclarativeUserDataFilter from gooddata_api_client.model.declarative_user_data_filters import DeclarativeUserDataFilters @@ -45,10 +45,10 @@ def get_workspace_folder(workspace_id: str, layout_organization_folder: Path) -> return layout_organization_folder / LAYOUT_WORKSPACES_DIR / workspace_id -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspaceModel(Base): - ldm: Optional[CatalogDeclarativeLdm] = None - analytics: Optional[CatalogDeclarativeAnalyticsLayer] = None + ldm: CatalogDeclarativeLdm | None = None + analytics: CatalogDeclarativeAnalyticsLayer | None = None @staticmethod def client_class() -> type[DeclarativeWorkspaceModel]: @@ -75,21 +75,21 @@ def change_wdf_refs_id(self, mapping: dict[str, str]) -> None: self.ldm.change_wdf_refs_id(mapping) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspace(Base): id: str name: str - description: Optional[str] = None - model: Optional[CatalogDeclarativeWorkspaceModel] = None - parent: Optional[CatalogWorkspaceIdentifier] = None - permissions: list[CatalogDeclarativeSingleWorkspacePermission] = attr.field(factory=list) - hierarchy_permissions: list[CatalogDeclarativeWorkspaceHierarchyPermission] = attr.field(factory=list) - early_access: Optional[str] = None - settings: list[CatalogDeclarativeSetting] = attr.field(factory=list) - user_data_filters: list[CatalogDeclarativeUserDataFilter] = attr.field(factory=list) - custom_application_settings: list[CatalogDeclarativeCustomApplicationSetting] = attr.field(factory=list) - automations: list[CatalogDeclarativeAutomation] = attr.field(factory=list) - filter_views: list[CatalogDeclarativeFilterView] = attr.field(factory=list) + description: str | None = None + model: CatalogDeclarativeWorkspaceModel | None = None + parent: CatalogWorkspaceIdentifier | None = None + permissions: list[CatalogDeclarativeSingleWorkspacePermission] = field(factory=list) + hierarchy_permissions: list[CatalogDeclarativeWorkspaceHierarchyPermission] = field(factory=list) + early_access: str | None = None + settings: list[CatalogDeclarativeSetting] = field(factory=list) + user_data_filters: list[CatalogDeclarativeUserDataFilter] = field(factory=list) + custom_application_settings: list[CatalogDeclarativeCustomApplicationSetting] = field(factory=list) + automations: list[CatalogDeclarativeAutomation] = field(factory=list) + filter_views: list[CatalogDeclarativeFilterView] = field(factory=list) @staticmethod def client_class() -> type[DeclarativeWorkspace]: @@ -124,20 +124,20 @@ def load_from_disk(cls, workspaces_folder: Path, workspace_id: str) -> CatalogDe return workspace_layout -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspaceDataFilterSetting(Base): id: str title: str filter_values: list[str] workspace: CatalogWorkspaceIdentifier - description: Optional[str] = None + description: str | None = None @staticmethod def client_class() -> type[DeclarativeWorkspaceDataFilterSetting]: return DeclarativeWorkspaceDataFilterSetting -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspaceDataFilters(Base): workspace_data_filters: list[CatalogDeclarativeWorkspaceDataFilter] @@ -191,14 +191,14 @@ def create_copy(self, source_ws_id: str, target_ws_id: str) -> tuple[CatalogDecl return self_copy, wdf_ref_mapping -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspaceDataFilter(Base): id: str title: str column_name: str workspace_data_filter_settings: list[CatalogDeclarativeWorkspaceDataFilterSetting] - description: Optional[str] = None - workspace: Optional[CatalogWorkspaceIdentifier] = None + description: str | None = None + workspace: CatalogWorkspaceIdentifier | None = None @staticmethod def client_class() -> type[DeclarativeWorkspaceDataFilter]: @@ -228,7 +228,7 @@ def from_dict(cls, data: dict[str, Any], camel_case: bool = True) -> CatalogDecl return cls.from_api(declarative_workspace_data_filter) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUserDataFilters(Base): user_data_filters: list[CatalogDeclarativeUserDataFilter] @@ -254,14 +254,14 @@ def load_from_disk(cls, layout_organization_folder: Path) -> CatalogDeclarativeU return cls(user_data_filters=user_data_filters) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeUserDataFilter(Base): id: str title: str maql: str - user: Optional[CatalogUserIdentifier] = None - user_group: Optional[CatalogDeclarativeUserGroupIdentifier] = None - description: Optional[str] = None + user: CatalogUserIdentifier | None = None + user_group: CatalogDeclarativeUserGroupIdentifier | None = None + description: str | None = None @staticmethod def client_class() -> type[DeclarativeUserDataFilter]: @@ -291,16 +291,16 @@ def from_dict(cls, data: dict[str, Any], camel_case: bool = True) -> CatalogDecl return cls.from_api(declarative_user_data_filter) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeFilterView(Base): id: str title: str - analytical_dashboard: Optional[CatalogDeclarativeAnalyticalDashboardIdentifier] = None - content: Optional[dict[str, Any]] = None - description: Optional[str] = None - is_default: Optional[bool] = None - tags: Optional[list[str]] = None - user: Optional[CatalogUserIdentifier] = None + analytical_dashboard: CatalogDeclarativeAnalyticalDashboardIdentifier | None = None + content: dict[str, Any] | None = None + description: str | None = None + is_default: bool | None = None + tags: list[str] | None = None + user: CatalogUserIdentifier | None = None @staticmethod def client_class() -> type[DeclarativeFilterView]: @@ -334,7 +334,7 @@ def load_filter_views_from_disk(cls, layout_organization_folder: Path) -> list[C ] -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDeclarativeWorkspaces(Base): workspaces: list[CatalogDeclarativeWorkspace] workspace_data_filters: list[CatalogDeclarativeWorkspaceDataFilter] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/dataset.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/dataset.py index 2bbf3320e..648db8613 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/dataset.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/dataset.py @@ -1,10 +1,9 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Any, Optional, Union, cast +from typing import Any, Union, cast -import attr -import attrs +from attrs import Factory, define, evolve, field from gooddata_api_client.model.json_api_aggregated_fact_out import JsonApiAggregatedFactOut from gooddata_api_client.model.json_api_attribute_out import JsonApiAttributeOut from gooddata_api_client.model.json_api_dataset_out import JsonApiDatasetOut @@ -18,7 +17,7 @@ from gooddata_sdk.utils import IdObjType, id_obj_to_key, safeget, safeget_list -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogLabel(AttrCatalogEntity): @staticmethod def client_class() -> Any: @@ -33,15 +32,15 @@ def value_type(self) -> bool: return safeget(self.json_api_attributes, ["valueType"]) @property - def is_hidden(self) -> Optional[bool]: + def is_hidden(self) -> bool | None: return safeget(self.json_api_attributes, ["isHidden"]) @property - def locale(self) -> Optional[str]: + def locale(self) -> str | None: return safeget(self.json_api_attributes, ["locale"]) @property - def translations(self) -> Optional[list[dict[str, str]]]: + def translations(self) -> list[dict[str, str]] | None: return safeget(self.json_api_attributes, ["translations"]) def as_computable(self) -> Attribute: @@ -50,7 +49,7 @@ def as_computable(self) -> Attribute: # TODO - attribute_id? dataset? -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAttribute(AttrCatalogEntity): @staticmethod def client_class() -> Any: @@ -78,11 +77,11 @@ def granularity(self) -> Union[str, None]: return self.json_api_attributes.get("granularity") @property - def is_hidden(self) -> Optional[bool]: + def is_hidden(self) -> bool | None: return safeget(self.json_api_attributes, ["isHidden"]) @property - def locale(self) -> Optional[bool]: + def locale(self) -> bool | None: return safeget(self.json_api_attributes, ["locale"]) def primary_label(self) -> Union[CatalogLabel, None]: @@ -108,14 +107,14 @@ def as_computable(self) -> Attribute: raise ValueError() -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogFact(AttrCatalogEntity): @staticmethod def client_class() -> Any: return JsonApiFactOut @property - def is_hidden(self) -> Optional[bool]: + def is_hidden(self) -> bool | None: return safeget(self.json_api_attributes, ["isHidden"]) def as_computable(self) -> Metric: @@ -124,7 +123,7 @@ def as_computable(self) -> Metric: # TODO - dataset? -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogAggregatedFact(AttrCatalogEntity): @staticmethod def client_class() -> Any: @@ -134,7 +133,7 @@ def client_class() -> Any: # TODO - dataset? -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDataset(AttrCatalogEntity): @property def dataset_type(self) -> str: @@ -149,51 +148,45 @@ def generate_attributes_from_api(self) -> list[CatalogAttribute]: ] return related_attributes - attributes: list[CatalogAttribute] = attr.field( + attributes: list[CatalogAttribute] = field( repr=False, - default=attr.Factory(lambda self: self.generate_attributes_from_api(), takes_self=True), + default=Factory(lambda self: self.generate_attributes_from_api(), takes_self=True), ) - facts: list[CatalogFact] = attr.field( + facts: list[CatalogFact] = field( repr=False, - default=attr.Factory( + default=Factory( lambda self: self._relation_entity_from_side_loads(CatalogFact, ["facts", "data"]), takes_self=True ), ) - aggregated_facts: Optional[list[CatalogAggregatedFact]] = attr.field( + aggregated_facts: list[CatalogAggregatedFact] | None = field( repr=False, - default=attr.Factory( + default=Factory( lambda self: self._relation_entity_from_side_loads(CatalogAggregatedFact, ["aggregatedFacts", "data"]), takes_self=True, ), ) - precedence: Optional[int] = attr.field( - default=attr.Factory(lambda self: self.json_api_attributes.get("precedence"), takes_self=True) + precedence: int | None = field( + default=Factory(lambda self: self.json_api_attributes.get("precedence"), takes_self=True) ) - grain: Optional[list] = attr.field( - default=attr.Factory(lambda self: self.json_api_attributes.get("grain"), takes_self=True) + grain: list | None = field(default=Factory(lambda self: self.json_api_attributes.get("grain"), takes_self=True)) + reference_properties: list | None = field( + default=Factory(lambda self: self.json_api_attributes.get("referenceProperties"), takes_self=True) ) - reference_properties: Optional[list] = attr.field( - default=attr.Factory(lambda self: self.json_api_attributes.get("referenceProperties"), takes_self=True) + data_source_table_id: str | None = field( + default=Factory(lambda self: self.json_api_attributes.get("dataSourceTableId"), takes_self=True) ) - data_source_table_id: Optional[str] = attr.field( - default=attr.Factory(lambda self: self.json_api_attributes.get("dataSourceTableId"), takes_self=True) + data_source_table_path: list | None = field( + default=Factory(lambda self: self.json_api_attributes.get("dataSourceTablePath"), takes_self=True) ) - data_source_table_path: Optional[list] = attr.field( - default=attr.Factory(lambda self: self.json_api_attributes.get("dataSourceTablePath"), takes_self=True) + sql: dict | None = field(default=Factory(lambda self: self.json_api_attributes.get("sql"), takes_self=True)) + are_relations_valid: bool | None = field( + default=Factory(lambda self: self.json_api_attributes.get("areRelationsValid"), takes_self=True) ) - sql: Optional[dict] = attr.field( - default=attr.Factory(lambda self: self.json_api_attributes.get("sql"), takes_self=True) + workspace_data_filter_columns: list | None = field( + default=Factory(lambda self: self.json_api_attributes.get("workspaceDataFilterColumns"), takes_self=True) ) - are_relations_valid: Optional[bool] = attr.field( - default=attr.Factory(lambda self: self.json_api_attributes.get("areRelationsValid"), takes_self=True) - ) - workspace_data_filter_columns: Optional[list] = attr.field( - default=attr.Factory(lambda self: self.json_api_attributes.get("workspaceDataFilterColumns"), takes_self=True) - ) - workspace_data_filter_references: Optional[list] = attr.field( - default=attr.Factory( - lambda self: self.json_api_attributes.get("workspaceDataFilterReferences"), takes_self=True - ) + workspace_data_filter_references: list | None = field( + default=Factory(lambda self: self.json_api_attributes.get("workspaceDataFilterReferences"), takes_self=True) ) @staticmethod @@ -207,7 +200,7 @@ def find_label_attribute(self, id_obj: IdObjType) -> Union[CatalogAttribute, Non return None - def filter_dataset(self, valid_objects: ValidObjects) -> Optional[CatalogDataset]: + def filter_dataset(self, valid_objects: ValidObjects) -> CatalogDataset | None: """ Filters dataset so that it contains only attributes and facts that are part of the provided valid objects structure. @@ -225,7 +218,7 @@ def filter_dataset(self, valid_objects: ValidObjects) -> Optional[CatalogDataset return ( None if len(new_facts) == 0 and len(new_attributes) == 0 - else attrs.evolve( + else evolve( self, attributes=new_attributes, facts=new_facts, diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/metric.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/metric.py index d50dc5185..f53814da5 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/metric.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/metric.py @@ -1,9 +1,9 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Any, Optional +from typing import Any -import attr +from attrs import define from gooddata_api_client.model.json_api_metric_out import JsonApiMetricOut from gooddata_sdk.catalog.entity import AttrCatalogEntity @@ -11,18 +11,18 @@ from gooddata_sdk.utils import safeget -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogMetric(AttrCatalogEntity): @staticmethod def client_class() -> Any: return JsonApiMetricOut @property - def format(self) -> Optional[str]: + def format(self) -> str | None: return safeget(self.json_api_attributes, ["content", "format"]) @property - def is_hidden(self) -> Optional[bool]: + def is_hidden(self) -> bool | None: return safeget(self.json_api_attributes, ["isHidden"]) def as_computable(self) -> Metric: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/workspace_setting.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/workspace_setting.py index 4e7f55f48..3d29b4d5a 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/workspace_setting.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/content_objects/workspace_setting.py @@ -4,7 +4,7 @@ import functools from typing import Any, Union -import attr +from attrs import Factory, define, field from gooddata_api_client.model.json_api_organization_setting_in_attributes import JsonApiOrganizationSettingInAttributes from gooddata_api_client.model.json_api_workspace_setting_in import JsonApiWorkspaceSettingIn from gooddata_api_client.model.json_api_workspace_setting_in_document import JsonApiWorkspaceSettingInDocument @@ -18,15 +18,15 @@ from gooddata_sdk.utils import safeget -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogWorkspaceSetting(Base): - id: str = attr.field(default=None) - setting_type: str = attr.field( + id: str = field(default=None) + setting_type: str = field( validator=functools.partial(value_in_allowed, client_class=JsonApiOrganizationSettingInAttributes) ) - content: dict = attr.field( + content: dict = field( repr=False, - default=attr.Factory(lambda self: safeget(self.json_api_entity.attributes, ["content"]), takes_self=True), + default=Factory(lambda self: safeget(self.json_api_entity.attributes, ["content"]), takes_self=True), ) @staticmethod diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/filter_view.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/filter_view.py index 87364998e..b751f7b3f 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/filter_view.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/filter_view.py @@ -1,9 +1,9 @@ # (C) 2024 GoodData Corporation from __future__ import annotations -from typing import Any, Optional, Union +from typing import Any, Union -import attr +from attrs import define from gooddata_api_client.model.json_api_filter_view_in import JsonApiFilterViewIn from gooddata_api_client.model.json_api_filter_view_in_attributes import JsonApiFilterViewInAttributes from gooddata_api_client.model.json_api_filter_view_in_document import JsonApiFilterViewInDocument @@ -13,7 +13,7 @@ from gooddata_sdk.catalog.identifier import CatalogDeclarativeAnalyticalDashboardIdentifier, CatalogUserIdentifier -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogFilterViewDocument(Base): data: CatalogFilterView @@ -29,11 +29,11 @@ def _data_entity(value: Any) -> dict[str, Any]: return {"data": value} -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogFilterView(Base): - id: Optional[str] = None + id: str | None = None attributes: CatalogFilterViewAttributes - relationships: Optional[CatalogFilterViewRelationships] = None + relationships: CatalogFilterViewRelationships | None = None @staticmethod def client_class() -> type[JsonApiFilterViewIn]: @@ -45,12 +45,12 @@ def init( filter_view_id: str, content: dict[str, Any], title: str, - are_relations_valid: Optional[bool] = None, - description: Optional[str] = None, - is_default: Optional[bool] = None, - tags: Optional[list[str]] = None, - user_id: Optional[str] = None, - analytical_dashboard_id: Optional[str] = None, + are_relations_valid: bool | None = None, + description: str | None = None, + is_default: bool | None = None, + tags: list[str] | None = None, + user_id: str | None = None, + analytical_dashboard_id: str | None = None, ) -> CatalogFilterView: attributes = CatalogFilterViewAttributes( content=content, @@ -106,24 +106,24 @@ def clean_relationships(self) -> None: self.relationships.analytical_dashboard = None -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogFilterViewAttributes(Base): content: dict[str, Any] title: str - are_relations_valid: Optional[bool] = None - description: Optional[str] = None - is_default: Optional[bool] = None - tags: Optional[list[str]] = None + are_relations_valid: bool | None = None + description: str | None = None + is_default: bool | None = None + tags: list[str] | None = None @staticmethod def client_class() -> type[JsonApiFilterViewInAttributes]: return JsonApiFilterViewInAttributes -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogFilterViewRelationships(Base): - user: Optional[dict[str, CatalogUserIdentifier]] = None - analytical_dashboard: Optional[dict[str, CatalogDeclarativeAnalyticalDashboardIdentifier]] = None + user: dict[str, CatalogUserIdentifier] | None = None + analytical_dashboard: dict[str, CatalogDeclarativeAnalyticalDashboardIdentifier] | None = None @staticmethod def client_class() -> type[JsonApiFilterViewInRelationships]: @@ -131,7 +131,7 @@ def client_class() -> type[JsonApiFilterViewInRelationships]: @classmethod def create_user_analytical_dashboard_relationship( - cls, user_id: Optional[str] = None, analytical_dashboard_id: Optional[str] = None + cls, user_id: str | None = None, analytical_dashboard_id: str | None = None ) -> CatalogFilterViewRelationships | None: if user_id is None and analytical_dashboard_id is None: return None diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/graph_objects/graph.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/graph_objects/graph.py index 936bffa2c..b5c2b0f45 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/graph_objects/graph.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/graph_objects/graph.py @@ -2,9 +2,8 @@ from __future__ import annotations import builtins -from typing import Optional -import attr +from attrs import define, field from gooddata_api_client.model.dependent_entities_graph import DependentEntitiesGraph from gooddata_api_client.model.dependent_entities_node import DependentEntitiesNode from gooddata_api_client.model.dependent_entities_request import DependentEntitiesRequest @@ -14,16 +13,16 @@ from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDependentEntitiesRequest(Base): - identifiers: list[CatalogEntityIdentifier] = attr.field(factory=list) + identifiers: list[CatalogEntityIdentifier] = field(factory=list) @staticmethod def client_class() -> builtins.type[DependentEntitiesRequest]: return DependentEntitiesRequest -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDependentEntitiesResponse(Base): graph: CatalogDependentEntitiesGraph @@ -32,28 +31,28 @@ def client_class() -> builtins.type[DependentEntitiesResponse]: return DependentEntitiesResponse -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDependentEntitiesGraph(Base): - nodes: list[CatalogDependentEntitiesNode] = attr.field(factory=list) - edges: list[list[CatalogEntityIdentifier]] = attr.field(factory=list) + nodes: list[CatalogDependentEntitiesNode] = field(factory=list) + edges: list[list[CatalogEntityIdentifier]] = field(factory=list) @staticmethod def client_class() -> builtins.type[DependentEntitiesGraph]: return DependentEntitiesGraph -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogDependentEntitiesNode(Base): id: str type: str - title: Optional[str] = None + title: str | None = None @staticmethod def client_class() -> builtins.type[DependentEntitiesNode]: return DependentEntitiesNode -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogEntityIdentifier(Base): id: str type: str diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/user_data_filter.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/user_data_filter.py index 428d55754..5011bf50c 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/user_data_filter.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/user_data_filter.py @@ -1,9 +1,9 @@ # (C) 2023 GoodData Corporation from __future__ import annotations -from typing import Any, Optional, Union +from typing import Any, Union -import attr +from attrs import define from gooddata_api_client.model.json_api_user_data_filter_in import JsonApiUserDataFilterIn from gooddata_api_client.model.json_api_user_data_filter_in_attributes import JsonApiUserDataFilterInAttributes from gooddata_api_client.model.json_api_user_data_filter_in_document import JsonApiUserDataFilterInDocument @@ -16,7 +16,7 @@ from gooddata_sdk.catalog.base import Base -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserDataFilterDocument(Base): data: CatalogUserDataFilter @@ -38,7 +38,7 @@ def to_post_api(self) -> JsonApiUserDataFilterPostOptionalIdDocument: return JsonApiUserDataFilterPostOptionalIdDocument.from_dict(dictionary, camel_case=False) -def _proces_entity_list_output(list_entity_data: Optional[dict[str, list[CatalogEntityIdentifier]]]) -> list[str]: +def _proces_entity_list_output(list_entity_data: dict[str, list[CatalogEntityIdentifier]] | None) -> list[str]: if list_entity_data: return list(map(lambda x: x.id, list_entity_data["data"])) return [] @@ -48,11 +48,11 @@ def _data_entity(value: Any) -> dict[str, Any]: return {"data": value} -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserDataFilter(Base): - id: Optional[str] = None + id: str | None = None attributes: CatalogUserDataFilterAttributes - relationships: Optional[CatalogUserDataFilterRelationships] = None + relationships: CatalogUserDataFilterRelationships | None = None @staticmethod def client_class() -> type[JsonApiUserDataFilterIn]: @@ -63,12 +63,12 @@ def init( cls, user_data_filter_id: str, maql: str, - are_relations_valid: Optional[bool] = None, - title: Optional[str] = None, - description: Optional[str] = None, - tags: Optional[list[str]] = None, - user_id: Optional[str] = None, - user_group_id: Optional[str] = None, + are_relations_valid: bool | None = None, + title: str | None = None, + description: str | None = None, + tags: list[str] | None = None, + user_id: str | None = None, + user_group_id: str | None = None, ) -> CatalogUserDataFilter: attributes = CatalogUserDataFilterAttributes( maql=maql, title=title, are_relations_valid=are_relations_valid, tags=tags, description=description @@ -152,28 +152,28 @@ def clean_assignments(self) -> None: self.relationships.user_group = None -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserDataFilterAttributes(Base): maql: str - are_relations_valid: Optional[bool] = None - title: Optional[str] = None - description: Optional[str] = None - tags: Optional[list[str]] = None + are_relations_valid: bool | None = None + title: str | None = None + description: str | None = None + tags: list[str] | None = None @staticmethod def client_class() -> type[JsonApiUserDataFilterInAttributes]: return JsonApiUserDataFilterInAttributes -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogUserDataFilterRelationships(Base): - user: Optional[dict[str, CatalogEntityIdentifier]] = None - user_group: Optional[dict[str, CatalogEntityIdentifier]] = None - attributes: Optional[dict[str, list[CatalogEntityIdentifier]]] = None - labels: Optional[dict[str, list[CatalogEntityIdentifier]]] = None - datasets: Optional[dict[str, list[CatalogEntityIdentifier]]] = None - facts: Optional[dict[str, list[CatalogEntityIdentifier]]] = None - metrics: Optional[dict[str, list[CatalogEntityIdentifier]]] = None + user: dict[str, CatalogEntityIdentifier] | None = None + user_group: dict[str, CatalogEntityIdentifier] | None = None + attributes: dict[str, list[CatalogEntityIdentifier]] | None = None + labels: dict[str, list[CatalogEntityIdentifier]] | None = None + datasets: dict[str, list[CatalogEntityIdentifier]] | None = None + facts: dict[str, list[CatalogEntityIdentifier]] | None = None + metrics: dict[str, list[CatalogEntityIdentifier]] | None = None @staticmethod def client_class() -> type[JsonApiUserDataFilterInRelationships]: @@ -181,7 +181,7 @@ def client_class() -> type[JsonApiUserDataFilterInRelationships]: @classmethod def create_user_user_group_relationship( - cls, user_id: Optional[str] = None, user_group_id: Optional[str] = None + cls, user_id: str | None = None, user_group_id: str | None = None ) -> CatalogUserDataFilterRelationships | None: if user_id is None and user_group_id is None: return None @@ -192,7 +192,7 @@ def create_user_user_group_relationship( return cls(user=assignee_user, user_group=assignee_user_group) -@attr.s(auto_attribs=True, kw_only=True) +@define(kw_only=True) class CatalogEntityIdentifier(Base): id: str - type: Optional[str] = None + type: str | None = None diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/workspace.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/workspace.py index b3e06f9f4..c659b0685 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/workspace.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/entity_model/workspace.py @@ -1,9 +1,9 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Any, Optional +from typing import Any -import attr +from attrs import Factory, define, field from gooddata_api_client.model.json_api_workspace_automation_out_relationships_workspace import ( JsonApiWorkspaceAutomationOutRelationshipsWorkspace, ) @@ -17,13 +17,13 @@ from gooddata_sdk.utils import safeget -@attr.s(auto_attribs=True) +@define class CatalogWorkspace(Base): workspace_id: str - id: str = attr.field(init=False, default=attr.Factory(lambda self: self.workspace_id, takes_self=True)) + id: str = field(init=False, default=Factory(lambda self: self.workspace_id, takes_self=True)) name: str - parent_id: Optional[str] = attr.field(default=None) - description: Optional[str] = attr.field(default=None) + parent_id: str | None = field(default=None) + description: str | None = field(default=None) @classmethod def from_api(cls, entity: dict[str, Any]) -> CatalogWorkspace: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/model_container.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/model_container.py index 289647e48..c92a457c3 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/model_container.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/model_container.py @@ -2,7 +2,7 @@ from __future__ import annotations import functools -from typing import Optional, Union +from typing import Union from gooddata_sdk.catalog.types import ValidObjects from gooddata_sdk.catalog.workspace.entity_model.content_objects.dataset import ( @@ -29,7 +29,7 @@ class CatalogWorkspaceContent: def __init__( self, - valid_obj_fun: Optional[functools.partial[dict[str, set[str]]]], + valid_obj_fun: functools.partial[dict[str, set[str]]] | None, datasets: list[CatalogDataset], metrics: list[CatalogMetric], ) -> None: @@ -166,7 +166,7 @@ def catalog_with_valid_objects(self, ctx: ValidObjectsInputType) -> CatalogWorks @classmethod def create_workspace_content_catalog( cls, - valid_obj_fun: Optional[functools.partial[dict[str, set[str]]]], + valid_obj_fun: functools.partial[dict[str, set[str]]] | None, datasets: AllPagedEntities, attributes: AllPagedEntities, metrics: AllPagedEntities, diff --git a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/service.py b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/service.py index 6719afaef..4ef49204a 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/service.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/service.py @@ -9,10 +9,10 @@ from math import ceil from pathlib import Path from time import time -from typing import Any, Callable, Optional +from typing import Any, Callable from xml.etree import ElementTree as ET -import attrs +from attrs import evolve from gooddata_api_client.api.translations_api import LocaleRequest from gooddata_api_client.exceptions import NotFoundException from gooddata_api_client.model.resolve_settings_request import ResolveSettingsRequest @@ -232,7 +232,7 @@ def resolve_workspace_settings(self, workspace_id: str, settings: list) -> dict: # Declarative methods - workspaces - def get_declarative_workspaces(self, exclude: Optional[list[str]] = None) -> CatalogDeclarativeWorkspaces: + def get_declarative_workspaces(self, exclude: list[str] | None = None) -> CatalogDeclarativeWorkspaces: """Get all workspaces in the current organization in a declarative form. Args: @@ -305,7 +305,7 @@ def load_and_put_declarative_workspaces(self, layout_root_path: Path = Path.cwd( # Declarative methods - workspace def get_declarative_workspace( - self, workspace_id: str, exclude: Optional[list[str]] = None + self, workspace_id: str, exclude: list[str] | None = None ) -> CatalogDeclarativeWorkspaceModel: """Retrieve a workspace layout. @@ -348,7 +348,7 @@ def put_declarative_workspace( self._layout_api.put_workspace_layout(workspace_id, workspace.to_api()) def store_declarative_workspace( - self, workspace_id: str, layout_root_path: Path = Path.cwd(), exclude: Optional[list[str]] = None + self, workspace_id: str, layout_root_path: Path = Path.cwd(), exclude: list[str] | None = None ) -> None: """Store workspace layout in a directory hierarchy. @@ -410,11 +410,11 @@ def load_and_put_declarative_workspace(self, workspace_id: str, layout_root_path def clone_workspace( self, source_workspace_id: str, - target_workspace_id: Optional[str] = None, - target_workspace_name: Optional[str] = None, - overwrite_existing: Optional[bool] = None, - data_source_mapping: Optional[dict] = None, - upper_case: Optional[bool] = True, + target_workspace_id: str | None = None, + target_workspace_name: str | None = None, + overwrite_existing: bool | None = None, + data_source_mapping: dict | None = None, + upper_case: bool | None = True, place_in_hierarchy: bool = True, ) -> None: """Clone workspace from existing workspace. @@ -489,7 +489,7 @@ def clone_workspace( target_declarative_ws = source_declarative_ws if source_declarative_ws.ldm: - target_declarative_ws = attrs.evolve( + target_declarative_ws = evolve( source_declarative_ws, ldm=source_declarative_ws.ldm.modify_mapped_data_source(data_source_mapping).change_tables_columns_case( upper_case @@ -513,10 +513,10 @@ def generate_localized_workspaces( to_lang: str, to_locale: str, from_lang: str = "en", - translator_func: Optional[Callable] = None, - layout_root_path: Optional[Path] = None, - provision_workspace: Optional[bool] = False, - store_layouts: Optional[bool] = False, + translator_func: Callable | None = None, + layout_root_path: Path | None = None, + provision_workspace: bool | None = False, + store_layouts: bool | None = False, place_in_hierarchy: bool = True, ) -> None: """ @@ -577,7 +577,7 @@ def generate_localized_workspaces( if provision_workspace: self.provision_workspace_with_locales(workspace_id, new_workspace, new_workspace_content, to_locale) - def create_custom_workspace_folder(self, workspace_id: str, layout_root_path: Optional[Path]) -> Path: + def create_custom_workspace_folder(self, workspace_id: str, layout_root_path: Path | None) -> Path: if layout_root_path: workspace_folder = layout_root_path else: @@ -661,7 +661,7 @@ def provision_workspace_with_locales( def translate_if_requested( self, to_translate: set[str], - translator_func: Optional[Callable], + translator_func: Callable | None, to_lang: str, from_lang: str, already_translated: dict[str, str], @@ -691,14 +691,14 @@ def translate_if_requested( return translated @staticmethod - def add_title_description(to_translate: set[str], title: Optional[str], description: Optional[str]) -> None: + def add_title_description(to_translate: set[str], title: str | None, description: str | None) -> None: if title: to_translate.add(title) if description: to_translate.add(description) def add_title_description_tags( - self, to_translate: set[str], title: Optional[str], description: Optional[str], tags: Optional[list[str]] + self, to_translate: set[str], title: str | None, description: str | None, tags: list[str] | None ) -> None: self.add_title_description(to_translate, title, description) if tags: diff --git a/packages/gooddata-sdk/src/gooddata_sdk/client.py b/packages/gooddata-sdk/src/gooddata_sdk/client.py index b1ac3197e..62bc12b9b 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/client.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/client.py @@ -4,7 +4,6 @@ from __future__ import annotations from pathlib import Path -from typing import Optional import gooddata_api_client as api_client import requests @@ -23,10 +22,10 @@ def __init__( self, host: str, token: str, - custom_headers: Optional[dict[str, str]] = None, - extra_user_agent: Optional[str] = None, + custom_headers: dict[str, str] | None = None, + extra_user_agent: str | None = None, executions_cancellable: bool = False, - ssl_ca_cert: Optional[str] = None, + ssl_ca_cert: str | None = None, ) -> None: """Take url, token for connecting to GoodData.CN. 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 64b9f1fce..595226d13 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/attribute.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/attribute.py @@ -1,7 +1,7 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Optional, Union +from typing import Union import gooddata_api_client.models as afm_models @@ -9,7 +9,7 @@ class Attribute(ExecModelEntity): - def __init__(self, local_id: str, label: Union[ObjId, str], show_all_values: Optional[bool] = None) -> None: + def __init__(self, local_id: str, label: Union[ObjId, str], show_all_values: bool | None = None) -> None: """ Creates new attribute that can be used to slice or dice metric values during computation. @@ -33,7 +33,7 @@ def label(self) -> ObjId: return self._label @property - def show_all_values(self) -> Optional[bool]: + def show_all_values(self) -> bool | None: return self._show_all_values def has_same_label(self, other: ExecModelEntity) -> bool: 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 753897313..a354bdf74 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/base.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/base.py @@ -1,7 +1,7 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Optional, Union +from typing import Union import gooddata_api_client.models as afm_models from gooddata_api_client.model_utils import OpenApiModel @@ -71,7 +71,7 @@ def as_api_model(self) -> OpenApiModel: class Filter(ExecModelEntity): - def __init__(self, _apply_on_result: Optional[bool] = None) -> None: + def __init__(self, _apply_on_result: bool | None = None) -> None: super().__init__() self._apply_on_result = _apply_on_result @@ -86,7 +86,7 @@ def is_noop(self) -> bool: def as_api_model(self) -> OpenApiModel: raise NotImplementedError() - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: """ Description of the filter as it's visible for customer in UI. 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 7f2d9cf92..a81b807ac 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py @@ -2,10 +2,10 @@ from __future__ import annotations import logging -from typing import Any, Optional, Union +from typing import Any, Union -from attr.setters import frozen as frozen_attr 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 @@ -46,7 +46,7 @@ class TotalDefinition: class TableDimension: """Dataclass used during total and dimension computation.""" - item_ids: Optional[list[str]] = field(on_setattr=frozen_attr) + item_ids: list[str] | None = field(on_setattr=frozen_attr) """table dimension item local identifiers""" sorting: list[dict] = field(default=[]) @@ -56,11 +56,11 @@ class TableDimension: class ExecutionDefinition: def __init__( self, - attributes: Optional[list[Attribute]], - metrics: Optional[list[Metric]], - filters: Optional[list[Filter]], + attributes: list[Attribute] | None, + metrics: list[Metric] | None, + filters: list[Filter] | None, dimensions: list[TableDimension], - totals: Optional[list[TotalDefinition]] = None, + totals: list[TotalDefinition] | None = None, is_cancellable: bool = False, ) -> None: self._attributes = attributes or [] @@ -165,7 +165,7 @@ def _create_dimensions(self) -> list[models.Dimension]: return dimensions - def _create_totals(self) -> Optional[list[models.Total]]: + def _create_totals(self) -> list[models.Total] | None: if not self._totals: return None @@ -205,7 +205,7 @@ def as_api_model(self) -> models.AfmExecution: return models.AfmExecution(execution=execution, result_spec=result_spec) -ResultSizeDimensions = tuple[Optional[int], ...] +ResultSizeDimensions = tuple[int | None, ...] class ResultSizeDimensionsLimitsExceeded(Exception): @@ -308,7 +308,7 @@ def __init__( api_client: GoodDataApiClient, workspace_id: str, execution_response: models.AfmExecutionResponse, - cancel_token: Optional[str] = None, + cancel_token: str | None = None, ): self._api_client = api_client self._actions_api = self._api_client.actions_api @@ -331,14 +331,14 @@ def dimensions(self) -> Any: return self._exec_response["dimensions"] @property - def cancel_token(self) -> Optional[str]: + def cancel_token(self) -> str | None: return self._cancel_token def read_result( self, limit: Union[int, list[int]], offset: Union[None, int, list[int]] = None, - timeout: Optional[Union[int, float, tuple]] = None, + timeout: Union[int, float, tuple] | None = None, ) -> ExecutionResult: """ Reads from the execution result. @@ -402,7 +402,7 @@ def __init__( workspace_id: str, exec_def: ExecutionDefinition, response: models.AfmExecutionResponse, - cancel_token: Optional[str] = None, + cancel_token: str | None = None, ): self._exec_def = exec_def self._bare_exec_response = BareExecutionResponse( @@ -430,7 +430,7 @@ def dimensions(self) -> Any: return self.bare_exec_response._exec_response["dimensions"] @property - def cancel_token(self) -> Optional[str]: + def cancel_token(self) -> str | None: return self.bare_exec_response.cancel_token def get_labels_and_formats(self) -> tuple[dict[str, str], dict[str, str]]: @@ -460,7 +460,7 @@ def read_result( self, limit: Union[int, list[int]], offset: Union[None, int, list[int]] = None, - timeout: Optional[Union[int, float, tuple]] = None, + timeout: Union[int, float, tuple] | None = None, ) -> ExecutionResult: return self.bare_exec_response.read_result(limit, offset, timeout) @@ -516,7 +516,7 @@ def result_size(self) -> int: def result_spec(self) -> ResultSpec: return self._result_cache_metadata.result_spec - def check_bytes_size_limit(self, result_size_bytes_limit: Optional[int] = None) -> None: + def check_bytes_size_limit(self, result_size_bytes_limit: int | None = None) -> None: if result_size_bytes_limit is not None and self.result_size > result_size_bytes_limit: raise ResultSizeBytesLimitExceeded( result_size_bytes_limit=result_size_bytes_limit, @@ -525,9 +525,9 @@ def check_bytes_size_limit(self, result_size_bytes_limit: Optional[int] = None) def compute_model_to_api_model( - attributes: Optional[list[Attribute]] = None, - metrics: Optional[list[Metric]] = None, - filters: Optional[list[Filter]] = None, + attributes: list[Attribute] | None = None, + metrics: list[Metric] | None = None, + filters: list[Filter] | None = None, ) -> models.AFM: """ Transforms categorized execution model entities (attributes, metrics, facts) into an API model 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 9816034a9..2cc061b47 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/filter.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/filter.py @@ -3,9 +3,9 @@ from datetime import datetime from importlib.util import find_spec -from typing import Any, Literal, Optional, TypeAlias, Union, cast +from typing import Any, Literal, TypeAlias, Union, cast -import attrs +from attrs import define from gooddata_api_client.model.inline_filter_definition_inline import InlineFilterDefinitionInline if find_spec("icu") is not None: @@ -95,7 +95,7 @@ def _to_identifier(val: Union[ObjId, str]) -> Union[afm_models.AfmLocalIdentifie class AttributeFilter(Filter): - def __init__(self, label: Union[ObjId, str, Attribute], values: Optional[list[str]] = None) -> None: + def __init__(self, label: Union[ObjId, str, Attribute], values: list[str] | None = None) -> None: super().__init__() self._label = _extract_id_or_local_id(label) @@ -130,7 +130,7 @@ def as_api_model(self) -> afm_models.PositiveAttributeFilter: body = PositiveAttributeFilterBody(label=label_id, _in=elements, _check_type=False) return afm_models.PositiveAttributeFilter(body, _check_type=False) - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: label_id = self.label.id if isinstance(self.label, ObjId) else self.label values = ", ".join(self.values) if len(self.values) else "All" return f"{labels.get(label_id, label_id)}: {values}" @@ -146,7 +146,7 @@ def as_api_model(self) -> afm_models.NegativeAttributeFilter: body = NegativeAttributeFilterBody(label=label_id, not_in=elements, _check_type=False) return afm_models.NegativeAttributeFilter(body) - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: label_id = self.label.id if isinstance(self.label, ObjId) else self.label values = "All except " + ", ".join(self.values) if len(self.values) else "All" return f"{labels.get(label_id, label_id)}: {values}" @@ -174,11 +174,11 @@ def description(self, labels: dict[str, str], format_locale: Optional[str] = Non } -@attrs.define +@define class BoundedFilter: granularity: str - from_shift: Optional[int] = None - to_shift: Optional[int] = None + from_shift: int | None = None + to_shift: int | None = None def __attrs_post_init__(self) -> None: # Validate that exactly one of from_shift or to_shift is set @@ -201,8 +201,8 @@ def __init__( granularity: str, from_shift: int, to_shift: int, - bounded_filter: Optional[BoundedFilter] = None, - empty_value_handling: Optional[EmptyValueHandling] = None, + bounded_filter: BoundedFilter | None = None, + empty_value_handling: EmptyValueHandling | None = None, ) -> None: super().__init__() @@ -241,11 +241,11 @@ def to_shift(self) -> int: return self._to_shift @property - def bounded_filter(self) -> Optional[BoundedFilter]: + def bounded_filter(self) -> BoundedFilter | None: return self._bounded_filter @property - def empty_value_handling(self) -> Optional[EmptyValueHandling]: + def empty_value_handling(self) -> EmptyValueHandling | None: return self._empty_value_handling def is_noop(self) -> bool: @@ -269,7 +269,7 @@ def as_api_model(self) -> afm_models.RelativeDateFilter: body = RelativeDateFilterBody(**body_params) return afm_models.RelativeDateFilter(body) - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: # TODO compare with other period is not implemented as it's not defined in the filter but in measures from_shift = self.from_shift to_shift = self.to_shift @@ -313,8 +313,8 @@ class AllTimeDateFilter(Filter): def __init__( self, dataset: ObjId, - granularity: Optional[str] = None, - empty_value_handling: Optional[EmptyValueHandling] = None, + granularity: str | None = None, + empty_value_handling: EmptyValueHandling | None = None, ) -> None: super().__init__() @@ -338,11 +338,11 @@ def dataset(self) -> ObjId: return self._dataset @property - def granularity(self) -> Optional[str]: + def granularity(self) -> str | None: return self._granularity @property - def empty_value_handling(self) -> Optional[EmptyValueHandling]: + def empty_value_handling(self) -> EmptyValueHandling | None: return self._empty_value_handling def is_noop(self) -> bool: @@ -363,7 +363,7 @@ def as_api_model(self) -> afm_models.AllTimeDateFilter: body = AllTimeDateFilterBody(**body_params) return afm_models.AllTimeDateFilter(body, _check_type=False) - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: return f"{labels.get(self.dataset.id, self.dataset.id)}: All time" @@ -373,7 +373,7 @@ def __init__( dataset: ObjId, from_date: str, to_date: str, - empty_value_handling: Optional[EmptyValueHandling] = None, + empty_value_handling: EmptyValueHandling | None = None, ) -> None: super().__init__() @@ -401,7 +401,7 @@ def to_date(self) -> str: return self._to_date @property - def empty_value_handling(self) -> Optional[EmptyValueHandling]: + def empty_value_handling(self) -> EmptyValueHandling | None: return self._empty_value_handling def is_noop(self) -> bool: @@ -428,7 +428,7 @@ def __eq__(self, other: object) -> bool: and self._to_date == other._to_date ) - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: if format_locale is not None and find_spec("icu") is not None: src_parser = SimpleDateFormat(_ICU_DATE_FORMAT_INPUT) dest_formatter = SimpleDateFormat( @@ -470,7 +470,7 @@ def metric(self) -> Union[ObjId, str]: def is_noop(self) -> bool: return True - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: metric_id = self.metric.id if isinstance(self.metric, ObjId) else self.metric return f"{labels.get(metric_id, metric_id)}: All" @@ -554,7 +554,7 @@ def as_api_model(self) -> Union[afm_models.ComparisonMeasureValueFilter, afm_mod body = RangeMeasureValueFilterBody(**kwargs) return afm_models.RangeMeasureValueFilter(body) - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: metric_id = self.metric.id if isinstance(self.metric, ObjId) else self.metric if self.operator in ["BETWEEN", "NOT_BETWEEN"] and len(self.values) == 2: not_between = "not" if self.operator == "NOT_BETWEEN" else "" @@ -567,7 +567,7 @@ def description(self, labels: dict[str, str], format_locale: Optional[str] = Non ) -@attrs.define(frozen=True, slots=True) +@define(frozen=True, slots=True) class MetricValueComparisonCondition: operator: ComparisonOperator value: Union[int, float] @@ -584,7 +584,7 @@ def description(self) -> str: return f"{_METRIC_VALUE_FILTER_OPERATOR_LABEL.get(self.operator, self.operator)} {float(self.value)}" -@attrs.define(frozen=True, slots=True) +@define(frozen=True, slots=True) class MetricValueRangeCondition: operator: RangeOperator from_value: Union[int, float] @@ -658,7 +658,7 @@ def as_api_model(self) -> afm_models.CompoundMeasureValueFilter: body = CompoundMeasureValueFilterBody(**kwargs) return afm_models.CompoundMeasureValueFilter(body, _check_type=False) - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: metric_id = self.metric.id if isinstance(self.metric, ObjId) else self.metric if not self.conditions: return f"{labels.get(metric_id, metric_id)}: All" @@ -675,7 +675,7 @@ def __init__( metrics: list[Union[ObjId, Metric, str]], operator: str, value: int, - dimensionality: Optional[list[Union[str, ObjId, Attribute, Metric]]], + dimensionality: list[Union[str, ObjId, Attribute, Metric]] | None, ) -> None: super().__init__() @@ -702,7 +702,7 @@ def value(self) -> int: return self._value @property - def dimensionality(self) -> Optional[list[Union[ObjId, str]]]: + def dimensionality(self) -> list[Union[ObjId, str]] | None: return self._dimensionality def is_noop(self) -> bool: @@ -718,7 +718,7 @@ def as_api_model(self) -> afm_models.RankingFilter: ) return afm_models.RankingFilter(body) - def description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> str: + def description(self, labels: dict[str, str], format_locale: str | None = None) -> str: # TODO more metrics and dimensions not supported now as it's not supported on FE as well dimensionality_ids = ( [d.id if isinstance(d, ObjId) else d for d in self.dimensionality] if self.dimensionality else [] @@ -755,7 +755,7 @@ class InlineFilter(Filter): """ def __init__( - self, maql: str, apply_on_result: Optional[bool] = None, local_identifier: Optional[Union[ObjId, str]] = None + self, maql: str, apply_on_result: bool | None = None, local_identifier: Union[ObjId, str] | None = None ) -> None: super().__init__(apply_on_result) 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 8f8b44887..3e671f4ca 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/metric.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/metric.py @@ -1,7 +1,7 @@ # (C) 2022 GoodData Corporation from __future__ import annotations -from typing import Optional, Union +from typing import Union import gooddata_api_client.models as afm_models from gooddata_api_client.model_utils import OpenApiModel @@ -53,9 +53,9 @@ def __init__( self, local_id: str, item: ObjId, - aggregation: Optional[str] = None, + aggregation: str | None = None, compute_ratio: bool = False, - filters: Optional[list[Filter]] = None, + filters: list[Filter] | None = None, ) -> None: super().__init__(local_id) @@ -86,7 +86,7 @@ def item(self) -> ObjId: return self._item @property - def aggregation(self) -> Optional[str]: + def aggregation(self) -> str | None: return self._aggregation @property diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/service.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/service.py index cd9a5d522..6163798b9 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/service.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/service.py @@ -4,7 +4,7 @@ import json import logging from collections.abc import Iterator -from typing import Any, Optional, Union +from typing import Any, Union from gooddata_api_client import ApiException from gooddata_api_client.model.afm_cancel_tokens import AfmCancelTokens @@ -44,7 +44,7 @@ def for_exec_def( self, workspace_id: str, exec_def: ExecutionDefinition, - timeout: Optional[Union[int, float, tuple]] = None, + timeout: Union[int, float, tuple] | None = None, ) -> Execution: """ Starts computation in GoodData.CN workspace, using the provided execution definition. @@ -275,11 +275,11 @@ def search_ai( self, workspace_id: str, question: str, - deep_search: Optional[bool] = None, - limit: Optional[int] = None, - object_types: Optional[list[str]] = None, - relevant_score_threshold: Optional[float] = None, - title_to_descriptor_ratio: Optional[float] = None, + deep_search: bool | None = None, + limit: int | None = None, + object_types: list[str] | None = None, + relevant_score_threshold: float | None = None, + title_to_descriptor_ratio: float | None = None, ) -> SearchResult: """ Search for metadata objects using similarity search. diff --git a/packages/gooddata-sdk/src/gooddata_sdk/config.py b/packages/gooddata-sdk/src/gooddata_sdk/config.py index 06b8d1e5e..bce62d3cc 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/config.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/config.py @@ -1,9 +1,8 @@ # (C) 2024 GoodData Corporation import os -from typing import Any, Optional, TypeVar +from typing import Any, TypeVar -import attrs -from attrs import define +from attrs import asdict, define from cattrs import structure from cattrs.errors import ClassValidationError from dotenv import load_dotenv @@ -14,7 +13,7 @@ @define class ConfigBase: def to_dict(self) -> dict[str, str]: - return attrs.asdict(self) + return asdict(self) @classmethod def from_dict(cls: type[T], data: dict[str, Any]) -> T: @@ -33,18 +32,18 @@ def can_structure(cls: type[T], data: dict[str, Any]) -> bool: class Profile(ConfigBase): host: str token: str - custom_headers: Optional[dict[str, str]] = None - extra_user_agent: Optional[str] = None - ssl_ca_cert: Optional[str] = None + custom_headers: dict[str, str] | None = None + extra_user_agent: str | None = None + ssl_ca_cert: str | None = None def to_dict(self, use_env: bool = False) -> dict[str, str]: load_dotenv() if not use_env: - return attrs.asdict(self) + return asdict(self) env_var = self.token[1:] if env_var not in os.environ: raise ValueError(f"Environment variable {env_var} not found") - return {**attrs.asdict(self), "token": os.environ[env_var]} + return {**asdict(self), "token": os.environ[env_var]} @define diff --git a/packages/gooddata-sdk/src/gooddata_sdk/sdk.py b/packages/gooddata-sdk/src/gooddata_sdk/sdk.py index 5e7587464..8c6ea5c48 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/sdk.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/sdk.py @@ -2,7 +2,6 @@ from __future__ import annotations from pathlib import Path -from typing import Optional from gooddata_sdk.catalog.data_source.service import CatalogDataSourceService from gooddata_sdk.catalog.export.service import ExportService @@ -45,11 +44,11 @@ def create( cls, host_: str, token_: str, - extra_user_agent_: Optional[str] = None, + extra_user_agent_: str | None = None, *, - ssl_ca_cert: Optional[str] = None, + ssl_ca_cert: str | None = None, executions_cancellable: bool = False, - **custom_headers_: Optional[str], + **custom_headers_: str | None, ) -> GoodDataSdk: """ Create common GoodDataApiClient and return new GoodDataSdk instance. diff --git a/packages/gooddata-sdk/src/gooddata_sdk/table.py b/packages/gooddata-sdk/src/gooddata_sdk/table.py index 10f297fa1..198e88d26 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/table.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/table.py @@ -4,7 +4,7 @@ import logging from collections.abc import Generator from operator import attrgetter -from typing import Any, Callable, Optional, Union +from typing import Any, Callable, Union from attrs import define, field, frozen from attrs.setters import frozen as frozen_attr @@ -243,7 +243,7 @@ def _prepare_tabular_definition( def _as_table( response: ExecutionResponse, always_two_dimensional: bool = False, - timeout: Optional[Union[int, float, tuple]] = None, + timeout: Union[int, float, tuple] | None = None, ) -> ExecutionTable: first_page_offset = [0, 0] first_page_limit = [_TABLE_ROW_BATCH_SIZE, _MAX_METRICS] @@ -359,9 +359,7 @@ def _create_data_col_locators(locators: list[VisualizationSortLocator]) -> list[ return converted_locators -def _get_dim_idx_for_predicate( - dims: list[TableDimension], predicate: Callable[[TableDimension], bool] -) -> Optional[int]: +def _get_dim_idx_for_predicate(dims: list[TableDimension], predicate: Callable[[TableDimension], bool]) -> int | None: for dim_idx, dim in enumerate(dims): if predicate(dim): return dim_idx @@ -391,8 +389,8 @@ def _append_attribute_sort_key( def _append_measure_sort_key( - measure_dim: Optional[TableDimension], - non_measure_dim_idx: Optional[int], + measure_dim: TableDimension | None, + non_measure_dim_idx: int | None, sort_item: VisualizationSort, sorting: list[list[SortKey]], ) -> None: @@ -472,7 +470,7 @@ def _vis_is_transposed(visualization: Visualization) -> bool: return controls.get("measureGroupDimension") == "rows" -def _create_dimension(bucket: VisualizationBucket, measures_item_identifier: Optional[str] = None) -> TableDimension: +def _create_dimension(bucket: VisualizationBucket, measures_item_identifier: str | None = None) -> TableDimension: item_ids = [a.local_id for a in bucket.attributes] if measures_item_identifier is not None: item_ids.append(measures_item_identifier) @@ -800,8 +798,8 @@ def for_items( self, workspace_id: str, items: list[Union[Attribute, Metric]], - filters: Optional[list[Filter]] = None, - timeout: Optional[Union[int, float, tuple]] = None, + filters: list[Filter] | None = None, + timeout: Union[int, float, tuple] | None = None, ) -> ExecutionTable: if filters is None: filters = [] diff --git a/packages/gooddata-sdk/src/gooddata_sdk/type_converter.py b/packages/gooddata-sdk/src/gooddata_sdk/type_converter.py index 6f6e14a41..10fcee4fb 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/type_converter.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/type_converter.py @@ -2,7 +2,7 @@ from __future__ import annotations from datetime import date, datetime -from typing import Any, Callable, Optional +from typing import Any, Callable from dateutil.parser import parse @@ -15,7 +15,7 @@ class Converter: DEFAULT_DB_DATA_TYPE = "VARCHAR(255)" - _EXTERNAL_CONVERSION_FNC: Optional[Callable[[object, Any], Any]] = None + _EXTERNAL_CONVERSION_FNC: Callable[[object, Any], Any] | None = None @classmethod def set_external_fnc(cls, fnc: Callable[[object, Any], Any]) -> None: @@ -126,9 +126,9 @@ def __init__(self, type_name: str): """ self._type_name = type_name self._converters: dict[str, Converter] = {} - self._default_converter: Optional[Converter] = None + self._default_converter: Converter | None = None - def register(self, converter: Converter, sub_type: Optional[str]) -> None: + def register(self, converter: Converter, sub_type: str | None) -> None: """ Register converter instance for given sub-type (granularity). If sub-type is not specified, converter is registered as the default one for the whole type. Default converter can be registered only once. @@ -174,7 +174,7 @@ def _register_default(self, converter: Converter) -> None: ) self._default_converter = converter - def converter(self, sub_type: Optional[str]) -> Converter: + def converter(self, sub_type: str | None) -> Converter: """ Find and return converter instance for a given sub-type. Default converter instance is returned if the sub-type is not found or not provided. When a default converter is not registered, ValueError @@ -230,7 +230,7 @@ def _get_registry(cls, type_name: str) -> TypeConverterRegistry: return cls._TYPE_REGISTRIES[type_name] @classmethod - def register(cls, type_name: str, class_converter: type[Converter], sub_types: Optional[list[str]] = None) -> None: + def register(cls, type_name: str, class_converter: type[Converter], sub_types: list[str] | None = None) -> None: """ Register Converter instance created from provided Converter class to given type and list of sub types. When sub types are not provided, converter is registered as the default one for given type. @@ -247,7 +247,7 @@ def register(cls, type_name: str, class_converter: type[Converter], sub_types: O registry.register(class_converter(), sub_type) @classmethod - def find_converter(cls, type_name: str, sub_type: Optional[str] = None) -> Converter: + def find_converter(cls, type_name: str, sub_type: str | None = None) -> Converter: """ Find Converter for given type and sub type. diff --git a/packages/gooddata-sdk/src/gooddata_sdk/visualization.py b/packages/gooddata-sdk/src/gooddata_sdk/visualization.py index b4d369d2f..6b00da4db 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/visualization.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/visualization.py @@ -4,7 +4,7 @@ import functools from collections import defaultdict from enum import Enum -from typing import Any, Optional, Union, cast +from typing import Any, Union, cast from gooddata_sdk.client import GoodDataApiClient from gooddata_sdk.compute.model.attribute import Attribute @@ -350,31 +350,31 @@ def local_id(self) -> str: return self._m["localIdentifier"] @property - def alias(self) -> Optional[str]: + def alias(self) -> str | None: return self._m.get("alias") @property - def title(self) -> Optional[str]: + def title(self) -> str | None: return self._m.get("title") @property - def format(self) -> Optional[str]: + def format(self) -> str | None: return self._m.get("format") @property - def item(self) -> Optional[dict[str, Any]]: + def item(self) -> dict[str, Any] | None: return safeget(self._d, ["measureDefinition", "item"]) @property - def aggregation(self) -> Optional[str]: + def aggregation(self) -> str | None: return safeget(self._d, ["measureDefinition", "aggregation"]) @property - def item_id(self) -> Optional[str]: + def item_id(self) -> str | None: return safeget(self.item, ["identifier", "id"]) @property - def item_type(self) -> Optional[str]: + def item_type(self) -> str | None: return safeget(self.item, ["identifier", "type"]) @property @@ -382,7 +382,7 @@ def is_time_comparison(self) -> bool: return "popMeasureDefinition" in self._d or "previousPeriodMeasure" in self._d @property - def time_comparison_master(self) -> Optional[str]: + def time_comparison_master(self) -> str | None: """ If this is a time comparison metric, return local_id of the master metric from which it is derived. @@ -417,7 +417,7 @@ def label_id(self) -> str: return self._a["displayForm"]["identifier"]["id"] @property - def alias(self) -> Optional[str]: + def alias(self) -> str | None: return self._a.get("alias") @property @@ -425,7 +425,7 @@ def label(self) -> dict[str, Any]: return self._a["displayForm"] @property - def show_all_values(self) -> Optional[bool]: + def show_all_values(self) -> bool | None: return self._a.get("showAllValues") def as_computable(self) -> Attribute: @@ -522,7 +522,7 @@ def __init__(self, sort: dict[str, Any]) -> None: sort_keys = list(sort.keys()) sort_key = sort_keys[0] if sort_keys else "" self._sort = sort[sort_key] if sort_key else {} - self._locators: Optional[list[VisualizationSortLocator]] = None + self._locators: list[VisualizationSortLocator] | None = None self.type = _SORT_KEY_TO_SORT_TYPE[sort_key] @property @@ -534,7 +534,7 @@ def attribute_identifier(self) -> str: return self._sort["attributeIdentifier"] if self.type == SortType.ATTRIBUTE else "" @property - def aggregation(self) -> Optional[str]: + def aggregation(self) -> str | None: return self._sort.get("aggregation") @property @@ -565,9 +565,9 @@ def locators(self) -> list[VisualizationSortLocator]: class VisualizationBucket: def __init__(self, bucket: dict[str, Any]) -> None: self._b = bucket - self._metrics: Optional[list[VisualizationMetric]] = None - self._attributes: Optional[list[VisualizationAttribute]] = None - self._totals: Optional[list[VisualizationTotal]] = None + self._metrics: list[VisualizationMetric] | None = None + self._attributes: list[VisualizationAttribute] | None = None + self._totals: list[VisualizationTotal] | None = None self.type = _LOCAL_ID_TO_BUCKET_TYPE[self.local_id] @property @@ -610,13 +610,13 @@ class Visualization: def __init__( self, from_vis_obj: dict[str, Any], - side_loads: Optional[SideLoads] = None, + side_loads: SideLoads | None = None, ) -> None: self._vo = from_vis_obj - self._attribute_filter_configs: Optional[list[VisualizationAttributeFilterConfig]] = None - self._buckets: Optional[list[VisualizationBucket]] = None - self._filters: Optional[list[VisualizationFilter]] = None - self._sorts: Optional[list[VisualizationSort]] = None + self._attribute_filter_configs: list[VisualizationAttributeFilterConfig] | None = None + self._buckets: list[VisualizationBucket] | None = None + self._filters: list[VisualizationFilter] | None = None + self._sorts: list[VisualizationSort] | None = None self._side_loads = SideLoads([]) if side_loads is None else side_loads @property @@ -637,7 +637,7 @@ def are_relations_valid(self) -> str: return self._vo["attributes"].get("areRelationsValid", "true") @property - def attribute_filter_configs(self) -> Optional[list[VisualizationAttributeFilterConfig]]: + def attribute_filter_configs(self) -> list[VisualizationAttributeFilterConfig] | None: visualization_attribute_filter_configs = safeget(self._vo, ["attributes", "content", "attributeFilterConfigs"]) if self._attribute_filter_configs is None and visualization_attribute_filter_configs is not None: self._attribute_filter_configs = [ @@ -706,7 +706,7 @@ def has_row_and_col_totals(self) -> bool: def side_loads(self) -> SideLoads: return self._side_loads - def get_metadata(self, id_obj: IdObjType) -> Optional[Any]: + def get_metadata(self, id_obj: IdObjType) -> Any | None: if not self._side_loads: return None @@ -731,7 +731,7 @@ def get_labels_and_formats(self) -> tuple[dict[str, str], dict[str, str]]: formats[item_values["localIdentifier"]] = item_values["format"] return labels, formats - def get_filters_description(self, labels: dict[str, str], format_locale: Optional[str] = None) -> list[str]: + def get_filters_description(self, labels: dict[str, str], format_locale: str | None = None) -> list[str]: return [f.as_computable().description(labels, format_locale) for f in self.filters] def __str__(self) -> str: @@ -792,7 +792,7 @@ def get_visualizations(self, workspace_id: str) -> list[Visualization]: return [Visualization(vis_obj, side_loads) for vis_obj in vis_objects.data] def get_visualization( - self, workspace_id: str, visualization_id: str, timeout: Optional[Union[int, float, tuple]] = None + self, workspace_id: str, visualization_id: str, timeout: Union[int, float, tuple] | None = None ) -> Visualization: """Gets a single visualization from a workspace. diff --git a/packages/gooddata-sdk/tests/catalog/test_catalog_data_source.py b/packages/gooddata-sdk/tests/catalog/test_catalog_data_source.py index ccc6ee09e..67f9f42d0 100644 --- a/packages/gooddata-sdk/tests/catalog/test_catalog_data_source.py +++ b/packages/gooddata-sdk/tests/catalog/test_catalog_data_source.py @@ -2,7 +2,7 @@ from __future__ import annotations from pathlib import Path -from typing import Optional, Union +from typing import Union from unittest import mock from unittest.mock import MagicMock @@ -252,7 +252,7 @@ def _create_default_data_source(sdk: GoodDataSdk, data_source_id: str = "test"): assert expected_data_source == data_source -def _get_data_source(data_sources: list[CatalogDataSource], data_source_id: str) -> Optional[CatalogDataSource]: +def _get_data_source(data_sources: list[CatalogDataSource], data_source_id: str) -> CatalogDataSource | None: for data_source in data_sources: if data_source.id == data_source_id: return data_source @@ -869,8 +869,8 @@ def test_jdbc_urls_creation( db_class: type[CatalogDataSource], attributes: type[DatabaseAttributes], url: str, - parameters: Optional[list], - url_params: Optional[list], + parameters: list | None, + url_params: list | None, ): data_source = db_class( id="test", diff --git a/packages/gooddata-sdk/tests/compute_model/test_compute_model.py b/packages/gooddata-sdk/tests/compute_model/test_compute_model.py index f747af146..1f83f96eb 100644 --- a/packages/gooddata-sdk/tests/compute_model/test_compute_model.py +++ b/packages/gooddata-sdk/tests/compute_model/test_compute_model.py @@ -3,7 +3,6 @@ import json import os -from typing import Optional import pytest from gooddata_sdk.compute.model.attribute import Attribute @@ -90,9 +89,9 @@ def _scenario_to_snapshot_name(scenario: str): @pytest.mark.parametrize("scenario,attributes,metrics,filters", test_inputs) def test_attribute_filters_to_api_model( scenario: str, - attributes: Optional[list[Attribute]], - metrics: Optional[list[Metric]], - filters: Optional[list[Filter]], + attributes: list[Attribute] | None, + metrics: list[Metric] | None, + filters: list[Filter] | None, snapshot, ): # it is essential to define snapshot dir using absolute path, otherwise snapshots cannot be found when