Skip to content

TypeError when comparing VersionInfo to None #346

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

Closed
cariad opened this issue Dec 12, 2021 · 11 comments
Closed

TypeError when comparing VersionInfo to None #346

cariad opened this issue Dec 12, 2021 · 11 comments
Labels
Bug Error, flaw or fault to produce incorrect or unexpected results

Comments

@cariad
Copy link

cariad commented Dec 12, 2021

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?
@cariad cariad added the Bug Error, flaw or fault to produce incorrect or unexpected results label Dec 12, 2021
@sebix
Copy link

sebix commented Jan 10, 2022

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 =========================

@tomschr
Copy link
Member

tomschr commented Jan 10, 2022

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?

@tomschr
Copy link
Member

tomschr commented Jan 10, 2022

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.

@sebix
Copy link

sebix commented Jan 10, 2022

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.

@tomschr
Copy link
Member

tomschr commented Jan 10, 2022

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?

@sebix
Copy link

sebix commented Jan 10, 2022

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.

@cariad
Copy link
Author

cariad commented Jan 11, 2022

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!

@tomschr
Copy link
Member

tomschr commented Jan 11, 2022

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.

@cariad
Copy link
Author

cariad commented Jan 11, 2022

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. 🚀

@cariad cariad closed this as completed Jan 11, 2022
@tomschr
Copy link
Member

tomschr commented Jan 20, 2022

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

@cariad
Copy link
Author

cariad commented Jan 21, 2022

@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
Labels
Bug Error, flaw or fault to produce incorrect or unexpected results
Projects
None yet
Development

No branches or pull requests

3 participants