From python-checkins at python.org Tue Sep 5 19:50:56 2006 From: python-checkins at python.org (richard.tew) Date: Tue, 5 Sep 2006 19:50:56 +0200 (CEST) Subject: [Stackless-checkins] r51750 - stackless/sandbox/libraries/uthread-ccp/uthread.py Message-ID: <20060905175056.598C01E4004@bag.python.org> Author: richard.tew Date: Tue Sep 5 19:50:56 2006 New Revision: 51750 Added: stackless/sandbox/libraries/uthread-ccp/uthread.py - copied unchanged from r51749, stackless/trunk/PCbuild/uthread_ccp.py Log: Branched the CCP uthread module into the sandbox libraries, since it doesn't really belong in PCBuild. _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Thu Sep 7 11:58:19 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 7 Sep 2006 11:58:19 +0200 (CEST) Subject: [Stackless-checkins] r51802 - stackless/sandbox/libraries/slpmonkeypatch/resources stackless/sandbox/libraries/slpmonkeypatch/resources/iocp.py Message-ID: <20060907095819.859591E4003@bag.python.org> Author: richard.tew Date: Thu Sep 7 11:58:17 2006 New Revision: 51802 Added: stackless/sandbox/libraries/slpmonkeypatch/resources/ stackless/sandbox/libraries/slpmonkeypatch/resources/iocp.py (contents, props changed) Log: Added the start of ctypes based IO completion ports usage, in order to have something equivalent to asyncore for Windows which will work for both files and sockets. Added: stackless/sandbox/libraries/slpmonkeypatch/resources/iocp.py ============================================================================== --- (empty file) +++ stackless/sandbox/libraries/slpmonkeypatch/resources/iocp.py Thu Sep 7 11:58:17 2006 @@ -0,0 +1,90 @@ + + +from ctypes import windll, c_int, c_long, c_void_p, byref, c_char_p, Structure, Union +from ctypes.wintypes import HANDLE, POINTER, ULONG, DWORD + +INVALID_HANDLE_VALUE = -1 + +WAIT_TIMEOUT = 0x102 +ERROR_IO_PENDING = 997 + +class _US(Structure): + __fields__ = [ + ("Offset", DWORD), + ("OffsetHigh", DWORD), + ] + +class _U(Union): + __fields__ = [ + ("s", _US), + ("Pointer", c_void_p), + ] + + _anonymous_ = ("s",) + +class OVERLAPPED(Structure): + __fields__ = [ + ("Internal", POINTER(ULONG)), + ("InternalHigh", POINTER(ULONG)), + + ("u", _U), + + ("hEvent", HANDLE), + ] + + _anonymous_ = ("u",) + +class IOCP: + def __init__(self): + port = windll.kernel32.CreateIoCompletionPort(INVALID_HANDLE_VALUE, None, None, numThreads) + if port is None: + raise RuntimeError("Failed to create an IO completion port") + self.port = port + + def __del__(self): + while 1: + numBytes = c_long() + completionKey = c_long() + overlapped = c_void_p() + ret = windll.kernel32.GetQueuedCompletionStatus(port, byref(numBytes), byref(completionKey), byref(overlapped), timeout) + + if overlapped.value is None and ret == 0: + break + + def poll(self, timeout=0): + result = [] + while 1: + numBytes = c_long() + completionKey = c_long() + overlapped = c_void_p() + ret = windll.kernel32.GetQueuedCompletionStatus(port, byref(numBytes), byref(completionKey), byref(overlapped), timeout) + timeout = 0 + + if overlapped.value is None: + if ret == 0: + if windll.kernel32.GetLastError() == WAIT_TIMEOUT: + raise RuntimeError("GetQueuedCompletionStatus failed") + return result + raise RuntimeError("Unexpected problem with GetQueuedCompletionStatus") + + def read(self, f, offset, wantBytes): + lpBuffer = c_void_p() + readBytes = c_long() + overlapped = None + ret = windll.kernel32.ReadFile(f.fileno(), byref(lpBuffer), wantBytes, byref(readBytes), overlapped) + if ret == 0: + if windll.kernel32.GetLastError() == ERROR_IO_PENDING: + return None + raise RuntimeError("ReadFile failed") + return ret + + def write(self, f, offset, data): + writeBytes = c_long(len(data)) + bytesWritten = c_long() + overlapped = None + ret = windll.kernel32.WriteFile(f.fileno(), c_char_p(data), writeBytes, byref(bytesWritten), overlapped) + if ret == 0: + if windll.kernel32.GetLastError() == ERROR_IO_PENDING: + return None + raise RuntimeError("WriteFile failed") + return ret _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Sun Sep 10 12:22:28 2006 From: python-checkins at python.org (richard.tew) Date: Sun, 10 Sep 2006 12:22:28 +0200 (CEST) Subject: [Stackless-checkins] r51840 - stackless/sandbox/examples/threadchannels.py Message-ID: <20060910102228.ECE851E4008@bag.python.org> Author: richard.tew Date: Sun Sep 10 12:22:28 2006 New Revision: 51840 Added: stackless/sandbox/examples/threadchannels.py (contents, props changed) Log: Wrote up an example to demonstrate how Stackless deals with multiple threads and channel usage. This as intended to show how sending and receiving on channels where the tasklet that will be awakened by doing so belongs to another thread, activates that thread and immediately schedules the blocked tasklet. This example demonstrates that this is the case. Added: stackless/sandbox/examples/threadchannels.py ============================================================================== --- (empty file) +++ stackless/sandbox/examples/threadchannels.py Sun Sep 10 12:22:28 2006 @@ -0,0 +1,125 @@ +# +# A demonstration of how channels are allow interthread communication. +# +# Author: Richard Tew +# +# This code was written to serve as an example of Stackless Python usage. +# Feel free to email me with any questions, comments, or suggestions for +# improvement. +# +# FURTHER DETAIL: +# +# Sending or receiving on a channel when there is a waiting tasklet +# from another thread, will always block and schedule the tasklet +# on the other thread. The channel 'preference' attribute has no +# effect on this behaviour. This may not be the most optimal way +# to do sleeping and it might be better to have per-thread +# management of sleepers. +# + +import threading +import stackless +import time + +# Flag which should allow the threads to exit if cleared. +running = True + +# Altered boilerplate Sleep function. +sleepingTasklets = [] +sleepCountByThread = {} +threadIDByChannelID = {} +lock = threading.Lock() + +def GetThreadID(): + return id(threading.currentThread()) + +def Sleep(secondsToWait): + global sleepingTasklets, lock, threadIDByChannelID, sleepCountByThread + + channel = stackless.channel() + endTime = time.time() + secondsToWait + threadID = GetThreadID() + + lock.acquire(True) + sleepCountByThread[threadID] = sleepCountByThread.get(threadID, 0) + 1 + threadIDByChannelID[id(channel)] = threadID + sleepingTasklets.append((endTime, channel)) + sleepingTasklets.sort() + lock.release() + + # Block until we get sent an awakening notification. + channel.receive() + +def ManageSleepingTasklets(threadID): + global sleepingTasklets, lock, running, threadIDByChannelID, sleepCountByThread + + sleepingTasklets = [] + while running: + if len(sleepingTasklets): + lock.acquire(True) + endTime = sleepingTasklets[0][0] + if endTime <= time.time(): + channel = sleepingTasklets[0][1] + del sleepingTasklets[0] + threadID = threadIDByChannelID[id(channel)] + sleepCountByThread[threadID] -= 1 + lock.release() + + # We have to send something, but it doesn't matter what as it is not used. + channel.send(None) + else: + lock.release() + elif stackless.getruncount() == 1: + # Give up if there are no more sleeping tasklets. Otherwise the two + # threads keep on running endlessly. + print "Sleeping tasklet exited due to no remaining work." + break + stackless.schedule() + else: + print threadID, "Sleeping tasklet exited due to change in 'running' flag" + +# ... + +def looping_tasklet(threadID, taskletID): + n = 3 + while n > 0: + n -= 1 + print threadID, "looping_tasklet", taskletID, "loop", n + Sleep(1.0) + print threadID, "looping_tasklet", taskletID, "exit" + + +def a_main_tasklet(): + global running + + threadID = GetThreadID() + + for i in range(3): + stackless.tasklet(looping_tasklet)(threadID, i+1) + + # We need to catch the keyboard interrupt and signal the other thread to exit. + try: + print threadID, "start: runcount", stackless.getruncount() + + # Do a preliminary run to get some tasklets in the scheduler or some + # sleeping tasklets in place, otherwise we would not run at all. + stackless.run() + + # Now we should be set to run until we are done. + while running and (stackless.getruncount() > 1 or sleepCountByThread.get(threadID, 0)): + print threadID, "start: runcount", stackless.getruncount(), "sleepcount", sleepCountByThread.get(threadID, 0) + stackless.run() + print threadID, "stop: runcount", stackless.getruncount(), "sleepcount", sleepCountByThread.get(threadID, 0) + except: + running = False + raise + +if __name__ == "__main__": + threadID = GetThreadID() + + stackless.tasklet(ManageSleepingTasklets)(threadID) + + thread = threading.Thread(target=a_main_tasklet) + thread.start() + + a_main_tasklet() _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Wed Sep 20 22:30:33 2006 From: python-checkins at python.org (richard.tew) Date: Wed, 20 Sep 2006 22:30:33 +0200 (CEST) Subject: [Stackless-checkins] r51933 - in stackless/branches/release25-maint: Doc/commontex/boilerplate.tex Doc/lib/libetree.tex Doc/lib/libpyexpat.tex Doc/lib/libsqlite3.tex Doc/lib/libuuid.tex Include/patchlevel.h Lib/idlelib/NEWS.txt Lib/idlelib/idlever.py Mac/BuildScript/build-installer.py Mac/Tools/fixapplepython23.py Misc/NEWS Misc/RPM/python-2.5.spec README Tools/msi/msi.py Message-ID: <20060920203033.0B62D1E4006@bag.python.org> Author: richard.tew Date: Wed Sep 20 22:30:30 2006 New Revision: 51933 Modified: stackless/branches/release25-maint/Doc/commontex/boilerplate.tex stackless/branches/release25-maint/Doc/lib/libetree.tex stackless/branches/release25-maint/Doc/lib/libpyexpat.tex stackless/branches/release25-maint/Doc/lib/libsqlite3.tex stackless/branches/release25-maint/Doc/lib/libuuid.tex stackless/branches/release25-maint/Include/patchlevel.h stackless/branches/release25-maint/Lib/idlelib/NEWS.txt stackless/branches/release25-maint/Lib/idlelib/idlever.py stackless/branches/release25-maint/Mac/BuildScript/build-installer.py stackless/branches/release25-maint/Mac/Tools/fixapplepython23.py stackless/branches/release25-maint/Misc/NEWS stackless/branches/release25-maint/Misc/RPM/python-2.5.spec stackless/branches/release25-maint/README stackless/branches/release25-maint/Tools/msi/msi.py Log: Merged in the 2.5 final changes (r51860-r51908). Modified: stackless/branches/release25-maint/Doc/commontex/boilerplate.tex ============================================================================== --- stackless/branches/release25-maint/Doc/commontex/boilerplate.tex (original) +++ stackless/branches/release25-maint/Doc/commontex/boilerplate.tex Wed Sep 20 22:30:30 2006 @@ -5,5 +5,5 @@ Email: \email{docs at python.org} } -\date{12th September, 2006} % XXX update before final release! +\date{19th September, 2006} % XXX update before final release! \input{patchlevel} % include Python version information Modified: stackless/branches/release25-maint/Doc/lib/libetree.tex ============================================================================== --- stackless/branches/release25-maint/Doc/lib/libetree.tex (original) +++ stackless/branches/release25-maint/Doc/lib/libetree.tex Wed Sep 20 22:30:30 2006 @@ -1,45 +1,34 @@ -\section{\module{elementtree} --- The xml.etree.ElementTree Module} -\declaremodule{standard}{elementtree} +\section{\module{xml.etree.ElementTree} --- The ElementTree XML API} +\declaremodule{standard}{xml.etree.ElementTree} \moduleauthor{Fredrik Lundh}{fredrik at pythonware.com} -\modulesynopsis{This module provides implementations -of the Element and ElementTree types, plus support classes. +\modulesynopsis{Implementation of the ElementTree API.} -A C version of this API is available as xml.etree.cElementTree.} \versionadded{2.5} - -\subsection{Overview\label{elementtree-overview}} - The Element type is a flexible container object, designed to store hierarchical data structures in memory. The type can be described as a cross between a list and a dictionary. Each element has a number of properties associated with it: -\begin{itemize} -\item {} -a tag which is a string identifying what kind of data -this element represents (the element type, in other words). - -\item {} -a number of attributes, stored in a Python dictionary. - -\item {} -a text string. - -\item {} -an optional tail string. - -\item {} -a number of child elements, stored in a Python sequence +\begin{itemize} + \item a tag which is a string identifying what kind of data + this element represents (the element type, in other words). + \item a number of attributes, stored in a Python dictionary. + \item a text string. + \item an optional tail string. + \item a number of child elements, stored in a Python sequence \end{itemize} To create an element instance, use the Element or SubElement factory functions. -The ElementTree class can be used to wrap an element +The \class{ElementTree} class can be used to wrap an element structure, and convert it from and to XML. +A C implementation of this API is available as +\module{xml.etree.cElementTree}. + \subsection{Functions\label{elementtree-functions}} Modified: stackless/branches/release25-maint/Doc/lib/libpyexpat.tex ============================================================================== --- stackless/branches/release25-maint/Doc/lib/libpyexpat.tex (original) +++ stackless/branches/release25-maint/Doc/lib/libpyexpat.tex Wed Sep 20 22:30:30 2006 @@ -216,9 +216,10 @@ \begin{memberdesc}[xmlparser]{returns_unicode} If this attribute is set to a non-zero integer, the handler functions -will be passed Unicode strings. If \member{returns_unicode} is 0, -8-bit strings containing UTF-8 encoded data will be passed to the -handlers. +will be passed Unicode strings. If \member{returns_unicode} is +\constant{False}, 8-bit strings containing UTF-8 encoded data will be +passed to the handlers. This is \constant{True} by default when +Python is built with Unicode support. \versionchanged[Can be changed at any time to affect the result type]{1.6} \end{memberdesc} Modified: stackless/branches/release25-maint/Doc/lib/libsqlite3.tex ============================================================================== --- stackless/branches/release25-maint/Doc/lib/libsqlite3.tex (original) +++ stackless/branches/release25-maint/Doc/lib/libsqlite3.tex Wed Sep 20 22:30:30 2006 @@ -146,8 +146,8 @@ wait for the lock to go away until raising an exception. The default for the timeout parameter is 5.0 (five seconds). -For the \var{isolation_level} parameter, please see \member{isolation_level} -\ref{sqlite3-Connection-IsolationLevel} property of \class{Connection} objects. +For the \var{isolation_level} parameter, please see the \member{isolation_level} +property of \class{Connection} objects in section~\ref{sqlite3-Connection-IsolationLevel}. SQLite natively supports only the types TEXT, INTEGER, FLOAT, BLOB and NULL. If you want to use other types, like you have to add support for them yourself. @@ -197,7 +197,7 @@ \verbatiminput{sqlite3/complete_statement.py} \end{funcdesc} -\begin{funcdesc}{}enable_callback_tracebacks{flag} +\begin{funcdesc}{enable_callback_tracebacks}{flag} By default you will not get any tracebacks in user-defined functions, aggregates, converters, authorizer callbacks etc. If you want to debug them, you can call this function with \var{flag} as True. Afterwards, you will get @@ -212,13 +212,14 @@ \label{sqlite3-Connection-IsolationLevel} \begin{memberdesc}{isolation_level} Get or set the current isolation level. None for autocommit mode or one of - "DEFERRED", "IMMEDIATE" or "EXLUSIVE". See Controlling Transactions - \ref{sqlite3-Controlling-Transactions} for a more detailed explanation. + "DEFERRED", "IMMEDIATE" or "EXLUSIVE". See ``Controlling Transactions'', + section~\ref{sqlite3-Controlling-Transactions}, for a more detailed explanation. \end{memberdesc} \begin{methoddesc}{cursor}{\optional{cursorClass}} The cursor method accepts a single optional parameter \var{cursorClass}. - This is a custom cursor class which must extend \class{sqlite3.Cursor}. + If supplied, this must be a custom cursor class that extends + \class{sqlite3.Cursor}. \end{methoddesc} \begin{methoddesc}{execute}{sql, \optional{parameters}} @@ -244,7 +245,7 @@ Creates a user-defined function that you can later use from within SQL statements under the function name \var{name}. \var{num_params} is the number of parameters the function accepts, and \var{func} is a Python callable that is -called as SQL function. +called as the SQL function. The function can return any of the types supported by SQLite: unicode, str, int, long, float, buffer and None. @@ -274,7 +275,7 @@ Creates a collation with the specified \var{name} and \var{callable}. The callable will be passed two string arguments. It should return -1 if the first -is ordered lower than the second, 0 if they are ordered equal and 1 and if the +is ordered lower than the second, 0 if they are ordered equal and 1 if the first is ordered higher than the second. Note that this controls sorting (ORDER BY in SQL) so your comparisons don't affect other SQL operations. @@ -323,20 +324,21 @@ \begin{memberdesc}{row_factory} You can change this attribute to a callable that accepts the cursor and - the original row as tuple and will return the real result row. This - way, you can implement more advanced ways of returning results, like - ones that can also access columns by name. + the original row as a tuple and will return the real result row. This + way, you can implement more advanced ways of returning results, such + as returning an object that can also access columns by name. Example: \verbatiminput{sqlite3/row_factory.py} - If the standard tuple types don't suffice for you, and you want name-based + If returning a tuple doesn't suffice and you want name-based access to columns, you should consider setting \member{row_factory} to the - highly-optimized sqlite3.Row type. It provides both + highly-optimized \class{sqlite3.Row} type. \class{Row} provides both index-based and case-insensitive name-based access to columns with almost - no memory overhead. Much better than your own custom dictionary-based - approach or even a db_row based solution. + no memory overhead. It will probably be better than your own custom + dictionary-based approach or even a db_row based solution. + % XXX what's a db_row-based solution? \end{memberdesc} \begin{memberdesc}{text_factory} @@ -350,7 +352,7 @@ attribute to \constant{sqlite3.OptimizedUnicode}. You can also set it to any other callable that accepts a single bytestring - parameter and returns the result object. + parameter and returns the resulting object. See the following example code for illustration: @@ -358,7 +360,7 @@ \end{memberdesc} \begin{memberdesc}{total_changes} - Returns the total number of database rows that have be modified, inserted, + Returns the total number of database rows that have been modified, inserted, or deleted since the database connection was opened. \end{memberdesc} @@ -385,9 +387,9 @@ \verbatiminput{sqlite3/execute_2.py} - \method{execute} will only execute a single SQL statement. If you try to + \method{execute()} will only execute a single SQL statement. If you try to execute more than one statement with it, it will raise a Warning. Use - \method{executescript} if want to execute multiple SQL statements with one + \method{executescript()} if you want to execute multiple SQL statements with one call. \end{methoddesc} @@ -395,7 +397,7 @@ \begin{methoddesc}{executemany}{sql, seq_of_parameters} Executes a SQL command against all parameter sequences or mappings found in the sequence \var{sql}. The \module{sqlite3} module also allows -to use an iterator yielding parameters instead of a sequence. +using an iterator yielding parameters instead of a sequence. \verbatiminput{sqlite3/executemany_1.py} @@ -407,7 +409,7 @@ \begin{methoddesc}{executescript}{sql_script} This is a nonstandard convenience method for executing multiple SQL statements -at once. It issues a COMMIT statement before, then executes the SQL script it +at once. It issues a COMMIT statement first, then executes the SQL script it gets as a parameter. \var{sql_script} can be a bytestring or a Unicode string. @@ -464,20 +466,19 @@ \lineii{BLOB}{buffer} \end{tableii} -The type system of the \module{sqlite3} module is extensible in both ways: you can store +The type system of the \module{sqlite3} module is extensible in two ways: you can store additional Python types in a SQLite database via object adaptation, and you can let the \module{sqlite3} module convert SQLite types to different Python types via converters. \subsubsection{Using adapters to store additional Python types in SQLite databases} -Like described before, SQLite supports only a limited set of types natively. To +As described before, SQLite supports only a limited set of types natively. To use other Python types with SQLite, you must \strong{adapt} them to one of the sqlite3 -module's supported types for SQLite. So, one of NoneType, int, long, float, +module's supported types for SQLite: one of NoneType, int, long, float, str, unicode, buffer. -The \module{sqlite3} module uses the Python object adaptation, like described in PEP 246 -for this. The protocol to use is \class{PrepareProtocol}. +The \module{sqlite3} module uses Python object adaptation, as described in \pep{246} for this. The protocol to use is \class{PrepareProtocol}. There are two ways to enable the \module{sqlite3} module to adapt a custom Python type to one of the supported ones. @@ -493,8 +494,8 @@ self.x, self.y = x, y \end{verbatim} -Now you want to store the point in a single SQLite column. You'll have to -choose one of the supported types first that you use to represent the point in. +Now you want to store the point in a single SQLite column. First you'll have to +choose one of the supported types first to be used for representing the point. Let's just use str and separate the coordinates using a semicolon. Then you need to give your class a method \code{__conform__(self, protocol)} which must return the converted value. The parameter \var{protocol} will be @@ -507,13 +508,13 @@ The other possibility is to create a function that converts the type to the string representation and register the function with \method{register_adapter}. - \verbatiminput{sqlite3/adapter_point_2.py} - \begin{notice} The type/class to adapt must be a new-style class, i. e. it must have \class{object} as one of its bases. \end{notice} + \verbatiminput{sqlite3/adapter_point_2.py} + The \module{sqlite3} module has two default adapters for Python's built-in \class{datetime.date} and \class{datetime.datetime} types. Now let's suppose we want to store \class{datetime.datetime} objects not in ISO representation, @@ -523,16 +524,17 @@ \subsubsection{Converting SQLite values to custom Python types} -Now that's all nice and dandy that you can send custom Python types to SQLite. +Writing an adapter lets you send custom Python types to SQLite. But to make it really useful we need to make the Python to SQLite to Python -roundtrip work. +roundtrip work. Enter converters. -Let's go back to the Point class. We stored the x and y coordinates separated -via semicolons as strings in SQLite. +Let's go back to the \class{Point} class. We stored the x and y +coordinates separated via semicolons as strings in SQLite. -Let's first define a converter function that accepts the string as a parameter and constructs a Point object from it. +First, we'll define a converter function that accepts the string as a +parameter and constructs a \class{Point} object from it. \begin{notice} Converter functions \strong{always} get called with a string, no matter @@ -558,11 +560,12 @@ \item Explicitly via the column name \end{itemize} -Both ways are described at \ref{sqlite3-Module-Contents} in the text explaining -the constants \constant{PARSE_DECLTYPES} and \constant{PARSE_COlNAMES}. +Both ways are described in ``Module Constants'', section~\ref{sqlite3-Module-Contents}, in +the entries for the constants \constant{PARSE_DECLTYPES} and +\constant{PARSE_COLNAMES}. -The following example illustrates both ways. +The following example illustrates both approaches. \verbatiminput{sqlite3/converter_point.py} @@ -571,8 +574,8 @@ There are default adapters for the date and datetime types in the datetime module. They will be sent as ISO dates/ISO timestamps to SQLite. -The default converters are registered under the name "date" for datetime.date -and under the name "timestamp" for datetime.datetime. +The default converters are registered under the name "date" for \class{datetime.date} +and under the name "timestamp" for \class{datetime.datetime}. This way, you can use date/timestamps from Python without any additional fiddling in most cases. The format of the adapters is also compatible with the @@ -584,12 +587,12 @@ \subsection{Controlling Transactions \label{sqlite3-Controlling-Transactions}} -By default, the \module{sqlite3} module opens transactions implicitly before a DML -statement (INSERT/UPDATE/DELETE/REPLACE), and commits transactions implicitly -before a non-DML, non-DQL statement (i. e. anything other than +By default, the \module{sqlite3} module opens transactions implicitly before a Data Modification Language (DML) +statement (i.e. INSERT/UPDATE/DELETE/REPLACE), and commits transactions implicitly +before a non-DML, non-query statement (i. e. anything other than SELECT/INSERT/UPDATE/DELETE/REPLACE). -So if you are within a transaction, and issue a command like \code{CREATE TABLE +So if you are within a transaction and issue a command like \code{CREATE TABLE ...}, \code{VACUUM}, \code{PRAGMA}, the \module{sqlite3} module will commit implicitly before executing that command. There are two reasons for doing that. The first is that some of these commands don't work within transactions. The other reason @@ -618,17 +621,17 @@ Using the nonstandard \method{execute}, \method{executemany} and \method{executescript} methods of the \class{Connection} object, your code can -be written more concisely, because you don't have to create the - often -superfluous \class{Cursor} objects explicitly. Instead, the \class{Cursor} +be written more concisely because you don't have to create the (often +superfluous) \class{Cursor} objects explicitly. Instead, the \class{Cursor} objects are created implicitly and these shortcut methods return the cursor -objects. This way, you can for example execute a SELECT statement and iterate +objects. This way, you can execute a SELECT statement and iterate over it directly using only a single call on the \class{Connection} object. \verbatiminput{sqlite3/shortcut_methods.py} \subsubsection{Accessing columns by name instead of by index} -One cool feature of the \module{sqlite3} module is the builtin \class{sqlite3.Row} class +One useful feature of the \module{sqlite3} module is the builtin \class{sqlite3.Row} class designed to be used as a row factory. Rows wrapped with this class can be accessed both by index (like tuples) and Modified: stackless/branches/release25-maint/Doc/lib/libuuid.tex ============================================================================== --- stackless/branches/release25-maint/Doc/lib/libuuid.tex (original) +++ stackless/branches/release25-maint/Doc/lib/libuuid.tex Wed Sep 20 22:30:30 2006 @@ -95,10 +95,10 @@ \begin{memberdesc}{variant} The UUID variant, which determines the internal layout of the UUID. -This will be an integer equal to one of the constants +This will be one of the integer constants \constant{RESERVED_NCS}, \constant{RFC_4122}, \constant{RESERVED_MICROSOFT}, or -\constant{RESERVED_FUTURE}). +\constant{RESERVED_FUTURE}. \end{memberdesc} \begin{memberdesc}{version} @@ -106,7 +106,7 @@ when the variant is \constant{RFC_4122}). \end{memberdesc} -The \module{uuid} module defines the following functions +The \module{uuid} module defines the following functions: \begin{funcdesc}{getnode}{} Get the hardware address as a 48-bit positive integer. The first time this @@ -129,11 +129,8 @@ \index{uuid1} \begin{funcdesc}{uuid3}{namespace, name} -Generate a UUID based upon a MD5 hash of the \var{name} string value -drawn from a specified namespace. \var{namespace} -must be one of \constant{NAMESPACE_DNS}, -\constant{NAMESPACE_URL}, \constant{NAMESPACE_OID}, -or \constant{NAMESPACE_X500}. +Generate a UUID based on the MD5 hash +of a namespace identifier (which is a UUID) and a name (which is a string). \end{funcdesc} \index{uuid3} @@ -143,31 +140,32 @@ \index{uuid4} \begin{funcdesc}{uuid5}{namespace, name} -Generate a UUID based upon a SHA-1 hash of the \var{name} string value -drawn from a specified namespace. \var{namespace} -must be one of \constant{NAMESPACE_DNS}, -\constant{NAMESPACE_URL}, \constant{NAMESPACE_OID}, -or \constant{NAMESPACE_X500}. +Generate a UUID based on the SHA-1 hash +of a namespace identifier (which is a UUID) and a name (which is a string). \end{funcdesc} \index{uuid5} -The \module{uuid} module defines the following namespace constants +The \module{uuid} module defines the following namespace identifiers for use with \function{uuid3()} or \function{uuid5()}. \begin{datadesc}{NAMESPACE_DNS} -Fully-qualified domain name namespace UUID. +When this namespace is specified, +the \var{name} string is a fully-qualified domain name. \end{datadesc} \begin{datadesc}{NAMESPACE_URL} -URL namespace UUID. +When this namespace is specified, +the \var{name} string is a URL. \end{datadesc} \begin{datadesc}{NAMESPACE_OID} -ISO OID namespace UUID. +When this namespace is specified, +the \var{name} string is an ISO OID. \end{datadesc} \begin{datadesc}{NAMESPACE_X500} -X.500 DN namespace UUID. +When this namespace is specified, +the \var{name} string is an X.500 DN in DER or a text output format. \end{datadesc} The \module{uuid} module defines the following constants @@ -178,11 +176,11 @@ \end{datadesc} \begin{datadesc}{RFC_4122} -Uses UUID layout specified in \rfc{4122}. +Specifies the UUID layout given in \rfc{4122}. \end{datadesc} \begin{datadesc}{RESERVED_MICROSOFT} -Reserved for Microsoft backward compatibility. +Reserved for Microsoft compatibility. \end{datadesc} \begin{datadesc}{RESERVED_FUTURE} @@ -192,12 +190,13 @@ \begin{seealso} \seerfc{4122}{A Universally Unique IDentifier (UUID) URN Namespace}{ - This specifies a Uniform Resource Name namespace for UUIDs.} +This specification defines a Uniform Resource Name namespace for UUIDs, +the internal format of UUIDs, and methods of generating UUIDs.} \end{seealso} \subsection{Example \label{uuid-example}} -Here is a typical usage: +Here are some examples of typical usage of the \module{uuid} module: \begin{verbatim} >>> import uuid Modified: stackless/branches/release25-maint/Include/patchlevel.h ============================================================================== --- stackless/branches/release25-maint/Include/patchlevel.h (original) +++ stackless/branches/release25-maint/Include/patchlevel.h Wed Sep 20 22:30:30 2006 @@ -22,11 +22,11 @@ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.5c2" +#define PY_VERSION "2.5" /* Subversion Revision number of this file (not of the repository) */ #define PY_PATCHLEVEL_REVISION "$Revision$" Modified: stackless/branches/release25-maint/Lib/idlelib/NEWS.txt ============================================================================== --- stackless/branches/release25-maint/Lib/idlelib/NEWS.txt (original) +++ stackless/branches/release25-maint/Lib/idlelib/NEWS.txt Wed Sep 20 22:30:30 2006 @@ -1,3 +1,8 @@ +What's New in IDLE 1.2? +======================= + +*Release date: 19-SEP-2006* + What's New in IDLE 1.2c2? ========================= Modified: stackless/branches/release25-maint/Lib/idlelib/idlever.py ============================================================================== --- stackless/branches/release25-maint/Lib/idlelib/idlever.py (original) +++ stackless/branches/release25-maint/Lib/idlelib/idlever.py Wed Sep 20 22:30:30 2006 @@ -1 +1 @@ -IDLE_VERSION = "1.2c2" +IDLE_VERSION = "1.2" Modified: stackless/branches/release25-maint/Mac/BuildScript/build-installer.py ============================================================================== --- stackless/branches/release25-maint/Mac/BuildScript/build-installer.py (original) +++ stackless/branches/release25-maint/Mac/BuildScript/build-installer.py Wed Sep 20 22:30:30 2006 @@ -945,6 +945,10 @@ ref, isDirectory = Carbon.File.FSPathMakeRef(filePath) if isDirectory: + # There is a problem with getting this into the pax(1) archive, + # just ignore directory icons for now. + return + tmpPath = os.path.join(filePath, "Icon\r") if not os.path.exists(tmpPath): fp = open(tmpPath, 'w') Modified: stackless/branches/release25-maint/Mac/Tools/fixapplepython23.py ============================================================================== --- stackless/branches/release25-maint/Mac/Tools/fixapplepython23.py (original) +++ stackless/branches/release25-maint/Mac/Tools/fixapplepython23.py Wed Sep 20 22:30:30 2006 @@ -123,7 +123,8 @@ makescript(GXX_SCRIPT, "g++") # Finally fix the makefile rv = fix(MAKEFILE, do_apply) - sys.exit(rv) + #sys.exit(rv) + sys.exit(0) if __name__ == '__main__': main() Modified: stackless/branches/release25-maint/Misc/NEWS ============================================================================== --- stackless/branches/release25-maint/Misc/NEWS (original) +++ stackless/branches/release25-maint/Misc/NEWS Wed Sep 20 22:30:30 2006 @@ -4,6 +4,13 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 2.5 (final) +================================ + +*Release date: 19-SEP-2006* + +No changes since release candidate 2. + What's New in Python 2.5 release candidate 2? ============================================= Modified: stackless/branches/release25-maint/Misc/RPM/python-2.5.spec ============================================================================== --- stackless/branches/release25-maint/Misc/RPM/python-2.5.spec (original) +++ stackless/branches/release25-maint/Misc/RPM/python-2.5.spec Wed Sep 20 22:30:30 2006 @@ -33,7 +33,7 @@ ################################# %define name python -%define version 2.5c2 +%define version 2.5 %define libvers 2.5 %define release 1pydotorg %define __prefix /usr Modified: stackless/branches/release25-maint/README ============================================================================== --- stackless/branches/release25-maint/README (original) +++ stackless/branches/release25-maint/README Wed Sep 20 22:30:30 2006 @@ -1,5 +1,5 @@ -This is Python version 2.5 rc 2 -=============================== +This is Python version 2.5 +========================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation. All rights reserved. @@ -276,6 +276,19 @@ submit a documentation bug report to SourceForge (see Bug Reports above) so we can remove them!) +GCC 4.1, +GCC 4.2: There is a known incompatibility between Python and GCC, + where GCC 4.1 and later uses an interpretation of C + different to earlier GCC releases in an area where the C + specification has undefined behaviour (namely, integer arithmetic + involving -sys.maxint-1). + + As a consequence, compiling Python with GCC 4.1/4.2 is not + recommended. It is likely that this problem will be resolved + in future Python releases. As a work-around, it seems that + adding -fwrapv to the compiler options restores the earlier + GCC behaviour. + Unix platforms: If your vendor still ships (and you still use) Berkeley DB 1.85 you will need to edit Modules/Setup to build the bsddb185 module and add a line to sitecustomize.py which makes it the @@ -593,7 +606,7 @@ You may also want to try the configure option "--enable-universalsdk" which builds Python as a universal binary with support for the - i386 and PPC architetures. This requires Xcode 2.1 or later to build. + i386 and PPC architectures. This requires Xcode 2.1 or later to build. See Mac/OSX/README for more information on framework and universal builds. Modified: stackless/branches/release25-maint/Tools/msi/msi.py ============================================================================== --- stackless/branches/release25-maint/Tools/msi/msi.py (original) +++ stackless/branches/release25-maint/Tools/msi/msi.py Wed Sep 20 22:30:30 2006 @@ -921,6 +921,7 @@ lib.add_file("185test.db") lib.add_file("audiotest.au") lib.add_file("cfgparser.1") + lib.add_file("sgml_input.html") lib.add_file("test.xml") lib.add_file("test.xml.out") lib.add_file("testtar.tar") _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Fri Sep 29 16:16:02 2006 From: python-checkins at python.org (richard.tew) Date: Fri, 29 Sep 2006 16:16:02 +0200 (CEST) Subject: [Stackless-checkins] r52039 - in stackless/branches/release25-maint: Mac/BuildScript/build-installer.py Mac/BuildScript/resources/ReadMe.txt Mac/BuildScript/resources/Welcome.rtf Stackless/platf/switch_ppc_macosx.h Stackless/platf/switch_x86_unix.h configure configure.in Message-ID: <20060929141602.C6A801E4008@bag.python.org> Author: richard.tew Date: Fri Sep 29 16:16:01 2006 New Revision: 52039 Modified: stackless/branches/release25-maint/Mac/BuildScript/build-installer.py stackless/branches/release25-maint/Mac/BuildScript/resources/ReadMe.txt stackless/branches/release25-maint/Mac/BuildScript/resources/Welcome.rtf stackless/branches/release25-maint/Stackless/platf/switch_ppc_macosx.h stackless/branches/release25-maint/Stackless/platf/switch_x86_unix.h stackless/branches/release25-maint/configure stackless/branches/release25-maint/configure.in Log: Patch from Jeff Senn. Provides more flexible support for MacOS X, where different versions of GCC may or may not cause the frame pointer to be used (and need to be preserved by the Stackless stack switching routines). Modified: stackless/branches/release25-maint/Mac/BuildScript/build-installer.py ============================================================================== --- stackless/branches/release25-maint/Mac/BuildScript/build-installer.py (original) +++ stackless/branches/release25-maint/Mac/BuildScript/build-installer.py Fri Sep 29 16:16:01 2006 @@ -628,7 +628,7 @@ version = getVersion() print "Running configure..." - runCommand("%s -C --enable-framework --enable-universalsdk=%s LDFLAGS='-g -L%s/libraries/usr/local/lib' OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( + runCommand("%s -C --enable-framework --enable-stacklessfewerregisters --enable-universalsdk=%s LDFLAGS='-g -L%s/libraries/usr/local/lib' OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%( shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH), shellQuote(WORKDIR)[1:-1], shellQuote(WORKDIR)[1:-1])) @@ -877,7 +877,7 @@ makeMpkgPlist(os.path.join(pkgroot, 'Info.plist')) pl = Plist( - IFPkgDescriptionTitle="Universal MacPython", + IFPkgDescriptionTitle="Universal Stackless MacPython", IFPkgDescriptionVersion=getVersion(), ) @@ -911,13 +911,13 @@ shutil.rmtree(outdir) imagepath = os.path.join(outdir, - 'python-%s-macosx'%(getFullVersion(),)) + 'stackless-%s-macosx'%(getFullVersion(),)) if INCLUDE_TIMESTAMP: imagepath = imagepath + '%04d-%02d-%02d'%(time.localtime()[:3]) imagepath = imagepath + '.dmg' os.mkdir(outdir) - runCommand("hdiutil create -volname 'Univeral MacPython %s' -srcfolder %s %s"%( + runCommand("hdiutil create -volname 'Universal Stackless MacPython %s' -srcfolder %s %s"%( getFullVersion(), shellQuote(os.path.join(WORKDIR, 'installer')), shellQuote(imagepath))) Modified: stackless/branches/release25-maint/Mac/BuildScript/resources/ReadMe.txt ============================================================================== --- stackless/branches/release25-maint/Mac/BuildScript/resources/ReadMe.txt (original) +++ stackless/branches/release25-maint/Mac/BuildScript/resources/ReadMe.txt Fri Sep 29 16:16:01 2006 @@ -1,3 +1,12 @@ +This is the Stackless (http://www.stackless.com/) +version of Python. It will replace the non-stackless +Python of the same version. Other than additional +features it should be compatible with normal Python. + +Everything below this point is from the original +Python ReadMe.txt +---------------------------- + This package will install MacPython $FULL_VERSION for Mac OS X $MACOSX_DEPLOYMENT_TARGET for the following architecture(s): $ARCHITECTURES. Modified: stackless/branches/release25-maint/Mac/BuildScript/resources/Welcome.rtf ============================================================================== --- stackless/branches/release25-maint/Mac/BuildScript/resources/Welcome.rtf (original) +++ stackless/branches/release25-maint/Mac/BuildScript/resources/Welcome.rtf Fri Sep 29 16:16:01 2006 @@ -4,7 +4,7 @@ \paperw11900\paperh16840\margl1440\margr1440\vieww9920\viewh10660\viewkind0 \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural -\f0\fs24 \cf0 This package will install +\f0\fs24 \cf0 This package will install the "Stackless" variant of \f1\b MacPython $FULL_VERSION \f0\b0 for \f1\b Mac OS X $MACOSX_DEPLOYMENT_TARGET @@ -15,4 +15,4 @@ See the ReadMe file for more information.\ \ \ -This package will by default update your shell profile to ensure that this version of Python is on the search path of your shell. Please deselect the "Shell profile updater" package on the package customization screen if you want to avoid this modification. } \ No newline at end of file +This package will by default update your shell profile to ensure that this version of Python is on the search path of your shell. Please deselect the "Shell profile updater" package on the package customization screen if you want to avoid this modification. } Modified: stackless/branches/release25-maint/Stackless/platf/switch_ppc_macosx.h ============================================================================== --- stackless/branches/release25-maint/Stackless/platf/switch_ppc_macosx.h (original) +++ stackless/branches/release25-maint/Stackless/platf/switch_ppc_macosx.h Fri Sep 29 16:16:01 2006 @@ -32,9 +32,15 @@ #define STACK_MAGIC 3 +#if STACKLESS_FRHACK #define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \ "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \ "cr2", "cr3", "cr4" +#else +#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \ + "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r31", \ + "cr2", "cr3", "cr4" +#endif static int slp_switch(void) Modified: stackless/branches/release25-maint/Stackless/platf/switch_x86_unix.h ============================================================================== --- stackless/branches/release25-maint/Stackless/platf/switch_x86_unix.h (original) +++ stackless/branches/release25-maint/Stackless/platf/switch_x86_unix.h Fri Sep 29 16:16:01 2006 @@ -31,10 +31,14 @@ slp_switch(void) { register int *stackref, stsizediff; +#if STACKLESS_FRHACK + __asm__ volatile ("" : : : "esi", "edi"); +#else __asm__ volatile ("" : : : "ebx", "esi", "edi"); +#endif __asm__ ("movl %%esp, %0" : "=g" (stackref)); { - SLP_SAVE_STATE(stackref, stsizediff); + SLP_SAVE_STATE(stackref, stsizediff); __asm__ volatile ( "addl %0, %%esp\n" "addl %0, %%ebp\n" @@ -44,9 +48,14 @@ SLP_RESTORE_STATE(); return 0; } +#if STACKLESS_FRHACK + __asm__ volatile ("" : : : "esi", "edi"); +#else __asm__ volatile ("" : : : "ebx", "esi", "edi"); +#endif } + #endif /* Modified: stackless/branches/release25-maint/configure ============================================================================== --- stackless/branches/release25-maint/configure (original) +++ stackless/branches/release25-maint/configure Fri Sep 29 16:16:01 2006 @@ -312,7 +312,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS VERSION SOVERSION CONFIG_ARGS UNIVERSALSDK PYTHONFRAMEWORK PYTHONFRAMEWORKDIR PYTHONFRAMEWORKPREFIX PYTHONFRAMEWORKINSTALLDIR FRAMEWORKINSTALLFIRST FRAMEWORKINSTALLLAST FRAMEWORKALTINSTALLFIRST FRAMEWORKALTINSTALLLAST FRAMEWORKUNIXTOOLSPREFIX MACHDEP SGI_ABI EXTRAPLATDIR EXTRAMACHDEPPATH CONFIGURE_MACOSX_DEPLOYMENT_TARGET EXPORT_MACOSX_DEPLOYMENT_TARGET CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX MAINCC CPP EGREP BUILDEXEEXT LIBRARY LDLIBRARY DLLLIBRARY BLDLIBRARY LDLIBRARYDIR INSTSONAME RUNSHARED LINKCC RANLIB ac_ct_RANLIB AR SVNVERSION INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN OPT BASECFLAGS OTHER_LIBTOOL_OPT LIBTOOL_CR! UFT SO LDSHARED BLDSHARED CCSHARED LINKFORSHARED CFLAGSFORSHARED SHLIBS USE_SIGNAL_MODULE SIGNAL_OBJS USE_THREAD_MODULE LDLAST THREADOBJ DLINCLDIR DYNLOADFILE MACHDEP_OBJS TRUE LIBOBJS HAVE_GETHOSTBYNAME_R_6_ARG HAVE_GETHOSTBYNAME_R_5_ARG HAVE_GETHOSTBYNAME_R_3_ARG HAVE_GETHOSTBYNAME_R HAVE_GETHOSTBYNAME LIBM LIBC UNICODE_OBJS THREADHEADERS SRCDIRS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS VERSION SOVERSION CONFIG_ARGS UNIVERSALSDK STACKLESS_FRHACK PYTHONFRAMEWORK PYTHONFRAMEWORKDIR PYTHONFRAMEWORKPREFIX PYTHONFRAMEWORKINSTALLDIR FRAMEWORKINSTALLFIRST FRAMEWORKINSTALLLAST FRAMEWORKALTINSTALLFIRST FRAMEWORKALTINSTALLLAST FRAMEWORKUNIXTOOLSPREFIX MACHDEP SGI_ABI EXTRAPLATDIR EXTRAMACHDEPPATH CONFIGURE_MACOSX_DEPLOYMENT_TARGET EXPORT_MACOSX_DEPLOYMENT_TARGET CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX MAINCC CPP EGREP BUILDEXEEXT LIBRARY LDLIBRARY DLLLIBRARY BLDLIBRARY LDLIBRARYDIR INSTSONAME RUNSHARED LINKCC RANLIB ac_ct_RANLIB AR SVNVERSION INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN OPT BASECFLAGS OTHER_LIBTO! OL_OPT LIBTOOL_CRUFT SO LDSHARED BLDSHARED CCSHARED LINKFORSHARED CFLAGSFORSHARED SHLIBS USE_SIGNAL_MODULE SIGNAL_OBJS USE_THREAD_MODULE LDLAST THREADOBJ DLINCLDIR DYNLOADFILE MACHDEP_OBJS TRUE LIBOBJS HAVE_GETHOSTBYNAME_R_6_ARG HAVE_GETHOSTBYNAME_R_5_ARG HAVE_GETHOSTBYNAME_R_3_ARG HAVE_GETHOSTBYNAME_R HAVE_GETHOSTBYNAME LIBM LIBC UNICODE_OBJS THREADHEADERS SRCDIRS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -847,6 +847,8 @@ --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-universalsdk[SDKDIR] Build agains Mac OS X 10.4u SDK (ppc/i386) + --enable-stacklessfewerregisters + save fewer registers building c-stack switching --enable-framework[=INSTALLDIR] Build (MacOSX|Darwin) framework --enable-shared disable/enable building shared python library @@ -1428,6 +1430,13 @@ fi; +# Check whether --enable-stacklessfewerregisters or --disable-stacklessfewerregisters was given. +if test "${enable_stacklessfewerregisters+set}" = set; then + enableval="$enable_stacklessfewerregisters" + STACKLESS_FRHACK=1 +else + STACKLESS_FRHACK=0 +fi; # Check whether --enable-framework or --disable-framework was given. if test "${enable_framework+set}" = set; then @@ -3888,6 +3897,7 @@ then BASECFLAGS="$BASECFLAGS -fno-strict-aliasing" fi + BASECFLAGS="$BASECFLAGS -DSTACKLESS_FRHACK=${STACKLESS_FRHACK}" case $ac_sys_system in SCO_SV*) BASECFLAGS="$BASECFLAGS -m486 -DSCO5" @@ -22743,6 +22753,7 @@ s, at SOVERSION@,$SOVERSION,;t t s, at CONFIG_ARGS@,$CONFIG_ARGS,;t t s, at UNIVERSALSDK@,$UNIVERSALSDK,;t t +s, at STACKLESS_FRHACK@,$STACKLESS_FRHACK,;t t s, at PYTHONFRAMEWORK@,$PYTHONFRAMEWORK,;t t s, at PYTHONFRAMEWORKDIR@,$PYTHONFRAMEWORKDIR,;t t s, at PYTHONFRAMEWORKPREFIX@,$PYTHONFRAMEWORKPREFIX,;t t Modified: stackless/branches/release25-maint/configure.in ============================================================================== --- stackless/branches/release25-maint/configure.in (original) +++ stackless/branches/release25-maint/configure.in Fri Sep 29 16:16:01 2006 @@ -83,6 +83,11 @@ ]) AC_SUBST(UNIVERSALSDK) +AC_ARG_ENABLE(stacklessfewerregisters, + AC_HELP_STRING(--enable-stacklessfewerregisters, save fewer registers building c-stack switching), +[STACKLESS_FRHACK=1],[ STACKLESS_FRHACK=0 ]) +AC_SUBST(STACKLESS_FRHACK) + dnl quadrigraphs "@<:@" and "@:>@" produce "[" and "]" in the output AC_ARG_ENABLE(framework, AC_HELP_STRING(--enable-framework@<:@=INSTALLDIR@:>@, Build (MacOSX|Darwin) framework), @@ -814,6 +819,7 @@ then BASECFLAGS="$BASECFLAGS -fno-strict-aliasing" fi + BASECFLAGS="${BASECFLAGS} -DSTACKLESS_FRHACK=${STACKLESS_FRHACK}" case $ac_sys_system in SCO_SV*) BASECFLAGS="$BASECFLAGS -m486 -DSCO5" _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Thu Sep 28 14:46:49 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 28 Sep 2006 14:46:49 +0200 (CEST) Subject: [Stackless-checkins] r52025 - stackless/branches/release25-maint/Stackless/module/channelobject.c Message-ID: <20060928124649.E7B1E1E4006@bag.python.org> Author: richard.tew Date: Thu Sep 28 14:46:49 2006 New Revision: 52025 Modified: stackless/branches/release25-maint/Stackless/module/channelobject.c Log: Patch from Jeff Senn. Correct a doc string and remove an unused variable in the channel object code. Modified: stackless/branches/release25-maint/Stackless/module/channelobject.c ============================================================================== --- stackless/branches/release25-maint/Stackless/module/channelobject.c (original) +++ stackless/branches/release25-maint/Stackless/module/channelobject.c Thu Sep 28 14:46:49 2006 @@ -693,7 +693,7 @@ */ static char channel_send_sequence__doc__[] = -"channel.send_sequence(seq) -- sed a stream of values\n\ +"channel.send_sequence(seq) -- send a stream of values\n\ over the channel. Combined with a generator, this is\n\ a very efficient way to build fast pipes."; @@ -825,7 +825,7 @@ { STACKLESS_GETARG(); PyThreadState *ts = PyThreadState_GET(); - PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type; + /*unused: PyChannel_HeapType *t = (PyChannel_HeapType *) self->ob_type;*/ PyObject *it; PyCFrameObject *f; @@ -981,7 +981,7 @@ {"__setstate__", (PCF)channel_setstate, METH_O, channel_setstate__doc__}, {"send_sequence", (PCF)channel_send_sequence, METH_OS, - channel_send__doc__}, + channel_send_sequence__doc__}, {NULL, NULL} /* sentinel */ }; _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Wed Sep 13 14:42:05 2006 From: python-checkins at python.org (richard.tew) Date: Wed, 13 Sep 2006 14:42:05 +0200 (CEST) Subject: [Stackless-checkins] r51871 - stackless/Python-2.4.3/dev/Stackless/module/taskletobject.c Message-ID: <20060913124205.CD8791E400D@bag.python.org> Author: richard.tew Date: Wed Sep 13 14:42:05 2006 New Revision: 51871 Modified: stackless/Python-2.4.3/dev/Stackless/module/taskletobject.c Log: Ported from release-maint25 (r51810): The recent bug fix to the killing of tasklets when the interpreter exited, still left in an assertion that would be hit under certain circumstances. While the assertion might be a useful sign something is going wrong, unfortunately there is no way to detect if it is running when the interpreter shuts down, and to only trigger it if that is no the case. Modified: stackless/Python-2.4.3/dev/Stackless/module/taskletobject.c ============================================================================== --- stackless/Python-2.4.3/dev/Stackless/module/taskletobject.c (original) +++ stackless/Python-2.4.3/dev/Stackless/module/taskletobject.c Wed Sep 13 14:42:05 2006 @@ -79,8 +79,12 @@ PyTaskletObject *self = (PyTaskletObject *) ob; int is_mine = ts == self->cstate->tstate; - /* this could happen if we have a refcount bug, so catch it here. */ + /* this could happen if we have a refcount bug, so catch it here. assert(self != ts->st.current); + It also gets triggered on interpreter exit when we kill the tasks + with stacks (PyStackless_kill_tasks_with_stacks) and there is no + way to differentiate that case.. so it just gets commented out. + */ self->flags.is_zombie = 1; while (self->f.frame != NULL) { @@ -103,6 +107,7 @@ Py_XDECREF(_hold); \ } + /* if (slp_get_frame(t) != NULL) */ if (t->f.frame != NULL) kill_finally((PyObject *) t); TASKLET_SETVAL(t, Py_None); /* always non-zero */ _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Thu Sep 7 14:32:39 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 7 Sep 2006 14:32:39 +0200 (CEST) Subject: [Stackless-checkins] r51810 - stackless/branches/release25-maint/Stackless/core/stacklesseval.c Message-ID: <20060907123239.2DBE51E4003@bag.python.org> Author: richard.tew Date: Thu Sep 7 14:32:13 2006 New Revision: 51810 Modified: stackless/branches/release25-maint/Stackless/core/stacklesseval.c Log: Ported from trunk r51808. Fix for threading/interpreter exit/tasklet killing bug. The test case was to have 10 threads launched with a time.sleep(0.1) in each. This would cause the tasklet killing to have an access violation when it tried to move the tasklet to be killed before the main tasklet in the scheduling list, but the tasklet being killed was the main tasklet. Now if this is the case, no scheduling ordering changes are made as it is not necessary anyway. Modified: stackless/branches/release25-maint/Stackless/core/stacklesseval.c ============================================================================== --- stackless/branches/release25-maint/Stackless/core/stacklesseval.c (original) +++ stackless/branches/release25-maint/Stackless/core/stacklesseval.c Thu Sep 7 14:32:13 2006 @@ -321,7 +321,7 @@ * killed, they will be implicitly placed before this one, * leaving it to run next. */ - if (!t->flags.blocked) { + if (!t->flags.blocked && t != cs->tstate->st.main) { chain = &t; SLP_CHAIN_REMOVE(PyTaskletObject, chain, task, next, prev) chain = &cs->tstate->st.main; _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Wed Sep 13 14:35:32 2006 From: python-checkins at python.org (richard.tew) Date: Wed, 13 Sep 2006 14:35:32 +0200 (CEST) Subject: [Stackless-checkins] r51869 - stackless/branches/release25-maint/Stackless/module/taskletobject.c Message-ID: <20060913123532.CE92F1E404C@bag.python.org> Author: richard.tew Date: Wed Sep 13 14:35:32 2006 New Revision: 51869 Modified: stackless/branches/release25-maint/Stackless/module/taskletobject.c Log: The recent bug fix to the killing of tasklets when the interpreter exited, still left in an assertion that would be hit under certain circumstances. While the assertion might be a useful sign something is going wrong, unfortunately there is no way to detect if it is running when the interpreter shuts down, and to only trigger it if that is no the case. Modified: stackless/branches/release25-maint/Stackless/module/taskletobject.c ============================================================================== --- stackless/branches/release25-maint/Stackless/module/taskletobject.c (original) +++ stackless/branches/release25-maint/Stackless/module/taskletobject.c Wed Sep 13 14:35:32 2006 @@ -79,8 +79,12 @@ PyTaskletObject *self = (PyTaskletObject *) ob; int is_mine = ts == self->cstate->tstate; - /* this could happen if we have a refcount bug, so catch it here. */ + /* this could happen if we have a refcount bug, so catch it here. assert(self != ts->st.current); + It also gets triggered on interpreter exit when we kill the tasks + with stacks (PyStackless_kill_tasks_with_stacks) and there is no + way to differentiate that case.. so it just gets commented out. + */ self->flags.is_zombie = 1; while (self->f.frame != NULL) { @@ -103,6 +107,7 @@ Py_XDECREF(_hold); \ } + /* if (slp_get_frame(t) != NULL) */ if (t->f.frame != NULL) kill_finally((PyObject *) t); TASKLET_SETVAL(t, Py_None); /* always non-zero */ _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Thu Sep 28 14:47:40 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 28 Sep 2006 14:47:40 +0200 (CEST) Subject: [Stackless-checkins] r52026 - stackless/branches/release25-maint/Stackless/pickling/prickelpit.c Message-ID: <20060928124740.A4A301E4006@bag.python.org> Author: richard.tew Date: Thu Sep 28 14:47:40 2006 New Revision: 52026 Modified: stackless/branches/release25-maint/Stackless/pickling/prickelpit.c Log: Patch from Jeff Senn. Use Py_ssize_t instead of int where applicable in the pickling code. Modified: stackless/branches/release25-maint/Stackless/pickling/prickelpit.c ============================================================================== --- stackless/branches/release25-maint/Stackless/pickling/prickelpit.c (original) +++ stackless/branches/release25-maint/Stackless/pickling/prickelpit.c Thu Sep 28 14:47:40 2006 @@ -1376,8 +1376,8 @@ typedef struct { PyObject_HEAD PyDictObject *di_dict; /* Set to NULL when iterator is exhausted */ - int di_used; - int di_pos; + Py_ssize_t di_used; + Py_ssize_t di_pos; binaryfunc di_select; } dictiterobject; @@ -1393,7 +1393,7 @@ dictiterkey_reduce(dictiterobject *di) { PyObject *tup, *list, *key; - int i; + Py_ssize_t i; list = PyList_New(0); if (list == NULL) @@ -1433,7 +1433,7 @@ dictitervalue_reduce(dictiterobject *di) { PyObject *tup, *list, *value; - int i; + Py_ssize_t i; list = PyList_New(0); if (list == NULL) @@ -1473,7 +1473,7 @@ dictiteritem_reduce(dictiterobject *di) { PyObject *tup, *list, *key, *value, *res; - int i; + Py_ssize_t i; list = PyList_New(0); if (list == NULL) @@ -1579,7 +1579,7 @@ setiter_reduce(setiterobject *it) { PyObject *list, *set, *elem; - int i; + Py_ssize_t i; list = PyList_New(0); if (list == NULL) _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Sun Sep 3 20:46:38 2006 From: python-checkins at python.org (richard.tew) Date: Sun, 3 Sep 2006 20:46:38 +0200 (CEST) Subject: [Stackless-checkins] r51699 - in stackless/Python-2.4.3/dev: Makefile.pre.in Stackless/platf/slp_platformselect.h Stackless/platf/switch_arm32_gcc.h Message-ID: <20060903184638.8AA6B1E4003@bag.python.org> Author: richard.tew Date: Sun Sep 3 20:46:37 2006 New Revision: 51699 Added: stackless/Python-2.4.3/dev/Stackless/platf/switch_arm32_gcc.h Modified: stackless/Python-2.4.3/dev/Makefile.pre.in stackless/Python-2.4.3/dev/Stackless/platf/slp_platformselect.h Log: Added Sylvain Baro's switch patch for arm32 support. Modified: stackless/Python-2.4.3/dev/Makefile.pre.in ============================================================================== --- stackless/Python-2.4.3/dev/Makefile.pre.in (original) +++ stackless/Python-2.4.3/dev/Makefile.pre.in Sun Sep 3 20:46:37 2006 @@ -554,6 +554,7 @@ Stackless/platf/switch_ppc_unix.h \ Stackless/platf/switch_s390_unix.h \ Stackless/platf/switch_sparc_sun_gcc.h \ + Stackless/platf/switch_arm32_gcc.h \ Stackless/platf/switch_x86_msvc.h \ Stackless/platf/switch_x86_unix.h \ pyconfig.h Modified: stackless/Python-2.4.3/dev/Stackless/platf/slp_platformselect.h ============================================================================== --- stackless/Python-2.4.3/dev/Stackless/platf/slp_platformselect.h (original) +++ stackless/Python-2.4.3/dev/Stackless/platf/slp_platformselect.h Sun Sep 3 20:46:37 2006 @@ -22,6 +22,8 @@ #include "switch_s390_unix.h" /* Linux/S390 zSeries (identical) */ #elif defined(__GNUC__) && defined(__arm__) && defined(__thumb__) #include "switch_arm_thumb_gcc.h" /* gcc using arm thumb */ +#elif defined(__GNUC__) && defined(__arm32__) +#include "switch_arm32_gcc.h" /* gcc using arm32 */ #endif /* default definitions if not defined in above files */ Added: stackless/Python-2.4.3/dev/Stackless/platf/switch_arm32_gcc.h ============================================================================== --- (empty file) +++ stackless/Python-2.4.3/dev/Stackless/platf/switch_arm32_gcc.h Sun Sep 3 20:46:37 2006 @@ -0,0 +1,50 @@ +/* + * this is the internal transfer function. + * + * HISTORY + * 14-Aug-06 File creation. Ported from Arm Thumb. Sylvain Baro + * 3-Sep-06 Commented out saving of r1-r3 (r4 already commented out) as I + * read that these do not need to be saved. Also added notes and + * errors related to the frame pointer. Richard Tew. + * + * NOTES + * + * It is not possible to detect if fp is used or not, so the supplied + * switch function needs to support it, so that you can remove it if + * it does not apply to you. + * + * POSSIBLE ERRORS + * + * "fp cannot be used in asm here" + * + * - Try commenting out "fp" in REGS_TO_SAVE. + * + */ + +#define STACK_REFPLUS 1 + +#ifdef SLP_EVAL +#define STACK_MAGIC 0 +#define REGS_TO_SAVE /*"r1", "r2", "r3", "r4",*/ "r5", "r6", "fp", "ip", "lr" + +static int +slp_switch(void) +{ + register int *stackref, stsizediff; + __asm__ volatile ("" : : : REGS_TO_SAVE); + __asm__ ("mov %0,sp" : "=g" (stackref)); + { + SLP_SAVE_STATE(stackref, stsizediff); + __asm__ volatile ( + "add sp,sp,%0\n" + "add fp,fp,%0\n" + : + : "r" (stsizediff) + ); + SLP_RESTORE_STATE(); + return 0; + } + __asm__ volatile ("" : : : REGS_TO_SAVE); +} + +#endif _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Tue Sep 5 21:27:26 2006 From: python-checkins at python.org (richard.tew) Date: Tue, 5 Sep 2006 21:27:26 +0200 (CEST) Subject: [Stackless-checkins] r51752 - stackless/sandbox/libraries/slpmonkeypatch/__init__.py stackless/sandbox/libraries/slpmonkeypatch/socketmodule.py Message-ID: <20060905192726.92A301E4004@bag.python.org> Author: richard.tew Date: Tue Sep 5 21:27:26 2006 New Revision: 51752 Added: stackless/sandbox/libraries/slpmonkeypatch/__init__.py (contents, props changed) stackless/sandbox/libraries/slpmonkeypatch/socketmodule.py (contents, props changed) Log: The initial version of the slpmonkeypatch module. Should suffice to replace the 'socket' module with the stackless compatible version. Added: stackless/sandbox/libraries/slpmonkeypatch/__init__.py ============================================================================== --- (empty file) +++ stackless/sandbox/libraries/slpmonkeypatch/__init__.py Tue Sep 5 21:27:26 2006 @@ -0,0 +1,45 @@ +import os +import sys +import stackless +import threading +import socket as stdsocket + +_config = stackless._config = threading.local() + +def register_thread_for_stackless(): + _config.using_stackless = True + _config.emulation_timeout = 0.1 + +def monkeypatch(): + # Go through some shenanigans to get the path to the 'examples' + # directory in the SVN 'sandbox' directory structure. + filePath = os.path.join(os.getcwd(), __file__) + dirPath = os.path.split(filePath)[0] + dirPath = os.path.join(dirPath, os.path.pardir) + dirPath = os.path.join(dirPath, os.path.pardir) + dirPath = os.path.normpath(dirPath) + dirPath = os.path.join(dirPath, "examples") + + # Add the 'examples' directory to the import path. + if dirPath not in sys.path: + sys.path.append(dirPath) + + # Install the import reference to the normal python socket module. + import socket + sys.modules["stdsocket"] = __import__(socket.__name__) + del socket + + # Obtain the asyncore-based socket module and put its 'socket' in place. + import stacklesssocket + stackless.socket = stacklesssocket.socket + del stacklesssocket + + import socketmodule + sys.modules["socket"] = socketmodule + + stackless.register_thread = register_thread_for_stackless + + # This thread is the only automatically registered one. + stackless.register_thread() + + Added: stackless/sandbox/libraries/slpmonkeypatch/socketmodule.py ============================================================================== --- (empty file) +++ stackless/sandbox/libraries/slpmonkeypatch/socketmodule.py Tue Sep 5 21:27:26 2006 @@ -0,0 +1,27 @@ +import threading +import stackless + +# We need the "socket" name for the function we export. +import stdsocket + +# If we are to masquerade as the socket module, we need to provide the constants. +for k, v in stdsocket.__dict__.iteritems(): + if k.upper() == k: + globals()[k] = v +error = stdsocket.error +timeout = stdsocket.timeout + +# WARNING: this function blocks and is not thread safe. +# The only solution is to spawn a thread to handle all +# getaddrinfo requests. Implementing a stackless DNS +# lookup service is only second best as getaddrinfo may +# use other methods. +getaddrinfo = stdsocket.getaddrinfo + +_config = stackless._config + +def socket(*args): + if getattr(_config, "using_stackless"): + return stackless.socket(*args) + else: + return stdsocket.socket(*args) _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Thu Sep 7 14:51:00 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 7 Sep 2006 14:51:00 +0200 (CEST) Subject: [Stackless-checkins] r51812 - stackless/binaries-pc/python24.zip stackless/binaries-pc/python24.zip.md5.py stackless/binaries-pc/python25.zip stackless/binaries-pc/python25.zip.md5.py Message-ID: <20060907125100.6441B1E4003@bag.python.org> Author: richard.tew Date: Thu Sep 7 14:50:08 2006 New Revision: 51812 Modified: stackless/binaries-pc/python24.zip stackless/binaries-pc/python24.zip.md5.py stackless/binaries-pc/python25.zip stackless/binaries-pc/python25.zip.md5.py Log: Uploaded new binaries with the fix from trunk r51808, for the bug discovered by Eggert J?n Magn?sson. Modified: stackless/binaries-pc/python24.zip ============================================================================== Binary files. No diff available. Modified: stackless/binaries-pc/python24.zip.md5.py ============================================================================== --- stackless/binaries-pc/python24.zip.md5.py (original) +++ stackless/binaries-pc/python24.zip.md5.py Thu Sep 7 14:50:08 2006 @@ -1,6 +1,6 @@ import md5 -expected = "90c50615f5aa023a3d50d92eb59f3bb3" +expected = "cfd532669a2edd16a3aa81f9c2a35995" fname = r"python24.zip" print "expected digest", expected received = md5.md5(file(fname, "rb").read()).hexdigest() Modified: stackless/binaries-pc/python25.zip ============================================================================== Binary files. No diff available. Modified: stackless/binaries-pc/python25.zip.md5.py ============================================================================== --- stackless/binaries-pc/python25.zip.md5.py (original) +++ stackless/binaries-pc/python25.zip.md5.py Thu Sep 7 14:50:08 2006 @@ -1,6 +1,6 @@ import md5 -expected = "759db858571ce0c5064c74a9f0bc5c9d" +expected = "0f524864f15f615c09ff1bc9599d7c0f" fname = r"python25.zip" print "expected digest", expected received = md5.md5(file(fname, "rb").read()).hexdigest() _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Tue Sep 5 19:47:47 2006 From: python-checkins at python.org (richard.tew) Date: Tue, 5 Sep 2006 19:47:47 +0200 (CEST) Subject: [Stackless-checkins] r51749 - in stackless/sandbox/libraries: slpmonkeypatch uthread-asgeir uthread-asgeir/uthread.py uthread-ccp Message-ID: <20060905174747.66E111E401A@bag.python.org> Author: richard.tew Date: Tue Sep 5 19:47:46 2006 New Revision: 51749 Added: stackless/sandbox/libraries/ stackless/sandbox/libraries/slpmonkeypatch/ stackless/sandbox/libraries/uthread-asgeir/ stackless/sandbox/libraries/uthread-asgeir/uthread.py (contents, props changed) stackless/sandbox/libraries/uthread-ccp/ Log: Working towards adding the CCP uthread.py and then starting on a slpmonkeypatch module based on Andrew Dalke's suggestions. Added: stackless/sandbox/libraries/uthread-asgeir/uthread.py ============================================================================== --- (empty file) +++ stackless/sandbox/libraries/uthread-asgeir/uthread.py Tue Sep 5 19:47:46 2006 @@ -0,0 +1,535 @@ +# +# Copyright (c) 2005, Asgeir Bjarni Ingvarsson +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the original author nor the names of other contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# Obtain the latest version from: +# +# http://ares.hlekkir.com/repo/shady-utils/trunk/uthread.py +# + +import stackless +import weakref +import cPickle +import atexit +import sys +import time + +#---------------------------------------------------------------------------- +# A class to support named microthreads +#---------------------------------------------------------------------------- +class NamedTasklet(stackless.tasklet): + __slots__ = ['name'] + + def __init__(self, func, name=None): + stackless.tasklet.__init__(self, func) + + if not name: + name = '%08x' % (id(self)) + self.name = name + + def __new__(self, func, name=None): + return stackless.tasklet.__new__(self, func) + + def __repr__(self): + try: + return '%s' % self.name + except AttributeError: + # I think that this will only happen with the main tasklet + return '%08x' % (id(self)) + +#---------------------------------------------------------------------------- +# A class to manage sleeping tasklets +#---------------------------------------------------------------------------- +_timeKeeperTaskletName = '__internal__TimeKeeper__mainLoop__' + +class TimeKeeper(object): + """Manages sleeping tasklets + + Uses channels to block tasklets that want to sleep. + """ + __slots__ = ['chnPool', 'sleepers'] + + def __init__(self): + self.chnPool = [stackless.channel() for i in range(100)] + self.sleepers = [] + + def getSleeperCount(self): + """Returns the number of sleeping tasklets + """ + return len(self.sleepers) + + def sleep(self, delay=0): + """Suspend the active tasklet for a specified amount of seconds + + If delay is zero (default) then the tasklet just blocks. + Returns seconds passed since sleep was called. + """ + startTime = time.clock() + when = startTime + delay + + if delay: + try: + try: + chn = self.chnPool.pop() + except IndexError: + chn = stackless.channel() + # could also allocate more channels for chnPool + + self.sleepers.append((when, chn)) + chn.receive() + finally: + self.chnPool.append(chn) + else: + stackless.schedule() + + return time.clock() - startTime + + def mainLoop(self): + """Internal function + + Created in a new tasklet by the scheduler + """ + try: + while True: + try: + # assume that the sleeper list is ordered + (when, chn) = self.sleepers.pop(0) + # an empty list will raise IndexError + while when <= time.clock(): + chn.send(None) + (when, chn) = self.sleepers.pop(0) + # an empty list will raise IndexError + + # The only way to reach this point is if the while evaluates as False. + # That means that the current sleeper wants to sleep longer. + self.sleepers.insert(0, (when, chn)) + except IndexError: + # The sleeper list is empty, nothing to do + pass + + stackless.schedule() + except Exception, e: + # Restart TimeKeeper unless it's being killed + if isinstance(e, TaskletExit): + # TimeKeeper is being killed. + # Send a TaskletExit to all sleepers + for (when, chn) in self.sleepers: + chn.send_exception(e) + + self.sleepers = [] + else: + # recreate the timeKeeper tasklet from another tasklet so + # the timeKeeper name may be reused + new(newNamed, self.mainLoop, _timeKeeperTaskletName) + +#---------------------------------------------------------------------------- +# Schedulers to manage tasklets +#---------------------------------------------------------------------------- +class BaseScheduler(object): + """This is the base thread scheduler + + _activeScheduler should not be set to an instance of this class. + Subclasses must override the run and runSingle methods + """ + __slots__ = ['running', 'paused', 'timeKeeper'] + + def __init__(self): + # References to tasklets will be dropped as soon as they + # stop executing + self.running = weakref.WeakValueDictionary() + self.paused = weakref.WeakValueDictionary() + + self.timeKeeper = TimeKeeper() + self.new(self.timeKeeper.mainLoop, _timeKeeperTaskletName) + + def new(self, func, name=None, *args, **kw): + """Create a new tasklet + + If name is already in use, a *random* name will be chosen + """ + if name not in self.listTasks(): + task = NamedTasklet(func, name) + else: + task = NamedTasklet(func) + task(*args, **kw) # tasklet will be lost in dict if this is not done + task.insert() + + currID = repr(task) + self.running[currID] = task + return currID + + def killAll(self): + """Kills all tasklets + """ + for taskID in (self.running.keys() + self.paused.keys()): + try: + self.kill(taskID) + except: + pass + + def kill(self, taskID): + """Stops a running tasklet + """ + task = self.running.pop(taskID, None) + workingDict = self.running + if task is None: + task = self.paused.pop(taskID, None) + workingDict = self.paused + + if task: + try: + task.kill() + return + except: + workingDict[taskID] = task + raise + + def pause(self, taskID): + """Pauses a running tasklet + """ + task = self.running.pop(taskID, None) + if task: + task.remove() + self.paused[taskID] = task + + def resume(self, taskID): + """Resumes a paused tasklet + """ + task = self.paused.pop(taskID, None) + if task: + task.insert() + self.running[taskID] = task + + def run(self): + """Execute all tasklets + """ + pass + + def runSingle(self): + """Execute the schedule list once, then return + """ + pass + + def dumpTask(self, taskID, kill=0): + """Returns a pickled tasklet + """ + task = self.running.get(taskID, None) or self.paused.get(taskID, None) + if task: + data = cPickle.dumps(task, 2) + if kill: + self.kill(repr(task)) + return data + + def loadTask(self, data, paused=1): + """Loads a pickled tasklet + """ + task = cPickle.loads(data) + currID = repr(task) + if paused: + self.paused[currID] = task + else: + self.running[currID] = task + task.insert() + return currID + + def listTasks(self): + """Returns a list of all tasklets + """ + return self.running.keys() + self.paused.keys() + + def getRunCount(self): + """Same as stackless.getruncount but takes sleeping tasklets into account + + Will return 1 when only the main tasklet is left, the timeKeeper tasklet + will not be counted since it is not a client tasklet. + + For consideration: If stackless.getruncount() returns 2 + only the main tasklet and the TimeKeeper tasklets are currently + running. This might then be a good place to sleep for one millisecond + to reduce CPU load + """ + runCount = stackless.getruncount() + self.timeKeeper.getSleeperCount() + return (runCount - 1) # subtract the timeKeeper tasklet + + def sleepTask(self, delay=0): + """Suspend the active tasklet for a specified amount of seconds + + If delay is zero (default) then the tasklet just blocks. + Returns seconds passed since sleep was called. + """ + return self.timeKeeper.sleep(delay) + + def printException(self): + """Uses sys.excepthook to report exceptions + """ + exc_info = sys.exc_info() + sys.excepthook(exc_info[0], exc_info[1], exc_info[2]) + +class PreemptiveScheduler(BaseScheduler): + """This is a preemptive tasklet scheduler + + This scheduler will execute each thread for as little time as possible. + When it interrupts tasklets, it will keep them in the scheduler list. + + THIS IS EXPERIMENTAL AND HAS NOT BEEN TESTED. UTHREAD HAS NOT BEEN + DESIGNED WITH THIS KIND OF USE IN MIND. You may need to modify code + in this module if you plan on using this scheduler. + """ + def __init__(self): + BaseScheduler.__init__(self) + self.maxSlice = 50 + + def run(self): + """Execute all tasklets + """ + while self.getRunCount() > 1: + try: + # Run a single slice, if the currently executing thread is + # still running append it to the scheduler list + victim = stackless.run(self.maxSlice) + if victim: + victim.insert() + except: + self.printException() + + def runSingle(self): + """Execute the schedule list once, then return + """ + try: + # Run a single slice, if the currently executing thread is + # still running append it to the scheduler list + victim = stackless.run(self.maxSlice) + if victim: + victim.insert() + except: + self.printException() + +class DefaultScheduler(BaseScheduler): + """This is the default tasklet scheduler + + This scheduler will execute threads sequentially. + If it needs to interrupt the execution of a tasklet it will remove + that tasklet from the scheduler list + """ + def __init__(self): + BaseScheduler.__init__(self) + + def run(self): + """Execute all tasklets + """ + while self.getRunCount() > 1: + try: + stackless.schedule() + except: + self.printException() + + def runSingle(self): + """Execute the schedule list once, then return + """ + try: + stackless.schedule() + except: + self.printException() + + +#---------------------------------------------------------------------------- +# Functions to interact with the active scheduler +#---------------------------------------------------------------------------- +_activeScheduler = DefaultScheduler() + +def setScheduler(newMgr, killOld=1, copy=0): + """Replace the active tasklet scheduler + + It is not recommended to call this after threads have been started. + If killOld is set to 1 then all threads in the old manager are killed. + If copy is set to 1 then the running and paused dicts are copied into + the new scheduler + """ + assert isinstance(newMgr, BaseScheduler), 'newMgr must inherit from BaseScheduler' + + global _activeScheduler + if killOld: + _activeScheduler.KillAll() + if copy: + newMgr.running = _activeScheduler.running + newMgr.paused = _activeScheduler.paused + _activeScheduler = newMgr + +def getScheduler(): + """Returns the active tasklet scheduler + """ + global _activeScheduler + return _activeScheduler + +def _exitHandler(): + """This function calls killAll on the active scheduler + + This function is called by the atexit module before interpreter shutdown. + This will give all tasklets a chance to shutdown cleanly if they are not + blocked. + """ + _activeScheduler.killAll() + +atexit.register(_exitHandler) + +#---------------------------------------------------------------------------- +# Functions to expose the scheduler to users +#---------------------------------------------------------------------------- +def new(func, *args, **kw): + """Create a new tasklet + """ + return _activeScheduler.new(func, None, *args, **kw) + +def newNamed(func, name, *args, **kw): + """Create a new named tasklet + + If name is already in use, a *random* name will be chosen + """ + return _activeScheduler.new(func, name, *args, **kw) + +def run(): + """Execute all tasklets + """ + _activeScheduler.run() + +def runSingle(): + """Execute the schedule list once, then return + """ + _activeScheduler.runSingle() + +def pause(taskID): + """Pauses a running tasklet + """ + _activeScheduler.pause(taskID) + +def resume(taskID): + """Resumes a paused tasklet + """ + _activeScheduler.resume(taskID) + +def kill(taskID): + """Stops a running tasklet + """ + _activeScheduler.kill(taskID) + +def dumpTask(taskID, kill=0): + """Returns a pickled tasklet + """ + return _activeScheduler.dumpTask(taskID, kill) + +def loadTask(data, paused=1): + """Loads a pickled tasklet + """ + return _activeScheduler.loadTask(data, paused) + +def sleep(delay=0): + """Suspend the active thread for a specified amount of seconds + + If delay is zero (default) then the tasklet just blocks. + Returns seconds passed since sleep was called. + """ + return _activeScheduler.sleepTask(delay) + +def getCurrent(): + """Returns the currently running tasklet + """ + return stackless.getcurrent() + +#---------------------------------------------------------------------------- +# Utility classes +#---------------------------------------------------------------------------- +class Semaphore(object): + """Protects globally accessible resources from context switching + """ + __slots__ = ['count', 'channel'] + + def __init__(self, maxcount=1): + self.count = maxcount + self.channel = stackless.channel() + + def acquire(self): + if self.count == 0: + self.channel.receive() + else: + self.count = self.count - 1 + + def release(self): + if self.channel.queue: + self.channel.send(None) + else: + self.count = self.count + 1 + +class Queue(object): + """A queue is a microthread-safe FIFO. + """ + __slots__ = ['contents', 'channel'] + + def __init__(self): + self.contents = [] + self.channel = stackless.channel() + + def put(self, x): + self.contents.append(x) + self.pump() + + def pump(self): + # Channel balance is <0 when there are tasklets waiting to recieve + while self.channel.queue and self.contents and self.channel.balance < 0: + self.channel.send(self.contents.pop(0)) + + def nonBlockingPut(self, x): + self.contents.append(x) + + def get(self): + if self.contents: + return self.contents.pop(0) + return self.channel.receive() + + def unget(self, x): + self.contents.insert(0, x) + +class Synchronizer(object): + """A traffic light for microthreads + + No synchronized thread can continue execution until all the other + synchronized threads have called sync. + """ + __slots__ = ['maxCount', 'queue', 'count'] + + def __init__(self, count): + self.maxCount = count + self.queue = Queue() + self.count = 0 + + def sync(self): + self.count += 1 + if self.count == self.maxCount: + for i in range(self.maxCount): + self.queue.put(None) + self.count = 0 + return self.queue.get() _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Wed Sep 20 22:51:36 2006 From: python-checkins at python.org (richard.tew) Date: Wed, 20 Sep 2006 22:51:36 +0200 (CEST) Subject: [Stackless-checkins] r51936 - stackless/binaries-pc/python25.zip stackless/binaries-pc/python25.zip.md5.py Message-ID: <20060920205136.BDB901E4006@bag.python.org> Author: richard.tew Date: Wed Sep 20 22:49:20 2006 New Revision: 51936 Modified: stackless/binaries-pc/python25.zip stackless/binaries-pc/python25.zip.md5.py Log: The windows binaries for the final release of Stackless Python 2.5! Modified: stackless/binaries-pc/python25.zip ============================================================================== Binary files. No diff available. Modified: stackless/binaries-pc/python25.zip.md5.py ============================================================================== --- stackless/binaries-pc/python25.zip.md5.py (original) +++ stackless/binaries-pc/python25.zip.md5.py Wed Sep 20 22:49:20 2006 @@ -1,6 +1,6 @@ import md5 -expected = "13e707247a888eeefa0217d599cf95a7" +expected = "cedb4552686d845ac750d3479cb06443" fname = r"python25.zip" print "expected digest", expected received = md5.md5(file(fname, "rb").read()).hexdigest() _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Wed Sep 20 22:32:11 2006 From: python-checkins at python.org (richard.tew) Date: Wed, 20 Sep 2006 22:32:11 +0200 (CEST) Subject: [Stackless-checkins] r51934 - stackless/tags/python-2.5 Message-ID: <20060920203211.B7A8E1E4006@bag.python.org> Author: richard.tew Date: Wed Sep 20 22:32:11 2006 New Revision: 51934 Added: stackless/tags/python-2.5/ - copied from r51933, stackless/branches/release25-maint/ Log: Tagged the merged in version of the 2.5 final release. _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Thu Sep 7 14:27:03 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 7 Sep 2006 14:27:03 +0200 (CEST) Subject: [Stackless-checkins] r51808 - stackless/trunk/Stackless/core/stacklesseval.c Message-ID: <20060907122703.097981E4003@bag.python.org> Author: richard.tew Date: Thu Sep 7 14:27:02 2006 New Revision: 51808 Modified: stackless/trunk/Stackless/core/stacklesseval.c Log: Fix for threading/interpreter exit/tasklet killing bug. The test case was to have 10 threads launched with a time.sleep(0.1) in each. This would cause the tasklet killing to have an access violation when it tried to move the tasklet to be killed before the main tasklet in the scheduling list, but the tasklet being killed was the main tasklet. Now if this is the case, no scheduling ordering changes are made as it is not necessary anyway. Modified: stackless/trunk/Stackless/core/stacklesseval.c ============================================================================== --- stackless/trunk/Stackless/core/stacklesseval.c (original) +++ stackless/trunk/Stackless/core/stacklesseval.c Thu Sep 7 14:27:02 2006 @@ -321,7 +321,7 @@ * killed, they will be implicitly placed before this one, * leaving it to run next. */ - if (!t->flags.blocked) { + if (!t->flags.blocked && t != cs->tstate->st.main) { chain = &t; SLP_CHAIN_REMOVE(PyTaskletObject, chain, task, next, prev) chain = &cs->tstate->st.main; _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Wed Sep 13 14:44:18 2006 From: python-checkins at python.org (richard.tew) Date: Wed, 13 Sep 2006 14:44:18 +0200 (CEST) Subject: [Stackless-checkins] r51872 - stackless/binaries-pc/python25.zip stackless/binaries-pc/python25.zip.md5.py Message-ID: <20060913124418.64FF51E4003@bag.python.org> Author: richard.tew Date: Wed Sep 13 14:43:52 2006 New Revision: 51872 Modified: stackless/binaries-pc/python25.zip stackless/binaries-pc/python25.zip.md5.py Log: Binaries that incorporate the fix from r51810. Modified: stackless/binaries-pc/python25.zip ============================================================================== Binary files. No diff available. Modified: stackless/binaries-pc/python25.zip.md5.py ============================================================================== --- stackless/binaries-pc/python25.zip.md5.py (original) +++ stackless/binaries-pc/python25.zip.md5.py Wed Sep 13 14:43:52 2006 @@ -1,6 +1,6 @@ import md5 -expected = "0f524864f15f615c09ff1bc9599d7c0f" +expected = "9c35771612a1abdf0f957f63d5f69fcd" fname = r"python25.zip" print "expected digest", expected received = md5.md5(file(fname, "rb").read()).hexdigest() _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Tue Sep 5 22:48:45 2006 From: python-checkins at python.org (richard.tew) Date: Tue, 5 Sep 2006 22:48:45 +0200 (CEST) Subject: [Stackless-checkins] r51754 - stackless/sandbox/examples/threadscheduling.py Message-ID: <20060905204845.8C4DF1E4005@bag.python.org> Author: richard.tew Date: Tue Sep 5 22:48:45 2006 New Revision: 51754 Added: stackless/sandbox/examples/threadscheduling.py (contents, props changed) Log: Wrote up an example to demonstrate how Stackless deals with multiple threads. The Python source code changes store the Stackless state on the threadstate, so the expected behaviour was that there would be a distinct and separate scheduler for each thread. So all tasklets launched on a thread are local to that thread and are scheduled together. This example demonstrates that this is the case. Added: stackless/sandbox/examples/threadscheduling.py ============================================================================== --- (empty file) +++ stackless/sandbox/examples/threadscheduling.py Tue Sep 5 22:48:45 2006 @@ -0,0 +1,100 @@ +# +# A demonstration of how each thread has its own scheduler. +# +# Author: Richard Tew +# +# This code was written to serve as an example of Stackless Python usage. +# Feel free to email me with any questions, comments, or suggestions for +# improvement. +# +# FURTHER DETAIL: +# +# This example starts some tasklets on the main thread, and starts a second +# thread as well, starting some tasklets on that. You should be able to +# see that the scheduler on each thread is unrelated to the one on the +# other, which is why I need to start a ManageSleepingTasklets for each of +# them. +# +# POSSIBLE PROBLEMS: +# +# If Stackless complains that "run() must be run from the main thread's +# main tasklet", then you need to get a later version of Stackless. +# This constraint was removed. +# + +import threading +import stackless +import time + +_locals = threading.local() +running = True + +# Altered boilerplate Sleep function. + +def Sleep(secondsToWait): + channel = stackless.channel() + endTime = time.time() + secondsToWait + _locals.sleepingTasklets.append((endTime, channel)) + _locals.sleepingTasklets.sort() + # Block until we get sent an awakening notification. + channel.receive() + +def ManageSleepingTasklets(threadID): + global running + + _locals.sleepingTasklets = [] + while running: + if len(_locals.sleepingTasklets): + endTime = _locals.sleepingTasklets[0][0] + if endTime <= time.time(): + channel = _locals.sleepingTasklets[0][1] + del _locals.sleepingTasklets[0] + # We have to send something, but it doesn't matter what as it is not used. + channel.send(None) + elif stackless.getruncount() == 1: + # Give up if there are no more sleeping tasklets. Otherwise the two + # threads keep on running endlessly. + break + stackless.schedule() + +# ... + +def looping_tasklet(threadID, taskletID): + n = 3 + while n > 0: + n -= 1 + print threadID, "looping_tasklet", taskletID, "loop", n + Sleep(1.0) + print threadID, "looping_tasklet", taskletID, "exit" + + +def a_main_tasklet(): + threadID = 2 + + stackless.tasklet(ManageSleepingTasklets)(threadID) + + stackless.tasklet(looping_tasklet)(threadID, 1) + + print threadID, "runcount.1", stackless.getruncount() + stackless.run() + +if __name__ == "__main__": + global running + + threadID = 1 + + stackless.tasklet(ManageSleepingTasklets)(threadID) + + stackless.tasklet(looping_tasklet)(threadID, 1) + stackless.tasklet(looping_tasklet)(threadID, 2) + + print threadID, "runcount", stackless.getruncount() + + thread = threading.Thread(target=a_main_tasklet) + thread.start() + + try: + stackless.run() + except: + running = False + raise _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Fri Sep 29 14:28:14 2006 From: python-checkins at python.org (richard.tew) Date: Fri, 29 Sep 2006 14:28:14 +0200 (CEST) Subject: [Stackless-checkins] r52034 - stackless/branches/release25-maint/Objects/typeobject.c Message-ID: <20060929122814.095421E4008@bag.python.org> Author: richard.tew Date: Fri Sep 29 14:28:13 2006 New Revision: 52034 Modified: stackless/branches/release25-maint/Objects/typeobject.c Log: Suggested fix from Jeff Senn. This allowed something not normally allowed in CPython, subclassing str and putting slots on it. And crashes would happen when instances were generated. I could not reproduce the crashes on Windows, but removing this special case for Stackless regardless is a good idea. Modified: stackless/branches/release25-maint/Objects/typeobject.c ============================================================================== --- stackless/branches/release25-maint/Objects/typeobject.c (original) +++ stackless/branches/release25-maint/Objects/typeobject.c Fri Sep 29 14:28:13 2006 @@ -1725,12 +1725,7 @@ /* Are slots allowed? */ nslots = PyTuple_GET_SIZE(slots); -#ifdef STACKLESS - if (nslots > 0 && base->tp_itemsize != 0 && !PyType_Check(base)) { - /* for the special case of meta types, allow slots */ -#else if (nslots > 0 && base->tp_itemsize != 0) { -#endif PyErr_Format(PyExc_TypeError, "nonempty __slots__ " "not supported for subtype of '%s'", _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Thu Sep 7 18:13:31 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 7 Sep 2006 18:13:31 +0200 (CEST) Subject: [Stackless-checkins] r51817 - in stackless/sandbox/libraries/slpmonkeypatch: fileobject.py resources/iocp.py Message-ID: <20060907161331.53D301E4003@bag.python.org> Author: richard.tew Date: Thu Sep 7 18:13:25 2006 New Revision: 51817 Added: stackless/sandbox/libraries/slpmonkeypatch/fileobject.py (contents, props changed) Modified: stackless/sandbox/libraries/slpmonkeypatch/resources/iocp.py Log: An initial monkeypatched file object. Still a long way to go. Added: stackless/sandbox/libraries/slpmonkeypatch/fileobject.py ============================================================================== --- (empty file) +++ stackless/sandbox/libraries/slpmonkeypatch/fileobject.py Thu Sep 7 18:13:25 2006 @@ -0,0 +1,23 @@ +import __builtin__ + +stdfile = file + +def stacklessopen(filename, mode='r', bufsize=None): + return StacklessFile(filename, mode, bufsize) + +class StacklessFile(file): + def __init__(self, filename, mode='r', bufsize=None): + # Preserve normal behaviour. + if bufsize is None: + super(file, self).__init__(filename, mode) + else: + super(file, self).__init__(filename, mode, bufsize) + def xread(self): + pass + def xwrite(self): + pass + +def monkeypatch1(): + __builtin__.stdopen = __builtin__.open + __builtin__.open = stacklessopen + __builtin__.file = StacklessFile Modified: stackless/sandbox/libraries/slpmonkeypatch/resources/iocp.py ============================================================================== --- stackless/sandbox/libraries/slpmonkeypatch/resources/iocp.py (original) +++ stackless/sandbox/libraries/slpmonkeypatch/resources/iocp.py Thu Sep 7 18:13:25 2006 @@ -57,7 +57,7 @@ numBytes = c_long() completionKey = c_long() overlapped = c_void_p() - ret = windll.kernel32.GetQueuedCompletionStatus(port, byref(numBytes), byref(completionKey), byref(overlapped), timeout) + ret = windll.kernel32.GetQueuedCompletionStatus(self.port, byref(numBytes), byref(completionKey), byref(overlapped), timeout) timeout = 0 if overlapped.value is None: _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Sat Sep 2 16:10:55 2006 From: python-checkins at python.org (richard.tew) Date: Sat, 2 Sep 2006 16:10:55 +0200 (CEST) Subject: [Stackless-checkins] r51687 - in stackless/sandbox: examples examples/mud.py examples/rpc.py examples/stacklesssocket.py Message-ID: <20060902141055.38E001E4010@bag.python.org> Author: richard.tew Date: Sat Sep 2 16:10:54 2006 New Revision: 51687 Added: stackless/sandbox/ stackless/sandbox/examples/ stackless/sandbox/examples/mud.py stackless/sandbox/examples/rpc.py stackless/sandbox/examples/stacklesssocket.py Log: Copied my Stackless networking examples from the wiki, so they can be fixed as need be with version control. Added: stackless/sandbox/examples/mud.py ============================================================================== --- (empty file) +++ stackless/sandbox/examples/mud.py Sat Sep 2 16:10:54 2006 @@ -0,0 +1,163 @@ +# +# A very simple MUD server based on the Stackless compatible sockets. +# +# Author: Richard Tew +# +# This code was written to serve as an example of Stackless Python usage. +# Feel free to email me with any questions, comments, or suggestions for +# improvement. +# +# - Could possibly be even simpler if the TelnetConnection class were removed +# and read/readline were done locally to the MUD code. Then disconnection +# detection could be built into the stacklesssocket.dispatcher class. +# + +import stackless +import stacklesssocket as socket +import random, time +import traceback + +class TelnetConnection(socket.dispatcher): + echo = False + connectionID = None + disconnectChannel = None + + def read(self): # TELNET + ret = self.readChannel.receive() + if self.echo: + if ret == '\x08': + self.send(ret+" ") + self.send(ret) + return ret + + def readline(self): # TELNET + buf = self.readBuffer + + while True: + if buf.find('\r\n') > -1: + i = buf.index('\r\n') + ret = buf[:i+2] + self.readBuffer = buf[i+2:] + while '\x08' in ret: + i = ret.index('\x08') + if i == 0: + ret = ret[1:] + else: + ret = ret[:i-1]+ret[i+1:] + return ret + + buf += self.read() + + def close(self): + # Notify the server. + if self.disconnectChannel is not None: + stackless.tasklet(self.disconnectChannel.send)(self) + self.disconnectChannel = None + # Do the standard socket closure handling. + socket.dispatcher.close(self) + +def RunServer(host, port): + listenSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + listenSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + listenSocket.bind((host, port)) + listenSocket.listen(5) + + # Connecting sockets should be wrapped in TelnetConnection, rather than + # stacklesssocket.dispatcher (the default wrapper). + def wrap_accept_socket(currentSocket): + return TelnetConnection(currentSocket) + listenSocket.wrap_accept_socket = wrap_accept_socket + + nextConnectionID = 1 + infoByConnectionID = {} + disconnectChannel = stackless.channel() + stackless.tasklet(MonitorDisconnections)(disconnectChannel, infoByConnectionID) + + print "Accepting connections on", host, port + try: + while listenSocket.accepting: + clientSocket, clientAddress = listenSocket.accept() + clientSocket = TelnetConnection(clientSocket.socket) + clientSocket.disconnectChannel = disconnectChannel + clientSocket.connectionID = nextConnectionID + print "Received connection #", clientSocket.connectionID, "from", clientAddress + infoByConnectionID[clientSocket.connectionID] = clientAddress, clientSocket + nextConnectionID += 1 + stackless.tasklet(MonitorIncomingConnection)(clientSocket, clientAddress, infoByConnectionID) + stackless.schedule() + except socket.error: + print "RunServer.error" + traceback.print_exc() + print "RunServer.exit" + +def MonitorDisconnections(disconnectChannel, infoByConnectionID): + print "MonitorDisconnections" + try: + while True: + clientSocket = disconnectChannel.receive() + print "Received disconnection of #", clientSocket.connectionID, "from", infoByConnectionID[clientSocket.connectionID][0] + del infoByConnectionID[clientSocket.connectionID] + except socket.error: + print "MonitorDisconnections.error" + traceback.print_exc() + print "MonitorDisconnections.exit" + +def MonitorIncomingConnection(clientSocket, clientAddress, infoByConnectionID): + clientSocket.send("Welcome to a basic Stackless Python MUD server.\r\n") + try: + while clientSocket.connected: + clientSocket.send("> ") + line = clientSocket.readline()[:-2].strip() + words = [ word.strip() for word in line.split(" ") ] + verb = words[0] + + if verb == "look": + clientSocket.send("There are %d users connected:\r\n" % len(infoByConnectionID)) + clientSocket.send("Name\tHost\t\tPort\r\n") + clientSocket.send("-" * 40 +"\r\n") + for clientAddress2, clientSocket2 in infoByConnectionID.itervalues(): + clientSocket.send("Unknown\t"+ str(clientAddress2[0]) +"\t"+ str(clientAddress2[1]) +"\r\n") + elif verb == "say": + line = line[4:] + secondPartyPrefix = "Someone says: " + for clientAddress2, clientSocket2 in infoByConnectionID.itervalues(): + if clientSocket2 is clientSocket: + prefix = "You say: " + else: + prefix = secondPartyPrefix + clientSocket2.send(prefix + "\"%s\"\r\n" % line) + elif verb == "quit": + clientSocket.close() + elif verb == "help": + clientSocket.send("Commands:\r\n") + for verb in [ "look", "say", "quit", "help" ]: + clientSocket.send(" "+ verb +"\r\n") + else: + clientSocket.send("Unknown command. Type 'help' to see a list of available commands.\r\n") + + stackless.schedule() + except socket.error: + print "MonitorIncomingConnection.socket.error" + traceback.print_exc() + +if __name__ == "__main__": + host = "127.0.0.1" + port = 3000 + + # We do not want this to start as we will run it ourselves. + socket.managerRunning = True + + t = stackless.tasklet(RunServer)(host, port) + # ManageSockets will exit if there are no sockets existing, so + # by running this tasklet once, we will get the listen socket in + # place before we invoke ManageSockets to run. + t.run() + + try: + socket.ManageSockets() + except KeyboardInterrupt: + print "** Detected ctrl-c in the console" + except: + print "main error" + traceback.print_exc() + print "EXIT" Added: stackless/sandbox/examples/rpc.py ============================================================================== --- (empty file) +++ stackless/sandbox/examples/rpc.py Sat Sep 2 16:10:54 2006 @@ -0,0 +1,158 @@ +# +# Remote procedure calls over sockets with Stackless Python. +# +# Author: Richard Tew +# +# This code was written to serve as an example of Stackless Python usage. +# Feel free to email me with any questions, comments, or suggestions for +# improvement. +# +# With just a page of code and the replacement socket module that is +# currently known as "stacklesssocket", it is possible to easily write +# a straightforward remote procedure call layer over a socket. +# + +import stackless +import stacklesssocket as socket +import types, struct, cPickle + +class EndPoint: + def __init__(self, epSocket): + self.socket = epSocket + self.callID = 0 + self.channelsByCallID = {} + self.otherEnd = RemoteEndPoint(self) + + stackless.tasklet(self.ManageSocket)() + + def ManageSocket(self): + try: + self.ReceiveIncomingData() + except socket.error: + # Disconnection while blocking on a recv call. + return + + def ReceiveIncomingData(self): + while self.socket.connected: + data = self.socket.recv(struct.calcsize("I")) + dataLength = struct.unpack("I", data)[0] + data = self.socket.recv(dataLength) + packet = cPickle.loads(data) + callID = packet[1] + if packet[0]: + channel = self.channelsByCallID[callID] + del self.channelsByCallID[callID] + channel.send(packet[2]) + else: + ret = self.HandleIncomingCall(packet[2], packet[3], packet[4]) + self.SendPacket(True, callID, ret) + stackless.schedule() + + def HandleIncomingCall(self, name, args, kwargs): + if name.startswith("__") or hasattr(EndPoint, name): + return # Raise error? + method = getattr(self, name) + if type(method) is not types.MethodType: + return # Raise error? + return method(*args, **kwargs) + + def RemoteCall(self, methodInfo): + self.callID += 1 + callID = self.callID + + channel = self.channelsByCallID[callID] = stackless.channel() + self.SendPacket(False, callID, methodInfo.name, methodInfo.args, methodInfo.kwargs) + return channel.receive() + + def SendPacket(self, *bits): + data = cPickle.dumps(bits) + data = struct.pack("I", len(data)) + data + self.socket.send(data) + +class RemoteEndPoint: + def __init__(self, endpoint): + self.endpoint = endpoint + + def __getattr__(self, name): + return RemoteFunction(self.endpoint, name) + +class RemoteFunction: + def __init__(self, endpoint, name): + self.endpoint = endpoint + self.name = name + + def __call__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs + + return self.endpoint.RemoteCall(self) + +if __name__ == "__main__": + # This test/example code is a little artificial, but it should both + # adequately test the RPC code above and demonstrate how easy it is + # to write this sort of code with Stackless Python. + + class Server: + def __init__(self, address): + self.socket = listenSocket = socket.socket() + listenSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + listenSocket.bind(address) + listenSocket.listen(5) + + self.endPoints = [] + + stackless.tasklet(self.ManageSocket)(listenSocket) + + def ManageSocket(self, listenSocket): + try: + while listenSocket.accepting: + epSocket, clientAddress = listenSocket.accept() + endPoint = ServerEndPoint(epSocket) + self.endPoints.append(endPoint) + except socket.error: + pass # Listen socket disconnected. Our job is done. + + if listenSocket.accepting: + listenSocket.close() + self.endPoints = [] + + class ClientEndPoint(EndPoint): + def Hello(self): + return "Client Hello!" + + class ServerEndPoint(EndPoint): + def Hello(self): + return "Server Hello!" + + address = "127.0.0.1", 3000 + + # Start the server. + server = Server(address) + + clientSocket = socket.socket() + clientSocket.connect(address) + + # Then connect the client. + client = ClientEndPoint(clientSocket) + + def ClientTasklet(client, server, clientSocket): + # Tell the server hello. + ret = client.otherEnd.Hello() + print " CLIENT GOT", ret + + stackless.tasklet(ServerTasklet)(server) + while server.socket.connected: + stackless.schedule() + clientSocket.close() + + def ServerTasklet(server): + # Tell all the clients hello. + for endpoint in server.endPoints: + ret = endpoint.otherEnd.Hello() + print " SERVER GOT", ret, "FROM CLIENT" + server.socket.close() + + stackless.tasklet(ClientTasklet)(client, server, clientSocket) + stackless.run() + + print "Done" Added: stackless/sandbox/examples/stacklesssocket.py ============================================================================== --- (empty file) +++ stackless/sandbox/examples/stacklesssocket.py Sat Sep 2 16:10:54 2006 @@ -0,0 +1,235 @@ +# +# Stackless compatible socket module: +# +# Author: Richard Tew +# +# This code was written to serve as an example of Stackless Python usage. +# Feel free to email me with any questions, comments, or suggestions for +# improvement. +# +# This wraps the asyncore module and the dispatcher class it provides in order +# write a socket module replacement that uses channels to allow calls to it to +# block until a delayed event occurs. +# +# Not all aspects of the socket module are provided by this file. Examples of +# it in use can be seen at the bottom of this file. +# +# NOTE: Versions of the asyncore module from Python 2.4 or later include bug +# fixes and earlier versions will not guarantee correct behaviour. +# Specifically, it monitors for errors on sockets where the version in +# Python 2.3.3 does not. +# + +# Possible improvements: +# - More correct error handling. When there is an error on a socket found by +# poll, there is no idea what it actually is. +# - Launching each bit of incoming data in its own tasklet on the readChannel +# send is a little over the top. It should be possible to add it to the +# rest of the queued data + +import stackless +import asyncore +import socket as stdsocket # We need the "socket" name for the function we export. + +# If we are to masquerade as the socket module, we need to provide the constants. +for k, v in stdsocket.__dict__.iteritems(): + if k.upper() == k: + locals()[k] = v +error = stdsocket.error + +managerRunning = False + +def ManageSockets(): + global managerRunning + + while len(asyncore.socket_map): + # Check the sockets for activity. + asyncore.poll(0.0) + # Yield to give other tasklets a chance to be scheduled. + stackless.schedule() + + managerRunning = False + +def socket(family=AF_INET, type=SOCK_STREAM, proto=0): + global managerRunning + + currentSocket = stdsocket.socket(family, type, proto) + ret = dispatcher(currentSocket) + # Ensure that the sockets actually work. + if not managerRunning: + managerRunning = True + stackless.tasklet(ManageSockets)() + return ret + +class dispatcher(asyncore.dispatcher): + def __init__(self, sock): + # This is worth doing. I was passing in an invalid socket which was + # an instance of dispatcher and it was causing tasklet death. + if not isinstance(sock, stdsocket.socket): + raise StandardError("Invalid socket passed to dispatcher") + + asyncore.dispatcher.__init__(self, sock) + + self.acceptChannel = stackless.channel() + self.connectChannel = stackless.channel() + self.readChannel = stackless.channel() + + self.readBuffer = '' + self.outBuffer = '' + + def writable(self): + return (not self.connected) or len(self.outBuffer) + + def accept(self): + return self.acceptChannel.receive() + + def connect(self, address): + asyncore.dispatcher.connect(self, address) + if not self.connected: + self.connectChannel.receive() + + def send(self, data): + self.outBuffer += data + return len(data) + + # Read at most byteCount bytes. + def recv(self, byteCount): + if len(self.readBuffer) < byteCount: + self.readBuffer += self.readChannel.receive() + ret = self.readBuffer[:byteCount] + self.readBuffer = self.readBuffer[byteCount:] + return ret + + def close(self): + asyncore.dispatcher.close(self) + self.connected = False + self.accepting = False + + # Clear out all the channels with relevant errors. + while self.acceptChannel.balance < 0: + self.acceptChannel.send_exception(error, 9, 'Bad file descriptor') + while self.connectChannel.balance < 0: + self.connectChannel.send_exception(error, 10061, 'Connection refused') + while self.readChannel.balance < 0: + self.readChannel.send_exception(error, 10054, 'Connection reset by peer') + + def handle_accept(self): + if self.acceptChannel.balance < 0: + currentSocket, clientAddress = asyncore.dispatcher.accept(self) + currentSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) + # Give them the asyncore based socket, not the standard one. + currentSocket = self.wrap_accept_socket(currentSocket) + stackless.tasklet(self.acceptChannel.send)((currentSocket, clientAddress)) + + # Inform the blocked connect call that the connection has been made. + def handle_connect(self): + self.connectChannel.send(None) + + # Just close the socket. That should send kind of relevant errors to waiting calls. + def handle_close(self): + self.close() + + # Some error, just close the channel and let that raise errors to blocked calls. + def handle_expt(self): + self.close() + + def handle_read(self): + buf = asyncore.dispatcher.recv(self, 20000) + stackless.tasklet(self.readChannel.send)(buf) + + def handle_write(self): + if len(self.outBuffer): + sentBytes = asyncore.dispatcher.send(self, self.outBuffer[:512]) + self.outBuffer = self.outBuffer[sentBytes:] + + # In order for incoming connections to be stackless compatible, they need to be + # wrapped by an asyncore based dispatcher subclass. + def wrap_accept_socket(self, currentSocket): + return dispatcher(currentSocket) + + +if __name__ == '__main__': + import struct + # Test code goes here. + testAddress = "127.0.0.1", 3000 + info = -12345678 + data = struct.pack("i", info) + dataLength = len(data) + + print "creating listen socket" + def ManageListener(address): + global info, data, dataLength + + listenSocket = socket(AF_INET, SOCK_STREAM) + listenSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) + listenSocket.bind(address) + listenSocket.listen(5) + # We will have to manually close the listening socket, at which point it + # should be the last one left and we want the socket manager tasklet to + # exit then. + + NUM_TESTS = 2 + + i = 1 + while i < NUM_TESTS + 1: + # No need to schedule this tasklet as the accept should yield most + # of the time on the underlying channel. + print "waiting for connection test", i + currentSocket, clientAddress = listenSocket.accept() + print "received connection", i, "from", clientAddress + + if i == 1: + currentSocket.close() + elif i == 2: + print "server test", i, "send" + currentSocket.send(data) + try: + print "server test", i, "recv" + currentSocket.recv(4) + break + except error: + pass + else: + currentSocket.close() + + print "server test", i, "OK" + i += 1 + + if i != NUM_TESTS+1: + print "server: FAIL", i + else: + print "server: OK", i + + listenSocket.close() + + def TestClientConnections(address): + global info, data, dataLength + + # Attempt 1: + clientSocket = socket() + clientSocket.connect(address) + print "client connection", 1, "waiting to recv" + try: + clientSocket.recv(5) + print "client test", 1, "FAIL" + return + except error: + pass + print "client test", 1, "OK" + + # Attempt 2: + clientSocket = socket() + clientSocket.connect(address) + print "client connection", 2, "waiting to recv" + s = clientSocket.recv(dataLength) + t = struct.unpack("i", s) + if t[0] == info: + print "client test", 2, "OK" + else: + print "client test", 2, "FAIL" + clientSocket.close() + + stackless.tasklet(ManageListener)(testAddress) + stackless.tasklet(TestClientConnections)(testAddress) + stackless.run() + print "result: SUCCESS" _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Thu Sep 7 14:30:27 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 7 Sep 2006 14:30:27 +0200 (CEST) Subject: [Stackless-checkins] r51809 - stackless/Python-2.4.3/dev/Stackless/core/stacklesseval.c Message-ID: <20060907123027.6AF9E1E4003@bag.python.org> Author: richard.tew Date: Thu Sep 7 14:30:26 2006 New Revision: 51809 Modified: stackless/Python-2.4.3/dev/Stackless/core/stacklesseval.c Log: Ported from trunk r51808. Fix for threading/interpreter exit/tasklet killing bug. The test case was to have 10 threads launched with a time.sleep(0.1) in each. This would cause the tasklet killing to have an access violation when it tried to move the tasklet to be killed before the main tasklet in the scheduling list, but the tasklet being killed was the main tasklet. Now if this is the case, no scheduling ordering changes are made as it is not necessary anyway. Modified: stackless/Python-2.4.3/dev/Stackless/core/stacklesseval.c ============================================================================== --- stackless/Python-2.4.3/dev/Stackless/core/stacklesseval.c (original) +++ stackless/Python-2.4.3/dev/Stackless/core/stacklesseval.c Thu Sep 7 14:30:26 2006 @@ -321,7 +321,7 @@ * killed, they will be implicitly placed before this one, * leaving it to run next. */ - if (!t->flags.blocked) { + if (!t->flags.blocked && t != cs->tstate->st.main) { chain = &t; SLP_CHAIN_REMOVE(PyTaskletObject, chain, task, next, prev) chain = &cs->tstate->st.main; _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Tue Sep 5 00:06:42 2006 From: python-checkins at python.org (andrew.dalke) Date: Tue, 5 Sep 2006 00:06:42 +0200 (CEST) Subject: [Stackless-checkins] r51707 - stackless/sandbox/examples/stacklesssocket.py Message-ID: <20060904220642.CA7B81E4004@bag.python.org> Author: andrew.dalke Date: Tue Sep 5 00:06:42 2006 New Revision: 51707 Modified: stackless/sandbox/examples/stacklesssocket.py Log: Split the dispatcher into two parts. New one is 'stacklesssocket'. Why? GC problems. The old scheme required explict .close() calls because asyncore's global socket_map kept a bound method from each dispatcher. This meant the dispatcher was never gc'ed if it was no longer in use elsewhere. The new scheme has stacklesssocket as a facade to dispatcher. When the stacklesssocket gets a __del__ it forces the dispatcher to close if not already closed. Removed all explicit close statements from the test code. Modified: stackless/sandbox/examples/stacklesssocket.py ============================================================================== --- stackless/sandbox/examples/stacklesssocket.py (original) +++ stackless/sandbox/examples/stacklesssocket.py Tue Sep 5 00:06:42 2006 @@ -46,19 +46,6 @@ getaddrinfo = stdsocket.getaddrinfo -# socket._fileobject does not forward close() to the underlying -# socket. That behavior is needed so gc'ed _fileobjects get -# correctly removed from the asyncore dispatcher. -class _stackless_fileobject(stdsocket._fileobject): - def close(self): - try: - if self._sock: - self.flush() - self._sock.close() - finally: - self._sock = None - - managerRunning = False def ManageSockets(): @@ -76,20 +63,51 @@ global managerRunning currentSocket = stdsocket.socket(family, type, proto) - ret = dispatcher(currentSocket) + ret = stacklesssocket(currentSocket) # Ensure that the sockets actually work. if not managerRunning: managerRunning = True stackless.tasklet(ManageSockets)() return ret +# This is a facade to the dispatcher object. +# It exists because asyncore's socket map keeps a bound reference to +# the dispatcher and hence the dispatcher will never get gc'ed. +# +# The rest of the world sees a 'stacklesssocket' which has no cycles +# and will be gc'ed correctly + +class stacklesssocket(object): + def __init__(self, sock): + self.sock = sock + self.dispatcher = dispatcher(sock) + + def __getattr__(self, name): + # Forward nearly everything to the dispatcher + if not name.startswith("__"): + # I don't like forwarding __repr__ + return getattr(self.dispatcher, name) + + def __del__(self): + # Close dispatcher if it isn't already closed + if self.dispatcher._fileno is not None: + try: + self.dispatcher.close() + finally: + self.dispatcher = None + + # Catch this one here to make gc work correctly. + # (Consider if stacklesssocket gets gc'ed before the _fileobject) + def makefile(self, mode='r', bufsize=-1): + return stdsocket._fileobject(self, mode, bufsize) + + class dispatcher(asyncore.dispatcher): def __init__(self, sock): # This is worth doing. I was passing in an invalid socket which was # an instance of dispatcher and it was causing tasklet death.