commit 4b980915168e3c712e7352c81c9c00671da7a075 Author: Damian Johnson atagar@torproject.org Date: Sat Nov 22 15:54:49 2014 -0800
Handling edge cases for earlier optimizations
Just a few minor edge cases...
* The is_valid_address() functions could have an uncaught TypeError if given unexpected types.
* Explicitly checking for lists in is_valid_port(). For instance, dictionaries could trip it up. Having a isinstance() check for just the list situation should still pretty much achieve the performance benefits this was after. --- docs/change_log.rst | 2 +- stem/util/connection.py | 22 ++++++++++++---------- stem/util/str_tools.py | 12 ++++++------ stem/util/tor_tools.py | 9 ++++----- test/unit/util/connection.py | 2 +- 5 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst index e0e765b..5a3ca34 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -53,7 +53,7 @@ The following are only available within Stem's `git repository
* **Descriptors**
- * Improved speed for parsing consensus documents by around 30% (:trac:`12859`) + * Improved speed for parsing consensus documents by around 40% (:trac:`12859` and :trac:`13821`) * Don't fail if consensus method 1 is not present, as it is no longer required (:spec:`fc8a6f0`) * Include '*.new' files when reading from a Tor data directory (:trac:`13756`) * Updated the authorities we list, `replacing turtles with longclaw https://lists.torproject.org/pipermail/tor-talk/2014-November/035650.html`_ and `updating gabelmoo's address https://lists.torproject.org/pipermail/tor-talk/2014-September/034898.html`_ diff --git a/stem/util/connection.py b/stem/util/connection.py index d1fb5c2..df918d2 100644 --- a/stem/util/connection.py +++ b/stem/util/connection.py @@ -337,7 +337,7 @@ def is_valid_ipv4_address(address): try: packed = socket.inet_pton(socket.AF_INET, address) return socket.inet_ntop(socket.AF_INET, packed) == address - except socket.error: + except (TypeError, socket.error): return False
@@ -358,7 +358,7 @@ def is_valid_ipv6_address(address, allow_brackets = False): try: socket.inet_pton(socket.AF_INET6, address) return True - except socket.error: + except (TypeError, socket.error): return False
@@ -374,20 +374,22 @@ def is_valid_port(entry, allow_zero = False):
try: value = int(entry) + if str(value) != str(entry): return False # invalid leading char, e.g. space or zero - if allow_zero: - return value >= 0 and value < 65536 + elif allow_zero and value == 0: + return True else: return value > 0 and value < 65536 - except TypeError: - # Maybe entry is list to validate? - for port in entry: - if not is_valid_port(port, allow_zero): - return False - return True + if isinstance(entry, (tuple, list)): + for port in entry: + if not is_valid_port(port, allow_zero): + return False
+ return True + else: + return False except ValueError: return False
diff --git a/stem/util/str_tools.py b/stem/util/str_tools.py index 039447e..43d12d6 100644 --- a/stem/util/str_tools.py +++ b/stem/util/str_tools.py @@ -449,13 +449,13 @@ def _parse_timestamp(entry):
:param str entry: timestamp to be parsed
- :returns: datetime for the time represented by the timestamp + :returns: **datetime** for the time represented by the timestamp
- :raises: ValueError if the timestamp is malformed + :raises: **ValueError** if the timestamp is malformed """
if not isinstance(entry, (str, unicode)): - raise IOError('parse_iso_timestamp() input must be a str, got a %s' % type(entry)) + raise ValueError('parse_timestamp() input must be a str, got a %s' % type(entry))
try: time = [int(x) for x in _timestamp_re.match(entry).groups()] @@ -475,12 +475,12 @@ def _parse_iso_timestamp(entry):
:param str entry: timestamp to be parsed
- :returns: datetime for the time represented by the timestamp + :returns: **datetime** for the time represented by the timestamp
- :raises: ValueError if the timestamp is malformed + :raises: **ValueError** if the timestamp is malformed """
- if not isinstance(entry, str): + if not isinstance(entry, (str, unicode)): raise ValueError('parse_iso_timestamp() input must be a str, got a %s' % type(entry))
# based after suggestions from... diff --git a/stem/util/tor_tools.py b/stem/util/tor_tools.py index 54579f6..7b02e6c 100644 --- a/stem/util/tor_tools.py +++ b/stem/util/tor_tools.py @@ -33,8 +33,6 @@ import re # case insensitive. Tor doesn't define this in the spec so flipping a coin # and going with case insensitive.
-HEX_DIGIT = '[0-9a-fA-F]' -FINGERPRINT_PATTERN = re.compile('^%s{40}$' % HEX_DIGIT) NICKNAME_PATTERN = re.compile('^[a-zA-Z0-9]{1,19}$') CIRC_ID_PATTERN = re.compile('^[a-zA-Z0-9]{1,16}$')
@@ -121,13 +119,14 @@ def is_hex_digits(entry, count): :param str entry: string to be checked :param int count: number of hex digits to be checked for
- :returns: **True** if the string matches this number + :returns: **True** if the given number of hex digits, **False** otherwise """
try: if len(entry) != count: return False - int(entry, 16) + + int(entry, 16) # attempt to convert it as hex + return True except (ValueError, TypeError): return False - return True diff --git a/test/unit/util/connection.py b/test/unit/util/connection.py index 0766c32..f0359eb 100644 --- a/test/unit/util/connection.py +++ b/test/unit/util/connection.py @@ -360,7 +360,7 @@ class TestConnection(unittest.TestCase): """
valid_ports = (1, '1', 1234, '1234', 65535, '65535', [1, '2']) - invalid_ports = (0, '0', 65536, '65536', 'abc', '*', ' 15', '01') + invalid_ports = (0, '0', 65536, '65536', 'abc', '*', ' 15', '01', True, {})
for port in valid_ports: self.assertTrue(stem.util.connection.is_valid_port(port))
tor-commits@lists.torproject.org