From 969df8303b848cef8342be25cbc9b6343d7425b8 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Fri, 11 Oct 2019 22:36:33 +0100 Subject: [PATCH 01/10] Remove some Python 2 era import gaming --- Lib/fontTools/misc/loggingTools.py | 11 ++--------- Lib/fontTools/misc/macRes.py | 5 +---- Lib/fontTools/misc/plistlib.py | 14 ++------------ Lib/fontTools/misc/psLib.py | 5 +---- Lib/fontTools/misc/testTools.py | 5 +---- Lib/fontTools/ttLib/tables/_h_d_m_x.py | 6 +----- Lib/fontTools/ttLib/tables/_t_r_a_k.py | 5 +---- Tests/misc/plistlib_test.py | 5 +---- 8 files changed, 10 insertions(+), 46 deletions(-) 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..3804e8e5f 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -5,18 +5,8 @@ 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 collections.abc import Mapping +from functools import singledispatch from fontTools.misc import etree 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..4a60600fb 100644 --- a/Tests/misc/plistlib_test.py +++ b/Tests/misc/plistlib_test.py @@ -12,11 +12,8 @@ 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: From b0afdc273e3fb770654b1667ecabf197b272b015 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 12 Oct 2019 12:20:06 +0100 Subject: [PATCH 02/10] Remove singledispatch import conditional --- Lib/fontTools/misc/plistlib.py | 59 ++++++++-------------------------- 1 file changed, 14 insertions(+), 45 deletions(-) diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index 3804e8e5f..96af36c9a 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -364,52 +364,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(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)) # Public functions to create element tree from plist-compatible python From 641058ead281136df655d12a06221123664a1818 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 12 Oct 2019 12:20:22 +0100 Subject: [PATCH 03/10] Remove PY2 conditional and `unicode` import --- Tests/misc/plistlib_test.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/Tests/misc/plistlib_test.py b/Tests/misc/plistlib_test.py index 4a60600fb..7222bd28b 100644 --- a/Tests/misc/plistlib_test.py +++ b/Tests/misc/plistlib_test.py @@ -5,7 +5,7 @@ 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 ( @@ -15,15 +15,6 @@ import pytest from collections.abc 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 # which uses PyObjC to control the Cocoa classes for generating plists @@ -185,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() @@ -513,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 From fb07ab1d8f63a1bd46ad96be7b715e1d909d248e Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 12 Oct 2019 12:24:16 +0100 Subject: [PATCH 04/10] Remove PY2-era re.ASCII reference --- Lib/fontTools/misc/plistlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index 96af36c9a..0b2f8bf17 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -52,7 +52,7 @@ _date_parser = re.compile( r"(?::(?P\d\d)" r"(?::(?P\d\d))" r"?)?)?)?)?Z", - getattr(re, "ASCII", 0), # py3-only + re.ASCII ) From 2acb1de6c9fbf0fe88aabff8630c0ee068f85ac9 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 12 Oct 2019 13:22:31 +0100 Subject: [PATCH 05/10] Remove `unicode` import --- Lib/fontTools/misc/plistlib.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index 0b2f8bf17..64dc9321c 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -11,7 +11,6 @@ from functools import singledispatch from fontTools.misc import etree from fontTools.misc.py23 import ( - unicode, basestring, tounicode, tobytes, @@ -368,7 +367,7 @@ def _string_or_data_element(raw_bytes, ctx): def _make_element(value, ctx): raise TypeError("unsupported type: %s" % type(value)) -_make_element.register(unicode)(_string_element) +_make_element.register(str)(_string_element) _make_element.register(bool)(_bool_element) _make_element.register(Integral)(_integer_element) _make_element.register(float)(_real_element) From c67a2e5ff0fcf7b4388606ec7e0cfd820687b21f Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 12 Oct 2019 13:26:59 +0100 Subject: [PATCH 06/10] Remove more legacy imports --- Lib/fontTools/misc/plistlib.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index 64dc9321c..0e1bd7d10 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -5,17 +5,15 @@ from datetime import datetime from base64 import b64encode, b64decode from numbers import Integral +from types import SimpleNamespace from collections.abc import Mapping from functools import singledispatch from fontTools.misc import etree from fontTools.misc.py23 import ( - basestring, tounicode, tobytes, - SimpleNamespace, - range, ) # On python3, by default we deserialize elements as bytes, whereas on @@ -311,7 +309,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") From b54e11c1a5bedba4b54d9a97ff96cf41508c409a Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 12 Oct 2019 13:40:48 +0100 Subject: [PATCH 07/10] Remove conditional to use built-in types by default --- Lib/fontTools/misc/plistlib.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index 0e1bd7d10..a23b92e6f 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -16,21 +16,19 @@ from fontTools.misc.py23 import ( tobytes, ) -# 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) +# - deserialized 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"""""" From 94c3aff9919f546c9717a3f5d325f6a0c5519e9f Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 12 Oct 2019 13:44:03 +0100 Subject: [PATCH 08/10] Remove redundant object subclassing --- Lib/fontTools/misc/plistlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index a23b92e6f..4b9325635 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -120,7 +120,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, From 6da6a2c377bf6507cfd3e42e9ec2200ec8afe024 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Sat, 12 Oct 2019 13:49:36 +0100 Subject: [PATCH 09/10] Fix typo --- Lib/fontTools/misc/plistlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index 4b9325635..0d5d0a482 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -22,7 +22,7 @@ from fontTools.misc.py23 import ( # 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) -# - deserialized bytes as elements (they must have only contained +# - 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. From 6b9eefcf48ff7e6f5c4475bc312f0dddd6eba294 Mon Sep 17 00:00:00 2001 From: Nikolaus Waxweiler Date: Mon, 14 Oct 2019 11:04:52 +0100 Subject: [PATCH 10/10] Warn if use_builtin_types is False --- Lib/fontTools/misc/plistlib.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Lib/fontTools/misc/plistlib.py b/Lib/fontTools/misc/plistlib.py index 0d5d0a482..5c40ba4d6 100644 --- a/Lib/fontTools/misc/plistlib.py +++ b/Lib/fontTools/misc/plistlib.py @@ -1,5 +1,6 @@ import sys import re +import warnings from io import BytesIO from datetime import datetime from base64 import b64encode, b64decode @@ -149,6 +150,12 @@ class PlistTarget: 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