Skip to content
This repository was archived by the owner on Apr 20, 2025. It is now read-only.

Problems with tests on Fedora #153

Closed
Fale opened this issue Jun 13, 2020 · 11 comments · Fixed by #176
Closed

Problems with tests on Fedora #153

Fale opened this issue Jun 13, 2020 · 11 comments · Fixed by #176

Comments

@Fale
Copy link
Contributor

Fale commented Jun 13, 2020

Hi,
I'm updating the Fedora package, but I'm not able to make the tests work. I'm not sure if it's a problem with how Fedora builds Python or there is something else going on.
I would say that the majority of tests works properly, but the SHA3 ones fail with an error like the following (the type it expects does change on the various Python versions):

======================================================================
FAIL: test_run_mypy (tests.test_mypy.MypyRunnerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/builddir/build/BUILD/rsa-4.6/tests/test_mypy.py", line 27, in test_run_mypy
    self.fail('\n'.join(['Mypy errors:'] + messages))
AssertionError: Mypy errors:
rsa/pkcs1.py:65: error: Dict entry 0 has incompatible type "str": "Type[_Hash]"; expected "str": "Callable[[Union[bytes, memoryview]], _Hash]"
rsa/pkcs1.py:66: error: Dict entry 1 has incompatible type "str": "Type[_Hash]"; expected "str": "Callable[[Union[bytes, memoryview]], _Hash]"
rsa/pkcs1.py:67: error: Dict entry 2 has incompatible type "str": "Type[_Hash]"; expected "str": "Callable[[Union[bytes, memoryview]], _Hash]"
Found 3 errors in 1 file (checked 30 source files)

Mypy failed with status 1

----------------------------------------------------------------------
Ran 94 tests in 7.514s

FAILED (failures=1)
Test failed: <unittest.runner.TextTestResult run=94 errors=0 failures=1>
	Message:   b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'
	Encrypted: b'1\x8c\x82\xb7)\x81w\xe7$\x0bB\x92I\xae\xee\x9dT\xd1\xec\x1d\x0f\xb9/\xdb\xa3\xf1w+%o\xb41'
	Decrypted: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'
	Message:   b'Euro=\xe2\x82\xac ABCDEFGHIJKLMNOPQRSTUVWXYZ'
	Encrypted: b'V^\x81\x02\xc5\xc72\x93\x9c\x13\xa1\xfc\xb7!\xf0\x93\x15oE\xdek\x11\xc8a\xaa\xa9C\xa5\xd2\x1a\xcc\x9b\xc8\x11\xd5\x80\xf2\xa8\xd75\x17\xa0\x959\x9f\xa7\xfc\xe9'
	Decrypted: b'Euro=\xe2\x82\xac ABCDEFGHIJKLMNOPQRSTUVWXYZ'
error: Test failed: <unittest.runner.TextTestResult run=94 errors=0 failures=1>

This happens with:

Do you have any idea on the possible cause and work around?

Thanks a lot!

@sybrenstuvel
Copy link
Owner

I had to read through the messages a few times, but I came to the conclusion that the Message/Encrypted/Decrypted prints are just red herrings. There is only one test failure, and that's the mypy check. What surprises me is that it fails for you, while for me on both Mint Linux and Windows 10 the tests succeed. Do you have any environment variables set that may influence mypy's behaviour?

@takaki
Copy link

takaki commented Jun 14, 2020

I got same problem on Debian(sid).

This is CI build log.
https://salsa.debian.org/python-team/modules/python-rsa/-/jobs/805553

@jmontleon
Copy link

I was looking at updating Fedora packages as well... looking around I found the issue below which looks like a similar error, but not having looked at the python-rsa code I can't say if it's the same.

python/mypy#7329

@sybrenstuvel
Copy link
Owner

I'd love to get this fixed, but I can't reproduce this locally, it all works fine for me on Ubuntu 18.04, Linux Mint, and Windows 10.

@jmontleon
Copy link

A few things to note, the offending lines are:

    HASH_METHODS.update({
        'SHA3-256': hashlib.sha3_256,
        'SHA3-384': hashlib.sha3_384,
        'SHA3-512': hashlib.sha3_512,
    })

I would only expect this to happen on python 3.6+, so part of why you are or aren't seeing this could depend on what versions of python you have on Mint/Windows.

I am not certain I'm following completely, but it seems that in Python 3.6 a Keccak SHA3 implementation was used. Later a FIPS 202 SHA3 implementation came along and both were kept and there might be some additional information about which implmentation is being used.

As a test I imported _sha3 and changed the above lines like so and ran tests successfully:

    HASH_METHODS.update({
        'SHA3-256': _sha3.sha3_256,
        'SHA3-384': _sha3.sha3_384,
        'SHA3-512': _sha3.sha3_512,
    })

I don't think this is a proper fix, but seems to point that the test errors might indeed be legitimate.

@Fale
Copy link
Contributor Author

Fale commented Jun 15, 2020

Hi,

I'm not sure which variables can affect those behavior, but I tested the following procedure that can be run on any machine that is able to execute a docker container:

docker run -it docker.io/fedora /bin/bash
cd /tmp
dnf -y install wget python3-devel python3-pyasn1 python3-setuptools python3-mypy
wget https://pypi.python.org/packages/source/r/rsa/rsa-4.6.tar.gz
tar xzvf rsa-4.6.tar.gz
cd rsa-4.6
python3 setup.py test

I hope this helps to debug the problem :-)

@jmontleon
Copy link

I don't really understand. This doesn't cause an error...

if sys.version_info >= (3, 6):
    HASH_METHODS = {
        'MD5': hashlib.md5,
        'SHA-1': hashlib.sha1,
        'SHA-224': hashlib.sha224,
        'SHA-256': hashlib.sha256,
        'SHA-384': hashlib.sha384,
        'SHA-512': hashlib.sha512,
        'SHA3-256': hashlib.sha3_256,
        'SHA3-384': hashlib.sha3_384,
        'SHA3-512': hashlib.sha3_512,
    }

else:
    HASH_METHODS = {
        'MD5': hashlib.md5,
        'SHA-1': hashlib.sha1,
        'SHA-224': hashlib.sha224,
        'SHA-256': hashlib.sha256,
        'SHA-384': hashlib.sha384,
        'SHA-512': hashlib.sha512,
    }


if sys.version_info >= (3, 6):
    # Python 3.6 introduced SHA3 support.
    HASH_ASN1.update({
        'SHA3-256': b'\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x08\x05\x00\x04\x20',
        'SHA3-384': b'\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x09\x05\x00\x04\x30',
        'SHA3-512': b'\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x0a\x05\x00\x04\x40',
    })

@jmontleon
Copy link

grasping at straws but I see multiple mypy issues wrt to update:
python/mypy#6019
python/mypy#6462

@saifelse
Copy link
Contributor

saifelse commented Feb 16, 2021

I believe the root cause of the "non-determinism" is which version of mypy you're running.
Since mypy vendors typeshed, if it is a recent enough version of mypy that includes python/typeshed#1663 , it's expected for the the sha3_* functions to be _Hash types, while the non-sha3 functions are callables that return _Hash instances.

Adding a type hint like this seems to avoid the mypy error:

HASH_METHODS: Dict[str, Callable[[], hashlib._Hash]] = {
    "MD5": hashlib.md5,
    "SHA-1": hashlib.sha1,
    "SHA-224": hashlib.sha224,
    "SHA-256": hashlib.sha256,
    "SHA-384": hashlib.sha384,
    "SHA-512": hashlib.sha512,
}
if sys.version_info >= (3, 6):
    # Python 3.6 introduced SHA3 support.
    HASH_METHODS.update(
        {
            "SHA3-256": hashlib.sha3_256,
            "SHA3-384": hashlib.sha3_384,
            "SHA3-512": hashlib.sha3_512
        }
    )

though... this root cause can't be right since the PR I referenced is fro 2017 and the latest version of mypy can run into the issue, but it goes away if you specify --python-version 3.7 🤔

@saifelse
Copy link
Contributor

saifelse commented Feb 16, 2021

I think I've tracked it down to python/typeshed#3626, where in PY 3.7, it's def md5(__string: _DataType = ...) -> _Hash: ... . __string follows the convention for a nameless positional argument. Reverting that to _string or arg results in the same errors as --python-version 3.8 or --python-version 3.9

@saifelse
Copy link
Contributor

I've figured out why Fedora was acting weirdly!

The typeshed commit I mentioned that avoids the issue in 3.7 was commited around Jan 22, 2020 and was vendored in mypy==0.770 (Mar 9, 2020).

From @Fale 's logs from above:

  1. For Fedora 31 (Python 3.7.7), python3-mypy==0.740-2.fc31
  2. For Fedora 32 (Python 3.8.3), python3-mypy==0.761-2.fc32
  3. For Fedora 33 (Python 3.8.3), python3-mypy==0.780-1.fc33

So it's expected that 1 and 2 would have run into issues. For 0.780 and even the lastest version of python3-mypy (0.782-2.fc33), we should have had the python/typeshed#3626 fix, but it looks like python3-mypy-0.782-2.fc33 did not vendor this correctly: https://bugzilla.redhat.com/show_bug.cgi?id=1929522

Ultimately, it looks like mypy's inference gets a bit wonky, so a type hint like I noted above seems like the best way to handle this, especially since the issue is present if we update setup.cfg to have mypy target 3.8 or 3.9.

saifelse added a commit to saifelse/python-rsa that referenced this issue Feb 17, 2021
As captured in python/typeshed#1663, the types for
SHA-1 and SHA-2 family of functions are callables that return a Hash instance,
whilst the SHA-3 family of functions are Hash `type`s (at least in Python 3.6).
Mixing the two kinds of functions together in a dictionary confuses mypy's type
inference as noted in sybrenstuvel#153, so we instead add an annotation as a hint.

Also, update test_my.py to match the python version set by tox.ini in CI
instead of always targeting Python 3.7 (as configured in setup.cfg) to
validate the types in all supported Python 3.x versions.

This fix also avoids the issue with the older mypy releases for
Python 3.6 / Python 3.7 found in distro repos...

... for Ubuntu:
```
docker run \
  -v $(pwd):/tmp/rsa \
  -w /tmp/rsa ubuntu:18.04 \
  /bin/bash -c 'apt-get update -qqy \
                  && apt-get install -qqy python3-pyasn1 python3-setuptools python3-mypy \
                  && python3 setup.py test'
```
... and for Fedora:
```
docker run \
  -v $(pwd):/tmp/rsa \
  -w /tmp/rsa docker.io/fedora \
  /bin/bash -c 'dnf -y install wget python3-devel python3-pyasn1 python3-setuptools python3-mypy \
                  && python3 setup.py test'
```

Fixes sybrenstuvel#153
sybrenstuvel pushed a commit that referenced this issue Mar 24, 2021
As captured in python/typeshed#1663, the types for
SHA-1 and SHA-2 family of functions are callables that return a Hash instance,
whilst the SHA-3 family of functions are Hash `type`s (at least in Python 3.6).
Mixing the two kinds of functions together in a dictionary confuses mypy's type
inference as noted in #153, so we instead add an annotation as a hint.

Also, update test_my.py to match the python version set by tox.ini in CI
instead of always targeting Python 3.7 (as configured in setup.cfg) to
validate the types in all supported Python 3.x versions.

This fix also avoids the issue with the older mypy releases for
Python 3.6 / Python 3.7 found in distro repos...

... for Ubuntu:
```
docker run \
  -v $(pwd):/tmp/rsa \
  -w /tmp/rsa ubuntu:18.04 \
  /bin/bash -c 'apt-get update -qqy \
                  && apt-get install -qqy python3-pyasn1 python3-setuptools python3-mypy \
                  && python3 setup.py test'
```
... and for Fedora:
```
docker run \
  -v $(pwd):/tmp/rsa \
  -w /tmp/rsa docker.io/fedora \
  /bin/bash -c 'dnf -y install wget python3-devel python3-pyasn1 python3-setuptools python3-mypy \
                  && python3 setup.py test'
```

Fixes #153
sybrenstuvel pushed a commit that referenced this issue Mar 24, 2021
As captured in python/typeshed#1663, the types for
SHA-1 and SHA-2 family of functions are callables that return a Hash instance,
whilst the SHA-3 family of functions are Hash `type`s (at least in Python 3.6).
Mixing the two kinds of functions together in a dictionary confuses mypy's type
inference as noted in #153, so we instead add an annotation as a hint.

Also, update test_my.py to match the python version set by tox.ini in CI
instead of always targeting Python 3.7 (as configured in setup.cfg) to
validate the types in all supported Python 3.x versions.

This fix also avoids the issue with the older mypy releases for
Python 3.6 / Python 3.7 found in distro repos...

... for Ubuntu:
```
docker run \
  -v $(pwd):/tmp/rsa \
  -w /tmp/rsa ubuntu:18.04 \
  /bin/bash -c 'apt-get update -qqy \
                  && apt-get install -qqy python3-pyasn1 python3-setuptools python3-mypy \
                  && python3 setup.py test'
```
... and for Fedora:
```
docker run \
  -v $(pwd):/tmp/rsa \
  -w /tmp/rsa docker.io/fedora \
  /bin/bash -c 'dnf -y install wget python3-devel python3-pyasn1 python3-setuptools python3-mypy \
                  && python3 setup.py test'
```

Fixes #153
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants