diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec1b68d..4e4cd62 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -130,6 +130,7 @@ jobs: fail-fast: true matrix: python-version: ["3.7", "3.8", "3.9", "3.10"] + poetry-version: ["1.5.1"] runs-on: "ubuntu-20.04" env: PYTHON_VER: "${{ matrix.python-version }}" @@ -137,9 +138,10 @@ jobs: - name: "Check out repository code" uses: "actions/checkout@v2" - name: "Setup environment" - uses: "networktocode/gh-action-setup-poetry-environment@v5" + uses: "networktocode/gh-action-setup-poetry-environment@3ea5d3ecf382cdcb0c74d4c0ff0629d95fce63c7" with: python-version: "${{ matrix.python-version }}" + poetry-version: "${{ matrix.poetry-version }}" - name: "Install redis" run: "sudo apt-get install -y redis" - name: "Run poetry Install" diff --git a/Dockerfile b/Dockerfile index 824f054..e5b36ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* RUN pip install --upgrade pip \ - && pip install poetry + && pip install poetry==1.5.1 WORKDIR /local diff --git a/README.md b/README.md index 96484f4..61eec47 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ DiffSync is at its most useful when you have multiple sources or sets of data to # Overview of DiffSync -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 `DiffSync` class, and each data model class will be a subclass of the `DiffSyncModel` class. +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. ![Diffsync Components](https://raw.githubusercontent.com/networktocode/diffsync/develop/docs/images/diffsync_components.png "Diffsync Components") diff --git a/diffsync/__init__.py b/diffsync/__init__.py index 412270d..916ca18 100644 --- a/diffsync/__init__.py +++ b/diffsync/__init__.py @@ -91,7 +91,7 @@ class DiffSyncModel(BaseModel): Can be set as a class attribute or an instance attribute as needed. """ - diffsync: Optional["DiffSync"] = None + diffsync: Optional["Adapter"] = None """Optional: the DiffSync instance that owns this model instance.""" _status: DiffSyncStatus = PrivateAttr(DiffSyncStatus.SUCCESS) @@ -183,7 +183,7 @@ def set_status(self, status: DiffSyncStatus, message: StrType = "") -> None: self._status_message = message @classmethod - def create_base(cls, diffsync: "DiffSync", ids: Dict, attrs: Dict) -> Optional[Self]: + def create_base(cls, diffsync: "Adapter", ids: Dict, attrs: Dict) -> Optional[Self]: """Instantiate this class, along with any platform-specific data creation. This method is not meant to be subclassed, users should redefine create() instead. @@ -201,7 +201,7 @@ def create_base(cls, diffsync: "DiffSync", ids: Dict, attrs: Dict) -> Optional[S return model @classmethod - def create(cls, diffsync: "DiffSync", ids: Dict, attrs: Dict) -> Optional[Self]: + def create(cls, diffsync: "Adapter", ids: Dict, attrs: Dict) -> Optional[Self]: """Instantiate this class, along with any platform-specific data creation. Subclasses must call `super().create()` or `self.create_base()`; they may wish to then override the default status information @@ -402,7 +402,7 @@ def remove_child(self, child: "DiffSyncModel") -> None: childs.remove(child.get_unique_id()) -class DiffSync: # pylint: disable=too-many-public-methods +class Adapter: # pylint: disable=too-many-public-methods """Class for storing a group of DiffSyncModel instances and diffing/synchronizing to another DiffSync instance.""" # In any subclass, you would add mapping of names to specific model classes here: @@ -535,7 +535,7 @@ def load_from_dict(self, data: Dict) -> None: def sync_from( # pylint: disable=too-many-arguments self, - source: "DiffSync", + source: "Adapter", diff_class: Type[Diff] = Diff, flags: DiffSyncFlags = DiffSyncFlags.NONE, callback: Optional[Callable[[StrType, int, int], None]] = None, @@ -573,7 +573,7 @@ def sync_from( # pylint: disable=too-many-arguments def sync_to( # pylint: disable=too-many-arguments self, - target: "DiffSync", + target: "Adapter", diff_class: Type[Diff] = Diff, flags: DiffSyncFlags = DiffSyncFlags.NONE, callback: Optional[Callable[[StrType, int, int], None]] = None, @@ -597,7 +597,7 @@ def sync_to( # pylint: disable=too-many-arguments def sync_complete( self, - source: "DiffSync", + source: "Adapter", diff: Diff, flags: DiffSyncFlags = DiffSyncFlags.NONE, logger: Optional[structlog.BoundLogger] = None, @@ -623,7 +623,7 @@ def sync_complete( def diff_from( self, - source: "DiffSync", + source: "Adapter", diff_class: Type[Diff] = Diff, flags: DiffSyncFlags = DiffSyncFlags.NONE, callback: Optional[Callable[[StrType, int, int], None]] = None, @@ -644,7 +644,7 @@ def diff_from( def diff_to( self, - target: "DiffSync", + target: "Adapter", diff_class: Type[Diff] = Diff, flags: DiffSyncFlags = DiffSyncFlags.NONE, callback: Optional[Callable[[StrType, int, int], None]] = None, @@ -854,5 +854,8 @@ def count(self, model: Union[StrType, "DiffSyncModel", Type["DiffSyncModel"], No return self.store.count(model=model) +# For backwards-compatibility, keep around the old name +DiffSync = Adapter + # DiffSyncModel references DiffSync and DiffSync references DiffSyncModel. Break the typing loop: DiffSyncModel.update_forward_refs() diff --git a/diffsync/helpers.py b/diffsync/helpers.py index 96882ba..b51f142 100644 --- a/diffsync/helpers.py +++ b/diffsync/helpers.py @@ -26,7 +26,7 @@ if TYPE_CHECKING: # pragma: no cover # For type annotation purposes, we have a circular import loop between __init__.py and this file. - from . import DiffSync, DiffSyncModel # pylint: disable=cyclic-import + from . import Adapter, DiffSyncModel # pylint: disable=cyclic-import class DiffSyncDiffer: # pylint: disable=too-many-instance-attributes @@ -37,8 +37,8 @@ class DiffSyncDiffer: # pylint: disable=too-many-instance-attributes def __init__( # pylint: disable=too-many-arguments self, - src_diffsync: "DiffSync", - dst_diffsync: "DiffSync", + src_diffsync: "Adapter", + dst_diffsync: "Adapter", flags: DiffSyncFlags, diff_class: Type[Diff] = Diff, callback: Optional[Callable[[str, int, int], None]] = None, @@ -288,8 +288,8 @@ class DiffSyncSyncer: # pylint: disable=too-many-instance-attributes def __init__( # pylint: disable=too-many-arguments self, diff: Diff, - src_diffsync: "DiffSync", - dst_diffsync: "DiffSync", + src_diffsync: "Adapter", + dst_diffsync: "Adapter", flags: DiffSyncFlags, callback: Optional[Callable[[str, int, int], None]] = None, ): diff --git a/diffsync/store/__init__.py b/diffsync/store/__init__.py index 77f1a9f..3dacf33 100644 --- a/diffsync/store/__init__.py +++ b/diffsync/store/__init__.py @@ -6,7 +6,7 @@ if TYPE_CHECKING: from diffsync import DiffSyncModel - from diffsync import DiffSync + from diffsync import Adapter class BaseStore: @@ -15,7 +15,7 @@ class BaseStore: def __init__( self, # pylint: disable=unused-argument *args: Any, # pylint: disable=unused-argument - diffsync: Optional["DiffSync"] = None, + diffsync: Optional["Adapter"] = None, name: str = "", **kwargs: Any, # pylint: disable=unused-argument ) -> None: diff --git a/docs/source/core_engine/01-flags.md b/docs/source/core_engine/01-flags.md index 542703e..12f4ca9 100644 --- a/docs/source/core_engine/01-flags.md +++ b/docs/source/core_engine/01-flags.md @@ -34,12 +34,12 @@ diff = nautobot.diff_from(local, flags=flags) Model flags are stored in the attribute `model_flags` of each model and are usually set when the data is being loaded into the adapter. ```python -from diffsync import DiffSync +from diffsync import Adapter from diffsync.enum import DiffSyncModelFlags from model import MyDeviceModel -class MyAdapter(DiffSync): +class MyAdapter(Adapter): device = MyDeviceModel def load(self, data): diff --git a/docs/source/core_engine/03-store.md b/docs/source/core_engine/03-store.md index 7a4a7bd..a3cb690 100644 --- a/docs/source/core_engine/03-store.md +++ b/docs/source/core_engine/03-store.md @@ -2,32 +2,36 @@ By default, `Diffsync` supports a local memory storage. All the loaded models from the adapters will be stored in memory, and become available for the diff calculation and sync process. This default behavior works well when executing all the steps in the same process, having access to the same memory space. However, if you want to scale out the execution of the tasks, running it in different processes or in totally different workers, a more distributed memory support is necessary. -The `store` is a class attribute in the `DiffSync` class, but all the store operations in that class are abstracted in the following methods: `get_all_model_names`, `get`, `get_by_uids`, `add`, `update`, `remove`, `get_or_instantiate`, `update_or_instantiate` and `count`. +The `store` is a class attribute in the `Adapter` class, but all the store operations in that class are abstracted in the following methods: `get_all_model_names`, `get`, `get_by_uids`, `add`, `update`, `remove`, `get_or_instantiate`, `update_or_instantiate` and `count`. ## Use the `LocalStore` Backend When you initialize the `Diffsync` Adapter class, there is an optional keyed-argument, `internal_storage_engine`, defaulting to the `LocalStore` class. ```python ->>> from diffsync import DiffSync ->>> adapter = DiffSync() ->>> type(adapter.store) - +>> > from diffsync import Adapter +>> > adapter = Adapter() +>> > type(adapter.store) +< + +class 'diffsync.store.local.LocalStore'> ``` ## Use the `RedisStore` Backend To get it, you have to install diffsync package with the "redis" extra option: `pip install diffsync[redis]` -The `RedisStore` backend, as the name suggests, connects to an external Redis service, to store data loaded by the `DiffSync` tasks. The biggest change is that it requires to initialize the Redis store class, before using it in the `DiffSync` adapter class. +The `RedisStore` backend, as the name suggests, connects to an external Redis service, to store data loaded by the `Adapter` tasks. The biggest change is that it requires to initialize the Redis store class, before using it in the `Adapter` adapter class. ```python ->>> from diffsync import DiffSync ->>> from diffsync.store.redis import RedisStore ->>> store = RedisStore(host="redis host") ->>> adapter = DiffSync(internal_storage_engine=store) ->>> type(adapter.store) - +>> > from diffsync import Adapter +>> > from diffsync.store.redis import RedisStore +>> > store = RedisStore(host="redis host") +>> > adapter = Adapter(internal_storage_engine=store) +>> > type(adapter.store) +< + +class 'diffsync.store.local.RedisStore'> ``` Notice that the `RedisStore` will validate, when initialized, that there is a reachability to the Redis host, and if not, will raise an exception: diff --git a/docs/source/getting_started/01-getting-started.md b/docs/source/getting_started/01-getting-started.md index 6f0cc0f..9b99cc3 100644 --- a/docs/source/getting_started/01-getting-started.md +++ b/docs/source/getting_started/01-getting-started.md @@ -1,5 +1,5 @@ To be able to properly compare different datasets, DiffSync relies on a shared data model that both systems must use. -Specifically, each system or dataset must provide a `DiffSync` "adapter" subclass, which in turn represents its dataset as instances of one or more `DiffSyncModel` data model classes. +Specifically, each system or dataset must provide a `Adapter` "adapter" subclass, which in turn represents its dataset as instances of one or more `DiffSyncModel` data model classes. When comparing two systems, DiffSync detects the intersection between the two systems (which data models they have in common, and which attributes are shared between each pair of data models) and uses this intersection to compare and/or synchronize the data. @@ -41,24 +41,24 @@ Currently the relationships between models are very loose by design. Instead of # Define your system adapter with DiffSync -A `DiffSync` "adapter" subclass must reference each model available at the top of the object by its modelname and must have a `top_level` attribute defined to indicate how the diff and the synchronization should be done. In the example below, `"site"` is the only top level object so the synchronization engine will only check all known `Site` instances and all children of each Site. In this case, as shown in the code above, `Device`s are children of `Site`s, so this is exactly the intended logic. +A `Adapter` "adapter" subclass must reference each model available at the top of the object by its modelname and must have a `top_level` attribute defined to indicate how the diff and the synchronization should be done. In the example below, `"site"` is the only top level object so the synchronization engine will only check all known `Site` instances and all children of each Site. In this case, as shown in the code above, `Device`s are children of `Site`s, so this is exactly the intended logic. ```python -from diffsync import DiffSync +from diffsync import Adapter -class BackendA(DiffSync): +class BackendA(Adapter): site = Site device = Device top_level = ["site"] ``` -It's up to the implementer to populate the `DiffSync`'s internal cache with the appropriate data. In the example below we are using the `load()` method to populate the cache but it's not mandatory, it could be done differently. +It's up to the implementer to populate the `Adapter`'s internal cache with the appropriate data. In the example below we are using the `load()` method to populate the cache but it's not mandatory, it could be done differently. ## Model Processing Ordering Logic -The models will be processed in a specfic order as defined by `top_level` atttribute on the `DiffSync` object and then the `_children` attribute on the `DiffSyncModel`. The processing algorithm is technically a "Preorder Tree Traversal", which means that "a parent node is processed before any of its child nodes is done." This can be described as: +The models will be processed in a specfic order as defined by `top_level` atttribute on the `Adapter` object and then the `_children` attribute on the `DiffSyncModel`. The processing algorithm is technically a "Preorder Tree Traversal", which means that "a parent node is processed before any of its child nodes is done." This can be described as: - Start with the first element of the first model in `top_level` and process it. - If that model has `_children` set on it, for each child of each child model, in order: @@ -145,7 +145,7 @@ NetworkImporterAdapter >>> ``` -# Store data in a `DiffSync` object +# Store data in a `Adapter` object To add a site to the local cache/store, you need to pass a valid `DiffSyncModel` object to the `add()` function. @@ -174,7 +174,7 @@ convenient to manage individual records (as in a database) or modify the entire ## Manage individual records To update individual records in a remote system, you need to extend your `DiffSyncModel` class(es) to define your own `create`, `update` and/or `delete` methods for each model. -A `DiffSyncModel` instance stores a reference to its parent `DiffSync` adapter instance in case you need to use it to look up other model instances from the `DiffSync`'s cache. +A `DiffSyncModel` instance stores a reference to its parent `Adapter` adapter instance in case you need to use it to look up other model instances from the `Adapter`'s cache. ```python class Device(DiffSyncModel): diff --git a/examples/01-multiple-data-sources/backend_a.py b/examples/01-multiple-data-sources/backend_a.py index a92435b..6edd799 100644 --- a/examples/01-multiple-data-sources/backend_a.py +++ b/examples/01-multiple-data-sources/backend_a.py @@ -16,7 +16,7 @@ """ # pylint: disable=wrong-import-order -from diffsync import DiffSync +from diffsync import Adapter from models import Site, Device, Interface # pylint: disable=no-name-in-module DATA = { @@ -31,7 +31,7 @@ } -class BackendA(DiffSync): +class BackendA(Adapter): """Example of a DiffSync adapter implementation.""" site = Site diff --git a/examples/01-multiple-data-sources/backend_b.py b/examples/01-multiple-data-sources/backend_b.py index 6fc7c20..98db921 100644 --- a/examples/01-multiple-data-sources/backend_b.py +++ b/examples/01-multiple-data-sources/backend_b.py @@ -16,7 +16,7 @@ """ # pylint: disable=wrong-import-order -from diffsync import DiffSync +from diffsync import Adapter from models import Site, Device, Interface # pylint: disable=no-name-in-module DATA = { @@ -35,7 +35,7 @@ } -class BackendB(DiffSync): +class BackendB(Adapter): """Example of a DiffSync adapter implementation.""" site = Site diff --git a/examples/01-multiple-data-sources/backend_c.py b/examples/01-multiple-data-sources/backend_c.py index a964e96..88ed91a 100644 --- a/examples/01-multiple-data-sources/backend_c.py +++ b/examples/01-multiple-data-sources/backend_c.py @@ -16,7 +16,7 @@ """ # pylint: disable=wrong-import-order -from diffsync import DiffSync +from diffsync import Adapter from models import Site, Device, Interface # pylint: disable=no-name-in-module DATA = { @@ -31,7 +31,7 @@ } -class BackendC(DiffSync): +class BackendC(Adapter): """Example of a DiffSync adapter implementation.""" site = Site diff --git a/examples/02-callback-function/main.py b/examples/02-callback-function/main.py index 514f2cb..84884f2 100755 --- a/examples/02-callback-function/main.py +++ b/examples/02-callback-function/main.py @@ -17,7 +17,7 @@ """ import random -from diffsync import DiffSync, DiffSyncModel +from diffsync import Adapter, DiffSyncModel from diffsync.logging import enable_console_logging @@ -30,7 +30,7 @@ class Number(DiffSyncModel): number: int -class DiffSync1(DiffSync): +class Adapter1(Adapter): """DiffSync adapter that contains a number of Numbers constructed in order.""" number = Number @@ -43,7 +43,7 @@ def load(self, count): # pylint: disable=arguments-differ self.add(Number(number=(i + 1))) -class DiffSync2(DiffSync): +class Adapter2(Adapter): """DiffSync adapter that contains a number of Numbers spread randomly across a range.""" number = Number @@ -69,11 +69,11 @@ def main(): enable_console_logging(verbosity=0) # Show WARNING and ERROR logs only # Create a DiffSync1 instance and load it with records numbered 1-100 - ds1 = DiffSync1() + ds1 = Adapter1() ds1.load(count=100) # Create a DiffSync2 instance and load it with 100 random records in the range 1-200 - ds2 = DiffSync2() + ds2 = Adapter2() ds2.load(count=100) # Identify and attempt to resolve the differences between the two, diff --git a/examples/03-remote-system/local_adapter.py b/examples/03-remote-system/local_adapter.py index eb39fdc..9f38d1e 100644 --- a/examples/03-remote-system/local_adapter.py +++ b/examples/03-remote-system/local_adapter.py @@ -4,13 +4,13 @@ from slugify import slugify # pylint: disable=import-error from models import Region, Country # pylint: disable=no-name-in-module -from diffsync import DiffSync +from diffsync import Adapter COUNTRIES_FILE = "countries.json" -class LocalAdapter(DiffSync): +class LocalAdapter(Adapter): """DiffSync Adapter to Load the list of regions and countries from a local JSON file.""" # Define all data models that this adapter makes use of. diff --git a/examples/03-remote-system/nautobot_adapter.py b/examples/03-remote-system/nautobot_adapter.py index e0fb386..9ec17c6 100644 --- a/examples/03-remote-system/nautobot_adapter.py +++ b/examples/03-remote-system/nautobot_adapter.py @@ -4,7 +4,7 @@ from nautobot_models import NautobotCountry, NautobotRegion -from diffsync import DiffSync +from diffsync import Adapter # pylint: disable=attribute-defined-outside-init @@ -22,7 +22,7 @@ ] -class NautobotAdapter(DiffSync): +class NautobotAdapter(Adapter): """Example of a DiffSync adapter implementation using pynautobot to communicate with a remote Nautobot system.""" # We are using NautobotCountry and NautobotRegion instead of Region and Country diff --git a/examples/03-remote-system/nautobot_models.py b/examples/03-remote-system/nautobot_models.py index c1377d8..2baba77 100644 --- a/examples/03-remote-system/nautobot_models.py +++ b/examples/03-remote-system/nautobot_models.py @@ -3,7 +3,7 @@ from models import Region, Country # pylint: disable=no-name-in-module -from diffsync import DiffSync +from diffsync import Adapter # pylint: disable=no-member,too-few-public-methods @@ -30,7 +30,7 @@ class NautobotCountry(Country): """Store the nautobot uuid in the object to allow update and delete of existing object.""" @classmethod - def create(cls, diffsync: DiffSync, ids: dict, attrs: dict): + def create(cls, diffsync: Adapter, ids: dict, attrs: dict): """Create a country object in Nautobot. Args: diff --git a/examples/04-get-update-instantiate/README.md b/examples/04-get-update-instantiate/README.md index ecb1390..14e2745 100644 --- a/examples/04-get-update-instantiate/README.md +++ b/examples/04-get-update-instantiate/README.md @@ -1,12 +1,12 @@ # Example 4 - Using get or update helpers -This example aims to expand on [Example 1](https://github.com/networktocode/diffsync/tree/main/examples/01-multiple-data-sources/README.md) that will take advantage of two new helper methods on the `DiffSync` class; `get_or_instantiate` and `update_or_instantiate`. +This example aims to expand on [Example 1](https://github.com/networktocode/diffsync/tree/main/examples/01-multiple-data-sources/README.md) that will take advantage of two new helper methods on the `Adapter` class; `get_or_instantiate` and `update_or_instantiate`. Both methods act similar to Django's `get_or_create` function to return the object and then a boolean to identify whether the object was created or not. Let's dive into each of them. ## get_or_instantiate -The following arguments are supported: model (`DiffSyncModel`), ids (dictionary), and attrs (dictionary). The `model` and `ids` are used to find an existing object. If the object does not currently exist within the `DiffSync` adapter, it will then use `model`, `ids`, and `attrs` to add the object. +The following arguments are supported: model (`DiffSyncModel`), ids (dictionary), and attrs (dictionary). The `model` and `ids` are used to find an existing object. If the object does not currently exist within the `Adapter` adapter, it will then use `model`, `ids`, and `attrs` to add the object. It will then return a tuple that can be unpacked. @@ -69,4 +69,4 @@ BACKEND_DATA_A = [ device.add_child(intf) ``` -The new methods are helpful due to having devices that are part of the same site. As we iterate over the data and load it into the `DiffSync` adapter, we would have to account for `ObjectAlreadyExists` exceptions when we go to add each duplicate site we encounter within the data or possibly several other models depending how complex the synchronization of data is between backends. +The new methods are helpful due to having devices that are part of the same site. As we iterate over the data and load it into the `Adapter` adapter, we would have to account for `ObjectAlreadyExists` exceptions when we go to add each duplicate site we encounter within the data or possibly several other models depending how complex the synchronization of data is between backends. diff --git a/examples/04-get-update-instantiate/backends.py b/examples/04-get-update-instantiate/backends.py index bbc06e4..ba73a8e 100644 --- a/examples/04-get-update-instantiate/backends.py +++ b/examples/04-get-update-instantiate/backends.py @@ -16,7 +16,7 @@ """ from models import Site, Device, Interface # pylint: disable=no-name-in-module -from diffsync import DiffSync +from diffsync import Adapter BACKEND_DATA_A = [ { @@ -74,7 +74,7 @@ ] -class BackendA(DiffSync): +class BackendA(Adapter): """Example of a DiffSync adapter implementation.""" site = Site @@ -104,7 +104,7 @@ def load(self): device.add_child(intf) -class BackendB(DiffSync): +class BackendB(Adapter): """Example of a DiffSync adapter implementation.""" site = Site diff --git a/examples/05-nautobot-peeringdb/adapter_nautobot.py b/examples/05-nautobot-peeringdb/adapter_nautobot.py index 7970274..84be2d6 100644 --- a/examples/05-nautobot-peeringdb/adapter_nautobot.py +++ b/examples/05-nautobot-peeringdb/adapter_nautobot.py @@ -2,7 +2,7 @@ # pylint: disable=import-error,no-name-in-module import pynautobot from models import RegionModel, SiteModel -from diffsync import DiffSync +from diffsync import Adapter class RegionNautobotModel(RegionModel): @@ -116,7 +116,7 @@ def delete(self): # pylint: disable= useless-super-delegation return super().delete() -class NautobotRemote(DiffSync): +class NautobotRemote(Adapter): """DiffSync adapter class for loading data from a remote Nautobot instance using Python requests.""" # Model classes used by this adapter class diff --git a/examples/05-nautobot-peeringdb/adapter_peeringdb.py b/examples/05-nautobot-peeringdb/adapter_peeringdb.py index 08feb60..91cdf6a 100644 --- a/examples/05-nautobot-peeringdb/adapter_peeringdb.py +++ b/examples/05-nautobot-peeringdb/adapter_peeringdb.py @@ -5,7 +5,7 @@ from slugify import slugify import pycountry from models import RegionModel, SiteModel -from diffsync import DiffSync +from diffsync import Adapter from diffsync.exceptions import ObjectNotFound @@ -13,7 +13,7 @@ PEERINGDB_API_KEY = os.environ.get("PEERINGDB_API_KEY", "").strip() -class PeeringDB(DiffSync): +class PeeringDB(Adapter): """DiffSync adapter using requests to communicate with PeeringDB.""" # Model classes used by this adapter class diff --git a/examples/06-ip-prefixes/adapter_ipam_a.py b/examples/06-ip-prefixes/adapter_ipam_a.py index 4b43595..5463cd4 100644 --- a/examples/06-ip-prefixes/adapter_ipam_a.py +++ b/examples/06-ip-prefixes/adapter_ipam_a.py @@ -3,7 +3,7 @@ import ipaddress import yaml from models import Prefix # pylint: disable=no-name-in-module -from diffsync import DiffSync +from diffsync import Adapter dirname = os.path.dirname(os.path.realpath(__file__)) @@ -50,7 +50,7 @@ def delete(self): return super().delete() -class IpamA(DiffSync): +class IpamA(Adapter): """IPAM A DiffSync adapter implementation.""" prefix = IpamAPrefix diff --git a/examples/06-ip-prefixes/adapter_ipam_b.py b/examples/06-ip-prefixes/adapter_ipam_b.py index b29e76b..7a6eadb 100644 --- a/examples/06-ip-prefixes/adapter_ipam_b.py +++ b/examples/06-ip-prefixes/adapter_ipam_b.py @@ -2,7 +2,7 @@ import os import yaml from models import Prefix # pylint: disable=no-name-in-module -from diffsync import DiffSync +from diffsync import Adapter dirname = os.path.dirname(os.path.realpath(__file__)) @@ -55,7 +55,7 @@ def delete(self): return super().delete() -class IpamB(DiffSync): +class IpamB(Adapter): """IPAM A DiffSync adapter implementation.""" prefix = IpamBPrefix diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index e0dd85c..498e889 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -18,7 +18,7 @@ import pytest -from diffsync import DiffSync, DiffSyncModel +from diffsync import Adapter, DiffSyncModel from diffsync.diff import Diff, DiffElement from diffsync.exceptions import ObjectNotCreated, ObjectNotUpdated, ObjectNotDeleted @@ -35,7 +35,7 @@ class ErrorProneModelMixin: _counter: ClassVar[int] = 0 @classmethod - def create(cls, diffsync: DiffSync, ids: Dict, attrs: Dict): + def create(cls, diffsync: Adapter, ids: Dict, attrs: Dict): """As DiffSyncModel.create(), but periodically throw exceptions.""" cls._counter += 1 if not cls._counter % 5: @@ -69,7 +69,7 @@ class ExceptionModelMixin: """Test class that always throws exceptions when creating/updating/deleting instances.""" @classmethod - def create(cls, diffsync: DiffSync, ids: Dict, attrs: Dict): + def create(cls, diffsync: Adapter, ids: Dict, attrs: Dict): """As DiffSyncModel.create(), but always throw exceptions.""" raise NotImplementedError @@ -160,7 +160,7 @@ def interface(device_name="device1", name="eth0", **kwargs): @pytest.fixture def generic_diffsync(): """Provide a generic DiffSync instance.""" - return DiffSync() + return Adapter() class UnusedModel(DiffSyncModel): @@ -172,7 +172,7 @@ class UnusedModel(DiffSyncModel): name: str -class GenericBackend(DiffSync): +class GenericBackend(Adapter): """An example semi-abstract subclass of DiffSync.""" site = Site # to be overridden by subclasses diff --git a/tests/unit/test_diffsync.py b/tests/unit/test_diffsync.py index 74727be..6f7feae 100644 --- a/tests/unit/test_diffsync.py +++ b/tests/unit/test_diffsync.py @@ -5,7 +5,7 @@ import pytest -from diffsync import DiffSync, DiffSyncModel +from diffsync import Adapter, DiffSyncModel from diffsync.enum import DiffSyncFlags, DiffSyncModelFlags from diffsync.exceptions import DiffClassMismatch, ObjectAlreadyExists, ObjectNotFound, ObjectCrudException @@ -13,8 +13,8 @@ def test_diffsync_default_name_type(generic_diffsync): - assert generic_diffsync.type == "DiffSync" - assert generic_diffsync.name == "DiffSync" + assert generic_diffsync.type == "Adapter" + assert generic_diffsync.name == "Adapter" def test_diffsync_generic_load_is_noop(generic_diffsync): @@ -351,7 +351,7 @@ def test_diffsync_subclass_validation_name_mismatch(): # pylint: disable=unused-variable with pytest.raises(AttributeError) as excinfo: - class BadElementName(DiffSync): + class BadElementName(Adapter): """DiffSync with a DiffSyncModel attribute whose name does not match the modelname.""" dev_class = Device # should be device = Device @@ -365,7 +365,7 @@ def test_diffsync_subclass_validation_missing_top_level(): # pylint: disable=unused-variable with pytest.raises(AttributeError) as excinfo: - class MissingTopLevel(DiffSync): + class MissingTopLevel(Adapter): """DiffSync whose top_level references an attribute that does not exist on the class.""" top_level = ["missing"] @@ -379,7 +379,7 @@ def test_diffsync_subclass_validation_top_level_not_diffsyncmodel(): # pylint: disable=unused-variable with pytest.raises(AttributeError) as excinfo: - class TopLevelNotDiffSyncModel(DiffSync): + class TopLevelNotDiffSyncModel(Adapter): """DiffSync whose top_level references an attribute that is not a DiffSyncModel subclass.""" age = 0 diff --git a/tests/unit/test_diffsync_model_flags.py b/tests/unit/test_diffsync_model_flags.py index 76457cc..a7525d5 100644 --- a/tests/unit/test_diffsync_model_flags.py +++ b/tests/unit/test_diffsync_model_flags.py @@ -18,7 +18,7 @@ import pytest -from diffsync import DiffSync, DiffSyncModel +from diffsync import Adapter, DiffSyncModel from diffsync.enum import DiffSyncModelFlags from diffsync.exceptions import ObjectNotFound @@ -141,7 +141,7 @@ def delete(self): call_order.append(self.name) return super().delete() - class TestBackend(DiffSync): # pylint: disable=missing-class-docstring + class TestBackend(Adapter): # pylint: disable=missing-class-docstring top_level = ["parent"] parent = TestModelParent