diffsync 2.0.1__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.1 → diffsync-2.1.0}/CHANGELOG.md +15 -1
- {diffsync-2.0.1 → diffsync-2.1.0}/PKG-INFO +5 -7
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/__init__.py +15 -14
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/diff.py +5 -6
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/exceptions.py +1 -0
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/helpers.py +11 -9
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/store/__init__.py +1 -0
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/store/redis.py +6 -5
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/utils.py +1 -0
- {diffsync-2.0.1 → diffsync-2.1.0}/pyproject.toml +4 -5
- {diffsync-2.0.1 → diffsync-2.1.0}/LICENSE +0 -0
- {diffsync-2.0.1 → diffsync-2.1.0}/README.md +0 -0
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/enum.py +0 -0
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/logging.py +0 -0
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/py.typed +0 -0
- {diffsync-2.0.1 → diffsync-2.1.0}/diffsync/store/local.py +0 -0
|
@@ -4,11 +4,25 @@ 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
|
+
|
|
7
21
|
## [2.0.1]
|
|
8
22
|
|
|
9
23
|
### Changed
|
|
10
24
|
|
|
11
|
-
- #276 - Removed upper version
|
|
25
|
+
- #276 - Removed upper version bound for `structlog` dependency
|
|
12
26
|
|
|
13
27
|
### Fixed
|
|
14
28
|
|
|
@@ -1,29 +1,27 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: diffsync
|
|
3
|
-
Version: 2.0
|
|
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
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
17
|
Provides-Extra: redis
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist: packaging (>=21.3,<24.0)
|
|
18
|
+
Requires-Dist: packaging (>=21.3)
|
|
22
19
|
Requires-Dist: pydantic (>=2.0.0,<3.0.0)
|
|
23
20
|
Requires-Dist: redis (>=4.3,<5.0) ; extra == "redis"
|
|
24
21
|
Requires-Dist: structlog (>=20.1.0)
|
|
25
22
|
Requires-Dist: typing-extensions (>=4.0.1) ; python_version < "3.11"
|
|
26
23
|
Project-URL: Documentation, https://diffsync.readthedocs.io
|
|
24
|
+
Project-URL: Homepage, https://diffsync.readthedocs.io
|
|
27
25
|
Project-URL: Repository, https://github.com/networktocode/diffsync
|
|
28
26
|
Description-Content-Type: text/markdown
|
|
29
27
|
|
|
@@ -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
|
-
from typing_extensions import deprecated
|
|
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)
|
|
@@ -431,7 +432,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
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]] = []
|
|
@@ -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,
|
|
@@ -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.0
|
|
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
21
|
structlog = ">= 20.1.0"
|
|
22
|
-
packaging = ">= 21.3
|
|
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 = "*"
|
|
@@ -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
|
|
File without changes
|