diffsync 2.1.0__tar.gz → 2.2.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.1.0 → diffsync-2.2.0}/LICENSE +4 -4
- {diffsync-2.1.0 → diffsync-2.2.0}/PKG-INFO +37 -19
- {diffsync-2.1.0 → diffsync-2.2.0}/README.md +33 -16
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/__init__.py +16 -4
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/exceptions.py +1 -1
- diffsync-2.2.0/diffsync/log.py +74 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/404.html +1505 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/install.html +1628 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/index.html +1607 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.0.html +1637 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.1.html +1678 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.10.html +1665 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.2.html +1656 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.3.html +1656 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.4.html +1738 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.5.html +1678 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.6.html +1656 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.7.html +1686 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.8.html +1671 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_1.9.html +1662 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_2.0.html +1707 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_2.1.html +1671 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/release_notes/version_2.2.html +1636 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/uninstall.html +1619 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/admin/upgrade.html +1619 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/_mkdocstrings.css +143 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/extra.css +152 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/favicon.ico +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/images/favicon.png +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/bundle.56ea9cef.min.js +16 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/bundle.56ea9cef.min.js.map +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/glightbox.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/tinyseg.js +206 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/lunr/wordcut.js +6708 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/workers/search.d50fe291.min.js +42 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/javascripts/workers/search.d50fe291.min.js.map +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/networktocode_bw.png +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/networktocode_logo.png +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/overrides/partials/copyright.html +21 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/stylesheets/glightbox.min.css +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/stylesheets/main.342714a4.min.css +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/stylesheets/main.342714a4.min.css.map +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/stylesheets/palette.06af60db.min.css +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/assets/stylesheets/palette.06af60db.min.css.map +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/__init__.html +6026 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/diff.html +3063 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/enum.html +2343 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/exceptions.html +2226 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/helpers.html +2423 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/log.html +1796 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/logging.html +1770 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/store/__init__.html +2934 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/store/local.html +2376 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/store/redis.html +2393 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/code-reference/diffsync/utils.html +2022 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/dev/arch_decision.html +1617 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/dev/contributing.html +1775 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/dev/dev_environment.html +1913 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/dev/extending.html +1617 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/dev/release_checklist.html +2037 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/generate_code_reference_pages.py +38 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/images/diffsync_components.png +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/images/diffsync_diff_creation.png +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/images/diffsync_sync.png +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/images/networktocode_logo.svg +150 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/images/preorder-tree-traversal.drawio.png +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/index.html +1906 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/objects.inv +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/requirements.txt +5 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/search/search_index.json +1 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/sitemap.xml +179 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/sitemap.xml.gz +0 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.diff.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.enum.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.exceptions.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.helpers.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.logging.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.rst +26 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.store.local.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.store.redis.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.store.rst +14 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/api/diffsync.utils.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/conf.py +99 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/core_engine/01-flags.html +1989 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/core_engine/02-customize-diff-class.html +1734 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/core_engine/03-store.html +1729 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/core_engine/index.rst +11 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/examples/index.rst +12 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/getting_started/01-getting-started.html +1861 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/getting_started/index.rst +5 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/index.rst +22 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/license/index.rst +5 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/overview/index.rst +7 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/static/schema-page.css +62 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/static/theme_overrides.css +13 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/template/api/module.rst_t +9 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/template/api/package.rst_t +51 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/upgrading/01-upgrading-to-2.0.html +1721 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/source/upgrading/index.rst +5 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/user/faq.html +1616 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/user/lib_getting_started.html +1724 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/user/lib_overview.html +1722 -0
- diffsync-2.2.0/diffsync/static/diffsync/docs/user/lib_use_cases.html +1718 -0
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/store/__init__.py +3 -3
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/store/local.py +2 -3
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/store/redis.py +2 -2
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/utils.py +2 -2
- diffsync-2.2.0/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.0}/diffsync/diff.py +0 -0
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/enum.py +0 -0
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/helpers.py +0 -0
- {diffsync-2.1.0 → diffsync-2.2.0}/diffsync/logging.py +0 -0
- {diffsync-2.1.0 → diffsync-2.2.0}/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.
|
|
3
|
+
Version: 2.2.0
|
|
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,13 @@ 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 = deepcopy(kwargs)
|
|
488
|
+
instance = super().__new__(cls)
|
|
489
|
+
instance._meta_kwargs = meta_kwargs
|
|
490
|
+
return instance
|
|
491
|
+
|
|
483
492
|
def __str__(self) -> StrType:
|
|
484
493
|
"""String representation of an Adapter."""
|
|
485
494
|
if self.type != self.name:
|
|
@@ -487,6 +496,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
487
496
|
return self.type
|
|
488
497
|
|
|
489
498
|
def __repr__(self) -> StrType:
|
|
499
|
+
"""Representation of an Adapter."""
|
|
490
500
|
return f"<{str(self)}>"
|
|
491
501
|
|
|
492
502
|
def __len__(self) -> int:
|
|
@@ -575,6 +585,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
575
585
|
callback: Function with parameters (stage, current, total), to be called at intervals as the calculation of
|
|
576
586
|
the diff and subsequent sync proceed.
|
|
577
587
|
diff: An existing diff to be used rather than generating a completely new diff.
|
|
588
|
+
|
|
578
589
|
Returns:
|
|
579
590
|
Diff between origin object and source
|
|
580
591
|
Raises:
|
|
@@ -619,6 +630,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
619
630
|
callback: Function with parameters (stage, current, total), to be called at intervals as the calculation of
|
|
620
631
|
the diff and subsequent sync proceed.
|
|
621
632
|
diff: An existing diff that will be used when determining what needs to be synced.
|
|
633
|
+
|
|
622
634
|
Returns:
|
|
623
635
|
Diff between origin object and target
|
|
624
636
|
Raises:
|
|
@@ -729,7 +741,7 @@ class Adapter: # pylint: disable=too-many-public-methods
|
|
|
729
741
|
obj: Union[StrType, DiffSyncModel, Type[DiffSyncModel]],
|
|
730
742
|
identifier: Union[StrType, Dict],
|
|
731
743
|
) -> Optional[DiffSyncModel]:
|
|
732
|
-
"""Get one object from the data store based on its unique id or get a None
|
|
744
|
+
"""Get one object from the data store based on its unique id or get a None.
|
|
733
745
|
|
|
734
746
|
Args:
|
|
735
747
|
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.")
|