[tor-commits] [bridgedb/master] Move Bridge backwards compat code into new base classes.

isis at torproject.org isis at torproject.org
Sat Mar 21 02:02:59 UTC 2015


commit c031cafea281f0b46d68657f3d194785b788562b
Author: Isis Lovecruft <isis at torproject.org>
Date:   Thu Dec 11 03:45:08 2014 +0000

    Move Bridge backwards compat code into new base classes.
    
    This changes the behaviour, such that if BridgeBackwardsCompatibility is
    inherited from, then the compatibility methods and attributes are always
    available, no matter how the class was instantiated (i.e. the old
    method, Bridge.getID() is always available). However, the assertions and
    errors raised in the BridgeBackwardsCompatiblity._backwardsCompatible
    method are only run *if* the inherited class is instantiated *with*
    arguments (as was the legacy manner of doing things).
    
     * ADD bridges.BridgeBase and bridges.BridgeBackwardsCompatibility
       classes.
---
 lib/bridgedb/bridges.py |  310 ++++++++++++++++++++++++++---------------------
 1 file changed, 170 insertions(+), 140 deletions(-)

diff --git a/lib/bridgedb/bridges.py b/lib/bridgedb/bridges.py
index 459e86a..fae5d19 100644
--- a/lib/bridgedb/bridges.py
+++ b/lib/bridgedb/bridges.py
@@ -380,7 +380,173 @@ class PluggableTransport(object):
         self._runChecks()
 
 
-class Bridge(object):
+class BridgeBase(object):
+    """The base class for all bridge implementations."""
+
+    def __init__(self):
+        self.fingerprint = None
+        self.nickname = None
+        self.address = None
+        self.orPort = None
+        self.socksPort = 0  # Bridges should always have ``SOCKSPort`` and
+        self.dirPort = 0    # ``DirPort`` set to ``0``
+        self.orAddresses = []
+        self.transports = []
+        self.flags = Flags()
+        
+
+class BridgeBackwardsCompatibility(BridgeBase):
+    """Backwards compatibility methods for the old Bridge class."""
+
+    def __init__(self, nickname=None, ip=None, orport=None,
+                 fingerprint=None, id_digest=None, or_addresses=None):
+        """Create a Bridge which is backwards compatible with the old Bridge class
+        implementation.
+
+        .. info: For backwards compatibility, `nickname`, `ip`, and `orport`
+            must be the first, second, and third arguments, respectively.  The
+            `fingerprint` and `id_digest` were previously kwargs, and are also
+            provided for backwards compatibility.  New calls to
+            :meth:`__init__` *should* avoid using these kwargs, and instead
+            use the methods :meth:`updateFromNetworkStatus`,
+            :meth:`updateFromServerDescriptor`, and
+            :meth:`updateFromExtraInfoDescriptor`.
+        """
+        super(BridgeBackwardsCompatibility, self).__init__()
+
+        self.desc_digest = None
+        self.ei_digest = None
+        self.running = False
+        self.stable = False
+
+        if nickname or ip or orport or fingerprint or id_digest:
+            self._backwardsCompatible(nickname=nickname, address=ip,
+                                      orPort=orport, fingerprint=fingerprint,
+                                      idDigest=id_digest,
+                                      orAddresses=or_addresses)
+
+    def _backwardsCompatible(self, nickname=None, address=None, orPort=None,
+                             fingerprint=None, idDigest=None,
+                             orAddresses=None):
+        """Functionality for maintaining backwards compatibility with the older
+        version of this class (see :class:`bridgedb.test.deprecated.Bridge`).
+        """
+        if nickname:
+            self.nickname = nickname  # XXX check nickname spec conformity?
+        if address:
+            self.address = address  # XXX check validip?
+        if orPort:
+            self.orPort = orPort  # XXX check validity?
+
+        if idDigest:
+            if not fingerprint:
+                if not len(idDigest) == 20:
+                    raise TypeError("Bridge with invalid ID")
+                self.fingerprint = toHex(idDigest)
+        elif fingerprint:
+            if not isValidFingerprint(fingerprint):
+                raise TypeError("Bridge with invalid fingerprint (%r)"
+                                % fingerprint)
+            self.fingerprint = fingerprint.lower()
+        else:
+            raise TypeError("Bridge with no ID")
+
+        if orAddresses and isinstance(orAddresses, dict):
+            for ip, portlist in orAddresses.items():
+                validAddress = isIPAddress(ip, compressed=False)
+                if validAddress:
+                    # The old code expected a `bridgedb.parse.addr.PortList`:
+                    if isinstance(portlist, PortList):
+                        for port in portlist.ports:
+                            self.orAddresses.append(
+                                (validAddress, port, validAddress.version,))
+                    elif isinstance(portlist, int):
+                        self.orAddresses.append(
+                            (validAddress, portlist, validAddress.version,))
+                    else:
+                        logging.warn("Can't parse port for ORAddress %r: %r"
+                                     % (ip, portlist))
+
+    def getID(self):
+        """Get the binary encoded form of this ``Bridge``'s ``fingerprint``.
+
+        This method is provided for backwards compatibility and should not
+        be relied upon.
+        """
+        if self.fingerprint:
+            return fromHex(self.fingerprint)
+
+    def setDescriptorDigest(self, digest):
+        """Set this ``Bridge``'s server-descriptor digest.
+
+        This method is provided for backwards compatibility and should not
+        be relied upon.
+        """
+        self.desc_digest = digest  # old attribute for backwards compat
+        self.descriptorDigest = digest  # new attribute
+
+    def setExtraInfoDigest(self, digest):
+        """Set this ``Bridge``'s extrainfo digest.
+
+        This method is provided for backwards compatibility and should not
+        be relied upon.
+        """
+        self.ei_digest = digest  # old attribute for backwards compat
+        self.extrainfoDigest = digest  # new attribute
+
+    def setStatus(self, running=None, stable=None):
+        """Set this ``Bridge``'s "Running" and "Stable" flags.
+
+        This method is provided for backwards compatibility and should not
+        be relied upon.
+        """
+        if running is not None:
+            self.running = bool(running)
+            self.flags.running = bool(running)
+        if stable is not None:
+            self.stable = bool(stable)
+            self.flags.stable = bool(running)
+
+    def getConfigLine(self, includeFingerprint=False, addressClass=None,
+                      request=None, transport=None):
+        """Get a vanilla bridge line for this ``Bridge``.
+
+        This method is provided for backwards compatibility and should not
+        be relied upon.
+
+        The old ``bridgedb.Bridges.Bridge.getConfigLine()`` method didn't know
+        about :class:`~bridgedb.bridgerequest.BridgeRequestBase`s, and so this
+        modified version is backwards compatible by creating a
+        :class:`~bridgedb.bridgerequest.BridgeRequestBase` for
+        :meth:`getBridgeLine`. The default parameters are the same as they
+        were in the old ``bridgedb.Bridges.Bridge`` class.
+
+        :param bool includeFingerprint: If ``True``, include the
+            ``fingerprint`` of this :class:`Bridge` in the returned bridge
+            line.
+        :type addressClass: :class:`ipaddr.IPv4Address` or
+            :class:`ipaddr.IPv6Address`.
+        :param addressClass: Type of address to choose.
+        :param str request: A string unique to this request e.g. email-address
+            or ``uniformMap(ip)`` or ``'default'``. In this case, this is not
+            a :class:`~bridgerequest.BridgeRequestBase` (as might be expected)
+            but the equivalent of
+            :data:`bridgerequest.BridgeRequestBase.client`.
+        :param str transport: A pluggable transport method name.
+        """
+        bridgeRequest = bridgerequest.BridgeRequestBase(addressClass)
+        bridgeRequest.client = request if request else bridgeRequest.client
+        bridgeRequest.isValid(True)
+
+        if transport:
+            bridgeRequest.withPluggableTransportType(transport)
+
+        bridgeRequest.generateFilters()
+        bridgeLine = self.getBridgeLine(bridgeRequest, includeFingerprint)
+        return bridgeLine
+
+
+class Bridge(BridgeBackwardsCompatibility):
     """A single bridge, and all the information we have for it.
 
     :type fingerprint: str or None
@@ -426,10 +592,7 @@ class Bridge(object):
     #: created with the ``signing-key`` contained in that descriptor.
     _checkServerDescriptorSignature = True
 
-    def __init__(self,
-                 # for backwards compatibility:
-                 nickname=None, ip=None, orport=None,
-                 fingerprint=None, id_digest=None, or_addresses=None):
+    def __init__(self, *args, **kwargs):
         """Create a and store information for a new ``Bridge``.
 
         .. info: For backwards compatibility, `nickname`, `ip`, and `orport`
@@ -441,6 +604,8 @@ class Bridge(object):
             :meth:`updateFromServerDescriptor`, and
             :meth:`updateFromExtraInfoDescriptor`.
         """
+        super(Bridge, self).__init__(*args, **kwargs)
+
         self.fingerprint = None
         self.nickname = None
         self.address = None
@@ -481,14 +646,6 @@ class Bridge(object):
         self.descriptorDigest = None
         self.extrainfoDigest = None
 
-        # For backwards compatibility with the old, deprecated version of this
-        # class:
-        if nickname or ip or orport or fingerprint or id_digest:
-            self._backwardsCompatible(nickname=nickname, address=ip,
-                                      orPort=orport, fingerprint=fingerprint,
-                                      idDigest=id_digest,
-                                      orAddresses=or_addresses)
-
     def __str__(self):
         """Return a pretty string representation that identifies this Bridge.
 
@@ -519,133 +676,6 @@ class Bridge(object):
 
         return nickname + separator + fingerprint
 
-    def _backwardsCompatible(self, nickname=None, address=None, orPort=None,
-                             fingerprint=None, idDigest=None,
-                             orAddresses=None):
-        """Functionality for maintaining backwards compatibility with the older
-        version of this class (see :class:`bridgedb.test.deprecated.Bridge`).
-        """
-        def getID():
-            """Get the binary encoded form of this ``Bridge``'s ``fingerprint``.
-
-            This method is provided for backwards compatibility and should not
-            be relied upon.
-            """
-            if self.fingerprint:
-                return fromHex(self.fingerprint)
-        self.getID = getID
-
-        def setDescriptorDigest(digest):
-            """Set this ``Bridge``'s server-descriptor digest.
-
-            This method is provided for backwards compatibility and should not
-            be relied upon.
-            """
-            self.desc_digest = digest  # old attribute for backwards compat
-            self.descriptorDigest = digest  # new attribute
-        self.desc_digest = None
-        self.setDescriptorDigest = setDescriptorDigest
-
-        def setExtraInfoDigest(digest):
-            """Set this ``Bridge``'s extrainfo digest.
-
-            This method is provided for backwards compatibility and should not
-            be relied upon.
-            """
-            self.ei_digest = digest  # old attribute for backwards compat
-            self.extrainfoDigest = digest  # new attribute
-        self.ei_digest = None
-        self.setExtraInfoDigest = setExtraInfoDigest
-
-        def setStatus(running=None, stable=None):
-            """Set this ``Bridge``'s "Running" and "Stable" flags.
-
-            This method is provided for backwards compatibility and should not
-            be relied upon.
-            """
-            if running is not None:
-                self.running = bool(running)
-                self.flags.running = bool(running)
-            if stable is not None:
-                self.stable = bool(stable)
-                self.flags.stable = bool(running)
-        self.running = False
-        self.stable = False
-        self.setStatus = setStatus
-
-        def getConfigLine(includeFingerprint=False, addressClass=None,
-                          request=None, transport=None):
-            """Get a vanilla bridge line for this ``Bridge``.
-
-            This method is provided for backwards compatibility and should not
-            be relied upon.
-
-            The old ``bridgedb.Bridges.Bridge.getConfigLine()`` method didn't
-            know about :class:`~bridgedb.bridgerequest.BridgeRequestBase`s,
-            and so this modified version is backwards compatible by creating a
-            :class:`~bridgedb.bridgerequest.BridgeRequestBase` for
-            :meth:`getBridgeLine`. The default parameters are the same as they
-            were in the old ``bridgedb.Bridges.Bridge`` class.
-
-            :param bool includeFingerprint: If ``True``, include the
-                ``fingerprint`` of this :class:`Bridge` in the returned bridge
-                line.
-            :type addressClass: :class:`ipaddr.IPv4Address` or
-                :class:`ipaddr.IPv6Address`.
-            :param addressClass: Type of address to choose.
-            :param str request: A string unique to this request
-                e.g. email-address or ``uniformMap(ip)`` or ``'default'``. In
-                this case, this is not a
-                :class:`~bridgerequest.BridgeRequestBase` (as might be
-                expected) but the equivalent of
-                :data:`bridgerequest.BridgeRequestBase.client`.
-            :param str transport: A pluggable transport method name.
-            """
-            bridgeRequest = bridgerequest.BridgeRequestBase(addressClass)
-            bridgeRequest.client = request if request else bridgeRequest.client
-            bridgeRequest.isValid(True)
-
-            if transport:
-                bridgeRequest.withPluggableTransportType(transport)
-
-            bridgeRequest.generateFilters()
-            bridgeLine = self.getBridgeLine(bridgeRequest, includeFingerprint)
-            return bridgeLine
-        self.getConfigLine = getConfigLine
-
-        if nickname:
-            self.nickname = nickname  # XXX check nickname spec conformity?
-        if address:
-            self.address = address  # XXX check validip?
-        if orPort:
-            self.orPort = orPort  # XXX check validity?
-
-        if idDigest:
-            if not fingerprint:
-                if not len(idDigest) == 20:
-                    raise TypeError("Bridge with invalid ID")
-                self.fingerprint = toHex(idDigest)
-        elif fingerprint:
-            if not isValidFingerprint(fingerprint):
-                raise TypeError("Bridge with invalid fingerprint (%r)"
-                                % fingerprint)
-            self.fingerprint = fingerprint.lower()
-        else:
-            raise TypeError("Bridge with no ID")
-
-        if orAddresses and isinstance(orAddresses, dict):
-            for ip, portlist in orAddresses.items():
-                validAddress = isIPAddress(ip, compressed=False)
-                if validAddress:
-                    # The old code expected a `bridgedb.parse.addr.PortList`:
-                    if isinstance(portlist, PortList):
-                        for port in portlist.ports:
-                            self.orAddresses.append(
-                                (validAddress, port, validAddress.version,))
-                    else:
-                        self.orAddresses.append(
-                            (validAddress, port, validAddress.version))
-
     def _checkServerDescriptor(self, descriptor):
         # If we're parsing the server-descriptor, require a networkstatus
         # document:





More information about the tor-commits mailing list