diffsync 2.0.0__tar.gz → 2.1.0__tar.gz
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.
- {diffsync-2.0.0 → diffsync-2.1.0}/CHANGELOG.md +29 -0
- {diffsync-2.0.0 → diffsync-2.1.0}/PKG-INFO +10 -11
- {diffsync-2.0.0 → diffsync-2.1.0}/README.md +3 -3
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/__init__.py +22 -26
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/diff.py +5 -6
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/exceptions.py +1 -0
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/helpers.py +11 -9
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/store/__init__.py +1 -0
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/store/redis.py +6 -5
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/utils.py +1 -0
- {diffsync-2.0.0 → diffsync-2.1.0}/pyproject.toml +6 -7
- {diffsync-2.0.0 → diffsync-2.1.0}/LICENSE +0 -0
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/enum.py +0 -0
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/logging.py +0 -0
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/py.typed +0 -0
- {diffsync-2.0.0 → diffsync-2.1.0}/diffsync/store/local.py +0 -0
|
@@ -4,6 +4,35 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## [2.1.0]
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- [284](https://github.com/networktocode/diffsync/pull/284) - Update pyyaml to 6.0.2 in poetry.lock by @gsnider2195
|
|
12
|
+
- [286](https://github.com/networktocode/diffsync/pull/286) - Update GitHub Actions runner version by @mjbear
|
|
13
|
+
- [289](https://github.com/networktocode/diffsync/pull/289) - Remove upper limit on Packaging by @jdrew82
|
|
14
|
+
|
|
15
|
+
## New Contributors
|
|
16
|
+
|
|
17
|
+
- @gsnider2195 made their first contribution in https://github.com/networktocode/diffsync/pull/284
|
|
18
|
+
- @mjbear made their first contribution in https://github.com/networktocode/diffsync/pull/286
|
|
19
|
+
- @jdrew82 made their first contribution in https://github.com/networktocode/diffsync/pull/289
|
|
20
|
+
|
|
21
|
+
## [2.0.1]
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- #276 - Removed upper version bound for `structlog` dependency
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- #281 - Properly deprecated `DiffSync` class name
|
|
30
|
+
- #273 - Properly capitalized `DiffSync` in documentation
|
|
31
|
+
- #273 - Removed more mentions of `DiffSync` in favor of `Adapter`
|
|
32
|
+
- #274 - Fixed doc section title for getting started
|
|
33
|
+
- #269 - Fixed wording for a couple of docstrings
|
|
34
|
+
- #265 - Fixed readthedocs build
|
|
35
|
+
|
|
7
36
|
## [2.0.0]
|
|
8
37
|
|
|
9
38
|
### Changed
|
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: diffsync
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Library to easily sync/diff/update 2 different data sources
|
|
5
|
-
Home-page: https://diffsync.readthedocs.io
|
|
6
5
|
License: Apache-2.0
|
|
7
6
|
Keywords: source-of-truth,synchronization
|
|
8
7
|
Author: Network to Code, LLC
|
|
9
8
|
Author-email: info@networktocode.com
|
|
10
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.9,<4.0
|
|
11
10
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
11
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
12
|
Classifier: Programming Language :: Python :: 3.9
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
17
|
Provides-Extra: redis
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist: packaging (>=21.3,<24.0)
|
|
18
|
+
Requires-Dist: packaging (>=21.3)
|
|
21
19
|
Requires-Dist: pydantic (>=2.0.0,<3.0.0)
|
|
22
20
|
Requires-Dist: redis (>=4.3,<5.0) ; extra == "redis"
|
|
23
|
-
Requires-Dist: structlog (>=20.1.0
|
|
21
|
+
Requires-Dist: structlog (>=20.1.0)
|
|
24
22
|
Requires-Dist: typing-extensions (>=4.0.1) ; python_version < "3.11"
|
|
25
23
|
Project-URL: Documentation, https://diffsync.readthedocs.io
|
|
24
|
+
Project-URL: Homepage, https://diffsync.readthedocs.io
|
|
26
25
|
Project-URL: Repository, https://github.com/networktocode/diffsync
|
|
27
26
|
Description-Content-Type: text/markdown
|
|
28
27
|
|
|
@@ -45,16 +44,16 @@ DiffSync is at its most useful when you have multiple sources or sets of data to
|
|
|
45
44
|
|
|
46
45
|
DiffSync acts as an intermediate translation layer between all of the data sets you are diffing and/or syncing. In practical terms, this means that to use DiffSync, you will define a set of data models as well as the “adapters” needed to translate between each base data source and the data model. In Python terms, the adapters will be subclasses of the `Adapter` class, and each data model class will be a subclass of the `DiffSyncModel` class.
|
|
47
46
|
|
|
48
|
-

|
|
49
48
|
|
|
50
49
|
|
|
51
50
|
Once you have used each adapter to load each data source into a collection of data model records, you can then ask DiffSync to “diff” the two data sets, and it will produce a structured representation of the difference between them. In Python, this is accomplished by calling the `diff_to()` or `diff_from()` method on one adapter and passing the other adapter as a parameter.
|
|
52
51
|
|
|
53
|
-

|
|
54
53
|
|
|
55
54
|
You can also ask DiffSync to “sync” one data set onto the other, and it will instruct your adapter as to the steps it needs to take to make sure that its data set accurately reflects the other. In Python, this is accomplished by calling the `sync_to()` or `sync_from()` method on one adapter and passing the other adapter as a parameter.
|
|
56
55
|
|
|
57
|
-

|
|
58
57
|
|
|
59
58
|
# Simple Example
|
|
60
59
|
|
|
@@ -17,16 +17,16 @@ DiffSync is at its most useful when you have multiple sources or sets of data to
|
|
|
17
17
|
|
|
18
18
|
DiffSync acts as an intermediate translation layer between all of the data sets you are diffing and/or syncing. In practical terms, this means that to use DiffSync, you will define a set of data models as well as the “adapters” needed to translate between each base data source and the data model. In Python terms, the adapters will be subclasses of the `Adapter` class, and each data model class will be a subclass of the `DiffSyncModel` class.
|
|
19
19
|
|
|
20
|
-

|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
Once you have used each adapter to load each data source into a collection of data model records, you can then ask DiffSync to “diff” the two data sets, and it will produce a structured representation of the difference between them. In Python, this is accomplished by calling the `diff_to()` or `diff_from()` method on one adapter and passing the other adapter as a parameter.
|
|
24
24
|
|
|
25
|
-

|
|
26
26
|
|
|
27
27
|
You can also ask DiffSync to “sync” one data set onto the other, and it will instruct your adapter as to the steps it needs to take to make sure that its data set accurately reflects the other. In Python, this is accomplished by calling the `sync_to()` or `sync_from()` method on one adapter and passing the other adapter as a parameter.
|
|
28
28
|
|
|
29
|
-

|
|
30
30
|
|
|
31
31
|
# Simple Example
|
|
32
32
|
|
|
@@ -14,32 +14,33 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
|
+
|
|
17
18
|
import sys
|
|
18
19
|
from inspect import isclass
|
|
19
20
|
from typing import (
|
|
21
|
+
Any,
|
|
20
22
|
Callable,
|
|
21
23
|
ClassVar,
|
|
22
24
|
Dict,
|
|
23
25
|
List,
|
|
24
26
|
Optional,
|
|
27
|
+
Set,
|
|
25
28
|
Tuple,
|
|
26
29
|
Type,
|
|
27
30
|
Union,
|
|
28
|
-
Any,
|
|
29
|
-
Set,
|
|
30
31
|
)
|
|
31
|
-
import warnings
|
|
32
32
|
|
|
33
|
-
from pydantic import ConfigDict, BaseModel, PrivateAttr
|
|
34
33
|
import structlog # type: ignore
|
|
34
|
+
from pydantic import BaseModel, ConfigDict, PrivateAttr
|
|
35
|
+
from typing_extensions import deprecated
|
|
35
36
|
|
|
36
37
|
from diffsync.diff import Diff
|
|
37
|
-
from diffsync.enum import
|
|
38
|
+
from diffsync.enum import DiffSyncFlags, DiffSyncModelFlags, DiffSyncStatus
|
|
38
39
|
from diffsync.exceptions import (
|
|
39
40
|
DiffClassMismatch,
|
|
40
41
|
ObjectAlreadyExists,
|
|
41
|
-
ObjectStoreWrongType,
|
|
42
42
|
ObjectNotFound,
|
|
43
|
+
ObjectStoreWrongType,
|
|
43
44
|
)
|
|
44
45
|
from diffsync.helpers import DiffSyncDiffer, DiffSyncSyncer
|
|
45
46
|
from diffsync.store import BaseStore
|
|
@@ -69,7 +70,7 @@ class DiffSyncModel(BaseModel):
|
|
|
69
70
|
be included in **at most** one of these three tuples.
|
|
70
71
|
"""
|
|
71
72
|
|
|
72
|
-
_modelname: ClassVar[str] = "diffsyncmodel"
|
|
73
|
+
_modelname: ClassVar[str] = "diffsyncmodel" # pylint: disable=used-before-assignment
|
|
73
74
|
"""Name of this model, used by DiffSync to store and look up instances of this model or its equivalents.
|
|
74
75
|
|
|
75
76
|
Lowercase by convention; typically corresponds to the class name, but that is not enforced.
|
|
@@ -133,16 +134,16 @@ class DiffSyncModel(BaseModel):
|
|
|
133
134
|
"""
|
|
134
135
|
# Make sure that any field referenced by name actually exists on the model
|
|
135
136
|
for attr in cls._identifiers:
|
|
136
|
-
if attr not in cls.model_fields and not hasattr(cls, attr):
|
|
137
|
+
if attr not in cls.model_fields and not hasattr(cls, attr): # pylint: disable=unsupported-membership-test
|
|
137
138
|
raise AttributeError(f"_identifiers {cls._identifiers} references missing or un-annotated attr {attr}")
|
|
138
139
|
for attr in cls._shortname:
|
|
139
|
-
if attr not in cls.model_fields:
|
|
140
|
+
if attr not in cls.model_fields: # pylint: disable=unsupported-membership-test
|
|
140
141
|
raise AttributeError(f"_shortname {cls._shortname} references missing or un-annotated attr {attr}")
|
|
141
142
|
for attr in cls._attributes:
|
|
142
|
-
if attr not in cls.model_fields:
|
|
143
|
+
if attr not in cls.model_fields: # pylint: disable=unsupported-membership-test
|
|
143
144
|
raise AttributeError(f"_attributes {cls._attributes} references missing or un-annotated attr {attr}")
|
|
144
145
|
for attr in cls._children.values():
|
|
145
|
-
if attr not in cls.model_fields:
|
|
146
|
+
if attr not in cls.model_fields: # pylint: disable=unsupported-membership-test
|
|
146
147
|
raise AttributeError(f"_children {cls._children} references missing or un-annotated attr {attr}")
|
|
147
148
|
|
|
148
149
|
# Any given field can only be in one of (_identifiers, _attributes, _children)
|
|
@@ -425,13 +426,13 @@ class DiffSyncModel(BaseModel):
|
|
|
425
426
|
|
|
426
427
|
|
|
427
428
|
class Adapter: # pylint: disable=too-many-public-methods
|
|
428
|
-
"""Class for storing a group of DiffSyncModel instances and diffing/synchronizing to another
|
|
429
|
+
"""Class for storing a group of DiffSyncModel instances and diffing/synchronizing to another Adapter instance."""
|
|
429
430
|
|
|
430
431
|
# In any subclass, you would add mapping of names to specific model classes here:
|
|
431
432
|
# modelname1 = MyModelClass1
|
|
432
433
|
# modelname2 = MyModelClass2
|
|
433
434
|
|
|
434
|
-
type: Optional[str] = None
|
|
435
|
+
type: Optional[str] = None # pylint: disable=used-before-assignment
|
|
435
436
|
"""Type of the object, will default to the name of the class if not provided."""
|
|
436
437
|
|
|
437
438
|
top_level: ClassVar[List[str]] = []
|
|
@@ -480,7 +481,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
480
481
|
raise AttributeError(f'top_level references attribute "{name}" but it is not a DiffSyncModel subclass!')
|
|
481
482
|
|
|
482
483
|
def __str__(self) -> StrType:
|
|
483
|
-
"""String representation of
|
|
484
|
+
"""String representation of an Adapter."""
|
|
484
485
|
if self.type != self.name:
|
|
485
486
|
return f'{self.type} "{self.name}"'
|
|
486
487
|
return self.type
|
|
@@ -526,7 +527,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
526
527
|
return data
|
|
527
528
|
|
|
528
529
|
def str(self, indent: int = 0) -> StrType:
|
|
529
|
-
"""Build a detailed string representation of this
|
|
530
|
+
"""Build a detailed string representation of this Adapter."""
|
|
530
531
|
margin = " " * indent
|
|
531
532
|
output = ""
|
|
532
533
|
for modelname in self.top_level:
|
|
@@ -557,7 +558,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
557
558
|
# Synchronization between DiffSync instances
|
|
558
559
|
# ------------------------------------------------------------------------------
|
|
559
560
|
|
|
560
|
-
def sync_from( # pylint: disable=too-many-arguments
|
|
561
|
+
def sync_from( # pylint: disable=too-many-arguments, too-many-positional-arguments
|
|
561
562
|
self,
|
|
562
563
|
source: "Adapter",
|
|
563
564
|
diff_class: Type[Diff] = Diff,
|
|
@@ -601,7 +602,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
601
602
|
|
|
602
603
|
return diff
|
|
603
604
|
|
|
604
|
-
def sync_to( # pylint: disable=too-many-arguments
|
|
605
|
+
def sync_to( # pylint: disable=too-many-arguments, too-many-positional-arguments
|
|
605
606
|
self,
|
|
606
607
|
target: "Adapter",
|
|
607
608
|
diff_class: Type[Diff] = Diff,
|
|
@@ -835,7 +836,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
835
836
|
def get_or_instantiate(
|
|
836
837
|
self, model: Type[DiffSyncModel], ids: Dict, attrs: Optional[Dict] = None
|
|
837
838
|
) -> Tuple[DiffSyncModel, bool]:
|
|
838
|
-
"""Attempt to get the object with provided identifiers or instantiate it with provided identifiers and attrs.
|
|
839
|
+
"""Attempt to get the object with provided identifiers or instantiate and add it with provided identifiers and attrs.
|
|
839
840
|
|
|
840
841
|
Args:
|
|
841
842
|
model: The DiffSyncModel to get or create.
|
|
@@ -848,7 +849,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
848
849
|
return self.store.get_or_instantiate(model=model, ids=ids, attrs=attrs)
|
|
849
850
|
|
|
850
851
|
def get_or_add_model_instance(self, obj: DiffSyncModel) -> Tuple[DiffSyncModel, bool]:
|
|
851
|
-
"""Attempt to get the object with provided obj identifiers or
|
|
852
|
+
"""Attempt to get the object with provided obj identifiers or add obj.
|
|
852
853
|
|
|
853
854
|
Args:
|
|
854
855
|
obj: An obj of the DiffSyncModel to get or add.
|
|
@@ -894,15 +895,10 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
894
895
|
return self.store.count(model=model)
|
|
895
896
|
|
|
896
897
|
|
|
897
|
-
|
|
898
|
+
@deprecated("'diffsync.DiffSync' is deprecated and will be removed with 2.1, use 'diffsync.Adapter' instead.")
|
|
899
|
+
class DiffSync(Adapter):
|
|
898
900
|
"""For backwards-compatibility, keep around the old name."""
|
|
899
901
|
|
|
900
|
-
warnings.warn(
|
|
901
|
-
"'diffsync.DiffSync' is deprecated and will be removed with 2.1, use 'diffsync.Adapter' instead.",
|
|
902
|
-
DeprecationWarning,
|
|
903
|
-
)
|
|
904
|
-
return Adapter(*args, **kwargs)
|
|
905
|
-
|
|
906
902
|
|
|
907
903
|
# DiffSyncModel references Adapter and Adapter references DiffSyncModel. Break the typing loop:
|
|
908
904
|
DiffSyncModel.model_rebuild()
|
|
@@ -16,11 +16,11 @@ limitations under the License.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
from functools import total_ordering
|
|
19
|
-
from typing import Any,
|
|
19
|
+
from typing import Any, Dict, Iterable, Iterator, List, Optional, Type
|
|
20
20
|
|
|
21
|
-
from .exceptions import ObjectAlreadyExists
|
|
22
|
-
from .utils import intersection, OrderedDefaultDict
|
|
23
21
|
from .enum import DiffSyncActions
|
|
22
|
+
from .exceptions import ObjectAlreadyExists
|
|
23
|
+
from .utils import OrderedDefaultDict, intersection
|
|
24
24
|
|
|
25
25
|
# This workaround is used because we are defining a method called `str` in our class definition, which therefore renders
|
|
26
26
|
# the builtin `str` type unusable.
|
|
@@ -105,8 +105,7 @@ class Diff:
|
|
|
105
105
|
|
|
106
106
|
Since children is already an OrderedDefaultDict, this method is not doing anything special.
|
|
107
107
|
"""
|
|
108
|
-
|
|
109
|
-
yield child
|
|
108
|
+
yield from children.values()
|
|
110
109
|
|
|
111
110
|
def summary(self) -> Dict[StrType, int]:
|
|
112
111
|
"""Build a dict summary of this Diff and its child DiffElements."""
|
|
@@ -161,7 +160,7 @@ class Diff:
|
|
|
161
160
|
class DiffElement: # pylint: disable=too-many-instance-attributes
|
|
162
161
|
"""DiffElement object, designed to represent a single item/object that may or may not have any diffs."""
|
|
163
162
|
|
|
164
|
-
def __init__(
|
|
163
|
+
def __init__( # pylint: disable=too-many-positional-arguments
|
|
165
164
|
self,
|
|
166
165
|
obj_type: StrType,
|
|
167
166
|
name: StrType,
|
|
@@ -14,14 +14,16 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
|
-
|
|
18
|
-
from
|
|
17
|
+
|
|
18
|
+
from collections.abc import Iterable as ABCIterable
|
|
19
|
+
from collections.abc import Mapping as ABCMapping
|
|
20
|
+
from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Optional, Tuple, Type
|
|
19
21
|
|
|
20
22
|
import structlog # type: ignore
|
|
21
23
|
|
|
22
24
|
from .diff import Diff, DiffElement
|
|
23
|
-
from .enum import
|
|
24
|
-
from .exceptions import
|
|
25
|
+
from .enum import DiffSyncActions, DiffSyncFlags, DiffSyncModelFlags, DiffSyncStatus
|
|
26
|
+
from .exceptions import ObjectCrudException, ObjectNotCreated, ObjectNotDeleted, ObjectNotFound, ObjectNotUpdated
|
|
25
27
|
from .utils import intersection, symmetric_difference
|
|
26
28
|
|
|
27
29
|
if TYPE_CHECKING: # pragma: no cover
|
|
@@ -35,7 +37,7 @@ class DiffSyncDiffer: # pylint: disable=too-many-instance-attributes
|
|
|
35
37
|
Independent from Diff and DiffElement as those classes are purely data objects, while this stores some state.
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
|
-
def __init__( # pylint: disable=too-many-arguments
|
|
40
|
+
def __init__( # pylint: disable=too-many-arguments, too-many-positional-arguments
|
|
39
41
|
self,
|
|
40
42
|
src_diffsync: "Adapter",
|
|
41
43
|
dst_diffsync: "Adapter",
|
|
@@ -114,9 +116,9 @@ class DiffSyncDiffer: # pylint: disable=too-many-instance-attributes
|
|
|
114
116
|
|
|
115
117
|
combined_dict = {}
|
|
116
118
|
for uid in dict_src:
|
|
117
|
-
combined_dict[uid] = (dict_src.get(uid), dict_dst.get(uid))
|
|
119
|
+
combined_dict[uid] = (dict_src.get(uid), dict_dst.get(uid)) # type: ignore
|
|
118
120
|
for uid in dict_dst:
|
|
119
|
-
combined_dict[uid] = (dict_src.get(uid), dict_dst.get(uid))
|
|
121
|
+
combined_dict[uid] = (dict_src.get(uid), dict_dst.get(uid)) # type: ignore
|
|
120
122
|
else:
|
|
121
123
|
# In the future we might support set, etc...
|
|
122
124
|
raise TypeError(f"Type combination {type(src)}/{type(dst)} is not supported... for now")
|
|
@@ -137,7 +139,7 @@ class DiffSyncDiffer: # pylint: disable=too-many-instance-attributes
|
|
|
137
139
|
|
|
138
140
|
@staticmethod
|
|
139
141
|
def validate_objects_for_diff(
|
|
140
|
-
object_pairs: Iterable[Tuple[Optional["DiffSyncModel"], Optional["DiffSyncModel"]]]
|
|
142
|
+
object_pairs: Iterable[Tuple[Optional["DiffSyncModel"], Optional["DiffSyncModel"]]],
|
|
141
143
|
) -> None:
|
|
142
144
|
"""Check whether all DiffSyncModels in the given dictionary are valid for comparison to one another.
|
|
143
145
|
|
|
@@ -285,7 +287,7 @@ class DiffSyncSyncer: # pylint: disable=too-many-instance-attributes
|
|
|
285
287
|
Independent from DiffSync and DiffSyncModel as those classes are purely data objects, while this stores some state.
|
|
286
288
|
"""
|
|
287
289
|
|
|
288
|
-
def __init__( # pylint: disable=too-many-arguments
|
|
290
|
+
def __init__( # pylint: disable=too-many-arguments, too-many-positional-arguments
|
|
289
291
|
self,
|
|
290
292
|
diff: Diff,
|
|
291
293
|
src_diffsync: "Adapter",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""RedisStore module."""
|
|
2
|
+
|
|
2
3
|
import copy
|
|
3
4
|
import uuid
|
|
4
|
-
from pickle import
|
|
5
|
-
from typing import
|
|
5
|
+
from pickle import dumps, loads # nosec
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Type, Union
|
|
6
7
|
|
|
7
8
|
try:
|
|
8
9
|
from redis import Redis
|
|
@@ -11,7 +12,7 @@ except ImportError as ierr:
|
|
|
11
12
|
print("Redis is not installed. Have you installed diffsync with redis extra? `pip install diffsync[redis]`")
|
|
12
13
|
raise ierr
|
|
13
14
|
|
|
14
|
-
from diffsync.exceptions import ObjectNotFound, ObjectStoreException
|
|
15
|
+
from diffsync.exceptions import ObjectAlreadyExists, ObjectNotFound, ObjectStoreException
|
|
15
16
|
from diffsync.store import BaseStore
|
|
16
17
|
|
|
17
18
|
if TYPE_CHECKING:
|
|
@@ -23,7 +24,7 @@ REDIS_DIFFSYNC_ROOT_LABEL = "diffsync"
|
|
|
23
24
|
class RedisStore(BaseStore):
|
|
24
25
|
"""RedisStore class."""
|
|
25
26
|
|
|
26
|
-
def __init__(
|
|
27
|
+
def __init__( # pylint: disable=too-many-arguments
|
|
27
28
|
self,
|
|
28
29
|
*args: Any,
|
|
29
30
|
store_id: Optional[str] = None,
|
|
@@ -167,7 +168,7 @@ class RedisStore(BaseStore):
|
|
|
167
168
|
|
|
168
169
|
existing_obj_binary = self._store.get(object_key)
|
|
169
170
|
if existing_obj_binary:
|
|
170
|
-
existing_obj = loads(existing_obj_binary)
|
|
171
|
+
existing_obj = loads(existing_obj_binary) # nosec
|
|
171
172
|
existing_obj_dict = existing_obj.dict()
|
|
172
173
|
|
|
173
174
|
if existing_obj_dict != obj.dict():
|
|
@@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
|
+
|
|
17
18
|
from collections import OrderedDict
|
|
18
19
|
from typing import Iterator, List, Dict, Optional, TypeVar, Callable, Generic
|
|
19
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "diffsync"
|
|
3
|
-
version = "v2.
|
|
3
|
+
version = "v2.1.0"
|
|
4
4
|
description = "Library to easily sync/diff/update 2 different data sources"
|
|
5
5
|
authors = ["Network to Code, LLC <info@networktocode.com>"]
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -16,10 +16,10 @@ include = [
|
|
|
16
16
|
]
|
|
17
17
|
|
|
18
18
|
[tool.poetry.dependencies]
|
|
19
|
-
python = ">=3.
|
|
19
|
+
python = ">=3.9,<4.0"
|
|
20
20
|
pydantic = "^2.0.0"
|
|
21
|
-
structlog = ">= 20.1.0
|
|
22
|
-
packaging = ">= 21.3
|
|
21
|
+
structlog = ">= 20.1.0"
|
|
22
|
+
packaging = ">= 21.3"
|
|
23
23
|
colorama = {version = "^0.4.3", optional = true}
|
|
24
24
|
redis = {version = "^4.3", optional = true}
|
|
25
25
|
# typing.Self introduced in 3.11
|
|
@@ -30,7 +30,7 @@ redis = ["redis"]
|
|
|
30
30
|
|
|
31
31
|
[tool.poetry.group.dev.dependencies]
|
|
32
32
|
pytest = "*"
|
|
33
|
-
pyyaml = "
|
|
33
|
+
pyyaml = ">= 6.0.1"
|
|
34
34
|
black = "*"
|
|
35
35
|
pylint = "*"
|
|
36
36
|
pydocstyle = "*"
|
|
@@ -42,7 +42,7 @@ mypy = "*"
|
|
|
42
42
|
pytest-cov = "*"
|
|
43
43
|
pytest-structlog = "*"
|
|
44
44
|
coverage = {extras = ["toml"], version = "*"}
|
|
45
|
-
Sphinx = "
|
|
45
|
+
Sphinx = "^6.0.0"
|
|
46
46
|
m2r2 = "*"
|
|
47
47
|
sphinx-rtd-theme = "*"
|
|
48
48
|
toml = "*"
|
|
@@ -84,7 +84,6 @@ no-docstring-rgx="^(_|test_)"
|
|
|
84
84
|
# Pylint and Black disagree about how to format multi-line arrays; Black wins.
|
|
85
85
|
disable = """,
|
|
86
86
|
line-too-long,
|
|
87
|
-
bad-continuation,
|
|
88
87
|
"""
|
|
89
88
|
|
|
90
89
|
[tool.pylint.miscellaneous]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|