commit 0b7f195ec82dae183eb5df84c95087e2f2216cd9 Author: Damian Johnson atagar@torproject.org Date: Thu Jul 19 10:42:07 2018 -0700
Builtin lru_cache buggy in python 3.5
Matt's narrowed sbws issues he's been having to a buggy implementation of lru_cache in python 3.5. Using our bundled version instead for that particular series. --- docs/change_log.rst | 1 + stem/descriptor/extrainfo_descriptor.py | 6 +++--- stem/descriptor/hidden_service_descriptor.py | 6 +++--- stem/descriptor/microdescriptor.py | 6 +++--- stem/descriptor/server_descriptor.py | 5 ++--- stem/exit_policy.py | 5 ++--- stem/interpreter/autocomplete.py | 7 ++++--- stem/interpreter/help.py | 7 ++++--- stem/manual.py | 5 ++--- stem/prereq.py | 28 ++++++++++++++++------------ stem/util/proc.py | 6 +++--- stem/version.py | 6 +++--- 12 files changed, 46 insertions(+), 42 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst index 16f54773..a66c2c9b 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -85,6 +85,7 @@ The following are only available within Stem's `git repository * Python 3.6+ syntax error if test_tools.py imported (:trac:`26739`) * Connection information from proc limited to 10,000 results * Accouting for attribute types in most equality checks and hashes + * Funcions using lru_cache could fail with a KeyError on Python 3.5 (:trac:`26412`)
* **Website**
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py index 1813a06e..485b3063 100644 --- a/stem/descriptor/extrainfo_descriptor.py +++ b/stem/descriptor/extrainfo_descriptor.py @@ -71,6 +71,7 @@ import functools import hashlib import re
+import stem.prereq import stem.util.connection import stem.util.enum import stem.util.str_tools @@ -96,10 +97,9 @@ from stem.descriptor import ( _random_crypto_blob, )
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
# known statuses for dirreq-v2-resp and dirreq-v3-resp... diff --git a/stem/descriptor/hidden_service_descriptor.py b/stem/descriptor/hidden_service_descriptor.py index 09b03d75..83618dd8 100644 --- a/stem/descriptor/hidden_service_descriptor.py +++ b/stem/descriptor/hidden_service_descriptor.py @@ -27,6 +27,7 @@ import collections import hashlib import io
+import stem.prereq import stem.util.connection import stem.util.str_tools
@@ -45,10 +46,9 @@ from stem.descriptor import ( _random_crypto_blob, )
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
REQUIRED_FIELDS = ( diff --git a/stem/descriptor/microdescriptor.py b/stem/descriptor/microdescriptor.py index 1ecd0c07..731e8453 100644 --- a/stem/descriptor/microdescriptor.py +++ b/stem/descriptor/microdescriptor.py @@ -67,6 +67,7 @@ Doing the same is trivial with server descriptors... import hashlib
import stem.exit_policy +import stem.prereq
from stem.descriptor import ( Descriptor, @@ -85,10 +86,9 @@ from stem.descriptor.router_status_entry import ( _parse_p_line, )
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
REQUIRED_FIELDS = ( diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py index afbec8e6..d212459e 100644 --- a/stem/descriptor/server_descriptor.py +++ b/stem/descriptor/server_descriptor.py @@ -89,10 +89,9 @@ from stem.descriptor import ( _random_crypto_blob, )
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
# relay descriptors must have exactly one of the following diff --git a/stem/exit_policy.py b/stem/exit_policy.py index 0b956db9..0912546b 100644 --- a/stem/exit_policy.py +++ b/stem/exit_policy.py @@ -77,10 +77,9 @@ import stem.util.connection import stem.util.enum import stem.util.str_tools
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
AddressType = stem.util.enum.Enum(('WILDCARD', 'Wildcard'), ('IPv4', 'IPv4'), ('IPv6', 'IPv6')) diff --git a/stem/interpreter/autocomplete.py b/stem/interpreter/autocomplete.py index 10444066..6401e22c 100644 --- a/stem/interpreter/autocomplete.py +++ b/stem/interpreter/autocomplete.py @@ -5,12 +5,13 @@ Tab completion for our interpreter prompt. """
+import stem.prereq + from stem.interpreter import uses_settings
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
diff --git a/stem/interpreter/help.py b/stem/interpreter/help.py index dddb3b31..20962c45 100644 --- a/stem/interpreter/help.py +++ b/stem/interpreter/help.py @@ -5,6 +5,8 @@ Provides our /help responses. """
+import stem.prereq + from stem.interpreter import ( STANDARD_OUTPUT, BOLD_OUTPUT, @@ -15,10 +17,9 @@ from stem.interpreter import (
from stem.util.term import format
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
diff --git a/stem/manual.py b/stem/manual.py index 458014b0..3e3d317f 100644 --- a/stem/manual.py +++ b/stem/manual.py @@ -66,10 +66,9 @@ try: except ImportError: from stem.util.ordereddict import OrderedDict
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
try: diff --git a/stem/prereq.py b/stem/prereq.py index 6989095c..ab2acba7 100644 --- a/stem/prereq.py +++ b/stem/prereq.py @@ -21,16 +21,11 @@ Checks for stem dependencies. We require python 2.6 or greater (including the is_mock_available - checks if the mock module is available """
+import functools import inspect import platform import sys
-try: - # added in python 3.2 - from functools import lru_cache -except ImportError: - from stem.util.lru_cache import lru_cache - CRYPTO_UNAVAILABLE = "Unable to import the cryptography module. Because of this we'll be unable to verify descriptor signature integrity. You can get cryptography from: https://pypi.python.org/pypi/cryptography" ZSTD_UNAVAILABLE = 'ZSTD compression requires the zstandard module (https://pypi.python.org/pypi/zstandard)' LZMA_UNAVAILABLE = 'LZMA compression requires the lzma module (https://docs.python.org/3/library/lzma.html)' @@ -102,7 +97,6 @@ def is_pypy(): return platform.python_implementation() == 'PyPy'
-@lru_cache() def is_sqlite_available(): """ Checks if the sqlite3 module is available. Usually this is built in, but some @@ -120,7 +114,6 @@ def is_sqlite_available(): return False
-@lru_cache() def is_crypto_available(): """ Checks if the cryptography functions we use are available. This is used for @@ -147,7 +140,6 @@ def is_crypto_available(): return False
-@lru_cache() def is_zstd_available(): """ Checks if the `zstd module https://pypi.python.org/pypi/zstandard`_ is @@ -171,7 +163,6 @@ def is_zstd_available(): return False
-@lru_cache() def is_lzma_available(): """ Checks if the `lzma module https://docs.python.org/3/library/lzma.html`_ is @@ -191,7 +182,6 @@ def is_lzma_available(): return False
-@lru_cache() def is_mock_available(): """ Checks if the mock module is available. In python 3.3 and up it is a builtin @@ -234,7 +224,21 @@ def is_mock_available(): return False
-@lru_cache() +def _is_lru_cache_available(): + """ + Functools added lru_cache to the standard library in Python 3.2. Prior to + this using a bundled implementation. We're also using this with Python 3.5 + due to a buggy implementation. (:trac:`26412`) + """ + + major_version, minor_version = sys.version_info[0:2] + + if major_version == 3 and minor_version == 5: + return False + else: + return hasattr(functools, 'lru_cache') + + def _is_pynacl_available(): """ Checks if the pynacl functions we use are available. This is used for diff --git a/stem/util/proc.py b/stem/util/proc.py index b15d708c..7fcfd1b3 100644 --- a/stem/util/proc.py +++ b/stem/util/proc.py @@ -54,6 +54,7 @@ import socket import sys import time
+import stem.prereq import stem.util.connection import stem.util.enum import stem.util.str_tools @@ -67,10 +68,9 @@ try: except ImportError: IS_PWD_AVAILABLE = False
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
# os.sysconf is only defined on unix diff --git a/stem/version.py b/stem/version.py index ed1a3a38..7e15fe51 100644 --- a/stem/version.py +++ b/stem/version.py @@ -83,14 +83,14 @@ easily parsed and compared, for instance... import os import re
+import stem.prereq import stem.util import stem.util.enum import stem.util.system
-try: - # added in python 3.2 +if stem.prereq._is_lru_cache_available(): from functools import lru_cache -except ImportError: +else: from stem.util.lru_cache import lru_cache
# cache for the get_system_tor_version function