castor-extractor 0.9.0__py3-none-any.whl → 0.10.0__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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.0 - 2023-11-28
4
+
5
+ * Looker : extract all Looker Explores, even if unused in Dashboards
6
+
7
+ ## 0.9.2 - 2023-11-23
8
+
9
+ * Looker : remove deprecated all_looks parameter
10
+
11
+ ## 0.9.1 - 2023-11-22
12
+
13
+ * Redshift : filter out queries exceeding 65535 char
14
+
3
15
  ## 0.9.0 - 2023-11-20
4
16
 
5
17
  * Snowflake : Add key-pair authentication
Dockerfile ADDED
@@ -0,0 +1,16 @@
1
+ # syntax=docker/dockerfile:1.5
2
+
3
+ FROM --platform=linux/amd64 python:3.10-slim
4
+
5
+ ARG EXTRA
6
+ ENV EXTRA=${EXTRA}
7
+
8
+ RUN pip install --upgrade pip && \
9
+ pip install castor-extractor[${EXTRA}]
10
+
11
+ ENV CASTOR_OUTPUT_DIRECTORY=/data
12
+
13
+ VOLUME [ "/data" ]
14
+
15
+ ENTRYPOINT castor-extract-${EXTRA}
16
+ CMD [ "--log-to-stdout" ]
@@ -27,13 +27,7 @@ def main():
27
27
  action="store_true",
28
28
  )
29
29
 
30
- group = parser.add_mutually_exclusive_group()
31
- group.add_argument(
32
- "--all-looks",
33
- help="Use all_looks endpoint instead of the paginated search_looks",
34
- action="store_true",
35
- )
36
- group.add_argument(
30
+ parser.add_argument(
37
31
  "--search-per-folder",
38
32
  help="Fetches Looks and Dashboards per folder",
39
33
  action="store_true",
@@ -42,7 +36,6 @@ def main():
42
36
  args = parser.parse_args()
43
37
 
44
38
  looker.extract_all(
45
- all_looks=args.all_looks,
46
39
  base_url=args.base_url,
47
40
  client_id=args.username,
48
41
  client_secret=args.password,
@@ -1,9 +1,3 @@
1
- from .api import (
2
- ApiClient,
3
- Credentials,
4
- dashboard_explore_names,
5
- explore_names_associated_to_dashboards,
6
- lookml_explore_names,
7
- )
1
+ from .api import ApiClient, Credentials, lookml_explore_names
8
2
  from .assets import LookerAsset
9
3
  from .extract import extract_all, iterate_all_data
@@ -1,7 +1,3 @@
1
1
  from .client import ApiClient
2
2
  from .sdk import Credentials
3
- from .utils import (
4
- dashboard_explore_names,
5
- explore_names_associated_to_dashboards,
6
- lookml_explore_names,
7
- )
3
+ from .utils import lookml_explore_names
@@ -125,7 +125,7 @@ class ApiClient:
125
125
 
126
126
  return Pager(_search, logger=self._logger).all(per_page=self.per_page)
127
127
 
128
- def _search_looks(self, folder_id: Optional[str] = None) -> List[Look]:
128
+ def looks(self, folder_id: Optional[str] = None) -> List[Look]:
129
129
  """
130
130
  Fetch looks via `search_looks` using pagination. The optional folder_id
131
131
  allows restricting the search to the given folder.
@@ -156,22 +156,6 @@ class ApiClient:
156
156
  # No pagination : see https://community.looker.com/looker-api-77/api-paging-limits-14598
157
157
  return list(self._sdk.all_looks(fields=format_fields(LOOK_FIELDS)))
158
158
 
159
- def looks(
160
- self,
161
- all_looks_endpoint: Optional[bool] = False,
162
- folder_id: Optional[str] = None,
163
- ) -> List[Look]:
164
- """Lists looks of the given Looker account
165
-
166
- By default, uses the endpoint `search_looks` that allows pagination and
167
- filtering on a folder.
168
- If `all_looks_endpoint` parameter is set to True, it uses `all_looks` endpoint.
169
- """
170
- if all_looks_endpoint:
171
- return self._all_looks()
172
-
173
- return self._search_looks(folder_id)
174
-
175
159
  def users(self) -> List[User]:
176
160
  """Lists users of the given Looker account"""
177
161
 
@@ -207,7 +191,7 @@ class ApiClient:
207
191
  def explores(
208
192
  self,
209
193
  explore_names=Iterator[Tuple[str, str]],
210
- ) -> List[LookmlModelExplore]:
194
+ ) -> Iterator[LookmlModelExplore]:
211
195
  """Iterates explores of the given Looker account for the provided model/explore names"""
212
196
 
213
197
  @safe_mode(self._safe_mode)
@@ -218,11 +202,10 @@ class ApiClient:
218
202
  self._on_api_call()
219
203
  return explore
220
204
 
221
- explores = [
222
- _call(model_name, explore_name)
223
- for model_name, explore_name in explore_names
224
- ]
225
- return list(filter(None, explores))
205
+ for lookml_model_name, lookml_explore_name_ in explore_names:
206
+ explore_ = _call(lookml_model_name, lookml_explore_name_)
207
+ if explore_ is not None:
208
+ yield explore_
226
209
 
227
210
  def connections(self) -> List[DBConnection]:
228
211
  """Lists databases connections of the given Looker account"""
@@ -1,6 +1,6 @@
1
1
  from typing import Iterable, Set, Tuple
2
2
 
3
- from .sdk import Dashboard, LookmlModel
3
+ from .sdk import LookmlModel
4
4
 
5
5
 
6
6
  def lookml_explore_names(
@@ -22,28 +22,3 @@ def lookml_explore_names(
22
22
  # accept hidden resources
23
23
  if model.name and explore.name
24
24
  }
25
-
26
-
27
- def dashboard_explore_names(
28
- dashboards: Iterable[Dashboard],
29
- ) -> Set[Tuple[str, str]]:
30
- """Explores that appear in dashboards"""
31
- elements = (
32
- element
33
- for dashboard in dashboards
34
- for element in dashboard.dashboard_elements or []
35
- )
36
-
37
- return {
38
- (element.query.model, element.query.view)
39
- for element in elements
40
- if element.query and element.query.model and element.query.view
41
- }
42
-
43
-
44
- def explore_names_associated_to_dashboards(
45
- lookmls: Iterable[LookmlModel],
46
- dashboard_explore_names_: Set[Tuple[str, str]],
47
- ):
48
- """Retrieve only explores that are associated to a looker dashboard"""
49
- return lookml_explore_names(lookmls).intersection(dashboard_explore_names_)
@@ -20,6 +20,5 @@ KEY_LOOKER_THREAD_POOL_SIZE = "CASTOR_LOOKER_THREAD_POOL_SIZE"
20
20
  BASE_URL = "CASTOR_LOOKER_BASE_URL"
21
21
  CLIENT_ID = "CASTOR_LOOKER_CLIENT_ID"
22
22
  CLIENT_SECRET = "CASTOR_LOOKER_CLIENT_SECRET" # noqa: S105
23
- ALL_LOOKS = "CASTOR_LOOKER_ALL_LOOKS"
24
23
  SEARCH_PER_FOLDER = "CASTOR_LOOKER_SEARCH_PER_FOLDER"
25
24
  LOG_TO_STDOUT = "CASTOR_LOOKER_LOG_TO_STDOUT"
@@ -11,12 +11,8 @@ from ...utils import (
11
11
  write_json,
12
12
  write_summary,
13
13
  )
14
- from .api import (
15
- ApiClient,
16
- Credentials,
17
- dashboard_explore_names,
18
- explore_names_associated_to_dashboards,
19
- )
14
+ from .api import ApiClient, Credentials, lookml_explore_names
15
+ from .api.sdk import LookmlModel
20
16
  from .assets import LookerAsset
21
17
  from .multithreading import MultithreadingFetcher
22
18
  from .parameters import get_parameters
@@ -24,6 +20,15 @@ from .parameters import get_parameters
24
20
  logger = logging.getLogger(__name__)
25
21
 
26
22
 
23
+ def _extract_explores_by_name(
24
+ lookmls: Iterable[LookmlModel], client: ApiClient
25
+ ) -> Iterable[dict]:
26
+ explore_names = lookml_explore_names(lookmls)
27
+ explores = client.explores(explore_names)
28
+ for explore in explores:
29
+ yield deep_serialize(explore) # type: ignore
30
+
31
+
27
32
  def _safe_mode(directory: str) -> SafeMode:
28
33
  add_logging_file_handler(directory)
29
34
  return SafeMode((Exception,), float("inf"))
@@ -47,7 +52,6 @@ def _client(
47
52
 
48
53
  def iterate_all_data(
49
54
  client: ApiClient,
50
- all_looks: bool,
51
55
  search_per_folder: bool,
52
56
  thread_pool_size: int,
53
57
  log_to_stdout: bool,
@@ -74,16 +78,14 @@ def iterate_all_data(
74
78
  looks_stream = fetcher.fetch_assets(LookerAsset.LOOKS)
75
79
  yield LookerAsset.LOOKS, StreamableList(looks_stream)
76
80
  else:
77
- yield LookerAsset.LOOKS, deep_serialize(client.looks(all_looks))
81
+ yield LookerAsset.LOOKS, deep_serialize(client.looks())
78
82
 
79
83
  logger.info("Extracting dashboards from Looker API")
80
84
  if search_per_folder:
81
85
  dashboards_stream = fetcher.fetch_assets(LookerAsset.DASHBOARDS)
82
86
  yield LookerAsset.DASHBOARDS, StreamableList(dashboards_stream)
83
- dashboard_explore_names_ = fetcher.explores
84
87
  else:
85
88
  dashboards = client.dashboards()
86
- dashboard_explore_names_ = dashboard_explore_names(dashboards)
87
89
  yield LookerAsset.DASHBOARDS, deep_serialize(dashboards)
88
90
 
89
91
  logger.info("Extracting lookml models from Looker API")
@@ -91,10 +93,8 @@ def iterate_all_data(
91
93
  yield LookerAsset.LOOKML_MODELS, deep_serialize(lookmls)
92
94
 
93
95
  logger.info("Extracting explores from Looker API")
94
- explore_names = explore_names_associated_to_dashboards(
95
- lookmls, dashboard_explore_names_
96
- )
97
- yield LookerAsset.EXPLORES, deep_serialize(client.explores(explore_names))
96
+ explores = _extract_explores_by_name(lookmls, client)
97
+ yield LookerAsset.EXPLORES, StreamableList(explores)
98
98
  del lookmls
99
99
 
100
100
  logger.info("Extracting connections from Looker API")
@@ -144,7 +144,6 @@ def extract_all(**kwargs) -> None:
144
144
 
145
145
  data = iterate_all_data(
146
146
  client=client,
147
- all_looks=parameters.all_looks,
148
147
  search_per_folder=parameters.search_per_folder,
149
148
  thread_pool_size=parameters.thread_pool_size,
150
149
  log_to_stdout=parameters.log_to_stdout,
@@ -2,13 +2,13 @@ import logging
2
2
  import sys
3
3
  from concurrent.futures import ThreadPoolExecutor
4
4
  from functools import partial
5
- from typing import Iterable, List, Set, Tuple
5
+ from typing import Iterable, List, Set
6
6
 
7
7
  from tqdm import tqdm # type: ignore
8
8
 
9
9
  from ...utils import RetryStrategy, deep_serialize, retry
10
- from . import ApiClient, dashboard_explore_names
11
- from .api.sdk import Dashboard, SDKError
10
+ from . import ApiClient
11
+ from .api.sdk import SDKError
12
12
  from .assets import LookerAsset
13
13
 
14
14
  logger = logging.getLogger(__name__)
@@ -54,16 +54,6 @@ class MultithreadingFetcher:
54
54
  self._thread_pool_size = thread_pool_size
55
55
  self._log_to_stdout = log_to_stdout
56
56
 
57
- self.explores: Set[Tuple[str, str]] = set()
58
-
59
- def _save_explore_names(self, dashboards_per_folder: Iterable[Dashboard]):
60
- """
61
- Since dashboards are streamed right to the file, we need to keep
62
- the relevant information to extract Explores later.
63
- """
64
- explores = dashboard_explore_names(dashboards_per_folder)
65
- self.explores.update(explores)
66
-
67
57
  def _progress_bar(self, fetch_results: Iterable, total: int) -> tqdm:
68
58
  """Create a tqdm progress bar with the appropriate logs destination"""
69
59
  file = sys.stderr
@@ -73,7 +63,7 @@ class MultithreadingFetcher:
73
63
 
74
64
  return tqdm(fetch_results, total=total, file=file)
75
65
 
76
- def fetch_assets(self, asset: LookerAsset):
66
+ def fetch_assets(self, asset: LookerAsset) -> Iterable[dict]:
77
67
  """
78
68
  Yields serialized Looks or Dashboards with a request per folder ID.
79
69
  Requests are parallelised.
@@ -88,12 +78,10 @@ class MultithreadingFetcher:
88
78
  fetch_results = executor.map(_fetch, self._folder_ids)
89
79
 
90
80
  for results in self._progress_bar(fetch_results, total_folders):
91
- if asset == LookerAsset.DASHBOARDS:
92
- self._save_explore_names(results)
93
-
94
81
  for result in results:
95
82
  if not result:
96
83
  continue
84
+
97
85
  total_assets_count += len(result)
98
86
  yield deep_serialize(result)
99
87
 
@@ -2,7 +2,6 @@ from typing import NamedTuple, Optional
2
2
 
3
3
  from ...utils import OUTPUT_DIR, from_env, validate_baseurl
4
4
  from .constant import (
5
- ALL_LOOKS,
6
5
  BASE_URL,
7
6
  CLIENT_ID,
8
7
  CLIENT_SECRET,
@@ -31,7 +30,6 @@ def _bool_env_variable(key: str) -> bool:
31
30
  class Parameters(NamedTuple):
32
31
  """Parameters for Looker extraction"""
33
32
 
34
- all_looks: bool
35
33
  base_url: str
36
34
  client_id: str
37
35
  client_secret: str
@@ -63,13 +61,11 @@ def get_parameters(**kwargs) -> Parameters:
63
61
  search_per_folder = kwargs.get("search_per_folder") or _bool_env_variable(
64
62
  SEARCH_PER_FOLDER,
65
63
  )
66
- all_looks = kwargs.get("all_looks") or _bool_env_variable(ALL_LOOKS)
67
64
  log_to_stdout = kwargs.get("log_to_stdout") or _bool_env_variable(
68
65
  LOG_TO_STDOUT
69
66
  )
70
67
 
71
68
  return Parameters(
72
- all_looks=all_looks,
73
69
  base_url=base_url,
74
70
  client_id=client_id,
75
71
  client_secret=client_secret,
@@ -14,16 +14,26 @@ queries_deduplicated AS (
14
14
  AND EXTRACT('hour' FROM q.starttime) BETWEEN p.hour_min AND p.hour_max
15
15
  ),
16
16
 
17
- raw_query_text AS
18
- (
17
+ query AS (
19
18
  SELECT
20
19
  q.query,
21
- LISTAGG(qt.text, '') WITHIN GROUP (ORDER BY qt.sequence) AS agg_text
20
+ qt.text,
21
+ qt.sequence,
22
+ COUNT(*) OVER(PARTITION BY q.query) AS sequence_count
22
23
  FROM queries_deduplicated AS q
23
24
  INNER JOIN pg_catalog.stl_querytext AS qt ON q.query = qt.query
25
+ ),
26
+
27
+ raw_query_text AS
28
+ (
29
+ SELECT
30
+ q.query,
31
+ LISTAGG(q.text, '') WITHIN GROUP (ORDER BY q.sequence) AS agg_text
32
+ FROM query AS q
24
33
  WHERE TRUE
25
- -- LISTAGG raises an error when total length >= 64K
26
- AND qt.sequence < (65535 / 200)
34
+ -- LISTAGG raises an error when total length >= 65535
35
+ -- each sequence contains 200 char max
36
+ AND q.sequence_count < (65535 / 200)
27
37
  GROUP BY q.query
28
38
  ),
29
39
 
@@ -59,7 +69,7 @@ read_query AS (
59
69
  AND EXTRACT('hour' FROM q.starttime) BETWEEN p.hour_min AND p.hour_max
60
70
  ),
61
71
 
62
- -- the DDL part is sensible to any change of JOIN and AGGREGATIOn: test in the field prior to merging
72
+ -- the DDL part is sensible to any change of JOIN and AGGREGATION: test in the field prior to merging
63
73
  ddl_query AS (
64
74
  SELECT
65
75
  (q.xid || '-' || q.query_part_rank)::VARCHAR(256) AS query_id,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: castor-extractor
3
- Version: 0.9.0
3
+ Version: 0.10.0
4
4
  Summary: Extract your metadata assets.
5
5
  Home-page: https://www.castordoc.com/
6
6
  License: EULA
@@ -1,11 +1,12 @@
1
- CHANGELOG.md,sha256=G1Im93-h9M3BD81X4diERzpLkgwGprLRSnGY_AlTKuc,7105
1
+ CHANGELOG.md,sha256=-SDIu5XMRtiE4Pp7-F8aCJteadjcjuxDwdvRIjKefBw,7349
2
+ Dockerfile,sha256=TC6hFjG3mvnt1nkw2EpaS42hRYaGA2YIPKgWhVSKTWc,303
2
3
  LICENCE,sha256=sL-IGa4hweyya1HgzMskrRdybbIa2cktzxb5qmUgDg8,8254
3
4
  README.md,sha256=EL6JpZxvaQFOYv5WFuSjZvSk9Hcpsf7alMlUC5IPFjA,3423
4
5
  castor_extractor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
6
  castor_extractor/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
7
  castor_extractor/commands/extract_bigquery.py,sha256=dU4OiYO1V0n32orvZnMh1_xtFKF_VxHNXcVsH3otY-g,1269
7
8
  castor_extractor/commands/extract_domo.py,sha256=lwJ7XeYOeLMF2plf5PK3cL56N9n2yjcDsyRM6UFwKTM,1208
8
- castor_extractor/commands/extract_looker.py,sha256=IXNTljfpmpyTzW3gh9HQvPpnHP0gbDM-RDVs8PZk7bY,1725
9
+ castor_extractor/commands/extract_looker.py,sha256=gwjIQPOHrXevgU_o2l8vDHHQT8Sb-mGdwcceb6wJJbg,1483
9
10
  castor_extractor/commands/extract_metabase_api.py,sha256=VPyEKO2VFXzk_OsbQnDhObE9siuBfoegechCZYPZi2k,778
10
11
  castor_extractor/commands/extract_metabase_db.py,sha256=cAwoeHrRg29dDh6lUlXZZsoq8NPyMrH-Gx3ovHPD3ds,1269
11
12
  castor_extractor/commands/extract_mode.py,sha256=-y8ML72sRVpBEjo9hB1WZyUPznqxnNn0iS8dfJu_ALg,953
@@ -88,22 +89,22 @@ castor_extractor/visualization/domo/client/endpoints.py,sha256=-B7mRKJ44Bg0hb3E5
88
89
  castor_extractor/visualization/domo/client/pagination.py,sha256=BT9ZIb-GYGWEQZpK_80aAYKQ-xrr7VlfsFbZv9rcejQ,565
89
90
  castor_extractor/visualization/domo/constants.py,sha256=AriJZPrCY5Z3HRUANrMu-4U0b7hQK_jRDcxiB-hbrQ4,233
90
91
  castor_extractor/visualization/domo/extract.py,sha256=GWWRfPEMt4SgzBGFaTcoOabsoOqLRFIEFAtgXwb8LDI,2567
91
- castor_extractor/visualization/looker/__init__.py,sha256=nUPT7ojaYE56Xk9LCCquRfuCepBIdbe-GwGbZNO7oXo,235
92
- castor_extractor/visualization/looker/api/__init__.py,sha256=eMtzoMAE7ZnvfwJJAOh9Cooztj4Juzc40wSEHhIYXw4,181
93
- castor_extractor/visualization/looker/api/client.py,sha256=QuzC29i-kM_6hLijOElPzh8pUlPdWoskOlsOZWGNLxw,10076
92
+ castor_extractor/visualization/looker/__init__.py,sha256=Xu5bJ3743kaP8szMMp2NXCgvM1EdOQgtic4utUlO9Cc,145
93
+ castor_extractor/visualization/looker/api/__init__.py,sha256=rN03VMucxIqc0yfd17dIe3ZNFpcg5CA09epn1fKJg90,99
94
+ castor_extractor/visualization/looker/api/client.py,sha256=R-hnVK1TYaCPYaJ1wvpVUwa_AqQPu2RAcZz0kOK4l58,9582
94
95
  castor_extractor/visualization/looker/api/client_test.py,sha256=wsi20-neBXHaahDqf4nwCp8Ew5fRFCmVHG3OqrePKFs,1868
95
96
  castor_extractor/visualization/looker/api/constants.py,sha256=pZpq09tqcGi2Vh8orXxn9eil8ewfPUOLKfVuqgV2W-A,4126
96
97
  castor_extractor/visualization/looker/api/sdk.py,sha256=hSNcRsCoFae3zmjWFGsMrhQCIP57TcMJ2SorMPYJwn4,3553
97
98
  castor_extractor/visualization/looker/api/sdk_test.py,sha256=NHtKZTflPhqzBFHs1TyAQaubgxfzLLwYKFT8rEqR55I,1742
98
- castor_extractor/visualization/looker/api/utils.py,sha256=9xDKekJU6FNl_X5clO2NkDxPm7Q9t4ogJC7-dbh7HXo,1315
99
+ castor_extractor/visualization/looker/api/utils.py,sha256=NpP90CA-SwdUjHhaWFBsKpJz0Z9BXgDOahIqfc3R9tk,565
99
100
  castor_extractor/visualization/looker/assets.py,sha256=4EwCI9VwIYRPrIjHU-ZnPY3Mf3cRykWACiYXanr5jFI,442
100
- castor_extractor/visualization/looker/constant.py,sha256=8fe_sX1NhgVaQmB3Fc8_yvXrWps8P9KcT3um15KetaA,732
101
+ castor_extractor/visualization/looker/constant.py,sha256=0tX6KOGdc9O6FiHcoj08j-QIZyBI2Mhh8UQc_XahDaM,694
101
102
  castor_extractor/visualization/looker/env.py,sha256=vPqirdeGKm3as2T-tBTjbpulQe8W7-3UE2j-Z57wFXk,1174
102
- castor_extractor/visualization/looker/extract.py,sha256=5_oOSeefdudb6p7-vsfM10FfWihqByCFVBDe1pf57c8,5121
103
+ castor_extractor/visualization/looker/extract.py,sha256=vOIP8Hoxv05MiRa-l79YKOCHahuNiSW9uSKjwQQQQKs,5112
103
104
  castor_extractor/visualization/looker/fields.py,sha256=WmiSehmczWTufCLg4r2Ozq2grUpzxDNvIAHyGuOoGs4,636
104
105
  castor_extractor/visualization/looker/fields_test.py,sha256=7Cwq8Qky6aTZg8nCHp1gmPJtd9pGNB4QeMIRRWdHo5w,782
105
- castor_extractor/visualization/looker/multithreading.py,sha256=SvyUiXXXbYeo0xtiqjVUdyM-btLeS-qnBjVEQvUjF5w,3122
106
- castor_extractor/visualization/looker/parameters.py,sha256=3SUSQG1qwrr_W8yMPZokV6AIvQRjOr-UFHqScLRSkOk,2564
106
+ castor_extractor/visualization/looker/multithreading.py,sha256=BB_oUkPo3LH96f1pPaywQ5Y8r2T7vo4hdAQl7y0bpPw,2596
107
+ castor_extractor/visualization/looker/parameters.py,sha256=Nk2hfrg3L9twU-51Q7Wdp9uaxy8M2_juEebWoLfIMPc,2427
107
108
  castor_extractor/visualization/metabase/__init__.py,sha256=hSIoVgPzhQh-9H8XRUzga4EZSOYejGdH-qY_hBNGbyw,125
108
109
  castor_extractor/visualization/metabase/assets.py,sha256=XeP8UzbqsrleBtdv2nJ2LtWC_p3TAL7g0zlrcjt82TM,2814
109
110
  castor_extractor/visualization/metabase/client/__init__.py,sha256=ZMn272PqMoHyWkK0fBuXw9YEnc-OeszNn_BDlMc_FSI,52
@@ -254,7 +255,7 @@ castor_extractor/warehouse/redshift/queries/.sqlfluff,sha256=W4pFQiY8KMtXwn3WguY
254
255
  castor_extractor/warehouse/redshift/queries/column.sql,sha256=VLmt8yfILajepv5ZEOyinA4101eZKHr1Mew4f2DqDk0,7044
255
256
  castor_extractor/warehouse/redshift/queries/database.sql,sha256=_C0knW159YDfReGuWLjIdvxHzefo1Xg2xw2dJKJzNk8,299
256
257
  castor_extractor/warehouse/redshift/queries/group.sql,sha256=8p0wlqllnwOTiAgiV237DvFYHGOEcYwaHdyqVQg3F6E,101
257
- castor_extractor/warehouse/redshift/queries/query.sql,sha256=xkCwhx8Vteyc2_EES8qoYI4cBOHqcaAA3WHFckx865k,3258
258
+ castor_extractor/warehouse/redshift/queries/query.sql,sha256=yZNGnUdebvvDx0J0KMSJ2hNgkK4gPduyOfPM_7-DIfo,3465
258
259
  castor_extractor/warehouse/redshift/queries/schema.sql,sha256=Mf6nooi2w2PhGxM2_kDAf3oQ8QnR-hpT5Y0AmUzghGg,585
259
260
  castor_extractor/warehouse/redshift/queries/table.sql,sha256=y8CGOwPHH_Mr8g1Zvuz2U5ldL8zuPm5v3M5RPZqIhsE,2645
260
261
  castor_extractor/warehouse/redshift/queries/table_freshness.sql,sha256=l61_ysmTEtuMwK9RmYmD5cu0HmD1RXwTEhX0ytBeyxg,726
@@ -288,7 +289,7 @@ castor_extractor/warehouse/synapse/queries/schema.sql,sha256=aX9xNrBD_ydwl-znGSF
288
289
  castor_extractor/warehouse/synapse/queries/table.sql,sha256=mCE8bR1Vb7j7SwZW2gafcXidQ2fo1HwxcybA8wP2Kfs,1049
289
290
  castor_extractor/warehouse/synapse/queries/user.sql,sha256=sTb_SS7Zj3AXW1SggKPLNMCd0qoTpL7XI_BJRMaEpBg,67
290
291
  castor_extractor/warehouse/synapse/queries/view_ddl.sql,sha256=3EVbp5_yTgdByHFIPLHmnoOnqqLE77SrjAwFDvu4e54,249
291
- castor_extractor-0.9.0.dist-info/METADATA,sha256=MY67RaDhJ6NZEyrjfKWh7ldjjSv0_s6ggG-6KtVbqy8,5879
292
- castor_extractor-0.9.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
293
- castor_extractor-0.9.0.dist-info/entry_points.txt,sha256=cvLvgE8Yi10sIiafUVL86XZPMUUyu9x11CF5PshAyiw,1045
294
- castor_extractor-0.9.0.dist-info/RECORD,,
292
+ castor_extractor-0.10.0.dist-info/METADATA,sha256=XnrJ7dly9vVplF9ksw1thIrfr3Y215iEPCJC4nfs_-A,5880
293
+ castor_extractor-0.10.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
294
+ castor_extractor-0.10.0.dist-info/entry_points.txt,sha256=cvLvgE8Yi10sIiafUVL86XZPMUUyu9x11CF5PshAyiw,1045
295
+ castor_extractor-0.10.0.dist-info/RECORD,,