I watch following beautiful codes ...

  • CherryPy
  • Django
  • Jinja
  • Pylons
  • SQLAlchemy
  • Tornado
  • TurboGears
  • Twisted
  • Werkzeug

You can following ...

  • atom feed
  • twitter

Twisted: Changeset [27780]: Merge forward, resolve numerous conflicts

Twisted

27780
at 2009-12-15 15:17:02
by exarkun@example.com (exarkun)

Index: /branches/signal-process-group-2726-4/twisted/test/mock_win32process.py
===================================================================
--- /branches/signal-process-group-2726-4/twisted/test/mock_win32process.py (revision 23212)
+++ /branches/signal-process-group-2726-4/twisted/test/mock_win32process.py (revision 27780)
@@ -12,4 +12,5 @@
 import win32process
 GetExitCodeProcess = win32process.GetExitCodeProcess
+ResumeThread = win32process.ResumeThread
 STARTUPINFO = win32process.STARTUPINFO
 
Index: /branches/signal-process-group-2726-4/twisted/test/process_signalgroup.py
===================================================================
--- /branches/signal-process-group-2726-4/twisted/test/process_signalgroup.py (revision 27780)
+++ /branches/signal-process-group-2726-4/twisted/test/process_signalgroup.py (revision 27780)
@@ -0,0 +1,29 @@
+import time, sys, signal
+
+signal.signal(signal.SIGHUP, signal.SIG_DFL)
+if sys.argv[1] == "parent":
+    from popen2 import Popen4
+    import os
+    try:
+        os.setsid()
+    except OSError:
+        # If it's a PTY process, the call has already been made
+        pass
+    process = Popen4("%s -u %s child" % (sys.executable, __file__))
+    stdout = process.fromchild.readline()
+    def handle(*args):
+        # Wait for child to terminate
+        process.wait()
+        # Put back SIG_DFL
+        signal.signal(signal.SIGINT, signal.SIG_DFL)
+        # Re-signal
+        os.kill(os.getpid(), signal.SIGINT)
+    signal.signal(signal.SIGINT, handle)
+    print 'ok, signal us'
+    sys.stdin.read()
+    sys.exit(1)
+else:
+    signal.signal(signal.SIGINT, signal.SIG_DFL)
+    print 'ok, signal us'
+    sys.stdin.read()
+    sys.exit(1)
Index: /branches/signal-process-group-2726-4/twisted/test/process_signaljob.py
===================================================================
--- /branches/signal-process-group-2726-4/twisted/test/process_signaljob.py (revision 27780)
+++ /branches/signal-process-group-2726-4/twisted/test/process_signaljob.py (revision 27780)
@@ -0,0 +1,21 @@
+from twisted.internet import reactor, protocol
+import sys, signal, time
+
+signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+if sys.argv[1] == "parent":
+    class WaitProcessProtocol(protocol.ProcessProtocol):
+        def outReceived(self, data):
+            print 'ok, signal us'
+
+    p = WaitProcessProtocol()
+    exe = sys.executable
+    reactor.spawnProcess(p, exe, [exe, "-u", __file__, "child"], env=None)
+
+    reactor.run(installSignalHandlers=False)
+else:
+    print 'ok, signal us'
+    # Ideally, I would wait on sys.stdin.read() here. But when the parent
+    # terminates, it's closed so the child is terminated too.
+    time.sleep(120)
+    sys.exit(1)
Index: /branches/signal-process-group-2726-4/twisted/test/test_process.py
===================================================================
--- /branches/signal-process-group-2726-4/twisted/test/test_process.py (revision 27135)
+++ /branches/signal-process-group-2726-4/twisted/test/test_process.py (revision 27780)
@@ -266,11 +266,12 @@
     """
 
-    def __init__(self, deferred, sig):
+    def __init__(self, deferred, sig, method="signalProcess"):
         self.deferred = deferred
         self.signal = sig
+        self.method = method
 
 
     def outReceived(self, data):
-        self.transport.signalProcess(self.signal)
+        getattr(self.transport, self.method)(self.signal)
 
 
@@ -1099,4 +1100,23 @@
 
 
+    def test_signalProcessGroup(self):
+        """
+        Send a INT signal to a group of processes.
+        """
+        exe = sys.executable
+        scriptPath = util.sibpath(__file__, "process_signalgroup.py")
+        d = defer.Deferred()
+        p = SignalProtocol(d, "INT", "signalProcessGroup")
+        reactor._handleSignals()
+        proc = reactor.spawnProcess(p, exe, [exe, "-u", scriptPath, "parent"],
+                                    env=None,
+                                    usePTY=self.usePTY)
+        pid = proc.pid
+        def check(result):
+            error = self.assertRaises(OSError, os.kill, -pid, 0)
+            self.assertEquals(error[0], errno.ESRCH)
+        return d.addCallback(check)
+
+
     def test_errorInProcessEnded(self):
         """
@@ -1937,4 +1957,6 @@
 
 
+
+
 class PosixProcessTestCasePTY(unittest.TestCase, PosixProcessBase):
     """
@@ -2076,5 +2098,4 @@
         """
         import win32api
-
         connected = defer.Deferred()
         ended = defer.Deferred()
@@ -2119,4 +2140,26 @@
 
         return defer.gatherResults([connected, ended])
+
+
+    def test_signalProcessGroup(self):
+        """
+        Send a INT signal to a group of processes.
+        """
+        exe = sys.executable
+        scriptPath = util.sibpath(__file__, "process_signaljob.py")
+        d = defer.Deferred()
+        p = Win32SignalProtocol(d, "INT", "signalProcessGroup")
+        reactor._handleSignals()
+        proc = reactor.spawnProcess(p, exe, [exe, "-u", scriptPath, "parent"],
+                                    env=None)
+
+        def check(result):
+            # If we're here, both processes must have terminated, so it's just
+            # a sanity check
+            import win32job
+            jobProcesses = win32job.QueryInformationJobObject(proc.job,
+                win32job.JobObjectBasicProcessIdList)
+            self.assertEquals(len(jobProcesses), 0)
+        return d.addCallback(check)
 
 
Index: /branches/signal-process-group-2726-4/twisted/internet/interfaces.py
===================================================================
--- /branches/signal-process-group-2726-4/twisted/internet/interfaces.py (revision 27770)
+++ /branches/signal-process-group-2726-4/twisted/internet/interfaces.py (revision 27780)
@@ -1506,4 +1506,5 @@
         """
 
+
     def signalProcess(signalID):
         """
@@ -1519,6 +1520,14 @@
 
         @raise twisted.internet.error.ProcessExitedAlready: The process has
-        already exited.
-        """
+            already exited.
+        """
+
+
+    def signalProcessGroup(signalID):
+        """
+        Send a signal to every processes in the process group. C{signalID}
+        takes the value as in L{signalProcess}.
+        """
+
 
 
Index: /branches/signal-process-group-2726-4/twisted/internet/_dumbwin32proc.py
===================================================================
--- /branches/signal-process-group-2726-4/twisted/internet/_dumbwin32proc.py (revision 27356)
+++ /branches/signal-process-group-2726-4/twisted/internet/_dumbwin32proc.py (revision 27780)
@@ -17,4 +17,5 @@
 import win32process
 import win32security
+import win32job
 
 import pywintypes
@@ -35,8 +36,5 @@
 from twisted.internet._baseprocess import BaseProcess
 
-def debug(msg):
-    import sys
-    print msg
-    sys.stdout.flush()
+
 
 class _Reaper(_pollingfile._PollableResource):
@@ -169,8 +167,11 @@
 
         cmdline = quoteArguments(args)
+
+        self.job = win32job.CreateJobObject(None, None)
         # TODO: error detection here.
         def doCreate():
             self.hProcess, self.hThread, self.pid, dwTid = win32process.CreateProcess(
-                command, cmdline, None, None, 1, 0, env, path, StartupInfo)
+                command, cmdline, None, None, 1, win32con.CREATE_SUSPENDED,
+                env, path, StartupInfo)
         try:
             doCreate()
@@ -206,4 +207,9 @@
                         raise OSError(pwte2)
 
+        win32job.AssignProcessToJobObject(self.job, self.hProcess)
+        win32process.ResumeThread(self.hThread)
+
+        win32file.CloseHandle(self.hThread)
+
         # close handles which only the child will use
         win32file.CloseHandle(hStderrW)
@@ -235,9 +241,40 @@
 
 
+    def _raiseUnknownSignal(self, signalID):
+        """
+        Helper method raising an error when a given signal can't be handled.
+        """
+        raise ValueError(
+            "Signal not handled: %s. "
+            "Only 'INT', 'TERM' or 'KILL' can be used." % (signalID,))
+
+
     def signalProcess(self, signalID):
+        """
+        Terminate process if C{signalID} is one of "INT", "TERM", or "KILL".
+
+        @type signalID: C{str}
+        """
         if self.pid is None:
             raise error.ProcessExitedAlready()
         if signalID in ("INT", "TERM", "KILL"):
             win32process.TerminateProcess(self.hProcess, 1)
+        else:
+            self._raiseUnknownSignal(signalID)
+
+
+    def signalProcessGroup(self, signalID):
+        """
+        Terminate process group if C{signalID} is one of "INT", "TERM", or
+        "KILL".
+
+        @type signalID: C{str}
+        """
+        if self.pid is None:
+            raise error.ProcessExitedAlready()
+        if signalID in ("INT", "TERM", "KILL"):
+            win32job.TerminateJobObject(self.job, 1)
+        else:
+            self._raiseUnknownSignal(signalID)
 
 
Index: /branches/signal-process-group-2726-4/twisted/internet/process.py
===================================================================
--- /branches/signal-process-group-2726-4/twisted/internet/process.py (revision 26050)
+++ /branches/signal-process-group-2726-4/twisted/internet/process.py (revision 27780)
@@ -332,4 +332,19 @@
         if self.pid is None:
             raise ProcessExitedAlready()
+        os.kill(self.pid, signalID)
+
+
+    def signalProcessGroup(self, signalID):
+        """
+        Send the given signal C{signalID} to the process group. It does the
+        same translation as L{signalProcess}.
+
+        @type signalID: C{str} or C{int}
+        """
+        if signalID in ('HUP', 'STOP', 'INT', 'KILL', 'TERM'):
+            signalID = getattr(signal, 'SIG%s' % (signalID,))
+        if self.pid is None:
+            raise ProcessExitedAlready()
+        self.pid = -self.pid
         os.kill(self.pid, signalID)
 

Twisted: Changeset [27779]: Branching to 'signal-process-group-2726-4'

Twisted

27779
at 2009-12-15 15:15:37
by exarkun@example.com (exarkun)

I can't get diff data. plese check original data.

Django: Changeset [11868]: [soc2009/multidb] Added backwards compatibility layer for contrib.gis. …

Django

11868
at 2009-12-15 08:25:58
by sorry, but unknown...

Index: /django/branches/soc2009/multidb/django/db/__init__.py
===================================================================
--- /django/branches/soc2009/multidb/django/db/__init__.py (revision 11781)
+++ /django/branches/soc2009/multidb/django/db/__init__.py (revision 11868)
@@ -37,10 +37,24 @@
 for database in settings.DATABASES.values():
     if database['ENGINE'] in ("postgresql", "postgresql_psycopg2", "sqlite3", "mysql", "oracle"):
-        database['ENGINE'] = "django.db.backends.%s" % database['ENGINE']
         import warnings
-        warnings.warn(
-            "Short names for DATABASE_ENGINE are deprecated; prepend with 'django.db.backends.'",
-            PendingDeprecationWarning
-        )
+        if 'django.contrib.gis' in settings.INSTALLED_APPS:
+            warnings.warn(
+                "django.contrib.gis is now implemented as a full database backend.\n"
+                "Modify DATABASE_ENGINE to select a backend from 'django.contrib.gis.db.backends'",
+                PendingDeprecationWarning
+            )
+            if database['ENGINE'] == 'postgresql_psycopg2':
+                full_engine = 'django.contrib.gis.db.backends.postgis'
+            elif database['ENGINE'] == 'sqlite3':
+                full_engine = 'django.contrib.gis.db.backends.spatialite'
+            else:
+                full_engine = 'django.contrib.gis.db.backends.%s' % database['ENGINE']
+        else:
+            warnings.warn(
+                "Short names for DATABASE_ENGINE are deprecated; prepend with 'django.db.backends.'",
+                PendingDeprecationWarning
+            )
+            full_engine = "django.db.backends.%s" % database['ENGINE']
+        database['ENGINE'] = full_engine
 
 connections = ConnectionHandler(settings.DATABASES)
Index: /django/branches/soc2009/multidb/TODO
===================================================================
--- /django/branches/soc2009/multidb/TODO (revision 11805)
+++ /django/branches/soc2009/multidb/TODO (revision 11868)
@@ -5,7 +5,4 @@
 ~~~~~~~~~~~~~~~~~
 
- * Finalize the sql.Query internals
-   * Clean up the use of db.backend.query_class()
-   * Verify it still works with GeoDjango
  * Modify the admin interface to support multiple databases (doh).
 

Django: Changeset [11867]: [soc2009/multidb] Corrected merge error. Patch from Russell Keith-Magee.

Django

11867
at 2009-12-15 08:25:50
by sorry, but unknown...

Index: /django/branches/soc2009/multidb/django/db/models/fields/__init__.py
===================================================================
--- /django/branches/soc2009/multidb/django/db/models/fields/__init__.py (revision 11860)
+++ /django/branches/soc2009/multidb/django/db/models/fields/__init__.py (revision 11867)
@@ -370,5 +370,5 @@
 class AutoField(Field):
     """Integer"""
-    
+
     empty_strings_allowed = False
 
@@ -449,5 +449,5 @@
 class CharField(Field):
     """String (up to %(max_length)s)"""
-    
+
     def get_internal_type(self):
         return "CharField"
@@ -472,5 +472,5 @@
 class CommaSeparatedIntegerField(CharField):
     """Comma-separated integers"""
-    
+
     def formfield(self, **kwargs):
         defaults = {
@@ -489,5 +489,5 @@
 class DateField(Field):
     """Date (without time)"""
-    
+
     empty_strings_allowed = False
 
@@ -572,5 +572,5 @@
 class DateTimeField(DateField):
     """Date (with time)"""
-    
+
     def get_internal_type(self):
         return "DateTimeField"
@@ -638,5 +638,5 @@
 class DecimalField(Field):
     """Decimal number"""
-    
+
     empty_strings_allowed = False
 
@@ -695,5 +695,5 @@
 class EmailField(CharField):
     """E-mail address"""
-    
+
     def __init__(self, *args, **kwargs):
         kwargs['max_length'] = kwargs.get('max_length', 75)
@@ -707,5 +707,5 @@
 class FilePathField(Field):
     """File path"""
-    
+
     def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs):
         self.path, self.match, self.recursive = path, match, recursive
@@ -728,5 +728,5 @@
 class FloatField(Field):
     """Floating point number"""
-    
+
     empty_strings_allowed = False
 
@@ -755,12 +755,8 @@
 class IntegerField(Field):
     """Integer"""
-    
+
     empty_strings_allowed = False
-<<<<<<< HEAD:django/db/models/fields/__init__.py
+
     def get_prep_value(self, value):
-=======
-
-    def get_db_prep_value(self, value):
->>>>>>> master:django/db/models/fields/__init__.py
         if value is None:
             return None
@@ -786,5 +782,5 @@
 class IPAddressField(Field):
     """IP address"""
-    
+
     empty_strings_allowed = False
 
@@ -846,5 +842,5 @@
 class PositiveIntegerField(IntegerField):
     """Integer"""
-    
+
     def get_internal_type(self):
         return "PositiveIntegerField"
@@ -886,5 +882,5 @@
 class SmallIntegerField(IntegerField):
     """Integer"""
-    
+
     def get_internal_type(self):
         return "SmallIntegerField"
@@ -892,5 +888,5 @@
 class TextField(Field):
     """Text"""
-    
+
     def get_internal_type(self):
         return "TextField"
@@ -903,5 +899,5 @@
 class TimeField(Field):
     """Time"""
-    
+
     empty_strings_allowed = False
 
@@ -983,5 +979,5 @@
 class URLField(CharField):
     """URL"""
-    
+
     def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
         kwargs['max_length'] = kwargs.get('max_length', 200)
@@ -996,5 +992,5 @@
 class XMLField(TextField):
     """XML text"""
-    
+
     def __init__(self, verbose_name=None, name=None, schema_path=None, **kwargs):
         self.schema_path = schema_path

Twisted: Changeset [27778]: Apply finger-tutorial-preambles2.patch Author: jesstess Reviewer: …

Twisted

27778
at 2009-12-15 03:35:13
by jesstess@example.com (jesstess)

Index: /trunk/doc/core/howto/application.xhtml
===================================================================
--- /trunk/doc/core/howto/application.xhtml (revision 27686)
+++ /trunk/doc/core/howto/application.xhtml (revision 27778)
@@ -19,5 +19,5 @@
 configurable fashion.  A Twisted user who wishes to use the Application
 framework needs to be familiar with developing Twisted <a
-href="servers.xhtml">servers</a> and/or <a href="clients.xhtml">clients</a></p>.
+href="servers.xhtml">servers</a> and/or <a href="clients.xhtml">clients</a>.</p>
 
 <h3>Goals</h3>
Index: /trunk/doc/core/howto/tutorial/library.xhtml
===================================================================
--- /trunk/doc/core/howto/tutorial/library.xhtml (revision 10593)
+++ /trunk/doc/core/howto/tutorial/library.xhtml (revision 27778)
@@ -14,8 +14,10 @@
 href="index.xhtml">Twisted from Scratch, or The Evolution of Finger</a>.</p>
 
-<p>In this part, we separate the application code that launches a finger
-service from the library code which defines a finger service, placing the
-application in a Twisted Application Configuration (.tac) file. We also move
-configuration (such as HTML templates) into separate files.</p>
+<p>In this part, we separate the application code that launches a finger service
+from the library code which defines a finger service, placing the application in
+a Twisted Application Configuration (.tac) file. We also move configuration
+(such as HTML templates) into separate files. Configuration and deployment with
+.tac and twistd are introduced in <a href="../application.xhtml">Using the
+Twisted Application Framework</a>.</p>
 
 <h2>Organization</h2>
Index: /trunk/doc/core/howto/tutorial/components.xhtml
===================================================================
--- /trunk/doc/core/howto/tutorial/components.xhtml (revision 24451)
+++ /trunk/doc/core/howto/tutorial/components.xhtml (revision 27778)
@@ -15,5 +15,7 @@
 
 <p>In this section of the tutorial, we'll move our code to a component
-architecture so that adding new features is trivial.</p>
+architecture so that adding new features is trivial.
+See <a href="../components.xhtml">Interfaces and Adapters</a> for a more
+complete discussion of components.</p>
 
 <h2>Write Maintainable Code</h2>
Index: /trunk/doc/core/howto/tutorial/configuration.xhtml
===================================================================
--- /trunk/doc/core/howto/tutorial/configuration.xhtml (revision 25672)
+++ /trunk/doc/core/howto/tutorial/configuration.xhtml (revision 27778)
@@ -15,5 +15,10 @@
 
 <p>In this part, we make it easier for non-programmers to configure a finger
-server, and show how to package it in the .deb and RPM package formats.</p>
+server and show how to package it in the .deb and RPM package formats. Plugins
+are discussed further in the <a href="../plugin.xhtml">Twisted Plugin System</a>
+howto. .tap files are covered in <a href="../tap.xhtml">Writing a twistd
+Plugin</a>, and .tac applications are covered
+in <a href="../application.xhtml">Using the Twisted Application
+Framework</a>.</p>
 
 <h2>Plugins</h2>
Index: /trunk/doc/core/howto/tutorial/factory.xhtml
===================================================================
--- /trunk/doc/core/howto/tutorial/factory.xhtml (revision 10593)
+++ /trunk/doc/core/howto/tutorial/factory.xhtml (revision 27778)
@@ -16,6 +16,7 @@
 href="index.xhtml">Twisted from Scratch, or The Evolution of Finger</a>.</p>
 
-<p>In this part, we add HTTPS support to our web frontend, showing how to have
-a single factory listen on multiple ports.</p>
+<p>In this part, we add HTTPS support to our web frontend, showing how to have a
+single factory listen on multiple ports. More information on using SSL in
+Twisted can be found in the <a href="../ssl.xhtml">SSL howto</a>.</p>
 
 <h2>Support HTTPS</h2>
Index: /trunk/doc/core/howto/tutorial/index.xhtml
===================================================================
--- /trunk/doc/core/howto/tutorial/index.xhtml (revision 10840)
+++ /trunk/doc/core/howto/tutorial/index.xhtml (revision 27778)
@@ -27,4 +27,17 @@
 We will extend this service slightly beyond the standard, in order to 
 demonstrate some of Twisted's higher-level features.
+</p>
+
+<p>
+Each section of the tutorial dives straight into applications for various
+Twisted topics. These topics have their own introductory howtos listed in
+the <a href="../index.xhtml">core howto index</a> and in the documentation for
+other Twisted projects like Twisted Web and Twisted Words. There are at least
+three ways to use this tutorial: you may find it useful to read through the rest
+of the topics listed in the <a href="../index.xhtml">core howto index</a> before
+working through the finger tutorial, work through the finger tutorial and then
+go back and hit the introductory material that is relevant to the Twisted
+project you're working on, or read the introductory material one piece at a time
+as it comes up in the finger tutorial.
 </p>
 
Index: /trunk/doc/core/howto/tutorial/intro.xhtml
===================================================================
--- /trunk/doc/core/howto/tutorial/intro.xhtml (revision 27174)
+++ /trunk/doc/core/howto/tutorial/intro.xhtml (revision 27778)
@@ -36,4 +36,11 @@
 organization. You can also define pseudo "users", which are essentially
 keywords.</p>
+
+<p>This portion of the tutorial makes use of factories and protocols as
+introduced in the <a href="../servers.xhtml">Writing a TCP Server howto</a> and
+deferreds as introduced in <a href="../defer.xhtml">Using Deferreds</a>
+and <a href="../gendefer.xhtml">Generating Deferreds</a>. Services and
+applications are discussed in <a href="../application.xhtml">Using the Twisted
+Application Framework</a>.</p>
 
 <p>By the end of this section of the tutorial, our finger server will answer
Index: /trunk/doc/core/howto/tutorial/pb.xhtml
===================================================================
--- /trunk/doc/core/howto/tutorial/pb.xhtml (revision 24451)
+++ /trunk/doc/core/howto/tutorial/pb.xhtml (revision 27778)
@@ -15,5 +15,7 @@
 
 <p>In this part, we add a Perspective Broker service to the finger application
-so that Twisted clients can access the finger server.</p>
+so that Twisted clients can access the finger server. Perspective Broker is
+introduced in depth in its own <a href="../index.xhtml#pb">section</a> of the
+core howto index.</p>
 
 <h2>Use Perspective Broker</h2>
Index: /trunk/doc/core/howto/tutorial/protocol.xhtml
===================================================================
--- /trunk/doc/core/howto/tutorial/protocol.xhtml (revision 25523)
+++ /trunk/doc/core/howto/tutorial/protocol.xhtml (revision 27778)
@@ -16,5 +16,10 @@
 <p>In this section of the tutorial, our finger server will continue to sprout
 features: the ability for users to set finger announces, and using our finger
-service to send those announcements on the web, on IRC and over XML-RPC.</p>
+service to send those announcements on the web, on IRC and over XML-RPC.
+Resources and XML-RPC are introduced in the Web Applications portion of
+the <a href="../../../web/howto/index.xhtml">Twisted Web howto</a>. More examples
+using <code class="API">twisted.words.protocols.irc</code> can be found
+in <a href="../clients.xhtml">Writing a TCP Client</a> and
+the <a href="../../../words/examples/index.xhtml">Twisted Words examples</a>.</p>
 
 <h2>Setting Message By Local Users</h2>
Index: /trunk/doc/core/howto/index.xhtml
===================================================================
--- /trunk/doc/core/howto/index.xhtml (revision 27267)
+++ /trunk/doc/core/howto/index.xhtml (revision 27778)
@@ -14,5 +14,5 @@
 
   <ul class="toc">
-    <li>Introduction
+    <li><a name="introduction">Introduction</a>
 
       <ul>
@@ -26,5 +26,5 @@
     </li>
 
-    <li>Tutorials
+    <li><a name="tutorials">Tutorials</a>
 
       <ul>
@@ -85,5 +85,5 @@
     </li>
 
-    <li>Low-Level Networking and Event Loop
+    <li><a name="lowlevel">Low-Level Networking and Event Loop</a>
 
       <ul>
@@ -112,5 +112,5 @@
     </li>
 
-    <li>High-Level Twisted
+    <li><a name="highlevel">High-Level Twisted</a>
 
       <ul>
@@ -129,9 +129,11 @@
         Authentication</a></li>
 
-        <li><a href="application.xhtml">Using application</a></li>
+        <li><a href="application.xhtml">Using the Twisted Application
+        Framework</a></li>
+
       </ul>
     </li>
 
-    <li>Utilities
+    <li><a name="utilities">Utilities</a>
 
       <ul>
@@ -150,5 +152,5 @@
     </li>
 
-    <li>Twisted RDBMS support
+    <li><a name="rdbms">Twisted RDBMS support</a>
 
       <ul>
@@ -161,5 +163,5 @@
     </li>
 
-    <li>Perspective Broker
+    <li><a name="pb">Perspective Broker</a>
 
       <ul>
@@ -180,5 +182,5 @@
     </li>
 
-    <li>Appendix
+    <li><a name="appendix">Appendix</a>
 
       <ul>
Copyright Surgo. twitter: @Surgo
Powered by Google App Engine.