diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index e4ea720..48f1b3b 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9] + python-version: [3.7, 3.8, 3.9, "3.10"] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -24,7 +24,7 @@ jobs: pip install -e ".[tests]" - name: Run Tests run: | - pytest --cov=pyas2lib --cov-config .coveragerc --black --pylava + pytest --cov=pyas2lib --cov-config .coveragerc --black --pylama - name: Generate CodeCov Report run: | pip install codecov diff --git a/pyas2lib/as2.py b/pyas2lib/as2.py index 6125c4b..8b454f3 100644 --- a/pyas2lib/as2.py +++ b/pyas2lib/as2.py @@ -103,20 +103,20 @@ def load_key(key_str: bytes, key_pass: str): except ValueError as e: # If it fails due to invalid password raise error here if e.args[0] == "Password provided is invalid": - raise AS2Exception("Password not valid for Private Key.") + raise AS2Exception("Password not valid for Private Key.") from e # if not try to parse as a pem file key, cert = None, None for kc in split_pem(key_str): try: cert = asymmetric.load_certificate(kc) - except (ValueError, TypeError): + except (ValueError, TypeError) as e: try: key = asymmetric.load_private_key(kc, key_pass) except OSError: raise AS2Exception( "Invalid Private Key or password is not correct." - ) + ) from e if not key or not cert: raise AS2Exception("Invalid Private key file or Public key not included.") diff --git a/pyas2lib/cms.py b/pyas2lib/cms.py index 439d908..01bc008 100644 --- a/pyas2lib/cms.py +++ b/pyas2lib/cms.py @@ -62,7 +62,7 @@ def decompress_message(compressed_data): raise DecompressionError("Compressed data not found in ASN.1 ") except Exception as e: - raise DecompressionError("Decompression failed with cause: {}".format(e)) + raise DecompressionError("Decompression failed with cause: {}".format(e)) from e def encrypt_message(data_to_encrypt, enc_alg, encryption_cert): @@ -204,10 +204,10 @@ def decrypt_message(encrypted_data, decryption_key): ): try: key = asymmetric.rsa_pkcs1v15_decrypt(decryption_key[0], encrypted_key) - except Exception: + except Exception as e: raise DecryptionError( "Failed to decrypt the payload: Could not extract decryption key." - ) + ) from e alg = cms_content["content"]["encrypted_content_info"][ "content_encryption_algorithm" @@ -235,7 +235,9 @@ def decrypt_message(encrypted_data, decryption_key): else: raise AS2Exception("Unsupported Encryption Algorithm") except Exception as e: - raise DecryptionError("Failed to decrypt the payload: {}".format(e)) + raise DecryptionError( + "Failed to decrypt the payload: {}".format(e) + ) from e else: raise AS2Exception("Unsupported Encryption Algorithm") else: @@ -276,7 +278,7 @@ def sign_message( message_digest = digest_func.digest() class SmimeCapability(core.Sequence): - """"Define the possible list of Smime Capability.""" + """Define the possible list of Smime Capability.""" _fields = [ ("0", core.Any, {"optional": True}), @@ -287,7 +289,7 @@ class SmimeCapability(core.Sequence): ] class SmimeCapabilities(core.Sequence): - """"Define the Smime Capabilities supported by pyas2.""" + """Define the Smime Capabilities supported by pyas2.""" _fields = [ ("0", SmimeCapability), @@ -515,7 +517,9 @@ def verify_message(data_to_verify, signature, verify_cert): else: raise AS2Exception("Unsupported Signature Algorithm") except Exception as e: - raise IntegrityError("Failed to verify message signature: {}".format(e)) + raise IntegrityError( + "Failed to verify message signature: {}".format(e) + ) from e else: raise IntegrityError("Signed data not found in ASN.1 ") diff --git a/pyas2lib/exceptions.py b/pyas2lib/exceptions.py index 1b1c2d6..5c4614a 100644 --- a/pyas2lib/exceptions.py +++ b/pyas2lib/exceptions.py @@ -31,7 +31,7 @@ class AS2Exception(Exception): disposition_modifier = "" def __init__(self, message, disposition_modifier=None): - super(AS2Exception, self).__init__(message) + super().__init__(message) if disposition_modifier: self.disposition_modifier = disposition_modifier diff --git a/pyas2lib/tests/livetest_with_mecas2.py b/pyas2lib/tests/livetest_with_mecas2.py index 11b1ef6..19b0505 100644 --- a/pyas2lib/tests/livetest_with_mecas2.py +++ b/pyas2lib/tests/livetest_with_mecas2.py @@ -29,7 +29,7 @@ def setUp(self): self.out_message = None def test_compressed_message(self): - """ Send Unencrypted Unsigned Compressed Message to Mendelson AS2""" + """Send Unencrypted Unsigned Compressed Message to Mendelson AS2""" self.partner.compress = True self.out_message = as2.Message(self.org, self.partner) @@ -53,7 +53,7 @@ def test_compressed_message(self): self.assertEqual(status, "processed") def test_encrypted_message(self): - """ Send Encrypted Unsigned Uncompressed Message to Mendelson AS2""" + """Send Encrypted Unsigned Uncompressed Message to Mendelson AS2""" self.partner.encrypt = True self.out_message = as2.Message(self.org, self.partner) @@ -77,7 +77,7 @@ def test_encrypted_message(self): self.assertEqual(status, "processed") def test_signed_message(self): - """ Send Unencrypted Signed Uncompressed Message to Mendelson AS2""" + """Send Unencrypted Signed Uncompressed Message to Mendelson AS2""" self.partner.sign = True self.out_message = as2.Message(self.org, self.partner) @@ -101,7 +101,7 @@ def test_signed_message(self): self.assertEqual(status, "processed") def test_encrypted_signed_message(self): - """ Send Encrypted Signed Uncompressed Message to Mendelson AS2""" + """Send Encrypted Signed Uncompressed Message to Mendelson AS2""" self.partner.sign = True self.partner.encrypt = True @@ -126,7 +126,7 @@ def test_encrypted_signed_message(self): self.assertEqual(status, "processed") def test_encrypted_signed_compressed_message(self): - """ Send Encrypted Signed Compressed Message to Mendelson AS2""" + """Send Encrypted Signed Compressed Message to Mendelson AS2""" self.partner.sign = True self.partner.encrypt = True diff --git a/pyas2lib/tests/livetest_with_oldpyas2.py b/pyas2lib/tests/livetest_with_oldpyas2.py index 6b30c49..fbd1e9a 100644 --- a/pyas2lib/tests/livetest_with_oldpyas2.py +++ b/pyas2lib/tests/livetest_with_oldpyas2.py @@ -29,7 +29,7 @@ def setUp(self): self.out_message = None def test_compressed_message(self): - """ Send Unencrypted Unsigned Compressed Message to Mendelson AS2""" + """Send Unencrypted Unsigned Compressed Message to Mendelson AS2""" self.partner.compress = True self.out_message = as2.Message(self.org, self.partner) @@ -53,7 +53,7 @@ def test_compressed_message(self): self.assertEqual(status, "processed") def test_encrypted_message(self): - """ Send Encrypted Unsigned Uncompressed Message to Mendelson AS2""" + """Send Encrypted Unsigned Uncompressed Message to Mendelson AS2""" self.partner.encrypt = True self.out_message = as2.Message(self.org, self.partner) @@ -77,7 +77,7 @@ def test_encrypted_message(self): self.assertEqual(status, "processed") def test_signed_message(self): - """ Send Unencrypted Signed Uncompressed Message to Mendelson AS2""" + """Send Unencrypted Signed Uncompressed Message to Mendelson AS2""" self.partner.sign = True self.out_message = as2.Message(self.org, self.partner) @@ -101,7 +101,7 @@ def test_signed_message(self): self.assertEqual(status, "processed") def test_encrypted_signed_message(self): - """ Send Encrypted Signed Uncompressed Message to Mendelson AS2""" + """Send Encrypted Signed Uncompressed Message to Mendelson AS2""" self.partner.sign = True self.partner.encrypt = True @@ -126,7 +126,7 @@ def test_encrypted_signed_message(self): self.assertEqual(status, "processed") def test_encrypted_signed_compressed_message(self): - """ Send Encrypted Signed Compressed Message to Mendelson AS2""" + """Send Encrypted Signed Compressed Message to Mendelson AS2""" self.partner.sign = True self.partner.encrypt = True diff --git a/pyas2lib/tests/test_advanced.py b/pyas2lib/tests/test_advanced.py index c893a21..0bc6db7 100644 --- a/pyas2lib/tests/test_advanced.py +++ b/pyas2lib/tests/test_advanced.py @@ -26,7 +26,7 @@ def setUp(self): ) def test_binary_message(self): - """ Test Encrypted Signed Binary Message """ + """Test Encrypted Signed Binary Message""" # Build an As2 message to be transmitted to partner self.partner.sign = True @@ -60,7 +60,7 @@ def test_binary_message(self): self.assertEqual(out_message.mic, in_message.mic) def test_partner_not_found(self): - """ Test case where partner and organization is not found """ + """Test case where partner and organization is not found""" # Build an As2 message to be transmitted to partner self.partner.sign = True @@ -106,7 +106,7 @@ def test_partner_not_found(self): self.assertEqual(detailed_status, "unknown-trading-partner") def test_duplicate_message(self): - """ Test case where a duplicate message is sent to the partner """ + """Test case where a duplicate message is sent to the partner""" # Build an As2 message to be transmitted to partner self.partner.sign = True @@ -135,7 +135,7 @@ def test_duplicate_message(self): self.assertEqual(detailed_status, "duplicate-document") def test_failed_decompression(self): - """ Test case where message decompression has failed """ + """Test case where message decompression has failed""" # Build an As2 message to be transmitted to partner self.partner.compress = True @@ -162,7 +162,7 @@ def test_failed_decompression(self): self.assertEqual(detailed_status, "decompression-failed") def test_insufficient_security(self): - """ Test case where message security is not as per the configuration """ + """Test case where message security is not as per the configuration""" # Build an As2 message to be transmitted to partner self.partner.mdn_mode = as2.SYNCHRONOUS_MDN @@ -198,7 +198,7 @@ def test_insufficient_security(self): self.assertEqual(exc.disposition_modifier, "insufficient-message-security") def test_failed_decryption(self): - """ Test case where message decryption has failed """ + """Test case where message decryption has failed""" # Build an As2 message to be transmitted to partner self.partner.encrypt = True @@ -228,7 +228,7 @@ def test_failed_decryption(self): self.assertEqual(detailed_status, "decryption-failed") def test_failed_signature(self): - """ Test case where signature verification has failed """ + """Test case where signature verification has failed""" # Build an As2 message to be transmitted to partner self.partner.sign = True @@ -258,7 +258,7 @@ def test_failed_signature(self): self.assertEqual(detailed_status, "authentication-failed") def test_verify_certificate(self): - """ Test case where we have try to load an expired cert """ + """Test case where we have try to load an expired cert""" # First test with a certificate with invalid root cert_path = os.path.join(TEST_DIR, "verify_cert_test1.pem") @@ -298,7 +298,7 @@ def test_verify_certificate(self): self.fail("Failed to load chain certificate: %s" % e) def test_load_private_key(self): - """ Test case where we have try to load keys in different formats """ + """Test case where we have try to load keys in different formats""" # First test with a pkcs12 key file cert_path = os.path.join(TEST_DIR, "cert_test.p12") @@ -547,7 +547,7 @@ def setUp(self): @pytest.mark.skip(reason="no way of currently testing this") def test_process_message(self): - """ Test processing message received from Sterling Integrator""" + """Test processing message received from Sterling Integrator""" with open(os.path.join(TEST_DIR, "sb2bi_signed_cmp.msg"), "rb") as msg: as2message = as2.Message() status, exception, as2mdn = as2message.parse( @@ -559,7 +559,7 @@ def test_process_message(self): self.assertEqual(status, "processed") def test_process_mdn(self): - """ Test processing mdn received from Sterling Integrator""" + """Test processing mdn received from Sterling Integrator""" msg = as2.Message(sender=self.org, receiver=self.partner) msg.message_id = ( "151694007918.24690.7052273208458909245@ip-172-31-14-209.ec2.internal" diff --git a/pyas2lib/tests/test_basic.py b/pyas2lib/tests/test_basic.py index fc6c20a..3c2c182 100644 --- a/pyas2lib/tests/test_basic.py +++ b/pyas2lib/tests/test_basic.py @@ -20,7 +20,7 @@ def setUp(self): ) def test_plain_message(self): - """ Test Unencrypted Unsigned Uncompressed Message """ + """Test Unencrypted Unsigned Uncompressed Message""" # Build an As2 message to be transmitted to partner out_message = as2.Message(self.org, self.partner) @@ -40,7 +40,7 @@ def test_plain_message(self): self.assertEqual(self.test_data, in_message.content) def test_compressed_message(self): - """ Test Unencrypted Unsigned Compressed Message """ + """Test Unencrypted Unsigned Compressed Message""" # Build an As2 message to be transmitted to partner self.partner.compress = True @@ -62,7 +62,7 @@ def test_compressed_message(self): self.assertEqual(self.test_data.splitlines(), in_message.content.splitlines()) def test_encrypted_message(self): - """ Test Encrypted Unsigned Uncompressed Message """ + """Test Encrypted Unsigned Uncompressed Message""" # Build an As2 message to be transmitted to partner self.partner.encrypt = True @@ -84,7 +84,7 @@ def test_encrypted_message(self): self.assertEqual(self.test_data.splitlines(), in_message.content.splitlines()) def test_signed_message(self): - """ Test Unencrypted Signed Uncompressed Message """ + """Test Unencrypted Signed Uncompressed Message""" # Build an As2 message to be transmitted to partner self.partner.sign = True @@ -107,7 +107,7 @@ def test_signed_message(self): self.assertEqual(out_message.mic, in_message.mic) def test_encrypted_signed_message(self): - """ Test Encrypted Signed Uncompressed Message """ + """Test Encrypted Signed Uncompressed Message""" # Build an As2 message to be transmitted to partner self.partner.sign = True @@ -132,7 +132,7 @@ def test_encrypted_signed_message(self): self.assertEqual(self.test_data.splitlines(), in_message.content.splitlines()) def test_encrypted_signed_message_dos(self): - """ Test Encrypted Signed Uncompressed Message with DOS line endings. """ + """Test Encrypted Signed Uncompressed Message with DOS line endings.""" # Build an As2 message to be transmitted to partner self.partner.sign = True @@ -157,7 +157,7 @@ def test_encrypted_signed_message_dos(self): self.assertEqual(self.test_data_dos, in_message.content) def test_encrypted_signed_compressed_message(self): - """ Test Encrypted Signed Compressed Message """ + """Test Encrypted Signed Compressed Message""" # Build an As2 message to be transmitted to partner self.partner.sign = True diff --git a/pyas2lib/tests/test_mdn.py b/pyas2lib/tests/test_mdn.py index 59ebfcc..dff451e 100644 --- a/pyas2lib/tests/test_mdn.py +++ b/pyas2lib/tests/test_mdn.py @@ -21,7 +21,7 @@ def setUp(self): self.out_message = None def test_unsigned_mdn(self): - """ Test unsigned MDN generation and parsing """ + """Test unsigned MDN generation and parsing""" # Build an As2 message to be transmitted to partner self.partner.sign = True @@ -49,7 +49,7 @@ def test_unsigned_mdn(self): self.assertEqual(status, "processed") def test_signed_mdn(self): - """ Test signed MDN generation and parsing """ + """Test signed MDN generation and parsing""" # Build an As2 message to be transmitted to partner self.partner.sign = True diff --git a/pyas2lib/tests/test_with_mecas2.py b/pyas2lib/tests/test_with_mecas2.py index 4c4d3de..86b9bce 100644 --- a/pyas2lib/tests/test_with_mecas2.py +++ b/pyas2lib/tests/test_with_mecas2.py @@ -22,7 +22,7 @@ def setUp(self): ) def test_compressed_message(self): - """ Test Compressed Message received from Mendelson AS2""" + """Test Compressed Message received from Mendelson AS2""" # Parse the generated AS2 message as the partner received_file = os.path.join(TEST_DIR, "mecas2_compressed.as2") @@ -37,7 +37,7 @@ def test_compressed_message(self): self.assertEqual(self.test_data, in_message.content) def test_encrypted_message(self): - """ Test Encrypted Message received from Mendelson AS2""" + """Test Encrypted Message received from Mendelson AS2""" # Parse the generated AS2 message as the partner received_file = os.path.join(TEST_DIR, "mecas2_encrypted.as2") @@ -53,7 +53,7 @@ def test_encrypted_message(self): self.assertEqual(self.test_data, in_message.content) def test_signed_message(self): - """ Test Unencrypted Signed Uncompressed Message from Mendelson AS2""" + """Test Unencrypted Signed Uncompressed Message from Mendelson AS2""" # Parse the generated AS2 message as the partner received_file = os.path.join(TEST_DIR, "mecas2_signed.as2") with open(received_file, "rb") as fp: @@ -68,7 +68,7 @@ def test_signed_message(self): self.assertEqual(self.test_data, in_message.content) def test_encrypted_signed_message(self): - """ Test Encrypted Signed Uncompressed Message from Mendelson AS2""" + """Test Encrypted Signed Uncompressed Message from Mendelson AS2""" # Parse the generated AS2 message as the partner received_file = os.path.join(TEST_DIR, "mecas2_signed_encrypted.as2") @@ -86,7 +86,7 @@ def test_encrypted_signed_message(self): self.assertEqual(self.test_data, in_message.content) def test_encrypted_signed_compressed_message(self): - """ Test Encrypted Signed Compressed Message from Mendelson AS2""" + """Test Encrypted Signed Compressed Message from Mendelson AS2""" # Parse the generated AS2 message as the partner received_file = os.path.join(TEST_DIR, "mecas2_compressed_signed_encrypted.as2") @@ -104,7 +104,7 @@ def test_encrypted_signed_compressed_message(self): self.assertEqual(self.test_data, in_message.content) def test_unsigned_mdn(self): - """ Test Unsigned MDN received from Mendelson AS2""" + """Test Unsigned MDN received from Mendelson AS2""" # Parse the generated AS2 message as the partner received_file = os.path.join(TEST_DIR, "mecas2_unsigned.mdn") @@ -118,7 +118,7 @@ def test_unsigned_mdn(self): self.assertEqual(detailed_status, "authentication-failed") def test_signed_mdn(self): - """ Test Signed MDN received from Mendelson AS2""" + """Test Signed MDN received from Mendelson AS2""" # Parse the generated AS2 message as the partner received_file = os.path.join(TEST_DIR, "mecas2_signed.mdn") diff --git a/pyas2lib/utils.py b/pyas2lib/utils.py index 3837684..ff204cc 100644 --- a/pyas2lib/utils.py +++ b/pyas2lib/utils.py @@ -201,7 +201,7 @@ def verify_certificate_chain(cert_bytes, trusted_certs, ignore_self_signed=True) except crypto.X509StoreContextError as e: raise AS2Exception( "Partner Certificate Invalid: %s" % e.args[-1][-1], "invalid-certificate" - ) + ) from e def extract_certificate_info(cert: bytes): diff --git a/setup.cfg b/setup.cfg index 1e53955..9fad98a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,21 +1,21 @@ [aliases] test=pytest -[pylava:pycodestyle] +[pylama:pycodestyle] max_line_length = 100 -[pylava:pylint] +[pylama:pylint] max_line_length = 100 -ignore = E1101,R0902,R0903,W1203,C0103 +ignore = E1101,R0902,R0903,W1203,C0103,C0302,C0209,R0913,R0915,W0612,R1705 -[pylava:pydocstyle] +[pylama:pydocstyle] convention = numpy ignore = D202 -[pylava:pep8] +[pylama:pep8] max_line_length = 100 -[pylava] +[pylama] format = pep8 skip = venv/*,.tox/*,*/tests/*,setup.py linters= pycodestyle,pyflakes,pylint,pep8 diff --git a/setup.py b/setup.py index f4b4079..b28be61 100644 --- a/setup.py +++ b/setup.py @@ -3,17 +3,17 @@ install_requires = [ "asn1crypto==1.4.0", "oscrypto==1.2.1", - "pyOpenSSL==20.0.1", + "pyOpenSSL==21.0.0", ] tests_require = [ - "pytest==6.2.1", - "toml==0.10.1", + "pytest==6.2.5", + "toml==0.10.2", "pytest-cov==2.8.1", "coverage==5.0.4", - "pylint==2.4.4", - "pylava-pylint==0.0.3", - "black==20.8b1", + "pylint==2.12.1", + "pylama-pylint==3.1.1", + "black==21.12b0", "pytest-black==0.3.12", ] diff --git a/tox.ini b/tox.ini index f209c38..c1f1f9f 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py37, py38 +envlist = py37, py38, py39, py310 [testenv] commands = {envpython} setup.py test