Skip to content

Remove upper Limit on Packaging #289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ 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@v6"
with:
poetry-version: "1.8.5"
- name: "Linting: black"
run: "poetry run invoke black"
bandit:
Expand All @@ -40,7 +42,9 @@ 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@v6"
with:
poetry-version: "1.8.5"
- name: "Linting: bandit"
run: "poetry run invoke bandit"
needs:
Expand All @@ -53,7 +57,9 @@ 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@v6"
with:
poetry-version: "1.8.5"
- name: "Linting: pydocstyle"
run: "poetry run invoke pydocstyle"
needs:
Expand All @@ -66,7 +72,9 @@ 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@v6"
with:
poetry-version: "1.8.5"
- name: "Linting: flake8"
run: "poetry run invoke flake8"
needs:
Expand All @@ -79,7 +87,9 @@ 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@v6"
with:
poetry-version: "1.8.5"
- name: "Linting: mypy"
run: "poetry run invoke mypy"
needs:
Expand All @@ -92,7 +102,9 @@ 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@v6"
with:
poetry-version: "1.8.5"
- name: "Linting: yamllint"
run: "poetry run invoke yamllint"
needs:
Expand All @@ -103,7 +115,9 @@ 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@v6"
with:
poetry-version: "1.8.5"
- name: "Build Container"
run: "poetry run invoke build"
needs:
Expand All @@ -118,7 +132,9 @@ 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@v6"
with:
poetry-version: "1.8.5"
- name: "Build Container"
run: "poetry run invoke build"
- name: "Linting: Pylint"
Expand All @@ -129,8 +145,8 @@ jobs:
strategy:
fail-fast: true
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
poetry-version: ["1.5.1"]
python-version: ["3.9", "3.10", "3.11"]
poetry-version: ["1.8.5"]
runs-on: "ubuntu-24.04"
env:
PYTHON_VER: "${{ matrix.python-version }}"
Expand All @@ -140,7 +156,7 @@ jobs:
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@3ea5d3ecf382cdcb0c74d4c0ff0629d95fce63c7"
env:
POETRY_VERSION: 1.5.1
POETRY_VERSION: 1.8.5
with:
python-version: "${{ matrix.python-version }}"
poetry-version: "${{ matrix.poetry-version }}"
Expand Down
29 changes: 15 additions & 14 deletions diffsync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,33 @@
See the License for the specific language governing permissions and
limitations under the License.
"""

import sys
from inspect import isclass
from typing import (
Any,
Callable,
ClassVar,
Dict,
List,
Optional,
Set,
Tuple,
Type,
Union,
Any,
Set,
)
from typing_extensions import deprecated

from pydantic import ConfigDict, BaseModel, PrivateAttr
import structlog # type: ignore
from pydantic import BaseModel, ConfigDict, PrivateAttr
from typing_extensions import deprecated

from diffsync.diff import Diff
from diffsync.enum import DiffSyncModelFlags, DiffSyncFlags, DiffSyncStatus
from diffsync.enum import DiffSyncFlags, DiffSyncModelFlags, DiffSyncStatus
from diffsync.exceptions import (
DiffClassMismatch,
ObjectAlreadyExists,
ObjectStoreWrongType,
ObjectNotFound,
ObjectStoreWrongType,
)
from diffsync.helpers import DiffSyncDiffer, DiffSyncSyncer
from diffsync.store import BaseStore
Expand Down Expand Up @@ -69,7 +70,7 @@ class DiffSyncModel(BaseModel):
be included in **at most** one of these three tuples.
"""

_modelname: ClassVar[str] = "diffsyncmodel"
_modelname: ClassVar[str] = "diffsyncmodel" # pylint: disable=used-before-assignment
"""Name of this model, used by DiffSync to store and look up instances of this model or its equivalents.

Lowercase by convention; typically corresponds to the class name, but that is not enforced.
Expand Down Expand Up @@ -133,16 +134,16 @@ def __pydantic_init_subclass__(cls, **kwargs: Any) -> None:
"""
# Make sure that any field referenced by name actually exists on the model
for attr in cls._identifiers:
if attr not in cls.model_fields and not hasattr(cls, attr):
if attr not in cls.model_fields and not hasattr(cls, attr): # pylint: disable=unsupported-membership-test
raise AttributeError(f"_identifiers {cls._identifiers} references missing or un-annotated attr {attr}")
for attr in cls._shortname:
if attr not in cls.model_fields:
if attr not in cls.model_fields: # pylint: disable=unsupported-membership-test
raise AttributeError(f"_shortname {cls._shortname} references missing or un-annotated attr {attr}")
for attr in cls._attributes:
if attr not in cls.model_fields:
if attr not in cls.model_fields: # pylint: disable=unsupported-membership-test
raise AttributeError(f"_attributes {cls._attributes} references missing or un-annotated attr {attr}")
for attr in cls._children.values():
if attr not in cls.model_fields:
if attr not in cls.model_fields: # pylint: disable=unsupported-membership-test
raise AttributeError(f"_children {cls._children} references missing or un-annotated attr {attr}")

# Any given field can only be in one of (_identifiers, _attributes, _children)
Expand Down Expand Up @@ -431,7 +432,7 @@ class Adapter: # pylint: disable=too-many-public-methods
# modelname1 = MyModelClass1
# modelname2 = MyModelClass2

type: Optional[str] = None
type: Optional[str] = None # pylint: disable=used-before-assignment
"""Type of the object, will default to the name of the class if not provided."""

top_level: ClassVar[List[str]] = []
Expand Down Expand Up @@ -557,7 +558,7 @@ def load_from_dict(self, data: Dict) -> None:
# Synchronization between DiffSync instances
# ------------------------------------------------------------------------------

def sync_from( # pylint: disable=too-many-arguments
def sync_from( # pylint: disable=too-many-arguments, too-many-positional-arguments
self,
source: "Adapter",
diff_class: Type[Diff] = Diff,
Expand Down Expand Up @@ -601,7 +602,7 @@ def sync_from( # pylint: disable=too-many-arguments

return diff

def sync_to( # pylint: disable=too-many-arguments
def sync_to( # pylint: disable=too-many-arguments, too-many-positional-arguments
self,
target: "Adapter",
diff_class: Type[Diff] = Diff,
Expand Down
11 changes: 5 additions & 6 deletions diffsync/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
"""

from functools import total_ordering
from typing import Any, Iterator, Optional, Type, List, Dict, Iterable
from typing import Any, Dict, Iterable, Iterator, List, Optional, Type

from .exceptions import ObjectAlreadyExists
from .utils import intersection, OrderedDefaultDict
from .enum import DiffSyncActions
from .exceptions import ObjectAlreadyExists
from .utils import OrderedDefaultDict, intersection

# This workaround is used because we are defining a method called `str` in our class definition, which therefore renders
# the builtin `str` type unusable.
Expand Down Expand Up @@ -105,8 +105,7 @@ def order_children_default(cls, children: Dict[StrType, "DiffElement"]) -> Itera

Since children is already an OrderedDefaultDict, this method is not doing anything special.
"""
for child in children.values():
yield child
yield from children.values()

def summary(self) -> Dict[StrType, int]:
"""Build a dict summary of this Diff and its child DiffElements."""
Expand Down Expand Up @@ -161,7 +160,7 @@ def dict(self) -> Dict[StrType, Dict[StrType, Dict]]:
class DiffElement: # pylint: disable=too-many-instance-attributes
"""DiffElement object, designed to represent a single item/object that may or may not have any diffs."""

def __init__(
def __init__( # pylint: disable=too-many-positional-arguments
self,
obj_type: StrType,
name: StrType,
Expand Down
1 change: 1 addition & 0 deletions diffsync/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
"""

from typing import TYPE_CHECKING, Union, Any

if TYPE_CHECKING:
Expand Down
20 changes: 11 additions & 9 deletions diffsync/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@
See the License for the specific language governing permissions and
limitations under the License.
"""
from collections.abc import Iterable as ABCIterable, Mapping as ABCMapping
from typing import Callable, List, Optional, Tuple, Type, TYPE_CHECKING, Dict, Iterable

from collections.abc import Iterable as ABCIterable
from collections.abc import Mapping as ABCMapping
from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Optional, Tuple, Type

import structlog # type: ignore

from .diff import Diff, DiffElement
from .enum import DiffSyncModelFlags, DiffSyncFlags, DiffSyncStatus, DiffSyncActions
from .exceptions import ObjectNotFound, ObjectNotCreated, ObjectNotUpdated, ObjectNotDeleted, ObjectCrudException
from .enum import DiffSyncActions, DiffSyncFlags, DiffSyncModelFlags, DiffSyncStatus
from .exceptions import ObjectCrudException, ObjectNotCreated, ObjectNotDeleted, ObjectNotFound, ObjectNotUpdated
from .utils import intersection, symmetric_difference

if TYPE_CHECKING: # pragma: no cover
Expand All @@ -35,7 +37,7 @@ class DiffSyncDiffer: # pylint: disable=too-many-instance-attributes
Independent from Diff and DiffElement as those classes are purely data objects, while this stores some state.
"""

def __init__( # pylint: disable=too-many-arguments
def __init__( # pylint: disable=too-many-arguments, too-many-positional-arguments
self,
src_diffsync: "Adapter",
dst_diffsync: "Adapter",
Expand Down Expand Up @@ -114,9 +116,9 @@ def diff_object_list(self, src: List["DiffSyncModel"], dst: List["DiffSyncModel"

combined_dict = {}
for uid in dict_src:
combined_dict[uid] = (dict_src.get(uid), dict_dst.get(uid))
combined_dict[uid] = (dict_src.get(uid), dict_dst.get(uid)) # type: ignore
for uid in dict_dst:
combined_dict[uid] = (dict_src.get(uid), dict_dst.get(uid))
combined_dict[uid] = (dict_src.get(uid), dict_dst.get(uid)) # type: ignore
else:
# In the future we might support set, etc...
raise TypeError(f"Type combination {type(src)}/{type(dst)} is not supported... for now")
Expand All @@ -137,7 +139,7 @@ def diff_object_list(self, src: List["DiffSyncModel"], dst: List["DiffSyncModel"

@staticmethod
def validate_objects_for_diff(
object_pairs: Iterable[Tuple[Optional["DiffSyncModel"], Optional["DiffSyncModel"]]]
object_pairs: Iterable[Tuple[Optional["DiffSyncModel"], Optional["DiffSyncModel"]]],
) -> None:
"""Check whether all DiffSyncModels in the given dictionary are valid for comparison to one another.

Expand Down Expand Up @@ -285,7 +287,7 @@ class DiffSyncSyncer: # pylint: disable=too-many-instance-attributes
Independent from DiffSync and DiffSyncModel as those classes are purely data objects, while this stores some state.
"""

def __init__( # pylint: disable=too-many-arguments
def __init__( # pylint: disable=too-many-arguments, too-many-positional-arguments
self,
diff: Diff,
src_diffsync: "Adapter",
Expand Down
1 change: 1 addition & 0 deletions diffsync/store/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""BaseStore module."""

from typing import Dict, List, Tuple, Type, Union, TYPE_CHECKING, Optional, Set, Any
import structlog # type: ignore

Expand Down
11 changes: 6 additions & 5 deletions diffsync/store/redis.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""RedisStore module."""

import copy
import uuid
from pickle import loads, dumps # nosec
from typing import List, Type, Union, TYPE_CHECKING, Set, Any, Optional, Dict
from pickle import dumps, loads # nosec
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Type, Union

try:
from redis import Redis
Expand All @@ -11,7 +12,7 @@
print("Redis is not installed. Have you installed diffsync with redis extra? `pip install diffsync[redis]`")
raise ierr

from diffsync.exceptions import ObjectNotFound, ObjectStoreException, ObjectAlreadyExists
from diffsync.exceptions import ObjectAlreadyExists, ObjectNotFound, ObjectStoreException
from diffsync.store import BaseStore

if TYPE_CHECKING:
Expand All @@ -23,7 +24,7 @@
class RedisStore(BaseStore):
"""RedisStore class."""

def __init__(
def __init__( # pylint: disable=too-many-arguments
self,
*args: Any,
store_id: Optional[str] = None,
Expand Down Expand Up @@ -167,7 +168,7 @@ def add(self, *, obj: "DiffSyncModel") -> None:

existing_obj_binary = self._store.get(object_key)
if existing_obj_binary:
existing_obj = loads(existing_obj_binary)
existing_obj = loads(existing_obj_binary) # nosec
existing_obj_dict = existing_obj.dict()

if existing_obj_dict != obj.dict():
Expand Down
1 change: 1 addition & 0 deletions diffsync/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
"""

from collections import OrderedDict
from typing import Iterator, List, Dict, Optional, TypeVar, Callable, Generic

Expand Down
1 change: 1 addition & 0 deletions examples/01-multiple-data-sources/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
"""

from typing import List, Optional
from diffsync import DiffSyncModel

Expand Down
3 changes: 2 additions & 1 deletion examples/02-callback-function/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
"""

import random

from diffsync import Adapter, DiffSyncModel
Expand All @@ -40,7 +41,7 @@ class Adapter1(Adapter):
def load(self, count): # pylint: disable=arguments-differ
"""Construct Numbers from 1 to count."""
for i in range(count):
self.add(Number(number=(i + 1)))
self.add(Number(number=i + 1))


class Adapter2(Adapter):
Expand Down
Loading