diffsync 2.1.0__tar.gz → 2.2.1__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.1.0 → diffsync-2.2.1}/LICENSE +4 -4
- {diffsync-2.1.0 → diffsync-2.2.1}/PKG-INFO +37 -19
- {diffsync-2.1.0 → diffsync-2.2.1}/README.md +33 -16
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/__init__.py +22 -4
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/exceptions.py +1 -1
- diffsync-2.2.1/diffsync/log.py +74 -0
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/store/__init__.py +3 -3
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/store/local.py +2 -3
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/store/redis.py +2 -2
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/utils.py +2 -2
- diffsync-2.2.1/pyproject.toml +235 -0
- diffsync-2.1.0/CHANGELOG.md +0 -212
- diffsync-2.1.0/pyproject.toml +0 -112
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/diff.py +0 -0
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/enum.py +0 -0
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/helpers.py +0 -0
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/logging.py +0 -0
- {diffsync-2.1.0 → diffsync-2.2.1}/diffsync/py.typed +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Apache Software License 2.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Network to Code, LLC
|
|
3
4
|
|
|
4
5
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
6
|
you may not use this file except in compliance with the License.
|
|
6
|
-
|
|
7
7
|
You may obtain a copy of the License at
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
10
|
|
|
11
11
|
Unless required by applicable law or agreed to in writing, software
|
|
12
12
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: diffsync
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: Library to easily sync/diff/update 2 different data sources
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: source-of-truth,synchronization
|
|
7
7
|
Author: Network to Code, LLC
|
|
8
8
|
Author-email: info@networktocode.com
|
|
9
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.10,<3.14
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
10
12
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
13
|
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
13
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -31,7 +32,7 @@ DiffSync is a utility library that can be used to compare and synchronize differ
|
|
|
31
32
|
|
|
32
33
|
For example, it can be used to compare a list of devices from 2 inventory systems and, if required, synchronize them in either direction.
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
## Primary Use Cases
|
|
35
36
|
|
|
36
37
|
DiffSync is at its most useful when you have multiple sources or sets of data to compare and/or synchronize, and especially if any of the following are true:
|
|
37
38
|
|
|
@@ -40,7 +41,7 @@ DiffSync is at its most useful when you have multiple sources or sets of data to
|
|
|
40
41
|
- If various types of data in your data set naturally form a tree-like or parent-child relationship with other data.
|
|
41
42
|
- If the different data sets have some attributes in common and other attributes that are exclusive to one or the other.
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
## Overview of DiffSync
|
|
44
45
|
|
|
45
46
|
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.
|
|
46
47
|
|
|
@@ -55,7 +56,7 @@ You can also ask DiffSync to “sync” one data set onto the other, and it will
|
|
|
55
56
|
|
|
56
57
|

|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
## Simple Example
|
|
59
60
|
|
|
60
61
|
```python
|
|
61
62
|
A = DiffSyncSystemA()
|
|
@@ -77,34 +78,51 @@ A.sync_to(B)
|
|
|
77
78
|
|
|
78
79
|
> You may wish to peruse the `diffsync` [GitHub topic](https://github.com/topics/diffsync) for examples of projects using this library.
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
## Documentation
|
|
81
82
|
|
|
82
|
-
|
|
83
|
+
Full documentation for this library can be found over on the [Diffsync Docs](https://diffsync.readthedocs.io/) website:
|
|
83
84
|
|
|
84
|
-
|
|
85
|
+
- [User Guide](https://diffsync.readthedocs.io/user/app_overview/) - Overview, Using the Library, Getting Started.
|
|
86
|
+
- [Administrator Guide](https://diffsync.readthedocs.io/admin/install/) - How to Install, Configure, Upgrade, or Uninstall the Library.
|
|
87
|
+
- [Developer Guide](https://diffsync.readthedocs.io/dev/contributing/) - Extending the Library, Code Reference, Contribution Guide.
|
|
88
|
+
- [Release Notes / Changelog](https://diffsync.readthedocs.io/admin/release_notes/).
|
|
89
|
+
- [Frequently Asked Questions](https://diffsync.readthedocs.io/user/faq/).
|
|
85
90
|
|
|
86
|
-
|
|
91
|
+
## Installation
|
|
87
92
|
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
### Option 1: Install from PyPI
|
|
94
|
+
|
|
95
|
+
```shell
|
|
96
|
+
pip install diffsync
|
|
90
97
|
```
|
|
91
98
|
|
|
92
99
|
### Option 2: Install from a GitHub branch, such as main as shown below.
|
|
100
|
+
|
|
101
|
+
```shell
|
|
102
|
+
pip install git+https://github.com/networktocode/diffsync.git@main
|
|
93
103
|
```
|
|
94
|
-
$ pip install git+https://github.com/networktocode/diffsync.git@main
|
|
95
|
-
```
|
|
96
104
|
|
|
97
|
-
|
|
105
|
+
## Contributing
|
|
106
|
+
|
|
98
107
|
Pull requests are welcomed and automatically built and tested against multiple versions of Python through GitHub Actions.
|
|
99
108
|
|
|
100
|
-
The project is following Network to Code software development guidelines and
|
|
109
|
+
The project is following Network to Code software development guidelines and is leveraging the following:
|
|
101
110
|
|
|
102
|
-
-
|
|
111
|
+
- Ruff, mypy for Python linting, formatting and type hint checking.
|
|
103
112
|
- pytest, coverage, and unittest for unit tests.
|
|
104
113
|
|
|
105
114
|
You can ensure your contribution adheres to these checks by running `invoke tests` from the CLI.
|
|
106
115
|
The command `invoke build` builds a docker container with all the necessary dependencies (including the redis backend) locally to facilitate the execution of these tests.
|
|
107
116
|
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
## Contributing to the Documentation
|
|
118
|
+
|
|
119
|
+
You can find all the Markdown source for the App documentation under the [`docs`](https://github.com/networktocode/diffsync/tree/develop/docs) folder in this repository. For simple edits, a Markdown capable editor is sufficient: clone the repository and edit away.
|
|
120
|
+
|
|
121
|
+
If you need to view the fully-generated documentation site, you can build it with [MkDocs](https://www.mkdocs.org/). A container hosting the documentation can be started using the `invoke` commands (details in the [Development Environment Guide](https://diffsync/dev/dev_environment/#docker-development-environment)) on [http://localhost:8001](http://localhost:8001). Using this container, as your changes to the documentation are saved, they will be automatically rebuilt and any pages currently being viewed will be reloaded in your browser.
|
|
122
|
+
|
|
123
|
+
Any PRs with fixes or improvements are very welcome!
|
|
124
|
+
|
|
125
|
+
## Questions
|
|
126
|
+
|
|
127
|
+
For any questions or comments, please check the [FAQ](https://diffsync.readthedocs.io/en/latest/user/faq/) first. Feel free to also swing by the [Network to Code Slack](https://networktocode.slack.com/) (channel `#networktocode`), sign up [here](http://slack.networktocode.com/) if you don't have an account.
|
|
110
128
|
|
|
@@ -4,7 +4,7 @@ DiffSync is a utility library that can be used to compare and synchronize differ
|
|
|
4
4
|
|
|
5
5
|
For example, it can be used to compare a list of devices from 2 inventory systems and, if required, synchronize them in either direction.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Primary Use Cases
|
|
8
8
|
|
|
9
9
|
DiffSync is at its most useful when you have multiple sources or sets of data to compare and/or synchronize, and especially if any of the following are true:
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@ DiffSync is at its most useful when you have multiple sources or sets of data to
|
|
|
13
13
|
- If various types of data in your data set naturally form a tree-like or parent-child relationship with other data.
|
|
14
14
|
- If the different data sets have some attributes in common and other attributes that are exclusive to one or the other.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
## Overview of DiffSync
|
|
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
|
|
|
@@ -28,7 +28,7 @@ You can also ask DiffSync to “sync” one data set onto the other, and it will
|
|
|
28
28
|
|
|
29
29
|

|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
## Simple Example
|
|
32
32
|
|
|
33
33
|
```python
|
|
34
34
|
A = DiffSyncSystemA()
|
|
@@ -50,33 +50,50 @@ A.sync_to(B)
|
|
|
50
50
|
|
|
51
51
|
> You may wish to peruse the `diffsync` [GitHub topic](https://github.com/topics/diffsync) for examples of projects using this library.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
## Documentation
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
Full documentation for this library can be found over on the [Diffsync Docs](https://diffsync.readthedocs.io/) website:
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
- [User Guide](https://diffsync.readthedocs.io/user/app_overview/) - Overview, Using the Library, Getting Started.
|
|
58
|
+
- [Administrator Guide](https://diffsync.readthedocs.io/admin/install/) - How to Install, Configure, Upgrade, or Uninstall the Library.
|
|
59
|
+
- [Developer Guide](https://diffsync.readthedocs.io/dev/contributing/) - Extending the Library, Code Reference, Contribution Guide.
|
|
60
|
+
- [Release Notes / Changelog](https://diffsync.readthedocs.io/admin/release_notes/).
|
|
61
|
+
- [Frequently Asked Questions](https://diffsync.readthedocs.io/user/faq/).
|
|
58
62
|
|
|
59
|
-
|
|
63
|
+
## Installation
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
|
|
65
|
+
### Option 1: Install from PyPI
|
|
66
|
+
|
|
67
|
+
```shell
|
|
68
|
+
pip install diffsync
|
|
63
69
|
```
|
|
64
70
|
|
|
65
71
|
### Option 2: Install from a GitHub branch, such as main as shown below.
|
|
72
|
+
|
|
73
|
+
```shell
|
|
74
|
+
pip install git+https://github.com/networktocode/diffsync.git@main
|
|
66
75
|
```
|
|
67
|
-
$ pip install git+https://github.com/networktocode/diffsync.git@main
|
|
68
|
-
```
|
|
69
76
|
|
|
70
|
-
|
|
77
|
+
## Contributing
|
|
78
|
+
|
|
71
79
|
Pull requests are welcomed and automatically built and tested against multiple versions of Python through GitHub Actions.
|
|
72
80
|
|
|
73
|
-
The project is following Network to Code software development guidelines and
|
|
81
|
+
The project is following Network to Code software development guidelines and is leveraging the following:
|
|
74
82
|
|
|
75
|
-
-
|
|
83
|
+
- Ruff, mypy for Python linting, formatting and type hint checking.
|
|
76
84
|
- pytest, coverage, and unittest for unit tests.
|
|
77
85
|
|
|
78
86
|
You can ensure your contribution adheres to these checks by running `invoke tests` from the CLI.
|
|
79
87
|
The command `invoke build` builds a docker container with all the necessary dependencies (including the redis backend) locally to facilitate the execution of these tests.
|
|
80
88
|
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
## Contributing to the Documentation
|
|
90
|
+
|
|
91
|
+
You can find all the Markdown source for the App documentation under the [`docs`](https://github.com/networktocode/diffsync/tree/develop/docs) folder in this repository. For simple edits, a Markdown capable editor is sufficient: clone the repository and edit away.
|
|
92
|
+
|
|
93
|
+
If you need to view the fully-generated documentation site, you can build it with [MkDocs](https://www.mkdocs.org/). A container hosting the documentation can be started using the `invoke` commands (details in the [Development Environment Guide](https://diffsync/dev/dev_environment/#docker-development-environment)) on [http://localhost:8001](http://localhost:8001). Using this container, as your changes to the documentation are saved, they will be automatically rebuilt and any pages currently being viewed will be reloaded in your browser.
|
|
94
|
+
|
|
95
|
+
Any PRs with fixes or improvements are very welcome!
|
|
96
|
+
|
|
97
|
+
## Questions
|
|
98
|
+
|
|
99
|
+
For any questions or comments, please check the [FAQ](https://diffsync.readthedocs.io/en/latest/user/faq/) first. Feel free to also swing by the [Network to Code Slack](https://networktocode.slack.com/) (channel `#networktocode`), sign up [here](http://slack.networktocode.com/) if you don't have an account.
|
|
@@ -16,6 +16,7 @@ limitations under the License.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
import sys
|
|
19
|
+
from copy import deepcopy
|
|
19
20
|
from inspect import isclass
|
|
20
21
|
from typing import (
|
|
21
22
|
Any,
|
|
@@ -60,7 +61,7 @@ StrType = str
|
|
|
60
61
|
class DiffSyncModel(BaseModel):
|
|
61
62
|
"""Base class for all DiffSync object models.
|
|
62
63
|
|
|
63
|
-
Note that read-only APIs of this class are implemented as `get_*()`
|
|
64
|
+
Note that read-only APIs of this class are implemented as `get_*()` methods rather than as properties;
|
|
64
65
|
this is intentional as specific model classes may want to use these names (`type`, `keys`, `attrs`, etc.)
|
|
65
66
|
as model attributes and we want to avoid any ambiguity or collisions.
|
|
66
67
|
|
|
@@ -158,9 +159,11 @@ class DiffSyncModel(BaseModel):
|
|
|
158
159
|
raise AttributeError(f"Fields {attr_child_overlap} are included in both _attributes and _children.")
|
|
159
160
|
|
|
160
161
|
def __repr__(self) -> str:
|
|
162
|
+
"""Return a string representation of this DiffSyncModel."""
|
|
161
163
|
return f'{self.get_type()} "{self.get_unique_id()}"'
|
|
162
164
|
|
|
163
165
|
def __str__(self) -> str:
|
|
166
|
+
"""Return a string representation of this DiffSyncModel."""
|
|
164
167
|
return self.get_unique_id()
|
|
165
168
|
|
|
166
169
|
def dict(self, **kwargs: Any) -> Dict:
|
|
@@ -305,7 +308,7 @@ class DiffSyncModel(BaseModel):
|
|
|
305
308
|
|
|
306
309
|
@classmethod
|
|
307
310
|
def get_type(cls) -> StrType:
|
|
308
|
-
"""Return the type AKA modelname of the object or the class
|
|
311
|
+
"""Return the type AKA modelname of the object or the class.
|
|
309
312
|
|
|
310
313
|
Returns:
|
|
311
314
|
str: modelname of the class, used in to store all objects
|
|
@@ -447,7 +450,6 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
447
450
|
|
|
448
451
|
Subclasses should be careful to call super().__init__() if they override this method.
|
|
449
452
|
"""
|
|
450
|
-
|
|
451
453
|
if isinstance(internal_storage_engine, BaseStore):
|
|
452
454
|
self.store = internal_storage_engine
|
|
453
455
|
self.store.adapter = self
|
|
@@ -480,6 +482,19 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
480
482
|
if not isclass(value) or not issubclass(value, DiffSyncModel):
|
|
481
483
|
raise AttributeError(f'top_level references attribute "{name}" but it is not a DiffSyncModel subclass!')
|
|
482
484
|
|
|
485
|
+
def __new__(cls, **kwargs): # type: ignore[no-untyped-def]
|
|
486
|
+
"""Document keyword arguments that were used to initialize Adapter."""
|
|
487
|
+
meta_kwargs = {}
|
|
488
|
+
for key, value in kwargs.items():
|
|
489
|
+
try:
|
|
490
|
+
meta_kwargs[key] = deepcopy(value)
|
|
491
|
+
except (TypeError, AttributeError):
|
|
492
|
+
# Some objects (e.g. Kafka Consumer, DB connections) cannot be deep copied
|
|
493
|
+
meta_kwargs[key] = value
|
|
494
|
+
instance = super().__new__(cls)
|
|
495
|
+
instance._meta_kwargs = meta_kwargs
|
|
496
|
+
return instance
|
|
497
|
+
|
|
483
498
|
def __str__(self) -> StrType:
|
|
484
499
|
"""String representation of an Adapter."""
|
|
485
500
|
if self.type != self.name:
|
|
@@ -487,6 +502,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
487
502
|
return self.type
|
|
488
503
|
|
|
489
504
|
def __repr__(self) -> StrType:
|
|
505
|
+
"""Representation of an Adapter."""
|
|
490
506
|
return f"<{str(self)}>"
|
|
491
507
|
|
|
492
508
|
def __len__(self) -> int:
|
|
@@ -575,6 +591,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
575
591
|
callback: Function with parameters (stage, current, total), to be called at intervals as the calculation of
|
|
576
592
|
the diff and subsequent sync proceed.
|
|
577
593
|
diff: An existing diff to be used rather than generating a completely new diff.
|
|
594
|
+
|
|
578
595
|
Returns:
|
|
579
596
|
Diff between origin object and source
|
|
580
597
|
Raises:
|
|
@@ -619,6 +636,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
619
636
|
callback: Function with parameters (stage, current, total), to be called at intervals as the calculation of
|
|
620
637
|
the diff and subsequent sync proceed.
|
|
621
638
|
diff: An existing diff that will be used when determining what needs to be synced.
|
|
639
|
+
|
|
622
640
|
Returns:
|
|
623
641
|
Diff between origin object and target
|
|
624
642
|
Raises:
|
|
@@ -729,7 +747,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
729
747
|
obj: Union[StrType, DiffSyncModel, Type[DiffSyncModel]],
|
|
730
748
|
identifier: Union[StrType, Dict],
|
|
731
749
|
) -> Optional[DiffSyncModel]:
|
|
732
|
-
"""Get one object from the data store based on its unique id or get a None
|
|
750
|
+
"""Get one object from the data store based on its unique id or get a None.
|
|
733
751
|
|
|
734
752
|
Args:
|
|
735
753
|
obj: DiffSyncModel class or instance, or modelname string, that defines the type of the object to retrieve
|
|
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
|
|
15
15
|
limitations under the License.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from typing import TYPE_CHECKING,
|
|
18
|
+
from typing import TYPE_CHECKING, Any, Union
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
21
|
from diffsync import DiffSyncModel
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Logging utilities for diffsync.
|
|
3
|
+
|
|
4
|
+
This module contains helpers and wrappers for making logging more consistent across applications.
|
|
5
|
+
|
|
6
|
+
How to use me:
|
|
7
|
+
|
|
8
|
+
>>> from diffsync.log import initialize_logging
|
|
9
|
+
>>> log = initialize_logging(level="debug")
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import logging.config
|
|
13
|
+
|
|
14
|
+
APP = "diffsync"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def initialize_logging(config=None, level="INFO", filename=None):
|
|
18
|
+
"""Initialize logging using sensible defaults.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
config (dict): User provided configuration dictionary.
|
|
22
|
+
level (str): The level of logging for STDOUT logging.
|
|
23
|
+
filename (str): Where to output debug logging to file.
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
if not config:
|
|
27
|
+
config = {
|
|
28
|
+
"version": 1,
|
|
29
|
+
"disable_existing_loggers": False,
|
|
30
|
+
"formatters": {
|
|
31
|
+
"standard": {
|
|
32
|
+
"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
|
33
|
+
"datefmt": "%Y-%m-%dT%H:%M:%S%z",
|
|
34
|
+
},
|
|
35
|
+
"debug": {
|
|
36
|
+
"format": "%(asctime)s [%(levelname)s] [%(module)s] [%(funcName)s] %(name)s: %(message)s",
|
|
37
|
+
"datefmt": "%Y-%m-%dT%H:%M:%S%z",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
"handlers": {
|
|
41
|
+
"standard": {
|
|
42
|
+
"class": "logging.StreamHandler",
|
|
43
|
+
"formatter": "standard",
|
|
44
|
+
"level": level.upper(),
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
"loggers": {
|
|
48
|
+
"": {
|
|
49
|
+
"handlers": ["standard"],
|
|
50
|
+
"level": "DEBUG",
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# If a filename is passed in, let's add a FileHandler
|
|
56
|
+
if filename:
|
|
57
|
+
config["handlers"].update(
|
|
58
|
+
{
|
|
59
|
+
"file_output": {
|
|
60
|
+
"class": "logging.FileHandler",
|
|
61
|
+
"formatter": "debug",
|
|
62
|
+
"level": "DEBUG",
|
|
63
|
+
"filename": filename,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
config["loggers"][""]["handlers"].append("file_output")
|
|
68
|
+
|
|
69
|
+
# Configure the logging
|
|
70
|
+
logging.config.dictConfig(config)
|
|
71
|
+
|
|
72
|
+
# Initialize root logger and advise logging has been initialized
|
|
73
|
+
log = logging.getLogger(APP)
|
|
74
|
+
log.debug("Logging initialized.")
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""BaseStore module."""
|
|
2
2
|
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, Type, Union
|
|
4
|
+
|
|
4
5
|
import structlog # type: ignore
|
|
5
6
|
|
|
6
7
|
from diffsync.exceptions import ObjectNotFound
|
|
7
8
|
|
|
8
9
|
if TYPE_CHECKING:
|
|
9
|
-
from diffsync import DiffSyncModel
|
|
10
|
-
from diffsync import Adapter
|
|
10
|
+
from diffsync import Adapter, DiffSyncModel
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class BaseStore:
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"""LocalStore module."""
|
|
2
2
|
|
|
3
3
|
from collections import defaultdict
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Set, Type, Union
|
|
5
5
|
|
|
6
|
-
from diffsync.exceptions import
|
|
6
|
+
from diffsync.exceptions import ObjectAlreadyExists, ObjectNotFound
|
|
7
7
|
from diffsync.store import BaseStore
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
if TYPE_CHECKING:
|
|
11
10
|
from diffsync import DiffSyncModel
|
|
12
11
|
|
|
@@ -65,7 +65,7 @@ class RedisStore(BaseStore):
|
|
|
65
65
|
"""Get the object from Redis key."""
|
|
66
66
|
pickled_object = self._store.get(key)
|
|
67
67
|
if pickled_object:
|
|
68
|
-
obj_result = loads(pickled_object) #
|
|
68
|
+
obj_result = loads(pickled_object) # noqa: S301
|
|
69
69
|
obj_result.adapter = self.adapter
|
|
70
70
|
return obj_result
|
|
71
71
|
raise ObjectNotFound(f"{key} not present in Cache")
|
|
@@ -168,7 +168,7 @@ class RedisStore(BaseStore):
|
|
|
168
168
|
|
|
169
169
|
existing_obj_binary = self._store.get(object_key)
|
|
170
170
|
if existing_obj_binary:
|
|
171
|
-
existing_obj = loads(existing_obj_binary) #
|
|
171
|
+
existing_obj = loads(existing_obj_binary) # noqa: S301
|
|
172
172
|
existing_obj_dict = existing_obj.dict()
|
|
173
173
|
|
|
174
174
|
if existing_obj_dict != obj.dict():
|
|
@@ -16,7 +16,7 @@ limitations under the License.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
from collections import OrderedDict
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Callable, Dict, Generic, Iterator, List, Optional, TypeVar
|
|
20
20
|
|
|
21
21
|
SPACE = " "
|
|
22
22
|
BRANCH = "│ "
|
|
@@ -44,7 +44,7 @@ def symmetric_difference(lst1: List[T], lst2: List[T]) -> List[T]:
|
|
|
44
44
|
class OrderedDefaultDict(OrderedDict, Generic[K, V]):
|
|
45
45
|
"""A combination of collections.OrderedDict and collections.DefaultDict behavior."""
|
|
46
46
|
|
|
47
|
-
def __init__(self, dict_type: Callable[[], V]) -> None:
|
|
47
|
+
def __init__(self, dict_type: Callable[[], V] = dict) -> None: # type: ignore[assignment]
|
|
48
48
|
"""Create a new OrderedDefaultDict."""
|
|
49
49
|
self.factory = dict_type
|
|
50
50
|
super().__init__(self)
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "diffsync"
|
|
3
|
+
version = "2.2.1"
|
|
4
|
+
description = "Library to easily sync/diff/update 2 different data sources"
|
|
5
|
+
authors = ["Network to Code, LLC <info@networktocode.com>"]
|
|
6
|
+
license = "Apache-2.0"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
homepage = "https://diffsync.readthedocs.io"
|
|
9
|
+
repository = "https://github.com/networktocode/diffsync"
|
|
10
|
+
documentation = "https://diffsync.readthedocs.io"
|
|
11
|
+
keywords = ["source-of-truth", "synchronization"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"Development Status :: 5 - Production/Stable",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
]
|
|
21
|
+
include = [
|
|
22
|
+
"CHANGELOG.md",
|
|
23
|
+
"LICENSE",
|
|
24
|
+
"README.md",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[tool.poetry.dependencies]
|
|
28
|
+
python = ">=3.10,<3.14"
|
|
29
|
+
pydantic = "^2.0.0"
|
|
30
|
+
structlog = ">= 20.1.0"
|
|
31
|
+
packaging = ">= 21.3"
|
|
32
|
+
colorama = {version = "^0.4.3", optional = true}
|
|
33
|
+
redis = {version = "^4.3", optional = true}
|
|
34
|
+
# typing.Self introduced in 3.11
|
|
35
|
+
typing-extensions = { version = ">=4.0.1", python = "<3.11" }
|
|
36
|
+
|
|
37
|
+
[tool.poetry.extras]
|
|
38
|
+
redis = ["redis"]
|
|
39
|
+
|
|
40
|
+
[tool.poetry.group.dev.dependencies]
|
|
41
|
+
coverage = "*"
|
|
42
|
+
pytest = "*"
|
|
43
|
+
mock = "*"
|
|
44
|
+
pyyaml = ">= 6.0.1"
|
|
45
|
+
pylint = "*"
|
|
46
|
+
yamllint = "^1.35.1"
|
|
47
|
+
invoke = "^2.2.0"
|
|
48
|
+
toml = "^0.10.2"
|
|
49
|
+
attrs = "^23.2.0"
|
|
50
|
+
towncrier = ">=23.6.0,<=24.8.0"
|
|
51
|
+
ruff = "*"
|
|
52
|
+
Markdown = "*"
|
|
53
|
+
|
|
54
|
+
[tool.poetry.group.docs.dependencies]
|
|
55
|
+
# Rendering docs to HTML
|
|
56
|
+
mkdocs = "1.6.1"
|
|
57
|
+
# Embedding YAML files into Markdown documents as tables
|
|
58
|
+
markdown-data-tables = "1.0.0"
|
|
59
|
+
# Render custom markdown for version added/changed/remove notes
|
|
60
|
+
markdown-version-annotations = "1.0.1"
|
|
61
|
+
# Automatically generate some files as part of mkdocs build
|
|
62
|
+
mkdocs-gen-files = "0.5.0"
|
|
63
|
+
# Image lightboxing in mkdocs
|
|
64
|
+
mkdocs-glightbox = "0.4.0"
|
|
65
|
+
# Use Jinja2 templating in docs - see settings.md
|
|
66
|
+
mkdocs-macros-plugin = "1.3.7"
|
|
67
|
+
# Material for mkdocs theme
|
|
68
|
+
mkdocs-material = "9.6.15"
|
|
69
|
+
# Handle docs redirections
|
|
70
|
+
mkdocs-redirects = "1.2.2"
|
|
71
|
+
# Automatically handle index pages for docs sections
|
|
72
|
+
mkdocs-section-index = "0.3.10"
|
|
73
|
+
# Automatic documentation from sources, for MkDocs
|
|
74
|
+
mkdocstrings = "0.27.0"
|
|
75
|
+
# Python-specific extension to mkdocstrings
|
|
76
|
+
mkdocstrings-python = "1.13.0"
|
|
77
|
+
griffe = "1.1.1"
|
|
78
|
+
mypy = "*"
|
|
79
|
+
pytest-cov = "*"
|
|
80
|
+
pytest-structlog = "*"
|
|
81
|
+
coverage = {extras = ["toml"], version = "*"}
|
|
82
|
+
Sphinx = "^6.0.0"
|
|
83
|
+
m2r2 = "*"
|
|
84
|
+
sphinx-rtd-theme = "*"
|
|
85
|
+
toml = "*"
|
|
86
|
+
types-toml = "*"
|
|
87
|
+
types-redis = "*"
|
|
88
|
+
pytest-redis = "^2.4.0"
|
|
89
|
+
types-requests = "^2.28.11.15"
|
|
90
|
+
types-python-slugify = "^8.0.0.1"
|
|
91
|
+
|
|
92
|
+
[tool.ruff]
|
|
93
|
+
line-length = 120
|
|
94
|
+
target-version = "py310"
|
|
95
|
+
|
|
96
|
+
[tool.ruff.lint]
|
|
97
|
+
select = [
|
|
98
|
+
"D", # pydocstyle
|
|
99
|
+
"F", "E", "W", # flake8
|
|
100
|
+
"S", # bandit
|
|
101
|
+
"I", # isort
|
|
102
|
+
]
|
|
103
|
+
ignore = [
|
|
104
|
+
# warning: `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible.
|
|
105
|
+
"D203", # 1 blank line required before class docstring
|
|
106
|
+
|
|
107
|
+
# D212 is enabled by default in google convention, and complains if we have a docstring like:
|
|
108
|
+
# """
|
|
109
|
+
# My docstring is on the line after the opening quotes instead of on the same line as them.
|
|
110
|
+
# """
|
|
111
|
+
# We've discussed and concluded that we consider this to be a valid style choice.
|
|
112
|
+
"D212", # Multi-line docstring summary should start at the first line
|
|
113
|
+
"D213", # Multi-line docstring summary should start at the second line
|
|
114
|
+
|
|
115
|
+
# Produces a lot of issues in the current codebase.
|
|
116
|
+
"D401", # First line of docstring should be in imperative mood
|
|
117
|
+
"D407", # Missing dashed underline after section
|
|
118
|
+
"D416", # Section name ends in colon
|
|
119
|
+
"E501", # Line too long
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
[tool.ruff.lint.pydocstyle]
|
|
123
|
+
convention = "google"
|
|
124
|
+
|
|
125
|
+
[tool.ruff.lint.per-file-ignores]
|
|
126
|
+
"tests/*" = [
|
|
127
|
+
"D",
|
|
128
|
+
"S"
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
[tool.mypy]
|
|
132
|
+
warn_unused_configs = true
|
|
133
|
+
disallow_untyped_defs = true
|
|
134
|
+
ignore_missing_imports = true
|
|
135
|
+
|
|
136
|
+
[tool.pylint.general]
|
|
137
|
+
extension-pkg-whitelist = [
|
|
138
|
+
"pydantic"
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
[tool.pylint.basic]
|
|
142
|
+
# No docstrings required for private methods (Pylint default), or for test_ functions, or for inner Meta classes.
|
|
143
|
+
no-docstring-rgx = "^(_|test_|Meta$)"
|
|
144
|
+
|
|
145
|
+
[tool.pylint.master]
|
|
146
|
+
ignore=[".venv", "tests"]
|
|
147
|
+
|
|
148
|
+
[tool.pylint.messages_control]
|
|
149
|
+
# Line length is enforced by Black, so pylint doesn't need to check it.
|
|
150
|
+
# Pylint and Black disagree about how to format multi-line arrays; Black wins.
|
|
151
|
+
disable = [
|
|
152
|
+
"line-too-long",
|
|
153
|
+
"duplicate-code",
|
|
154
|
+
"cyclic-import",
|
|
155
|
+
]
|
|
156
|
+
|
|
157
|
+
[tool.pylint.miscellaneous]
|
|
158
|
+
# Don't flag TODO as a failure, let us commit with things that still need to be done in the code
|
|
159
|
+
notes = """,
|
|
160
|
+
FIXME,
|
|
161
|
+
XXX,
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
[tool.pylint.similarities]
|
|
165
|
+
# There's a lot of duplicate code in the examples/backend_*.py files - don't complain about it for now
|
|
166
|
+
min-similarity-lines = 20
|
|
167
|
+
|
|
168
|
+
[tool.pytest.ini_options]
|
|
169
|
+
python_paths = "./"
|
|
170
|
+
testpaths = [
|
|
171
|
+
"tests/"
|
|
172
|
+
]
|
|
173
|
+
addopts = "-vv --doctest-modules -p no:warnings --ignore-glob='*mock*'"
|
|
174
|
+
|
|
175
|
+
[tool.towncrier]
|
|
176
|
+
package = "diffsync"
|
|
177
|
+
directory = "changes"
|
|
178
|
+
filename = "docs/admin/release_notes/version_X.Y.md"
|
|
179
|
+
template = "towncrier_template.j2"
|
|
180
|
+
start_string = "<!-- towncrier release notes start -->"
|
|
181
|
+
issue_format = "[#{issue}](https://github.com/networktocode/diffsync/issues/{issue})"
|
|
182
|
+
|
|
183
|
+
[[tool.towncrier.type]]
|
|
184
|
+
directory = "breaking"
|
|
185
|
+
name = "Breaking Changes"
|
|
186
|
+
showcontent = true
|
|
187
|
+
|
|
188
|
+
[[tool.towncrier.type]]
|
|
189
|
+
directory = "security"
|
|
190
|
+
name = "Security"
|
|
191
|
+
showcontent = true
|
|
192
|
+
|
|
193
|
+
[[tool.towncrier.type]]
|
|
194
|
+
directory = "added"
|
|
195
|
+
name = "Added"
|
|
196
|
+
showcontent = true
|
|
197
|
+
|
|
198
|
+
[[tool.towncrier.type]]
|
|
199
|
+
directory = "changed"
|
|
200
|
+
name = "Changed"
|
|
201
|
+
showcontent = true
|
|
202
|
+
|
|
203
|
+
[[tool.towncrier.type]]
|
|
204
|
+
directory = "deprecated"
|
|
205
|
+
name = "Deprecated"
|
|
206
|
+
showcontent = true
|
|
207
|
+
|
|
208
|
+
[[tool.towncrier.type]]
|
|
209
|
+
directory = "removed"
|
|
210
|
+
name = "Removed"
|
|
211
|
+
showcontent = true
|
|
212
|
+
|
|
213
|
+
[[tool.towncrier.type]]
|
|
214
|
+
directory = "fixed"
|
|
215
|
+
name = "Fixed"
|
|
216
|
+
showcontent = true
|
|
217
|
+
|
|
218
|
+
[[tool.towncrier.type]]
|
|
219
|
+
directory = "dependencies"
|
|
220
|
+
name = "Dependencies"
|
|
221
|
+
showcontent = true
|
|
222
|
+
|
|
223
|
+
[[tool.towncrier.type]]
|
|
224
|
+
directory = "documentation"
|
|
225
|
+
name = "Documentation"
|
|
226
|
+
showcontent = true
|
|
227
|
+
|
|
228
|
+
[[tool.towncrier.type]]
|
|
229
|
+
directory = "housekeeping"
|
|
230
|
+
name = "Housekeeping"
|
|
231
|
+
showcontent = true
|
|
232
|
+
|
|
233
|
+
[build-system]
|
|
234
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
235
|
+
build-backend = "poetry.core.masonry.api"
|
diffsync-2.1.0/CHANGELOG.md
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
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
|
-
|
|
36
|
-
## [2.0.0]
|
|
37
|
-
|
|
38
|
-
### Changed
|
|
39
|
-
|
|
40
|
-
- **BREAKING CHANGE** #236/240 - Upgrade to Pydantic v2.
|
|
41
|
-
|
|
42
|
-
## [1.10.0] - 2023-11-16
|
|
43
|
-
|
|
44
|
-
### Fixed
|
|
45
|
-
|
|
46
|
-
- #249 - Fixes natural deletion order flag
|
|
47
|
-
- #247 - Fixes underspecified typing_extensions dependency
|
|
48
|
-
|
|
49
|
-
### Changed
|
|
50
|
-
|
|
51
|
-
- #247 - Deprecates Python 3.7
|
|
52
|
-
|
|
53
|
-
## [1.9.0] - 2023-10-16
|
|
54
|
-
|
|
55
|
-
### Added
|
|
56
|
-
|
|
57
|
-
- #220 - Implement DiffSyncModelFlags.NATURAL_DELETION_ORDER.
|
|
58
|
-
|
|
59
|
-
### Changed
|
|
60
|
-
|
|
61
|
-
- #219 - Type hinting overhaul
|
|
62
|
-
|
|
63
|
-
## [1.8.0] - 2023-04-18
|
|
64
|
-
|
|
65
|
-
### Added
|
|
66
|
-
|
|
67
|
-
- #182 - Added `get_or_add_model_instance()` and `update_or_add_model_instance()` APIs.
|
|
68
|
-
- #189 - Added note in `README.md` about running `invoke tests`.
|
|
69
|
-
- #190 - Added note in `README.md` about running `invoke build`.
|
|
70
|
-
|
|
71
|
-
### Changed
|
|
72
|
-
|
|
73
|
-
- #77/#188 - `sync_from()` and `sync_to()` now return the `Diff` that was applied.
|
|
74
|
-
- #211 - Loosened `packaging` and `structlog` library dependency constraints for broader compatibility.
|
|
75
|
-
|
|
76
|
-
## [1.7.0] - 2022-11-03
|
|
77
|
-
|
|
78
|
-
### Changed
|
|
79
|
-
|
|
80
|
-
- #176 - Remove pytest-redislite in favor of pytest-redis.
|
|
81
|
-
- #174 - Update Dockerfile to install build-essential
|
|
82
|
-
|
|
83
|
-
### Added
|
|
84
|
-
|
|
85
|
-
- #174 - Add methods to load data from dictionary and enable tree traversal
|
|
86
|
-
- #174 - Add a `get_or_none` method to the DiffSync class
|
|
87
|
-
- #168 - Add 'skip' counter to diff.summary()
|
|
88
|
-
- #169/#170 - Add documentation about model processing order
|
|
89
|
-
- #121/#140 - Add and configure renovate
|
|
90
|
-
- #140 - Add renovate configuration validation to the CI
|
|
91
|
-
|
|
92
|
-
### Fixed
|
|
93
|
-
|
|
94
|
-
- #149 - Limit redundant CI concurrency
|
|
95
|
-
|
|
96
|
-
## [1.6.0] - 2022-07-09
|
|
97
|
-
|
|
98
|
-
### Changed
|
|
99
|
-
|
|
100
|
-
- #120 - Dropped support for Python 3.6, new minimum is Python 3.7
|
|
101
|
-
|
|
102
|
-
## [1.5.1] - 2022-06-30
|
|
103
|
-
|
|
104
|
-
### Added
|
|
105
|
-
|
|
106
|
-
- #111 - Added example 6, regarding IP prefixes.
|
|
107
|
-
|
|
108
|
-
### Changed
|
|
109
|
-
|
|
110
|
-
- #107 - Updated example 5 to use the Redis backend store.
|
|
111
|
-
|
|
112
|
-
### Fixed
|
|
113
|
-
|
|
114
|
-
- #115 - Fixed ReadTheDocs rendering pipeline
|
|
115
|
-
- #118 - Fixed a regression in `DiffSync.get(modelname, identifiers)` introduced in 1.5.0
|
|
116
|
-
|
|
117
|
-
## [1.5.0] - 2022-06-07
|
|
118
|
-
|
|
119
|
-
### Added
|
|
120
|
-
|
|
121
|
-
- #106 - Add a new, optional, backend store based in Redis
|
|
122
|
-
|
|
123
|
-
## [1.4.3] - 2022-03-03
|
|
124
|
-
|
|
125
|
-
### Fixed
|
|
126
|
-
|
|
127
|
-
- #101 - Revert changed introduced in #90 that affected `DiffElement.action`
|
|
128
|
-
|
|
129
|
-
**NOTE**: this change is a breaking change against DiffSync 1.4.0 through 1.4.2, but was necessary to restore backward compatibility with DiffSync 1.3.x and earlier. Apologies for any inconvenience this causes.
|
|
130
|
-
|
|
131
|
-
### Changed
|
|
132
|
-
|
|
133
|
-
- #103 - Update development dependencies
|
|
134
|
-
|
|
135
|
-
## [1.4.2] - 2022-02-28
|
|
136
|
-
|
|
137
|
-
**WARNING** - #90 inadvertently introduced a breaking API change in DiffSync 1.4.0 through 1.4.2 (#101); this change was reverted in #102 for DiffSync 1.4.3 and later. We recommend not using this release, and moving to 1.4.3 instead.
|
|
138
|
-
|
|
139
|
-
### Fixed
|
|
140
|
-
|
|
141
|
-
- #100 - Added explicit dependency on `packaging`.
|
|
142
|
-
|
|
143
|
-
## [1.4.1] - 2022-01-26
|
|
144
|
-
|
|
145
|
-
**WARNING** - #90 inadvertently introduced a breaking API change in DiffSync 1.4.0 through 1.4.2 (#101); this change was reverted in #102 for DiffSync 1.4.3 and later. We recommend not using this release, and moving to 1.4.3 instead.
|
|
146
|
-
|
|
147
|
-
### Fixed
|
|
148
|
-
|
|
149
|
-
- #95 - Removed optional dependencies on `sphinx`, `m2r2`, `sphinx-rtd-theme`, `toml`.
|
|
150
|
-
|
|
151
|
-
## [1.4.0] - 2022-01-24
|
|
152
|
-
|
|
153
|
-
**WARNING** - #90 inadvertently introduced a breaking API change in DiffSync 1.4.0 through 1.4.2 (#101); this change was reverted in #102 for DiffSync 1.4.3 and later. We recommend not using this release, and moving to 1.4.3 instead.
|
|
154
|
-
|
|
155
|
-
### Added
|
|
156
|
-
|
|
157
|
-
- #53 - Add a new example based on pynautobot and Nautobot REST API
|
|
158
|
-
- #59 - Add proper documentation published in Read the doc
|
|
159
|
-
- #68 - Cleanup Readme, add link to new documentation site
|
|
160
|
-
- #70 - Add `add_or_update()` method to DiffSync class that requires a DiffSyncModel to be passed in and will attempt to add or update an existing object
|
|
161
|
-
- #72 - Add core engine section in docs and rename example directories
|
|
162
|
-
- #75 - Add support for Structlog v21 in addition to v20.
|
|
163
|
-
- #80 - Add support for an existing Diff object to be passed to `sync_to()` & `sync_from()` to prevent another diff from being calculated.
|
|
164
|
-
- #81 - Add a new example based on PeeringDB
|
|
165
|
-
- #83 - Add support for Python 3.10
|
|
166
|
-
- #87 - Add new model flags : `SKIP_UNMATCHED_BOTH`, `SKIP_UNMATCHED_SRC` & `SKIP_UNMATCHED_DST` to match the behavior of the global flags
|
|
167
|
-
|
|
168
|
-
### Changed
|
|
169
|
-
|
|
170
|
-
- #62 - Update CI Token
|
|
171
|
-
- #69 - Replace Travis CI with Github Actions to run unit tests
|
|
172
|
-
- #82 - Update lock file with latest versions.
|
|
173
|
-
- #90 - Convert list of actions (`create`, `update`, `delete`) to proper Enum
|
|
174
|
-
|
|
175
|
-
### Fixed
|
|
176
|
-
|
|
177
|
-
- #51 - Update minimum Pydantic version due to security advisory GHSA-5jqp-qgf6-3pvh
|
|
178
|
-
- #63 - Fix type in Readme
|
|
179
|
-
|
|
180
|
-
## [1.3.0] - 2021-04-07
|
|
181
|
-
|
|
182
|
-
### Added
|
|
183
|
-
|
|
184
|
-
- #48 - added optional `callback` argument to `diff_from`/`diff_to`/`sync_from`/`sync_to` for use with progress reporting.
|
|
185
|
-
|
|
186
|
-
## [1.2.0] - 2020-12-08
|
|
187
|
-
|
|
188
|
-
### Added
|
|
189
|
-
|
|
190
|
-
- #45 - minimum Python version lowered from 3.7 to 3.6, also now tested against Python 3.9.
|
|
191
|
-
|
|
192
|
-
## [1.1.0] - 2020-12-01
|
|
193
|
-
|
|
194
|
-
### Added
|
|
195
|
-
|
|
196
|
-
- #37 - added `sync_complete` callback, triggered on `sync_from` completion with changes.
|
|
197
|
-
- #41 - added `summary` API for Diff and DiffElement objects.
|
|
198
|
-
- #44 - added `set_status()` and `get_status()` APIs so that DiffSyncModel implementations can provide details for create/update/delete logging
|
|
199
|
-
|
|
200
|
-
### Changed
|
|
201
|
-
|
|
202
|
-
- Now requires Pydantic 1.7.2 or later
|
|
203
|
-
- #34 - in diff dicts, changed keys `src`/`dst`/`_src`/`_dst` to `-` and `+`
|
|
204
|
-
- #43 - `DiffSync.get_by_uids()` now raises `ObjectNotFound` if any of the provided uids cannot be located; `DiffSync.get()` raises `ObjectNotFound` or `ValueError` on failure, instead of returning `None`.
|
|
205
|
-
|
|
206
|
-
### Fixed
|
|
207
|
-
|
|
208
|
-
- #44 - On CRUD failure, do not generate an extraneous "success" log message in addition to the "failed" message
|
|
209
|
-
|
|
210
|
-
## [1.0.0] - 2020-10-23
|
|
211
|
-
|
|
212
|
-
Initial release
|
diffsync-2.1.0/pyproject.toml
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
[tool.poetry]
|
|
2
|
-
name = "diffsync"
|
|
3
|
-
version = "v2.1.0"
|
|
4
|
-
description = "Library to easily sync/diff/update 2 different data sources"
|
|
5
|
-
authors = ["Network to Code, LLC <info@networktocode.com>"]
|
|
6
|
-
license = "Apache-2.0"
|
|
7
|
-
readme = "README.md"
|
|
8
|
-
homepage = "https://diffsync.readthedocs.io"
|
|
9
|
-
repository = "https://github.com/networktocode/diffsync"
|
|
10
|
-
documentation = "https://diffsync.readthedocs.io"
|
|
11
|
-
keywords = ["source-of-truth", "synchronization"]
|
|
12
|
-
include = [
|
|
13
|
-
"CHANGELOG.md",
|
|
14
|
-
"LICENSE",
|
|
15
|
-
"README.md",
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
[tool.poetry.dependencies]
|
|
19
|
-
python = ">=3.9,<4.0"
|
|
20
|
-
pydantic = "^2.0.0"
|
|
21
|
-
structlog = ">= 20.1.0"
|
|
22
|
-
packaging = ">= 21.3"
|
|
23
|
-
colorama = {version = "^0.4.3", optional = true}
|
|
24
|
-
redis = {version = "^4.3", optional = true}
|
|
25
|
-
# typing.Self introduced in 3.11
|
|
26
|
-
typing-extensions = { version = ">=4.0.1", python = "<3.11" }
|
|
27
|
-
|
|
28
|
-
[tool.poetry.extras]
|
|
29
|
-
redis = ["redis"]
|
|
30
|
-
|
|
31
|
-
[tool.poetry.group.dev.dependencies]
|
|
32
|
-
pytest = "*"
|
|
33
|
-
pyyaml = ">= 6.0.1"
|
|
34
|
-
black = "*"
|
|
35
|
-
pylint = "*"
|
|
36
|
-
pydocstyle = "*"
|
|
37
|
-
yamllint = "*"
|
|
38
|
-
bandit = "*"
|
|
39
|
-
invoke = "*"
|
|
40
|
-
flake8 = "*"
|
|
41
|
-
mypy = "*"
|
|
42
|
-
pytest-cov = "*"
|
|
43
|
-
pytest-structlog = "*"
|
|
44
|
-
coverage = {extras = ["toml"], version = "*"}
|
|
45
|
-
Sphinx = "^6.0.0"
|
|
46
|
-
m2r2 = "*"
|
|
47
|
-
sphinx-rtd-theme = "*"
|
|
48
|
-
toml = "*"
|
|
49
|
-
types-toml = "*"
|
|
50
|
-
types-redis = "*"
|
|
51
|
-
pytest-redis = "^2.4.0"
|
|
52
|
-
types-requests = "^2.28.11.15"
|
|
53
|
-
types-python-slugify = "^8.0.0.1"
|
|
54
|
-
|
|
55
|
-
[tool.black]
|
|
56
|
-
line-length = 120
|
|
57
|
-
include = '\.pyi?$'
|
|
58
|
-
exclude = '''
|
|
59
|
-
/(
|
|
60
|
-
\.git
|
|
61
|
-
| \.tox
|
|
62
|
-
| \.venv
|
|
63
|
-
| env/
|
|
64
|
-
| _build
|
|
65
|
-
| build
|
|
66
|
-
| dist
|
|
67
|
-
)/
|
|
68
|
-
'''
|
|
69
|
-
|
|
70
|
-
[tool.coverage.run]
|
|
71
|
-
branch = true
|
|
72
|
-
|
|
73
|
-
[tool.pylint.general]
|
|
74
|
-
extension-pkg-whitelist = [
|
|
75
|
-
"pydantic"
|
|
76
|
-
]
|
|
77
|
-
|
|
78
|
-
[tool.pylint.basic]
|
|
79
|
-
# No docstrings required for private methods (Pylint default), or for test_ functions.
|
|
80
|
-
no-docstring-rgx="^(_|test_)"
|
|
81
|
-
|
|
82
|
-
[tool.pylint.messages_control]
|
|
83
|
-
# Line length is enforced by Black, so pylint doesn't need to check it.
|
|
84
|
-
# Pylint and Black disagree about how to format multi-line arrays; Black wins.
|
|
85
|
-
disable = """,
|
|
86
|
-
line-too-long,
|
|
87
|
-
"""
|
|
88
|
-
|
|
89
|
-
[tool.pylint.miscellaneous]
|
|
90
|
-
# Don't flag TODO as a failure, let us commit with things that still need to be done in the code
|
|
91
|
-
notes = """,
|
|
92
|
-
FIXME,
|
|
93
|
-
XXX,
|
|
94
|
-
"""
|
|
95
|
-
|
|
96
|
-
[tool.pylint.similarities]
|
|
97
|
-
# There's a lot of duplicate code in the examples/backend_*.py files - don't complain about it for now
|
|
98
|
-
min-similarity-lines = 20
|
|
99
|
-
|
|
100
|
-
[tool.pytest.ini_options]
|
|
101
|
-
testpaths = [
|
|
102
|
-
"tests"
|
|
103
|
-
]
|
|
104
|
-
|
|
105
|
-
[tool.mypy]
|
|
106
|
-
warn_unused_configs = true
|
|
107
|
-
disallow_untyped_defs = true
|
|
108
|
-
ignore_missing_imports = true
|
|
109
|
-
|
|
110
|
-
[build-system]
|
|
111
|
-
requires = ["poetry_core>=1.0.8"]
|
|
112
|
-
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|