Skip to content

Commit

Permalink
Merge pull request #3 from bernhard-hagmann/SIANXKE-414
Browse files Browse the repository at this point in the history
SIANXKE-414: Add pre-commit configuration and checks in pipeline
  • Loading branch information
nezhar authored Nov 8, 2024
2 parents df9576a + a157164 commit a9ec6c2
Show file tree
Hide file tree
Showing 11 changed files with 546 additions and 302 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,9 @@ jobs:
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Lint with flake8
- name: Run linters and format checks
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 './deepcompare' --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 './deepcompare' --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
pre-commit run --all-files
- name: Run tests
run: |
Expand Down
27 changes: 27 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-merge-conflict
- id: end-of-file-fixer
- id: requirements-txt-fixer
- id: trailing-whitespace
args: ["--markdown-linebreak-ext=md"]

- repo: https://github.com/asottile/pyupgrade
rev: v3.17.0
hooks:
- id: pyupgrade
args: ["--py39-plus"]

- repo: https://github.com/asottile/add-trailing-comma
rev: v3.1.0
hooks:
- id: add-trailing-comma

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
1 change: 0 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ deepcompare
[![Test Status](https://github.com/anexia/python-deepcompare/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/anexia/python-deepcompare/actions/workflows/test.yml)
[![Codecov](https://codecov.io/gh/anexia/python-deepcompare/branch/main/graph/badge.svg)](https://codecov.io/gh/anexia/python-deepcompare)

`deepcompare` is a library to deep compare data structures with each other. It can check if two data
structures contain the same data, or if a data structure is a subset of another data structure. The library
`deepcompare` is a library to deep compare data structures with each other. It can check if two data
structures contain the same data, or if a data structure is a subset of another data structure. The library
supports `Sequence` (e.g. `list` or `tuple`) and `Mapping` (e.g. `dict`) types for the deep comparison.

# Installation
Expand All @@ -26,15 +26,15 @@ pip install deepcompare
# Getting started

## How it works
- As a default, the comparison treats all `Sequence` and all `Mapping` types the same (e.g. `(1, 2, 3)` is equal to
- As a default, the comparison treats all `Sequence` and all `Mapping` types the same (e.g. `(1, 2, 3)` is equal to
`[1, 2, 3]`). To enable strict type checks, use the `strict` keyword argument.
- The `partial_compare` method checks if the data structure given as the second parameter is a subset of the data
structure given as the first parameter.
- For `Mapping` types this means, that all keys of the second data structure are also keys on the first data
structure, and the values of the keys are also equal (e.g. `{'a': 1, 'b': 2}` is a subset
structure, and the values of the keys are also equal (e.g. `{'a': 1, 'b': 2}` is a subset
of `{'a': 1, 'b': 2, 'c': 3}`, but `{'a': 1, 'b': 2, 'd': 4}` is not).
- For `Sequence` types this means, that all values of the second data structure are also values of the first data
structure, and the values are in the same order (e.g. `[1, 3, 5]` is a subset
structure, and the values are in the same order (e.g. `[1, 3, 5]` is a subset
of `[1, 2, 3, 4, 5]`, but `[1, 5, 3]` is not).

## Usage
Expand All @@ -55,14 +55,14 @@ deepcompare.compare(
strict=True,
) # returns: False

# test if the second data structure is contained within the first, but
# test if the second data structure is contained within the first, but
# the types to not need to match exactly
deepcompare.partial_compare(
{'key1': (1, 2, 3), 'key2': {'key3': [4, 5, 6]}, 'key4': True},
{'key1': [1, 2], 'key2': {'key3': (4, 6)}},
) # returns: True

# test if the second data structure is contained within the first, and
# test if the second data structure is contained within the first, and
# make sure the types match exactly
deepcompare.partial_compare(
{'key1': (1, 2, 3), 'key2': {'key3': [4, 5, 6]}, 'key4': True},
Expand Down
32 changes: 23 additions & 9 deletions deepcompare/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
from typing import Any

__all__ = [
'compare',
'partial_compare',
"compare",
"partial_compare",
]

_LIST_TYPES = (abc.Sequence, )
_DICT_TYPES = (abc.Mapping, )
_STR_TYPES = (str, bytes, )
_LIST_TYPES = (abc.Sequence,)
_DICT_TYPES = (abc.Mapping,)
_STR_TYPES = (str, bytes)


def compare(haystack: Any, subset: Any, strict: bool = False) -> bool:
Expand Down Expand Up @@ -64,16 +64,25 @@ def _compare(haystack: Any, subset: Any, partial: bool, strict: bool) -> bool:

# if we compare two list types, we check each value of the haystack object to be equal to the
# subset object. if we are working in partial mode, we ignore if the subset list is shorter than the haystack list.
elif isinstance(haystack, _LIST_TYPES) and not isinstance(haystack, _STR_TYPES) \
and isinstance(subset, _LIST_TYPES) and not isinstance(subset, _STR_TYPES):
elif (
isinstance(haystack, _LIST_TYPES)
and not isinstance(haystack, _STR_TYPES)
and isinstance(subset, _LIST_TYPES)
and not isinstance(subset, _STR_TYPES)
):
return _compare_sequence(haystack, subset, partial, strict)

# for any other type, we just compare the two values.
else:
return haystack == subset


def _compare_mapping(haystack: abc.Mapping, subset: abc.Mapping, partial: bool, strict: bool) -> bool:
def _compare_mapping(
haystack: abc.Mapping,
subset: abc.Mapping,
partial: bool,
strict: bool,
) -> bool:
# check if all keys of the subset are also on the haystack object
for key in subset.keys():
if key not in haystack:
Expand All @@ -94,7 +103,12 @@ def _compare_mapping(haystack: abc.Mapping, subset: abc.Mapping, partial: bool,
return True


def _compare_sequence(haystack: abc.Sequence, subset: abc.Sequence, partial: bool, strict: bool) -> bool:
def _compare_sequence(
haystack: abc.Sequence,
subset: abc.Sequence,
partial: bool,
strict: bool,
) -> bool:
haystack_slice = haystack[:]

# if we do not partially compare the lists, we need to check if the lengths of the two lists to compare are
Expand Down
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
-e .

# Development dependencies
pytest>=8.3,<8.4
flake8>=7.1,<7.2
codecov>=2.1,<2.2
pre-commit>=4.0.1,<4.2
pytest>=8.3,<8.4
setuptools>=75
wheel>=0.44
twine>=5.1
wheel>=0.44
42 changes: 21 additions & 21 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,37 @@

from setuptools import find_packages, setup

with open(os.path.join(os.path.dirname(__file__), 'README.md')) as fh:
with open(os.path.join(os.path.dirname(__file__), "README.md")) as fh:
readme = fh.read()

# allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))

setup(
name='deepcompare',
version=os.getenv('PACKAGE_VERSION', '0.0.0').replace('refs/tags/', ''),
name="deepcompare",
version=os.getenv("PACKAGE_VERSION", "0.0.0").replace("refs/tags/", ""),
packages=find_packages(),
include_package_data=True,
license='MIT',
description='A library for deep comparison of data structures consisting of `dict`, `list` and `tuple`.',
license="MIT",
description="A library for deep comparison of data structures consisting of `dict`, `list` and `tuple`.",
long_description=readme,
long_description_content_type='text/markdown',
url='https://github.com/anexia/python-deepcompare',
author='Andreas Stocker',
author_email='[email protected]',
long_description_content_type="text/markdown",
url="https://github.com/anexia/python-deepcompare",
author="Andreas Stocker",
author_email="[email protected]",
install_requires=[],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Topic :: Software Development',
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Software Development",
],
)
Loading

0 comments on commit a9ec6c2

Please sign in to comment.