Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-josepy for openSUSE:Factory checked in at 2021-05-10 15:39:08 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-josepy (Old) and /work/SRC/openSUSE:Factory/.python-josepy.new.2988 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-josepy" Mon May 10 15:39:08 2021 rev:10 rq:891882 version:1.8.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-josepy/python-josepy.changes 2021-03-08 15:20:55.062099515 +0100 +++ /work/SRC/openSUSE:Factory/.python-josepy.new.2988/python-josepy.changes 2021-05-10 15:41:53.200967362 +0200 @@ -1,0 +2,9 @@ +Sun May 9 14:43:52 UTC 2021 - Dirk M??ller <dmuel...@suse.com> + +- update to 1.8.0: + * Removed external mock dependency. + * Removed dependency on six. + * Deprecated the module josepy.magic_typing. + * Fix JWS/JWK generation with EC keys when keys or signatures have leading zeros. + +------------------------------------------------------------------- Old: ---- josepy-1.7.0.tar.gz josepy-1.7.0.tar.gz.asc New: ---- josepy-1.8.0.tar.gz josepy-1.8.0.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-josepy.spec ++++++ --- /var/tmp/diff_new_pack.bwsNHp/_old 2021-05-10 15:41:53.660965563 +0200 +++ /var/tmp/diff_new_pack.bwsNHp/_new 2021-05-10 15:41:53.664965547 +0200 @@ -20,7 +20,7 @@ %define libname josepy %global skip_python2 1 Name: python-%{libname} -Version: 1.7.0 +Version: 1.8.0 Release: 0 Summary: JOSE protocol implementation in Python License: Apache-2.0 @@ -31,16 +31,13 @@ BuildRequires: %{python_module coverage >= 4.0} BuildRequires: %{python_module cryptography >= 0.8} BuildRequires: %{python_module devel >= 2.7} -BuildRequires: %{python_module mock} BuildRequires: %{python_module pyOpenSSL >= 0.13} BuildRequires: %{python_module pytest >= 2.8.0} BuildRequires: %{python_module setuptools >= 1.0} -BuildRequires: %{python_module six >= 1.9.0} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-cryptography >= 0.8 Requires: python-pyOpenSSL >= 0.13 -Requires: python-six >= 1.9.0 Conflicts: python-acme < 0.21.0 Obsoletes: python-%{libname}-doc BuildArch: noarch ++++++ josepy-1.7.0.tar.gz -> josepy-1.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/CHANGELOG.rst new/josepy-1.8.0/CHANGELOG.rst --- old/josepy-1.7.0/CHANGELOG.rst 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/CHANGELOG.rst 2021-03-16 00:18:22.000000000 +0100 @@ -1,6 +1,14 @@ Changelog ========= +1.8.0 (2021-03-15) +----------------- + +* Removed external mock dependency. +* Removed dependency on six. +* Deprecated the module josepy.magic_typing. +* Fix JWS/JWK generation with EC keys when keys or signatures have leading zeros. + 1.7.0 (2021-02-11) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/PKG-INFO new/josepy-1.8.0/PKG-INFO --- old/josepy-1.7.0/PKG-INFO 2021-02-11 20:42:42.238660600 +0100 +++ new/josepy-1.8.0/PKG-INFO 2021-03-16 00:18:48.011415200 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: josepy -Version: 1.7.0 +Version: 1.8.0 Summary: JOSE protocol implementation in Python Home-page: https://github.com/certbot/josepy Author: Certbot Project @@ -35,6 +35,5 @@ Classifier: Topic :: Security Requires-Python: >=3.6 Provides-Extra: dev -Provides-Extra: dev3 Provides-Extra: docs Provides-Extra: tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/docs/conf.py new/josepy-1.8.0/docs/conf.py --- old/josepy-1.7.0/docs/conf.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/docs/conf.py 2021-03-16 00:18:22.000000000 +0100 @@ -63,9 +63,9 @@ # built documents. # # The short X.Y version. -version = u'1.7' +version = u'1.8' # The full version, including alpha/beta/rc tags. -release = u'1.7.0' +release = u'1.8.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/pytest.ini new/josepy-1.8.0/pytest.ini --- old/josepy-1.7.0/pytest.ini 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/pytest.ini 2021-03-16 00:18:22.000000000 +0100 @@ -1,4 +1,6 @@ [pytest] addopts = -v --flake8 --cov-report xml --cov-report=term-missing --cov=josepy --cov-config .coveragerc +filterwarnings = + error norecursedirs = *.egg .eggs dist build docs .tox flake8-ignore = W504 E501 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/setup.py new/josepy-1.8.0/setup.py --- old/josepy-1.7.0/setup.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/setup.py 2021-03-16 00:18:22.000000000 +0100 @@ -2,7 +2,7 @@ from setuptools import find_packages, setup -version = '1.7.0' +version = '1.8.0' # Please update tox.ini when modifying dependency version requirements install_requires = [ @@ -14,7 +14,6 @@ # For pkg_resources. >=1.0 so pip resolves it to a version cryptography # will tolerate; see #2599: 'setuptools>=1.0', - 'six>=1.9.0', # needed for python_2_unicode_compatible ] testing_requires = [ @@ -24,18 +23,14 @@ 'flake8', 'pytest-flake8>=0.5', 'pytest>=2.8.0', - 'mock', ] dev_extras = [ + 'mypy', 'pytest', 'tox', ] -dev3_extras = [ - 'mypy', -] - docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', @@ -76,7 +71,6 @@ install_requires=install_requires, extras_require={ 'dev': dev_extras, - 'dev3': dev3_extras, 'docs': docs_extras, 'tests': testing_requires, }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/b64.py new/josepy-1.8.0/src/josepy/b64.py --- old/josepy-1.7.0/src/josepy/b64.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/b64.py 2021-03-16 00:18:22.000000000 +0100 @@ -12,8 +12,6 @@ """ import base64 -import six - def b64encode(data): """JOSE Base64 encode. @@ -27,8 +25,8 @@ :raises TypeError: if ``data`` is of incorrect type """ - if not isinstance(data, six.binary_type): - raise TypeError('argument should be {0}'.format(six.binary_type)) + if not isinstance(data, bytes): + raise TypeError('argument should be bytes') return base64.urlsafe_b64encode(data).rstrip(b'=') @@ -46,13 +44,13 @@ :raises ValueError: if input is unicode with non-ASCII characters """ - if isinstance(data, six.string_types): + if isinstance(data, str): try: data = data.encode('ascii') except UnicodeEncodeError: raise ValueError( 'unicode argument should contain only ASCII characters') - elif not isinstance(data, six.binary_type): + elif not isinstance(data, bytes): raise TypeError('argument should be a str or unicode') return base64.urlsafe_b64decode(data + b'=' * (4 - (len(data) % 4))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/b64_test.py new/josepy-1.8.0/src/josepy/b64_test.py --- old/josepy-1.7.0/src/josepy/b64_test.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/b64_test.py 2021-03-16 00:18:22.000000000 +0100 @@ -1,7 +1,6 @@ """Tests for josepy.b64.""" import unittest -import six # https://en.wikipedia.org/wiki/Base64#Examples B64_PADDING_EXAMPLES = { @@ -14,8 +13,8 @@ B64_URL_UNSAFE_EXAMPLES = { - six.int2byte(251) + six.int2byte(239): b'--8', - six.int2byte(255) * 2: b'__8', + bytes((251, 239)): b'--8', + bytes((255,)) * 2: b'__8', } @@ -31,11 +30,11 @@ self.assertEqual(self._call(b''), b'') def test_unsafe_url(self): - for text, b64 in six.iteritems(B64_URL_UNSAFE_EXAMPLES): + for text, b64 in B64_URL_UNSAFE_EXAMPLES.items(): self.assertEqual(self._call(text), b64) def test_different_paddings(self): - for text, (b64, _) in six.iteritems(B64_PADDING_EXAMPLES): + for text, (b64, _) in B64_PADDING_EXAMPLES.items(): self.assertEqual(self._call(text), b64) def test_unicode_fails_with_type_error(self): @@ -51,15 +50,15 @@ return b64decode(data) def test_unsafe_url(self): - for text, b64 in six.iteritems(B64_URL_UNSAFE_EXAMPLES): + for text, b64 in B64_URL_UNSAFE_EXAMPLES.items(): self.assertEqual(self._call(b64), text) def test_input_without_padding(self): - for text, (b64, _) in six.iteritems(B64_PADDING_EXAMPLES): + for text, (b64, _) in B64_PADDING_EXAMPLES.items(): self.assertEqual(self._call(b64), text) def test_input_with_padding(self): - for text, (b64, pad) in six.iteritems(B64_PADDING_EXAMPLES): + for text, (b64, pad) in B64_PADDING_EXAMPLES.items(): self.assertEqual(self._call(b64 + pad), text) def test_unicode_with_ascii(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/interfaces.py new/josepy-1.8.0/src/josepy/interfaces.py --- old/josepy-1.7.0/src/josepy/interfaces.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/interfaces.py 2021-03-16 00:18:22.000000000 +0100 @@ -2,21 +2,16 @@ import abc import json -import six from josepy import errors, util -try: - from collections.abc import Sequence, Mapping # pylint: disable=import-error -except ImportError: - from collections import Sequence, Mapping +from collections.abc import Sequence, Mapping # pylint: disable=no-self-argument,no-method-argument,no-init,inherit-non-class # pylint: disable=too-few-public-methods -@six.add_metaclass(abc.ABCMeta) -class JSONDeSerializable(object): +class JSONDeSerializable(object, metaclass=abc.ABCMeta): # pylint: disable=too-few-public-methods """Interface for (de)serializable JSON objects. @@ -139,7 +134,7 @@ def _serialize(obj): if isinstance(obj, JSONDeSerializable): return _serialize(obj.to_partial_json()) - if isinstance(obj, six.string_types): # strings are Sequence + if isinstance(obj, str): # strings are Sequence return obj elif isinstance(obj, list): return [_serialize(subobj) for subobj in obj] @@ -149,7 +144,7 @@ return tuple(_serialize(subobj) for subobj in obj) elif isinstance(obj, Mapping): return dict((_serialize(key), _serialize(value)) - for key, value in six.iteritems(obj)) + for key, value in obj.items()) else: return obj diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/interfaces_test.py new/josepy-1.8.0/src/josepy/interfaces_test.py --- old/josepy-1.7.0/src/josepy/interfaces_test.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/interfaces_test.py 2021-03-16 00:18:22.000000000 +0100 @@ -66,7 +66,7 @@ def test_to_json_other(self): mock_value = object() - self.assertTrue(self.Basic(mock_value).to_json() is mock_value) + self.assertIs(self.Basic(mock_value).to_json(), mock_value) def test_to_json_nested(self): self.assertEqual(self.nested.to_json(), [['foo1']]) @@ -80,9 +80,9 @@ def test_json_loads(self): seq = self.Sequence.json_loads('["foo1", "foo2"]') - self.assertTrue(isinstance(seq, self.Sequence)) - self.assertTrue(isinstance(seq.x, self.Basic)) - self.assertTrue(isinstance(seq.y, self.Basic)) + self.assertIsInstance(seq, self.Sequence) + self.assertIsInstance(seq.x, self.Basic) + self.assertIsInstance(seq.y, self.Basic) self.assertEqual(seq.x.v, 'foo1') self.assertEqual(seq.y.v, 'foo2') @@ -101,8 +101,8 @@ jobj = JSONDeSerializable.json_dump_default(self.seq) self.assertEqual(len(jobj), 2) - self.assertTrue(jobj[0] is self.basic1) - self.assertTrue(jobj[1] is self.basic2) + self.assertIs(jobj[0], self.basic1) + self.assertIs(jobj[1], self.basic2) def test_json_dump_default_type_error(self): from josepy.interfaces import JSONDeSerializable diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/json_util.py new/josepy-1.8.0/src/josepy/json_util.py --- old/josepy-1.7.0/src/josepy/json_util.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/json_util.py 2021-03-16 00:18:22.000000000 +0100 @@ -11,7 +11,6 @@ import logging import OpenSSL -import six from josepy import b64, errors, interfaces, util @@ -106,7 +105,7 @@ elif isinstance(value, dict): return util.frozendict( dict((cls.default_decoder(key), cls.default_decoder(value)) - for key, value in six.iteritems(value))) + for key, value in value.items())) else: # integer or string return value @@ -164,21 +163,23 @@ for base in bases: fields.update(getattr(base, '_fields', {})) # Do not reorder, this class might override fields from base classes! - for key, value in tuple(six.iteritems(dikt)): - # not six.iterkeys() (in-place edit!) + # We create a tuple based on dikt.items() here because the loop + # modifies dikt. + for key, value in tuple(dikt.items()): if isinstance(value, Field): fields[key] = dikt.pop(key) dikt['_orig_slots'] = dikt.get('__slots__', ()) dikt['__slots__'] = tuple( - list(dikt['_orig_slots']) + list(six.iterkeys(fields))) + list(dikt['_orig_slots']) + list(fields.keys())) dikt['_fields'] = fields return abc.ABCMeta.__new__(mcs, name, bases, dikt) -@six.add_metaclass(JSONObjectWithFieldsMeta) -class JSONObjectWithFields(util.ImmutableMap, interfaces.JSONDeSerializable): +class JSONObjectWithFields(util.ImmutableMap, + interfaces.JSONDeSerializable, + metaclass=JSONObjectWithFieldsMeta): # pylint: disable=too-few-public-methods """JSON object with fields. @@ -210,7 +211,7 @@ def _defaults(cls): """Get default fields values.""" return dict([(slot, field.default) for slot, field - in six.iteritems(cls._fields)]) + in cls._fields.items()]) def __init__(self, **kwargs): # pylint: disable=star-args @@ -237,7 +238,7 @@ """Serialize fields to JSON.""" jobj = {} omitted = set() - for slot, field in six.iteritems(self._fields): + for slot, field in self._fields.items(): value = getattr(self, slot) if field.omit(value): @@ -257,7 +258,7 @@ @classmethod def _check_required(cls, jobj): missing = set() - for _, field in six.iteritems(cls._fields): + for _, field in cls._fields.items(): if not field.omitempty and field.json_name not in jobj: missing.add(field.json_name) @@ -271,7 +272,7 @@ """Deserialize fields from JSON.""" cls._check_required(jobj) fields = {} - for slot, field in six.iteritems(cls._fields): + for slot, field in cls._fields.items(): if field.json_name not in jobj and field.omitempty: fields[slot] = field.default else: @@ -311,10 +312,9 @@ :rtype: bytes """ - error_cls = TypeError if six.PY2 else binascii.Error try: decoded = b64.b64decode(data.encode()) - except error_cls as error: + except binascii.Error as error: raise errors.DeserializationError(error) if size is not None and ((not minimum and len(decoded) != size) or @@ -350,10 +350,9 @@ if size is not None and ((not minimum and len(value) != size * 2) or (minimum and len(value) < size * 2)): raise errors.DeserializationError() - error_cls = TypeError if six.PY2 else binascii.Error try: return binascii.unhexlify(value) - except error_cls as error: + except binascii.Error as error: raise errors.DeserializationError(error) @@ -433,7 +432,7 @@ @classmethod def get_type_cls(cls, jobj): """Get the registered class for ``jobj``.""" - if cls in six.itervalues(cls.TYPES): + if cls in cls.TYPES.values(): if cls.type_field_name not in jobj: raise errors.DeserializationError( "Missing type field ({0})".format(cls.type_field_name)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/json_util_test.py new/josepy-1.8.0/src/josepy/json_util_test.py --- old/josepy-1.7.0/src/josepy/json_util_test.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/json_util_test.py 2021-03-16 00:18:22.000000000 +0100 @@ -1,9 +1,7 @@ """Tests for josepy.json_util.""" import itertools import unittest - -import mock -import six +from unittest import mock from josepy import errors, interfaces, test_util, util @@ -18,8 +16,8 @@ from josepy.json_util import Field for default, omitempty, value in itertools.product( [True, False], [True, False], [True, False]): - self.assertFalse( - Field("foo", default=default, omitempty=omitempty).omit(value)) + self.assertIs( + Field("foo", default=default, omitempty=omitempty).omit(value), False) def test_descriptors(self): mock_value = mock.MagicMock() @@ -54,14 +52,14 @@ mock_field = MockField() from josepy.json_util import Field - self.assertTrue(Field.default_encoder(mock_field) is mock_field) + self.assertIs(Field.default_encoder(mock_field), mock_field) # in particular... self.assertNotEqual('foo', Field.default_encoder(mock_field)) def test_default_encoder_passthrough(self): mock_value = mock.MagicMock() from josepy.json_util import Field - self.assertTrue(Field.default_encoder(mock_value) is mock_value) + self.assertIs(Field.default_encoder(mock_value), mock_value) def test_default_decoder_list_to_tuple(self): from josepy.json_util import Field @@ -70,13 +68,13 @@ def test_default_decoder_dict_to_frozendict(self): from josepy.json_util import Field obj = Field.default_decoder({'x': 2}) - self.assertTrue(isinstance(obj, util.frozendict)) + self.assertIsInstance(obj, util.frozendict) self.assertEqual(obj, util.frozendict(x=2)) def test_default_decoder_passthrough(self): mock_value = mock.MagicMock() from josepy.json_util import Field - self.assertTrue(Field.default_decoder(mock_value) is mock_value) + self.assertIs(Field.default_decoder(mock_value), mock_value) class JSONObjectWithFieldsMetaTest(unittest.TestCase): @@ -90,8 +88,7 @@ # pylint: disable=invalid-name,missing-docstring,too-few-public-methods # pylint: disable=blacklisted-name - @six.add_metaclass(JSONObjectWithFieldsMeta) - class A(object): + class A(object, metaclass=JSONObjectWithFieldsMeta): __slots__ = ('bar',) baz = self.field @@ -246,13 +243,13 @@ def test_encode_b64jose(self): from josepy.json_util import encode_b64jose encoded = encode_b64jose(b'x') - self.assertTrue(isinstance(encoded, six.string_types)) + self.assertIsInstance(encoded, str) self.assertEqual(u'eA', encoded) def test_decode_b64jose(self): from josepy.json_util import decode_b64jose decoded = decode_b64jose(u'eA') - self.assertTrue(isinstance(decoded, six.binary_type)) + self.assertIsInstance(decoded, bytes) self.assertEqual(b'x', decoded) def test_decode_b64jose_padding_error(self): @@ -278,13 +275,13 @@ from josepy.json_util import encode_hex16 encoded = encode_hex16(b'foo') self.assertEqual(u'666f6f', encoded) - self.assertTrue(isinstance(encoded, six.string_types)) + self.assertIsInstance(encoded, str) def test_decode_hex16(self): from josepy.json_util import decode_hex16 decoded = decode_hex16(u'666f6f') self.assertEqual(b'foo', decoded) - self.assertTrue(isinstance(decoded, six.binary_type)) + self.assertIsInstance(decoded, bytes) def test_decode_hex16_minimum_size(self): from josepy.json_util import decode_hex16 @@ -304,7 +301,7 @@ def test_decode_cert(self): from josepy.json_util import decode_cert cert = decode_cert(self.b64_cert) - self.assertTrue(isinstance(cert, util.ComparableX509)) + self.assertIsInstance(cert, util.ComparableX509) self.assertEqual(cert, CERT) self.assertRaises(errors.DeserializationError, decode_cert, u'') @@ -315,7 +312,7 @@ def test_decode_csr(self): from josepy.json_util import decode_csr csr = decode_csr(self.b64_csr) - self.assertTrue(isinstance(csr, util.ComparableX509)) + self.assertIsInstance(csr, util.ComparableX509) self.assertEqual(csr, CSR) self.assertRaises(errors.DeserializationError, decode_csr, u'') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/jwa.py new/josepy-1.8.0/src/josepy/jwa.py --- old/josepy-1.7.0/src/josepy/jwa.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/jwa.py 2021-03-16 00:18:22.000000000 +0100 @@ -17,10 +17,7 @@ from josepy import errors, interfaces, jwk -try: - from collections.abc import Hashable # pylint: disable=import-error -except ImportError: - from collections import Hashable +from collections.abc import Hashable logger = logging.getLogger(__name__) @@ -175,8 +172,9 @@ """Sign the ``msg`` using ``key``.""" sig = self._sign(key, msg) dr, ds = decode_dss_signature(sig) - return (dr.to_bytes(length=math.ceil(dr.bit_length() / 8), byteorder='big') + - ds.to_bytes(length=math.ceil(ds.bit_length() / 8), byteorder='big')) + length = math.ceil(key.key_size / 8) + return (dr.to_bytes(length=length, byteorder='big') + + ds.to_bytes(length=length, byteorder='big')) def _sign(self, key, msg): # If cryptography library supports new style api (v1.4 and later) @@ -201,6 +199,9 @@ def verify(self, key, msg, sig): """Verify the ``msg` and ``sig`` using ``key``.""" rlen = math.ceil(key.key_size / 8) + if len(sig) != 2 * rlen: + # Format error - rfc7518 - 3.4 ??? MUST NOT be shortened to omit any leading zero octets + return False asn1sig = encode_dss_signature( int.from_bytes(sig[0:rlen], byteorder='big'), int.from_bytes(sig[rlen:], byteorder='big') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/jwa_test.py new/josepy-1.8.0/src/josepy/jwa_test.py --- old/josepy-1.7.0/src/josepy/jwa_test.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/jwa_test.py 2021-03-16 00:18:22.000000000 +0100 @@ -1,7 +1,6 @@ """Tests for josepy.jwa.""" import unittest - -import mock +from unittest import mock from josepy import errors, test_util @@ -52,7 +51,7 @@ def test_from_json(self): from josepy.jwa import JWASignature from josepy.jwa import RS256 - self.assertTrue(JWASignature.from_json('RS256') is RS256) + self.assertIs(JWASignature.from_json('RS256'), RS256) class JWAHSTest(unittest.TestCase): # pylint: disable=too-few-public-methods @@ -64,8 +63,8 @@ b"\r\x85+\x0e\x85\xaeUZ\xd4\xb3\x97zO" ) self.assertEqual(HS256.sign(b'some key', b'foo'), sig) - self.assertTrue(HS256.verify(b'some key', b'foo', sig) is True) - self.assertTrue(HS256.verify(b'some key', b'foo', sig + b'!') is False) + self.assertIs(HS256.verify(b'some key', b'foo', sig), True) + self.assertIs(HS256.verify(b'some key', b'foo', sig + b'!'), False) class JWARSTest(unittest.TestCase): @@ -89,22 +88,22 @@ b'\xd2\xb9.>}\xfd' ) self.assertEqual(RS256.sign(RSA512_KEY, b'foo'), sig) - self.assertTrue(RS256.verify(RSA512_KEY.public_key(), b'foo', sig)) - self.assertFalse(RS256.verify( - RSA512_KEY.public_key(), b'foo', sig + b'!')) + self.assertIs(RS256.verify(RSA512_KEY.public_key(), b'foo', sig), True) + self.assertIs(RS256.verify( + RSA512_KEY.public_key(), b'foo', sig + b'!'), False) def test_ps(self): from josepy.jwa import PS256 sig = PS256.sign(RSA1024_KEY, b'foo') - self.assertTrue(PS256.verify(RSA1024_KEY.public_key(), b'foo', sig)) - self.assertFalse(PS256.verify( - RSA1024_KEY.public_key(), b'foo', sig + b'!')) + self.assertIs(PS256.verify(RSA1024_KEY.public_key(), b'foo', sig), True) + self.assertIs(PS256.verify( + RSA1024_KEY.public_key(), b'foo', sig + b'!'), False) def test_sign_new_api(self): from josepy.jwa import RS256 key = mock.MagicMock() RS256.sign(key, "message") - self.assertTrue(key.sign.called) + self.assertIs(key.sign.called, True) def test_sign_old_api(self): from josepy.jwa import RS256 @@ -112,16 +111,15 @@ signer = mock.MagicMock() key.signer.return_value = signer RS256.sign(key, "message") - self.assertTrue(all([ - key.signer.called, - signer.update.called, - signer.finalize.called])) + self.assertIs(key.signer.called, True) + self.assertIs(signer.update.called, True) + self.assertIs(signer.finalize.called, True) def test_verify_new_api(self): from josepy.jwa import RS256 key = mock.MagicMock() RS256.verify(key, "message", "signature") - self.assertTrue(key.verify.called) + self.assertIs(key.verify.called, True) def test_verify_old_api(self): from josepy.jwa import RS256 @@ -129,10 +127,9 @@ verifier = mock.MagicMock() key.verifier.return_value = verifier RS256.verify(key, "message", "signature") - self.assertTrue(all([ - key.verifier.called, - verifier.update.called, - verifier.verify.called])) + self.assertIs(key.verifier.called, True) + self.assertIs(verifier.update.called, True) + self.assertIs(verifier.verify.called, True) class JWAECTest(unittest.TestCase): @@ -146,19 +143,19 @@ from josepy.jwa import ES256 message = b'foo' signature = ES256.sign(EC_P256_KEY, message) - self.assertTrue(ES256.verify(EC_P256_KEY.public_key(), message, signature)) + self.assertIs(ES256.verify(EC_P256_KEY.public_key(), message, signature), True) def test_es384_sign_and_verify(self): from josepy.jwa import ES384 message = b'foo' signature = ES384.sign(EC_P384_KEY, message) - self.assertTrue(ES384.verify(EC_P384_KEY.public_key(), message, signature)) + self.assertIs(ES384.verify(EC_P384_KEY.public_key(), message, signature), True) def test_verify_with_wrong_jwa(self): from josepy.jwa import ES256, ES384 message = b'foo' signature = ES256.sign(EC_P256_KEY, message) - self.assertFalse(ES384.verify(EC_P384_KEY.public_key(), message, signature)) + self.assertIs(ES384.verify(EC_P384_KEY.public_key(), message, signature), False) def test_verify_with_different_key(self): from josepy.jwa import ES256 @@ -168,7 +165,7 @@ message = b'foo' signature = ES256.sign(EC_P256_KEY, message) different_key = ec.generate_private_key(ec.SECP256R1, default_backend()) - self.assertFalse(ES256.verify(different_key.public_key(), message, signature)) + self.assertIs(ES256.verify(different_key.public_key(), message, signature), False) def test_sign_new_api(self): from josepy.jwa import ES256 @@ -176,26 +173,25 @@ with mock.patch("josepy.jwa.decode_dss_signature") as decode_patch: decode_patch.return_value = (0, 0) ES256.sign(key, "message") - self.assertTrue(key.sign.called) + self.assertIs(key.sign.called, True) def test_sign_old_api(self): from josepy.jwa import ES256 - key = mock.MagicMock(spec=[u'signer']) + key = mock.MagicMock(spec=[u'signer'], key_size=256) signer = mock.MagicMock() key.signer.return_value = signer with mock.patch("josepy.jwa.decode_dss_signature") as decode_patch: decode_patch.return_value = (0, 0) ES256.sign(key, "message") - self.assertTrue(all([ - key.signer.called, - signer.update.called, - signer.finalize.called])) + self.assertIs(key.signer.called, True) + self.assertIs(signer.update.called, True) + self.assertIs(signer.finalize.called, True) def test_verify_new_api(self): from josepy.jwa import ES256 - key = mock.MagicMock() - ES256.verify(key, "message", "signature".encode()) - self.assertTrue(key.verify.called) + key = mock.MagicMock(key_size=256) + ES256.verify(key, "message", b'\x00' * int(key.key_size / 8) * 2) + self.assertIs(key.verify.called, True) def test_verify_old_api(self): from josepy.jwa import ES256 @@ -203,11 +199,26 @@ verifier = mock.MagicMock() key.verifier.return_value = verifier key.key_size = 65 * 8 - ES256.verify(key, "message", "signature".encode()) - self.assertTrue(all([ - key.verifier.called, - verifier.update.called, - verifier.verify.called])) + ES256.verify(key, "message", b'\x00' * int(key.key_size / 8) * 2) + self.assertIs(key.verifier.called, True) + self.assertIs(verifier.update.called, True) + self.assertIs(verifier.verify.called, True) + + def test_signature_size(self): + from josepy.jwa import ES512 + from josepy.jwk import JWK + key = JWK.from_json( + { + 'd': 'Af9KP6DqLRbtit6NS_LRIaCP_-NdC5l5R2ugbILdfpv6dS9R4wUPNxiGw-vVWumA56Yo1oBnEm8ZdR4W-u1lPHw5', + 'x': 'PiLhJPInTuJkmQeSkoQ64gKmfogeSfPACWt_7XDVrl2o6xF7fQQQJI3i8XFp4Ca10FIIoHAKruHWrhs-AysxS8U', + 'y': 'cCVfGtpuNzH_IHEY5ueb8OQRAwkrUTr04djfHdXEXlVegpz3cIbgYuho--mFlC9me3kR8TFCg-S3A4whWEEdoVE', + 'crv': 'P-521', + 'kty': 'EC' + }) + with mock.patch("josepy.jwa.decode_dss_signature") as decode_patch: + decode_patch.return_value = (0, 0) + sig = ES512.sign(key.key, b"test") + self.assertEqual(len(sig), 2 * 66) if __name__ == '__main__': diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/jwk.py new/josepy-1.8.0/src/josepy/jwk.py --- old/josepy-1.7.0/src/josepy/jwk.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/jwk.py 2021-03-16 00:18:22.000000000 +0100 @@ -1,11 +1,10 @@ """JSON Web Key.""" import abc -import binascii import json import logging +import math import cryptography.exceptions -import six from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes # type: ignore from cryptography.hazmat.primitives import serialization @@ -48,7 +47,7 @@ """ digest = hashes.Hash(hash_function(), backend=default_backend()) digest.update(json.dumps( - dict((k, v) for k, v in six.iteritems(self.to_json()) + dict((k, v) for k, v in self.to_json().items() if k in self.required), **self._thumbprint_json_dumps_params).encode()) return digest.finalize() @@ -114,7 +113,7 @@ key, cls.cryptography_key_types): raise errors.Error('Unable to deserialize {0} into {1}'.format( key.__class__, cls.__class__)) - for jwk_cls in six.itervalues(cls.TYPES): + for jwk_cls in cls.TYPES.values(): if isinstance(key, jwk_cls.cryptography_key_types): return jwk_cls(key=key) raise errors.Error('Unsupported algorithm: {0}'.format(key.__class__)) @@ -165,25 +164,21 @@ @classmethod def _encode_param(cls, data): """Encode Base64urlUInt. - :type data: long :rtype: unicode - """ - - def _leading_zeros(arg): - if len(arg) % 2: - return '0' + arg - return arg - - return json_util.encode_b64jose(binascii.unhexlify( - _leading_zeros(hex(data)[2:].rstrip('L')))) + length = max(data.bit_length(), 8) # decoding 0 + length = math.ceil(length / 8) + return json_util.encode_b64jose(data.to_bytes(byteorder="big", length=length)) @classmethod def _decode_param(cls, data): """Decode Base64urlUInt.""" try: - return int(binascii.hexlify(json_util.decode_b64jose(data)), 16) + binary = json_util.decode_b64jose(data) + if not binary: + raise errors.DeserializationError() + return int.from_bytes(binary, byteorder="big") except ValueError: # invalid literal for long() with base 16 raise errors.DeserializationError() @@ -251,7 +246,7 @@ 'qi': private.iqmp, } return dict((key, self._encode_param(value)) - for key, value in six.iteritems(params)) + for key, value in params.items()) @JWK.register @@ -281,14 +276,9 @@ :type data: long :rtype: unicode """ - - def _leading_zeros(arg): - if len(arg) % 2: - return '0' + arg - return arg - - return json_util.encode_b64jose(binascii.unhexlify( - _leading_zeros(hex(data)[2:].rstrip('L')))) + length = max(data.bit_length(), 8) # decoding 0 + length = math.ceil(length / 8) + return json_util.encode_b64jose(data.to_bytes(byteorder="big", length=length)) @classmethod def _decode_param(cls, data, name, valid_lengths): @@ -301,7 +291,7 @@ 'after base64-decoding; got {length} bytes instead'.format( name=name, valid_lengths=valid_lengths, length=len(binary)) ) - return int(binascii.hexlify(binary), 16) + return int.from_bytes(binary, byteorder="big") except ValueError: # invalid literal for long() with base 16 raise errors.DeserializationError() @@ -348,7 +338,7 @@ 'Supplied key is neither of type EllipticCurvePublicKey nor EllipticCurvePrivateKey') params['x'] = public.x params['y'] = public.y - params = {key: self._encode_param(value) for key, value in six.iteritems(params)} + params = {key: self._encode_param(value) for key, value in params.items()} params['crv'] = self._curve_name_to_crv(public.curve.name) return params diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/jwk_test.py new/josepy-1.8.0/src/josepy/jwk_test.py --- old/josepy-1.7.0/src/josepy/jwk_test.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/jwk_test.py 2021-03-16 00:18:22.000000000 +0100 @@ -64,7 +64,7 @@ self.assertEqual(self.jwk, JWKOct.load(b'foo')) def test_public_key(self): - self.assertTrue(self.jwk.public_key() is self.jwk) + self.assertIs(self.jwk.public_key(), self.jwk) class JWKRSATest(unittest.TestCase, JWKTestBaseMixin): @@ -108,8 +108,7 @@ self.jwk = self.private def test_init_auto_comparable(self): - self.assertTrue(isinstance( - self.jwk256_not_comparable.key, util.ComparableRSAKey)) + self.assertIsInstance(self.jwk256_not_comparable.key, util.ComparableRSAKey) self.assertEqual(self.jwk256, self.jwk256_not_comparable) def test_encode_param_zero(self): @@ -226,8 +225,8 @@ self.jwk = self.private def test_init_auto_comparable(self): - self.assertTrue(isinstance( - self.jwk256_not_comparable.key, util.ComparableECKey)) + self.assertIsInstance( + self.jwk256_not_comparable.key, util.ComparableECKey) self.assertEqual(self.jwk256, self.jwk256_not_comparable) def test_encode_param_zero(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/jws.py new/josepy-1.8.0/src/josepy/jws.py --- old/josepy-1.7.0/src/josepy/jws.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/jws.py 2021-03-16 00:18:22.000000000 +0100 @@ -4,7 +4,6 @@ import sys import OpenSSL -import six from josepy import b64, errors, json_util, jwa, jwk, util @@ -76,7 +75,7 @@ def not_omitted(self): """Fields that would not be omitted in the JSON object.""" return dict((name, getattr(self, name)) - for name, field in six.iteritems(self._fields) + for name, field in self._fields.items() if not field.omit(getattr(self, name))) def __add__(self, other): @@ -357,9 +356,9 @@ protect=set(args.protect)) if args.compact: - six.print_(sig.to_compact().decode('utf-8')) + print(sig.to_compact().decode('utf-8')) else: # JSON - six.print_(sig.json_dumps_pretty()) + print(sig.json_dumps_pretty()) @classmethod def verify(cls, args): @@ -370,7 +369,7 @@ try: sig = JWS.json_loads(sys.stdin.read()) except errors.Error as error: - six.print_(error) + print(error) return -1 if args.key is not None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/jws_test.py new/josepy-1.8.0/src/josepy/jws_test.py --- old/josepy-1.7.0/src/josepy/jws_test.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/jws_test.py 2021-03-16 00:18:22.000000000 +0100 @@ -1,8 +1,8 @@ """Tests for josepy.jws.""" import base64 import unittest +from unittest import mock -import mock import OpenSSL from josepy import errors, json_util, jwa, jwk, test_util @@ -116,13 +116,13 @@ self.assertEqual(self.mixed.signature.combined.jwk, self.pubkey) def test_sign_unprotected(self): - self.assertTrue(self.unprotected.verify()) + self.assertIs(self.unprotected.verify(), True) def test_sign_protected(self): - self.assertTrue(self.protected.verify()) + self.assertIs(self.protected.verify(), True) def test_sign_mixed(self): - self.assertTrue(self.mixed.verify()) + self.assertIs(self.mixed.verify(), True) def test_compact_lost_unprotected(self): compact = self.mixed.to_compact() @@ -146,8 +146,8 @@ protected_jobj = self.protected.to_partial_json(flat=True) unprotected_jobj = self.unprotected.to_partial_json(flat=True) - self.assertTrue('protected' not in unprotected_jobj) - self.assertTrue('header' not in protected_jobj) + self.assertNotIn('protected', unprotected_jobj) + self.assertNotIn('header', protected_jobj) unprotected_jobj['header'] = unprotected_jobj['header'].to_json() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/magic_typing.py new/josepy-1.8.0/src/josepy/magic_typing.py --- old/josepy-1.7.0/src/josepy/magic_typing.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/magic_typing.py 2021-03-16 00:18:22.000000000 +0100 @@ -1,5 +1,10 @@ """Shim class to not have to depend on typing module in prod.""" import sys +import warnings + + +warnings.warn("josepy.magic_typing is deprecated and will be removed in a future release.", + DeprecationWarning) class TypingClass(object): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/magic_typing_test.py new/josepy-1.8.0/src/josepy/magic_typing_test.py --- old/josepy-1.7.0/src/josepy/magic_typing_test.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/magic_typing_test.py 2021-03-16 00:18:22.000000000 +0100 @@ -1,8 +1,8 @@ """Tests for josepy.magic_typing.""" import sys import unittest - -import mock +import warnings +from unittest import mock class MagicTypingTest(unittest.TestCase): @@ -18,24 +18,13 @@ sys.modules['typing'] = typing_class_mock if 'josepy.magic_typing' in sys.modules: del sys.modules['josepy.magic_typing'] # pragma: no cover - from josepy.magic_typing import Text # pylint: disable=no-name-in-module + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + from josepy.magic_typing import Text # pylint: disable=no-name-in-module self.assertEqual(Text, text_mock) del sys.modules['josepy.magic_typing'] sys.modules['typing'] = temp_typing - def test_import_failure(self): - try: - import typing as temp_typing - except ImportError: # pragma: no cover - temp_typing = None # pragma: no cover - sys.modules['typing'] = None - if 'josepy.magic_typing' in sys.modules: - del sys.modules['josepy.magic_typing'] # pragma: no cover - from josepy.magic_typing import Text # pylint: disable=no-name-in-module - self.assertTrue(Text is None) - del sys.modules['josepy.magic_typing'] - sys.modules['typing'] = temp_typing - if __name__ == '__main__': unittest.main() # pragma: no cover diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/util.py new/josepy-1.8.0/src/josepy/util.py --- old/josepy-1.7.0/src/josepy/util.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/util.py 2021-03-16 00:18:22.000000000 +0100 @@ -1,11 +1,7 @@ """JOSE utilities.""" -try: - from collections.abc import Hashable, Mapping # pylint: disable=import-error -except ImportError: - from collections import Hashable, Mapping +from collections.abc import Hashable, Mapping import OpenSSL -import six from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import ec, rsa @@ -211,7 +207,7 @@ def __repr__(self): return '{0}({1})'.format(self.__class__.__name__, ', '.join( '{0}={1!r}'.format(key, value) - for key, value in six.iteritems(self))) + for key, value in self.items())) class frozendict(Mapping, Hashable): # type: ignore @@ -229,7 +225,7 @@ # TODO: support generators/iterators object.__setattr__(self, '_items', items) - object.__setattr__(self, '_keys', tuple(sorted(six.iterkeys(items)))) + object.__setattr__(self, '_keys', tuple(sorted(items.keys()))) def __getitem__(self, key): return self._items[key] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy/util_test.py new/josepy-1.8.0/src/josepy/util_test.py --- old/josepy-1.7.0/src/josepy/util_test.py 2021-02-11 20:42:03.000000000 +0100 +++ new/josepy-1.8.0/src/josepy/util_test.py 2021-03-16 00:18:22.000000000 +0100 @@ -2,7 +2,6 @@ import functools import unittest -import six from josepy import test_util @@ -21,7 +20,7 @@ self.cert_other = test_util.load_comparable_cert('cert-san.pem') def test_getattr_proxy(self): - self.assertTrue(self.cert1.has_expired()) + self.assertIs(self.cert1.has_expired(), True) def test_eq(self): self.assertEqual(self.req1, self.req2) @@ -78,17 +77,17 @@ self.assertNotEqual(ComparableRSAKey(5), ComparableRSAKey(5)) def test_hash(self): - self.assertTrue(isinstance(hash(self.key), int)) + self.assertIsInstance(hash(self.key), int) self.assertEqual(hash(self.key), hash(self.key_same)) self.assertNotEqual(hash(self.key), hash(self.key2)) def test_repr(self): - self.assertTrue(repr(self.key).startswith( - '<ComparableRSAKey(<cryptography.hazmat.')) + self.assertIs(repr(self.key).startswith( + '<ComparableRSAKey(<cryptography.hazmat.'), True) def test_public_key(self): from josepy.util import ComparableRSAKey - self.assertTrue(isinstance(self.key.public_key(), ComparableRSAKey)) + self.assertIsInstance(self.key.public_key(), ComparableRSAKey) class ComparableECKeyTest(unittest.TestCase): @@ -123,18 +122,18 @@ self.assertNotEqual(ComparableECKey(5), ComparableECKey(5)) def test_hash(self): - self.assertTrue(isinstance(hash(self.p256_key), int)) + self.assertIsInstance(hash(self.p256_key), int) self.assertEqual(hash(self.p256_key), hash(self.p256_key_same)) self.assertNotEqual(hash(self.p256_key), hash(self.p384_key)) self.assertNotEqual(hash(self.p256_key), hash(self.p521_key)) def test_repr(self): - self.assertTrue(repr(self.p256_key).startswith( - '<ComparableECKey(<cryptography.hazmat.')) + self.assertIs(repr(self.p256_key).startswith( + '<ComparableECKey(<cryptography.hazmat.'), True) def test_public_key(self): from josepy.util import ComparableECKey - self.assertTrue(isinstance(self.p256_key.public_key(), ComparableECKey)) + self.assertIsInstance(self.p256_key.public_key(), ComparableECKey) class ImmutableMapTest(unittest.TestCase): @@ -219,13 +218,13 @@ def test_init_other_raises_type_error(self): from josepy.util import frozendict # specifically fail for generators... - self.assertRaises(TypeError, frozendict, six.iteritems({'a': 'b'})) + self.assertRaises(TypeError, frozendict, {'a': 'b'}.items()) def test_len(self): self.assertEqual(2, len(self.fdict)) def test_hash(self): - self.assertTrue(isinstance(hash(self.fdict), int)) + self.assertIsInstance(hash(self.fdict), int) def test_getattr_proxy(self): self.assertEqual(1, self.fdict.x) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy.egg-info/PKG-INFO new/josepy-1.8.0/src/josepy.egg-info/PKG-INFO --- old/josepy-1.7.0/src/josepy.egg-info/PKG-INFO 2021-02-11 20:42:42.000000000 +0100 +++ new/josepy-1.8.0/src/josepy.egg-info/PKG-INFO 2021-03-16 00:18:47.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: josepy -Version: 1.7.0 +Version: 1.8.0 Summary: JOSE protocol implementation in Python Home-page: https://github.com/certbot/josepy Author: Certbot Project @@ -35,6 +35,5 @@ Classifier: Topic :: Security Requires-Python: >=3.6 Provides-Extra: dev -Provides-Extra: dev3 Provides-Extra: docs Provides-Extra: tests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/josepy-1.7.0/src/josepy.egg-info/requires.txt new/josepy-1.8.0/src/josepy.egg-info/requires.txt --- old/josepy-1.7.0/src/josepy.egg-info/requires.txt 2021-02-11 20:42:42.000000000 +0100 +++ new/josepy-1.8.0/src/josepy.egg-info/requires.txt 2021-03-16 00:18:47.000000000 +0100 @@ -1,15 +1,12 @@ cryptography>=0.8 PyOpenSSL>=0.13 setuptools>=1.0 -six>=1.9.0 [dev] +mypy pytest tox -[dev3] -mypy - [docs] Sphinx>=1.0 sphinx_rtd_theme @@ -21,4 +18,3 @@ flake8 pytest-flake8>=0.5 pytest>=2.8.0 -mock