[tor-commits] [stem/master] Builtin lru_cache buggy in python 3.5

atagar at torproject.org atagar at torproject.org
Thu Jul 19 19:27:57 UTC 2018


commit 0b7f195ec82dae183eb5df84c95087e2f2216cd9
Author: Damian Johnson <atagar at 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'
 
 
- at 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
 
 
- at 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
 
 
- at 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
 
 
- at 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
 
 
- at 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
 
 
- at 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



More information about the tor-commits mailing list