dcs-sdk 1.6.0__py3-none-any.whl → 1.6.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.
- data_diff/databases/redis.py +93 -0
- data_diff/hashdiff_tables.py +2 -1
- data_diff/table_segment.py +31 -2
- data_diff/utils.py +6 -0
- dcs_sdk/__version__.py +1 -1
- dcs_sdk/sdk/config/config_loader.py +2 -0
- dcs_sdk/sdk/data_diff/data_differ.py +15 -4
- {dcs_sdk-1.6.0.dist-info → dcs_sdk-1.6.2.dist-info}/METADATA +3 -2
- {dcs_sdk-1.6.0.dist-info → dcs_sdk-1.6.2.dist-info}/RECORD +11 -10
- {dcs_sdk-1.6.0.dist-info → dcs_sdk-1.6.2.dist-info}/WHEEL +0 -0
- {dcs_sdk-1.6.0.dist-info → dcs_sdk-1.6.2.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Copyright 2022-present, the Waterdip Labs Pvt. Ltd.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import threading
|
|
17
|
+
import time
|
|
18
|
+
|
|
19
|
+
from loguru import logger
|
|
20
|
+
from redis import ConnectionPool, Redis, RedisError
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class RedisBackend:
|
|
24
|
+
_INSTANCE = None
|
|
25
|
+
_lock = threading.Lock()
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def get_instance(cls, force_recreate: bool = False):
|
|
29
|
+
with cls._lock:
|
|
30
|
+
if cls._INSTANCE is None or force_recreate:
|
|
31
|
+
logger.info("Creating a new RedisBackend instance (force_recreate=%s)", force_recreate)
|
|
32
|
+
cls._INSTANCE = cls._create_instance()
|
|
33
|
+
return cls._INSTANCE
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def _create_instance(cls):
|
|
37
|
+
redis_url = (
|
|
38
|
+
os.getenv("DCS_REDIS_URL", None)
|
|
39
|
+
or os.getenv("DCS_RABBIT_URL", None)
|
|
40
|
+
or os.getenv("REDIS_URL", None)
|
|
41
|
+
or os.getenv("RABBIT_URL", None)
|
|
42
|
+
)
|
|
43
|
+
if not redis_url:
|
|
44
|
+
logger.warning("environment variable is not configured for redis")
|
|
45
|
+
return None
|
|
46
|
+
try:
|
|
47
|
+
pool = ConnectionPool.from_url(
|
|
48
|
+
redis_url,
|
|
49
|
+
max_connections=int(os.getenv("DCS_REDIS_MAX_CONNECTIONS", "100")),
|
|
50
|
+
health_check_interval=int(os.getenv("DCS_REDIS_HEALTH_CHECK_INTERVAL", "30")),
|
|
51
|
+
socket_connect_timeout=float(os.getenv("DCS_REDIS_SOCKET_CONNECT_TIMEOUT", "5")),
|
|
52
|
+
socket_timeout=float(os.getenv("DCS_REDIS_SOCKET_TIMEOUT", "5")),
|
|
53
|
+
socket_keepalive=True,
|
|
54
|
+
)
|
|
55
|
+
client = Redis(connection_pool=pool, decode_responses=False, retry_on_timeout=True)
|
|
56
|
+
# ping to ensure connection and raise early if config wrong
|
|
57
|
+
client.ping()
|
|
58
|
+
return cls(client)
|
|
59
|
+
except RedisError as exc:
|
|
60
|
+
logger.exception("Failed to create Redis client: %s", exc)
|
|
61
|
+
raise
|
|
62
|
+
|
|
63
|
+
def __init__(self, client: Redis):
|
|
64
|
+
self._client = client
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def client(self) -> Redis:
|
|
68
|
+
return self._client
|
|
69
|
+
|
|
70
|
+
def ensure_connected(self) -> bool:
|
|
71
|
+
try:
|
|
72
|
+
self._client.ping()
|
|
73
|
+
return True
|
|
74
|
+
except RedisError:
|
|
75
|
+
logger.warning("Redis ping failed; trying to recreate connection/pool")
|
|
76
|
+
try:
|
|
77
|
+
time.sleep(0.2)
|
|
78
|
+
new_instance = self.__class__._create_instance()
|
|
79
|
+
self.__class__._INSTANCE = new_instance
|
|
80
|
+
self._client = new_instance.client
|
|
81
|
+
self._client.ping()
|
|
82
|
+
logger.info("Recreated Redis client/pool successfully")
|
|
83
|
+
return True
|
|
84
|
+
except Exception as exc:
|
|
85
|
+
logger.exception("Failed to recreate Redis client: %s", exc)
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
def close(self):
|
|
89
|
+
try:
|
|
90
|
+
self._client.connection_pool.disconnect()
|
|
91
|
+
logger.info("Closed Redis connection pool")
|
|
92
|
+
except Exception as e:
|
|
93
|
+
logger.exception("Error closing Redis connection pool: %s", e)
|
data_diff/hashdiff_tables.py
CHANGED
|
@@ -871,7 +871,7 @@ class HashDiffer(HashDiffer):
|
|
|
871
871
|
level: int,
|
|
872
872
|
) -> List:
|
|
873
873
|
"""Download segment rows and perform in-memory diff."""
|
|
874
|
-
|
|
874
|
+
start_time = time.monotonic()
|
|
875
875
|
mode_label = "[IN-MEMORY]" if self.in_memory_diff else "[STANDARD]"
|
|
876
876
|
logger.info(
|
|
877
877
|
". " * level + f"{mode_label} Downloading rows for comparison: " f"{table1.min_key}..{table1.max_key}"
|
|
@@ -887,6 +887,7 @@ class HashDiffer(HashDiffer):
|
|
|
887
887
|
logger.info(
|
|
888
888
|
". " * level + f"{mode_label} Downloaded {len(rows1)} and {len(rows2)} rows. "
|
|
889
889
|
f"Total downloaded: {self.stats['rows_downloaded']}"
|
|
890
|
+
f"Time taken in ms: {int((time.monotonic() - start_time) * 1000)}ms"
|
|
890
891
|
)
|
|
891
892
|
|
|
892
893
|
# Perform in-memory diff
|
data_diff/table_segment.py
CHANGED
|
@@ -25,6 +25,7 @@ from typing_extensions import Self
|
|
|
25
25
|
|
|
26
26
|
from data_diff.abcs.database_types import DbKey, DbPath, DbTime, IKey, NumericType
|
|
27
27
|
from data_diff.databases.base import Database
|
|
28
|
+
from data_diff.databases.redis import RedisBackend
|
|
28
29
|
from data_diff.queries.api import (
|
|
29
30
|
SKIP,
|
|
30
31
|
Code,
|
|
@@ -50,6 +51,7 @@ from data_diff.utils import (
|
|
|
50
51
|
ArithTimestamp,
|
|
51
52
|
ArithTimestampTZ,
|
|
52
53
|
ArithUnicodeString,
|
|
54
|
+
JobCancelledError,
|
|
53
55
|
Vector,
|
|
54
56
|
safezip,
|
|
55
57
|
split_space,
|
|
@@ -220,6 +222,7 @@ class TableSegment:
|
|
|
220
222
|
},
|
|
221
223
|
}
|
|
222
224
|
)
|
|
225
|
+
job_id: Optional[int] = None
|
|
223
226
|
|
|
224
227
|
def __attrs_post_init__(self) -> None:
|
|
225
228
|
if not self.update_column and (self.min_update or self.max_update):
|
|
@@ -326,7 +329,8 @@ class TableSegment:
|
|
|
326
329
|
|
|
327
330
|
# fetched_cols = [NormalizeAsString(this[c]) for c in self.relevant_columns]
|
|
328
331
|
# select = self.make_select().select(*fetched_cols)
|
|
329
|
-
|
|
332
|
+
if self._is_cancelled():
|
|
333
|
+
raise JobCancelledError(self.job_id)
|
|
330
334
|
select = self.make_select().select(*self._relevant_columns_repr)
|
|
331
335
|
start_time = time.monotonic()
|
|
332
336
|
result = self.database.query(select, List[Tuple])
|
|
@@ -366,6 +370,8 @@ class TableSegment:
|
|
|
366
370
|
Returns:
|
|
367
371
|
list: List of tuples containing the queried row data.
|
|
368
372
|
"""
|
|
373
|
+
if self._is_cancelled():
|
|
374
|
+
raise JobCancelledError(self.job_id)
|
|
369
375
|
select = self.make_select().select(*self._relevant_columns_repr)
|
|
370
376
|
|
|
371
377
|
filters = []
|
|
@@ -471,6 +477,8 @@ class TableSegment:
|
|
|
471
477
|
|
|
472
478
|
def count(self) -> int:
|
|
473
479
|
"""Count how many rows are in the segment, in one pass."""
|
|
480
|
+
if self._is_cancelled():
|
|
481
|
+
raise JobCancelledError(self.job_id)
|
|
474
482
|
start_time = time.monotonic()
|
|
475
483
|
result = self.database.query(self.make_select().select(Count()), int)
|
|
476
484
|
query_time_ms = (time.monotonic() - start_time) * 1000
|
|
@@ -480,7 +488,8 @@ class TableSegment:
|
|
|
480
488
|
|
|
481
489
|
def count_and_checksum(self) -> Tuple[int, int]:
|
|
482
490
|
"""Count and checksum the rows in the segment, in one pass."""
|
|
483
|
-
|
|
491
|
+
if self._is_cancelled():
|
|
492
|
+
raise JobCancelledError(self.job_id)
|
|
484
493
|
checked_columns = [c for c in self.relevant_columns if c not in self.ignored_columns]
|
|
485
494
|
# Build transformed expressions for checksum, honoring transforms and normalization
|
|
486
495
|
checksum_exprs: List[Expr] = []
|
|
@@ -552,3 +561,23 @@ class TableSegment:
|
|
|
552
561
|
return row_count if row_count is not None else self.count()
|
|
553
562
|
else:
|
|
554
563
|
return row_count if row_count is not None else self.count()
|
|
564
|
+
|
|
565
|
+
def _is_cancelled(self) -> bool:
|
|
566
|
+
run_id = self.job_id
|
|
567
|
+
if not run_id:
|
|
568
|
+
return False
|
|
569
|
+
run_id = f"revoke_job:{run_id}"
|
|
570
|
+
try:
|
|
571
|
+
backend = RedisBackend.get_instance()
|
|
572
|
+
val = backend.client.get(run_id)
|
|
573
|
+
if not val:
|
|
574
|
+
return False
|
|
575
|
+
if isinstance(val, bytes):
|
|
576
|
+
try:
|
|
577
|
+
val = val.decode()
|
|
578
|
+
except Exception:
|
|
579
|
+
val = str(val)
|
|
580
|
+
return isinstance(val, str) and val.strip().lower() == "revoke"
|
|
581
|
+
except Exception:
|
|
582
|
+
logger.warning("Unable to query Redis for cancellation for run_id=%s", run_id)
|
|
583
|
+
return False
|
data_diff/utils.py
CHANGED
|
@@ -1014,3 +1014,9 @@ class SybaseDriverTypes:
|
|
|
1014
1014
|
is_ase: bool = False
|
|
1015
1015
|
is_iq: bool = False
|
|
1016
1016
|
is_freetds: bool = False
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
class JobCancelledError(RuntimeError):
|
|
1020
|
+
def __init__(self, job_id: str):
|
|
1021
|
+
super().__init__(f"Job ID {job_id} has been revoked.")
|
|
1022
|
+
self.job_id = job_id
|
dcs_sdk/__version__.py
CHANGED
|
@@ -86,6 +86,7 @@ class DiffAdvancedConfig(BaseModel):
|
|
|
86
86
|
|
|
87
87
|
class Comparison(BaseModel):
|
|
88
88
|
comparison_name: str
|
|
89
|
+
job_id: Optional[int] = None
|
|
89
90
|
source: SourceTargetConnection
|
|
90
91
|
target: SourceTargetConnection
|
|
91
92
|
source_columns: Optional[List[str]] = None
|
|
@@ -429,6 +430,7 @@ class DataDiffConfig:
|
|
|
429
430
|
)
|
|
430
431
|
new_comparison = {
|
|
431
432
|
"comparison_name": comparison_name,
|
|
433
|
+
"job_id": comparison_data.get("job_id", None),
|
|
432
434
|
"source": self.create_connection_config(
|
|
433
435
|
source_connection,
|
|
434
436
|
comparison_data,
|
|
@@ -25,6 +25,7 @@ from rich.console import Console
|
|
|
25
25
|
|
|
26
26
|
from data_diff import TableSegment, connect, connect_to_table, diff_tables
|
|
27
27
|
from data_diff.databases import Database
|
|
28
|
+
from data_diff.databases.redis import RedisBackend
|
|
28
29
|
from dcs_sdk.sdk.config.config_loader import Comparison, SourceTargetConnection
|
|
29
30
|
from dcs_sdk.sdk.rules.rules_repository import RulesRepository
|
|
30
31
|
from dcs_sdk.sdk.utils.serializer import serialize_table_schema
|
|
@@ -160,6 +161,7 @@ class DBTableDiffer:
|
|
|
160
161
|
extra_columns=tuple(columns),
|
|
161
162
|
where=where,
|
|
162
163
|
transform_columns=config.transform_columns,
|
|
164
|
+
job_id=self.config.job_id,
|
|
163
165
|
)
|
|
164
166
|
|
|
165
167
|
def connect_to_db(self, config: SourceTargetConnection, is_source: bool):
|
|
@@ -322,7 +324,6 @@ class DBTableDiffer:
|
|
|
322
324
|
|
|
323
325
|
self.table1 = self.connect_to_db_table(self.config.source, is_source=True)
|
|
324
326
|
self.table2 = self.connect_to_db_table(self.config.target, is_source=False)
|
|
325
|
-
|
|
326
327
|
table_1_sample_data = []
|
|
327
328
|
table_2_sample_data = []
|
|
328
329
|
db1_name = (
|
|
@@ -399,8 +400,8 @@ class DBTableDiffer:
|
|
|
399
400
|
table_1_sample_data = self.table1.with_schema().get_sample_data(limit=100)
|
|
400
401
|
sample_keys = [list(row[:pks_len]) for row in table_1_sample_data]
|
|
401
402
|
table_2_sample_data = self.table2.with_schema().get_sample_data(limit=100, sample_keys=sample_keys)
|
|
402
|
-
if self.config.advanced_configuration.in_memory_diff:
|
|
403
|
-
|
|
403
|
+
# if self.config.advanced_configuration.in_memory_diff:
|
|
404
|
+
# self.config.advanced_configuration.egress_limit = min(max_row_count, 50_00_000)
|
|
404
405
|
self.diff_iter = diff_tables(
|
|
405
406
|
self.table1,
|
|
406
407
|
self.table2,
|
|
@@ -658,7 +659,15 @@ class DBTableDiffer:
|
|
|
658
659
|
break
|
|
659
660
|
|
|
660
661
|
def sort_key(row, key_columns, extra_columns):
|
|
661
|
-
|
|
662
|
+
key_values = []
|
|
663
|
+
for k in key_columns + extra_columns:
|
|
664
|
+
if k in row:
|
|
665
|
+
value = row[k]
|
|
666
|
+
if value is None:
|
|
667
|
+
key_values.append("None")
|
|
668
|
+
else:
|
|
669
|
+
key_values.append(value)
|
|
670
|
+
return tuple(key_values)
|
|
662
671
|
|
|
663
672
|
remaining_sources = [row for i, row in enumerate(source_rows) if i not in used_sources]
|
|
664
673
|
remaining_targets = [row for j, row in enumerate(target_rows) if j not in used_targets]
|
|
@@ -745,6 +754,8 @@ class DBTableDiffer:
|
|
|
745
754
|
|
|
746
755
|
safe_close(self.source_db)
|
|
747
756
|
safe_close(self.target_db)
|
|
757
|
+
if self.config.job_id:
|
|
758
|
+
safe_close(RedisBackend.get_instance())
|
|
748
759
|
|
|
749
760
|
def cleanup_duckdb(self, src: str, target: str):
|
|
750
761
|
if src and src.endswith("duckdb"):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dcs-sdk
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: SDK for DataChecks
|
|
5
5
|
Author: Waterdip Labs
|
|
6
6
|
Author-email: hello@waterdip.ai
|
|
@@ -49,6 +49,7 @@ Requires-Dist: pydantic (>=1.10.12)
|
|
|
49
49
|
Requires-Dist: pyodbc (>=4.0.39) ; extra == "mssql" or extra == "sybase" or extra == "all-dbs"
|
|
50
50
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
|
51
51
|
Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
|
|
52
|
+
Requires-Dist: redis[hiredis] (>=5.2.1,<6.0.0)
|
|
52
53
|
Requires-Dist: requests (>=2.32.4,<3.0.0)
|
|
53
54
|
Requires-Dist: rich (>=13.8.0)
|
|
54
55
|
Requires-Dist: snowflake-connector-python (>=3.17.2) ; extra == "snowflake" or extra == "all-dbs"
|
|
@@ -61,7 +62,7 @@ Requires-Dist: vertica-python (>=1.4.0) ; extra == "vertica" or extra == "all-db
|
|
|
61
62
|
Description-Content-Type: text/markdown
|
|
62
63
|
|
|
63
64
|
<h1 align="center">
|
|
64
|
-
DCS SDK v1.6.
|
|
65
|
+
DCS SDK v1.6.2
|
|
65
66
|
</h1>
|
|
66
67
|
|
|
67
68
|
> SDK for DataChecks
|
|
@@ -16,6 +16,7 @@ data_diff/databases/mysql.py,sha256=LTuLTkxac16y7w5_q1nEuKy6ZefqQUBQqV_tdnzjNT4,
|
|
|
16
16
|
data_diff/databases/oracle.py,sha256=GIczARg96lOlmgUpHd-hOFl8etFJmxWMy-KkA2COG74,8031
|
|
17
17
|
data_diff/databases/postgresql.py,sha256=dSZBUYbGwWnvCwTxSwMSiaElmQSpB2Q3chsmgvUeqQE,10787
|
|
18
18
|
data_diff/databases/presto.py,sha256=1Z8iDV2pc35Bu7DuUerFuFLbrwgSHSkBYmJ72JlZSZ8,7116
|
|
19
|
+
data_diff/databases/redis.py,sha256=gspPgUr7uFyZrqhIHBgYZo7-ecKNn8Wc_S8CVSQasLU,3501
|
|
19
20
|
data_diff/databases/redshift.py,sha256=-gFWs3NCcevO4s6c4zV3_LYihK24fUd5BADTKahubjw,8122
|
|
20
21
|
data_diff/databases/snowflake.py,sha256=7G6fvVJXOtTvXmSfWCxTslF4WohoscQoiqcmJIN684A,7910
|
|
21
22
|
data_diff/databases/sybase.py,sha256=RCZu2sqY08w8CN5NY0WN6QZFJBvQ3Ezk8OtfH8enxaY,31311
|
|
@@ -24,7 +25,7 @@ data_diff/databases/vertica.py,sha256=2dSDZp6qOEvUVPldI5Tgn7Sm3dCpC3vNXJL3qb3FDv
|
|
|
24
25
|
data_diff/diff_tables.py,sha256=AyFJF6oaam06AH4ZPI8pj63BiYojHoZTykjrdJCX2fI,20899
|
|
25
26
|
data_diff/errors.py,sha256=4Yru8yOwyuDuBlTABnGCvJMSpe6-rbLJpNnVHeTTyHU,745
|
|
26
27
|
data_diff/format.py,sha256=QFDjdZaBVf_N-jfKiX4ppOUdpXTPZXmv1j0pc1RiOoc,10245
|
|
27
|
-
data_diff/hashdiff_tables.py,sha256=
|
|
28
|
+
data_diff/hashdiff_tables.py,sha256=c-YOOkjUGUok_MJpvkwVOxfJPIQdvtJkW686kPLUYsM,43252
|
|
28
29
|
data_diff/info_tree.py,sha256=yHtFSoXuu6oBafLYOYQjUSKlB-DnAAd08U9HOEAdTPI,2799
|
|
29
30
|
data_diff/joindiff_tables.py,sha256=fyrEYjyh2BX1vGibwVZLYM1V6JJTOY-uGXY-KInvMkw,17612
|
|
30
31
|
data_diff/lexicographic_space.py,sha256=bBoCbbH1Mla9jNOq1b5RuwjAxSVU7gWkra673tPBwXQ,8305
|
|
@@ -37,20 +38,20 @@ data_diff/queries/base.py,sha256=pT-iaII7Nlu-w-Cuq9fhoNKX7-GSxkQ3Fk8K-tMkk60,964
|
|
|
37
38
|
data_diff/queries/extras.py,sha256=aUm-ifj3BMlz4o4bbuHtmnvHZuptYAKGS5yWTHmNpvc,1270
|
|
38
39
|
data_diff/query_utils.py,sha256=R7ZfRwcvv9Zf4zWXNln4tr_OxLmDI7CPmmCahYfHxlo,2101
|
|
39
40
|
data_diff/schema.py,sha256=QoYSSB3k-svLXz680uRgsI4qjii8BFKOOQvheqtgEbs,2413
|
|
40
|
-
data_diff/table_segment.py,sha256=
|
|
41
|
+
data_diff/table_segment.py,sha256=pGSrTmtVt4ioDj06U47XBlJf_p5EtwO2QVXR9iunkZM,24491
|
|
41
42
|
data_diff/thread_utils.py,sha256=_692ERjnWfHKaZsLdg7CNfkKiRd66y7_kpgDwzntp44,3831
|
|
42
|
-
data_diff/utils.py,sha256=
|
|
43
|
+
data_diff/utils.py,sha256=A0ZoxIngdU-uiiFp1uXcNx1XlEsLWgXr8J36my_ViSw,33627
|
|
43
44
|
data_diff/version.py,sha256=Wk0ovyBlLEF2UaWLWEcVBLFElREtIxi7TU1hD3CuTFI,634
|
|
44
45
|
dcs_sdk/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
|
|
45
46
|
dcs_sdk/__main__.py,sha256=Qn8stIaQGrdLjHQ-H7xO0T-brtq5RWZoWU9QvqoarV8,683
|
|
46
|
-
dcs_sdk/__version__.py,sha256=
|
|
47
|
+
dcs_sdk/__version__.py,sha256=Pa1cOhyUyQyETiOwXfxJyAF2FKshzqr1qkVSsgMjYAs,633
|
|
47
48
|
dcs_sdk/cli/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
|
|
48
49
|
dcs_sdk/cli/cli.py,sha256=LyrRk972OL9pTqrvBeXWBu5rUDAN17lQ1g8FdSRW_8M,4299
|
|
49
50
|
dcs_sdk/sdk/__init__.py,sha256=skrZcgWWJBL6NXTUERywJ3qRJRemgpDXyW7lPg1FJk8,2107
|
|
50
51
|
dcs_sdk/sdk/config/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
|
|
51
|
-
dcs_sdk/sdk/config/config_loader.py,sha256=
|
|
52
|
+
dcs_sdk/sdk/config/config_loader.py,sha256=oooSTV6QjbXKpCkwpl6vcBdjABGT-h99vBbWTbIkmjc,21683
|
|
52
53
|
dcs_sdk/sdk/data_diff/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
|
|
53
|
-
dcs_sdk/sdk/data_diff/data_differ.py,sha256=
|
|
54
|
+
dcs_sdk/sdk/data_diff/data_differ.py,sha256=zxWa-mYAdfZepNuXz1h_xxFQBC4tdhBqlbZCVEfb8Y8,36378
|
|
54
55
|
dcs_sdk/sdk/rules/__init__.py,sha256=_BkKcE_jfdDQI_ECdOamJaefMKEXrKpYjPpnBQXl_Xs,657
|
|
55
56
|
dcs_sdk/sdk/rules/rules_mappping.py,sha256=fxakVkf7B2cVkYSO946LTim_HmMsl6lBDBqZjTTsSPI,1292
|
|
56
57
|
dcs_sdk/sdk/rules/rules_repository.py,sha256=x0Rli-wdnHAmXm5526go_qC3P-eFRt-4L7fs4hNqC-g,7564
|
|
@@ -65,7 +66,7 @@ dcs_sdk/sdk/utils/similarity_score/levenshtein_distance_provider.py,sha256=puAWP
|
|
|
65
66
|
dcs_sdk/sdk/utils/table.py,sha256=X8HxdYTWyx_oVrBWPsXlmA-xJKXXDBW9RrhlWNqA1As,18224
|
|
66
67
|
dcs_sdk/sdk/utils/themes.py,sha256=Meo2Yldv4uyPpEqI7qdA28Aa6sxtwUU1dLKKm4QavjM,1403
|
|
67
68
|
dcs_sdk/sdk/utils/utils.py,sha256=vF2zAvgt__Y8limicWTEWRyn41SBVJN81ZCTBRy6hQg,11907
|
|
68
|
-
dcs_sdk-1.6.
|
|
69
|
-
dcs_sdk-1.6.
|
|
70
|
-
dcs_sdk-1.6.
|
|
71
|
-
dcs_sdk-1.6.
|
|
69
|
+
dcs_sdk-1.6.2.dist-info/METADATA,sha256=pSN0LCAuwyoWjSaHN_pibtgtHKLH8nsea-A2sbgdeRg,6322
|
|
70
|
+
dcs_sdk-1.6.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
71
|
+
dcs_sdk-1.6.2.dist-info/entry_points.txt,sha256=zQtrZL7YuaKtt6WPwihCTV1BRXnqBkaY6zUGdYJbBSg,49
|
|
72
|
+
dcs_sdk-1.6.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|