Visitar URL original
TypeError when comparing VersionInfo to None · Issue #346 · python-semver/python-semver · GitHub
Skip to content

TypeError when comparing VersionInfo to None #346

Closed

Description

@cariad

Situation

semver raises TypeError when comparing VersionInfo to None.

To Reproduce

from dataclasses import dataclass
from typing import Optional

from semver import VersionInfo


@dataclass
class MyData:
    data: Optional[VersionInfo]


a = MyData(data=VersionInfo(1))
b = MyData(data=None)

assert a != b
Traceback (most recent call last):
  File "/home/cariad/startifact/version.py", line 15, in <module>
    assert a != b
  File "<string>", line 4, in __eq__
  File "/home/cariad/startifact/.venv/lib/python3.10/site-packages/semver.py", line 200, in wrapper
    raise TypeError(
TypeError: other type <class 'NoneType'> must be in (<class 'semver.VersionInfo'>, <class 'dict'>, <class 'tuple'>, <class 'list'>, <class 'str'>, <class 'bytes'>)

Expected Behavior

I expect a comparison of VersionInfo to None to return False.

For reference, this example with strings does work:

from dataclasses import dataclass
from typing import Optional


@dataclass
class MyData:
    data: Optional[str]


a = MyData(data="foo")
b = MyData(data=None)

assert a != b

Environment

  • OS: Linux
  • Python version: 3.10
  • Version of semver library: 2.13.0

Additional context

  1. I ❤️ semver -- thanks for all your work!
  2. I'm happy to work on a pull request. Let me know?

Activity

  1. added
    BugError, flaw or fault to produce incorrect or unexpected results
    on Dec 12, 2021
  2. sebix commented on Jan 10, 2022

    @sebix

    I see a test fail which is probably related:

    [    6s] =================================== FAILURES ===================================
    [    6s] _____________________________ [doctest] usage.rst ______________________________
    [    6s] 446    True
    [    6s] 447 
    [    6s] 448   The opposite does also work::
    [    6s] 449 
    [    6s] 450    >>> dict(major=1) < v
    [    6s] 451    True
    [    6s] 452 
    [    6s] 453   If the dictionary contains unknown keys, you get a :class:`TypeError` exception::
    [    6s] 454 
    [    6s] 455     >>> v > dict(major=1, unknown=42)
    [    6s] Differences (ndiff with -expected +actual):
    [    6s]       Traceback (most recent call last):
    [    6s]     - ...
    [    6s]     +   File "/usr/lib64/python3.10/doctest.py", line 1346, in __run
    [    6s]     +     exec(compile(example.source, filename, "single",
    [    6s]     +   File "<doctest usage.rst[75]>", line 1, in <module>
    [    6s]     +     v > dict(major=1, unknown=42)
    [    6s]     +   File "/home/abuild/rpmbuild/BUILD/semver-2.13.0/semver.py", line 203, in wrapper
    [    6s]     +     return operator(self, other)
    [    6s]     +   File "/home/abuild/rpmbuild/BUILD/semver-2.13.0/semver.py", line 589, in __gt__
    [    6s]     +     return self.compare(other) > 0
    [    6s]     +   File "/home/abuild/rpmbuild/BUILD/semver-2.13.0/semver.py", line 495, in compare
    [    6s]     +     other = cls(**other)
    [    6s]     - TypeError: __init__() got an unexpected keyword argument 'unknown'
    [    6s]     + TypeError: VersionInfo.__init__() got an unexpected keyword argument 'unknown'
    [    6s]     ?            ++++++++++++
    [    6s] 
    [    6s] /home/abuild/rpmbuild/BUILD/semver-2.13.0/docs/usage.rst:455: DocTestFailure
    [    6s] =========================== short test summary info ============================
    [    6s] FAILED docs/usage.rst::usage.rst
    [    6s] ======================== 1 failed, 318 passed in 0.63s =========================
    
  3. tomschr commented on Jan 10, 2022

    @tomschr
    Member

    Hi @cariad thanks for your report. Much appreciated and sorry for the late response (vacation).

    I haven't used semver together with dataclasses. What a nice way!

    However, I think, you miss something. 😉 Versions are ordered. According to the Python documentation, the @dataclass decorator has the following signature:

    dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False)

    As you can see, the order key is set to False by default. This means, the decorator does not create comparison operators automatically (like __lt__()). However, in order to compare dataclasses, you need the order key.

    Have you tried the following code?

    # imports the same as above
    
    @dataclass(order=True)
    class MyData2:
        data: Optional[VersionInfo]
    
    a = MyData2(data=VersionInfo(1))
    b = MyData2(data=None)
    assert a!= b

    With the above code you don't get any tracebacks. I hope I haven't overlooked something.

    Perhaps we could use this example in the documentation. Would that help? What do you think?

  4. tomschr commented on Jan 10, 2022

    @tomschr
    Member

    I see a test fail which is probably related:

    How did you run the tests? When I run it against Python3.9, all tests pass. I did it with the command tox -e py39.

    The test you've mentioned is a (doc)test from the documentation. The project is set up in a way that these tests are included too. In this specific case, this test is expected to fail because of the unknown keyword.

  5. sebix commented on Jan 10, 2022

    @sebix

    I see a test fail which is probably related:

    How did you run the tests? When I run it against Python3.9, all tests pass. I did it with the command tox -e py39.

    Using pytest on python 3.10. As @cariad is using Python 3.10 as well, maybe that's the reason?

    The test you've mentioned is a (doc)test from the documentation. The project is set up in a way that these tests are included too. In this specific case, this test is expected to fail because of the unknown keyword.

    If I interpret the error right, the problem is not the traceback itself, which is expected, but that

    [    6s]     - TypeError: __init__() got an unexpected keyword argument 'unknown'
    

    is expected, but

    [    6s]     + TypeError: VersionInfo.__init__() got an unexpected keyword argument 'unknown'
    

    actually happens which shows similarity to the issue described by @cariad (and same Python version as well). The connection of the bugs is still a guess, but there are too much similarities.

  6. tomschr commented on Jan 10, 2022

    @tomschr
    Member

    Using pytest on python 3.10. As @cariad is using Python 3.10 as well, maybe that's the reason?

    That could be the reason. I've just added support for Python 3.10 in #347. Wanna have a look? 🙂

    If I interpret the error right, the problem is not the traceback itself, which is expected, but that TypeError: __init__ is expected, but TypeError: VersionInfo.__init__ actually happens which shows similarity to the issue described by @cariad (and same Python version as well).

    Ahh, I see! Thanks for pointing it out. 👍

    However, what I don't understand: if you look into the file docs/usage.rst (line 789), you can see this:

    >>> v > dict(major=1, unknown=42)
    Traceback (most recent call last):
    ...
    TypeError: ... got an unexpected keyword argument 'unknown'

    I remember, I've added the ellipsis (the three dots) after TypeError to avoid such errors like the above one. Any ideas?

  7. sebix commented on Jan 10, 2022

    @sebix

    Using pytest on python 3.10. As @cariad is using Python 3.10 as well, maybe that's the reason?

    That could be the reason. I've just added support for Python 3.10 in #347. Wanna have a look? slightly_smiling_face

    As the pypi package has a different directory structure, applying the PR as patch, doesn't work, so I tried using the branch itself and the build and test with it works. I didn't identify which exact commit of the 63 fixed it, but I doubt the the PR itself does fix it. -> A new release would solve the problem.

  8. cariad commented on Jan 11, 2022

    @cariad
    Author

    Hey folks! I just built from the latest source and my original reproduction step now works.

    I'm happy to close this, knowing that an updated package will be released when it's good and ready. 😎

    Thank you!

  9. tomschr commented on Jan 11, 2022

    @tomschr
    Member

    Thanks for all! Actually I plan to release a new development version in the next days (depending on my schedule). Hope that's fine. 🙂

    @cariad If you like, you can close the issue. Or you can leave it open and close it once the new dev version is released.

  10. cariad commented on Jan 11, 2022

    @cariad
    Author

    Closing now! This issue isn't blocking me (I've forgotten how I worked around it, but everything's working so 🤷) so I'm not waiting on that dev release. 🚀

  11. tomschr commented on Jan 20, 2022

    @tomschr
    Member

    Hi @cariad, you might be interested in a new release, see the discussion in #349. 🙂

  12. cariad commented on Jan 21, 2022

    @cariad
    Author

    @tomschr Ah, you're amazing! Thank you! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugError, flaw or fault to produce incorrect or unexpected results

    Type

    No type

    Fields

    SIze

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions