Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-dirty-equals for 
openSUSE:Factory checked in at 2022-11-14 14:28:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-dirty-equals (Old)
 and      /work/SRC/openSUSE:Factory/.python-dirty-equals.new.1597 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-dirty-equals"

Mon Nov 14 14:28:59 2022 rev:3 rq:1035577 version:0.5.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-dirty-equals/python-dirty-equals.changes  
2022-09-01 22:11:54.352364720 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-dirty-equals.new.1597/python-dirty-equals.changes
        2022-11-14 14:29:10.507022854 +0100
@@ -1,0 +2,10 @@
+Thu Nov 10 15:18:24 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com>
+
+-Update to version 0.5.0
+ *Document how the dirty __eq__ is called by @Marco-Kaulea in #41
+ *Make IsNow relative to current moment of time by @hyzyla in #40
+ *correct version in pyproject.toml, #46
+ *feat Add IsIP by @osintalex in #43
+ *Remove Poetry and transition to hatchling, #49 
+
+-------------------------------------------------------------------

Old:
----
  dirty-equals-0.4.tar.gz

New:
----
  dirty-equals-0.5.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-dirty-equals.spec ++++++
--- /var/tmp/diff_new_pack.D3hD8s/_old  2022-11-14 14:29:11.679028279 +0100
+++ /var/tmp/diff_new_pack.D3hD8s/_new  2022-11-14 14:29:11.683028297 +0100
@@ -17,13 +17,14 @@
 
 
 Name:           python-dirty-equals
-Version:        0.4
+Version:        0.5.0
 Release:        0
 Summary:        Doing dirty (but useful) things with equals
 License:        MIT
 URL:            https://dirty-equals.helpmanual.io
 Source:         
https://github.com/samuelcolvin/dirty-equals/archive/refs/tags/v%{version}.tar.gz#/dirty-equals-%{version}.tar.gz
 BuildRequires:  %{python_module base >= 3.7}
+BuildRequires:  %{python_module hatchling}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module poetry-core}
 BuildRequires:  %{python_module pytest-mock}

++++++ dirty-equals-0.4.tar.gz -> dirty-equals-0.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/.github/workflows/ci.yml 
new/dirty-equals-0.5.0/.github/workflows/ci.yml
--- old/dirty-equals-0.4/.github/workflows/ci.yml       2022-04-28 
17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/.github/workflows/ci.yml     2022-08-30 
20:44:09.000000000 +0200
@@ -11,12 +11,22 @@
 
 jobs:
   test:
-    name: test py-${{ matrix.python-version }} on ${{ matrix.os }}
+    name: test ${{ matrix.python-version }} on ${{ matrix.os }}
     strategy:
       fail-fast: false
       matrix:
         os: [ubuntu, macos]
-        python-version: ['3.7', '3.8', '3.9', '3.10', 'pypy-3.7', 'pypy-3.8', 
'pypy-3.9']
+        python-version: ['3.7', '3.8', '3.9', '3.10']
+        # test 3.11-dev and pypy on ubuntu only to speed up CI, no reason why 
macos X pypy should fail separately
+        include:
+          - os: 'ubuntu'
+            python-version: '3.11-dev'
+          - os: 'ubuntu'
+            python-version: 'pypy-3.7'
+          - os: 'ubuntu'
+            python-version: 'pypy-3.8'
+          - os: 'ubuntu'
+            python-version: 'pypy-3.9'
 
     runs-on: ${{ matrix.os }}-latest
 
@@ -25,30 +35,27 @@
       OS: ${{ matrix.os }}
 
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
 
     - name: set up python
-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v4
       with:
         python-version: ${{ matrix.python-version }}
 
-    - uses: actions/cache@v2
+    - uses: actions/cache@v3
       id: cache
       with:
         path: ${{ env.pythonLocation }}
-        key: ${{ runner.os }}-${{ env.pythonLocation }}-${{ 
hashFiles('pyproject.toml') }}-${{ hashFiles('tests/requirements.txt') }}
+        key: ${{ runner.os }}-${{ env.pythonLocation }}-${{ 
hashFiles('pyproject.toml') }}-${{ hashFiles('requirements/tests.txt') }}
 
-    - run: pip install -r tests/requirements.txt
-#      if: steps.cache.outputs.cache-hit != 'true'  # breaks pypy tests
-
-    - run: poetry install
-#      if: steps.cache.outputs.cache-hit != 'true'  # breaks pypy tests
+    - run: pip install -r requirements/tests.txt -r requirements/pyproject.txt
+      if: steps.cache.outputs.cache-hit != 'true'
 
     - run: make test
 
     - run: coverage xml
 
-    - uses: codecov/codecov-action@v2.1.0
+    - uses: codecov/codecov-action@v3
       with:
         file: ./coverage.xml
         env_vars: PYTHON,OS
@@ -57,36 +64,37 @@
     runs-on: ubuntu-latest
 
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
 
-    - uses: actions/setup-python@v1
+    - uses: actions/setup-python@v4
       with:
         python-version: '3.10'
 
-    - uses: actions/cache@v2
+    - uses: actions/cache@v3
       id: cache
       with:
         path: ${{ env.pythonLocation }}
-        key: ${{ hashFiles('tests/requirements-linting.txt') }}
+        key: ${{ env.pythonLocation }}-${{ 
hashFiles('requirements/linting.txt') }}-${{ hashFiles('pyproject.toml') }}
 
-    - run: pip install -r tests/requirements-linting.txt
+    - run: pip install -r requirements/linting.txt
       if: steps.cache.outputs.cache-hit != 'true'
 
-    - run: make lint
-    - run: make mypy
+    - uses: pre-commit/action@v3.0.0
+      with:
+        extra_args: --all-files
 
   docs:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
 
     - name: set up python
-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v4
       with:
         python-version: '3.10'
 
     - name: install
-      run: pip install -r docs/requirements.txt
+      run: pip install -r requirements/docs.txt
 
     - name: install mkdocs-material-insiders
       if: github.ref == 'refs/heads/main' || startsWith(github.ref, 
'refs/tags/')
@@ -98,7 +106,7 @@
       run: mkdocs build --strict
 
     - name: store docs site
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v3
       with:
         name: docs
         path: site
@@ -112,30 +120,42 @@
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
 
       - name: set up python
-        uses: actions/setup-python@v2
+        uses: actions/setup-python@v4
         with:
           python-version: '3.9'
 
       - name: get docs
-        uses: actions/download-artifact@v2
+        uses: actions/download-artifact@v3
         with:
           name: docs
           path: site
 
-      - name: set version
-        run: VERSION_PATH=dirty_equals python <(curl -Ls 
https://bit.ly/set__version__)
+      - name: install
+        run: pip install -U twine build packaging
+
+      - name: check version
+        id: check-version
+        run: python <(curl -Ls 
https://gist.githubusercontent.com/samuelcolvin/4e1ad439c5489e8d6478cdee3eb952ef/raw/check_version.py)
+        env:
+          VERSION_PATH: 'dirty_equals/version.py'
+
+      - name: build
+        run: python -m build
 
-      - run: pip install poetry==1.2.0a2 poetry-version-plugin
+      - run: twine check dist/*
 
-      - run: poetry publish --build
+      - name: upload to pypi
+        run: twine upload dist/*
         env:
-          POETRY_PYPI_TOKEN_PYPI: ${{ secrets.pypi_token }}
+          TWINE_USERNAME: __token__
+          TWINE_PASSWORD: ${{ secrets.pypi_token }}
 
       - name: publish docs
-        uses: JamesIves/github-pages-deploy-action@v4.2.5
+        uses: JamesIves/github-pages-deploy-action@v4
+        if: '!fromJSON(steps.check-version.outputs.IS_PRERELEASE)'
         with:
           branch: gh-pages
           folder: site
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/.pre-commit-config.yaml 
new/dirty-equals-0.5.0/.pre-commit-config.yaml
--- old/dirty-equals-0.4/.pre-commit-config.yaml        2022-04-28 
17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/.pre-commit-config.yaml      2022-08-30 
20:44:09.000000000 +0200
@@ -4,7 +4,10 @@
   hooks:
   - id: check-yaml
     args: ['--unsafe']
+  - id: check-toml
   - id: end-of-file-fixer
+  - id: trailing-whitespace
+  - id: check-added-large-files
 
 - repo: local
   hooks:
@@ -13,8 +16,10 @@
     entry: make lint
     types: [python]
     language: system
+    pass_filenames: false
   - id: mypy
     name: Mypy
     entry: make mypy
     types: [python]
     language: system
+    pass_filenames: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/Makefile 
new/dirty-equals-0.5.0/Makefile
--- old/dirty-equals-0.4/Makefile       2022-04-28 17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/Makefile     2022-08-30 20:44:09.000000000 +0200
@@ -4,10 +4,7 @@
 
 .PHONY: install
 install:
-       pip install -r tests/requirements.txt
-       pip install -r tests/requirements-linting.txt
-       pip install -r docs/requirements.txt
-       poetry install
+       pip install -r requirements/all.txt
        pre-commit install
 
 .PHONY: format
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/README.md 
new/dirty-equals-0.5.0/README.md
--- old/dirty-equals-0.4/README.md      2022-04-28 17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/README.md    2022-08-30 20:44:09.000000000 +0200
@@ -74,17 +74,17 @@
 
 *dirty-equals* can do so much more than that, for example:
 
-* 
[`IsPartialDict`](https://dirty-equals.helpmanual.io/types/dict/#dirty_equals.IsPartialDict)
 
+* 
[`IsPartialDict`](https://dirty-equals.helpmanual.io/types/dict/#dirty_equals.IsPartialDict)
   lets you compare a subset of a dictionary
-* 
[`IsStrictDict`](https://dirty-equals.helpmanual.io/types/dict/#dirty_equals.IsStrictDict)
 
+* 
[`IsStrictDict`](https://dirty-equals.helpmanual.io/types/dict/#dirty_equals.IsStrictDict)
   lets you confirm order in a dictionary
-* 
[`IsList`](https://dirty-equals.helpmanual.io/types/sequence/#dirty_equals.IsList)
 and 
+* 
[`IsList`](https://dirty-equals.helpmanual.io/types/sequence/#dirty_equals.IsList)
 and
   
[`IsTuple`](https://dirty-equals.helpmanual.io/types/sequence/#dirty_equals.IsTuple)
   lets you compare partial lists and tuples, with or without order constraints
 * nesting any of these types inside any others
-* 
[`IsInstance`](https://dirty-equals.helpmanual.io/types/other/#dirty_equals.IsInstance)
 
+* 
[`IsInstance`](https://dirty-equals.helpmanual.io/types/other/#dirty_equals.IsInstance)
   lets you simply confirm the type of an object
-* You can even use [boolean 
operators](https://dirty-equals.helpmanual.io/usage/#boolean-logic) 
+* You can even use [boolean 
operators](https://dirty-equals.helpmanual.io/usage/#boolean-logic)
   `|` and `&` to combine multiple conditions
 * and much more...
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/dirty_equals/__init__.py 
new/dirty-equals-0.5.0/dirty_equals/__init__.py
--- old/dirty-equals-0.4/dirty_equals/__init__.py       2022-04-28 
17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/dirty_equals/__init__.py     2022-08-30 
20:44:09.000000000 +0200
@@ -18,9 +18,10 @@
     IsPositiveFloat,
     IsPositiveInt,
 )
-from ._other import FunctionCheck, IsJson, IsUUID
+from ._other import FunctionCheck, IsIP, IsJson, IsUUID
 from ._sequence import Contains, HasLen, IsList, IsListOrTuple, IsTuple
 from ._strings import IsAnyStr, IsBytes, IsStr
+from .version import VERSION
 
 __all__ = (
     # base
@@ -69,6 +70,7 @@
     'FunctionCheck',
     'IsJson',
     'IsUUID',
+    'IsIP',
     # strings
     'IsStr',
     'IsBytes',
@@ -77,4 +79,4 @@
     '__version__',
 )
 
-__version__ = '0.0.dev0'
+__version__ = VERSION
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/dirty_equals/_datetime.py 
new/dirty-equals-0.5.0/dirty_equals/_datetime.py
--- old/dirty-equals-0.4/dirty_equals/_datetime.py      2022-04-28 
17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/dirty_equals/_datetime.py    2022-08-30 
20:44:09.000000000 +0200
@@ -163,13 +163,12 @@
 
             tz = pytz.timezone(tz)
 
-        if tz is not None:
-            now = datetime.utcnow().replace(tzinfo=timezone.utc).astimezone(tz)
-        else:
-            now = datetime.now()
+        self.tz = tz
+
+        approx = self._get_now()
 
         super().__init__(
-            approx=now,
+            approx=approx,
             delta=delta,
             unix_number=unix_number,
             iso_string=iso_string,
@@ -179,6 +178,20 @@
         if tz is not None:
             self._repr_kwargs['tz'] = tz
 
+    def _get_now(self) -> datetime:
+        if self.tz is None:
+            return datetime.now()
+        else:
+            return 
datetime.utcnow().replace(tzinfo=timezone.utc).astimezone(self.tz)
+
+    def prepare(self, other: Any) -> datetime:
+
+        # update approx for every comparing, to check if other value is dirty 
equal
+        # to current moment of time
+        self.approx = self._get_now()
+
+        return super().prepare(other)
+
 
 class IsDate(IsNumeric[date]):
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/dirty_equals/_other.py 
new/dirty-equals-0.5.0/dirty_equals/_other.py
--- old/dirty-equals-0.4/dirty_equals/_other.py 2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/dirty_equals/_other.py       2022-08-30 
20:44:09.000000000 +0200
@@ -1,9 +1,10 @@
 import json
-from typing import Any, Callable, TypeVar, overload
+from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network, 
ip_network
+from typing import Any, Callable, Optional, TypeVar, Union, overload
 from uuid import UUID
 
 from ._base import DirtyEquals
-from ._utils import plain_repr
+from ._utils import Omit, plain_repr
 
 try:
     from typing import Literal
@@ -145,3 +146,60 @@
 
     def equals(self, other: Any) -> bool:
         return self.func(other)
+
+
+IP = TypeVar('IP', IPv4Address, IPv4Network, IPv6Address, IPv6Network, 
Union[str, int, bytes])
+
+
+class IsIP(DirtyEquals[IP]):
+    """
+    A class that checks if a value is a valid IP address, optionally checking 
IP version, netmask.
+    """
+
+    def __init__(self, *, version: Literal[None, 4, 6] = None, netmask: 
Optional[str] = None):
+        """
+        Args:
+            version: The version of the IP to check, if omitted, versions 4 
and 6 are both accepted.
+            netmask: The netmask of the IP to check, if omitted, any netmask 
is accepted. Requires version.
+
+        ```py title="IsIP"
+        from ipaddress import IPv4Address, IPv6Address, IPv4Network
+        from dirty_equals import IsIP
+
+        assert '179.27.154.96' == IsIP
+        assert '179.27.154.96' == IsIP(version=4)
+        assert '2001:0db8:0a0b:12f0:0000:0000:0000:0001' == IsIP(version=6)
+        assert IPv4Address('127.0.0.1') == IsIP
+        assert IPv4Network('43.48.0.0/12') == IsIP
+        assert IPv6Address('::eeff:ae3f:d473') == IsIP
+        assert '54.43.53.219/10' == IsIP(version=4, netmask='255.192.0.0')
+        assert '54.43.53.219/10' == IsIP(version=4, netmask=4290772992)
+        assert '::ffff:aebf:d473/12' == IsIP(version=6, netmask='fff0::')
+        assert 3232235521 == IsIP
+        ```
+        """
+        self.version = version
+        if netmask and not self.version:
+            raise TypeError('To check the netmask you must specify the IP 
version')
+        self.netmask = netmask
+        super().__init__(version=version or Omit, netmask=netmask or Omit)
+
+    def equals(self, other: Any) -> bool:
+
+        if isinstance(other, (IPv4Network, IPv6Network)):
+            ip = other
+        elif isinstance(other, (str, bytes, int, IPv4Address, IPv6Address)):
+            ip = ip_network(other, strict=False)
+        else:
+            return False
+
+        if self.version:
+            if self.netmask:
+                version_check = self.version == ip.version
+                address_format = {4: IPv4Address, 6: IPv6Address}[self.version]
+                netmask_check = int(address_format(self.netmask)) == 
int(ip.netmask)
+                return version_check and netmask_check
+            elif self.version != ip.version:
+                return False
+
+        return True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/dirty_equals/version.py 
new/dirty-equals-0.5.0/dirty_equals/version.py
--- old/dirty-equals-0.4/dirty_equals/version.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/dirty-equals-0.5.0/dirty_equals/version.py      2022-08-30 
20:44:09.000000000 +0200
@@ -0,0 +1 @@
+VERSION = '0.5.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/docs/index.md 
new/dirty-equals-0.5.0/docs/index.md
--- old/dirty-equals-0.4/docs/index.md  2022-04-28 17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/docs/index.md        2022-08-30 20:44:09.000000000 
+0200
@@ -44,7 +44,7 @@
 ```
 
 1. This `assert` will pass since `1` is indeed positive, so the result of `1 
== IsPositive` is `True`.
-2. This will fail (raise a `AssertionError`) since `-2` is not positive, 
+2. This will fail (raise a `AssertionError`) since `-2` is not positive,
    so the result of `-2 == IsPositive` is `False`.
 
 **Not that interesting yet!**, but consider the following unit test code using 
**dirty-equals**:
@@ -53,7 +53,7 @@
 title="More Powerful Usage"
 from dirty_equals import IsJson, IsNow, IsPositiveInt, IsStr
 
-def test_user_endpoint(client: 'HttpClient', db_conn: 'Database'): 
+def test_user_endpoint(client: 'HttpClient', db_conn: 'Database'):
    client.pust('/users/create/', data=...)
 
    user_data = db_conn.fetchrow('select * from users')
@@ -68,21 +68,21 @@
 
 1. We don't actually care what the `id` is, just that it's present, it's an 
`int` and it's positive.
 2. We can use a normal key and value here since we know exactly what value 
`username` should have before we test it.
-3. `avatar_file` is a string, but we don't know all of the string before the 
`assert`, 
+3. `avatar_file` is a string, but we don't know all of the string before the 
`assert`,
    just the format (regex) it should match.
 4. `settings_json` is a `JSON` string, but it's simpler and more robust to 
confirm it represents a particular python
    object rather than compare strings.
 5. `created_at` is a `datetime`, although we don't know (or care) about its 
exact value;
    since the user was just created we know it must be close to now. `delta` is 
optional, it defaults to 2 seconds.
 
-Without **dirty-equals**, you'd have to compare individual fields and/or 
modify some fields before comparison 
+Without **dirty-equals**, you'd have to compare individual fields and/or 
modify some fields before comparison
 - the test would not be declarative or as clear.
 
 **dirty-equals** can do so much more than that, for example:
 
 * [`IsPartialDict`][dirty_equals.IsPartialDict] lets you compare a subset of a 
dictionary
 * [`IsStrictDict`][dirty_equals.IsStrictDict] lets you confirm order in a 
dictionary
-* [`IsList`][dirty_equals.IsList] and [`IsTuple`][dirty_equals.IsTuple] lets 
you compare partial lists and tuples, 
+* [`IsList`][dirty_equals.IsList] and [`IsTuple`][dirty_equals.IsTuple] lets 
you compare partial lists and tuples,
   with or without order constraints
 * nesting any of these types inside any others
 * [`IsInstance`][dirty_equals.IsInstance] lets you simply confirm the type of 
an object
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/docs/internals.md 
new/dirty-equals-0.5.0/docs/internals.md
--- old/dirty-equals-0.4/docs/internals.md      1970-01-01 01:00:00.000000000 
+0100
+++ new/dirty-equals-0.5.0/docs/internals.md    2022-08-30 20:44:09.000000000 
+0200
@@ -0,0 +1,20 @@
+# Internals
+## How the magic of `DirtyEquals.__eq__` works?
+When you call `x == y`, Python first calls `x.__eq__(y)`. This would not help 
us
+much, because we would have to keep an eye on order of the arguments when
+comparing to `DirtyEquals` objects. But that's where were another feature of
+Python comes in.
+
+When `x.__eq__(y)` returns the `NotImplemented` object, then Python will try to
+call `y.__eq__(x)`. Objects in the standard library return that value when they
+don't know how to compare themselves to objects of `type(y)` (Without checking
+the C source I can't be certain if this assumption holds for all classes, but 
it
+works for all the basic ones).
+In 
[`pathlib.PurePath`](https://github.com/python/cpython/blob/aebbd7579a421208f48dd6884b67dbd3278b71ad/Lib/pathlib.py#L751)
+you can see an example how that is implemented in Python.
+
+> By default, object implements `__eq__()` by using `is`,
+> returning `NotImplemented` in the case of a false comparison:
+> `True if x is y else NotImplemented`.
+
+See the Python documentation for more information 
([`object.__eq__`](https://docs.python.org/3/reference/datamodel.html#object.__eq__)).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/docs/plugins.py 
new/dirty-equals-0.5.0/docs/plugins.py
--- old/dirty-equals-0.4/docs/plugins.py        2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/docs/plugins.py      2022-08-30 20:44:09.000000000 
+0200
@@ -22,11 +22,13 @@
     """
     Run the examples tests.
     """
-    if not pytest:
+    try:
+        run_pytest = getattr('pytest', 'main')
+    except AttributeError:
         logger.info('pytest not installed, skipping examples tests')
     else:
         logger.info('running examples tests...')
-        return_code = pytest.main(['-q', '-p', 'no:sugar', 
'tests/test_docs.py'])
+        return_code = run_pytest(['-q', '-p', 'no:sugar', 
'tests/test_docs.py'])
         if return_code != 0:
             logger.warning('examples tests failed')
 
@@ -38,7 +40,7 @@
 def remove_files(files: Files) -> Files:
     to_remove = []
     for file in files:
-        if file.src_path in {'plugins.py', 'requirements.txt'}:
+        if file.src_path in {'plugins.py'}:
             to_remove.append(file)
         elif file.src_path.startswith('__pycache__/'):
             to_remove.append(file)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/docs/requirements.txt 
new/dirty-equals-0.5.0/docs/requirements.txt
--- old/dirty-equals-0.4/docs/requirements.txt  2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/docs/requirements.txt        1970-01-01 
01:00:00.000000000 +0100
@@ -1,7 +0,0 @@
-black==22.3.0
-griffe==0.17.0
-mkdocs==1.3.0
-mkdocs-autorefs==0.4.1
-mkdocs-material==8.2.9
-mkdocs-simple-hooks==0.1.5
-mkdocstrings[python]==0.18.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/docs/types/custom.md 
new/dirty-equals-0.5.0/docs/types/custom.md
--- old/dirty-equals-0.4/docs/types/custom.md   2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/docs/types/custom.md 2022-08-30 20:44:09.000000000 
+0200
@@ -27,12 +27,12 @@
 assert 3 == IsEven | IsOneOf(3)
 ```
 
-There are a few advantages of inheriting from 
[`DirtyEquals`][dirty_equals.DirtyEquals] compared to just 
+There are a few advantages of inheriting from 
[`DirtyEquals`][dirty_equals.DirtyEquals] compared to just
 implementing your own class with an `__eq__` method:
 
 1. `TypeError` and `ValueError` in `equals` are caught and result in a 
not-equals result.
 2. A useful `__repr__` is generated, and modified if the `==` operation 
returns `True`,
    see [pytest compatibility](../usage.md#__repr__-and-pytest-compatibility)
 3. [boolean logic](../usage.md#boolean-logic) works out of the box
-4. [Uninitialised usage](../usage.md#initialised-vs-class-comparison) 
+4. [Uninitialised usage](../usage.md#initialised-vs-class-comparison)
    (`IsEven` rather than `IsEven()`) works out of the box
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/docs/types/datetime.md 
new/dirty-equals-0.5.0/docs/types/datetime.md
--- old/dirty-equals-0.4/docs/types/datetime.md 2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/docs/types/datetime.md       2022-08-30 
20:44:09.000000000 +0200
@@ -11,12 +11,12 @@
 
 * `enforce_tz=True` (the default):
     * if the datetime wrapped by `IsDatetime` is timezone naive, the compared 
value must also be timezone naive.
-    * if the datetime wrapped by `IsDatetime` has a timezone, the compared 
value must have a 
+    * if the datetime wrapped by `IsDatetime` has a timezone, the compared 
value must have a
       timezone with the same offset.
 * `enforce_tz=False`:
-    * if the datetime wrapped by `IsDatetime` is timezone naive, the compared 
value can either be naive or have a 
+    * if the datetime wrapped by `IsDatetime` is timezone naive, the compared 
value can either be naive or have a
       timezone all that matters is the datetime values match.
-    * if the datetime wrapped by `IsDatetime` has a timezone, the compared 
value needs to represent the same point in 
+    * if the datetime wrapped by `IsDatetime` has a timezone, the compared 
value needs to represent the same point in
       time - either way it must have a timezone.
 
 Example
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/docs/types/other.md 
new/dirty-equals-0.5.0/docs/types/other.md
--- old/dirty-equals-0.4/docs/types/other.md    2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/docs/types/other.md  2022-08-30 20:44:09.000000000 
+0200
@@ -11,3 +11,5 @@
 ::: dirty_equals.AnyThing
 
 ::: dirty_equals.IsOneOf
+
+::: dirty_equals.IsIP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/docs/usage.md 
new/dirty-equals-0.5.0/docs/usage.md
--- old/dirty-equals-0.4/docs/usage.md  2022-04-28 17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/docs/usage.md        2022-08-30 20:44:09.000000000 
+0200
@@ -1,7 +1,7 @@
 ## Boolean Logic
 
-*dirty-equals* types can be combined based on either `&` 
-(and, all checks must be `True` for the combined check to be `True`) or `|` 
+*dirty-equals* types can be combined based on either `&`
+(and, all checks must be `True` for the combined check to be `True`) or `|`
 (or, any check can be `True` for the combined check to be `True`).
 
 Types can also be inverted using the `~` operator, this is equivalent to using 
`!=` instead of `==`.
@@ -72,7 +72,7 @@
 assert repr(v) == '42'
 ```
 
-This black magic is designed to make the output of pytest when asserts on 
large objects fail as simple as 
+This black magic is designed to make the output of pytest when asserts on 
large objects fail as simple as
 possible to read.
 
 Consider the following unit test:
@@ -100,7 +100,7 @@
     }
 ```
 
-1. For simplicity we've hardcoded `id` here, but in a test it could be any 
positive int, 
+1. For simplicity we've hardcoded `id` here, but in a test it could be any 
positive int,
    hence why we need `IsPositiveInt()`
 
 Here's an except from the output of `pytest -vv` show the error details:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/mkdocs.yml 
new/dirty-equals-0.5.0/mkdocs.yml
--- old/dirty-equals-0.4/mkdocs.yml     2022-04-28 17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/mkdocs.yml   2022-08-30 20:44:09.000000000 +0200
@@ -44,6 +44,7 @@
       - types/boolean.md
       - types/other.md
       - types/custom.md
+  - Internals: internals.md
 
 markdown_extensions:
   - toc:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/poetry.lock 
new/dirty-equals-0.5.0/poetry.lock
--- old/dirty-equals-0.4/poetry.lock    2022-04-28 17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/poetry.lock  1970-01-01 01:00:00.000000000 +0100
@@ -1,30 +0,0 @@
-[[package]]
-name = "pytz"
-version = "2022.1"
-description = "World timezone definitions, modern and historical"
-category = "main"
-optional = false
-python-versions = "*"
-
-[[package]]
-name = "typing-extensions"
-version = "4.0.1"
-description = "Backported and Experimental Type Hints for Python 3.6+"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[metadata]
-lock-version = "1.1"
-python-versions = "^3.7.0"
-content-hash = 
"22731d3dcd696281e4beb78ee4fd91786321b3b5e4787b4ab44489f501e55538"
-
-[metadata.files]
-pytz = [
-    {file = "pytz-2022.1-py2.py3-none-any.whl", hash = 
"sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"},
-    {file = "pytz-2022.1.tar.gz", hash = 
"sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"},
-]
-typing-extensions = [
-    {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = 
"sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
-    {file = "typing_extensions-4.0.1.tar.gz", hash = 
"sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
-]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/poetry.toml 
new/dirty-equals-0.5.0/poetry.toml
--- old/dirty-equals-0.4/poetry.toml    2022-04-28 17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/poetry.toml  1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-[virtualenvs]
-create = false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/pyproject.toml 
new/dirty-equals-0.5.0/pyproject.toml
--- old/dirty-equals-0.4/pyproject.toml 2022-04-28 17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/pyproject.toml       2022-08-30 20:44:09.000000000 
+0200
@@ -1,46 +1,51 @@
-[tool.poetry]
-name = "dirty-equals"
-version = "0"
-description = "Doing dirty (but extremely useful) things with equals."
-authors = ["Samuel Colvin <s...@muelcolvin.com>"]
-readme = "README.md"
-homepage = "https://dirty-equals.helpmanual.io";
-repository = "https://github.com/samuelcolvin/dirty-equals";
-license = "MIT"
-classifiers = [
-    "Development Status :: 4 - Beta",
-    "Framework :: Pytest",
-    "Intended Audience :: Developers",
-    "Intended Audience :: Education",
-    "Intended Audience :: Information Technology",
-    "Intended Audience :: Science/Research",
-    "Intended Audience :: System Administrators",
-    "Operating System :: Unix",
-    "Operating System :: POSIX :: Linux",
-    "Environment :: Console",
-    "Environment :: MacOS X",
-    "License :: OSI Approved :: MIT License",
-    "Programming Language :: Python :: 3 :: Only",
-    "Programming Language :: Python :: 3.7",
-    "Programming Language :: Python :: 3.8",
-    "Programming Language :: Python :: 3.9",
-    "Programming Language :: Python :: 3.10",
-    "Topic :: Software Development :: Libraries :: Python Modules",
-    "Topic :: Internet",
-    "Typing :: Typed",
-]
+[build-system]
+requires = ['hatchling']
+build-backend = 'hatchling.build'
 
-[tool.poetry.dependencies]
-python = "^3.7.0"
-typing-extensions = {version = "^4.0.1", python = "<3.8"}
-pytz = ">=2021.3"
+[tool.hatch.version]
+path = 'dirty_equals/version.py'
 
-[build-system]
-requires = ["poetry-core"]
-build-backend = "poetry.core.masonry.api"
+[project]
+name = 'dirty-equals'
+description = 'Doing dirty (but extremely useful) things with equals.'
+authors = [{name = 'Samuel Colvin', email = 's...@muelcolvin.com'}]
+license = {file = 'LICENSE'}
+readme = 'README.md'
+classifiers = [
+    'Development Status :: 4 - Beta',
+    'Framework :: Pytest',
+    'Intended Audience :: Developers',
+    'Intended Audience :: Education',
+    'Intended Audience :: Information Technology',
+    'Intended Audience :: Science/Research',
+    'Intended Audience :: System Administrators',
+    'Operating System :: Unix',
+    'Operating System :: POSIX :: Linux',
+    'Environment :: Console',
+    'Environment :: MacOS X',
+    'License :: OSI Approved :: MIT License',
+    'Programming Language :: Python :: 3 :: Only',
+    'Programming Language :: Python :: 3.7',
+    'Programming Language :: Python :: 3.8',
+    'Programming Language :: Python :: 3.9',
+    'Programming Language :: Python :: 3.10',
+    'Topic :: Software Development :: Libraries :: Python Modules',
+    'Topic :: Internet',
+    'Typing :: Typed',
+]
+requires-python = '>=3.7'
+dependencies = [
+    'typing-extensions>=4.0.1',
+    'pytz>=2021.3',
+]
+dynamic = ['version']
 
-[tool.poetry-version-plugin]
-source = "init"
+[project.urls]
+Homepage = 'https://github.com/samuelcolvin/dirty-equals'
+Documentation = 'https://dirty-equals.helpmanual.io'
+Funding = 'https://github.com/sponsors/samuelcolvin'
+Source = 'https://github.com/samuelcolvin/dirty-equals'
+Changelog = 'https://github.com/samuelcolvin/dirty-equals/releases'
 
 [tool.pytest.ini_options]
 testpaths = "tests"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/requirements/all.txt 
new/dirty-equals-0.5.0/requirements/all.txt
--- old/dirty-equals-0.4/requirements/all.txt   1970-01-01 01:00:00.000000000 
+0100
+++ new/dirty-equals-0.5.0/requirements/all.txt 2022-08-30 20:44:09.000000000 
+0200
@@ -0,0 +1,4 @@
+-r ./docs.txt
+-r ./linting.txt
+-r ./tests.txt
+-r ./pyproject.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/requirements/docs.in 
new/dirty-equals-0.5.0/requirements/docs.in
--- old/dirty-equals-0.4/requirements/docs.in   1970-01-01 01:00:00.000000000 
+0100
+++ new/dirty-equals-0.5.0/requirements/docs.in 2022-08-30 20:44:09.000000000 
+0200
@@ -0,0 +1,5 @@
+black
+mkdocs
+mkdocs-material
+mkdocs-simple-hooks
+mkdocstrings[python]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/requirements/docs.txt 
new/dirty-equals-0.5.0/requirements/docs.txt
--- old/dirty-equals-0.4/requirements/docs.txt  1970-01-01 01:00:00.000000000 
+0100
+++ new/dirty-equals-0.5.0/requirements/docs.txt        2022-08-30 
20:44:09.000000000 +0200
@@ -0,0 +1,89 @@
+#
+# This file is autogenerated by pip-compile with python 3.10
+# To update, run:
+#
+#    pip-compile --output-file=requirements/docs.txt requirements/docs.in
+#
+black==22.6.0
+    # via -r requirements/docs.in
+click==8.1.3
+    # via
+    #   black
+    #   mkdocs
+ghp-import==2.1.0
+    # via mkdocs
+griffe==0.22.0
+    # via mkdocstrings-python
+importlib-metadata==4.12.0
+    # via mkdocs
+jinja2==3.1.2
+    # via
+    #   mkdocs
+    #   mkdocs-material
+    #   mkdocstrings
+markdown==3.3.7
+    # via
+    #   mkdocs
+    #   mkdocs-autorefs
+    #   mkdocs-material
+    #   mkdocstrings
+    #   pymdown-extensions
+markupsafe==2.1.1
+    # via
+    #   jinja2
+    #   mkdocstrings
+mergedeep==1.3.4
+    # via mkdocs
+mkdocs==1.3.1
+    # via
+    #   -r requirements/docs.in
+    #   mkdocs-autorefs
+    #   mkdocs-material
+    #   mkdocs-simple-hooks
+    #   mkdocstrings
+mkdocs-autorefs==0.4.1
+    # via mkdocstrings
+mkdocs-material==8.4.1
+    # via -r requirements/docs.in
+mkdocs-material-extensions==1.0.3
+    # via mkdocs-material
+mkdocs-simple-hooks==0.1.5
+    # via -r requirements/docs.in
+mkdocstrings[python]==0.19.0
+    # via
+    #   -r requirements/docs.in
+    #   mkdocstrings-python
+mkdocstrings-python==0.7.1
+    # via mkdocstrings
+mypy-extensions==0.4.3
+    # via black
+packaging==21.3
+    # via mkdocs
+pathspec==0.9.0
+    # via black
+platformdirs==2.5.2
+    # via black
+pygments==2.13.0
+    # via mkdocs-material
+pymdown-extensions==9.5
+    # via
+    #   mkdocs-material
+    #   mkdocstrings
+pyparsing==3.0.9
+    # via packaging
+python-dateutil==2.8.2
+    # via ghp-import
+pyyaml==6.0
+    # via
+    #   mkdocs
+    #   pyyaml-env-tag
+pyyaml-env-tag==0.1
+    # via mkdocs
+six==1.16.0
+    # via python-dateutil
+tomli==2.0.1
+    # via black
+watchdog==2.1.9
+    # via mkdocs
+zipp==3.8.1
+    # via importlib-metadata
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/requirements/linting.in 
new/dirty-equals-0.5.0/requirements/linting.in
--- old/dirty-equals-0.4/requirements/linting.in        1970-01-01 
01:00:00.000000000 +0100
+++ new/dirty-equals-0.5.0/requirements/linting.in      2022-08-30 
20:44:09.000000000 +0200
@@ -0,0 +1,9 @@
+black
+flake8
+flake8-quotes
+isort[colors]
+mypy
+pre-commit
+pycodestyle
+pyflakes
+types-pytz
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/requirements/linting.txt 
new/dirty-equals-0.5.0/requirements/linting.txt
--- old/dirty-equals-0.4/requirements/linting.txt       1970-01-01 
01:00:00.000000000 +0100
+++ new/dirty-equals-0.5.0/requirements/linting.txt     2022-08-30 
20:44:09.000000000 +0200
@@ -0,0 +1,71 @@
+#
+# This file is autogenerated by pip-compile with python 3.10
+# To update, run:
+#
+#    pip-compile --output-file=requirements/linting.txt requirements/linting.in
+#
+black==22.6.0
+    # via -r requirements/linting.in
+cfgv==3.3.1
+    # via pre-commit
+click==8.1.3
+    # via black
+colorama==0.4.5
+    # via isort
+distlib==0.3.6
+    # via virtualenv
+filelock==3.8.0
+    # via virtualenv
+flake8==5.0.4
+    # via
+    #   -r requirements/linting.in
+    #   flake8-quotes
+flake8-quotes==3.3.1
+    # via -r requirements/linting.in
+identify==2.5.3
+    # via pre-commit
+isort[colors]==5.10.1
+    # via -r requirements/linting.in
+mccabe==0.7.0
+    # via flake8
+mypy==0.971
+    # via -r requirements/linting.in
+mypy-extensions==0.4.3
+    # via
+    #   black
+    #   mypy
+nodeenv==1.7.0
+    # via pre-commit
+pathspec==0.9.0
+    # via black
+platformdirs==2.5.2
+    # via
+    #   black
+    #   virtualenv
+pre-commit==2.20.0
+    # via -r requirements/linting.in
+pycodestyle==2.9.1
+    # via
+    #   -r requirements/linting.in
+    #   flake8
+pyflakes==2.5.0
+    # via
+    #   -r requirements/linting.in
+    #   flake8
+pyyaml==6.0
+    # via pre-commit
+toml==0.10.2
+    # via pre-commit
+tomli==2.0.1
+    # via
+    #   black
+    #   mypy
+types-pytz==2022.2.1.0
+    # via -r requirements/linting.in
+typing-extensions==4.3.0
+    # via mypy
+virtualenv==20.16.4
+    # via pre-commit
+
+# The following packages are considered to be unsafe in a requirements file:
+# setuptools
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/requirements/pyproject.txt 
new/dirty-equals-0.5.0/requirements/pyproject.txt
--- old/dirty-equals-0.4/requirements/pyproject.txt     1970-01-01 
01:00:00.000000000 +0100
+++ new/dirty-equals-0.5.0/requirements/pyproject.txt   2022-08-30 
20:44:09.000000000 +0200
@@ -0,0 +1,10 @@
+#
+# This file is autogenerated by pip-compile with python 3.10
+# To update, run:
+#
+#    pip-compile --output-file=requirements/pyproject.txt pyproject.toml
+#
+pytz==2022.2.1
+    # via dirty-equals (pyproject.toml)
+typing-extensions==4.3.0
+    # via dirty-equals (pyproject.toml)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/requirements/tests.in 
new/dirty-equals-0.5.0/requirements/tests.in
--- old/dirty-equals-0.4/requirements/tests.in  1970-01-01 01:00:00.000000000 
+0100
+++ new/dirty-equals-0.5.0/requirements/tests.in        2022-08-30 
20:44:09.000000000 +0200
@@ -0,0 +1,4 @@
+coverage[toml]
+pytest
+pytest-mock
+pytest-sugar
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/requirements/tests.txt 
new/dirty-equals-0.5.0/requirements/tests.txt
--- old/dirty-equals-0.4/requirements/tests.txt 1970-01-01 01:00:00.000000000 
+0100
+++ new/dirty-equals-0.5.0/requirements/tests.txt       2022-08-30 
20:44:09.000000000 +0200
@@ -0,0 +1,37 @@
+#
+# This file is autogenerated by pip-compile with python 3.10
+# To update, run:
+#
+#    pip-compile --output-file=requirements/testing.txt requirements/testing.in
+#
+attrs==22.1.0
+    # via pytest
+coverage[toml]==6.4.4
+    # via -r requirements/testing.in
+iniconfig==1.1.1
+    # via pytest
+packaging==21.3
+    # via
+    #   pytest
+    #   pytest-sugar
+pluggy==1.0.0
+    # via pytest
+py==1.11.0
+    # via pytest
+pyparsing==3.0.9
+    # via packaging
+pytest==7.1.2
+    # via
+    #   -r requirements/testing.in
+    #   pytest-mock
+    #   pytest-sugar
+pytest-mock==3.8.2
+    # via -r requirements/testing.in
+pytest-sugar==0.9.5
+    # via -r requirements/testing.in
+termcolor==1.1.0
+    # via pytest-sugar
+tomli==2.0.1
+    # via
+    #   coverage
+    #   pytest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/setup.py 
new/dirty-equals-0.5.0/setup.py
--- old/dirty-equals-0.4/setup.py       1970-01-01 01:00:00.000000000 +0100
+++ new/dirty-equals-0.5.0/setup.py     2022-08-30 20:44:09.000000000 +0200
@@ -0,0 +1,27 @@
+import sys
+
+sys.stderr.write(
+    """
+===============================
+Unsupported installation method
+===============================
+dirty-equals no longer supports installation with `python setup.py install`.
+Please use `python -m pip install .` instead.
+"""
+)
+sys.exit(1)
+
+
+# The below code will never execute, however GitHub is particularly
+# picky about where it finds Python packaging metadata.
+# See: https://github.com/github/feedback/discussions/6456
+#
+# To be removed once GitHub catches up.
+
+setup(
+    name='dirty-equals',
+    install_requires=[
+        'typing-extensions>=4.0.1',
+        'pytz>=2021.3',
+    ],
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/tests/mypy_checks.py 
new/dirty-equals-0.5.0/tests/mypy_checks.py
--- old/dirty-equals-0.4/tests/mypy_checks.py   2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/tests/mypy_checks.py 2022-08-30 20:44:09.000000000 
+0200
@@ -1,12 +1,16 @@
 """
 This module is run with mypy to check types can be used correctly externally.
 """
-from dirty_equals import HasName, HasRepr, IsStr
+import sys
+
+sys.path.append('.')
+
+from dirty_equals import HasName, HasRepr, IsStr  # noqa E402
 
 assert 123 == HasName('int')
 assert 123 == HasRepr('123')
 assert 123 == HasName(IsStr(regex='i..'))
 assert 123 == HasRepr(IsStr(regex=r'\d{3}'))
 
-# type ignore is required (if it wasn't, there would be an error
+# type ignore is required (if it wasn't, there would be an error)
 assert 123 != HasName(123)  # type: ignore[arg-type]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/tests/requirements-linting.txt 
new/dirty-equals-0.5.0/tests/requirements-linting.txt
--- old/dirty-equals-0.4/tests/requirements-linting.txt 2022-04-28 
17:37:25.000000000 +0200
+++ new/dirty-equals-0.5.0/tests/requirements-linting.txt       1970-01-01 
01:00:00.000000000 +0100
@@ -1,9 +0,0 @@
-black==22.3.0
-flake8==4.0.1
-flake8-quotes==3.3.1
-isort[colors]==5.10.1
-mypy==0.942
-pre-commit==2.17.0
-pycodestyle==2.8.0
-pyflakes==2.4.0
-types-pytz==2021.3.6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/tests/requirements.txt 
new/dirty-equals-0.5.0/tests/requirements.txt
--- old/dirty-equals-0.4/tests/requirements.txt 2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/tests/requirements.txt       1970-01-01 
01:00:00.000000000 +0100
@@ -1,5 +0,0 @@
-coverage[toml]==6.3.2
-poetry==1.2.0a2
-pytest==7.1.1
-pytest-mock==3.7.0
-pytest-sugar==0.9.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/tests/test_datetime.py 
new/dirty-equals-0.5.0/tests/test_datetime.py
--- old/dirty-equals-0.4/tests/test_datetime.py 2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/tests/test_datetime.py       2022-08-30 
20:44:09.000000000 +0200
@@ -1,4 +1,5 @@
 from datetime import date, datetime, timedelta, timezone
+from unittest.mock import Mock
 
 import pytest
 import pytz
@@ -25,7 +26,6 @@
         ),
         pytest.param('28/01/87', IsDatetime(approx=datetime(2000, 1, 1)), 
False, id='string-format-different'),
         pytest.param('foobar', IsDatetime(approx=datetime(2000, 1, 1)), False, 
id='string-format-wrong'),
-        pytest.param(datetime.now().isoformat(), IsNow(iso_string=True), True, 
id='isnow-str-true'),
         pytest.param(datetime(2000, 1, 1).isoformat(), IsNow(iso_string=True), 
False, id='isnow-str-different'),
         pytest.param([1, 2, 3], IsDatetime(approx=datetime(2000, 1, 1)), 
False, id='wrong-type'),
         pytest.param(
@@ -121,6 +121,12 @@
     assert IsNow(delta=3600.1).delta == timedelta(seconds=3600, 
microseconds=100000)
 
 
+def test_is_now_relative(monkeypatch):
+    mock = Mock(return_value=datetime(2020, 1, 1, 12, 13, 14))
+    monkeypatch.setattr(IsNow, '_get_now', mock)
+    assert IsNow() == datetime(2020, 1, 1, 12, 13, 14)
+
+
 def test_tz():
     new_year_london = pytz.timezone('Europe/London').localize(datetime(2000, 
1, 1))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dirty-equals-0.4/tests/test_other.py 
new/dirty-equals-0.5.0/tests/test_other.py
--- old/dirty-equals-0.4/tests/test_other.py    2022-04-28 17:37:25.000000000 
+0200
+++ new/dirty-equals-0.5.0/tests/test_other.py  2022-08-30 20:44:09.000000000 
+0200
@@ -1,8 +1,9 @@
 import uuid
+from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network
 
 import pytest
 
-from dirty_equals import FunctionCheck, IsJson, IsUUID
+from dirty_equals import FunctionCheck, IsIP, IsJson, IsUUID
 
 
 @pytest.mark.parametrize(
@@ -128,3 +129,57 @@
 def test_json_both():
     with pytest.raises(TypeError, match='IsJson requires either an argument or 
kwargs, not both'):
         IsJson(1, a=2)
+
+
+@pytest.mark.parametrize(
+    'other,dirty',
+    [
+        (IPv4Address('127.0.0.1'), IsIP()),
+        (IPv4Network('43.48.0.0/12'), IsIP()),
+        (IPv6Address('::eeff:ae3f:d473'), IsIP()),
+        (IPv6Network('::eeff:ae3f:d473/128'), IsIP()),
+        ('2001:0db8:0a0b:12f0:0000:0000:0000:0001', IsIP()),
+        ('179.27.154.96', IsIP),
+        ('43.62.123.119', IsIP(version=4)),
+        ('::ffff:2b3e:7b77', IsIP(version=6)),
+        ('0:0:0:0:0:ffff:2b3e:7b77', IsIP(version=6)),
+        ('54.43.53.219/10', IsIP(version=4, netmask='255.192.0.0')),
+        ('::ffff:aebf:d473/12', IsIP(version=6, netmask='fff0::')),
+        ('2001:0db8:0a0b:12f0:0000:0000:0000:0001', IsIP(version=6)),
+        (3232235521, IsIP()),
+        (b'\xC0\xA8\x00\x01', IsIP()),
+        (338288524927261089654018896845572831328, IsIP(version=6)),
+        (b'\x20\x01\x06\x58\x02\x2a\xca\xfe\x02\x00\x00\x00\x00\x00\x00\x01', 
IsIP(version=6)),
+    ],
+)
+def test_is_ip_true(other, dirty):
+    assert other == dirty
+
+
+@pytest.mark.parametrize(
+    'other,dirty',
+    [
+        ('foobar', IsIP()),
+        ([1, 2, 3], IsIP()),
+        ('210.115.28.193', IsIP(version=6)),
+        ('::ffff:d273:1cc1', IsIP(version=4)),
+        ('210.115.28.193/12', IsIP(version=6, netmask='255.255.255.0')),
+        ('::ffff:d273:1cc1', IsIP(version=6, netmask='fff0::')),
+        (3232235521, IsIP(version=6)),
+        (338288524927261089654018896845572831328, IsIP(version=4)),
+    ],
+)
+def test_is_ip_false(other, dirty):
+    assert other != dirty
+
+
+def test_not_ip_repr():
+    is_ip = IsIP()
+    with pytest.raises(AssertionError):
+        assert '123' == is_ip
+    assert str(is_ip) == 'IsIP()'
+
+
+def test_ip_bad_netmask():
+    with pytest.raises(TypeError, match='To check the netmask you must specify 
the IP version'):
+        IsIP(netmask='255.255.255.0')

Reply via email to