castor-extractor 0.17.4__py3-none-any.whl → 0.18.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of castor-extractor might be problematic. Click here for more details.
- CHANGELOG.md +16 -0
- castor_extractor/commands/extract_metabase_api.py +2 -1
- castor_extractor/commands/extract_metabase_db.py +3 -1
- castor_extractor/commands/extract_mode.py +2 -3
- castor_extractor/utils/__init__.py +2 -1
- castor_extractor/utils/collection.py +8 -0
- castor_extractor/utils/safe_request.py +57 -0
- castor_extractor/utils/safe_request_test.py +77 -0
- castor_extractor/utils/salesforce/__init__.py +1 -2
- castor_extractor/utils/salesforce/constants.py +0 -11
- castor_extractor/utils/salesforce/credentials.py +22 -45
- castor_extractor/visualization/domo/__init__.py +1 -1
- castor_extractor/visualization/domo/client/__init__.py +1 -1
- castor_extractor/visualization/domo/client/client.py +37 -52
- castor_extractor/visualization/domo/client/credentials.py +14 -27
- castor_extractor/visualization/domo/extract.py +6 -12
- castor_extractor/visualization/looker/__init__.py +6 -1
- castor_extractor/visualization/looker/api/__init__.py +2 -1
- castor_extractor/visualization/looker/api/client.py +6 -4
- castor_extractor/visualization/looker/api/client_test.py +5 -3
- castor_extractor/visualization/looker/api/credentials.py +33 -0
- castor_extractor/visualization/looker/api/extraction_parameters.py +38 -0
- castor_extractor/visualization/looker/api/sdk.py +2 -28
- castor_extractor/visualization/looker/constant.py +2 -27
- castor_extractor/visualization/looker/constants.py +17 -0
- castor_extractor/visualization/looker/extract.py +30 -29
- castor_extractor/visualization/metabase/__init__.py +6 -1
- castor_extractor/visualization/metabase/client/__init__.py +2 -2
- castor_extractor/visualization/metabase/client/api/__init__.py +1 -0
- castor_extractor/visualization/metabase/client/api/client.py +8 -14
- castor_extractor/visualization/metabase/client/api/credentials.py +13 -40
- castor_extractor/visualization/metabase/client/db/__init__.py +1 -0
- castor_extractor/visualization/metabase/client/db/client.py +13 -34
- castor_extractor/visualization/metabase/client/db/credentials.py +19 -73
- castor_extractor/visualization/metabase/errors.py +5 -3
- castor_extractor/visualization/metabase/extract.py +1 -1
- castor_extractor/visualization/mode/__init__.py +1 -1
- castor_extractor/visualization/mode/client/__init__.py +1 -0
- castor_extractor/visualization/mode/client/client.py +9 -12
- castor_extractor/visualization/mode/client/client_test.py +3 -3
- castor_extractor/visualization/mode/client/credentials.py +18 -51
- castor_extractor/visualization/mode/extract.py +5 -3
- castor_extractor/visualization/powerbi/__init__.py +1 -1
- castor_extractor/visualization/powerbi/client/__init__.py +2 -1
- castor_extractor/visualization/powerbi/client/credentials.py +17 -9
- castor_extractor/visualization/powerbi/client/credentials_test.py +12 -4
- castor_extractor/visualization/powerbi/client/rest.py +2 -2
- castor_extractor/visualization/powerbi/client/rest_test.py +2 -2
- castor_extractor/visualization/powerbi/extract.py +2 -2
- castor_extractor/visualization/qlik/__init__.py +5 -1
- castor_extractor/visualization/qlik/client/__init__.py +1 -0
- castor_extractor/visualization/qlik/client/engine/__init__.py +1 -0
- castor_extractor/visualization/qlik/client/engine/client.py +5 -6
- castor_extractor/visualization/qlik/client/engine/credentials.py +26 -0
- castor_extractor/visualization/qlik/client/master.py +5 -11
- castor_extractor/visualization/qlik/client/rest.py +4 -4
- castor_extractor/visualization/qlik/client/rest_test.py +6 -2
- castor_extractor/visualization/qlik/extract.py +4 -8
- castor_extractor/visualization/sigma/__init__.py +1 -1
- castor_extractor/visualization/sigma/client/__init__.py +1 -1
- castor_extractor/visualization/sigma/client/client.py +5 -4
- castor_extractor/visualization/sigma/client/credentials.py +12 -28
- castor_extractor/visualization/sigma/extract.py +4 -8
- castor_extractor/visualization/tableau_revamp/client/credentials.py +40 -87
- castor_extractor/warehouse/redshift/queries/column.sql +0 -5
- castor_extractor/warehouse/salesforce/extract.py +2 -2
- castor_extractor/warehouse/snowflake/queries/column.sql +0 -1
- castor_extractor/warehouse/synapse/queries/column.sql +0 -1
- {castor_extractor-0.17.4.dist-info → castor_extractor-0.18.2.dist-info}/METADATA +9 -9
- {castor_extractor-0.17.4.dist-info → castor_extractor-0.18.2.dist-info}/RECORD +73 -73
- castor_extractor/visualization/domo/client/client_test.py +0 -60
- castor_extractor/visualization/domo/constants.py +0 -6
- castor_extractor/visualization/looker/env.py +0 -48
- castor_extractor/visualization/looker/parameters.py +0 -78
- castor_extractor/visualization/qlik/constants.py +0 -3
- castor_extractor/visualization/sigma/constants.py +0 -4
- {castor_extractor-0.17.4.dist-info → castor_extractor-0.18.2.dist-info}/LICENCE +0 -0
- {castor_extractor-0.17.4.dist-info → castor_extractor-0.18.2.dist-info}/WHEEL +0 -0
- {castor_extractor-0.17.4.dist-info → castor_extractor-0.18.2.dist-info}/entry_points.txt +0 -0
|
@@ -7,13 +7,11 @@ from ...utils import (
|
|
|
7
7
|
deep_serialize,
|
|
8
8
|
from_env,
|
|
9
9
|
get_output_filename,
|
|
10
|
-
validate_baseurl,
|
|
11
10
|
write_json,
|
|
12
11
|
write_summary,
|
|
13
12
|
)
|
|
14
13
|
from .assets import QlikAsset
|
|
15
|
-
from .client import QlikClient
|
|
16
|
-
from .constants import API_KEY, BASE_URL
|
|
14
|
+
from .client import QlikClient, QlikCredentials
|
|
17
15
|
|
|
18
16
|
logger = logging.getLogger(__name__)
|
|
19
17
|
|
|
@@ -59,13 +57,11 @@ def extract_all(
|
|
|
59
57
|
Store the output files locally under the given output_directory
|
|
60
58
|
"""
|
|
61
59
|
|
|
60
|
+
credentials = QlikCredentials(base_url=base_url, api_key=api_key)
|
|
62
61
|
_output_directory = output_directory or from_env(OUTPUT_DIR)
|
|
63
|
-
_base_url = validate_baseurl(base_url or from_env(BASE_URL))
|
|
64
|
-
_api_key = api_key or from_env(API_KEY)
|
|
65
62
|
|
|
66
63
|
client = QlikClient(
|
|
67
|
-
|
|
68
|
-
api_key=_api_key,
|
|
64
|
+
credentials=credentials,
|
|
69
65
|
except_http_error_statuses=except_http_error_statuses,
|
|
70
66
|
)
|
|
71
67
|
|
|
@@ -75,4 +71,4 @@ def extract_all(
|
|
|
75
71
|
filename = get_output_filename(key.name.lower(), _output_directory, ts)
|
|
76
72
|
write_json(filename, data)
|
|
77
73
|
|
|
78
|
-
write_summary(_output_directory, ts, base_url=
|
|
74
|
+
write_summary(_output_directory, ts, base_url=credentials.base_url)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
from .client import SigmaClient
|
|
2
|
-
from .credentials import
|
|
2
|
+
from .credentials import SigmaCredentials
|
|
@@ -5,7 +5,7 @@ from urllib.parse import urljoin
|
|
|
5
5
|
import requests
|
|
6
6
|
|
|
7
7
|
from ..assets import SigmaAsset
|
|
8
|
-
from .credentials import
|
|
8
|
+
from .credentials import SigmaCredentials
|
|
9
9
|
from .endpoints import EndpointFactory
|
|
10
10
|
from .pagination import Pagination
|
|
11
11
|
|
|
@@ -29,6 +29,7 @@ class SigmaClient:
|
|
|
29
29
|
self.host = credentials.host
|
|
30
30
|
self.client_id = credentials.client_id
|
|
31
31
|
self.api_token = credentials.api_token
|
|
32
|
+
self.grant_type = credentials.grant_type
|
|
32
33
|
self.headers: Optional[Dict[str, str]] = None
|
|
33
34
|
|
|
34
35
|
def _get_token(self) -> Dict[str, str]:
|
|
@@ -37,9 +38,9 @@ class SigmaClient:
|
|
|
37
38
|
token_response = requests.post( # noqa: S113
|
|
38
39
|
token_api_path,
|
|
39
40
|
data={
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
"grant_type": self.grant_type,
|
|
42
|
+
"client_id": self.client_id,
|
|
43
|
+
"client_secret": self.api_token,
|
|
43
44
|
},
|
|
44
45
|
)
|
|
45
46
|
if token_response.status_code != requests.codes.OK:
|
|
@@ -1,35 +1,19 @@
|
|
|
1
|
-
from
|
|
2
|
-
from
|
|
1
|
+
from pydantic import Field, SecretStr
|
|
2
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
3
3
|
|
|
4
|
+
CASTOR_ENV_PREFIX = "CASTOR_SIGMA_"
|
|
4
5
|
|
|
5
|
-
class CredentialsKey(Enum):
|
|
6
|
-
"""Value enum object for the credentials"""
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
CLIENT_ID = "client_id"
|
|
10
|
-
HOST = "host"
|
|
11
|
-
GRANT_TYPE = "grant_type"
|
|
12
|
-
API_TOKEN = "api_token" # noqa: S105
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
CLIENT_ALLOWED_KEYS = (
|
|
16
|
-
CredentialsKey.HOST.value,
|
|
17
|
-
CredentialsKey.CLIENT_ID.value,
|
|
18
|
-
CredentialsKey.API_TOKEN.value,
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@dataclass
|
|
23
|
-
class SigmaCredentials:
|
|
7
|
+
class SigmaCredentials(BaseSettings):
|
|
24
8
|
"""Class to handle Sigma rest API permissions"""
|
|
25
9
|
|
|
26
|
-
|
|
10
|
+
model_config = SettingsConfigDict(
|
|
11
|
+
env_prefix=CASTOR_ENV_PREFIX,
|
|
12
|
+
extra="ignore",
|
|
13
|
+
populate_by_name=True,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
api_token: str = Field(repr=False)
|
|
27
17
|
client_id: str
|
|
28
18
|
host: str
|
|
29
|
-
|
|
30
|
-
@classmethod
|
|
31
|
-
def from_secret(cls, secret: dict) -> "SigmaCredentials":
|
|
32
|
-
credentials = {
|
|
33
|
-
k: v for k, v in secret.items() if k in CLIENT_ALLOWED_KEYS
|
|
34
|
-
}
|
|
35
|
-
return cls(**credentials)
|
|
19
|
+
grant_type: str = "client_credentials"
|
|
@@ -12,7 +12,6 @@ from ...utils import (
|
|
|
12
12
|
)
|
|
13
13
|
from .assets import SigmaAsset
|
|
14
14
|
from .client import SigmaClient, SigmaCredentials
|
|
15
|
-
from .constants import API_TOKEN, CLIENT_ID, HOST
|
|
16
15
|
|
|
17
16
|
logger = logging.getLogger(__name__)
|
|
18
17
|
|
|
@@ -63,14 +62,11 @@ def extract_all(
|
|
|
63
62
|
"""
|
|
64
63
|
|
|
65
64
|
_output_directory = output_directory or from_env(OUTPUT_DIR)
|
|
66
|
-
_client_id = client_id or from_env(CLIENT_ID)
|
|
67
|
-
_host = host or from_env(HOST)
|
|
68
|
-
_api_token = api_token or from_env(API_TOKEN)
|
|
69
65
|
|
|
70
66
|
credentials = SigmaCredentials(
|
|
71
|
-
host=
|
|
72
|
-
client_id=
|
|
73
|
-
api_token=
|
|
67
|
+
host=host,
|
|
68
|
+
client_id=client_id,
|
|
69
|
+
api_token=api_token,
|
|
74
70
|
)
|
|
75
71
|
client = SigmaClient(credentials=credentials)
|
|
76
72
|
|
|
@@ -80,4 +76,4 @@ def extract_all(
|
|
|
80
76
|
filename = get_output_filename(key.name.lower(), _output_directory, ts)
|
|
81
77
|
write_json(filename, data)
|
|
82
78
|
|
|
83
|
-
write_summary(_output_directory, ts, host=
|
|
79
|
+
write_summary(_output_directory, ts, host=credentials.host)
|
|
@@ -1,104 +1,57 @@
|
|
|
1
|
-
from
|
|
2
|
-
from typing import Dict, Literal, Optional, overload
|
|
1
|
+
from typing import Optional
|
|
3
2
|
|
|
4
|
-
from
|
|
5
|
-
|
|
6
|
-
_AUTH_ERROR_MSG = "Need either user and password or token_name and token"
|
|
3
|
+
from pydantic import field_validator, model_validator
|
|
4
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
7
5
|
|
|
8
6
|
# To specify the default site on Tableau Server, you can use an empty string
|
|
9
7
|
# https://tableau.github.io/server-client-python/docs/api-ref#authentication
|
|
10
8
|
_DEFAULT_SERVER_SITE_ID = ""
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
TABLEAU_USER = "user"
|
|
17
|
-
TABLEAU_PASSWORD = "password" # noqa: S105
|
|
18
|
-
TABLEAU_TOKEN_NAME = "token_name" # noqa: S105
|
|
19
|
-
TABLEAU_TOKEN = "token" # noqa: S105
|
|
20
|
-
TABLEAU_SITE_ID = "site_id"
|
|
21
|
-
TABLEAU_SERVER_URL = "server_url"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
CREDENTIALS_ENV: Dict[CredentialsKey, str] = {
|
|
25
|
-
CredentialsKey.TABLEAU_USER: "CASTOR_TABLEAU_USER",
|
|
26
|
-
CredentialsKey.TABLEAU_PASSWORD: "CASTOR_TABLEAU_PASSWORD",
|
|
27
|
-
CredentialsKey.TABLEAU_TOKEN_NAME: "CASTOR_TABLEAU_TOKEN_NAME",
|
|
28
|
-
CredentialsKey.TABLEAU_TOKEN: "CASTOR_TABLEAU_TOKEN",
|
|
29
|
-
CredentialsKey.TABLEAU_SITE_ID: "CASTOR_TABLEAU_SITE_ID",
|
|
30
|
-
CredentialsKey.TABLEAU_SERVER_URL: "CASTOR_TABLEAU_SERVER_URL",
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@overload
|
|
35
|
-
def get_value(key: CredentialsKey, kwargs: dict) -> Optional[str]: ...
|
|
10
|
+
# In Castor APP, site_id is mandatory: users can't let this field empty
|
|
11
|
+
# In that case, we encourage users to write "Default" instead
|
|
12
|
+
_DEFAULT_SITE_ID_USER_INPUT = "default"
|
|
36
13
|
|
|
37
14
|
|
|
38
|
-
|
|
39
|
-
def get_value(
|
|
40
|
-
key: CredentialsKey, kwargs: dict, optional: Literal[True]
|
|
41
|
-
) -> Optional[str]: ...
|
|
15
|
+
TABLEAU_ENV_PREFIX = "CASTOR_TABLEAU_"
|
|
42
16
|
|
|
43
17
|
|
|
44
|
-
|
|
45
|
-
def get_value(
|
|
46
|
-
key: CredentialsKey, kwargs: dict, optional: Literal[False]
|
|
47
|
-
) -> str: ...
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def get_value(
|
|
51
|
-
key: CredentialsKey,
|
|
52
|
-
kwargs: dict,
|
|
53
|
-
optional: bool = True,
|
|
54
|
-
) -> Optional[str]:
|
|
18
|
+
class TableauRevampCredentials(BaseSettings):
|
|
55
19
|
"""
|
|
56
|
-
|
|
57
|
-
- from kwargs in priority
|
|
58
|
-
- from ENV otherwise
|
|
59
|
-
Raises an error if not found (unless optional)
|
|
20
|
+
Tableau's credentials to connect to both APIs (REST and GRAPHQL)
|
|
60
21
|
"""
|
|
61
22
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
23
|
+
model_config = SettingsConfigDict(
|
|
24
|
+
env_prefix=TABLEAU_ENV_PREFIX,
|
|
25
|
+
extra="ignore",
|
|
26
|
+
populate_by_name=True,
|
|
27
|
+
)
|
|
67
28
|
|
|
29
|
+
server_url: str
|
|
30
|
+
site_id: str = ""
|
|
68
31
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def __init__(
|
|
75
|
-
self,
|
|
76
|
-
*,
|
|
77
|
-
server_url: str,
|
|
78
|
-
site_id: Optional[str],
|
|
79
|
-
user: Optional[str],
|
|
80
|
-
password: Optional[str],
|
|
81
|
-
token_name: Optional[str],
|
|
82
|
-
token: Optional[str],
|
|
83
|
-
):
|
|
84
|
-
self.user = user
|
|
85
|
-
self.site_id = site_id or _DEFAULT_SERVER_SITE_ID
|
|
86
|
-
self.server_url = server_url
|
|
87
|
-
self.password = password
|
|
88
|
-
self.token_name = token_name
|
|
89
|
-
self.token = token
|
|
32
|
+
password: Optional[str] = None
|
|
33
|
+
token: Optional[str] = None
|
|
34
|
+
token_name: Optional[str] = None
|
|
35
|
+
user: Optional[str] = None
|
|
90
36
|
|
|
37
|
+
@field_validator("site_id", mode="before")
|
|
91
38
|
@classmethod
|
|
92
|
-
def
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
39
|
+
def _check_site_id(cls, site_id: Optional[str]) -> str:
|
|
40
|
+
if not site_id or site_id.lower() == _DEFAULT_SITE_ID_USER_INPUT:
|
|
41
|
+
return _DEFAULT_SERVER_SITE_ID
|
|
42
|
+
return site_id
|
|
43
|
+
|
|
44
|
+
@model_validator(mode="after")
|
|
45
|
+
def _check_user_xor_pat_login(self) -> "TableauRevampCredentials":
|
|
46
|
+
"""
|
|
47
|
+
Checks that credentials are correctly input, it means either:
|
|
48
|
+
- User and password are filled
|
|
49
|
+
- Token and Token name are filled
|
|
50
|
+
"""
|
|
51
|
+
user_login = self.password and self.user
|
|
52
|
+
pat_login = self.token_name and self.token
|
|
53
|
+
if not user_login and not pat_login:
|
|
54
|
+
raise ValueError("Either token or user identification is required")
|
|
55
|
+
if user_login and pat_login:
|
|
56
|
+
raise ValueError("Can't have both token and user identification")
|
|
57
|
+
return self
|
|
@@ -28,7 +28,6 @@ information_tables AS (
|
|
|
28
28
|
i.table_id || '.' || c.column_name AS column_id,
|
|
29
29
|
c.data_type,
|
|
30
30
|
c.ordinal_position,
|
|
31
|
-
c.column_default,
|
|
32
31
|
c.is_nullable,
|
|
33
32
|
c.character_maximum_length,
|
|
34
33
|
c.character_octet_length,
|
|
@@ -59,7 +58,6 @@ raw_tables AS (
|
|
|
59
58
|
a.attname AS column_name,
|
|
60
59
|
c.oid::TEXT || '.' || a.attname AS column_id,
|
|
61
60
|
a.attnum AS ordinal_position,
|
|
62
|
-
ad.adsrc AS column_default,
|
|
63
61
|
CASE
|
|
64
62
|
WHEN t.typname = 'bpchar' THEN 'char'
|
|
65
63
|
ELSE t.typname
|
|
@@ -90,7 +88,6 @@ tables AS (
|
|
|
90
88
|
COALESCE(i.data_type, r.data_type) AS data_type,
|
|
91
89
|
COALESCE(i.ordinal_position, r.ordinal_position) AS ordinal_position,
|
|
92
90
|
COALESCE(i.is_nullable, r.is_nullable) AS is_nullable,
|
|
93
|
-
COALESCE(i.column_default, r.column_default) AS column_default,
|
|
94
91
|
i.character_maximum_length::INT AS character_maximum_length,
|
|
95
92
|
i.character_octet_length::INT AS character_octet_length,
|
|
96
93
|
i.numeric_precision::INT AS numeric_precision,
|
|
@@ -117,7 +114,6 @@ views_late_binding AS (
|
|
|
117
114
|
c.data_type,
|
|
118
115
|
c.ordinal_position,
|
|
119
116
|
'YES' AS is_nullable,
|
|
120
|
-
NULL::TEXT AS column_default,
|
|
121
117
|
NULL::INT AS character_maximum_length,
|
|
122
118
|
NULL::INT AS character_octet_length,
|
|
123
119
|
NULL::INT AS numeric_precision,
|
|
@@ -162,7 +158,6 @@ external_columns AS (
|
|
|
162
158
|
c.external_type AS data_type,
|
|
163
159
|
MIN(c.columnnum) AS ordinal_position,
|
|
164
160
|
CASE c.is_nullable WHEN 'false' THEN 'NO' ELSE 'YES' END AS is_nullable,
|
|
165
|
-
NULL AS column_default,
|
|
166
161
|
NULL AS character_maximum_length,
|
|
167
162
|
NULL AS character_octet_length,
|
|
168
163
|
NULL AS numeric_precision,
|
|
@@ -2,7 +2,7 @@ import logging
|
|
|
2
2
|
from typing import Dict, List, Tuple
|
|
3
3
|
|
|
4
4
|
from ...utils import AbstractStorage, LocalStorage, write_summary
|
|
5
|
-
from ...utils.salesforce import
|
|
5
|
+
from ...utils.salesforce import SalesforceCredentials
|
|
6
6
|
from ..abstract import (
|
|
7
7
|
SupportedAssets,
|
|
8
8
|
WarehouseAsset,
|
|
@@ -93,7 +93,7 @@ def extract_all(**kwargs) -> None:
|
|
|
93
93
|
"""
|
|
94
94
|
output_directory, skip_existing = common_args(kwargs)
|
|
95
95
|
|
|
96
|
-
client = SalesforceClient(credentials=
|
|
96
|
+
client = SalesforceClient(credentials=SalesforceCredentials(**kwargs))
|
|
97
97
|
storage = LocalStorage(directory=output_directory)
|
|
98
98
|
extractor = SalesforceExtractionProcessor(
|
|
99
99
|
client=client,
|
|
@@ -18,7 +18,6 @@ SELECT
|
|
|
18
18
|
COALESCE(su.uid, pu.uid) AS column_owner_id,
|
|
19
19
|
ty.name AS data_type,
|
|
20
20
|
ty.is_nullable AS is_nullable,
|
|
21
|
-
sc.column_default AS column_default,
|
|
22
21
|
c.max_length AS character_maximum_length,
|
|
23
22
|
o.create_date AS created_at,
|
|
24
23
|
o.modify_date AS updated_at,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: castor-extractor
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.18.2
|
|
4
4
|
Summary: Extract your metadata assets.
|
|
5
5
|
Home-page: https://www.castordoc.com/
|
|
6
6
|
License: EULA
|
|
@@ -37,13 +37,13 @@ Requires-Dist: google-cloud-core (>=2.1.0,<3.0.0)
|
|
|
37
37
|
Requires-Dist: google-cloud-storage (>=2,<3)
|
|
38
38
|
Requires-Dist: google-resumable-media (>=2.0.3,<3.0.0)
|
|
39
39
|
Requires-Dist: googleapis-common-protos (>=1.53.0,<2.0.0)
|
|
40
|
-
Requires-Dist: looker-sdk (>=23.0.0) ; extra == "looker" or extra == "all"
|
|
40
|
+
Requires-Dist: looker-sdk (>=23.0.0,<24.0.0) ; extra == "looker" or extra == "all"
|
|
41
41
|
Requires-Dist: msal (>=1.20.0,<2.0.0) ; extra == "powerbi" or extra == "all"
|
|
42
|
-
Requires-Dist: numpy (<1.25) ; python_version >= "3.8" and python_version < "3.9"
|
|
43
|
-
Requires-Dist: numpy (
|
|
44
|
-
Requires-Dist:
|
|
45
|
-
Requires-Dist: pandas (
|
|
46
|
-
Requires-Dist: pandas (>=2.1
|
|
42
|
+
Requires-Dist: numpy (<1.25) ; (python_version >= "3.8" and python_version < "3.9") and (extra == "bigquery" or extra == "databricks" or extra == "all")
|
|
43
|
+
Requires-Dist: numpy (<2) ; extra == "bigquery" or extra == "databricks" or extra == "all"
|
|
44
|
+
Requires-Dist: numpy (>=1.26) ; (python_version >= "3.12" and python_version < "3.13") and (extra == "bigquery" or extra == "databricks" or extra == "all")
|
|
45
|
+
Requires-Dist: pandas (<2.1) ; (python_version >= "3.8" and python_version < "3.9") and (extra == "databricks" or extra == "all")
|
|
46
|
+
Requires-Dist: pandas (>=2.1) ; (python_version >= "3.12" and python_version < "3.13") and (extra == "databricks" or extra == "all")
|
|
47
47
|
Requires-Dist: psycopg2-binary (>=2.0.0,<3.0.0) ; extra == "metabase" or extra == "postgres" or extra == "redshift" or extra == "all"
|
|
48
48
|
Requires-Dist: pycryptodome (>=3.0.0,<4.0.0) ; extra == "metabase" or extra == "all"
|
|
49
49
|
Requires-Dist: pydantic (>=2.6,<3.0)
|
|
@@ -52,13 +52,13 @@ Requires-Dist: pymssql (>=2.2.11,<3.0.0) ; extra == "sqlserver" or extra == "all
|
|
|
52
52
|
Requires-Dist: pymysql[rsa] (>=1.1.0,<2.0.0) ; extra == "mysql" or extra == "all"
|
|
53
53
|
Requires-Dist: python-dateutil (>=2.0.0,<=3.0.0)
|
|
54
54
|
Requires-Dist: requests (>=2.0.0,<3.0.0)
|
|
55
|
-
Requires-Dist: setuptools (>=
|
|
55
|
+
Requires-Dist: setuptools (>=70,<71)
|
|
56
56
|
Requires-Dist: snowflake-connector-python (>=3.4.0,<4.0.0) ; extra == "snowflake" or extra == "all"
|
|
57
57
|
Requires-Dist: snowflake-sqlalchemy (!=1.2.5,<2.0.0) ; extra == "snowflake" or extra == "all"
|
|
58
58
|
Requires-Dist: sqlalchemy (>=1.4,<1.5)
|
|
59
59
|
Requires-Dist: sqlalchemy-bigquery[bqstorage] (>=1.0.0,<=2.0.0) ; extra == "bigquery" or extra == "all"
|
|
60
60
|
Requires-Dist: sqlalchemy-redshift (>=0.8.14,<0.9.0) ; extra == "redshift" or extra == "all"
|
|
61
|
-
Requires-Dist: tableauserverclient (==0.
|
|
61
|
+
Requires-Dist: tableauserverclient (==0.25.0) ; extra == "tableau" or extra == "all"
|
|
62
62
|
Requires-Dist: tqdm (>=4.0.0,<5.0.0)
|
|
63
63
|
Requires-Dist: typing-extensions (>=4,<5)
|
|
64
64
|
Requires-Dist: websocket-client (>=1,<2) ; extra == "qlik" or extra == "all"
|