[Inteproxy-commits] r59 - in trunk: . inteproxy test

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Apr 23 14:54:25 CEST 2007


Author: bh
Date: 2007-04-23 14:54:25 +0200 (Mon, 23 Apr 2007)
New Revision: 59

Added:
   trunk/inteproxy/
   trunk/inteproxy/__init__.py
   trunk/inteproxy/getpassword.py
   trunk/inteproxy/proxyconnection.py
   trunk/inteproxy/threadpool.py
   trunk/inteproxy/transcoder.py
Removed:
   trunk/getpassword.py
   trunk/proxyconnection.py
   trunk/threadpool.py
   trunk/transcoder.py
Modified:
   trunk/ChangeLog
   trunk/InteProxy.py
   trunk/test/test_owsproxy_get_transcoder.py
   trunk/test/test_owsproxy_post_transcoder.py
   trunk/test/test_threadpool.py
   trunk/test/test_transcoder_map.py
Log:
* inteproxy, inteproxy/__init__.py: New.  Introduce inteproxy
package for better code organisation

* getpassword.py, proxyconnection.py, threadpool.py, transcoder.py: 
Moved to the new inteproxy package

* InteProxy.py, test/test_owsproxy_get_transcoder.py,
test/test_owsproxy_post_transcoder.py, test/test_threadpool.py,
test/test_transcoder_map.py: Adapt to code reorganization


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/ChangeLog	2007-04-23 12:54:25 UTC (rev 59)
@@ -1,3 +1,15 @@
+2007-04-23  Bernhard Herzog  <bh at intevation.de>
+
+	* inteproxy, inteproxy/__init__.py: New.  Introduce inteproxy
+	package for better code organisation
+
+	* getpassword.py, proxyconnection.py, threadpool.py, transcoder.py: 
+	Moved to the new inteproxy package
+
+	* InteProxy.py, test/test_owsproxy_get_transcoder.py,
+	test/test_owsproxy_post_transcoder.py, test/test_threadpool.py,
+	test/test_transcoder_map.py: Adapt to code reorganization
+
 2007-04-20  Stephan Holl  <stephan.holl at intevation.de>
 
 	* website/index-de.htm4: german translation finished

Modified: trunk/InteProxy.py
===================================================================
--- trunk/InteProxy.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/InteProxy.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -22,10 +22,10 @@
 import urllib2
 import BaseHTTPServer
 import socket
-import proxyconnection
-from transcoder import transcoder_map
-from getpassword import getpassword
-from threadpool import ThreadPool
+import inteproxy.proxyconnection as proxyconnection
+from inteproxy.transcoder import transcoder_map
+from inteproxy.getpassword import getpassword
+from inteproxy.threadpool import ThreadPool
 
 inteproxy_version = "0.1.2"
 

Deleted: trunk/getpassword.py
===================================================================
--- trunk/getpassword.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/getpassword.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -1,120 +0,0 @@
-# Copyright (C) 2007 by Intevation GmbH
-# Authors:
-# Bernhard Herzog <bh at intevation.de>
-#
-# This program is free software under the GPL (>=v2)
-# Read the file COPYING coming with the software for details.
-
-"""Code to ask the user for username and password"""
-
-import threading
-import traceback
-
-# Determine the window system we're using.  This determines how the user
-# is asked for the username/password.
-try:
-    # If gtk isn't available, we get an ImportError here.  However, on
-    # Unix, if we gtk cannot establish the connection to the X-server,
-    # we get a RuntimeError here.  We do not catch the RuntimeError for
-    # now, because we want to use gtk by default and don't want to hide
-    # configuration errors like missing or incorrect DISPLAY variables.
-    import gtk
-    windowsystem = "gtk"
-except ImportError:
-    try:
-        import pywin.dialogs.login
-        windowsystem = "pywin"
-    except ImportError:
-        windowsystem = "tty"
-
-def getpassword_gtk(title):
-    dialog = gtk.Dialog("My dialog", None,
-                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                        (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT,
-                         gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
-    label = gtk.Label(title)
-    label.show()
-    dialog.vbox.pack_start(label, True, True, 5)
-
-    table = gtk.Table(2, 2)
-    dialog.vbox.pack_start(table)
-
-    def add_field(row, name, visibility):
-        label = gtk.Label(name)
-        label.set_alignment(1.0, 0.5)
-        table.attach(label, 0, 1, row, row + 1, xoptions=gtk.FILL,
-                     xpadding=5, ypadding=5)
-        entry = gtk.Entry()
-        entry.set_visibility(visibility)
-        table.attach(entry, 1, 2, row, row + 1, xoptions=gtk.FILL|gtk.EXPAND,
-                     xpadding=5, ypadding=5)
-        return entry
-
-    username_entry = add_field(0, "Username:", True)
-    password_entry = add_field(1, "Password:", False)
-
-    table.show_all()
-
-    if dialog.run() == gtk.RESPONSE_ACCEPT:
-        result = (username_entry.get_text(),
-                  password_entry.get_text())
-    else:
-        result = None
-
-    dialog.destroy()
-
-    # process pending events to make sure the dialog is destroyed and
-    # unmapped properly from the screen.
-    while gtk.events_pending():
-        gtk.main_iteration_do()
-
-    return result
-
-def getpassword_pywin(title):
-    return pywin.dialogs.login.GetLogin(title)
-
-def getpassword_tty(title):
-    import getpass
-    try:
-        user = raw_input(title)
-        password = getpass.getpass()
-    except IOError:
-        import traceback
-        traceback.print_exception()
-        user = password = None
-    return user, password
-
-getpassword = globals()["getpassword_" + windowsystem]
-
-# password cache and lock
-pw_cache = {}
-pw_lock = threading.Lock()
-
-def get_password_with_cache(path):
-    """Ask the user for a username and password and cache the
-    information.  The path parameter should be a string with hostname
-    and path of the URL the caller is trying to access.  If a username
-    and password for that string is already stored in the cache, the
-    cached information is returned.  Otherwise this function uses the
-    getpassword function to ask the user and then adds this information
-    to the cache and returns it.
-
-    The return value is the tuple (username, password).
-    """
-    pw_lock.acquire()
-    try:
-        if path in pw_cache:
-            user, password = pw_cache[path]
-        else:
-            title = "Username for %s: " % path
-            user, password = getpassword(title)
-            pw_cache[path] = user, password
-
-        return user, password
-    finally:
-        pw_lock.release()
-
-
-if __name__ == "__main__":
-    result = getpassword("Password Dialog Test")
-    print repr(result)

Added: trunk/inteproxy/__init__.py
===================================================================


Property changes on: trunk/inteproxy/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Copied: trunk/inteproxy/getpassword.py (from rev 58, trunk/getpassword.py)

Copied: trunk/inteproxy/proxyconnection.py (from rev 58, trunk/proxyconnection.py)

Copied: trunk/inteproxy/threadpool.py (from rev 58, trunk/threadpool.py)

Copied: trunk/inteproxy/transcoder.py (from rev 58, trunk/transcoder.py)

Deleted: trunk/proxyconnection.py
===================================================================
--- trunk/proxyconnection.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/proxyconnection.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -1,117 +0,0 @@
-# Copyright (C) 2006 by Alessandro Budai
-# from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/456195
-#
-# This software may be used and distributed according to the terms
-# of the Python License 2.3 or newer, see http://www.python.org/license
-
-"""
-urrlib2 opener for SSL proxy (CONNECT method)
-
-This small module builds an urllib2 opener that can be used to make a
-connection through a proxy using the http CONNECT method (that can be used to
-proxy SSLconnections). The current urrlib2 seems to not support this method.
-
-tested with python 2.4
-"""
-
-import urllib2
-import urllib
-import httplib
-import socket
-
-
-class ProxyHTTPConnection(httplib.HTTPConnection):
-
-    _ports = {'http' : 80, 'https' : 443}
-
-
-    def request(self, method, url, body=None, headers={}):
-        #request is called before connect, so can interpret url and get
-        #real host/port to be used to make CONNECT request to proxy
-        proto, rest = urllib.splittype(url)
-        if proto is None:
-            raise ValueError, "unknown URL type: %s" % url
-        #get host
-        host, rest = urllib.splithost(rest)
-        #try to get port
-        host, port = urllib.splitport(host)
-        #if port is not defined try to get from proto
-        if port is None:
-            try:
-                port = self._ports[proto]
-            except KeyError:
-                raise ValueError, "unknown protocol for: %s" % url
-        self._real_host = host
-        self._real_port = int(port)
-        httplib.HTTPConnection.request(self, method, rest or '/', body, headers)
-
-
-    def connect(self):
-        httplib.HTTPConnection.connect(self)
-        #send proxy CONNECT request
-        self.send("CONNECT %s:%d HTTP/1.0\r\n\r\n" % (self._real_host, self._real_port))
-        #expect a HTTP/1.0 200 Connection established
-        response = self.response_class(self.sock, strict=self.strict, method=self._method)
-        (version, code, message) = response._read_status()
-        #probably here we can handle auth requests...
-        if code != 200:
-            #proxy returned and error, abort connection, and raise exception
-            self.close()
-            raise socket.error, "Proxy connection failed: %d %s" % (code, message.strip())
-        #eat up header block from proxy....
-        while True:
-            #should not use directly fp probably
-            line = response.fp.readline()
-            if line == '\r\n': break
-
-
-class ProxyHTTPSConnection(ProxyHTTPConnection):
-
-    default_port = 443
-
-    def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
-        ProxyHTTPConnection.__init__(self, host, port)
-        self.key_file = key_file
-        self.cert_file = cert_file
-
-    def connect(self):
-        ProxyHTTPConnection.connect(self)
-        #make the sock ssl-aware
-        ssl = socket.ssl(self.sock, self.key_file, self.cert_file)
-        self.sock = httplib.FakeSocket(self.sock, ssl)
-
-
-class ConnectHTTPHandler(urllib2.HTTPHandler):
-
-    def __init__(self, proxy=None, debuglevel=0):
-        self.proxy = proxy
-        urllib2.HTTPHandler.__init__(self, debuglevel)
-
-    def do_open(self, http_class, req):
-        if self.proxy is not None:
-            req.set_proxy(self.proxy, 'http')
-        return urllib2.HTTPHandler.do_open(self, ProxyHTTPConnection, req)
-
-
-class ConnectHTTPSHandler(urllib2.HTTPSHandler):
-
-    def __init__(self, proxy=None, debuglevel=0):
-        self.proxy = proxy
-        urllib2.HTTPSHandler.__init__(self, debuglevel)
-
-    def do_open(self, http_class, req):
-        if self.proxy is not None:
-            req.set_proxy(self.proxy, 'https')
-        return urllib2.HTTPSHandler.do_open(self, ProxyHTTPSConnection, req)
-
-
-if __name__ == '__main__':
-
-    import sys
-
-    opener = urllib2.build_opener(ConnectHTTPHandler(sys.argv[2]),
-                                  ConnectHTTPSHandler(sys.argv[2]))
-    urllib2.install_opener(opener)
-    req = urllib2.Request(url=sys.argv[1])
-    f = urllib2.urlopen(req)
-    print f.read()

Modified: trunk/test/test_owsproxy_get_transcoder.py
===================================================================
--- trunk/test/test_owsproxy_get_transcoder.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/test/test_owsproxy_get_transcoder.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -10,7 +10,7 @@
 import urlparse
 import unittest
 
-from transcoder import OWSProxyGETTranscoder
+from inteproxy.transcoder import OWSProxyGETTranscoder
 
 
 class TestOWSProxyGETTranscoder(unittest.TestCase):

Modified: trunk/test/test_owsproxy_post_transcoder.py
===================================================================
--- trunk/test/test_owsproxy_post_transcoder.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/test/test_owsproxy_post_transcoder.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -8,7 +8,7 @@
 """Tests for OWSProxyPOSTTranscoder"""
 
 import unittest
-from transcoder import OWSProxyPOSTTranscoder
+from inteproxy.transcoder import OWSProxyPOSTTranscoder
 
 
 class TestOWSProxyPOSTTranscoder(unittest.TestCase):

Modified: trunk/test/test_threadpool.py
===================================================================
--- trunk/test/test_threadpool.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/test/test_threadpool.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -10,7 +10,7 @@
 import threading
 import unittest
 
-import threadpool
+import inteproxy.threadpool
 
 def currentThreadSet():
     """Returns the currently running threads as a set"""
@@ -32,7 +32,7 @@
         initial_threads = currentThreadSet()
 
         # Create a thread pool and start its threads
-        pool = threadpool.ThreadPool(5, handler)
+        pool = inteproxy.threadpool.ThreadPool(5, handler)
         pool.start()
 
         # check that 5 new threads have been started

Modified: trunk/test/test_transcoder_map.py
===================================================================
--- trunk/test/test_transcoder_map.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/test/test_transcoder_map.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -11,7 +11,7 @@
 
 import support
 
-from transcoder import create_transcoder_map, \
+from inteproxy.transcoder import create_transcoder_map, \
      OWSProxyGETTranscoder, OWSProxyPOSTTranscoder, IdentityTranscoder
 
 

Deleted: trunk/threadpool.py
===================================================================
--- trunk/threadpool.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/threadpool.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -1,72 +0,0 @@
-# Copyright (C) 2007 by Intevation GmbH
-# Authors:
-# Bernhard Herzog <bh at intevation.de>
-#
-# This program is free software under the GPL (>=v2)
-# Read the file COPYING coming with the software for details.
-
-"""Simple pool of worker threads to process tasks like e.g. HTTP requests"""
-
-
-import threading
-import Queue
-
-
-class ThreadPool(object):
-
-    """A class to manage a set of threads that read tasks from a queue.
-
-    The threads managed by the class are started as deamon threads so
-    that it's not required to terminate them if the program using them
-    wants to exit.  Still, they can be explicitly stopped with the stop
-    method.
-
-    The threads read tasks from a Queue object managed by the ThreadPool
-    instance using the queue's blocking get() method.  Tasks taken from
-    the queue are then passed to the handler_function which was
-    specified then the ThreadPool instance was created.  The
-    handler_function is called with one parameter, the task object
-    (which can be any object except None), and should return when the
-    task is finished.  Repeatedly getting new tasks from the queue is
-    handled by the thread pool itself.
-
-    The program using the thread pool puts tasks into the queue with the
-    thread pool's put method.
-    """
-
-    def __init__(self, num_threads, handler_function):
-        """Initialize the thread pool with a number of threads and a handler"""
-        self.queue = Queue.Queue(0)
-        self.num_threads = num_threads
-        self.handler_function = handler_function
-        self.threads = []
-
-    def start(self):
-        """Starts the threads"""
-        self.threads = []
-        for i in range(self.num_threads):
-            thread = threading.Thread(target = self._thread)
-            thread.setDaemon(1)
-            thread.start()
-            self.threads.append(thread)
-
-    def _thread(self):
-        """Takes tasks repeatedly the queue and calls the handler_function
-        This is an internal method.
-        """
-        while 1:
-            item = self.queue.get()
-            if item is None:
-                break
-            self.handler_function(item)
-
-    def stop(self):
-        """Stops the worker threads"""
-        for i in range(len(self.threads)):
-            self.put(None)
-        for thread in self.threads:
-            thread.join()
-
-    def put(self, item):
-        """Puts item into the queue to be processed by a worker thread"""
-        self.queue.put(item)

Deleted: trunk/transcoder.py
===================================================================
--- trunk/transcoder.py	2007-04-20 15:55:01 UTC (rev 58)
+++ trunk/transcoder.py	2007-04-23 12:54:25 UTC (rev 59)
@@ -1,221 +0,0 @@
-# Copyright (C) 2007 by Intevation GmbH
-# Authors:
-# Bernhard Herzog <bh at intevation.de>
-#
-# This program is free software under the GPL (>=v2)
-# Read the file COPYING coming with the software for details.
-
-"""Classes to modify HTTP requests."""
-
-import urlparse
-from urllib import quote_plus
-from StringIO import StringIO
-from ConfigParser import SafeConfigParser
-
-from lxml import etree
-
-import getpassword
-
-
-class IdentityTranscoder(object):
-
-    """A transcoder that does not change anything
-
-    Other transcoders can be derived from this class so that they only
-    need to implement the methods that actually change parts of a
-    request.
-    """
-
-    def __init__(self, method, spliturl):
-        """Initializes the transcoder
-
-        Parameters:
-        method -- The HTTP method, either 'GET' or 'POST'
-        spliturl -- A tuple with the split url of the real remote host.
-                    The tuple has the form of the returl value of
-                    urlparse.urlsplit
-        """
-        self.method = method
-        self.spliturl = spliturl
-
-    def get_password(self):
-        """Returns the username and password needed for the request
-
-        The default implementation here simply uses the host and path
-        parts of the url as the parameter for the
-        get_password_with_cache function.
-        """
-        return getpassword.get_password_with_cache("".join(self.spliturl[1:3]))
-
-    def get_url(self):
-        """Returns the real url to connect to when handling this request
-
-        The default implementation simply returns the recombined url
-        given to the constructor
-        """
-        return urlparse.urlunsplit(self.spliturl)
-
-    def convert_body(self, content_type, body):
-        """Convert the body of the request
-
-        Parameters:
-        content_type -- The value of the Content-Type header of the request.
-                        If no Content-Type was give, the value is None
-        body -- The body of the request as a string.
-
-        The return value is a tuple (new_content_type, new_body).  The
-        default implementation simply returns the parameters unchanged.
-        """
-        return content_type, body
-
-
-class HTTPSTranscoder(IdentityTranscoder):
-
-    """Transcoder that turns the URL unconditionally into a HTTPS URL"""
-
-    def __init__(self, method, spliturl):
-        super(HTTPSTranscoder, self).__init__(method, ("https",) + spliturl[1:])
-
-
-class OWSProxyGETTranscoder(HTTPSTranscoder):
-
-    """Transcoder for GET requests to the OWSProxy"""
-
-    def get_url(self):
-        """Returns the URL with username and password added to the query"""
-        scheme, netloc, path, query, fragment = self.spliturl
-        if self.method == "GET":
-            user, password = self.get_password()
-            # FIXME: quote username and password properly
-            if query:
-                split_query = query.split("&")
-            else:
-                split_query = []
-            query = "&".join(split_query
-                             + ["user=%s" % quote_plus(user),
-                                "password=%s" % quote_plus(password)])
-        return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
-
-
-class OWSProxyPOSTTranscoder(HTTPSTranscoder):
-
-    """Transcoder for POST requests to the OWSProxy"""
-
-    def convert_body(self, content_type, body):
-        """Adds user and password attributes to the GetFeature element.
-        """
-        t = etree.parse(StringIO(body))
-        root = t.getroot()
-        if root.tag in ("{http://www.opengis.net/wfs}GetFeature",
-                        "{http://www.opengis.net/wfs}Transaction"):
-            user, password = self.get_password()
-            root.set("user", user)
-            root.set("password", password)
-            body = etree.tostring(t, xml_declaration=True)
-            content_type = "text/xml"
-        return content_type, body
-
-
-class TranscoderMap(object):
-
-    """Manages the host specific transcoder settings"""
-
-    def __init__(self, classes):
-        """Initializes the TranscoderMap.
-
-        The parameter 'classes' should be a sequence of (name, get,
-        post) triples.  They will be used to add classes with the
-        add_class method.  The first item in classes will become the
-        default class.
-        """
-        self.hostmap = dict()
-        self.classmap = dict()
-        self.default_classname = None
-
-        if classes:
-            for item in classes:
-                self.add_class(*item)
-            self.set_default_class(classes[0][0])
-
-    def set_default_class(self, name):
-        """Sets the default class"""
-        self.default_classname = name
-
-    def add_class(self, name, get, post):
-        """Adds a transcoder class named name.
-        The get and post parameters are the python classes implementing
-        the transcoder for the GET and POST methods.
-        """
-        self.classmap[name] = dict(GET=get, POST=post)
-
-    def add_host(self, host, path, classname):
-        """Adds a host description.
-
-        A connection path on host will be done with the appropriate
-        transcoder from the class given by classname.
-        """
-        self.hostmap[(host, path)] = classname
-
-    def lookup(self, method, host, path):
-        """Returns the python class implementing the transcoder for path on host
-        """
-        classname = self.hostmap.get((host, path), self.default_classname)
-        return self.classmap[classname][method]
-
-    def get_transcoder(self, method, url):
-        """Returns a transcoder for the given HTTP method and URL
-
-        URL should be the URL given for the GET or POST http request.
-        This function extracts the real remote host from the URL and
-        uses the URL to look up the transcoder with lookup_transcoder.
-
-        This method supports two ways to encode the remote host in the
-        URL:
-
-           -- InteProxy is accessed directly as an HTTP server.  In this
-              cases URL is an absolute pathname and does not include a
-              hostname in the normal URL syntax.  Instead get_transcoder
-              assumes that it encodes the real remote host in the first
-              component of the path.  This is the old InteProxy method
-
-           -- InteProxy is used as a HTTP-proxy.  In this case URL will
-              be a full URL including a hostname.  In this case
-              get_transcoder will use the host of the URL as the real
-              remote host.  The path component of the URL is not
-              modified.
-        """
-        scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
-
-        # If scheme is given, InteProxy is used as a HTTP proxy, otherwise
-        # it's the old InteProxy approach.  Only the old approach needs
-        # special casing.
-        if not scheme:
-            scheme = "http"
-            # determine the remote host encoded in the path
-            split_path = path.split("/")
-            if not split_path[0]:
-                del split_path[0]
-            netloc = split_path.pop(0)
-            path = "/" + "/".join(split_path)
-
-        transcoder_class = self.lookup(method, netloc, path)
-        return transcoder_class(method,
-                                (scheme, netloc, path, query, fragment))
-
-    def read_config(self, filename):
-        """Reads a configuration file and adds the host descriptions found"""
-        parser = SafeConfigParser()
-        parser.read([filename])
-        for section in parser.sections():
-            host = parser.get(section, "host")
-            path = parser.get(section, "path")
-            cls = parser.get(section, "class")
-            self.add_host(host, path, cls)
-
-
-def create_transcoder_map():
-    return TranscoderMap([
-        ("identity", IdentityTranscoder, IdentityTranscoder),
-        ("owsproxy", OWSProxyGETTranscoder, OWSProxyPOSTTranscoder),
-        ])
-transcoder_map = create_transcoder_map()



More information about the Inteproxy-commits mailing list