castor-extractor 0.24.20__py3-none-any.whl → 0.24.22__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 +8 -0
- castor_extractor/commands/extract_looker_studio.py +6 -0
- castor_extractor/transformation/coalesce/client/client.py +0 -11
- castor_extractor/utils/client/api/client.py +10 -1
- castor_extractor/utils/retry.py +11 -2
- castor_extractor/visualization/looker_studio/assets.py +5 -1
- castor_extractor/visualization/looker_studio/client/admin_sdk_client.py +1 -2
- castor_extractor/visualization/looker_studio/client/credentials.py +21 -0
- castor_extractor/visualization/looker_studio/client/looker_studio_api_client.py +2 -2
- castor_extractor/visualization/looker_studio/extract.py +13 -2
- {castor_extractor-0.24.20.dist-info → castor_extractor-0.24.22.dist-info}/METADATA +9 -1
- {castor_extractor-0.24.20.dist-info → castor_extractor-0.24.22.dist-info}/RECORD +15 -16
- castor_extractor/visualization/looker_studio/client/scopes.py +0 -6
- {castor_extractor-0.24.20.dist-info → castor_extractor-0.24.22.dist-info}/LICENCE +0 -0
- {castor_extractor-0.24.20.dist-info → castor_extractor-0.24.22.dist-info}/WHEEL +0 -0
- {castor_extractor-0.24.20.dist-info → castor_extractor-0.24.22.dist-info}/entry_points.txt +0 -0
CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.24.22 - 2025-05-27
|
|
4
|
+
|
|
5
|
+
* Add retry for `Request.Timeout` on **ApiClient**
|
|
6
|
+
|
|
7
|
+
## 0.24.21 - 2025-05-26
|
|
8
|
+
|
|
9
|
+
* Looker Studio: add option to skip the extraction of view activity logs
|
|
10
|
+
|
|
3
11
|
## 0.24.20 - 2025-05-19
|
|
4
12
|
|
|
5
13
|
* Powerbi: allow custom api base and login url
|
|
@@ -24,6 +24,12 @@ def main():
|
|
|
24
24
|
"This can be the same file path as for Looker Studio."
|
|
25
25
|
),
|
|
26
26
|
)
|
|
27
|
+
parser.add_argument(
|
|
28
|
+
"--skip-view-activity-logs",
|
|
29
|
+
action="store_true",
|
|
30
|
+
default=False,
|
|
31
|
+
help="Skips the extraction of activity logs",
|
|
32
|
+
)
|
|
27
33
|
|
|
28
34
|
parser.add_argument("-o", "--output", help="Directory to write to")
|
|
29
35
|
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
from http import HTTPStatus
|
|
2
2
|
from typing import Iterator, Optional
|
|
3
3
|
|
|
4
|
-
import requests
|
|
5
|
-
|
|
6
4
|
from ....utils import (
|
|
7
5
|
APIClient,
|
|
8
6
|
BearerAuth,
|
|
9
7
|
RequestSafeMode,
|
|
10
8
|
SerializedAsset,
|
|
11
|
-
retry,
|
|
12
9
|
)
|
|
13
10
|
from ..assets import CoalesceAsset, CoalesceQualityAsset
|
|
14
11
|
from .credentials import CoalesceCredentials
|
|
@@ -20,9 +17,6 @@ from .utils import column_names_per_node, is_test, test_names_per_node
|
|
|
20
17
|
|
|
21
18
|
_LIMIT_MAX = 1_000
|
|
22
19
|
_MAX_ERRORS = 50
|
|
23
|
-
_RETRY_BASE_MS = 10 * 60 * 1000 # 10 minutes
|
|
24
|
-
_RETRY_COUNT = 2
|
|
25
|
-
_RETRY_EXCEPTIONS = [requests.exceptions.ConnectTimeout]
|
|
26
20
|
|
|
27
21
|
|
|
28
22
|
def _run_result_payload(result: dict, query_result: dict) -> dict:
|
|
@@ -75,11 +69,6 @@ class CoalesceClient(APIClient):
|
|
|
75
69
|
result = self._get(endpoint=endpoint)
|
|
76
70
|
return result["data"]
|
|
77
71
|
|
|
78
|
-
@retry(
|
|
79
|
-
exceptions=_RETRY_EXCEPTIONS,
|
|
80
|
-
max_retries=_RETRY_COUNT,
|
|
81
|
-
base_ms=_RETRY_BASE_MS,
|
|
82
|
-
)
|
|
83
72
|
def _node_details(self, environment_id: int, node_id: str) -> dict:
|
|
84
73
|
endpoint = CoalesceEndpointFactory.nodes(
|
|
85
74
|
environment_id=environment_id, node_id=node_id
|
|
@@ -5,7 +5,7 @@ from typing import Callable, Literal, Optional
|
|
|
5
5
|
import requests
|
|
6
6
|
from requests import Response
|
|
7
7
|
|
|
8
|
-
from ...retry import retry_request
|
|
8
|
+
from ...retry import retry, retry_request
|
|
9
9
|
from .auth import Auth
|
|
10
10
|
from .safe_request import RequestSafeMode, handle_response
|
|
11
11
|
from .utils import build_url
|
|
@@ -21,6 +21,10 @@ DEFAULT_TIMEOUT = 60
|
|
|
21
21
|
RETRY_ON_EXPIRED_TOKEN = 1
|
|
22
22
|
RETRY_ON_GATEWAY_TIMEOUT = 3
|
|
23
23
|
|
|
24
|
+
_TIMEOUT_RETRY_BASE_MS = 10 * 60 * 1000 # 10 minutes
|
|
25
|
+
_TIMEOUT_RETRY_COUNT = 2
|
|
26
|
+
_TIMEOUT_RETRY_EXCEPTIONS = (requests.exceptions.Timeout,)
|
|
27
|
+
|
|
24
28
|
|
|
25
29
|
def _generate_payloads(
|
|
26
30
|
method: HttpMethod,
|
|
@@ -72,6 +76,11 @@ class APIClient:
|
|
|
72
76
|
self._auth = auth
|
|
73
77
|
self._safe_mode = safe_mode
|
|
74
78
|
|
|
79
|
+
@retry(
|
|
80
|
+
exceptions=_TIMEOUT_RETRY_EXCEPTIONS,
|
|
81
|
+
max_retries=_TIMEOUT_RETRY_COUNT,
|
|
82
|
+
base_ms=_TIMEOUT_RETRY_BASE_MS,
|
|
83
|
+
)
|
|
75
84
|
def _call(
|
|
76
85
|
self,
|
|
77
86
|
method: HttpMethod,
|
castor_extractor/utils/retry.py
CHANGED
|
@@ -26,6 +26,15 @@ class RetryStrategy(Enum):
|
|
|
26
26
|
DEFAULT_STRATEGY = RetryStrategy.CONSTANT
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
def _warning(callable: Callable, exception: BaseException) -> None:
|
|
30
|
+
exception_type = type(exception)
|
|
31
|
+
exception_path = f"{exception_type.__module__}.{exception_type.__name__}"
|
|
32
|
+
callable_path = f"{callable.__module__}.{callable.__name__}"
|
|
33
|
+
|
|
34
|
+
msg = f"Exception '{exception_path}' occurred within `{callable_path}`"
|
|
35
|
+
logger.warning(msg)
|
|
36
|
+
|
|
37
|
+
|
|
29
38
|
class Retry(BaseModel):
|
|
30
39
|
"""
|
|
31
40
|
This class checks if the retry conditions are met, and if so, how long to
|
|
@@ -96,7 +105,7 @@ def retry(
|
|
|
96
105
|
try:
|
|
97
106
|
return None, callable(*args, **kwargs)
|
|
98
107
|
except exceptions_ as err:
|
|
99
|
-
|
|
108
|
+
_warning(callable, err)
|
|
100
109
|
return err, None
|
|
101
110
|
|
|
102
111
|
def _func(*args, **kwargs) -> Any:
|
|
@@ -139,7 +148,7 @@ def retry_request(
|
|
|
139
148
|
status_code = err.response.status_code
|
|
140
149
|
if status_code not in exceptions_:
|
|
141
150
|
raise err
|
|
142
|
-
|
|
151
|
+
_warning(callable, err)
|
|
143
152
|
return err, None
|
|
144
153
|
|
|
145
154
|
def _func(*args, **kwargs) -> Any:
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
from ...types import ExternalAsset
|
|
1
|
+
from ...types import ExternalAsset, classproperty
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class LookerStudioAsset(ExternalAsset):
|
|
5
5
|
ASSETS = "assets"
|
|
6
6
|
SOURCE_QUERIES = "source_queries"
|
|
7
7
|
VIEW_ACTIVITY = "view_activity"
|
|
8
|
+
|
|
9
|
+
@classproperty
|
|
10
|
+
def optional(cls) -> set["LookerStudioAsset"]:
|
|
11
|
+
return {LookerStudioAsset.VIEW_ACTIVITY}
|
|
@@ -12,7 +12,6 @@ from ....utils import (
|
|
|
12
12
|
)
|
|
13
13
|
from .credentials import LookerStudioCredentials
|
|
14
14
|
from .pagination import LookerStudioPagination
|
|
15
|
-
from .scopes import SCOPES
|
|
16
15
|
|
|
17
16
|
USER_EMAIL_FIELD = "primaryEmail"
|
|
18
17
|
|
|
@@ -26,7 +25,7 @@ class AdminSDKClient:
|
|
|
26
25
|
def __init__(self, credentials: LookerStudioCredentials):
|
|
27
26
|
self._credentials = Credentials.from_service_account_info(
|
|
28
27
|
credentials.model_dump(),
|
|
29
|
-
scopes=
|
|
28
|
+
scopes=credentials.scopes,
|
|
30
29
|
subject=credentials.admin_email, # impersonates an admin
|
|
31
30
|
)
|
|
32
31
|
self.directory_api = discovery.build(
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
1
3
|
from pydantic import BaseModel, SecretStr, field_serializer
|
|
2
4
|
|
|
5
|
+
SCOPES_NO_ACTIVITY: tuple[str, ...] = (
|
|
6
|
+
"https://www.googleapis.com/auth/datastudio",
|
|
7
|
+
"https://www.googleapis.com/auth/userinfo.profile",
|
|
8
|
+
"https://www.googleapis.com/auth/admin.directory.user.readonly",
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
DEFAULT_SCOPES: tuple[str, ...] = (
|
|
12
|
+
*SCOPES_NO_ACTIVITY,
|
|
13
|
+
"https://www.googleapis.com/auth/admin.reports.audit.readonly",
|
|
14
|
+
)
|
|
15
|
+
|
|
3
16
|
|
|
4
17
|
class LookerStudioCredentials(BaseModel):
|
|
5
18
|
"""
|
|
@@ -19,6 +32,14 @@ class LookerStudioCredentials(BaseModel):
|
|
|
19
32
|
token_uri: str
|
|
20
33
|
type: str
|
|
21
34
|
|
|
35
|
+
has_view_activity_logs: Optional[bool] = True
|
|
36
|
+
scopes: Optional[tuple] = DEFAULT_SCOPES
|
|
37
|
+
|
|
38
|
+
def model_post_init(self, __context):
|
|
39
|
+
"""Set scopes based on has_view_activity_logs after initialization"""
|
|
40
|
+
if self.has_view_activity_logs is False:
|
|
41
|
+
self.scopes = SCOPES_NO_ACTIVITY
|
|
42
|
+
|
|
22
43
|
@field_serializer("private_key")
|
|
23
44
|
def dump_secret(self, pk):
|
|
24
45
|
"""When using model_dump, show private_key value"""
|
|
@@ -16,7 +16,6 @@ from .credentials import LookerStudioCredentials
|
|
|
16
16
|
from .endpoints import LookerStudioAPIEndpoint
|
|
17
17
|
from .enums import LookerStudioAssetType
|
|
18
18
|
from .pagination import LookerStudioPagination
|
|
19
|
-
from .scopes import SCOPES
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
@contextmanager
|
|
@@ -47,7 +46,8 @@ class LookerStudioAPIAuth(BearerAuth):
|
|
|
47
46
|
that user and make requests on that user's behalf.
|
|
48
47
|
"""
|
|
49
48
|
self._credentials = Credentials.from_service_account_info(
|
|
50
|
-
credentials.model_dump(),
|
|
49
|
+
credentials.model_dump(),
|
|
50
|
+
scopes=credentials.scopes,
|
|
51
51
|
)
|
|
52
52
|
if subject:
|
|
53
53
|
self._credentials = self._credentials.with_subject(subject)
|
|
@@ -23,8 +23,14 @@ LOOKER_STUDIO_ADMIN_EMAIL = "CASTOR_LOOKER_STUDIO_ADMIN_EMAIL"
|
|
|
23
23
|
|
|
24
24
|
def iterate_all_data(
|
|
25
25
|
client: LookerStudioClient,
|
|
26
|
+
has_view_activity_logs: bool = True,
|
|
26
27
|
) -> Iterable[tuple[LookerStudioAsset, Union[list, dict]]]:
|
|
27
|
-
|
|
28
|
+
assets_to_extract = LookerStudioAsset.mandatory
|
|
29
|
+
|
|
30
|
+
if has_view_activity_logs:
|
|
31
|
+
assets_to_extract.add(LookerStudioAsset.VIEW_ACTIVITY)
|
|
32
|
+
|
|
33
|
+
for asset in assets_to_extract:
|
|
28
34
|
logger.info(f"Extracting {asset.name} from API")
|
|
29
35
|
data = list(deep_serialize(client.fetch(asset)))
|
|
30
36
|
yield asset, data
|
|
@@ -45,6 +51,8 @@ def _credentials(params: dict) -> LookerStudioCredentials:
|
|
|
45
51
|
LOOKER_STUDIO_ADMIN_EMAIL
|
|
46
52
|
)
|
|
47
53
|
credentials["admin_email"] = admin_email
|
|
54
|
+
has_view_activity_logs = not params["skip_view_activity_logs"]
|
|
55
|
+
credentials["has_view_activity_logs"] = has_view_activity_logs
|
|
48
56
|
return LookerStudioCredentials(**credentials)
|
|
49
57
|
|
|
50
58
|
|
|
@@ -68,7 +76,10 @@ def extract_all(**kwargs) -> None:
|
|
|
68
76
|
the given output_directory.
|
|
69
77
|
"""
|
|
70
78
|
output_directory = kwargs.get("output") or from_env(OUTPUT_DIR)
|
|
79
|
+
|
|
71
80
|
credentials = _credentials(kwargs)
|
|
81
|
+
has_view_activity_logs = bool(credentials.has_view_activity_logs)
|
|
82
|
+
|
|
72
83
|
bigquery_credentials = _bigquery_credentials_or_none(kwargs)
|
|
73
84
|
|
|
74
85
|
client = LookerStudioClient(
|
|
@@ -77,7 +88,7 @@ def extract_all(**kwargs) -> None:
|
|
|
77
88
|
)
|
|
78
89
|
ts = current_timestamp()
|
|
79
90
|
|
|
80
|
-
for key, data in iterate_all_data(client):
|
|
91
|
+
for key, data in iterate_all_data(client, has_view_activity_logs):
|
|
81
92
|
filename = get_output_filename(key.name.lower(), output_directory, ts)
|
|
82
93
|
write_json(filename, data)
|
|
83
94
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: castor-extractor
|
|
3
|
-
Version: 0.24.
|
|
3
|
+
Version: 0.24.22
|
|
4
4
|
Summary: Extract your metadata assets.
|
|
5
5
|
Home-page: https://www.castordoc.com/
|
|
6
6
|
License: EULA
|
|
@@ -215,6 +215,14 @@ For any questions or bug report, contact us at [support@coalesce.io](mailto:supp
|
|
|
215
215
|
|
|
216
216
|
# Changelog
|
|
217
217
|
|
|
218
|
+
## 0.24.22 - 2025-05-27
|
|
219
|
+
|
|
220
|
+
* Add retry for `Request.Timeout` on **ApiClient**
|
|
221
|
+
|
|
222
|
+
## 0.24.21 - 2025-05-26
|
|
223
|
+
|
|
224
|
+
* Looker Studio: add option to skip the extraction of view activity logs
|
|
225
|
+
|
|
218
226
|
## 0.24.20 - 2025-05-19
|
|
219
227
|
|
|
220
228
|
* Powerbi: allow custom api base and login url
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
CHANGELOG.md,sha256=
|
|
1
|
+
CHANGELOG.md,sha256=8EyATqcpMtcJ3LhQgQadRhcDiEULwOXYw40137Y5jgs,17936
|
|
2
2
|
Dockerfile,sha256=xQ05-CFfGShT3oUqaiumaldwA288dj9Yb_pxofQpufg,301
|
|
3
3
|
DockerfileUsage.md,sha256=2hkJQF-5JuuzfPZ7IOxgM6QgIQW7l-9oRMFVwyXC4gE,998
|
|
4
4
|
LICENCE,sha256=sL-IGa4hweyya1HgzMskrRdybbIa2cktzxb5qmUgDg8,8254
|
|
@@ -10,7 +10,7 @@ castor_extractor/commands/extract_confluence.py,sha256=blYcnDqywXNKRQ1aZAD9FclhL
|
|
|
10
10
|
castor_extractor/commands/extract_databricks.py,sha256=SVKyoa-BBUQAM6HRHf1Wdg9-tpICic2yyvXQwHcNBhA,1264
|
|
11
11
|
castor_extractor/commands/extract_domo.py,sha256=jvAawUsUTHrwCn_koK6StmQr4n_b5GyvJi6uu6WS0SM,1061
|
|
12
12
|
castor_extractor/commands/extract_looker.py,sha256=cySLiolLCgrREJ9d0kMrJ7P8K3efHTBTzShalWVfI3A,1214
|
|
13
|
-
castor_extractor/commands/extract_looker_studio.py,sha256=
|
|
13
|
+
castor_extractor/commands/extract_looker_studio.py,sha256=M7wx8XZScLizCI2vq80aj88vYrdiHChiCiebrrChlZY,1090
|
|
14
14
|
castor_extractor/commands/extract_metabase_api.py,sha256=NXctea4GT_1iRDitY92nV3TKSqhjEUwYSxwPJMRS3iw,786
|
|
15
15
|
castor_extractor/commands/extract_metabase_db.py,sha256=tYIhTPPgj1mN-07LyWcL6e-YoGp7HCWda58-5Ukyg_I,1255
|
|
16
16
|
castor_extractor/commands/extract_mode.py,sha256=Q4iO-VAKMg4zFPejhAO-foZibL5Ht3jsnhWKwJ0oqUU,823
|
|
@@ -76,7 +76,7 @@ castor_extractor/transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
|
|
|
76
76
|
castor_extractor/transformation/coalesce/__init__.py,sha256=CW_qdtEfwgJRsCyBlk5hNlxwEO-VV6mBXZvkRbND_J8,112
|
|
77
77
|
castor_extractor/transformation/coalesce/assets.py,sha256=pzccYPP66c9PAnVroemx7-6MeRHw7Ft1OlTC6jIamAA,363
|
|
78
78
|
castor_extractor/transformation/coalesce/client/__init__.py,sha256=VRmVpH29rOghtDQnCN7dAdA0dI0Lxseu4BC8rnwM9dU,80
|
|
79
|
-
castor_extractor/transformation/coalesce/client/client.py,sha256
|
|
79
|
+
castor_extractor/transformation/coalesce/client/client.py,sha256=o-BlVqdzcQ2RhrmShsNFXVhsmJF4i0pP6DmiWGAE2dY,6172
|
|
80
80
|
castor_extractor/transformation/coalesce/client/credentials.py,sha256=jbJxjbdPspf-dzYKfeb7oqL_8TXd1nvkJrjAcdAnLPc,548
|
|
81
81
|
castor_extractor/transformation/coalesce/client/endpoint.py,sha256=0uLh7dpA1vsR9qr_50SEYV_-heQE4BwED9oNMgYsL-w,1272
|
|
82
82
|
castor_extractor/transformation/coalesce/client/type.py,sha256=oiiVP9NL0ijTXyQmaB8aJVYckc7m-m8ZgMyNIAduUKE,43
|
|
@@ -106,7 +106,7 @@ castor_extractor/utils/client/abstract.py,sha256=CWF7_afNpEZ3jor-22wXbKIvM20ukHk
|
|
|
106
106
|
castor_extractor/utils/client/api/__init__.py,sha256=vlG7WXznYgLTn3XyMGsyUkgRkup8FbKM14EXJ8mv-b0,264
|
|
107
107
|
castor_extractor/utils/client/api/auth.py,sha256=lq0K3UEl1vwIIa_vKTdlpIQPdE5K1-5DXmCwO4dKzng,1890
|
|
108
108
|
castor_extractor/utils/client/api/auth_test.py,sha256=LlyXytnatg6ZzR4Zkvzk0BH99FYhHX7qn_nyr2MSnDI,1305
|
|
109
|
-
castor_extractor/utils/client/api/client.py,sha256=
|
|
109
|
+
castor_extractor/utils/client/api/client.py,sha256=En1V9eglhB71q5jZwi5XhNZanLb7IUKfd4AT-sSexJk,4866
|
|
110
110
|
castor_extractor/utils/client/api/client_test.py,sha256=FM3ZxsLLfMOBn44cXX6FIgnA31-5TTNIyp9D4LBwtXE,1222
|
|
111
111
|
castor_extractor/utils/client/api/pagination.py,sha256=ph5TYqPiyFGgygsIhCATAHPIQ9UJNZyiTcqlyRdGEno,2460
|
|
112
112
|
castor_extractor/utils/client/api/pagination_test.py,sha256=jCOgXFXrH-jrCxe2dfk80ZksJF-EtmpJPU11BGabsqk,1385
|
|
@@ -138,7 +138,7 @@ castor_extractor/utils/pager/pager.py,sha256=93Rw7jCz6GnqrS4HfYfKYV2xgEx2esl1qC9
|
|
|
138
138
|
castor_extractor/utils/pager/pager_on_id.py,sha256=jBvmlEhkJ-sODkNyz1KyyXHobLsNhC4AwhOwYvLyB4E,1967
|
|
139
139
|
castor_extractor/utils/pager/pager_on_id_test.py,sha256=eDGrIYPGffuKPUATgu5fiXIwPKdSwEXGgTtfMiHqoj0,1601
|
|
140
140
|
castor_extractor/utils/pager/pager_test.py,sha256=PQOXQwQD2wOP0xzZfNTuLxcn3Bpa4FCASVklH71GO_s,1699
|
|
141
|
-
castor_extractor/utils/retry.py,sha256=
|
|
141
|
+
castor_extractor/utils/retry.py,sha256=xRlAxHRnjmjh2sDUuuUSS-s38pokoAvSgSKjdgWGqbc,5020
|
|
142
142
|
castor_extractor/utils/retry_test.py,sha256=j_6IJStBomEhxmGpIY9IIlESgMxhcDpmIKj24unLqlA,2892
|
|
143
143
|
castor_extractor/utils/safe.py,sha256=gvIMRIoggdVeYMl222IYqXnHVDninDklFMlAHt-WldA,1948
|
|
144
144
|
castor_extractor/utils/safe_test.py,sha256=IHN1Z761tYMFslYC-2HAfkXmFPh4LYSqNLs4QZwykjk,2160
|
|
@@ -186,18 +186,17 @@ castor_extractor/visualization/looker/fields.py,sha256=7oC7p-3Wp7XHBP_FT_D1wH3kI
|
|
|
186
186
|
castor_extractor/visualization/looker/fields_test.py,sha256=7Cwq8Qky6aTZg8nCHp1gmPJtd9pGNB4QeMIRRWdHo5w,782
|
|
187
187
|
castor_extractor/visualization/looker/multithreading.py,sha256=Muuh3usBLqtv3sfHoyPYJ6jJ7V5ajR6N9ZJ_F-bNc60,2608
|
|
188
188
|
castor_extractor/visualization/looker_studio/__init__.py,sha256=GccG-GJXoNhjXFPkw-rHHZ0SXVQTFKjqkMIYHVeu3T4,175
|
|
189
|
-
castor_extractor/visualization/looker_studio/assets.py,sha256=
|
|
189
|
+
castor_extractor/visualization/looker_studio/assets.py,sha256=rI73rbVrfwkkepqZr0zPouP2lPUfJxSi21RKtOTHtAA,308
|
|
190
190
|
castor_extractor/visualization/looker_studio/client/__init__.py,sha256=YkQaVDJa-7KSwdOLjtgKJMRiafbGNKC_46YVx0hYZ1Q,129
|
|
191
|
-
castor_extractor/visualization/looker_studio/client/admin_sdk_client.py,sha256=
|
|
191
|
+
castor_extractor/visualization/looker_studio/client/admin_sdk_client.py,sha256=HIeyT9JTW1TPwVzD2Q-VfJ99jMP80Z-4CznKAnTnp2w,3493
|
|
192
192
|
castor_extractor/visualization/looker_studio/client/client.py,sha256=6sTfLRUhuxhkqDjC2ZBEaw6YnR6ze8-_VW2rc1u9Ksk,3191
|
|
193
|
-
castor_extractor/visualization/looker_studio/client/credentials.py,sha256=
|
|
193
|
+
castor_extractor/visualization/looker_studio/client/credentials.py,sha256=F4ISI8Ua_HJsMuGhYql28o3hKYR4sL_uzkrUkRiekRo,1347
|
|
194
194
|
castor_extractor/visualization/looker_studio/client/endpoints.py,sha256=5eY-ffqNDdlDBOOpiF7LpjyHMrzeClJktidCr1pTDUs,669
|
|
195
195
|
castor_extractor/visualization/looker_studio/client/enums.py,sha256=fHgemTaQpnwee8cw1YQVDsVnH--vTyFwT4Px8aVYYHQ,167
|
|
196
|
-
castor_extractor/visualization/looker_studio/client/looker_studio_api_client.py,sha256=
|
|
196
|
+
castor_extractor/visualization/looker_studio/client/looker_studio_api_client.py,sha256=Phq378VEaFLD-nyP2_A1wge6HUP45jSthhlNjD7aqSg,4085
|
|
197
197
|
castor_extractor/visualization/looker_studio/client/pagination.py,sha256=9HQ3Rkdiz2VB6AvYtZ0F-WouiD0pMmdZyAmkv-3wh08,783
|
|
198
198
|
castor_extractor/visualization/looker_studio/client/queries/query.sql,sha256=Ub4rdrJ5WTPWKI-eVmXrNMv0Ktmti4b-93zZBr0xEB0,1426
|
|
199
|
-
castor_extractor/visualization/looker_studio/
|
|
200
|
-
castor_extractor/visualization/looker_studio/extract.py,sha256=cHyroNZ1fKoBTvIbEebnKDrU3xpkcEgIPJy75ljCL70,2607
|
|
199
|
+
castor_extractor/visualization/looker_studio/extract.py,sha256=uNpvg4wtFflmpkqXFfo_9Nm12AEKXBOCKKajIggySho,3026
|
|
201
200
|
castor_extractor/visualization/metabase/__init__.py,sha256=3E36cmkMyEgBB6Ot5rWk-N75i0G-7k24QTlc-Iol4pM,193
|
|
202
201
|
castor_extractor/visualization/metabase/assets.py,sha256=nu3FwQBU_hdS2DBvgXAwQlEEi76QiNK2tMKEtMyctaY,2874
|
|
203
202
|
castor_extractor/visualization/metabase/client/__init__.py,sha256=KBvaPMofBRV3m_sZAnKNCrJGr-Z88EbpdzEzWPQ_uBk,99
|
|
@@ -426,8 +425,8 @@ castor_extractor/warehouse/sqlserver/queries/table.sql,sha256=kbBQP-TdG5px1IVgyx
|
|
|
426
425
|
castor_extractor/warehouse/sqlserver/queries/user.sql,sha256=gOrZsMVypusR2dc4vwVs4E1a-CliRsr_UjnD2EbXs-A,94
|
|
427
426
|
castor_extractor/warehouse/sqlserver/query.py,sha256=g0hPT-RmeGi2DyenAi3o72cTlQsLToXIFYojqc8E5fQ,533
|
|
428
427
|
castor_extractor/warehouse/synapse/queries/column.sql,sha256=lNcFoIW3Y0PFOqoOzJEXmPvZvfAsY0AP63Mu2LuPzPo,1351
|
|
429
|
-
castor_extractor-0.24.
|
|
430
|
-
castor_extractor-0.24.
|
|
431
|
-
castor_extractor-0.24.
|
|
432
|
-
castor_extractor-0.24.
|
|
433
|
-
castor_extractor-0.24.
|
|
428
|
+
castor_extractor-0.24.22.dist-info/LICENCE,sha256=sL-IGa4hweyya1HgzMskrRdybbIa2cktzxb5qmUgDg8,8254
|
|
429
|
+
castor_extractor-0.24.22.dist-info/METADATA,sha256=VTqwYHqBEng4wSZ5N88tT1z6Y2OdS9uETv4qIE3CZVw,25389
|
|
430
|
+
castor_extractor-0.24.22.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
431
|
+
castor_extractor-0.24.22.dist-info/entry_points.txt,sha256=_F-qeZCybjoMkNb9ErEhnyqXuG6afHIFQhakdBHZsr4,1803
|
|
432
|
+
castor_extractor-0.24.22.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|