castor-extractor 0.24.1__py3-none-any.whl → 0.24.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 +4 -0
- castor_extractor/commands/extract_tableau.py +2 -2
- castor_extractor/visualization/tableau/__init__.py +3 -0
- castor_extractor/visualization/{tableau_revamp → tableau}/assets.py +4 -4
- castor_extractor/visualization/tableau/client/__init__.py +2 -0
- castor_extractor/visualization/{tableau_revamp → tableau}/client/client.py +15 -15
- castor_extractor/visualization/{tableau_revamp → tableau}/client/client_metadata_api.py +9 -9
- castor_extractor/visualization/{tableau_revamp → tableau}/client/client_rest_api.py +6 -6
- castor_extractor/visualization/{tableau_revamp → tableau}/client/client_tsc.py +9 -9
- castor_extractor/visualization/{tableau_revamp → tableau}/client/credentials.py +2 -2
- castor_extractor/visualization/{tableau_revamp → tableau}/client/gql_queries.py +8 -8
- castor_extractor/visualization/{tableau_revamp → tableau}/client/rest_fields.py +10 -10
- castor_extractor/visualization/{tableau_revamp → tableau}/extract.py +7 -7
- {castor_extractor-0.24.1.dist-info → castor_extractor-0.24.2.dist-info}/METADATA +5 -1
- {castor_extractor-0.24.1.dist-info → castor_extractor-0.24.2.dist-info}/RECORD +20 -20
- castor_extractor/visualization/tableau_revamp/__init__.py +0 -3
- castor_extractor/visualization/tableau_revamp/client/__init__.py +0 -2
- /castor_extractor/visualization/{tableau_revamp → tableau}/client/errors.py +0 -0
- /castor_extractor/visualization/{tableau_revamp → tableau}/constants.py +0 -0
- {castor_extractor-0.24.1.dist-info → castor_extractor-0.24.2.dist-info}/LICENCE +0 -0
- {castor_extractor-0.24.1.dist-info → castor_extractor-0.24.2.dist-info}/WHEEL +0 -0
- {castor_extractor-0.24.1.dist-info → castor_extractor-0.24.2.dist-info}/entry_points.txt +0 -0
CHANGELOG.md
CHANGED
|
@@ -2,7 +2,7 @@ import logging
|
|
|
2
2
|
from argparse import ArgumentParser
|
|
3
3
|
|
|
4
4
|
from castor_extractor.utils import parse_filled_arguments # type: ignore
|
|
5
|
-
from castor_extractor.visualization import
|
|
5
|
+
from castor_extractor.visualization import tableau # type: ignore
|
|
6
6
|
|
|
7
7
|
logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s")
|
|
8
8
|
|
|
@@ -36,4 +36,4 @@ def main():
|
|
|
36
36
|
|
|
37
37
|
parser.add_argument("-o", "--output", help="Directory to write to")
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
tableau.extract_all(**parse_filled_arguments(parser))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from ...types import ExternalAsset
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class TableauAsset(ExternalAsset):
|
|
5
5
|
"""
|
|
6
6
|
Tableau assets
|
|
7
7
|
"""
|
|
@@ -23,7 +23,7 @@ class TableauRevampAsset(ExternalAsset):
|
|
|
23
23
|
|
|
24
24
|
# assets that are only available for clients using Tableau Pulse
|
|
25
25
|
TABLEAU_PULSE_ASSETS = (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
TableauAsset.METRIC,
|
|
27
|
+
TableauAsset.METRIC_DEFINITION,
|
|
28
|
+
TableauAsset.SUBSCRIPTION,
|
|
29
29
|
)
|
|
@@ -4,31 +4,31 @@ from typing import Optional
|
|
|
4
4
|
import tableauserverclient as TSC # type: ignore
|
|
5
5
|
|
|
6
6
|
from ....utils import SerializedAsset
|
|
7
|
-
from ..assets import TABLEAU_PULSE_ASSETS,
|
|
7
|
+
from ..assets import TABLEAU_PULSE_ASSETS, TableauAsset
|
|
8
8
|
from ..constants import CREDENTIALS_SITE_ID_KEY, DEFAULT_TIMEOUT_SECONDS
|
|
9
9
|
from .client_metadata_api import TableauClientMetadataApi
|
|
10
10
|
from .client_rest_api import TableauClientRestApi
|
|
11
11
|
from .client_tsc import TableauClientTSC
|
|
12
|
-
from .credentials import
|
|
12
|
+
from .credentials import TableauCredentials
|
|
13
13
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
|
|
16
16
|
# these assets must be extracted via TableauServerClient (TSC)
|
|
17
17
|
_TSC_ASSETS = (
|
|
18
18
|
# projects are not available in Metadata API
|
|
19
|
-
|
|
19
|
+
TableauAsset.PROJECT,
|
|
20
20
|
# view count are not available in Metadata API
|
|
21
|
-
|
|
21
|
+
TableauAsset.USAGE,
|
|
22
22
|
# only users who published content can be extracted from MetadataAPI
|
|
23
|
-
|
|
23
|
+
TableauAsset.USER,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
# these assets must be extracted via the REST API
|
|
27
27
|
_REST_API_ASSETS = (
|
|
28
28
|
# Tableau Pulse assets are only available in REST API
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
TableauAsset.METRIC,
|
|
30
|
+
TableauAsset.METRIC_DEFINITION,
|
|
31
|
+
TableauAsset.SUBSCRIPTION,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
logging.getLogger("tableau.endpoint").setLevel(logging.WARNING)
|
|
@@ -109,7 +109,7 @@ def _server(
|
|
|
109
109
|
return server
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
class
|
|
112
|
+
class TableauClient:
|
|
113
113
|
"""
|
|
114
114
|
Connect to Tableau's API and extract assets.
|
|
115
115
|
|
|
@@ -119,7 +119,7 @@ class TableauRevampClient:
|
|
|
119
119
|
|
|
120
120
|
def __init__(
|
|
121
121
|
self,
|
|
122
|
-
credentials:
|
|
122
|
+
credentials: TableauCredentials,
|
|
123
123
|
timeout_sec: int = DEFAULT_TIMEOUT_SECONDS,
|
|
124
124
|
with_pulse: bool = False,
|
|
125
125
|
override_page_size: Optional[int] = None,
|
|
@@ -186,7 +186,7 @@ class TableauRevampClient:
|
|
|
186
186
|
)
|
|
187
187
|
|
|
188
188
|
def _fetch_datasources(self) -> SerializedAsset:
|
|
189
|
-
asset =
|
|
189
|
+
asset = TableauAsset.DATASOURCE
|
|
190
190
|
|
|
191
191
|
datasources = self._client_metadata.fetch(asset)
|
|
192
192
|
tsc_datasources = self._client_tsc.fetch(asset)
|
|
@@ -194,7 +194,7 @@ class TableauRevampClient:
|
|
|
194
194
|
return _merge_datasources(datasources, tsc_datasources)
|
|
195
195
|
|
|
196
196
|
def _fetch_workbooks(self) -> SerializedAsset:
|
|
197
|
-
asset =
|
|
197
|
+
asset = TableauAsset.WORKBOOK
|
|
198
198
|
|
|
199
199
|
site_id = self._credentials.site_id
|
|
200
200
|
workbooks = self._client_metadata.fetch(asset)
|
|
@@ -206,7 +206,7 @@ class TableauRevampClient:
|
|
|
206
206
|
|
|
207
207
|
def fetch(
|
|
208
208
|
self,
|
|
209
|
-
asset:
|
|
209
|
+
asset: TableauAsset,
|
|
210
210
|
) -> SerializedAsset:
|
|
211
211
|
"""
|
|
212
212
|
Extract the given Tableau Asset
|
|
@@ -217,11 +217,11 @@ class TableauRevampClient:
|
|
|
217
217
|
|
|
218
218
|
logger.info(f"Extracting {asset.name}...")
|
|
219
219
|
|
|
220
|
-
if asset ==
|
|
220
|
+
if asset == TableauAsset.DATASOURCE:
|
|
221
221
|
# two APIs are required to extract datasources
|
|
222
222
|
return self._fetch_datasources()
|
|
223
223
|
|
|
224
|
-
if asset ==
|
|
224
|
+
if asset == TableauAsset.WORKBOOK:
|
|
225
225
|
# two APIs are required to extract workbooks
|
|
226
226
|
return self._fetch_workbooks()
|
|
227
227
|
|
|
@@ -4,21 +4,21 @@ from typing import Optional
|
|
|
4
4
|
import tableauserverclient as TSC # type: ignore
|
|
5
5
|
|
|
6
6
|
from ....utils import SerializedAsset, retry
|
|
7
|
-
from ..assets import
|
|
7
|
+
from ..assets import TableauAsset
|
|
8
8
|
from ..constants import DEFAULT_PAGE_SIZE
|
|
9
9
|
from .errors import TableauApiError, TableauApiTimeout
|
|
10
10
|
from .gql_queries import FIELDS_QUERIES, GQL_QUERIES, QUERY_TEMPLATE
|
|
11
11
|
|
|
12
12
|
# increase the value when extraction is too slow
|
|
13
13
|
# decrease the value when timeouts arise
|
|
14
|
-
_CUSTOM_PAGE_SIZE: dict[
|
|
14
|
+
_CUSTOM_PAGE_SIZE: dict[TableauAsset, int] = {
|
|
15
15
|
# for some clients, extraction of columns tend to hit the node limit
|
|
16
16
|
# https://community.tableau.com/s/question/0D54T00000YuK60SAF/metadata-query-nodelimitexceeded-error
|
|
17
17
|
# the workaround is to reduce pagination
|
|
18
|
-
|
|
18
|
+
TableauAsset.COLUMN: 50,
|
|
19
19
|
# fields are light but volumes are bigger
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
TableauAsset.FIELD: 1000,
|
|
21
|
+
TableauAsset.TABLE: 50,
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
_TIMEOUT_MESSAGE = (
|
|
@@ -115,7 +115,7 @@ class TableauClientMetadataApi:
|
|
|
115
115
|
result_pages = gql_query_scroll(self._server, query, resource)
|
|
116
116
|
return [asset for page in result_pages for asset in page]
|
|
117
117
|
|
|
118
|
-
def _page_size(self, asset:
|
|
118
|
+
def _page_size(self, asset: TableauAsset) -> int:
|
|
119
119
|
return (
|
|
120
120
|
self._override_page_size
|
|
121
121
|
or _CUSTOM_PAGE_SIZE.get(asset)
|
|
@@ -124,7 +124,7 @@ class TableauClientMetadataApi:
|
|
|
124
124
|
|
|
125
125
|
def _fetch_fields(self) -> SerializedAsset:
|
|
126
126
|
result: SerializedAsset = []
|
|
127
|
-
page_size = self._page_size(
|
|
127
|
+
page_size = self._page_size(TableauAsset.FIELD)
|
|
128
128
|
for resource, fields in FIELDS_QUERIES:
|
|
129
129
|
current = self._call(resource, fields, page_size)
|
|
130
130
|
result.extend(current)
|
|
@@ -132,9 +132,9 @@ class TableauClientMetadataApi:
|
|
|
132
132
|
|
|
133
133
|
def fetch(
|
|
134
134
|
self,
|
|
135
|
-
asset:
|
|
135
|
+
asset: TableauAsset,
|
|
136
136
|
) -> SerializedAsset:
|
|
137
|
-
if asset ==
|
|
137
|
+
if asset == TableauAsset.FIELD:
|
|
138
138
|
return self._fetch_fields()
|
|
139
139
|
|
|
140
140
|
page_size = self._page_size(asset)
|
|
@@ -5,7 +5,7 @@ import requests
|
|
|
5
5
|
import tableauserverclient as TSC # type: ignore
|
|
6
6
|
|
|
7
7
|
from ....utils import SerializedAsset, deduplicate
|
|
8
|
-
from ..assets import
|
|
8
|
+
from ..assets import TableauAsset
|
|
9
9
|
from .rest_fields import REST_FIELDS
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
@@ -17,7 +17,7 @@ _METRICS_DEFINITION_URL = "{base}/pulse/site/{site}/{definition_id}"
|
|
|
17
17
|
|
|
18
18
|
def _pick(
|
|
19
19
|
data: SerializedAsset,
|
|
20
|
-
asset:
|
|
20
|
+
asset: TableauAsset,
|
|
21
21
|
) -> SerializedAsset:
|
|
22
22
|
keys = REST_FIELDS[asset]
|
|
23
23
|
return [{key: row[key] for key in keys} for row in data]
|
|
@@ -107,18 +107,18 @@ class TableauClientRestApi:
|
|
|
107
107
|
|
|
108
108
|
def fetch(
|
|
109
109
|
self,
|
|
110
|
-
asset:
|
|
110
|
+
asset: TableauAsset,
|
|
111
111
|
) -> SerializedAsset:
|
|
112
|
-
if asset ==
|
|
112
|
+
if asset == TableauAsset.SUBSCRIPTION:
|
|
113
113
|
# https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_pulse.htm#PulseSubscriptionService_ListSubscriptions
|
|
114
114
|
data = self._call(path=_PULSE_API, target="subscriptions")
|
|
115
115
|
|
|
116
|
-
elif asset ==
|
|
116
|
+
elif asset == TableauAsset.METRIC_DEFINITION:
|
|
117
117
|
# https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_pulse.htm#MetricQueryService_ListDefinitions
|
|
118
118
|
data = self._call(path=_PULSE_API, target="definitions")
|
|
119
119
|
self._compute_metric_url(data)
|
|
120
120
|
|
|
121
|
-
elif asset ==
|
|
121
|
+
elif asset == TableauAsset.METRIC:
|
|
122
122
|
# https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_pulse.htm#MetricQueryService_ListMetrics
|
|
123
123
|
definitions = self._call(path=_PULSE_API, target="definitions")
|
|
124
124
|
data = self._fetch_metrics(definitions)
|
|
@@ -4,7 +4,7 @@ from typing import Any
|
|
|
4
4
|
import tableauserverclient as TSC # type: ignore
|
|
5
5
|
|
|
6
6
|
from ....utils import JsonType, SerializedAsset
|
|
7
|
-
from ..assets import
|
|
7
|
+
from ..assets import TableauAsset
|
|
8
8
|
from .rest_fields import REST_FIELDS
|
|
9
9
|
|
|
10
10
|
|
|
@@ -30,13 +30,13 @@ class TableauClientTSC:
|
|
|
30
30
|
def _pick_fields(
|
|
31
31
|
self,
|
|
32
32
|
data: Iterable,
|
|
33
|
-
asset:
|
|
33
|
+
asset: TableauAsset,
|
|
34
34
|
) -> Iterator[dict]:
|
|
35
35
|
keys = REST_FIELDS[asset]
|
|
36
36
|
|
|
37
37
|
for row in data:
|
|
38
38
|
fields = {key: _pick(row, key) for key in keys}
|
|
39
|
-
if asset ==
|
|
39
|
+
if asset == TableauAsset.USER:
|
|
40
40
|
self._server.users.populate_groups(row)
|
|
41
41
|
fields["group_ids"] = [group.id for group in row.groups]
|
|
42
42
|
|
|
@@ -44,21 +44,21 @@ class TableauClientTSC:
|
|
|
44
44
|
|
|
45
45
|
def fetch(
|
|
46
46
|
self,
|
|
47
|
-
asset:
|
|
47
|
+
asset: TableauAsset,
|
|
48
48
|
) -> SerializedAsset:
|
|
49
|
-
if asset ==
|
|
49
|
+
if asset == TableauAsset.DATASOURCE:
|
|
50
50
|
data = TSC.Pager(self._server.datasources)
|
|
51
51
|
|
|
52
|
-
elif asset ==
|
|
52
|
+
elif asset == TableauAsset.PROJECT:
|
|
53
53
|
data = TSC.Pager(self._server.projects)
|
|
54
54
|
|
|
55
|
-
elif asset ==
|
|
55
|
+
elif asset == TableauAsset.USAGE:
|
|
56
56
|
data = TSC.Pager(self._server.views, usage=True)
|
|
57
57
|
|
|
58
|
-
elif asset ==
|
|
58
|
+
elif asset == TableauAsset.USER:
|
|
59
59
|
data = TSC.Pager(self._server.users)
|
|
60
60
|
|
|
61
|
-
elif asset ==
|
|
61
|
+
elif asset == TableauAsset.WORKBOOK:
|
|
62
62
|
data = TSC.Pager(self._server.workbooks)
|
|
63
63
|
|
|
64
64
|
else:
|
|
@@ -15,7 +15,7 @@ _DEFAULT_SITE_ID_USER_INPUT = "default"
|
|
|
15
15
|
TABLEAU_ENV_PREFIX = "CASTOR_TABLEAU_"
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class
|
|
18
|
+
class TableauCredentials(BaseSettings):
|
|
19
19
|
"""
|
|
20
20
|
Tableau's credentials to connect to both APIs (REST and GRAPHQL)
|
|
21
21
|
"""
|
|
@@ -42,7 +42,7 @@ class TableauRevampCredentials(BaseSettings):
|
|
|
42
42
|
return site_id
|
|
43
43
|
|
|
44
44
|
@model_validator(mode="after")
|
|
45
|
-
def _check_user_xor_pat_login(self) -> "
|
|
45
|
+
def _check_user_xor_pat_login(self) -> "TableauCredentials":
|
|
46
46
|
"""
|
|
47
47
|
Checks that credentials are correctly input, it means either:
|
|
48
48
|
- User and password are filled
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from ..assets import
|
|
1
|
+
from ..assets import TableauAsset
|
|
2
2
|
|
|
3
3
|
QUERY_TEMPLATE = """
|
|
4
4
|
{{
|
|
@@ -128,13 +128,13 @@ workbook { id }
|
|
|
128
128
|
"""
|
|
129
129
|
|
|
130
130
|
|
|
131
|
-
GQL_QUERIES: dict[
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
GQL_QUERIES: dict[TableauAsset, tuple[str, str]] = {
|
|
132
|
+
TableauAsset.COLUMN: ("columns", _COLUMNS_QUERY),
|
|
133
|
+
TableauAsset.DASHBOARD: ("dashboards", _DASHBOARDS_QUERY),
|
|
134
|
+
TableauAsset.DATASOURCE: ("datasources", _DATASOURCES_QUERY),
|
|
135
|
+
TableauAsset.SHEET: ("sheets", _SHEETS_QUERY),
|
|
136
|
+
TableauAsset.TABLE: ("tables", _TABLES_QUERY),
|
|
137
|
+
TableauAsset.WORKBOOK: ("workbooks", _WORKBOOKS_QUERY),
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
FIELDS_QUERIES = (
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
from ..assets import
|
|
1
|
+
from ..assets import TableauAsset
|
|
2
2
|
|
|
3
3
|
# list of fields to pick in REST API or TSC responses
|
|
4
|
-
REST_FIELDS: dict[
|
|
5
|
-
|
|
4
|
+
REST_FIELDS: dict[TableauAsset, set[str]] = {
|
|
5
|
+
TableauAsset.DATASOURCE: {
|
|
6
6
|
"id",
|
|
7
7
|
"project_id",
|
|
8
8
|
"webpage_url",
|
|
9
9
|
},
|
|
10
|
-
|
|
10
|
+
TableauAsset.METRIC: {
|
|
11
11
|
"id",
|
|
12
12
|
"definition_id",
|
|
13
13
|
},
|
|
14
|
-
|
|
14
|
+
TableauAsset.METRIC_DEFINITION: {
|
|
15
15
|
"metadata",
|
|
16
16
|
"specification",
|
|
17
17
|
},
|
|
18
|
-
|
|
18
|
+
TableauAsset.PROJECT: {
|
|
19
19
|
"description",
|
|
20
20
|
"id",
|
|
21
21
|
"name",
|
|
22
22
|
"parent_id",
|
|
23
23
|
},
|
|
24
|
-
|
|
24
|
+
TableauAsset.SUBSCRIPTION: {
|
|
25
25
|
"follower",
|
|
26
26
|
"id",
|
|
27
27
|
"metric_id",
|
|
28
28
|
},
|
|
29
|
-
|
|
29
|
+
TableauAsset.USAGE: {
|
|
30
30
|
"name",
|
|
31
31
|
"total_views",
|
|
32
32
|
"workbook_id",
|
|
33
33
|
},
|
|
34
|
-
|
|
34
|
+
TableauAsset.USER: {
|
|
35
35
|
"email",
|
|
36
36
|
"fullname",
|
|
37
37
|
"id",
|
|
38
38
|
"name",
|
|
39
39
|
"site_role",
|
|
40
40
|
},
|
|
41
|
-
|
|
41
|
+
TableauAsset.WORKBOOK: {
|
|
42
42
|
"id",
|
|
43
43
|
"project_id",
|
|
44
44
|
},
|
|
@@ -10,18 +10,18 @@ from ...utils import (
|
|
|
10
10
|
write_json,
|
|
11
11
|
write_summary,
|
|
12
12
|
)
|
|
13
|
-
from .assets import
|
|
14
|
-
from .client import
|
|
13
|
+
from .assets import TableauAsset
|
|
14
|
+
from .client import TableauClient, TableauCredentials
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def iterate_all_data(
|
|
20
|
-
client:
|
|
21
|
-
) -> Iterable[tuple[
|
|
20
|
+
client: TableauClient,
|
|
21
|
+
) -> Iterable[tuple[TableauAsset, list]]:
|
|
22
22
|
"""Iterate over the extracted Data from Tableau"""
|
|
23
23
|
|
|
24
|
-
for asset in
|
|
24
|
+
for asset in TableauAsset:
|
|
25
25
|
data = client.fetch(asset)
|
|
26
26
|
yield asset, deep_serialize(data)
|
|
27
27
|
|
|
@@ -36,8 +36,8 @@ def extract_all(**kwargs) -> None:
|
|
|
36
36
|
page_size = kwargs.get("page_size")
|
|
37
37
|
timestamp = current_timestamp()
|
|
38
38
|
|
|
39
|
-
credentials =
|
|
40
|
-
client =
|
|
39
|
+
credentials = TableauCredentials(**kwargs)
|
|
40
|
+
client = TableauClient(
|
|
41
41
|
credentials,
|
|
42
42
|
with_pulse=with_pulse,
|
|
43
43
|
override_page_size=page_size,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: castor-extractor
|
|
3
|
-
Version: 0.24.
|
|
3
|
+
Version: 0.24.2
|
|
4
4
|
Summary: Extract your metadata assets.
|
|
5
5
|
Home-page: https://www.castordoc.com/
|
|
6
6
|
License: EULA
|
|
@@ -210,6 +210,10 @@ For any questions or bug report, contact us at [support@castordoc.com](mailto:su
|
|
|
210
210
|
|
|
211
211
|
# Changelog
|
|
212
212
|
|
|
213
|
+
## 0.24.2 - 2025-03-17
|
|
214
|
+
|
|
215
|
+
* Rename Revamped Tableau Connector classes
|
|
216
|
+
|
|
213
217
|
## 0.24.1 - 2025-03-14
|
|
214
218
|
|
|
215
219
|
* Added support for Looker Studio
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
CHANGELOG.md,sha256=
|
|
1
|
+
CHANGELOG.md,sha256=8iEypB0lozhyFumiedys3lbpowlX3HXCPnK-3QvjueE,15884
|
|
2
2
|
Dockerfile,sha256=xQ05-CFfGShT3oUqaiumaldwA288dj9Yb_pxofQpufg,301
|
|
3
3
|
DockerfileUsage.md,sha256=2hkJQF-5JuuzfPZ7IOxgM6QgIQW7l-9oRMFVwyXC4gE,998
|
|
4
4
|
LICENCE,sha256=sL-IGa4hweyya1HgzMskrRdybbIa2cktzxb5qmUgDg8,8254
|
|
@@ -25,7 +25,7 @@ castor_extractor/commands/extract_salesforce_reporting.py,sha256=FdANTNiLkIPdm80
|
|
|
25
25
|
castor_extractor/commands/extract_sigma.py,sha256=sxewHcZ1Doq35V2qnpX_zCKKXkrb1_9bYjUMg7BOW-k,643
|
|
26
26
|
castor_extractor/commands/extract_snowflake.py,sha256=GwlrRxwEBjHqGs_3bs5vM9fzmv61_iwvBr1KcIgFgWM,2161
|
|
27
27
|
castor_extractor/commands/extract_sqlserver.py,sha256=lwhbcNChaXHZgMgSOch3faVr7WJw-sDU6GHl3lzBt_0,1141
|
|
28
|
-
castor_extractor/commands/extract_tableau.py,sha256=
|
|
28
|
+
castor_extractor/commands/extract_tableau.py,sha256=xXlLKLN8Eu_a8Kt2F4E-C5D-gq8SUmvoxJcdR_thKKY,1365
|
|
29
29
|
castor_extractor/commands/extract_thoughtspot.py,sha256=caAYJlH-vK7u5IUB6OKXxcaWfLgc7d_XqnFDWK6YNS4,639
|
|
30
30
|
castor_extractor/commands/file_check.py,sha256=TJx76Ymd0QCECmq35zRJMkPE8DJtSInB28MuSXWk8Ao,2644
|
|
31
31
|
castor_extractor/commands/upload.py,sha256=rLXp7gQ8zb1kLbho4FT87q8eJd8Gvo_TkyIynAaQ-4s,1342
|
|
@@ -260,19 +260,19 @@ castor_extractor/visualization/sigma/client/credentials.py,sha256=XddAuQSmCKpxJ7
|
|
|
260
260
|
castor_extractor/visualization/sigma/client/endpoints.py,sha256=DBFphbgoH78_MZUGM_bKBAq28Nl7LWSZ6VRsbxrxtDg,1162
|
|
261
261
|
castor_extractor/visualization/sigma/client/pagination.py,sha256=kNEhNq08tTGbypyMjxs0w4uvDtQc_iaWpOZweaa_FsU,690
|
|
262
262
|
castor_extractor/visualization/sigma/extract.py,sha256=XIT1qsj6g6dgBWP8HPfj_medZexu48EaY9tUwi14gzM,2298
|
|
263
|
-
castor_extractor/visualization/
|
|
264
|
-
castor_extractor/visualization/
|
|
265
|
-
castor_extractor/visualization/
|
|
266
|
-
castor_extractor/visualization/
|
|
267
|
-
castor_extractor/visualization/
|
|
268
|
-
castor_extractor/visualization/
|
|
269
|
-
castor_extractor/visualization/
|
|
270
|
-
castor_extractor/visualization/
|
|
271
|
-
castor_extractor/visualization/
|
|
272
|
-
castor_extractor/visualization/
|
|
273
|
-
castor_extractor/visualization/
|
|
274
|
-
castor_extractor/visualization/
|
|
275
|
-
castor_extractor/visualization/
|
|
263
|
+
castor_extractor/visualization/tableau/__init__.py,sha256=eFI_1hjdkxyUiAYiy3szwyuwn3yJ5C_KbpBU0ySJDcQ,138
|
|
264
|
+
castor_extractor/visualization/tableau/assets.py,sha256=HbCRd8VCj1WBEeqg9jwnygnT7xOFJ6PQD7Lq7sV-XR0,635
|
|
265
|
+
castor_extractor/visualization/tableau/client/__init__.py,sha256=P8RKFKOC63WkH5hdEytJOwHS9vzQ8GXreLfXZetmMP8,78
|
|
266
|
+
castor_extractor/visualization/tableau/client/client.py,sha256=zzqhzIqKyJygo4ZNGk6cZh0e6Z9R1W5T0P9un52KC1M,7626
|
|
267
|
+
castor_extractor/visualization/tableau/client/client_metadata_api.py,sha256=fIBsSbRTypBABsCoigO2dkKsw4Eu3GrsEPTDfjY8A80,4303
|
|
268
|
+
castor_extractor/visualization/tableau/client/client_rest_api.py,sha256=x4dNw4PPJdalTlGowwkANwqiS2ZhGxzpQytkHq3KbpY,3988
|
|
269
|
+
castor_extractor/visualization/tableau/client/client_tsc.py,sha256=VI_PJyd1ty3HSYXHHQjshmG2ziowIbrwJRonRPCHbks,1820
|
|
270
|
+
castor_extractor/visualization/tableau/client/credentials.py,sha256=uQICIgeXmLZfOroTgZt7PuKNKTyqQllRGSTcOmIfrKU,1893
|
|
271
|
+
castor_extractor/visualization/tableau/client/errors.py,sha256=ecT8Tit5VtzrOBB9ykblA0nvd75j5-_QDFupjV48zJQ,300
|
|
272
|
+
castor_extractor/visualization/tableau/client/gql_queries.py,sha256=NISarYh33Ij7DhYxqjTdv681AHYpbft8kPwVUQbAZ7U,2190
|
|
273
|
+
castor_extractor/visualization/tableau/client/rest_fields.py,sha256=ZKYYuMxg9PXhczVXaD4rXNk7dYyWJ1_bVM8FLEXju7s,888
|
|
274
|
+
castor_extractor/visualization/tableau/constants.py,sha256=lHGB50FgVNO2nXeIhkvQKivD8ZFBIjDrflgD5cTXKJw,104
|
|
275
|
+
castor_extractor/visualization/tableau/extract.py,sha256=FnjmmUdNA9MEf3S5Tw37x6ZXxVsK8R3YnVk1UVYbaZk,1423
|
|
276
276
|
castor_extractor/visualization/thoughtspot/__init__.py,sha256=NhTGUk5Kdt54oCjHYoAt0cLBmVLys5lFYiRANL6wCmI,150
|
|
277
277
|
castor_extractor/visualization/thoughtspot/assets.py,sha256=SAQWPKaD2NTSDg7-GSkcRSSEkKSws0MJfOVcHkdeTSg,276
|
|
278
278
|
castor_extractor/visualization/thoughtspot/client/__init__.py,sha256=svrE2rMxR-OXctjPeAHMEPePlfcra-9KDevTMcHunAA,86
|
|
@@ -404,8 +404,8 @@ castor_extractor/warehouse/sqlserver/queries/table.sql,sha256=kbBQP-TdG5px1IVgyx
|
|
|
404
404
|
castor_extractor/warehouse/sqlserver/queries/user.sql,sha256=gOrZsMVypusR2dc4vwVs4E1a-CliRsr_UjnD2EbXs-A,94
|
|
405
405
|
castor_extractor/warehouse/sqlserver/query.py,sha256=g0hPT-RmeGi2DyenAi3o72cTlQsLToXIFYojqc8E5fQ,533
|
|
406
406
|
castor_extractor/warehouse/synapse/queries/column.sql,sha256=lNcFoIW3Y0PFOqoOzJEXmPvZvfAsY0AP63Mu2LuPzPo,1351
|
|
407
|
-
castor_extractor-0.24.
|
|
408
|
-
castor_extractor-0.24.
|
|
409
|
-
castor_extractor-0.24.
|
|
410
|
-
castor_extractor-0.24.
|
|
411
|
-
castor_extractor-0.24.
|
|
407
|
+
castor_extractor-0.24.2.dist-info/LICENCE,sha256=sL-IGa4hweyya1HgzMskrRdybbIa2cktzxb5qmUgDg8,8254
|
|
408
|
+
castor_extractor-0.24.2.dist-info/METADATA,sha256=FNJlgmFPbgSmHoVwHx-hXj9rvHYw2wctlcEXeGck52I,23040
|
|
409
|
+
castor_extractor-0.24.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
410
|
+
castor_extractor-0.24.2.dist-info/entry_points.txt,sha256=FQNShG4w4nRO95_bZnagh7FQ2oiZ-40bdt8ZdTW1-uI,1731
|
|
411
|
+
castor_extractor-0.24.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|