Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 16 additions & 18 deletions packages/gooddata-sdk/src/gooddata_sdk/catalog/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,))
Expand All @@ -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:
Expand Down Expand Up @@ -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)
)

Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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]:
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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]:
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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]:
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
@@ -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]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]:
Expand All @@ -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)
Loading