From 3047edd7f532c3f5ea1bb4cc5786bf0a27562f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Gmach?= Date: Fri, 22 Apr 2022 13:21:24 +0200 Subject: [PATCH] Modernize Python support --- .coveragerc | 6 +- .github/workflows/ci.yml | 39 ++++++ .gitignore | 1 - .travis.yml | 24 ---- README.md | 15 +- pytest.ini | 2 + requirements.txt | 7 +- setup.py | 9 +- .../functional_tests/encrypted_field_tests.py | 9 +- tests/functional_tests/functional_tests.py | 128 ++++++------------ tests/functional_tests/serialization_tests.py | 9 +- .../property_tests/macaroon_property_tests.py | 13 +- tox.ini | 21 +-- 13 files changed, 137 insertions(+), 146 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml create mode 100644 pytest.ini diff --git a/.coveragerc b/.coveragerc index 812fc3b..da89d7b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,4 +1,8 @@ [report] omit = */python?.?/* - */site-packages/nose/* + +# do not report missing coverage for abstract methods +exclude_lines = + @abstractmethod + @abc.abstractmethod diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0034110 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events + push: + pull_request: + schedule: + - cron: '0 12 * * 0' # run once a week on Sunday + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + tests: + name: "Python ${{ matrix.python-version }}" + runs-on: "ubuntu-latest" + + strategy: + matrix: + python-version: ["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "pypy3"] + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: "actions/checkout@v2" + - uses: "actions/setup-python@v2" + with: + python-version: "${{ matrix.python-version }}" + - name: "Install dependencies" + run: | + set -xe + python -VV + python -m site + python -m pip install --upgrade pip setuptools wheel + python -m pip install --upgrade virtualenv tox tox-gh-actions + - name: "Run tox targets for ${{ matrix.python-version }}" + run: "python -m tox" diff --git a/.gitignore b/.gitignore index 731e176..320d7d0 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,6 @@ htmlcov/ .tox/ .coverage .cache -nosetests.xml coverage.xml # Translations diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 11d4cd4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: python -python: 3.4 -before_install: - - wget https://github.com/jedisct1/libsodium/releases/download/1.0.0/libsodium-1.0.0.tar.gz - - tar xzvf libsodium-1.0.0.tar.gz - - cd libsodium-1.0.0 - - ./configure && make && make check && sudo make install - - cd .. - - sudo ldconfig -install: - - pip install tox -script: - - tox -e $TOX_ENV -env: - - TOX_ENV=py26 - - TOX_ENV=py27 - - TOX_ENV=py33 - - TOX_ENV=py34 - - TOX_ENV=pypy - - TOX_ENV=pypy3.3-5.5-alpha - - TOX_ENV=docs - - TOX_ENV=flake8 - - TOX_ENV=coverage -after_success: coveralls diff --git a/README.md b/README.md index fd3423f..a37c311 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # PyMacaroons -[![Build Status](https://travis-ci.org/ecordell/pymacaroons.svg?branch=master)](https://travis-ci.org/ecordell/pymacaroons) [![Coverage Status](https://coveralls.io/repos/ecordell/pymacaroons/badge.png)](https://coveralls.io/r/ecordell/pymacaroons) [![Downloads](https://img.shields.io/pypi/dd/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Latest Version](https://img.shields.io/pypi/v/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Supported Python versions](https://img.shields.io/pypi/pyversions/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Supported Python implementations](https://img.shields.io/pypi/implementation/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Development Status](https://img.shields.io/pypi/status/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Wheel Status](https://img.shields.io/pypi/wheel/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![License](https://img.shields.io/pypi/l/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) +[![Build Status](https://github.com/ecordell/pymacaroons/workflows/CI/badge.svg?branch=master)](https://github.com/ecordell/pymacaroons/actions?workflow=CI) +[![Downloads](https://img.shields.io/pypi/dd/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) +[![Latest Version](https://img.shields.io/pypi/v/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) +[![Supported Python versions](https://img.shields.io/pypi/pyversions/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) +[![Supported Python implementations](https://img.shields.io/pypi/implementation/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) +[![Development Status](https://img.shields.io/pypi/status/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) +[![Wheel Status](https://img.shields.io/pypi/wheel/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) +[![License](https://img.shields.io/pypi/l/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) This is a Python implementation of Macaroons. PyMacaroons is stable and does not change frequently. Please see the GitHub issues for the current roadmap. @@ -97,7 +104,7 @@ The latest documentation can always be found on [ReadTheDocs](http://pymacaroons ## Python notes -Compatible with Python 2 and 3. CI builds are generated for 2.6, 2.7, 3.3 and 3.4, as well as PyPy and PyPy3. May be compatible with other versions (or may require tweaking - feel free to contribute!) +Compatible with Python 2 and 3. CI builds are generated for 2.7, 3.5, 3.6, 3.7, 3.8 and 3.9, as well as PyPy3. May be compatible with other versions (or may require tweaking - feel free to contribute!) ## Running Tests @@ -107,9 +114,9 @@ To run the tests: To run against a specific version of Python: -`tox -e py34` +`tox -e py39` -[tox](https://tox.readthedocs.org/en/latest/index.html) is used for running tests locally against multiple versions of Python. Tests will only run against versions available to tox. +[tox](https://tox.wiki/en/latest/) is used for running tests locally against multiple versions of Python. Tests will only run against versions available to tox. ## More Macaroons diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..eef2ade --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +python_files = *_tests.py diff --git a/requirements.txt b/requirements.txt index dd19a41..62afd2c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,12 +2,13 @@ -e . # Test Dependencies -nose==1.3.7 -coverage>=4.5,<4.99 +pytest +pytest-coverage +coverage mock>=2.0.0,<2.99 sphinx>=1.2.3 python-coveralls>=2.4.2 -hypothesis==1.0.0 +hypothesis==1.11.4 bumpversion tox yanc diff --git a/setup.py b/setup.py index 0231f1f..6b3815a 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ import os -import sys from setuptools import find_packages, setup @@ -36,11 +35,13 @@ def read_file(*paths): 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Internet :: WWW/HTTP', diff --git a/tests/functional_tests/encrypted_field_tests.py b/tests/functional_tests/encrypted_field_tests.py index cabde0d..85fc17f 100644 --- a/tests/functional_tests/encrypted_field_tests.py +++ b/tests/functional_tests/encrypted_field_tests.py @@ -1,7 +1,5 @@ from __future__ import unicode_literals -from nose.tools import * - from nacl.bindings import crypto_box_NONCEBYTES from pymacaroons import Macaroon, Verifier from pymacaroons.caveat_delegates import EncryptedFirstPartyCaveatDelegate, EncryptedFirstPartyCaveatVerifierDelegate @@ -26,10 +24,9 @@ def test_encrypted_first_party_caveat(self): )) m.first_party_caveat_delegate = EncryptedFirstPartyCaveatDelegate(field_encryptor=encryptor) m.add_first_party_caveat('test = caveat', encrypted=True) - assert_equal( - m.signature, + assert\ + m.signature ==\ 'a443bc61e8f45dca4f0c441d6cfde90b804cebb0b267aab60de1ec2ab8cc8522' - ) def test_verify_encrypted_first_party_exact_caveats(self): m = Macaroon( @@ -47,4 +44,4 @@ def test_verify_encrypted_first_party_exact_caveats(self): m, 'this is our super secret key; only we should know it' ) - assert_true(verified) + assert verified diff --git a/tests/functional_tests/functional_tests.py b/tests/functional_tests/functional_tests.py index 3807760..a9dcb62 100644 --- a/tests/functional_tests/functional_tests.py +++ b/tests/functional_tests/functional_tests.py @@ -2,7 +2,7 @@ import json from mock import * -from nose.tools import * +import pytest from nacl.bindings import crypto_box_NONCEBYTES from pymacaroons import Macaroon, MACAROON_V1, MACAROON_V2, Verifier @@ -22,10 +22,7 @@ def test_basic_signature(self): identifier='we used our secret key', key='this is our super secret key; only we should know it' ) - assert_equal( - m.signature, - 'e3d9e02908526c4c0039ae15114115d97fdd68bf2ba379b342aaf0f617d0552f' - ) + assert m.signature == 'e3d9e02908526c4c0039ae15114115d97fdd68bf2ba379b342aaf0f617d0552f' def test_first_party_caveat(self): m = Macaroon( @@ -34,10 +31,7 @@ def test_first_party_caveat(self): key='this is our super secret key; only we should know it' ) m.add_first_party_caveat('test = caveat') - assert_equal( - m.signature, - '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' - ) + assert m.signature == '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' def test_serializing(self): m = Macaroon( @@ -47,12 +41,9 @@ def test_serializing(self): version=MACAROON_V1 ) m.add_first_party_caveat('test = caveat') - assert_equal( - m.serialize(), - 'MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZ\ + assert m.serialize() == 'MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZ\ WQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1cmUgGXusegR\ K8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK' - ) def test_serializing_with_binary_v1(self): m = Macaroon( @@ -63,8 +54,8 @@ def test_serializing_with_binary_v1(self): ) m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize(m.serialize()) - assert_equal(m.identifier, n.identifier) - assert_equal(m.version, n.version) + assert m.identifier == n.identifier + assert m.version == n.version def test_serializing_with_binary_v2(self): identifier = base64.b64decode('AK2o+q0Aq9+bONkXw7ky7HAuhCLO9hhaMMc==') @@ -76,8 +67,8 @@ def test_serializing_with_binary_v2(self): ) m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize(m.serialize()) - assert_equal(m.identifier_bytes, n.identifier_bytes) - assert_equal(m.version, n.version) + assert m.identifier_bytes == n.identifier_bytes + assert m.version == n.version def test_serializing_v1(self): m = Macaroon( @@ -88,8 +79,8 @@ def test_serializing_v1(self): ) m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize(m.serialize()) - assert_equal(m.identifier, n.identifier) - assert_equal(m.version, n.version) + assert m.identifier == n.identifier + assert m.version == n.version def test_serializing_v2(self): m = Macaroon( @@ -100,11 +91,11 @@ def test_serializing_v2(self): ) m.add_first_party_caveat('test = caveat') n = Macaroon.deserialize(m.serialize()) - assert_equal(m.identifier_bytes, n.identifier_bytes) - assert_equal(m.version, n.version) + assert m.identifier_bytes == n.identifier_bytes + assert m.version == n.version def test_deserializing_invalid(self): - with assert_raises(MacaroonDeserializationException) as cm: + with pytest.raises(MacaroonDeserializationException) as cm: Macaroon.deserialize("QA") def test_serializing_strips_padding(self): @@ -115,31 +106,22 @@ def test_serializing_strips_padding(self): version=MACAROON_V1 ) m.add_first_party_caveat('test = acaveat') - assert_equal( - m.serialize(), - # In padded base64, this would end with '==' - ('MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz' - 'ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln' + # In padded base64, this would end with '==' + assert m.serialize() == ('MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVz'\ + 'ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln'\ 'bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg') - ) def test_serializing_max_length_packet(self): m = Macaroon(location='test', identifier='blah', key='secret', version=MACAROON_V1) m.add_first_party_caveat('x' * 65526) # exactly 0xFFFF - assert_not_equal( - m.serialize(), - None - ) + assert m.serialize() != None def test_serializing_too_long_packet(self): m = Macaroon(location='test', identifier='blah', key='secret', version=MACAROON_V1) m.add_first_party_caveat('x' * 65527) # one byte too long - assert_raises( - MacaroonSerializationException, - m.serialize - ) + pytest.raises(MacaroonSerializationException, m.serialize) def test_deserializing(self): m = Macaroon.deserialize( @@ -147,10 +129,7 @@ def test_deserializing(self): VyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1\ cmUgGXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK' ) - assert_equal( - m.signature, - '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' - ) + assert m.signature == '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' def test_deserializing_with_binary(self): m = Macaroon.deserialize( @@ -158,10 +137,7 @@ def test_deserializing_with_binary(self): VyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1\ cmUgGXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK'.encode('ascii') ) - assert_equal( - m.signature, - '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' - ) + assert m.signature == '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' def test_deserializing_accepts_padding(self): m = Macaroon.deserialize( @@ -169,10 +145,7 @@ def test_deserializing_accepts_padding(self): 'ZWQgb3VyIHNlY3JldCBrZXkKMDAxN2NpZCB0ZXN0ID0gYWNhdmVhdAowMDJmc2ln' 'bmF0dXJlIJRJ_V3WNJQnqlVq5eez7spnltwU_AXs8NIRY739sHooCg==') ) - assert_equal( - m.signature, - '9449fd5dd6349427aa556ae5e7b3eeca6796dc14fc05ecf0d21163bdfdb07a28' - ) + assert m.signature == '9449fd5dd6349427aa556ae5e7b3eeca6796dc14fc05ecf0d21163bdfdb07a28' def test_serializing_json_v1(self): m = Macaroon( @@ -182,10 +155,8 @@ def test_serializing_json_v1(self): version=MACAROON_V1 ) m.add_first_party_caveat('test = caveat') - assert_equal( - json.loads(m.serialize(serializer=JsonSerializer()))['signature'], + assert json.loads(m.serialize(serializer=JsonSerializer()))['signature'] ==\ "197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67" - ) def test_serializing_json_v2_with_binary(self): id = base64.b64decode('AK2o+q0Aq9+bONkXw7ky7HAuhCLO9hhaMMc==') @@ -195,15 +166,14 @@ def test_serializing_json_v2_with_binary(self): key='this is our super secret key; only we should know it', version=MACAROON_V2 ) - assert_equal( - json.loads(m.serialize(serializer=JsonSerializer()))['i64'], + assert json.loads(m.serialize(serializer=JsonSerializer()))['i64'] ==\ "AK2o-q0Aq9-bONkXw7ky7HAuhCLO9hhaMMc" - ) + n = Macaroon.deserialize( m.serialize(serializer=JsonSerializer()), serializer=JsonSerializer() ) - assert_equal(m.identifier_bytes, n.identifier_bytes) + assert m.identifier_bytes == n.identifier_bytes def test_serializing_json_v2(self): m = Macaroon( @@ -213,10 +183,9 @@ def test_serializing_json_v2(self): version=MACAROON_V2 ) m.add_first_party_caveat('test = caveat') - assert_equal( - json.loads(m.serialize(serializer=JsonSerializer()))['s64'], + assert\ + json.loads(m.serialize(serializer=JsonSerializer()))['s64'] ==\ "GXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWc" - ) def test_deserializing_json_v1(self): m = Macaroon.deserialize( @@ -225,10 +194,9 @@ def test_deserializing_json_v1(self): 3dbd67", "caveats": [{"cl": null, "cid": "test = caveat", "vid": null}]}', serializer=JsonSerializer() ) - assert_equal( - m.signature, + assert\ + m.signature ==\ '197bac7a044af33332865b9266e26d493bdd668a660e44d88ce1a998c23dbd67' - ) def test_deserializing_json_v2(self): m = Macaroon.deserialize( @@ -237,10 +205,9 @@ def test_deserializing_json_v2(self): ', "c": [{"l": null, "i": "test = caveat", "v": null}]}', serializer=JsonSerializer() ) - assert_equal( - m.signature_bytes, + assert \ + m.signature_bytes ==\ binascii.hexlify(b'197bac7a044af33332') - ) def test_serializing_deserializing_json_v1(self): self._serializing_deserializing_json_with_version(MACAROON_V1) @@ -260,7 +227,7 @@ def _serializing_deserializing_json_with_version(self, version): m.serialize(serializer=JsonSerializer()), serializer=JsonSerializer() ) - assert_equal(m.signature, n.signature) + assert m.signature == n.signature def test_verify_first_party_exact_caveats(self): m = Macaroon( @@ -275,7 +242,7 @@ def test_verify_first_party_exact_caveats(self): m, 'this is our super secret key; only we should know it' ) - assert_true(verified) + assert verified def test_verify_first_party_general_caveats(self): m = Macaroon( @@ -294,7 +261,7 @@ def general_caveat_validator(predicate): m, 'this is our super secret key; only we should know it' ) - assert_true(verified) + assert verified @patch('nacl.secret.random') def test_third_party_caveat(self, rand_nonce): @@ -313,10 +280,9 @@ def test_third_party_caveat(self, rand_nonce): caveat_key = '4; guaranteed random by a fair toss of the dice' identifier = 'this was how we remind auth of key/pred' m.add_third_party_caveat('http://auth.mybank/', caveat_key, identifier) - assert_equal( - m.signature, + assert\ + m.signature ==\ 'd27db2fd1f22760e4c3dae8137e2d8fc1df6c0741c18aed4b97256bf78d1f55c' - ) def test_serializing_macaroon_with_first_and_third_caveats_v1(self): self._serializing_macaroon_with_first_and_third_caveats(MACAROON_V1) @@ -339,10 +305,7 @@ def _serializing_macaroon_with_first_and_third_caveats(self, version): n = Macaroon.deserialize(m.serialize()) - assert_equal( - m.signature, - n.signature - ) + assert m.signature == n.signature @patch('nacl.secret.random') def test_prepare_for_request(self, rand_nonce): @@ -373,10 +336,9 @@ def test_prepare_for_request(self, rand_nonce): ) discharge.add_first_party_caveat('time < 2015-01-01T00:00') protected = m.prepare_for_request(discharge) - assert_equal( - protected.signature, + assert\ + protected.signature ==\ '2eb01d0dd2b4475330739140188648cf25dda0425ea9f661f1574ca0a9eac54e' - ) def test_verify_third_party_caveats(self): m = Macaroon( @@ -406,7 +368,7 @@ def test_verify_third_party_caveats(self): 'this is a different super-secret key; \ never use the same secret twice' ) - assert_true(verified) + assert verified def test_verify_third_party_caveats_multi_level(self): # See https://github.com/ecordell/pymacaroons/issues/37 @@ -425,7 +387,7 @@ def test_verify_third_party_caveats_multi_level(self): discharge2 = root.prepare_for_request(discharge2) verified = Verifier(discharge_macaroons=[discharge1, discharge2]).verify(root, "root-key") - assert_true(verified) + assert verified @patch('nacl.secret.random') def test_inspect(self, rand_nonce): @@ -443,20 +405,20 @@ def test_inspect(self, rand_nonce): caveat_key = '4; guaranteed random by a fair toss of the dice' identifier = 'this was how we remind auth of key/pred' m.add_third_party_caveat('http://auth.mybank/', caveat_key, identifier) - assert_equal(m.inspect(), ( + assert m.inspect() == ( 'location http://mybank/\n' 'identifier we used our secret key\n' 'cid test = caveat\n' 'cid this was how we remind auth of key/pred\n' 'vid AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68NYajhiFuHnKGSNcVhkAwgbs0VZ0yK2o+q0Aq9+bONkXw7ky7HAuhCLO9hhaMMc\n' 'cl http://auth.mybank/\n' - 'signature 7a9289bfbb92d725f748bbcb4f3e04e56b7021513ebeed8411bfba10a16a662e')) + 'signature 7a9289bfbb92d725f748bbcb4f3e04e56b7021513ebeed8411bfba10a16a662e') - @raises(MacaroonUnmetCaveatException) def test_mutual_discharge(self): m1 = Macaroon(location="", identifier="root-id", key="root-key") m1.add_third_party_caveat("bob", "bob-caveat-root-key", "bob-is-great") m2 = Macaroon(location="bob", identifier="bob-is-great", key="bob-caveat-root-key") m2.add_third_party_caveat("charlie", "bob-caveat-root-key", "bob-is-great") m2 = m1.prepare_for_request(m2) - Verifier(discharge_macaroons=[m2]).verify(m1, "root-key") + with pytest.raises(MacaroonUnmetCaveatException): + Verifier(discharge_macaroons=[m2]).verify(m1, "root-key") diff --git a/tests/functional_tests/serialization_tests.py b/tests/functional_tests/serialization_tests.py index 4ddd749..63f3152 100644 --- a/tests/functional_tests/serialization_tests.py +++ b/tests/functional_tests/serialization_tests.py @@ -1,4 +1,3 @@ -from nose.tools import * from pymacaroons import Macaroon, Verifier, MACAROON_V1, MACAROON_V2 from pymacaroons.serializers import JsonSerializer @@ -66,13 +65,13 @@ def test_from_go_macaroon_json_v2(self): def assert_macaroon(m, discharge, version): - assert_equal(m.location, 'my location') - assert_equal(m.version, version) - assert_equal(m.identifier_bytes, b'my identifier') + assert m.location == 'my location' + assert m.version == version + assert m.identifier_bytes == b'my identifier' v = Verifier(discharge_macaroons=[discharge]) v.satisfy_exact('fp caveat') verified = v.verify( m, "my secret key", ) - assert_true(verified) + assert verified diff --git a/tests/property_tests/macaroon_property_tests.py b/tests/property_tests/macaroon_property_tests.py index 1fbe554..ce889be 100644 --- a/tests/property_tests/macaroon_property_tests.py +++ b/tests/property_tests/macaroon_property_tests.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -from nose.tools import * from hypothesis import * from hypothesis.specifiers import * @@ -36,9 +35,9 @@ def test_serializing_deserializing_macaroon(self, key_id, loc, key): version=MACAROON_V1 ) deserialized = Macaroon.deserialize(macaroon.serialize()) - assert_equal(macaroon.identifier, deserialized.identifier) - assert_equal(macaroon.location, deserialized.location) - assert_equal(macaroon.signature, deserialized.signature) + assert macaroon.identifier == deserialized.identifier + assert macaroon.location == deserialized.location + assert macaroon.signature == deserialized.signature macaroon = Macaroon( location=loc, identifier=key_id, @@ -46,6 +45,6 @@ def test_serializing_deserializing_macaroon(self, key_id, loc, key): version=MACAROON_V2 ) deserialized = Macaroon.deserialize(macaroon.serialize()) - assert_equal(macaroon.identifier_bytes, deserialized.identifier_bytes) - assert_equal(macaroon.location, deserialized.location) - assert_equal(macaroon.signature, deserialized.signature) + assert macaroon.identifier_bytes == deserialized.identifier_bytes + assert macaroon.location == deserialized.location + assert macaroon.signature == deserialized.signature diff --git a/tox.ini b/tox.ini index 1241e1f..a9f3a7a 100644 --- a/tox.ini +++ b/tox.ini @@ -1,16 +1,11 @@ [tox] -envlist = py26, py27, py33, py34, py35, pypy, pypy3.3-5.5-alpha, flake8, docs +envlist = py27, py35, py36, py37, py38, py39, pypy3, flake8, docs skip_missing_interpreters=True [testenv] deps=-rrequirements.txt commands= - nosetests --with-yanc - -[testenv:py26] -deps=-rrequirements.txt -commands= - nosetests tests/functional_tests --with-yanc + pytest {posargs} [testenv:docs] basepython=python @@ -28,4 +23,14 @@ commands= [testenv:coverage] deps=-rrequirements.txt commands= - nosetests --with-coverage --cover-erase --cover-package=pymacaroons + pytest --cov=pymacaroons --cov-report term-missing --cov-report html + +[gh-actions] +python = + 2.7: py27 + 3.5: py35 + 3.6: py36 + 3.7: py37 + 3.8: py38 + 3.9: py39 + pypy3: pypy3