[tor-commits] [ooni-probe/master] Move peculiar code to wtf directory.

art at torproject.org art at torproject.org
Wed Nov 7 20:37:43 UTC 2012


commit 70a3d94b5f5edeaafbd1867c67fb5cd2d61ad149
Author: Arturo Filastò <arturo at filasto.net>
Date:   Wed Nov 7 21:36:06 2012 +0100

    Move peculiar code to wtf directory.
    * Comment on tor related code and propose that it gets removed.
---
 ooni/utils/config.py  |  121 -------------------------------------------------
 ooni/utils/onion.py   |   17 +++++++-
 ooni/utils/process.py |   73 -----------------------------
 wtf/README            |    9 ++++
 wtf/config.py         |   66 +++++++++++++++++++++++++++
 wtf/process.py        |   73 +++++++++++++++++++++++++++++
 6 files changed, 164 insertions(+), 195 deletions(-)

diff --git a/ooni/utils/config.py b/ooni/utils/config.py
deleted file mode 100644
index 5a0782d..0000000
--- a/ooni/utils/config.py
+++ /dev/null
@@ -1,121 +0,0 @@
-import ConfigParser
-import os
-
-from ooni.utils import Storage, log
-
-class Config(Storage):
-    """
-    A Storage-like class which loads and store each attribute into a portable
-    conf file.
-    """
-    def __init__(self, section, cfgfile="ooni-probe.conf"):
-        super(Config, self).__init__()
-
-        self._cfgfile = cfgfile
-        # setting up confgiparser
-        self._cfgparser = ConfigParser.ConfigParser()
-        self._cfgparser.read([self._cfgfile])
-        self._section = section
-
-    def __getattr__(self, name):
-        if name.startswith('_'):
-            return self.__dict__.get(name, None)
-
-        try:
-            value = self._cfgparser.get(self._section, name)
-            if value.isdigit():
-                return int(value)
-            elif value.lower() in ('true', 'false'):
-                return value.lower() == 'true'
-            else:
-                return value
-        except ConfigParser.NoOptionError:
-            return ''  # if option doesn't exists return an empty string
-
-    def __setattr__(self, name, value):
-        # keep an open port with private attributes
-        if name.startswith('_'):
-            self.__dict__[name] = value
-            return
-
-        try:
-            # XXX: Automagically discover variable type
-            self._cfgparser.set(self._section, name, value)
-        except ConfigParser.NoOptionError:
-            raise NameError(name)
-
-    def commit(self):
-        """
-        Commit changes in config file.
-        """
-        cfgfile = open(self._cfgfile, 'w')
-        try:
-            self._cfgparser.write(cfgfile)
-        finally:
-            cfgfile.close()
-
-class ValueChecker(object):
-    """
-    A class for general purpose value checks on commandline parameters
-    passed to subclasses of :class:`twisted.python.usage.Options`.
-    """
-    def __init__(self, coerce_doc=None):
-        self.coerce_doc = coerce_doc
-
-    def port_check(self, port, range_min=1024, range_max=65535):
-        """
-        Check that given ports are in the allowed range for an unprivileged
-        user.
-
-        :param port:
-            The port to check.
-        :param range_min:
-            The minimum allowable port number.
-        :param range_max:
-            The minimum allowable port number.
-        :param coerce_doc:
-            The documentation string to show in the optParameters menu, see
-            :class:`twisted.python.usage.Options`.
-        """
-        if self.coerce_doc is not None:
-            coerceDoc = self.coerce_doc
-
-        assert type(port) is int
-        if port not in range(range_min, range_max):
-            raise ValueError("Port out of range")
-            log.err()
-
-    @staticmethod
-    def uid_check(error_message):
-        """
-        Check that we're not root. If we are, setuid(1000) to normal user if
-        we're running on a posix-based system, and if we're on Windows just
-        tell the user that we can't be run as root with the specified options
-        and then exit.
-
-        :param error_message:
-            The string to log as an error message when the uid check fails.
-        """
-        uid, gid = os.getuid(), os.getgid()
-        if uid == 0 and gid == 0:
-            log.msg(error_message)
-        if os.name == 'posix':
-            log.msg("Dropping privileges to normal user...")
-            os.setgid(1000)
-            os.setuid(1000)
-        else:
-            sys.exit(0)
-
-    @staticmethod
-    def dir_check(d):
-        """Check that the given directory exists."""
-        if not os.path.isdir(d):
-            raise ValueError("%s doesn't exist, or has wrong permissions"
-                             % d)
-
-    @staticmethod
-    def file_check(f):
-        """Check that the given file exists."""
-        if not os.path.isfile(f):
-            raise ValueError("%s does not exist, or has wrong permissions"
-                             % f)
diff --git a/ooni/utils/onion.py b/ooni/utils/onion.py
index fe97ca3..58b4c02 100644
--- a/ooni/utils/onion.py
+++ b/ooni/utils/onion.py
@@ -26,7 +26,10 @@ from txtorcon          import TorState, TorConfig
 from ooni.utils        import log
 from ooni.utils.timer  import deferred_timeout, TimeoutError
 
-
+# XXX This can be refactored to os.path.abspath
+# os.path.abspath(path)
+# Return a normalized absolutized version of the pathname path. On most
+# platforms, this is equivalent to normpath(join(os.getcwd(), path)).
 def parse_data_dir(data_dir):
     """
     Parse a string that a has been given as a DataDirectory and determine
@@ -63,6 +66,9 @@ def parse_data_dir(data_dir):
     else:
         return data_dir
 
+# XXX txtorcon handles this already.
+# Also this function is called write_torrc but it has hardcoded inside of it
+# bridget-tordata.
 def write_torrc(conf, data_dir=None):
     """
     Create a torrc in our data_dir. If we don't yet have a data_dir, create a
@@ -157,6 +163,8 @@ def remove_public_relays(state, bridges):
             log.err("Removing public relays %s from bridge list failed:\n%s"
                     % (both, e))
 
+# XXX It is unclear to me how all of these functions would be reused. Why must
+# hey be inside of a module?
 def setup_done(proto):
     log.msg("Setup Complete")
     state = TorState(proto.tor_protocol)
@@ -192,6 +200,7 @@ def bootstrap(ctrl):
     conf.post_bootstrap.addCallback(setup_done).addErrback(setup_fail)
     log.msg("Tor process connected, bootstrapping ...")
 
+# XXX txtorcon does this already for us.
 def start_tor(reactor, config, control_port, tor_binary, data_dir,
               report=None, progress=updates,
               process_cb=None, process_eb=None):
@@ -315,6 +324,7 @@ def start_tor_filter_nodes(reactor, config, control_port, tor_binary,
     filter_nodes = yield remove_public_relays(setup, bridges)
     defer.returnValue(filter_nodes)
 
+# XXX Why is this needed?
 @defer.inlineCallbacks
 def start_tor_with_timer(reactor, config, control_port, tor_binary, data_dir,
                          bridges, timeout):
@@ -366,6 +376,7 @@ def start_tor_with_timer(reactor, config, control_port, tor_binary, data_dir,
         state = yield remove_public_relays(setup, bridges)
         defer.returnValue(state)
 
+# XXX This is a copy and paste of the above class with just an extra argument.
 @defer.inlineCallbacks
 def start_tor_filter_nodes_with_timer(reactor, config, control_port,
                                       tor_binary, data_dir, bridges, timeout):
@@ -431,6 +442,10 @@ class CustomCircuit(CircuitListenerMixin):
         The list of circuits which we are waiting to attach to. You shouldn't
         need to touch this.
     """
+    # XXX
+    # 14:57 < meejah> to build a custom circuit (with no streams) in txtorcon,
+    # call TorState.build_circuit -- the Deferred callbacks with the circid
+
     implements(IStreamAttacher)
 
     def __init__(self, state, relays=None):
diff --git a/ooni/utils/process.py b/ooni/utils/process.py
deleted file mode 100644
index 25d6368..0000000
--- a/ooni/utils/process.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# process.py
-# ----------
-# OONI utilities for dealing with starting and stopping processes.
-#
-# :author: Isis Lovecruft
-# :version: 0.1.0-pre-alpha
-# :license: see include LICENSE file
-# :copyright: copyright (c) 2012, Isis Lovecruft, The Tor Project Inc.
-# 
-
-from twisted.internet import defer
-
- at defer.inlineCallbacks
-def singleton_semaphore(deferred_process_init, 
-                        callbacks=[], errbacks=[],
-                        max_inits=1):
-    """
-    Initialize a process only once, and do not return until
-    that initialization is complete. If the keyword parameter max_inits=
-    is given, run the process a maximum of that number of times.
-
-    :param deferred_process_init:
-        A deferred which returns a connected process via
-        :meth:`twisted.internet.reactor.spawnProcess`.
-    :param callbacks:
-        A list of callback functions to add to the initialized processes'
-        deferred.
-    :param errbacks:
-        A list of errback functions to add to the initialized processes'
-        deferred.
-    :param max_inits:
-        An integer specifying the maximum number of allowed
-        initializations for :param:deferred_process_init. If no maximum
-        is given, only one instance (a singleton) of the process is
-        initialized.
-    :return:
-        The final state of the :param deferred_process_init: after the
-        callback chain has completed. This should be a fully initialized
-        process connected to a :class:`twisted.internet.reactor`.
-    """
-    assert isinstance(callbacks, list)
-    assert isinstance(errbacks, list)
-    assert isinstance(max_inits, int)
-
-    for cb in callbacks:
-        deferred_process_init.addCallback(cb)
-    for eb in errbacks:
-        deferred_process_init.addErrback(eb)
-
-    only_this_many = defer.DeferredSemaphore(max_inits)
-    singleton = yield only_this_many.run(deferred_process_init)
-    defer.returnValue(singleton)
-
-class Singleton(object):
-    """
-    Generic Class for creating Singleton subclasses.
-
-    Subclass me to create a singleton class, which will only ever have one
-    instance, regardless of how many times the subclass constructor is called.
-
-    Any subclass of me should override ``init`` rather than ``__init__``,
-    because the latter is called whenever the constructor is called.
-    """
-    def __new__(cls, *args, **kwds):
-        it = cls.__dict__.get("__it__")
-        if it is not None:
-            return it
-        cls.__it__ = it = object.__new__(cls)
-        it.init(*args, **kwds)
-        return it
-    def init(self, *args, **kwds):
-        pass
diff --git a/wtf/README b/wtf/README
new file mode 100644
index 0000000..7696130
--- /dev/null
+++ b/wtf/README
@@ -0,0 +1,9 @@
+I have moved here all the pieces of code that are either not being used
+anywhere or that should probably not be part of OONIProbe.
+
+They are very neat pieces of code, though I have not tester their
+functionality, since there are no examples of how they should be called or
+used in the repo.
+
+I believe they should go on a separate branch or on another repo called
+something like "python class kung foo".
diff --git a/wtf/config.py b/wtf/config.py
new file mode 100644
index 0000000..25f9576
--- /dev/null
+++ b/wtf/config.py
@@ -0,0 +1,66 @@
+class ValueChecker(object):
+    """
+    A class for general purpose value checks on commandline parameters
+    passed to subclasses of :class:`twisted.python.usage.Options`.
+    """
+    def __init__(self, coerce_doc=None):
+        self.coerce_doc = coerce_doc
+
+    def port_check(self, port, range_min=1024, range_max=65535):
+        """
+        Check that given ports are in the allowed range for an unprivileged
+        user.
+
+        :param port:
+            The port to check.
+        :param range_min:
+            The minimum allowable port number.
+        :param range_max:
+            The minimum allowable port number.
+        :param coerce_doc:
+            The documentation string to show in the optParameters menu, see
+            :class:`twisted.python.usage.Options`.
+        """
+        if self.coerce_doc is not None:
+            coerceDoc = self.coerce_doc
+
+        assert type(port) is int
+        if port not in range(range_min, range_max):
+            raise ValueError("Port out of range")
+            log.err()
+
+    @staticmethod
+    def uid_check(error_message):
+        """
+        Check that we're not root. If we are, setuid(1000) to normal user if
+        we're running on a posix-based system, and if we're on Windows just
+        tell the user that we can't be run as root with the specified options
+        and then exit.
+
+        :param error_message:
+            The string to log as an error message when the uid check fails.
+        """
+        uid, gid = os.getuid(), os.getgid()
+        if uid == 0 and gid == 0:
+            log.msg(error_message)
+        if os.name == 'posix':
+            log.msg("Dropping privileges to normal user...")
+            os.setgid(1000)
+            os.setuid(1000)
+        else:
+            sys.exit(0)
+
+    @staticmethod
+    def dir_check(d):
+        """Check that the given directory exists."""
+        if not os.path.isdir(d):
+            raise ValueError("%s doesn't exist, or has wrong permissions"
+                             % d)
+
+    @staticmethod
+    def file_check(f):
+        """Check that the given file exists."""
+        if not os.path.isfile(f):
+            raise ValueError("%s does not exist, or has wrong permissions"
+                             % f)
+
diff --git a/wtf/process.py b/wtf/process.py
new file mode 100644
index 0000000..25d6368
--- /dev/null
+++ b/wtf/process.py
@@ -0,0 +1,73 @@
+#
+# process.py
+# ----------
+# OONI utilities for dealing with starting and stopping processes.
+#
+# :author: Isis Lovecruft
+# :version: 0.1.0-pre-alpha
+# :license: see include LICENSE file
+# :copyright: copyright (c) 2012, Isis Lovecruft, The Tor Project Inc.
+# 
+
+from twisted.internet import defer
+
+ at defer.inlineCallbacks
+def singleton_semaphore(deferred_process_init, 
+                        callbacks=[], errbacks=[],
+                        max_inits=1):
+    """
+    Initialize a process only once, and do not return until
+    that initialization is complete. If the keyword parameter max_inits=
+    is given, run the process a maximum of that number of times.
+
+    :param deferred_process_init:
+        A deferred which returns a connected process via
+        :meth:`twisted.internet.reactor.spawnProcess`.
+    :param callbacks:
+        A list of callback functions to add to the initialized processes'
+        deferred.
+    :param errbacks:
+        A list of errback functions to add to the initialized processes'
+        deferred.
+    :param max_inits:
+        An integer specifying the maximum number of allowed
+        initializations for :param:deferred_process_init. If no maximum
+        is given, only one instance (a singleton) of the process is
+        initialized.
+    :return:
+        The final state of the :param deferred_process_init: after the
+        callback chain has completed. This should be a fully initialized
+        process connected to a :class:`twisted.internet.reactor`.
+    """
+    assert isinstance(callbacks, list)
+    assert isinstance(errbacks, list)
+    assert isinstance(max_inits, int)
+
+    for cb in callbacks:
+        deferred_process_init.addCallback(cb)
+    for eb in errbacks:
+        deferred_process_init.addErrback(eb)
+
+    only_this_many = defer.DeferredSemaphore(max_inits)
+    singleton = yield only_this_many.run(deferred_process_init)
+    defer.returnValue(singleton)
+
+class Singleton(object):
+    """
+    Generic Class for creating Singleton subclasses.
+
+    Subclass me to create a singleton class, which will only ever have one
+    instance, regardless of how many times the subclass constructor is called.
+
+    Any subclass of me should override ``init`` rather than ``__init__``,
+    because the latter is called whenever the constructor is called.
+    """
+    def __new__(cls, *args, **kwds):
+        it = cls.__dict__.get("__it__")
+        if it is not None:
+            return it
+        cls.__it__ = it = object.__new__(cls)
+        it.init(*args, **kwds)
+        return it
+    def init(self, *args, **kwds):
+        pass





More information about the tor-commits mailing list