From a23dccef97711f37de8b461b9bbbb4e68c2fbe38 Mon Sep 17 00:00:00 2001 From: KOLANICH Date: Thu, 3 Nov 2022 14:18:56 +0300 Subject: [PATCH] Got rid of `six`. --- pgpy/constants.py | 14 +-- pgpy/decorators.py | 4 +- pgpy/memoryview.py | 128 ------------------------ pgpy/packet/packets.py | 6 +- pgpy/packet/subpackets/signature.py | 20 ++-- pgpy/packet/subpackets/userattribute.py | 3 - pgpy/packet/types.py | 9 +- pgpy/pgp.py | 24 ++--- pgpy/symenc.py | 6 +- pgpy/types.py | 55 ++++------ setup.cfg | 1 - tests/test_04_PGP_objects.py | 19 ++-- tests/test_04_copy.py | 3 +- 13 files changed, 56 insertions(+), 236 deletions(-) delete mode 100644 pgpy/memoryview.py diff --git a/pgpy/constants.py b/pgpy/constants.py index c55fb8b8..1a609c7d 100644 --- a/pgpy/constants.py +++ b/pgpy/constants.py @@ -16,8 +16,6 @@ from pyasn1.type.univ import ObjectIdentifier -import six - from cryptography.hazmat.backends import openssl from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.ciphers import algorithms @@ -63,13 +61,8 @@ def __rand__(self, other): # pragma: no cover return self & other -if six.PY2: - class FlagEnum(IntEnum): - __metaclass__ = FlagEnumMeta - -else: - namespace = FlagEnumMeta.__prepare__('FlagEnum', (IntEnum,)) - FlagEnum = FlagEnumMeta('FlagEnum', (IntEnum,), namespace) +namespace = FlagEnumMeta.__prepare__('FlagEnum', (IntEnum,)) +FlagEnum = FlagEnumMeta('FlagEnum', (IntEnum,), namespace) @@ -336,9 +329,6 @@ def compress(self, data): raise NotImplementedError(self) def decompress(self, data): - if six.PY2: - data = bytes(data) - if self is CompressionAlgorithm.Uncompressed: return data diff --git a/pgpy/decorators.py b/pgpy/decorators.py index eb3212a3..8a050c15 100644 --- a/pgpy/decorators.py +++ b/pgpy/decorators.py @@ -2,7 +2,6 @@ """ import contextlib import functools -import six import logging try: @@ -116,8 +115,7 @@ def check_attributes(self, key): "".format(attr=attr, eval=str(expected), got=str(getattr(key, attr)))) def __call__(self, action): - # @functools.wraps(action) - @six.wraps(action) + @functools.wraps(action) def _action(key, *args, **kwargs): if key._key is None: raise PGPError("No key!") diff --git a/pgpy/memoryview.py b/pgpy/memoryview.py deleted file mode 100644 index 35f38017..00000000 --- a/pgpy/memoryview.py +++ /dev/null @@ -1,128 +0,0 @@ -""" util.py -""" -import six - -__all__ = ('memoryview', ) - -memoryview = memoryview - -if six.PY2: - # because Python2's memoryview can't be released directly, nor can it be used as a context manager - # this wrapper object should hopefully make the behavior more uniform to python 3's - import __builtin__ - import functools - - # this decorator will raise a ValueError if the wrapped memoryview object has been "released" - def notreleased(meth): - @functools.wraps(meth) - def _inner(self, *args, **kwargs): - if self._mem is None: - raise ValueError("operation forbidden on released memoryview object") - return meth(self, *args, **kwargs) - - return _inner - - class memoryview(object): # flake8: noqa - @property - @notreleased - def obj(self): - """The underlying object of the memoryview.""" - return self._obj - - @property - @notreleased - def nbytes(self): - # nbytes == product(shape) * itemsize == len(m.tobytes()) - nb = 1 - for dim in self.shape: - nb *= dim - return nb * self.itemsize - - # TODO: c_contiguous -> (self.ndim == 0 or ???) - # TODO: f_contiguous -> (self.ndim == 0 or ???) - # TODO: contiguous -> return self.c_contiguous or self.f_contiguous - - def __new__(cls, obj, parent=None): - memview = object.__new__(cls) - memview._obj = obj if parent is None else parent.obj - return memview - - def __init__(self, obj): - if not hasattr(self, '_mem'): - if not isinstance(obj, __builtin__.memoryview): - obj = __builtin__.memoryview(obj) - self._mem = obj - - def __dir__(self): - # so dir(...) looks like a memoryview object, and also - # contains our additional methods and properties, but not our instance members - return sorted(set(self.__class__.__dict__) | set(dir(self._mem))) - - @notreleased - def __getitem__(self, item): - # if this is a slice, it'll return another real memoryview object - # we'll need to wrap that subview in another memoryview wrapper - if isinstance(item, slice): - return memoryview(self._mem.__getitem__(item)) - - return self._mem.__getitem__(item) - - @notreleased - def __setitem__(self, key, value): - self._mem.__setitem__(key, value) - - @notreleased - def __delitem__(self, key): - raise TypeError("cannot delete memory") - - def __getattribute__(self, item): - try: - return object.__getattribute__(self, item) - - except AttributeError: - if object.__getattribute__(self, '_mem') is None: - raise ValueError("operation forbidden on released memoryview object") - - return object.__getattribute__(self, '_mem').__getattribute__(item) - - def __setattr__(self, key, value): - if key not in self.__dict__ and hasattr(__builtin__.memoryview, key): - # there are no writable attributes on memoryview objects - # changing indexed values is handled by __setitem__ - raise AttributeError("attribute '{}' of 'memoryview' objects is not writable".format(key)) - - else: - object.__setattr__(self, key, value) - - @notreleased - def __len__(self): - return len(self._mem) - - def __eq__(self, other): - if isinstance(other, memoryview): - return self._mem == other._mem - - return self._mem == other - - @notreleased - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.release() - - def __repr__(self): - return '<{}memory at 0x{:02X}>'.format('' if self._mem else 'released ', id(self)) - - def release(self): - """Release the underlying buffer exposed by the memoryview object""" - # this should effectively do the same job as memoryview.release() in Python 3 - self._mem = None - self._obj = None - - @notreleased - def hex(self): - """Return the data in the buffer as a string of hexadecimal numbers.""" - return ''.join(('{:02X}'.format(ord(c)) for c in self._mem)) - - # TODO: cast diff --git a/pgpy/packet/packets.py b/pgpy/packet/packets.py index 36e5c1df..d1738abc 100644 --- a/pgpy/packet/packets.py +++ b/pgpy/packet/packets.py @@ -11,8 +11,6 @@ from datetime import datetime, timezone -import six - from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.asymmetric import padding @@ -697,7 +695,7 @@ def signer(self): return self._signer @signer.register(str) - @signer.register(six.text_type) + @signer.register(str) def signer_str(self, val): self._signer = val @@ -719,7 +717,7 @@ def __bytearray__(self): _bytes += bytearray([self.sigtype]) _bytes += bytearray([self.halg]) _bytes += bytearray([self.pubalg]) - _bytes += binascii.unhexlify(six.b(self.signer)) + _bytes += binascii.unhexlify(self.signer.encode("latin-1")) _bytes += bytearray([int(self.nested)]) return _bytes diff --git a/pgpy/packet/subpackets/signature.py b/pgpy/packet/subpackets/signature.py index 4b7d7d93..2991bb76 100644 --- a/pgpy/packet/subpackets/signature.py +++ b/pgpy/packet/subpackets/signature.py @@ -10,8 +10,6 @@ from datetime import timedelta from datetime import timezone -import six - from .types import EmbeddedSignatureHeader from .types import Signature @@ -69,7 +67,7 @@ def uri(self): return self._uri @uri.register(str) - @uri.register(six.text_type) + @uri.register(str) def uri_str(self, val): self._uri = val @@ -420,7 +418,7 @@ def regex(self): return self._regex @regex.register(str) - @regex.register(six.text_type) + @regex.register(str) def regex_str(self, val): self._regex = val @@ -550,7 +548,7 @@ def fingerprint(self): return self._fingerprint @fingerprint.register(str) - @fingerprint.register(six.text_type) + @fingerprint.register(str) @fingerprint.register(Fingerprint) def fingerprint_str(self, val): self._fingerprint = Fingerprint(val) @@ -633,7 +631,7 @@ def name(self): return self._name @name.register(str) - @name.register(six.text_type) + @name.register(str) def name_str(self, val): self._name = val @@ -646,7 +644,7 @@ def value(self): return self._value @value.register(str) - @value.register(six.text_type) + @value.register(str) def value_str(self, val): self._value = val @@ -761,7 +759,7 @@ def userid(self): return self._userid @userid.register(str) - @userid.register(six.text_type) + @userid.register(str) def userid_str(self, val): self._userid = val @@ -805,7 +803,7 @@ def string(self): return self._string @string.register(str) - @string.register(six.text_type) + @string.register(str) def string_str(self, val): self._string = val @@ -932,7 +930,7 @@ def issuer_fingerprint(self): return self._issuer_fpr @issuer_fingerprint.register(str) - @issuer_fingerprint.register(six.text_type) + @issuer_fingerprint.register(str) @issuer_fingerprint.register(Fingerprint) def issuer_fingerprint_str(self, val): self._issuer_fpr = Fingerprint(val) @@ -1004,7 +1002,7 @@ def intended_recipient(self): return self._intended_recipient @intended_recipient.register(str) - @intended_recipient.register(six.text_type) + @intended_recipient.register(str) @intended_recipient.register(Fingerprint) def intended_recipient_str(self, val): self._intended_recipient = Fingerprint(val) diff --git a/pgpy/packet/subpackets/userattribute.py b/pgpy/packet/subpackets/userattribute.py index 32f74102..407deb92 100644 --- a/pgpy/packet/subpackets/userattribute.py +++ b/pgpy/packet/subpackets/userattribute.py @@ -8,8 +8,6 @@ from ...decorators import sdproperty -from ...memoryview import memoryview - __all__ = ('Image',) @@ -100,7 +98,6 @@ def __bytearray__(self): def parse(self, packet): super(Image, self).parse(packet) - # on Python 2, this will be the wrapper object from memoryview.py with memoryview(packet) as _head: _, self.version, self.iencoding, _, _, _ = struct.unpack_from('").format(self.email) - return six.u("{:s}{:s}{:s}").format(self.name, comment, email) + comment = "" if self.comment == "" else " ({:s})".format(self.comment) + email = "" if self.email == "" else " <{:s}>".format(self.email) + return "{:s}{:s}{:s}".format(self.name, comment, email) raise NotImplementedError @@ -945,7 +943,7 @@ def signers(self): @property def type(self): ##TODO: it might be better to use an Enum for the output of this - if isinstance(self._message, (six.string_types, six.binary_type, bytearray)): + if isinstance(self._message, (str, bytes, bytearray)): return 'cleartext' if isinstance(self._message, LiteralData): @@ -1043,7 +1041,7 @@ def __or__(self, other): self |= pkt return self - if isinstance(other, (six.string_types, six.binary_type, bytearray)): + if isinstance(other, (str, bytes, bytearray)): if self._message is None: self._message = self.text_to_bytes(other) return self @@ -1139,7 +1137,7 @@ def new(cls, message, **kwargs): if charset: msg.charset = charset - # if format in 'tu' and isinstance(message, (six.binary_type, bytearray)): + # if format in 'tu' and isinstance(message, (bytes, bytearray)): # # if message format is text or unicode and we got binary data, we'll need to transcode it to UTF-8 # message = @@ -1153,7 +1151,7 @@ def new(cls, message, **kwargs): # if format is None, we can try to detect it if format is None: - if isinstance(message, six.text_type): + if isinstance(message, str): # message is definitely UTF-8 already format = 'u' @@ -1166,7 +1164,7 @@ def new(cls, message, **kwargs): format = 'b' # if message is a binary type and we're building a textual message, we need to transcode the bytes to UTF-8 - if isinstance(message, (six.binary_type, bytearray)) and (cleartext or format in 'tu'): + if isinstance(message, (bytes, bytearray)) and (cleartext or format in 'tu'): message = message.decode(charset or 'utf-8') if cleartext: @@ -2428,7 +2426,7 @@ def verify(self, subject, signature=None): sspairs = [] # some type checking - if not isinstance(subject, (type(None), PGPMessage, PGPKey, PGPUID, PGPSignature, six.string_types, bytes, bytearray)): + if not isinstance(subject, (type(None), PGPMessage, PGPKey, PGPUID, PGPSignature, str, bytes, bytearray)): raise TypeError("Unexpected subject value: {:s}".format(str(type(subject)))) if not isinstance(signature, (type(None), PGPSignature)): raise TypeError("Unexpected signature value: {:s}".format(str(type(signature)))) @@ -2697,7 +2695,7 @@ def __init__(self, *args): def __contains__(self, alias): aliases = set().union(*self._aliases) - if isinstance(alias, six.string_types): + if isinstance(alias, str): return alias in aliases or alias.replace(' ', '') in aliases return alias in aliases # pragma: no cover diff --git a/pgpy/symenc.py b/pgpy/symenc.py index 988564a4..59a0aa0e 100644 --- a/pgpy/symenc.py +++ b/pgpy/symenc.py @@ -1,7 +1,5 @@ """ symenc.py """ -import six - from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends import default_backend @@ -31,7 +29,7 @@ def _encrypt(pt, key, alg, iv=None): encryptor = Cipher(alg.cipher(key), modes.CFB(iv), default_backend()).encryptor() except UnsupportedAlgorithm as ex: # pragma: no cover - six.raise_from(PGPEncryptionError, ex) + raise PGPEncryptionError from ex else: return bytearray(encryptor.update(pt) + encryptor.finalize()) @@ -52,7 +50,7 @@ def _decrypt(ct, key, alg, iv=None): decryptor = Cipher(alg.cipher(key), modes.CFB(iv), default_backend()).decryptor() except UnsupportedAlgorithm as ex: # pragma: no cover - six.raise_from(PGPDecryptionError, ex) + raise PGPDecryptionError from ex else: return bytearray(decryptor.update(ct) + decryptor.finalize()) diff --git a/pgpy/types.py b/pgpy/types.py index 916d02c5..bea4f460 100644 --- a/pgpy/types.py +++ b/pgpy/types.py @@ -17,8 +17,6 @@ from enum import EnumMeta from enum import IntEnum -import six - from .decorators import sdproperty from .errors import PGPError @@ -36,12 +34,8 @@ 'Fingerprint', 'SorteDeque'] -if six.PY2: - FileNotFoundError = IOError - re.ASCII = 0 - -class Armorable(six.with_metaclass(abc.ABCMeta)): +class Armorable(metaclass=abc.ABCMeta): __crc24_init = 0x0B704CE __crc24_poly = 0x1864CFB @@ -83,7 +77,7 @@ def charset(self, encoding): @staticmethod def is_ascii(text): - if isinstance(text, six.string_types): + if isinstance(text, str): return bool(re.match(r'^[ -~\r\n\t]*$', text, flags=re.ASCII)) if isinstance(text, (bytes, bytearray)): @@ -141,7 +135,7 @@ def ascii_unarmor(text): m['body'] = bytearray(base64.b64decode(m['body'].encode())) except (binascii.Error, TypeError) as ex: - six.raise_from(PGPError(str(ex)), ex) + raise PGPError(str(ex)) from ex if m['crc'] is not None: m['crc'] = Header.bytes_to_int(base64.b64decode(m['crc'].encode())) @@ -163,7 +157,7 @@ def crc24(data): crc = Armorable.__crc24_init if not isinstance(data, bytearray): - data = six.iterbytes(data) + data = iter(data) for b in data: crc ^= b << 16 @@ -196,7 +190,7 @@ def from_file(cls, filename): @classmethod def from_blob(cls, blob): obj = cls() - if (not isinstance(blob, six.binary_type)) and (not isinstance(blob, bytearray)): + if (not isinstance(blob, bytes)) and (not isinstance(blob, bytearray)): po = obj.parse(bytearray(blob, 'latin-1')) else: @@ -254,7 +248,7 @@ def __init__(self): self._parent = None -class PGPObject(six.with_metaclass(abc.ABCMeta, object)): +class PGPObject(metaclass=abc.ABCMeta): @staticmethod def int_byte_len(i): @@ -263,16 +257,6 @@ def int_byte_len(i): @staticmethod def bytes_to_int(b, order='big'): # pragma: no cover """convert bytes to integer""" - if six.PY2: - # save the original type of b without having to copy any data - _b = b.__class__() - if order != 'little': - b = reversed(b) - - if not isinstance(_b, bytearray): - b = six.iterbytes(b) - - return sum(c << (i * 8) for i, c in enumerate(b)) return int.from_bytes(b, order) @@ -281,10 +265,6 @@ def int_to_bytes(i, minlen=1, order='big'): # pragma: no cover """convert integer to bytes""" blen = max(minlen, PGPObject.int_byte_len(i), 1) - if six.PY2: - r = iter(_ * 8 for _ in (range(blen) if order == 'little' else range(blen - 1, -1, -1))) - return bytes(bytearray((i >> c) & 0xff for c in r)) - return i.to_bytes(blen, order) @staticmethod @@ -293,7 +273,7 @@ def text_to_bytes(text): return text # if we got bytes, just return it - if isinstance(text, (bytearray, six.binary_type)): + if isinstance(text, (bytearray, bytes)): return text # if we were given a unicode string, or if we translated the string into utf-8, @@ -302,7 +282,7 @@ def text_to_bytes(text): @staticmethod def bytes_to_text(text): - if text is None or isinstance(text, six.text_type): + if text is None or isinstance(text, str): return text return text.decode('utf-8') @@ -359,7 +339,7 @@ def length(self): def length_int(self, val): self._len = val - @length.register(six.binary_type) + @length.register(bytes) @length.register(bytearray) def length_bin(self, val): def _new_len(b): @@ -536,7 +516,7 @@ def _makeobj(cls): nh.parse(packet) except Exception as ex: - six.raise_from(PGPError(str(ex)), ex) + raise PGPError(str(ex)) from ex header = nh @@ -556,7 +536,7 @@ def _makeobj(cls): obj.parse(packet) except Exception as ex: - six.raise_from(PGPError(str(ex)), ex) + raise PGPError(str(ex)) from ex else: obj = _makeobj(cls) @@ -564,7 +544,7 @@ def _makeobj(cls): return obj -class Dispatchable(six.with_metaclass(MetaDispatchable, PGPObject)): +class Dispatchable(PGPObject, metaclass=MetaDispatchable): @abc.abstractproperty def __headercls__(self): # pragma: no cover @@ -612,8 +592,7 @@ def bad_signatures(self): # pragma: no cover ``sigsubj.subject`` - the subject that was verified using the signature. """ - for s in [ i for i in self._subjects if i.issues ]: - yield s + yield from [ i for i in self._subjects if i.issues ] def __init__(self): """ @@ -676,7 +655,7 @@ def __eq__(self, other): if isinstance(other, Fingerprint): return str(self) == str(other) - if isinstance(other, (six.text_type, bytes, bytearray)): + if isinstance(other, (str, bytes, bytearray)): if isinstance(other, (bytes, bytearray)): # pragma: no cover other = other.decode('latin-1') @@ -694,7 +673,7 @@ def __hash__(self): return hash(str(self)) def __bytes__(self): - return binascii.unhexlify(six.b(self)) + return binascii.unhexlify(self.encode("latin-1")) def __pretty__(self): content = self @@ -704,8 +683,8 @@ def __pretty__(self): # store in the format: "AAAA BBBB CCCC DDDD EEEE FFFF 0000 1111 2222 3333" # ^^ note 2 spaces here spaces = [ ' ' if i != 4 else ' ' for i in range(10) ] - chunks = [ ''.join(g) for g in six.moves.zip_longest(*[iter(content)] * 4) ] - content = ''.join(j for i in six.moves.zip_longest(chunks, spaces, fillvalue='') for j in i).strip() + chunks = [ ''.join(g) for g in itertools.zip_longest(*[iter(content)] * 4) ] + content = ''.join(j for i in itertools.zip_longest(chunks, spaces, fillvalue='') for j in i).strip() return content def __repr__(self): diff --git a/setup.cfg b/setup.cfg index f8c2b2ed..dc8e9471 100644 --- a/setup.cfg +++ b/setup.cfg @@ -44,7 +44,6 @@ packages = install_requires = cryptography>=2.6,<38 pyasn1 - six>=1.9.0 python_requires = >=3.5 # doc_requires = diff --git a/tests/test_04_PGP_objects.py b/tests/test_04_PGP_objects.py index 97903bfa..b8d5b392 100644 --- a/tests/test_04_PGP_objects.py +++ b/tests/test_04_PGP_objects.py @@ -3,7 +3,6 @@ import pytest import glob import os -import six from pgpy import PGPKey from pgpy import PGPKeyring @@ -41,22 +40,22 @@ def test_load_from_file(self, msgfile): @pytest.fixture def un(): - return PGPUID.new(six.u('Temperair\xe9e Youx\'seur')) + return PGPUID.new('Temperair\xe9e Youx\'seur') @pytest.fixture def unc(): - return PGPUID.new(six.u('Temperair\xe9e Youx\'seur'), comment=six.u('\u2603')) + return PGPUID.new('Temperair\xe9e Youx\'seur', comment='\u2603') @pytest.fixture def une(): - return PGPUID.new(six.u('Temperair\xe9e Youx\'seur'), email='snowman@not.an.email.addre.ss') + return PGPUID.new('Temperair\xe9e Youx\'seur', email='snowman@not.an.email.addre.ss') @pytest.fixture def unce(): - return PGPUID.new(six.u('Temperair\xe9e Youx\'seur'), comment=six.u('\u2603'), email='snowman@not.an.email.addre.ss') + return PGPUID.new('Temperair\xe9e Youx\'seur', comment='\u2603', email='snowman@not.an.email.addre.ss') @pytest.fixture @@ -81,10 +80,10 @@ def test_userphoto(self, abe_image): assert abe_image.image == abebytes def test_format(self, un, unc, une, unce): - assert six.u("{:s}").format(un) == six.u('Temperair\xe9e Youx\'seur') - assert six.u("{:s}").format(unc) == six.u('Temperair\xe9e Youx\'seur (\u2603)') - assert six.u("{:s}").format(une) == six.u('Temperair\xe9e Youx\'seur ') - assert six.u("{:s}").format(unce) == six.u('Temperair\xe9e Youx\'seur (\u2603) ') + assert "{:s}".format(un) == 'Temperair\xe9e Youx\'seur' + assert "{:s}".format(unc) == 'Temperair\xe9e Youx\'seur (\u2603)' + assert "{:s}".format(une) == 'Temperair\xe9e Youx\'seur ' + assert "{:s}".format(unce) == 'Temperair\xe9e Youx\'seur (\u2603) ' _keyfiles = sorted(glob.glob('tests/testdata/blocks/*key*.asc')) @@ -211,10 +210,8 @@ def test_load_key_instance(self, keyring, kf): def test_select_fingerprint(self, keyring): for fp, name in [("F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36", "RSA von TestKey"), - (six.u("F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36"), six.u("RSA von TestKey")), (Fingerprint("F429 4BC8 094A 7E05 85C8 5E86 3747 3B37 58C4 4F36"), "RSA von TestKey"), ("EBC8 8A94 ACB1 10F1 BE3F E3C1 2B47 4BB0 2084 C712", "DSA von TestKey"), - (six.u("EBC8 8A94 ACB1 10F1 BE3F E3C1 2B47 4BB0 2084 C712"), six.u("DSA von TestKey")), (Fingerprint("EBC8 8A94 ACB1 10F1 BE3F E3C1 2B47 4BB0 2084 C712"), "DSA von TestKey"),]: with keyring.key(fp) as key: assert key.fingerprint == fp diff --git a/tests/test_04_copy.py b/tests/test_04_copy.py index d89a5001..366ff743 100644 --- a/tests/test_04_copy.py +++ b/tests/test_04_copy.py @@ -7,7 +7,6 @@ import glob import inspect import os.path -import six import pgpy @@ -55,7 +54,7 @@ def check_id(obj): return False # these types are immutable - if isinstance(obj, (six.string_types, datetime)): + if isinstance(obj, (str, datetime)): return False # integers are kind of a special case.