diff options
Diffstat (limited to 'passlib/utils/binary.py')
-rw-r--r-- | passlib/utils/binary.py | 88 |
1 files changed, 39 insertions, 49 deletions
diff --git a/passlib/utils/binary.py b/passlib/utils/binary.py index 521b64a..f60ddf2 100644 --- a/passlib/utils/binary.py +++ b/passlib/utils/binary.py @@ -5,7 +5,6 @@ passlib.utils.binary - binary data encoding/decoding/manipulation # imports #============================================================================= # core -from __future__ import absolute_import, division, print_function from base64 import ( b64encode, b64decode, @@ -19,10 +18,9 @@ log = logging.getLogger(__name__) # pkg from passlib import exc from passlib.utils.compat import ( - PY3, bascii_to_str, - irange, imap, iter_byte_chars, join_byte_values, join_byte_elems, - nextgetter, suppress_cause, - u, unicode, unicode_or_bytes_types, + bascii_to_str, + iter_byte_chars, + unicode_or_bytes, ) from passlib.utils.decor import memoized_property # from passlib.utils import BASE64_CHARS, HASH64_CHARS @@ -64,28 +62,28 @@ __all__ = [ #------------------------------------------------------------- #: standard base64 charmap -BASE64_CHARS = u("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") +BASE64_CHARS = u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" #: alt base64 charmap -- "." instead of "+" -AB64_CHARS = u("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./") +AB64_CHARS = u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./" #: charmap used by HASH64 encoding. -HASH64_CHARS = u("./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") +HASH64_CHARS = u"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" #: charmap used by BCrypt -BCRYPT_CHARS = u("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") +BCRYPT_CHARS = u"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" #: std base64 chars + padding char -PADDED_BASE64_CHARS = BASE64_CHARS + u("=") +PADDED_BASE64_CHARS = BASE64_CHARS + u"=" #: all hex chars -HEX_CHARS = u("0123456789abcdefABCDEF") +HEX_CHARS = u"0123456789abcdefABCDEF" #: upper case hex chars -UPPER_HEX_CHARS = u("0123456789ABCDEF") +UPPER_HEX_CHARS = u"0123456789ABCDEF" #: lower case hex chars -LOWER_HEX_CHARS = u("0123456789abcdef") +LOWER_HEX_CHARS = u"0123456789abcdef" #------------------------------------------------------------- # byte strings @@ -93,7 +91,7 @@ LOWER_HEX_CHARS = u("0123456789abcdef") #: special byte string containing all possible byte values #: NOTE: for efficiency, this is treated as singleton by some of the code -ALL_BYTE_VALUES = join_byte_values(irange(256)) +ALL_BYTE_VALUES = bytes(range(256)) #: some string constants we reuse B_EMPTY = b'' @@ -128,10 +126,10 @@ def compile_byte_translation(mapping, source=None): assert isinstance(source, bytes) and len(source) == 255 target = list(iter_byte_chars(source)) for k, v in mapping.items(): - if isinstance(k, unicode_or_bytes_types): + if isinstance(k, unicode_or_bytes): k = ord(k) assert isinstance(k, int) and 0 <= k < 256 - if isinstance(v, unicode): + if isinstance(v, str): v = v.encode("ascii") assert isinstance(v, bytes) and len(v) == 1 target[k] = v @@ -152,12 +150,12 @@ def b64s_decode(data): decode from shortened base64 format which omits padding & whitespace. uses default ``+/`` altchars. """ - if isinstance(data, unicode): + if isinstance(data, str): # needs bytes for replace() call, but want to accept ascii-unicode ala a2b_base64() try: data = data.encode("ascii") except UnicodeEncodeError: - raise suppress_cause(ValueError("string argument should contain only ASCII characters")) + raise ValueError("string argument should contain only ASCII characters") from None off = len(data) & 3 if off == 0: pass @@ -170,7 +168,7 @@ def b64s_decode(data): try: return a2b_base64(data) except _BinAsciiError as err: - raise suppress_cause(TypeError(err)) + raise TypeError(err) from None #============================================================================= # adapted-base64 encoding @@ -198,12 +196,12 @@ def ab64_decode(data): it is primarily used by Passlib's custom pbkdf2 hashes. """ - if isinstance(data, unicode): + if isinstance(data, str): # needs bytes for replace() call, but want to accept ascii-unicode ala a2b_base64() try: data = data.encode("ascii") except UnicodeEncodeError: - raise suppress_cause(ValueError("string argument should contain only ASCII characters")) + raise ValueError("string argument should contain only ASCII characters") from None return b64s_decode(data.replace(b".", b"+")) #============================================================================= @@ -233,7 +231,7 @@ def b32decode(source): padding optional, ignored if present. """ # encode & correct for typos - if isinstance(source, unicode): + if isinstance(source, str): source = source.encode("ascii") source = source.translate(_b32_translate) @@ -336,7 +334,7 @@ class Base64Engine(object): #=================================================================== def __init__(self, charmap, big=False): # validate charmap, generate encode64/decode64 helper functions. - if isinstance(charmap, unicode): + if isinstance(charmap, str): charmap = charmap.encode("latin-1") elif not isinstance(charmap, bytes): raise exc.ExpectedStringError(charmap, "charmap") @@ -385,12 +383,9 @@ class Base64Engine(object): if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) chunks, tail = divmod(len(source), 3) - if PY3: - next_value = nextgetter(iter(source)) - else: - next_value = nextgetter(ord(elem) for elem in source) + next_value = iter(source).__next__ gen = self._encode_bytes(next_value, chunks, tail) - out = join_byte_elems(imap(self._encode64, gen)) + out = bytes(map(self._encode64, gen)) ##if tail: ## padding = self.padding ## if padding: @@ -495,9 +490,9 @@ class Base64Engine(object): if tail == 1: # only 6 bits left, can't encode a whole byte! raise ValueError("input string length cannot be == 1 mod 4") - next_value = nextgetter(imap(self._decode64, source)) + next_value = map(self._decode64, source).__next__ try: - return join_byte_values(self._decode_bytes(next_value, chunks, tail)) + return bytes(self._decode_bytes(next_value, chunks, tail)) except KeyError as err: raise ValueError("invalid character: %r" % (err.args[0],)) @@ -626,7 +621,7 @@ class Base64Engine(object): # we have dirty bits - repair the string by decoding last char, # clearing the padding bits via <mask>, and encoding new char. - if isinstance(source, unicode): + if isinstance(source, str): cm = self.charmap last = cm[cm.index(last) & mask] assert last in padset, "failed to generate valid padding char" @@ -635,8 +630,7 @@ class Base64Engine(object): # all chars used by encoding are 7-bit ascii. last = self._encode64(self._decode64(last) & mask) assert last in padset, "failed to generate valid padding char" - if PY3: - last = bytes([last]) + last = bytes([last]) return True, source[:-1] + last def repair_unused(self, source): @@ -661,19 +655,19 @@ class Base64Engine(object): """encode byte string, first transposing source using offset list""" if not isinstance(source, bytes): raise TypeError("source must be bytes, not %s" % (type(source),)) - tmp = join_byte_elems(source[off] for off in offsets) + tmp = bytes(source[off] for off in offsets) return self.encode_bytes(tmp) def decode_transposed_bytes(self, source, offsets): """decode byte string, then reverse transposition described by offset list""" # NOTE: if transposition does not use all bytes of source, - # the original can't be recovered... and join_byte_elems() will throw + # the original can't be recovered... and bytes() will throw # an error because 1+ values in <buf> will be None. tmp = self.decode_bytes(source) buf = [None] * len(offsets) for off, char in zip(offsets, tmp): buf[off] = char - return join_byte_elems(buf) + return bytes(buf) #=================================================================== # integer decoding helpers - mainly used by des_crypt family @@ -724,9 +718,8 @@ class Base64Engine(object): raise TypeError("source must be bytes, not %s" % (type(source),)) if len(source) != 1: raise ValueError("source must be exactly 1 byte") - if PY3: - # convert to 8bit int before doing lookup - source = source[0] + # convert to 8bit int before doing lookup + source = source[0] try: return self._decode64(source) except KeyError: @@ -792,13 +785,13 @@ class Base64Engine(object): pad = -bits % 6 bits += pad if self.big: - itr = irange(bits-6, -6, -6) + itr = range(bits-6, -6, -6) # shift to add lsb padding. value <<= pad else: - itr = irange(0, bits, 6) + itr = range(0, bits, 6) # padding is msb, so no change needed. - return join_byte_elems(imap(self._encode64, + return bytes(map(self._encode64, ((value>>off) & 0x3f for off in itr))) #--------------------------------------------------------------- @@ -809,10 +802,7 @@ class Base64Engine(object): """encodes 6-bit integer -> single hash64 character""" if value < 0 or value > 63: raise ValueError("value out of range") - if PY3: - return self.bytemap[value:value+1] - else: - return self._encode64(value) + return self.bytemap[value:value+1] def encode_int12(self, value): """encodes 12-bit integer -> 2 char string""" @@ -821,7 +811,7 @@ class Base64Engine(object): raw = [value & 0x3f, (value>>6) & 0x3f] if self.big: raw = reversed(raw) - return join_byte_elems(imap(self._encode64, raw)) + return bytes(map(self._encode64, raw)) def encode_int24(self, value): """encodes 24-bit integer -> 4 char string""" @@ -831,7 +821,7 @@ class Base64Engine(object): (value>>12) & 0x3f, (value>>18) & 0x3f] if self.big: raw = reversed(raw) - return join_byte_elems(imap(self._encode64, raw)) + return bytes(map(self._encode64, raw)) def encode_int30(self, value): """decode 5 char string -> 30 bit integer""" @@ -862,7 +852,7 @@ class LazyBase64Engine(Base64Engine): def _lazy_init(self): args, kwds = self._lazy_opts - super(LazyBase64Engine, self).__init__(*args, **kwds) + super().__init__(*args, **kwds) del self._lazy_opts self.__class__ = Base64Engine |