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)
I can't get diff data. plese check original data.
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).
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
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>