diff --git a/Lib/fontTools/misc/loggingTools.py b/Lib/fontTools/misc/loggingTools.py index f479c916a..e08aec989 100644 --- a/Lib/fontTools/misc/loggingTools.py +++ b/Lib/fontTools/misc/loggingTools.py @@ -7,16 +7,9 @@ import sys import logging import timeit from functools import wraps -try: - from collections.abc import Mapping, Callable -except ImportError: # python < 3.3 - from collections import Mapping, Callable +from collections.abc import Mapping, Callable import warnings - -try: - from logging import PercentStyle -except ImportError: - PercentStyle = None +from logging import PercentStyle # default logging level used by Timer class diff --git a/Lib/fontTools/misc/macRes.py b/Lib/fontTools/misc/macRes.py index e8b3cbc20..da3237394 100644 --- a/Lib/fontTools/misc/macRes.py +++ b/Lib/fontTools/misc/macRes.py @@ -3,10 +3,7 @@ from fontTools.misc.py23 import * import struct from fontTools.misc import sstruct from collections import OrderedDict -try: - from collections.abc import MutableMapping -except ImportError: - from UserDict import DictMixin as MutableMapping +from collections.abc import MutableMapping class ResourceError(Exception): diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index 52f7ec391..5c40ba4d6 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -1,49 +1,35 @@ import sys import re +import warnings from io import BytesIO from datetime import datetime from base64 import b64encode, b64decode from numbers import Integral -try: - from collections.abc import Mapping # python >= 3.3 -except ImportError: - from collections import Mapping - -try: - from functools import singledispatch -except ImportError: - try: - from singledispatch import singledispatch - except ImportError: - singledispatch = None +from types import SimpleNamespace +from collections.abc import Mapping +from functools import singledispatch from fontTools.misc import etree from fontTools.misc.py23 import ( - unicode, - basestring, tounicode, tobytes, - SimpleNamespace, - range, ) -# On python3, by default we deserialize elements as bytes, whereas on -# python2 we deserialize elements as plistlib.Data objects, in order -# to distinguish them from the built-in str type (which is bytes on python2). -# Similarly, by default on python3 we serialize bytes as elements; -# however, on python2 we serialize bytes as elements (they must -# only contain ASCII characters in this case). -# You can pass use_builtin_types=[True|False] to load/dump etc. functions to -# enforce the same treatment of bytes across python 2 and 3. +# By default, we +# - deserialize elements as bytes and +# - serialize bytes as elements. +# Before, on Python 2, we +# - deserialized elements as plistlib.Data objects, in order to +# distinguish them from the built-in str type (which is bytes on python2) +# - serialized bytes as elements (they must have only contained +# ASCII characters in this case) +# You can pass use_builtin_types=[True|False] to the load/dump etc. functions +# to enforce a specific treatment. # NOTE that unicode type always maps to element, and plistlib.Data # always maps to element, regardless of use_builtin_types. -PY3 = sys.version_info[0] > 2 -if PY3: - USE_BUILTIN_TYPES = True -else: - USE_BUILTIN_TYPES = False +USE_BUILTIN_TYPES = True XML_DECLARATION = b"""""" @@ -62,7 +48,7 @@ _date_parser = re.compile( r"(?::(?P\d\d)" r"(?::(?P\d\d))" r"?)?)?)?)?Z", - getattr(re, "ASCII", 0), # py3-only + re.ASCII ) @@ -135,7 +121,7 @@ class Data: return "%s(%s)" % (self.__class__.__name__, repr(self.data)) -class PlistTarget(object): +class PlistTarget: """ Event handler using the ElementTree Target API that can be passed to a XMLParser to produce property list objects from XML. It is based on the CPython plistlib module's _PlistParser class, @@ -164,6 +150,12 @@ class PlistTarget(object): if use_builtin_types is None: self._use_builtin_types = USE_BUILTIN_TYPES else: + if use_builtin_types is False: + warnings.warn( + "Setting use_builtin_types to False is deprecated and will be " + "removed soon.", + DeprecationWarning, + ) self._use_builtin_types = use_builtin_types self._dict_type = dict_type @@ -322,7 +314,7 @@ def _dict_element(d, ctx): items = sorted(items) ctx.indent_level += 1 for key, value in items: - if not isinstance(key, basestring): + if not isinstance(key, str): if ctx.skipkeys: continue raise TypeError("keys must be strings") @@ -374,52 +366,21 @@ def _string_or_data_element(raw_bytes, ctx): return _string_element(string, ctx) -# if singledispatch is available, we use a generic '_make_element' function -# and register overloaded implementations that are run based on the type of -# the first argument +@singledispatch +def _make_element(value, ctx): + raise TypeError("unsupported type: %s" % type(value)) -if singledispatch is not None: - - @singledispatch - def _make_element(value, ctx): - raise TypeError("unsupported type: %s" % type(value)) - - _make_element.register(unicode)(_string_element) - _make_element.register(bool)(_bool_element) - _make_element.register(Integral)(_integer_element) - _make_element.register(float)(_real_element) - _make_element.register(Mapping)(_dict_element) - _make_element.register(list)(_array_element) - _make_element.register(tuple)(_array_element) - _make_element.register(datetime)(_date_element) - _make_element.register(bytes)(_string_or_data_element) - _make_element.register(bytearray)(_data_element) - _make_element.register(Data)(lambda v, ctx: _data_element(v.data, ctx)) - -else: - # otherwise we use a long switch-like if statement - - def _make_element(value, ctx): - if isinstance(value, unicode): - return _string_element(value, ctx) - elif isinstance(value, bool): - return _bool_element(value, ctx) - elif isinstance(value, Integral): - return _integer_element(value, ctx) - elif isinstance(value, float): - return _real_element(value, ctx) - elif isinstance(value, Mapping): - return _dict_element(value, ctx) - elif isinstance(value, (list, tuple)): - return _array_element(value, ctx) - elif isinstance(value, datetime): - return _date_element(value, ctx) - elif isinstance(value, bytes): - return _string_or_data_element(value, ctx) - elif isinstance(value, bytearray): - return _data_element(value, ctx) - elif isinstance(value, Data): - return _data_element(value.data, ctx) +_make_element.register(str)(_string_element) +_make_element.register(bool)(_bool_element) +_make_element.register(Integral)(_integer_element) +_make_element.register(float)(_real_element) +_make_element.register(Mapping)(_dict_element) +_make_element.register(list)(_array_element) +_make_element.register(tuple)(_array_element) +_make_element.register(datetime)(_date_element) +_make_element.register(bytes)(_string_or_data_element) +_make_element.register(bytearray)(_data_element) +_make_element.register(Data)(lambda v, ctx: _data_element(v.data, ctx)) # Public functions to create element tree from plist-compatible python diff --git a/Lib/fontTools/misc/psLib.py b/Lib/fontTools/misc/psLib.py index 5dc94ae38..e47483021 100644 --- a/Lib/fontTools/misc/psLib.py +++ b/Lib/fontTools/misc/psLib.py @@ -2,10 +2,7 @@ from fontTools.misc.py23 import * from fontTools.misc import eexec from .psOperators import * import re -try: - from collections.abc import Callable -except ImportError: # python < 3.3 - from collections import Callable +from collections.abc import Callable from string import whitespace import logging diff --git a/Lib/fontTools/misc/testTools.py b/Lib/fontTools/misc/testTools.py index b4ade8b5a..59055062b 100644 --- a/Lib/fontTools/misc/testTools.py +++ b/Lib/fontTools/misc/testTools.py @@ -1,9 +1,6 @@ """Helpers for writing unit tests.""" -try: - from collections.abc import Iterable -except ImportError: # python < 3.3 - from collections import Iterable +from collections.abc import Iterable import os import shutil import sys diff --git a/Lib/fontTools/ttLib/tables/_h_d_m_x.py b/Lib/fontTools/ttLib/tables/_h_d_m_x.py index a42cb6a73..db5d9d8aa 100644 --- a/Lib/fontTools/ttLib/tables/_h_d_m_x.py +++ b/Lib/fontTools/ttLib/tables/_h_d_m_x.py @@ -2,6 +2,7 @@ from fontTools.misc.py23 import * from fontTools.misc import sstruct from . import DefaultTable import array +from collections.abc import Mapping hdmxHeaderFormat = """ > # big endian! @@ -10,11 +11,6 @@ hdmxHeaderFormat = """ recordSize: l """ -try: - from collections.abc import Mapping -except: - from UserDict import DictMixin as Mapping - class _GlyphnamedList(Mapping): def __init__(self, reverseGlyphOrder, data): diff --git a/Lib/fontTools/ttLib/tables/_t_r_a_k.py b/Lib/fontTools/ttLib/tables/_t_r_a_k.py index 090bf14a2..7448916c2 100644 --- a/Lib/fontTools/ttLib/tables/_t_r_a_k.py +++ b/Lib/fontTools/ttLib/tables/_t_r_a_k.py @@ -10,10 +10,7 @@ from fontTools.misc.textTools import safeEval from fontTools.ttLib import TTLibError from . import DefaultTable import struct -try: - from collections.abc import MutableMapping -except ImportError: - from UserDict import DictMixin as MutableMapping +from collections.abc import MutableMapping # Apple's documentation of 'trak': diff --git a/Tests/misc/plistlib_test.py b/Tests/misc/plistlib_test.py index aa2a24e25..7222bd28b 100644 --- a/Tests/misc/plistlib_test.py +++ b/Tests/misc/plistlib_test.py @@ -5,27 +5,15 @@ import codecs import collections from io import BytesIO from numbers import Integral -from fontTools.misc.py23 import tounicode, unicode +from fontTools.misc.py23 import tounicode from fontTools.misc import etree from fontTools.misc import plistlib from fontTools.ufoLib.plistlib import ( readPlist, readPlistFromString, writePlist, writePlistToString, ) import pytest +from collections.abc import Mapping -try: - from collections.abc import Mapping # python >= 3.3 -except ImportError: - from collections import Mapping - -PY2 = sys.version_info < (3,) -if PY2: - # This is a ResourceWarning that only happens on py27 at interpreter - # finalization, and only when coverage is enabled. We can ignore it. - # https://github.com/numpy/numpy/issues/3778#issuecomment-24885336 - pytestmark = pytest.mark.filterwarnings( - "ignore:tp_compare didn't return -1 or -2 for exception" - ) # The testdata is generated using https://github.com/python/cpython/... # Mac/Tools/plistlib_generate_testdata.py @@ -188,7 +176,7 @@ def test_bytes_string(use_builtin_types): pl = b"some ASCII bytes" data = plistlib.dumps(pl, use_builtin_types=False) pl2 = plistlib.loads(data, use_builtin_types=use_builtin_types) - assert isinstance(pl2, unicode) # it's always a + assert isinstance(pl2, str) # it's always a assert pl2 == pl.decode() @@ -516,15 +504,13 @@ def test_writePlistToString(pl_no_builtin_types): def test_load_use_builtin_types_default(): pl = plistlib.loads(TESTDATA) - expected = plistlib.Data if PY2 else bytes - assert isinstance(pl["someData"], expected) + assert isinstance(pl["someData"], bytes) def test_dump_use_builtin_types_default(pl_no_builtin_types): data = plistlib.dumps(pl_no_builtin_types) pl2 = plistlib.loads(data) - expected = plistlib.Data if PY2 else bytes - assert isinstance(pl2["someData"], expected) + assert isinstance(pl2["someData"], bytes) assert pl2 == pl_no_builtin_types