dcs-sdk 1.5.7__py3-none-any.whl → 1.5.9__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/__init__.py CHANGED
@@ -114,6 +114,7 @@ def diff_tables(
114
114
  # Timeout limit in minutes
115
115
  # (used for diffing large tables, to avoid long-running queries)
116
116
  timeout_limit: int = DEAFULT_TIMEOUT,
117
+ in_memory_diff: bool = False,
117
118
  ) -> Iterator:
118
119
  """Finds the diff between table1 and table2.
119
120
 
@@ -198,6 +199,7 @@ def diff_tables(
198
199
  per_column_diff_limit=per_column_diff_limit,
199
200
  egress_limit=egress_limit,
200
201
  timeout_limit=timeout_limit,
202
+ in_memory_diff=in_memory_diff,
201
203
  )
202
204
  elif algorithm == Algorithm.JOINDIFF:
203
205
  if isinstance(materialize_to_table, str):
@@ -185,7 +185,13 @@ class PostgresqlDialect(BaseDialect):
185
185
  return padded
186
186
 
187
187
  def normalize_number(self, value: str, coltype: FractionalType) -> str:
188
- return self.to_string(f"{value}::decimal(38, {coltype.precision})")
188
+ precision = coltype.precision
189
+ if precision:
190
+ if precision >= 1000:
191
+ precision = 1000
192
+ elif precision <= -1000:
193
+ precision = -1000
194
+ return self.to_string(f"{value}::decimal(38, {precision})")
189
195
 
190
196
  def normalize_boolean(self, value: str, _coltype: Boolean) -> str:
191
197
  return self.to_string(f"{value}::int")
@@ -299,8 +299,9 @@ class Dialect(BaseDialect):
299
299
  return timestamp_str
300
300
 
301
301
  def normalize_number(self, value: str, coltype: FractionalType) -> str:
302
- scale = getattr(coltype, "scale", 0) or 0
303
- return self.to_string(f"CAST({value} AS DECIMAL(38, {scale}))")
302
+ # scale = getattr(coltype, "scale", 0) or 0
303
+ precision = getattr(coltype, "precision", 0) or 0
304
+ return self.to_string(f"CAST({value} AS DECIMAL(38, {precision}))")
304
305
 
305
306
  # def md5_as_int(self, s: str) -> str:
306
307
  # """Returns an MD5 hash of the input string as an integer for Sybase IQ."""
@@ -18,7 +18,7 @@ import time
18
18
  from collections import defaultdict
19
19
  from numbers import Number
20
20
  from threading import Lock
21
- from typing import Any, Collection, Dict, Iterator, List, Sequence, Set, Tuple
21
+ from typing import Any, Collection, Dict, Iterator, List, Optional, Sequence, Set, Tuple
22
22
 
23
23
  import attrs
24
24
  from loguru import logger
@@ -711,3 +711,315 @@ class HashDiffer(TableDiffer):
711
711
  return diff
712
712
 
713
713
  return super()._bisect_and_diff_segments(ti, table1, table2, info_tree, level, max_rows)
714
+
715
+
716
+ @attrs.define(frozen=False)
717
+ class HashDiffer(HashDiffer):
718
+ """
719
+ Enhanced HashDiffer with in-memory mode support.
720
+
721
+ Additional Parameters:
722
+ in_memory_diff (bool): If True, skip checksums and download segments directly for in-memory comparison.
723
+ If False, use standard checksum-based bisection (default behavior).
724
+ memory_segment_size (int): When in_memory_diff=True, target number of rows per segment before downloading.
725
+ """
726
+
727
+ in_memory_diff: bool = False
728
+ memory_segment_size: int = 10000
729
+
730
+ def __attrs_post_init__(self) -> None:
731
+ super().__attrs_post_init__()
732
+
733
+ if self.in_memory_diff:
734
+ logger.info("=" * 70)
735
+ logger.info("IN-MEMORY DIFF MODE ENABLED")
736
+ logger.info(" - Checksum queries: DISABLED")
737
+ logger.info(f" - Segment size: {self.memory_segment_size} rows")
738
+ logger.info(f" - Threading: {'ENABLED' if self.threaded else 'DISABLED'}")
739
+ logger.info(f" - Egress limit: {self.egress_limit} rows")
740
+ logger.info("=" * 70)
741
+
742
+ # Adjust bisection threshold for in-memory mode
743
+ if self.memory_segment_size > 0:
744
+ self.bisection_threshold = self.memory_segment_size
745
+
746
+ def _should_skip_checksum_and_download(self, max_rows: int) -> bool:
747
+ """
748
+ Determine if we should skip checksum and directly download segment data.
749
+
750
+ Returns True if:
751
+ 1. in_memory_diff flag is enabled, OR
752
+ 2. Traditional conditions: segment is below bisection threshold
753
+ """
754
+ return self.in_memory_diff
755
+ # if self.in_memory_diff:
756
+ # # In memory mode: download if segment is at or below target size
757
+ # return max_rows <= self.memory_segment_size
758
+ # else:
759
+ # # Traditional mode: use bisection threshold
760
+ # return self.bisection_disabled or max_rows < self.bisection_threshold
761
+
762
+ def _diff_segments(
763
+ self,
764
+ ti,
765
+ table1: TableSegment,
766
+ table2: TableSegment,
767
+ info_tree: InfoTree,
768
+ max_rows: int,
769
+ level=0,
770
+ segment_index=None,
771
+ segment_count=None,
772
+ ):
773
+ """
774
+ Enhanced segment diffing with in-memory mode support.
775
+ """
776
+ # Check recursion depth limit
777
+ if level > 15:
778
+ logger.warning(
779
+ ". " * level + f"Maximum recursion level ({level}) reached; "
780
+ f"downloading segment {table1.min_key}..{table1.max_key}"
781
+ )
782
+ return self._download_and_diff_locally(table1, table2, info_tree, level)
783
+
784
+ # Initialize diff tracker
785
+ self._initialize_diff_tracker(table1, table2)
786
+
787
+ logger.info(
788
+ ". " * level + f"Diffing segment {segment_index}/{segment_count}, "
789
+ f"key-range: {table1.min_key}..{table2.max_key}, "
790
+ f"size <= {max_rows}"
791
+ )
792
+
793
+ # Check all stop conditions
794
+ if not self._check_continuation_conditions(table1, info_tree, level):
795
+ return
796
+
797
+ # IN-MEMORY MODE: Skip checksum if flag is set or segment is small enough
798
+ if self._should_skip_checksum_and_download(max_rows):
799
+ if self.in_memory_diff:
800
+ logger.info(". " * level + f"[IN-MEMORY MODE] Downloading segment directly " f"(size: {max_rows} rows)")
801
+
802
+ return self._download_and_diff_locally(table1, table2, info_tree, level)
803
+
804
+ # STANDARD MODE: Perform checksum-based comparison
805
+ return self._checksum_and_bisect_if_needed(
806
+ ti, table1, table2, info_tree, level, max_rows, segment_index, segment_count
807
+ )
808
+
809
+ def _check_continuation_conditions(self, table1: TableSegment, info_tree: InfoTree, level: int) -> bool:
810
+ """Check if we should continue diffing (respects limits)."""
811
+
812
+ # Check per-column diff limit
813
+ elapsed = time.monotonic() - self.start_time
814
+ if (
815
+ len(self._diff_tracker.get_stopped_columns()) > 0
816
+ and not self.stats.get("rows_downloaded", 0) >= self.egress_limit
817
+ and not elapsed > self.timeout_limit * 60
818
+ ):
819
+ self.update_comparison_tracker(
820
+ reason_type="per_column_diff_limit",
821
+ segment=f"{table1.min_key}..{table1.max_key}",
822
+ )
823
+
824
+ if not self._diff_tracker.has_active_targets(len(table1.relevant_columns)):
825
+ logger.info(
826
+ "Diffing stopped because columns with potential differences "
827
+ "have reached their configured diff limits."
828
+ )
829
+ info_tree.info.is_diff = False
830
+ self.update_comparison_tracker(
831
+ reason_type="per_column_diff_limit",
832
+ segment=f"{table1.min_key}..{table1.max_key}",
833
+ )
834
+ return False
835
+
836
+ # Check egress limit
837
+ if self.stats.get("rows_downloaded", 0) >= self.egress_limit:
838
+ info_tree.info.is_diff = False
839
+ logger.info(
840
+ ". " * level + f"Row download limit reached "
841
+ f"{self.stats.get('rows_downloaded')}, stopping bisection for "
842
+ f"segment {table1.min_key}..{table1.max_key}"
843
+ )
844
+ self.update_comparison_tracker(
845
+ reason_type="egress_limit",
846
+ segment=f"{table1.min_key}..{table1.max_key}",
847
+ )
848
+ return False
849
+
850
+ # Check timeout
851
+ elapsed = time.monotonic() - self.start_time
852
+ if elapsed > self.timeout_limit * 60:
853
+ info_tree.info.is_diff = False
854
+ logger.info(
855
+ ". " * level + f"Timeout limit reached ({self.timeout_limit} min); "
856
+ f"stopping bisection for segment {table1.min_key}..{table1.max_key}"
857
+ )
858
+ self.update_comparison_tracker(
859
+ reason_type="timeout",
860
+ segment=f"{table1.min_key}..{table1.max_key}",
861
+ )
862
+ return False
863
+
864
+ return True
865
+
866
+ def _download_and_diff_locally(
867
+ self,
868
+ table1: TableSegment,
869
+ table2: TableSegment,
870
+ info_tree: InfoTree,
871
+ level: int,
872
+ ) -> List:
873
+ """Download segment rows and perform in-memory diff."""
874
+
875
+ mode_label = "[IN-MEMORY]" if self.in_memory_diff else "[STANDARD]"
876
+ logger.info(
877
+ ". " * level + f"{mode_label} Downloading rows for comparison: " f"{table1.min_key}..{table1.max_key}"
878
+ )
879
+
880
+ # Download rows from both tables
881
+ rows1, rows2 = self._threaded_call("get_values", [table1, table2])
882
+
883
+ # Update statistics
884
+ downloaded = max(len(rows1), len(rows2))
885
+ self.stats["rows_downloaded"] = self.stats.get("rows_downloaded", 0) + downloaded
886
+
887
+ logger.info(
888
+ ". " * level + f"{mode_label} Downloaded {len(rows1)} and {len(rows2)} rows. "
889
+ f"Total downloaded: {self.stats['rows_downloaded']}"
890
+ )
891
+
892
+ # Perform in-memory diff
893
+ json_cols = {
894
+ i: colname for i, colname in enumerate(table1.extra_columns) if isinstance(table1._schema[colname], JSON)
895
+ }
896
+
897
+ diff = list(
898
+ diff_sets(
899
+ rows1,
900
+ rows2,
901
+ json_cols=json_cols,
902
+ columns1=table1.relevant_columns,
903
+ columns2=table2.relevant_columns,
904
+ key_columns1=table1.key_columns,
905
+ key_columns2=table2.key_columns,
906
+ ignored_columns1=self.ignored_columns1,
907
+ ignored_columns2=self.ignored_columns2,
908
+ diff_tracker=self._diff_tracker,
909
+ )
910
+ )
911
+
912
+ # Update info tree
913
+ info_tree.info.set_diff(diff)
914
+ info_tree.info.rowcounts = {1: len(rows1), 2: len(rows2)}
915
+
916
+ logger.info(". " * level + f"{mode_label} Found {len(diff)} different rows in this segment")
917
+
918
+ return diff
919
+
920
+ def _checksum_and_bisect_if_needed(
921
+ self,
922
+ ti,
923
+ table1: TableSegment,
924
+ table2: TableSegment,
925
+ info_tree: InfoTree,
926
+ level: int,
927
+ max_rows: int,
928
+ segment_index: Optional[int],
929
+ segment_count: Optional[int],
930
+ ):
931
+ """Perform checksum comparison and bisect if differences found (standard mode)."""
932
+
933
+ logger.info(". " * level + "[CHECKSUM MODE] Comparing segment checksums")
934
+
935
+ # Get active columns for checksum (excluding stopped columns)
936
+ active_cols1, active_cols2 = self._get_checksum_columns(table1, table2)
937
+
938
+ # Create segments with updated columns for checksum
939
+ checksum_table1 = self._create_segment_with_updated_columns(table1, active_cols1)
940
+ checksum_table2 = self._create_segment_with_updated_columns(table2, active_cols2)
941
+
942
+ # Perform checksum
943
+ (count1, checksum1), (count2, checksum2) = self._threaded_call(
944
+ "count_and_checksum", [checksum_table1, checksum_table2]
945
+ )
946
+
947
+ assert not info_tree.info.rowcounts
948
+ info_tree.info.rowcounts = {1: count1, 2: count2}
949
+
950
+ # Handle empty segments
951
+ if count1 == 0 and count2 == 0:
952
+ logger.debug(
953
+ "Uneven distribution of keys detected in segment {}..{} "
954
+ "(big gaps in the key column). For better performance, "
955
+ "we recommend to increase the bisection-threshold.",
956
+ table1.min_key,
957
+ table1.max_key,
958
+ )
959
+ assert checksum1 is None and checksum2 is None
960
+ info_tree.info.is_diff = False
961
+ return
962
+
963
+ # Compare checksums
964
+ if checksum1 == checksum2:
965
+ logger.info(". " * level + "[CHECKSUM MODE] Checksums match - no differences")
966
+ info_tree.info.is_diff = False
967
+ return
968
+
969
+ logger.info(". " * level + "[CHECKSUM MODE] Checksums differ - bisecting segment")
970
+ info_tree.info.is_diff = True
971
+
972
+ # Bisect and continue
973
+ return self._bisect_and_diff_segments(ti, table1, table2, info_tree, level=level, max_rows=max(count1, count2))
974
+
975
+ def _bisect_and_diff_segments(
976
+ self,
977
+ ti,
978
+ table1: TableSegment,
979
+ table2: TableSegment,
980
+ info_tree: InfoTree,
981
+ level=0,
982
+ max_rows=None,
983
+ ):
984
+ """
985
+ Enhanced bisection with in-memory mode support.
986
+ """
987
+ # Check recursion limit
988
+ if level > 15:
989
+ logger.warning(
990
+ ". " * level + f"Maximum recursion level ({level}) reached; "
991
+ f"downloading segment {table1.min_key}..{table1.max_key}"
992
+ )
993
+ return self._download_and_diff_locally(table1, table2, info_tree, level)
994
+
995
+ assert table1.is_bounded and table2.is_bounded
996
+
997
+ # Initialize diff tracker
998
+ self._initialize_diff_tracker(table1, table2)
999
+
1000
+ # Check continuation conditions
1001
+ if not self._check_continuation_conditions(table1, info_tree, level):
1002
+ return
1003
+
1004
+ # Calculate max space size
1005
+ max_space_size = max(table1.approximate_size(self.t1_row_count), table2.approximate_size(self.t2_row_count))
1006
+
1007
+ if max_rows is None:
1008
+ max_rows = max_space_size
1009
+
1010
+ info_tree.info.max_rows = max_rows
1011
+
1012
+ # Check if we should download directly
1013
+ should_download = (
1014
+ self.bisection_disabled or max_rows < self.bisection_threshold or max_space_size < self.bisection_factor * 2
1015
+ )
1016
+
1017
+ # In-memory mode: also download if at target segment size
1018
+ if self.in_memory_diff and max_rows <= self.memory_segment_size:
1019
+ should_download = True
1020
+
1021
+ if should_download:
1022
+ return self._download_and_diff_locally(table1, table2, info_tree, level)
1023
+
1024
+ # Otherwise, continue with standard bisection
1025
+ return super()._bisect_and_diff_segments(ti, table1, table2, info_tree, level, max_rows)
dcs_sdk/__version__.py CHANGED
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __version__ = "1.5.7"
15
+ __version__ = "1.5.9"
@@ -81,6 +81,7 @@ class DiffAdvancedConfig(BaseModel):
81
81
  egress_limit: int = 5_00_000
82
82
  per_column_diff_limit: int = 100
83
83
  timeout_limit: int = 60 * 5 # minutes
84
+ in_memory_diff: bool = False # Whether to perform diff in memory (may use more RAM)
84
85
 
85
86
 
86
87
  class Comparison(BaseModel):
@@ -424,6 +425,7 @@ class DataDiffConfig:
424
425
  egress_limit=advanced_diff_config.get("egress_limit", 5_00_000),
425
426
  per_column_diff_limit=advanced_diff_config.get("per_column_diff_limit", 100),
426
427
  timeout_limit=advanced_diff_config.get("timeout_limit", 60 * 5),
428
+ in_memory_diff=advanced_diff_config.get("in_memory_diff", False),
427
429
  )
428
430
  new_comparison = {
429
431
  "comparison_name": comparison_name,
@@ -399,6 +399,8 @@ class DBTableDiffer:
399
399
  table_1_sample_data = self.table1.with_schema().get_sample_data(limit=100)
400
400
  sample_keys = [list(row[:pks_len]) for row in table_1_sample_data]
401
401
  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
+ self.config.advanced_configuration.egress_limit = min(max_row_count, 50_00_000)
402
404
  self.diff_iter = diff_tables(
403
405
  self.table1,
404
406
  self.table2,
@@ -410,6 +412,7 @@ class DBTableDiffer:
410
412
  per_column_diff_limit=self.config.advanced_configuration.per_column_diff_limit,
411
413
  egress_limit=self.config.advanced_configuration.egress_limit,
412
414
  timeout_limit=self.config.advanced_configuration.timeout_limit,
415
+ in_memory_diff=self.config.advanced_configuration.in_memory_diff,
413
416
  )
414
417
 
415
418
  columns_mappings = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dcs-sdk
3
- Version: 1.5.7
3
+ Version: 1.5.9
4
4
  Summary: SDK for DataChecks
5
5
  Author: Waterdip Labs
6
6
  Author-email: hello@waterdip.ai
@@ -61,7 +61,7 @@ Requires-Dist: vertica-python (>=1.4.0) ; extra == "vertica" or extra == "all-db
61
61
  Description-Content-Type: text/markdown
62
62
 
63
63
  <h1 align="center">
64
- DCS SDK v1.5.7
64
+ DCS SDK v1.5.9
65
65
  </h1>
66
66
 
67
67
  > SDK for DataChecks
@@ -1,4 +1,4 @@
1
- data_diff/__init__.py,sha256=TGNvifF-dIbitACA6PS4sORtHEcTUukcrZz2NEIsL9U,10336
1
+ data_diff/__init__.py,sha256=QrrQt6GxG5gzVRlvFjJmfOzhR14fqKLrQs186KBWryY,10413
2
2
  data_diff/__main__.py,sha256=UvFvBKU74202bfRcIO_Wk-SU8WmnNuDK_1YVJpueMlc,16969
3
3
  data_diff/abcs/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
4
4
  data_diff/abcs/compiler.py,sha256=RuGhGlLTQuCzOJfYxa4gjcADsyvbZ9yZPuDuY6XH8Rk,785
@@ -14,17 +14,17 @@ data_diff/databases/duckdb.py,sha256=7r1PwPUpp61QN_ZorsBTyn6NTB1LcBKQofYl_wovm1U
14
14
  data_diff/databases/mssql.py,sha256=mA6myRemhad-q9yyRSt6VRj6na_i4joD0HI7IgGt8zQ,11987
15
15
  data_diff/databases/mysql.py,sha256=LTuLTkxac16y7w5_q1nEuKy6ZefqQUBQqV_tdnzjNT4,6148
16
16
  data_diff/databases/oracle.py,sha256=GIczARg96lOlmgUpHd-hOFl8etFJmxWMy-KkA2COG74,8031
17
- data_diff/databases/postgresql.py,sha256=QrvYDsMSECQiPfsl85UQxY9ivxTRXnEwjAfRjd-Qnk4,10748
17
+ data_diff/databases/postgresql.py,sha256=E8VtuHDGlULegb42KXzls0agEhEAJ2O9h-Mwr5ViHZU,10938
18
18
  data_diff/databases/presto.py,sha256=1Z8iDV2pc35Bu7DuUerFuFLbrwgSHSkBYmJ72JlZSZ8,7116
19
19
  data_diff/databases/redshift.py,sha256=-gFWs3NCcevO4s6c4zV3_LYihK24fUd5BADTKahubjw,8122
20
20
  data_diff/databases/snowflake.py,sha256=7G6fvVJXOtTvXmSfWCxTslF4WohoscQoiqcmJIN684A,7910
21
- data_diff/databases/sybase.py,sha256=ap_FWJk39ZM68y9c5B-luxlo-IgOXCi862HBh7MZutU,31248
21
+ data_diff/databases/sybase.py,sha256=DIai691f1PrPORWb9EjdoQWFMLEKtXFoHQ9vJvEHnPU,31312
22
22
  data_diff/databases/trino.py,sha256=VIN3gMJvT4oSYuXCJ1QnngVL2gjjEYMFw87QTHgjs8c,2328
23
23
  data_diff/databases/vertica.py,sha256=2dSDZp6qOEvUVPldI5Tgn7Sm3dCpC3vNXJL3qb3FDvQ,5529
24
24
  data_diff/diff_tables.py,sha256=AyFJF6oaam06AH4ZPI8pj63BiYojHoZTykjrdJCX2fI,20899
25
25
  data_diff/errors.py,sha256=4Yru8yOwyuDuBlTABnGCvJMSpe6-rbLJpNnVHeTTyHU,745
26
26
  data_diff/format.py,sha256=QFDjdZaBVf_N-jfKiX4ppOUdpXTPZXmv1j0pc1RiOoc,10245
27
- data_diff/hashdiff_tables.py,sha256=EBhEAZz-2a-qNs3OlFArInAV1KszBdZPotZmX7Z_lwo,31315
27
+ data_diff/hashdiff_tables.py,sha256=oElu0rFAFaRGVZpiIl546yUVYQm02J6HFjVkpuHHFIQ,43134
28
28
  data_diff/info_tree.py,sha256=yHtFSoXuu6oBafLYOYQjUSKlB-DnAAd08U9HOEAdTPI,2799
29
29
  data_diff/joindiff_tables.py,sha256=fyrEYjyh2BX1vGibwVZLYM1V6JJTOY-uGXY-KInvMkw,17612
30
30
  data_diff/lexicographic_space.py,sha256=bBoCbbH1Mla9jNOq1b5RuwjAxSVU7gWkra673tPBwXQ,8305
@@ -43,14 +43,14 @@ data_diff/utils.py,sha256=ZSgK6utdYDWvnsYgl7sJQa6J3XK3T6xSB_BGdQVeK24,33457
43
43
  data_diff/version.py,sha256=Wk0ovyBlLEF2UaWLWEcVBLFElREtIxi7TU1hD3CuTFI,634
44
44
  dcs_sdk/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
45
45
  dcs_sdk/__main__.py,sha256=Qn8stIaQGrdLjHQ-H7xO0T-brtq5RWZoWU9QvqoarV8,683
46
- dcs_sdk/__version__.py,sha256=xvnvu6wSe7otkNeAkcLgPV0ELqT7G6RGaYllHIVN2Ts,633
46
+ dcs_sdk/__version__.py,sha256=Syic9kjTewAbYYhDKKRgMcp-NZeosWsa7uGfE_JlLHs,633
47
47
  dcs_sdk/cli/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
48
48
  dcs_sdk/cli/cli.py,sha256=LyrRk972OL9pTqrvBeXWBu5rUDAN17lQ1g8FdSRW_8M,4299
49
49
  dcs_sdk/sdk/__init__.py,sha256=skrZcgWWJBL6NXTUERywJ3qRJRemgpDXyW7lPg1FJk8,2107
50
50
  dcs_sdk/sdk/config/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
51
- dcs_sdk/sdk/config/config_loader.py,sha256=Sg0gvleGrOcDaX41amgw6Uj6c_s4Zel6gQalIp9CltI,21416
51
+ dcs_sdk/sdk/config/config_loader.py,sha256=hVdGidcm6ibqJ0yt7fZcL_0kFcorBfM7vHGhUiBH9Ww,21587
52
52
  dcs_sdk/sdk/data_diff/__init__.py,sha256=RkfhRKLXEForLCs4rZkTf0qc_b0TokSggSAcKI4yfZg,610
53
- dcs_sdk/sdk/data_diff/data_differ.py,sha256=RH9C9OthahU8eeJzmUgQe24UZGGuBu7X2a_DrhTCa-U,35590
53
+ dcs_sdk/sdk/data_diff/data_differ.py,sha256=d8hwXs0zG5AuaRjsNlpFShpTxA1_YPgH2aCRsJQfDMU,35846
54
54
  dcs_sdk/sdk/rules/__init__.py,sha256=_BkKcE_jfdDQI_ECdOamJaefMKEXrKpYjPpnBQXl_Xs,657
55
55
  dcs_sdk/sdk/rules/rules_mappping.py,sha256=fxakVkf7B2cVkYSO946LTim_HmMsl6lBDBqZjTTsSPI,1292
56
56
  dcs_sdk/sdk/rules/rules_repository.py,sha256=x0Rli-wdnHAmXm5526go_qC3P-eFRt-4L7fs4hNqC-g,7564
@@ -65,7 +65,7 @@ dcs_sdk/sdk/utils/similarity_score/levenshtein_distance_provider.py,sha256=puAWP
65
65
  dcs_sdk/sdk/utils/table.py,sha256=X8HxdYTWyx_oVrBWPsXlmA-xJKXXDBW9RrhlWNqA1As,18224
66
66
  dcs_sdk/sdk/utils/themes.py,sha256=Meo2Yldv4uyPpEqI7qdA28Aa6sxtwUU1dLKKm4QavjM,1403
67
67
  dcs_sdk/sdk/utils/utils.py,sha256=vF2zAvgt__Y8limicWTEWRyn41SBVJN81ZCTBRy6hQg,11907
68
- dcs_sdk-1.5.7.dist-info/METADATA,sha256=eQ1wuGbpB6gmbCWfC5yrPLWWCJXRZYASpWt4IaBl97Q,6275
69
- dcs_sdk-1.5.7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
70
- dcs_sdk-1.5.7.dist-info/entry_points.txt,sha256=zQtrZL7YuaKtt6WPwihCTV1BRXnqBkaY6zUGdYJbBSg,49
71
- dcs_sdk-1.5.7.dist-info/RECORD,,
68
+ dcs_sdk-1.5.9.dist-info/METADATA,sha256=sKgAYCQgujtdlWQZNWJnlY2XSKvti7YdAyrOAIOaH6o,6275
69
+ dcs_sdk-1.5.9.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
70
+ dcs_sdk-1.5.9.dist-info/entry_points.txt,sha256=zQtrZL7YuaKtt6WPwihCTV1BRXnqBkaY6zUGdYJbBSg,49
71
+ dcs_sdk-1.5.9.dist-info/RECORD,,