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. if not isinstance(sock, stdsocket.socket): raise StandardError("Invalid socket passed to dispatcher") - asyncore.dispatcher.__init__(self, sock) self.acceptChannel = stackless.channel() @@ -178,13 +196,12 @@ # 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) + return stacklesssocket(currentSocket) + # asyncore doesn't support this. Why not? def fileno(self): return self.socket.fileno() - def makefile(self, mode='r', bufsize=-1): - return _stackless_fileobject(self, mode, bufsize) if __name__ == '__main__': import struct @@ -202,9 +219,6 @@ 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 @@ -224,15 +238,12 @@ print "server test", i, "recv" if currentSocket.recv(4) != "": print "server recv(1)", i, "FAIL" - currentSocket.close() break # multiple empty recvs are fine if currentSocket.recv(4) != "": print "server recv(2)", i, "FAIL" - currentSocket.close() break - currentSocket.close() else: currentSocket.close() @@ -244,7 +255,6 @@ else: print "server: OK", i - listenSocket.close() print "Done server" def TestClientConnections(address): @@ -258,7 +268,6 @@ print "client test", 1, "FAIL" else: print "client test", 1, "OK" - clientSocket.close() # Attempt 2: clientSocket = socket() @@ -270,7 +279,6 @@ print "client test", 2, "OK" else: print "client test", 2, "FAIL" - clientSocket.close() def TestMonkeyPatch(uri): # replace the system socket with this module @@ -278,7 +286,7 @@ sys.modules["socket"] = __import__(__name__) import urllib # must occur after monkey-patching! f = urllib.urlopen(uri) - if not isinstance(f.fp._sock, dispatcher): + if not isinstance(f.fp._sock, stacklesssocket): raise AssertionError("failed to apply monkeypatch") s = f.read() if len(s) != 0: _______________________________________________ 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 15:19:59 2006 From: python-checkins at python.org (richard.tew) Date: Wed, 13 Sep 2006 15:19:59 +0200 (CEST) Subject: [Stackless-checkins] r51873 - in stackless: binaries-pc/python25.zip binaries-pc/python25.zip.md5.py branches/release25-maint/Doc/api/abstract.tex branches/release25-maint/Doc/api/concrete.tex branches/release25-maint/Doc/api/intro.tex branches/release25-maint/Doc/api/newtypes.tex branches/release25-maint/Doc/commontex/boilerplate.tex branches/release25-maint/Doc/lib/libdecimal.tex branches/release25-maint/Doc/lib/libhashlib.tex branches/release25-maint/Doc/lib/libsqlite3.tex branches/release25-maint/Doc/lib/libstdtypes.tex branches/release25-maint/Doc/lib/libunittest.tex branches/release25-maint/Doc/lib/libuuid.tex branches/release25-maint/Doc/lib/sqlite3/executescript.py branches/release25-maint/Doc/ref/ref3.tex branches/release25-maint/Doc/tut/tut.tex branches/release25-maint/Doc/whatsnew/whatsnew25.tex branches/release25-maint/Include/import.h branches/release25-maint/Include/patchlevel.h branches/release25-maint/Lib/bsddb/test/test_basics.py branches/release25-maint/Lib/ctypes/test! /test_bitfields.py branches/release25-maint/Lib/ctypes/test/test_cast.py branches/release25-maint/Lib/decimal.py branches/release25-maint/Lib/doctest.py branches/release25-maint/Lib/idlelib/NEWS.txt branches/release25-maint/Lib/idlelib/idlever.py branches/release25-maint/Lib/inspect.py branches/release25-maint/Lib/logging/config.py branches/release25-maint/Lib/sgmllib.py branches/release25-maint/Lib/subprocess.py branches/release25-maint/Lib/tarfile.py branches/release25-maint/Lib/test/sgml_input.html branches/release25-maint/Lib/test/string_tests.py branches/release25-maint/Lib/test/test_codecencodings_cn.py branches/release25-maint/Lib/test/test_contextlib.py branches/release25-maint/Lib/test/test_decimal.py branches/release25-maint/Lib/test/test_exceptions.py branches/release25-maint/Lib/test/test_fcntl.py branches/release25-maint/Lib/test/test_grammar.py branches/release25-maint/Lib/test/test_inspect.py branches/release25-maint/Lib/test/test_itertools.py branches/releas! e25-maint/Lib/test/test_multibytecodec.py branches/release25-maint/Lib/test/test_mutants.py branches/release25-maint/Lib/test/test_pep352.py branches/release25-maint/Lib/test/test_sgmllib.py branches/release25-maint/Lib/test/test_subprocess.py branches/release25-maint/Lib/test/test_tarfile.py branches/release25-maint/Lib/tes Message-ID: <20060913131959.AC3681E4003@bag.python.org> Author: richard.tew Date: Wed Sep 13 15:19:16 2006 New Revision: 51873 Added: stackless/branches/release25-maint/Lib/test/sgml_input.html - copied unchanged from r51860, python/branches/release25-maint/Lib/test/sgml_input.html Modified: stackless/binaries-pc/python25.zip stackless/binaries-pc/python25.zip.md5.py stackless/branches/release25-maint/Doc/api/abstract.tex stackless/branches/release25-maint/Doc/api/concrete.tex stackless/branches/release25-maint/Doc/api/intro.tex stackless/branches/release25-maint/Doc/api/newtypes.tex stackless/branches/release25-maint/Doc/commontex/boilerplate.tex stackless/branches/release25-maint/Doc/lib/libdecimal.tex stackless/branches/release25-maint/Doc/lib/libhashlib.tex stackless/branches/release25-maint/Doc/lib/libsqlite3.tex stackless/branches/release25-maint/Doc/lib/libstdtypes.tex stackless/branches/release25-maint/Doc/lib/libunittest.tex stackless/branches/release25-maint/Doc/lib/libuuid.tex stackless/branches/release25-maint/Doc/lib/sqlite3/executescript.py stackless/branches/release25-maint/Doc/ref/ref3.tex stackless/branches/release25-maint/Doc/tut/tut.tex stackless/branches/release25-maint/Doc/whatsnew/whatsnew25.tex stackless/branches/release25-maint/Include/import.h stackless/branches/release25-maint/Include/patchlevel.h stackless/branches/release25-maint/Lib/bsddb/test/test_basics.py stackless/branches/release25-maint/Lib/ctypes/test/test_bitfields.py stackless/branches/release25-maint/Lib/ctypes/test/test_cast.py stackless/branches/release25-maint/Lib/decimal.py stackless/branches/release25-maint/Lib/doctest.py stackless/branches/release25-maint/Lib/idlelib/NEWS.txt stackless/branches/release25-maint/Lib/idlelib/idlever.py stackless/branches/release25-maint/Lib/inspect.py stackless/branches/release25-maint/Lib/logging/config.py stackless/branches/release25-maint/Lib/sgmllib.py stackless/branches/release25-maint/Lib/subprocess.py stackless/branches/release25-maint/Lib/tarfile.py stackless/branches/release25-maint/Lib/test/string_tests.py stackless/branches/release25-maint/Lib/test/test_codecencodings_cn.py stackless/branches/release25-maint/Lib/test/test_contextlib.py stackless/branches/release25-maint/Lib/test/test_decimal.py stackless/branches/release25-maint/Lib/test/test_exceptions.py stackless/branches/release25-maint/Lib/test/test_fcntl.py stackless/branches/release25-maint/Lib/test/test_grammar.py stackless/branches/release25-maint/Lib/test/test_inspect.py stackless/branches/release25-maint/Lib/test/test_itertools.py stackless/branches/release25-maint/Lib/test/test_multibytecodec.py stackless/branches/release25-maint/Lib/test/test_mutants.py stackless/branches/release25-maint/Lib/test/test_pep352.py stackless/branches/release25-maint/Lib/test/test_sgmllib.py stackless/branches/release25-maint/Lib/test/test_subprocess.py stackless/branches/release25-maint/Lib/test/test_tarfile.py stackless/branches/release25-maint/Lib/test/test_tempfile.py stackless/branches/release25-maint/Lib/test/test_unicode.py stackless/branches/release25-maint/Lib/test/test_urllib2.py stackless/branches/release25-maint/Lib/test/test_uuid.py stackless/branches/release25-maint/Lib/urllib2.py stackless/branches/release25-maint/Lib/uuid.py stackless/branches/release25-maint/Mac/README stackless/branches/release25-maint/Misc/ACKS stackless/branches/release25-maint/Misc/NEWS stackless/branches/release25-maint/Misc/RPM/python-2.5.spec stackless/branches/release25-maint/Modules/_ctypes/_ctypes.c stackless/branches/release25-maint/Modules/_ctypes/stgdict.c stackless/branches/release25-maint/Modules/_cursesmodule.c stackless/branches/release25-maint/Modules/cjkcodecs/_codecs_cn.c stackless/branches/release25-maint/Modules/cjkcodecs/_codecs_iso2022.c stackless/branches/release25-maint/Modules/cjkcodecs/cjkcodecs.h stackless/branches/release25-maint/Modules/itertoolsmodule.c stackless/branches/release25-maint/Modules/mmapmodule.c stackless/branches/release25-maint/Modules/posixmodule.c stackless/branches/release25-maint/Objects/classobject.c stackless/branches/release25-maint/Objects/dictobject.c stackless/branches/release25-maint/Objects/exceptions.c stackless/branches/release25-maint/Objects/fileobject.c stackless/branches/release25-maint/Objects/intobject.c stackless/branches/release25-maint/Objects/setobject.c stackless/branches/release25-maint/Objects/stringlib/partition.h stackless/branches/release25-maint/Objects/stringobject.c stackless/branches/release25-maint/Objects/unicodeobject.c stackless/branches/release25-maint/PCbuild/build_ssl.py stackless/branches/release25-maint/Python/ast.c stackless/branches/release25-maint/Python/bltinmodule.c stackless/branches/release25-maint/Python/import.c stackless/branches/release25-maint/Python/pystate.c stackless/branches/release25-maint/Python/pythonrun.c stackless/branches/release25-maint/README stackless/branches/release25-maint/Tools/buildbot/external.bat stackless/branches/release25-maint/Tools/msi/msi.py stackless/branches/release25-maint/Tools/pybench/pybench.py stackless/branches/release25-maint/configure stackless/branches/release25-maint/configure.in Log: Merged in the rc2 changes. Also included rebuilt binaries for rc2. 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 15:19:16 2006 @@ -1,6 +1,6 @@ import md5 -expected = "9c35771612a1abdf0f957f63d5f69fcd" +expected = "13e707247a888eeefa0217d599cf95a7" fname = r"python25.zip" print "expected digest", expected received = md5.md5(file(fname, "rb").read()).hexdigest() Modified: stackless/branches/release25-maint/Doc/api/abstract.tex ============================================================================== --- stackless/branches/release25-maint/Doc/api/abstract.tex (original) +++ stackless/branches/release25-maint/Doc/api/abstract.tex Wed Sep 13 15:19:16 2006 @@ -5,6 +5,10 @@ numerical types, or all sequence types). When used on object types for which they do not apply, they will raise a Python exception. +It is not possible to use these functions on objects that are not properly +initialized, such as a list object that has been created by +\cfunction{PyList_New()}, but whose items have not been set to some +non-\code{NULL} value yet. \section{Object Protocol \label{object}} Modified: stackless/branches/release25-maint/Doc/api/concrete.tex ============================================================================== --- stackless/branches/release25-maint/Doc/api/concrete.tex (original) +++ stackless/branches/release25-maint/Doc/api/concrete.tex Wed Sep 13 15:19:16 2006 @@ -1840,6 +1840,11 @@ \begin{cfuncdesc}{PyObject*}{PyList_New}{Py_ssize_t len} Return a new list of length \var{len} on success, or \NULL{} on failure. + \note{If \var{length} is greater than zero, the returned list object's + items are set to \code{NULL}. Thus you cannot use abstract + API functions such as \cfunction{PySequence_SetItem()} + or expose the object to Python code before setting all items to a + real object with \cfunction{PyList_SetItem()}.} \end{cfuncdesc} \begin{cfuncdesc}{Py_ssize_t}{PyList_Size}{PyObject *list} Modified: stackless/branches/release25-maint/Doc/api/intro.tex ============================================================================== --- stackless/branches/release25-maint/Doc/api/intro.tex (original) +++ stackless/branches/release25-maint/Doc/api/intro.tex Wed Sep 13 15:19:16 2006 @@ -225,25 +225,10 @@ \cfunction{PyTuple_SetItem()} for tuples that you are creating yourself. -Equivalent code for populating a list can be written using -\cfunction{PyList_New()} and \cfunction{PyList_SetItem()}. Such code -can also use \cfunction{PySequence_SetItem()}; this illustrates the -difference between the two (the extra \cfunction{Py_DECREF()} calls): +Equivalent code for populating a list can be written using +\cfunction{PyList_New()} and \cfunction{PyList_SetItem()}. -\begin{verbatim} -PyObject *l, *x; - -l = PyList_New(3); -x = PyInt_FromLong(1L); -PySequence_SetItem(l, 0, x); Py_DECREF(x); -x = PyInt_FromLong(2L); -PySequence_SetItem(l, 1, x); Py_DECREF(x); -x = PyString_FromString("three"); -PySequence_SetItem(l, 2, x); Py_DECREF(x); -\end{verbatim} - -You might find it strange that the ``recommended'' approach takes more -code. However, in practice, you will rarely use these ways of +However, in practice, you will rarely use these ways of creating and populating a tuple or list. There's a generic function, \cfunction{Py_BuildValue()}, that can create most common objects from C values, directed by a \dfn{format string}. For example, the @@ -251,10 +236,10 @@ also takes care of the error checking): \begin{verbatim} -PyObject *t, *l; +PyObject *tuple, *list; -t = Py_BuildValue("(iis)", 1, 2, "three"); -l = Py_BuildValue("[iis]", 1, 2, "three"); +tuple = Py_BuildValue("(iis)", 1, 2, "three"); +list = Py_BuildValue("[iis]", 1, 2, "three"); \end{verbatim} It is much more common to use \cfunction{PyObject_SetItem()} and @@ -276,8 +261,12 @@ if (n < 0) return -1; for (i = 0; i < n; i++) { - if (PyObject_SetItem(target, i, item) < 0) + PyObject *index = PyInt_FromLong(i); + if (!index) + return -1; + if (PyObject_SetItem(target, index, item) < 0) return -1; + Py_DECREF(index); } return 0; } Modified: stackless/branches/release25-maint/Doc/api/newtypes.tex ============================================================================== --- stackless/branches/release25-maint/Doc/api/newtypes.tex (original) +++ stackless/branches/release25-maint/Doc/api/newtypes.tex Wed Sep 13 15:19:16 2006 @@ -979,7 +979,7 @@ More information about Python's garbage collection scheme can be found in section \ref{supporting-cycle-detection}. - This field is inherited by subtypes together with \member{tp_clear} + This field is inherited by subtypes together with \member{tp_traverse} and the \constant{Py_TPFLAGS_HAVE_GC} flag bit: the flag bit, \member{tp_traverse}, and \member{tp_clear} are all inherited from the base type if they are all zero in the subtype \emph{and} the 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 13 15:19:16 2006 @@ -5,5 +5,5 @@ Email: \email{docs at python.org} } -\date{17th August, 2006} % XXX update before final release! +\date{12th September, 2006} % XXX update before final release! \input{patchlevel} % include Python version information Modified: stackless/branches/release25-maint/Doc/lib/libdecimal.tex ============================================================================== --- stackless/branches/release25-maint/Doc/lib/libdecimal.tex (original) +++ stackless/branches/release25-maint/Doc/lib/libdecimal.tex Wed Sep 13 15:19:16 2006 @@ -435,36 +435,37 @@ the \function{getcontext()} and \function{setcontext()} functions: \begin{funcdesc}{getcontext}{} - Return the current context for the active thread. + Return the current context for the active thread. \end{funcdesc} \begin{funcdesc}{setcontext}{c} - Set the current context for the active thread to \var{c}. + Set the current context for the active thread to \var{c}. \end{funcdesc} Beginning with Python 2.5, you can also use the \keyword{with} statement -to temporarily change the active context. For example the following code -increases the current decimal precision by 2 places, performs a -calculation, and then automatically restores the previous context: +and the \function{localcontext()} function to temporarily change the +active context. -\begin{verbatim} -from __future__ import with_statement -import decimal - -with decimal.getcontext() as ctx: - ctx.prec += 2 # add 2 more digits of precision - calculate_something() +\begin{funcdesc}{localcontext}{\optional{c}} + Return a context manager that will set the current context for + the active thread to a copy of \var{c} on entry to the with-statement + and restore the previous context when exiting the with-statement. If + no context is specified, a copy of the current context is used. + \versionadded{2.5} + + For example, the following code sets the current decimal precision + to 42 places, performs a calculation, and then automatically restores + the previous context: +\begin{verbatim} + from __future__ import with_statement + from decimal import localcontext + + with localcontext() as ctx: + ctx.prec = 42 # Perform a high precision calculation + s = calculate_something() + s = +s # Round the final result back to the default precision \end{verbatim} - -The context that's active in the body of the \keyword{with} statement is -a \emph{copy} of the context you provided to the \keyword{with} -statement, so modifying its attributes doesn't affect anything except -that temporary copy. - -You can use any decimal context in a \keyword{with} statement, but if -you just want to make a temporary change to some aspect of the current -context, it's easiest to just use \function{getcontext()} as shown -above. +\end{funcdesc} New contexts can also be created using the \class{Context} constructor described below. In addition, the module provides three pre-made Modified: stackless/branches/release25-maint/Doc/lib/libhashlib.tex ============================================================================== --- stackless/branches/release25-maint/Doc/lib/libhashlib.tex (original) +++ stackless/branches/release25-maint/Doc/lib/libhashlib.tex Wed Sep 13 15:19:16 2006 @@ -86,8 +86,8 @@ \begin{methoddesc}[hash]{digest}{} Return the digest of the strings passed to the \method{update()} -method so far. This is a 16-byte string which may contain -non-\ASCII{} characters, including null bytes. +method so far. This is a string of \member{digest_size} bytes which may +contain non-\ASCII{} characters, including null bytes. \end{methoddesc} \begin{methoddesc}[hash]{hexdigest}{} 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 13 15:19:16 2006 @@ -6,14 +6,16 @@ \sectionauthor{Gerhard H?ring}{gh at ghaering.de} \versionadded{2.5} -SQLite is a C library that provides a SQL-language database that -stores data in disk files without requiring a separate server process. +SQLite is a C library that provides a lightweight disk-based database +that doesn't require a separate server process and allows accessing +the database using a nonstandard variant of the SQL query language. +Some applications can use SQLite for internal data storage. It's also +possible to prototype an application using SQLite and then port the +code to a larger database such as PostgreSQL or Oracle. + pysqlite was written by Gerhard H\"aring and provides a SQL interface compliant with the DB-API 2.0 specification described by -\pep{249}. This means that it should be possible to write the first -version of your applications using SQLite for data storage. If -switching to a larger database such as PostgreSQL or Oracle is -later necessary, the switch should be relatively easy. +\pep{249}. To use the module, you must first create a \class{Connection} object that represents the database. Here the data will be stored in the @@ -34,8 +36,8 @@ # Create table c.execute('''create table stocks -(date timestamp, trans varchar, symbol varchar, - qty decimal, price decimal)''') +(date text, trans text, symbol text, + qty real, price real)''') # Insert a row of data c.execute("""insert into stocks Modified: stackless/branches/release25-maint/Doc/lib/libstdtypes.tex ============================================================================== --- stackless/branches/release25-maint/Doc/lib/libstdtypes.tex (original) +++ stackless/branches/release25-maint/Doc/lib/libstdtypes.tex Wed Sep 13 15:19:16 2006 @@ -771,8 +771,8 @@ Split the string at the last occurrence of \var{sep}, and return a 3-tuple containing the part before the separator, the separator itself, and the part after the separator. If the separator is not -found, return a 3-tuple containing the string itself, followed by -two empty strings. +found, return a 3-tuple containing two empty strings, followed by +the string itself. \versionadded{2.5} \end{methoddesc} @@ -1410,15 +1410,15 @@ {(1)} \lineiii{\var{a}.clear()}{remove all items from \code{a}}{} \lineiii{\var{a}.copy()}{a (shallow) copy of \code{a}}{} - \lineiii{\var{a}.has_key(\var{k})} + \lineiii{\var{k} in \var{a}} {\code{True} if \var{a} has a key \var{k}, else \code{False}} - {} - \lineiii{\var{k} \code{in} \var{a}} - {Equivalent to \var{a}.has_key(\var{k})} {(2)} \lineiii{\var{k} not in \var{a}} - {Equivalent to \code{not} \var{a}.has_key(\var{k})} + {Equivalent to \code{not} \var{k} in \var{a}} {(2)} + \lineiii{\var{a}.has_key(\var{k})} + {Equivalent to \var{k} \code{in} \var{a}, use that form in new code} + {} \lineiii{\var{a}.items()} {a copy of \var{a}'s list of (\var{key}, \var{value}) pairs} {(3)} Modified: stackless/branches/release25-maint/Doc/lib/libunittest.tex ============================================================================== --- stackless/branches/release25-maint/Doc/lib/libunittest.tex (original) +++ stackless/branches/release25-maint/Doc/lib/libunittest.tex Wed Sep 13 15:19:16 2006 @@ -212,8 +212,8 @@ class DefaultWidgetSizeTestCase(unittest.TestCase): def runTest(self): - widget = Widget("The widget") - self.failUnless(widget.size() == (50,50), 'incorrect default size') + widget = Widget('The widget') + self.assertEqual(widget.size(), (50, 50), 'incorrect default size') \end{verbatim} Note that in order to test something, we use the one of the @@ -247,7 +247,7 @@ class SimpleWidgetTestCase(unittest.TestCase): def setUp(self): - self.widget = Widget("The widget") + self.widget = Widget('The widget') class DefaultWidgetSizeTestCase(SimpleWidgetTestCase): def runTest(self): @@ -273,7 +273,7 @@ class SimpleWidgetTestCase(unittest.TestCase): def setUp(self): - self.widget = Widget("The widget") + self.widget = Widget('The widget') def tearDown(self): self.widget.dispose() @@ -298,7 +298,7 @@ class WidgetTestCase(unittest.TestCase): def setUp(self): - self.widget = Widget("The widget") + self.widget = Widget('The widget') def tearDown(self): self.widget.dispose() @@ -322,8 +322,8 @@ passing the method name in the constructor: \begin{verbatim} -defaultSizeTestCase = WidgetTestCase("testDefaultSize") -resizeTestCase = WidgetTestCase("testResize") +defaultSizeTestCase = WidgetTestCase('testDefaultSize') +resizeTestCase = WidgetTestCase('testResize') \end{verbatim} Test case instances are grouped together according to the features @@ -333,8 +333,8 @@ \begin{verbatim} widgetTestSuite = unittest.TestSuite() -widgetTestSuite.addTest(WidgetTestCase("testDefaultSize")) -widgetTestSuite.addTest(WidgetTestCase("testResize")) +widgetTestSuite.addTest(WidgetTestCase('testDefaultSize')) +widgetTestSuite.addTest(WidgetTestCase('testResize')) \end{verbatim} For the ease of running tests, as we will see later, it is a good @@ -344,8 +344,8 @@ \begin{verbatim} def suite(): suite = unittest.TestSuite() - suite.addTest(WidgetTestCase("testDefaultSize")) - suite.addTest(WidgetTestCase("testResize")) + suite.addTest(WidgetTestCase('testDefaultSize')) + suite.addTest(WidgetTestCase('testResize')) return suite \end{verbatim} @@ -353,7 +353,7 @@ \begin{verbatim} def suite(): - tests = ["testDefaultSize", "testResize"] + tests = ['testDefaultSize', 'testResize'] return unittest.TestSuite(map(WidgetTestCase, tests)) \end{verbatim} @@ -462,7 +462,7 @@ \subsection{Classes and functions \label{unittest-contents}} -\begin{classdesc}{TestCase}{} +\begin{classdesc}{TestCase}{\optional{methodName}} Instances of the \class{TestCase} class represent the smallest testable units in the \module{unittest} universe. This class is intended to be used as a base class, with specific tests being @@ -470,6 +470,23 @@ interface needed by the test runner to allow it to drive the test, and methods that the test code can use to check for and report various kinds of failure. + + Each instance of \class{TestCase} will run a single test method: + the method named \var{methodName}. If you remember, we had an + earlier example that went something like this: + + \begin{verbatim} + def suite(): + suite = unittest.TestSuite() + suite.addTest(WidgetTestCase('testDefaultSize')) + suite.addTest(WidgetTestCase('testResize')) + return suite + \end{verbatim} + + Here, we create two instances of \class{WidgetTestCase}, each of + which runs a single test. + + \var{methodName} defaults to \code{'runTest'}. \end{classdesc} \begin{classdesc}{FunctionTestCase}{testFunc\optional{, @@ -502,6 +519,11 @@ subclass. \end{classdesc} +\begin{classdesc}{TestResult}{} + This class is used to compile information about which tests have succeeded + and which have failed. +\end{classdesc} + \begin{datadesc}{defaultTestLoader} Instance of the \class{TestLoader} class intended to be shared. If no customization of the \class{TestLoader} is needed, this instance can @@ -574,8 +596,9 @@ \begin{methoddesc}[TestCase]{run}{\optional{result}} Run the test, collecting the result into the test result object passed as \var{result}. If \var{result} is omitted or \constant{None}, - a temporary result object is created and used, but is not made - available to the caller. + a temporary result object is created (by calling the + \method{defaultTestCase()} method) and used; this result object is not + returned to \method{run()}'s caller. The same effect may be had by simply calling the \class{TestCase} instance. @@ -684,8 +707,13 @@ \end{methoddesc} \begin{methoddesc}[TestCase]{defaultTestResult}{} - Return the default type of test result object to be used to run this - test. + Return an instance of the test result class that should be used + for this test case class (if no other result instance is provided + to the \method{run()} method). + + For \class{TestCase} instances, this will always be an instance of + \class{TestResult}; subclasses of \class{TestCase} should + override this as necessary. \end{methoddesc} \begin{methoddesc}[TestCase]{id}{} @@ -761,26 +789,20 @@ tests for reporting purposes; a \class{TestResult} instance is returned by the \method{TestRunner.run()} method for this purpose. -Each instance holds the total number of tests run, and collections of -failures and errors that occurred among those test runs. The -collections contain tuples of \code{(\var{testcase}, -\var{traceback})}, where \var{traceback} is a string containing a -formatted version of the traceback for the exception. - \class{TestResult} instances have the following attributes that will be of interest when inspecting the results of running a set of tests: \begin{memberdesc}[TestResult]{errors} A list containing 2-tuples of \class{TestCase} instances and - formatted tracebacks. Each tuple represents a test which raised an - unexpected exception. + strings holding formatted tracebacks. Each tuple represents a test which + raised an unexpected exception. \versionchanged[Contains formatted tracebacks instead of \function{sys.exc_info()} results]{2.2} \end{memberdesc} \begin{memberdesc}[TestResult]{failures} - A list containing 2-tuples of \class{TestCase} instances and - formatted tracebacks. Each tuple represents a test where a failure + A list containing 2-tuples of \class{TestCase} instances and strings + holding formatted tracebacks. Each tuple represents a test where a failure was explicitly signalled using the \method{TestCase.fail*()} or \method{TestCase.assert*()} methods. \versionchanged[Contains formatted tracebacks instead of @@ -817,17 +839,25 @@ \begin{methoddesc}[TestResult]{startTest}{test} Called when the test case \var{test} is about to be run. + + The default implementation simply increments the instance's + \code{testsRun} counter. \end{methoddesc} \begin{methoddesc}[TestResult]{stopTest}{test} - Called when the test case \var{test} has been executed, regardless + Called after the test case \var{test} has been executed, regardless of the outcome. + + The default implementation does nothing. \end{methoddesc} \begin{methoddesc}[TestResult]{addError}{test, err} Called when the test case \var{test} raises an unexpected exception \var{err} is a tuple of the form returned by \function{sys.exc_info()}: \code{(\var{type}, \var{value}, \var{traceback})}. + + The default implementation appends \code{(\var{test}, \var{err})} to + the instance's \code{errors} attribute. \end{methoddesc} \begin{methoddesc}[TestResult]{addFailure}{test, err} @@ -835,10 +865,15 @@ \var{err} is a tuple of the form returned by \function{sys.exc_info()}: \code{(\var{type}, \var{value}, \var{traceback})}. + + The default implementation appends \code{(\var{test}, \var{err})} to + the instance's \code{failures} attribute. \end{methoddesc} \begin{methoddesc}[TestResult]{addSuccess}{test} Called when the test case \var{test} succeeds. + + The default implementation does nothing. \end{methoddesc} @@ -878,9 +913,12 @@ Return a suite of all tests cases given a string specifier. The specifier \var{name} is a ``dotted name'' that may resolve - either to a module, a test case class, a \class{TestSuite} instance, - a test method within a test case class, or a callable object which - returns a \class{TestCase} or \class{TestSuite} instance. + either to a module, a test case class, a test method within a test + case class, a \class{TestSuite} instance, or a callable object which + returns a \class{TestCase} or \class{TestSuite} instance. These checks + are applied in the order listed here; that is, a method on a possible + test case class will be picked up as ``a test method within a test + case class'', rather than ``a callable object''. For example, if you have a module \module{SampleTests} containing a \class{TestCase}-derived class \class{SampleTestCase} with three test @@ -905,7 +943,7 @@ \begin{methoddesc}[TestLoader]{getTestCaseNames}{testCaseClass} Return a sorted sequence of method names found within - \var{testCaseClass}. + \var{testCaseClass}; this should be a subclass of \class{TestCase}. \end{methoddesc} 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 13 15:19:16 2006 @@ -18,20 +18,11 @@ network address. \function{uuid4()} creates a random UUID. \begin{classdesc}{UUID}{\optional{hex\optional{, bytes\optional{, -fields\optional{, int\optional{, version}}}}}} - -%Instances of the UUID class represent UUIDs as specified in RFC 4122. -%UUID objects are immutable, hashable, and usable as dictionary keys. -%Converting a UUID to a string with str() yields something in the form -%'12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts -%four possible forms: a similar string of hexadecimal digits, or a -%string of 16 raw bytes as an argument named 'bytes', or a tuple of -%six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and -%48-bit values respectively) as an argument named 'fields', or a single -%128-bit integer as an argument named 'int'. +bytes_le\optional{, fields\optional{, int\optional{, version}}}}}}} Create a UUID from either a string of 32 hexadecimal digits, -a string of 16 bytes as the \var{bytes} argument, a tuple of six +a string of 16 bytes as the \var{bytes} argument, a string of 16 bytes +in little-endian order as the \var{bytes_le} argument, a tuple of six integers (32-bit \var{time_low}, 16-bit \var{time_mid}, 16-bit \var{time_hi_version}, 8-bit \var{clock_seq_hi_variant}, 8-bit \var{clock_seq_low}, 48-bit \var{node}) @@ -45,22 +36,31 @@ UUID('12345678123456781234567812345678') UUID('urn:uuid:12345678-1234-5678-1234-567812345678') UUID(bytes='\x12\x34\x56\x78'*4) +UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' + + '\x12\x34\x56\x78\x12\x34\x56\x78') UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) UUID(int=0x12345678123456781234567812345678) \end{verbatim} -Exactly one of \var{hex}, \var{bytes}, \var{fields}, or \var{int} must +Exactly one of \var{hex}, \var{bytes}, \var{bytes_le}, \var{fields}, +or \var{int} must be given. The \var{version} argument is optional; if given, the resulting UUID will have its variant and version number set according to RFC 4122, overriding bits in the given \var{hex}, \var{bytes}, -\var{fields}, or \var{int}. +\var{bytes_le}, \var{fields}, or \var{int}. \end{classdesc} \class{UUID} instances have these read-only attributes: \begin{memberdesc}{bytes} -The UUID as a 16-byte string. +The UUID as a 16-byte string (containing the six +integer fields in big-endian byte order). +\end{memberdesc} + +\begin{memberdesc}{bytes_le} +The UUID as a 16-byte string (with \var{time_low}, \var{time_mid}, +and \var{time_hi_version} in little-endian byte order). \end{memberdesc} \begin{memberdesc}{fields} Modified: stackless/branches/release25-maint/Doc/lib/sqlite3/executescript.py ============================================================================== --- stackless/branches/release25-maint/Doc/lib/sqlite3/executescript.py (original) +++ stackless/branches/release25-maint/Doc/lib/sqlite3/executescript.py Wed Sep 13 15:19:16 2006 @@ -17,7 +17,7 @@ insert into book(title, author, published) values ( - 'Dirk Gently''s Holistic Detective Agency + 'Dirk Gently''s Holistic Detective Agency', 'Douglas Adams', 1987 ); Modified: stackless/branches/release25-maint/Doc/ref/ref3.tex ============================================================================== --- stackless/branches/release25-maint/Doc/ref/ref3.tex (original) +++ stackless/branches/release25-maint/Doc/ref/ref3.tex Wed Sep 13 15:19:16 2006 @@ -762,7 +762,7 @@ (call it~\class{C}) of the instance for which the attribute reference was initiated or one of its bases, it is transformed into a bound user-defined method object whose -\member{im_class} attribute is~\class{C} whose \member{im_self} attribute +\member{im_class} attribute is~\class{C} and whose \member{im_self} attribute is the instance. Static method and class method objects are also transformed, as if they had been retrieved from class~\class{C}; see above under ``Classes''. See section~\ref{descriptors} for Modified: stackless/branches/release25-maint/Doc/tut/tut.tex ============================================================================== --- stackless/branches/release25-maint/Doc/tut/tut.tex (original) +++ stackless/branches/release25-maint/Doc/tut/tut.tex Wed Sep 13 15:19:16 2006 @@ -4381,7 +4381,7 @@ makes use of private variables of the base class possible.) Notice that code passed to \code{exec}, \code{eval()} or -\code{evalfile()} does not consider the classname of the invoking +\code{execfile()} does not consider the classname of the invoking class to be the current class; this is similar to the effect of the \code{global} statement, the effect of which is likewise restricted to code that is byte-compiled together. The same restriction applies to Modified: stackless/branches/release25-maint/Doc/whatsnew/whatsnew25.tex ============================================================================== --- stackless/branches/release25-maint/Doc/whatsnew/whatsnew25.tex (original) +++ stackless/branches/release25-maint/Doc/whatsnew/whatsnew25.tex Wed Sep 13 15:19:16 2006 @@ -683,22 +683,22 @@ The lock is acquired before the block is executed and always released once the block is complete. -The \module{decimal} module's contexts, which encapsulate the desired -precision and rounding characteristics for computations, provide a -\method{context_manager()} method for getting a context manager: +The new \function{localcontext()} function in the \module{decimal} module +makes it easy to save and restore the current decimal context, which +encapsulates the desired precision and rounding characteristics for +computations: \begin{verbatim} -import decimal +from decimal import Decimal, Context, localcontext # Displays with default precision of 28 digits -v1 = decimal.Decimal('578') -print v1.sqrt() +v = Decimal('578') +print v.sqrt() -ctx = decimal.Context(prec=16) -with ctx.context_manager(): +with localcontext(Context(prec=16)): # All code in this block uses a precision of 16 digits. # The original context is restored on exiting the block. - print v1.sqrt() + print v.sqrt() \end{verbatim} \subsection{Writing Context Managers\label{context-managers}} @@ -1115,12 +1115,14 @@ \begin{verbatim} >>> ('http://www.python.org').partition('://') ('http', '://', 'www.python.org') ->>> (u'Subject: a quick question').partition(':') -(u'Subject', u':', u' a quick question') >>> ('file:/usr/share/doc/index.html').partition('://') ('file:/usr/share/doc/index.html', '', '') +>>> (u'Subject: a quick question').partition(':') +(u'Subject', u':', u' a quick question') >>> 'www.python.org'.rpartition('.') ('www.python', '.', 'org') +>>> 'www.python.org'.rpartition(':') +('', '', 'www.python.org') \end{verbatim} (Implemented by Fredrik Lundh following a suggestion by Raymond Hettinger.) Modified: stackless/branches/release25-maint/Include/import.h ============================================================================== --- stackless/branches/release25-maint/Include/import.h (original) +++ stackless/branches/release25-maint/Include/import.h Wed Sep 13 15:19:16 2006 @@ -22,7 +22,7 @@ PyAPI_FUNC(PyObject *) PyImport_ImportModuleEx( char *name, PyObject *globals, PyObject *locals, PyObject *fromlist); #define PyImport_ImportModuleEx(n, g, l, f) \ - PyImport_ImportModuleLevel(n, g, l, f, -1); + PyImport_ImportModuleLevel(n, g, l, f, -1) PyAPI_FUNC(PyObject *) PyImport_Import(PyObject *name); PyAPI_FUNC(PyObject *) PyImport_ReloadModule(PyObject *m); 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 13 15:19:16 2006 @@ -23,10 +23,10 @@ #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "2.5c1" +#define PY_VERSION "2.5c2" /* Subversion Revision number of this file (not of the repository) */ #define PY_PATCHLEVEL_REVISION "$Revision$" Modified: stackless/branches/release25-maint/Lib/bsddb/test/test_basics.py ============================================================================== --- stackless/branches/release25-maint/Lib/bsddb/test/test_basics.py (original) +++ stackless/branches/release25-maint/Lib/bsddb/test/test_basics.py Wed Sep 13 15:19:16 2006 @@ -697,7 +697,7 @@ for log in logs: if verbose: print 'log file: ' + log - if db.version >= (4,2): + if db.version() >= (4,2): logs = self.env.log_archive(db.DB_ARCH_REMOVE) assert not logs Modified: stackless/branches/release25-maint/Lib/ctypes/test/test_bitfields.py ============================================================================== --- stackless/branches/release25-maint/Lib/ctypes/test/test_bitfields.py (original) +++ stackless/branches/release25-maint/Lib/ctypes/test/test_bitfields.py Wed Sep 13 15:19:16 2006 @@ -215,5 +215,14 @@ ("b", c_ubyte, 4)] self.failUnlessEqual(sizeof(X), sizeof(c_byte)) + def test_anon_bitfields(self): + # anonymous bit-fields gave a strange error message + class X(Structure): + _fields_ = [("a", c_byte, 4), + ("b", c_ubyte, 4)] + class Y(Structure): + _anonymous_ = ["_"] + _fields_ = [("_", X)] + if __name__ == "__main__": unittest.main() Modified: stackless/branches/release25-maint/Lib/ctypes/test/test_cast.py ============================================================================== --- stackless/branches/release25-maint/Lib/ctypes/test/test_cast.py (original) +++ stackless/branches/release25-maint/Lib/ctypes/test/test_cast.py Wed Sep 13 15:19:16 2006 @@ -57,5 +57,21 @@ c_int() self.failUnlessEqual(p[:4], [1, 2, 96, 4]) + def test_char_p(self): + # This didn't work: bad argument to internal function + s = c_char_p("hiho") + self.failUnlessEqual(cast(cast(s, c_void_p), c_char_p).value, + "hiho") + + try: + c_wchar_p + except NameError: + pass + else: + def test_wchar_p(self): + s = c_wchar_p("hiho") + self.failUnlessEqual(cast(cast(s, c_void_p), c_wchar_p).value, + "hiho") + if __name__ == "__main__": unittest.main() Modified: stackless/branches/release25-maint/Lib/decimal.py ============================================================================== --- stackless/branches/release25-maint/Lib/decimal.py (original) +++ stackless/branches/release25-maint/Lib/decimal.py Wed Sep 13 15:19:16 2006 @@ -131,7 +131,7 @@ 'ROUND_FLOOR', 'ROUND_UP', 'ROUND_HALF_DOWN', # Functions for manipulating contexts - 'setcontext', 'getcontext' + 'setcontext', 'getcontext', 'localcontext' ] import copy as _copy @@ -458,6 +458,49 @@ del threading, local # Don't contaminate the namespace +def localcontext(ctx=None): + """Return a context manager for a copy of the supplied context + + Uses a copy of the current context if no context is specified + The returned context manager creates a local decimal context + in a with statement: + def sin(x): + with localcontext() as ctx: + ctx.prec += 2 + # Rest of sin calculation algorithm + # uses a precision 2 greater than normal + return +s # Convert result to normal precision + + def sin(x): + with localcontext(ExtendedContext): + # Rest of sin calculation algorithm + # uses the Extended Context from the + # General Decimal Arithmetic Specification + return +s # Convert result to normal context + + """ + # The string below can't be included in the docstring until Python 2.6 + # as the doctest module doesn't understand __future__ statements + """ + >>> from __future__ import with_statement + >>> print getcontext().prec + 28 + >>> with localcontext(): + ... ctx = getcontext() + ... ctx.prec() += 2 + ... print ctx.prec + ... + 30 + >>> with localcontext(ExtendedContext): + ... print getcontext().prec + ... + 9 + >>> print getcontext().prec + 28 + """ + if ctx is None: ctx = getcontext() + return _ContextManager(ctx) + ##### Decimal class ########################################### @@ -2173,23 +2216,14 @@ del name, val, globalname, rounding_functions -class ContextManager(object): - """Helper class to simplify Context management. - - Sample usage: - - with decimal.ExtendedContext: - s = ... - return +s # Convert result to normal precision - - with decimal.getcontext() as ctx: - ctx.prec += 2 - s = ... - return +s +class _ContextManager(object): + """Context manager class to support localcontext(). + Sets a copy of the supplied context in __enter__() and restores + the previous decimal context in __exit__() """ def __init__(self, new_context): - self.new_context = new_context + self.new_context = new_context.copy() def __enter__(self): self.saved_context = getcontext() setcontext(self.new_context) @@ -2248,9 +2282,6 @@ s.append('traps=[' + ', '.join([t.__name__ for t, v in self.traps.items() if v]) + ']') return ', '.join(s) + ')' - def get_manager(self): - return ContextManager(self.copy()) - def clear_flags(self): """Reset all flags to zero""" for flag in self.flags: Modified: stackless/branches/release25-maint/Lib/doctest.py ============================================================================== --- stackless/branches/release25-maint/Lib/doctest.py (original) +++ stackless/branches/release25-maint/Lib/doctest.py Wed Sep 13 15:19:16 2006 @@ -1561,7 +1561,7 @@ - test: the DocTest object being run - - excample: the Example object that failed + - example: the Example object that failed - got: the actual output """ @@ -1580,7 +1580,7 @@ - test: the DocTest object being run - - excample: the Example object that failed + - example: the Example object that failed - exc_info: the exception info """ 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 13 15:19:16 2006 @@ -1,3 +1,8 @@ +What's New in IDLE 1.2c2? +========================= + +*Release date: 12-SEP-2006* + What's New in IDLE 1.2c1? ========================= 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 13 15:19:16 2006 @@ -1 +1 @@ -IDLE_VERSION = "1.2c1" +IDLE_VERSION = "1.2c2" Modified: stackless/branches/release25-maint/Lib/inspect.py ============================================================================== --- stackless/branches/release25-maint/Lib/inspect.py (original) +++ stackless/branches/release25-maint/Lib/inspect.py Wed Sep 13 15:19:16 2006 @@ -403,6 +403,7 @@ return os.path.normcase(os.path.abspath(_filename)) modulesbyfile = {} +_filesbymodname = {} def getmodule(object, _filename=None): """Return the module an object was defined in, or None if not found.""" @@ -410,19 +411,32 @@ return object if hasattr(object, '__module__'): return sys.modules.get(object.__module__) + # Try the filename to modulename cache + if _filename is not None and _filename in modulesbyfile: + return sys.modules.get(modulesbyfile[_filename]) + # Try the cache again with the absolute file name try: file = getabsfile(object, _filename) except TypeError: return None if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) - for module in sys.modules.values(): + # Update the filename to module name cache and check yet again + # Copy sys.modules in order to cope with changes while iterating + for modname, module in sys.modules.items(): if ismodule(module) and hasattr(module, '__file__'): + f = module.__file__ + if f == _filesbymodname.get(modname, None): + # Have already mapped this module, so skip it + continue + _filesbymodname[modname] = f f = getabsfile(module) + # Always map to the name the module knows itself by modulesbyfile[f] = modulesbyfile[ os.path.realpath(f)] = module.__name__ if file in modulesbyfile: return sys.modules.get(modulesbyfile[file]) + # Check the main module main = sys.modules['__main__'] if not hasattr(object, '__name__'): return None @@ -430,6 +444,7 @@ mainobject = getattr(main, object.__name__) if mainobject is object: return main + # Check builtins builtin = sys.modules['__builtin__'] if hasattr(builtin, object.__name__): builtinobject = getattr(builtin, object.__name__) @@ -444,7 +459,7 @@ in the file and the line number indexes a line in that list. An IOError is raised if the source code cannot be retrieved.""" file = getsourcefile(object) or getfile(object) - module = getmodule(object) + module = getmodule(object, file) if module: lines = linecache.getlines(file, module.__dict__) else: Modified: stackless/branches/release25-maint/Lib/logging/config.py ============================================================================== --- stackless/branches/release25-maint/Lib/logging/config.py (original) +++ stackless/branches/release25-maint/Lib/logging/config.py Wed Sep 13 15:19:16 2006 @@ -27,7 +27,7 @@ To use, simply 'import logging' and log away! """ -import sys, logging, logging.handlers, string, socket, struct, os, traceback +import sys, logging, logging.handlers, string, socket, struct, os, traceback, types try: import thread Modified: stackless/branches/release25-maint/Lib/sgmllib.py ============================================================================== --- stackless/branches/release25-maint/Lib/sgmllib.py (original) +++ stackless/branches/release25-maint/Lib/sgmllib.py Wed Sep 13 15:19:16 2006 @@ -29,12 +29,7 @@ shorttagopen = re.compile('<[a-zA-Z][-.a-zA-Z0-9]*/') shorttag = re.compile('<([a-zA-Z][-.a-zA-Z0-9]*)/([^/]*)/') piclose = re.compile('>') -starttag = re.compile(r'<[a-zA-Z][-_.:a-zA-Z0-9]*\s*(' - r'\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)(\s*=\s*' - r'(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~@]' - r'[][\-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*(?=[\s>/<])))?' - r')*\s*/?\s*(?=[<>])') -endtag = re.compile(r'])') +endbracket = re.compile('[<>]') tagfind = re.compile('[a-zA-Z][-_.a-zA-Z0-9]*') attrfind = re.compile( r'\s*([a-zA-Z_][-:.a-zA-Z_0-9]*)(\s*=\s*' @@ -254,10 +249,14 @@ self.finish_shorttag(tag, data) self.__starttag_text = rawdata[start_pos:match.end(1) + 1] return k - match = starttag.match(rawdata, i) + # XXX The following should skip matching quotes (' or ") + # As a shortcut way to exit, this isn't so bad, but shouldn't + # be used to locate the actual end of the start tag since the + # < or > characters may be embedded in an attribute value. + match = endbracket.search(rawdata, i+1) if not match: return -1 - j = match.end(0) + j = match.start(0) # Now parse the data between i+1 and j into a tag and attrs attrs = [] if rawdata[i:i+2] == '<>': @@ -306,10 +305,10 @@ # Internal -- parse endtag def parse_endtag(self, i): rawdata = self.rawdata - match = endtag.match(rawdata, i) + match = endbracket.search(rawdata, i+1) if not match: return -1 - j = match.end(0) + j = match.start(0) tag = rawdata[i+2:j].strip().lower() if rawdata[j] == '>': j = j+1 Modified: stackless/branches/release25-maint/Lib/subprocess.py ============================================================================== --- stackless/branches/release25-maint/Lib/subprocess.py (original) +++ stackless/branches/release25-maint/Lib/subprocess.py Wed Sep 13 15:19:16 2006 @@ -1000,14 +1000,10 @@ if errwrite: os.dup2(errwrite, 2) - # Close pipe fds. Make sure we doesn't close the same - # fd more than once. - if p2cread: - os.close(p2cread) - if c2pwrite and c2pwrite not in (p2cread,): - os.close(c2pwrite) - if errwrite and errwrite not in (p2cread, c2pwrite): - os.close(errwrite) + # Close pipe fds. Make sure we don't close the same + # fd more than once, or standard fds. + for fd in set((p2cread, c2pwrite, errwrite))-set((0,1,2)): + if fd: os.close(fd) # Close all other fds, if asked for if close_fds: Modified: stackless/branches/release25-maint/Lib/tarfile.py ============================================================================== --- stackless/branches/release25-maint/Lib/tarfile.py (original) +++ stackless/branches/release25-maint/Lib/tarfile.py Wed Sep 13 15:19:16 2006 @@ -411,9 +411,6 @@ self.buf += self.cmp.flush() if self.mode == "w" and self.buf: - blocks, remainder = divmod(len(self.buf), self.bufsize) - if remainder > 0: - self.buf += NUL * (self.bufsize - remainder) self.fileobj.write(self.buf) self.buf = "" if self.comptype == "gz": Modified: stackless/branches/release25-maint/Lib/test/string_tests.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/string_tests.py (original) +++ stackless/branches/release25-maint/Lib/test/string_tests.py Wed Sep 13 15:19:16 2006 @@ -1069,7 +1069,7 @@ # from raymond's original specification S = 'http://www.python.org' self.checkequal(('http', '://', 'www.python.org'), S, 'rpartition', '://') - self.checkequal(('http://www.python.org', '', ''), S, 'rpartition', '?') + self.checkequal(('', '', 'http://www.python.org'), S, 'rpartition', '?') self.checkequal(('', 'http://', 'www.python.org'), S, 'rpartition', 'http://') self.checkequal(('http://www.python.', 'org', ''), S, 'rpartition', 'org') Modified: stackless/branches/release25-maint/Lib/test/test_codecencodings_cn.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_codecencodings_cn.py (original) +++ stackless/branches/release25-maint/Lib/test/test_codecencodings_cn.py Wed Sep 13 15:19:16 2006 @@ -32,6 +32,7 @@ ("abc\x80\x80\xc1\xc4\xc8", "replace", u"abc\ufffd\u804a\ufffd"), ("abc\x80\x80\xc1\xc4", "ignore", u"abc\u804a"), ("\x83\x34\x83\x31", "strict", None), + (u"\u30fb", "strict", None), ) class Test_GB18030(test_multibytecodec_support.TestBase, unittest.TestCase): @@ -45,6 +46,7 @@ ("abc\x80\x80\xc1\xc4\xc8", "replace", u"abc\ufffd\u804a\ufffd"), ("abc\x80\x80\xc1\xc4", "ignore", u"abc\u804a"), ("abc\x84\x39\x84\x39\xc1\xc4", "replace", u"abc\ufffd\u804a"), + (u"\u30fb", "strict", "\x819\xa79"), ) has_iso10646 = True Modified: stackless/branches/release25-maint/Lib/test/test_contextlib.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_contextlib.py (original) +++ stackless/branches/release25-maint/Lib/test/test_contextlib.py Wed Sep 13 15:19:16 2006 @@ -330,32 +330,6 @@ return True self.boilerPlate(lock, locked) -class DecimalContextTestCase(unittest.TestCase): - - # XXX Somebody should write more thorough tests for this - - def testBasic(self): - ctx = decimal.getcontext() - orig_context = ctx.copy() - try: - ctx.prec = save_prec = decimal.ExtendedContext.prec + 5 - with decimal.ExtendedContext.get_manager(): - self.assertEqual(decimal.getcontext().prec, - decimal.ExtendedContext.prec) - self.assertEqual(decimal.getcontext().prec, save_prec) - try: - with decimal.ExtendedContext.get_manager(): - self.assertEqual(decimal.getcontext().prec, - decimal.ExtendedContext.prec) - 1/0 - except ZeroDivisionError: - self.assertEqual(decimal.getcontext().prec, save_prec) - else: - self.fail("Didn't raise ZeroDivisionError") - finally: - decimal.setcontext(orig_context) - - # This is needed to make the test actually run under regrtest.py! def test_main(): run_suite( Modified: stackless/branches/release25-maint/Lib/test/test_decimal.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_decimal.py (original) +++ stackless/branches/release25-maint/Lib/test/test_decimal.py Wed Sep 13 15:19:16 2006 @@ -23,6 +23,7 @@ you're working through IDLE, you can import this test module and call test_main() with the corresponding argument. """ +from __future__ import with_statement import unittest import glob @@ -1064,6 +1065,32 @@ self.assertNotEqual(id(c.flags), id(d.flags)) self.assertNotEqual(id(c.traps), id(d.traps)) +class WithStatementTest(unittest.TestCase): + # Can't do these as docstrings until Python 2.6 + # as doctest can't handle __future__ statements + + def test_localcontext(self): + # Use a copy of the current context in the block + orig_ctx = getcontext() + with localcontext() as enter_ctx: + set_ctx = getcontext() + final_ctx = getcontext() + self.assert_(orig_ctx is final_ctx, 'did not restore context correctly') + self.assert_(orig_ctx is not set_ctx, 'did not copy the context') + self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context') + + def test_localcontextarg(self): + # Use a copy of the supplied context in the block + orig_ctx = getcontext() + new_ctx = Context(prec=42) + with localcontext(new_ctx) as enter_ctx: + set_ctx = getcontext() + final_ctx = getcontext() + self.assert_(orig_ctx is final_ctx, 'did not restore context correctly') + self.assert_(set_ctx.prec == new_ctx.prec, 'did not set correct context') + self.assert_(new_ctx is not set_ctx, 'did not copy the context') + self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context') + def test_main(arith=False, verbose=None): """ Execute the tests. @@ -1084,6 +1111,7 @@ DecimalPythonAPItests, ContextAPItests, DecimalTest, + WithStatementTest, ] try: Modified: stackless/branches/release25-maint/Lib/test/test_exceptions.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_exceptions.py (original) +++ stackless/branches/release25-maint/Lib/test/test_exceptions.py Wed Sep 13 15:19:16 2006 @@ -185,15 +185,6 @@ def testAttributes(self): # test that exception attributes are happy - try: - str(u'Hello \u00E1') - except Exception, e: - sampleUnicodeEncodeError = e - - try: - unicode('\xff') - except Exception, e: - sampleUnicodeDecodeError = e exceptionList = [ (BaseException, (), {'message' : '', 'args' : ()}), @@ -236,16 +227,16 @@ 'print_file_and_line' : None, 'msg' : 'msgStr', 'filename' : None, 'lineno' : None, 'offset' : None}), (UnicodeError, (), {'message' : '', 'args' : (),}), - (sampleUnicodeEncodeError, - {'message' : '', 'args' : ('ascii', u'Hello \xe1', 6, 7, - 'ordinal not in range(128)'), - 'encoding' : 'ascii', 'object' : u'Hello \xe1', - 'start' : 6, 'reason' : 'ordinal not in range(128)'}), - (sampleUnicodeDecodeError, + (UnicodeEncodeError, ('ascii', u'a', 0, 1, 'ordinal not in range'), + {'message' : '', 'args' : ('ascii', u'a', 0, 1, + 'ordinal not in range'), + 'encoding' : 'ascii', 'object' : u'a', + 'start' : 0, 'reason' : 'ordinal not in range'}), + (UnicodeDecodeError, ('ascii', '\xff', 0, 1, 'ordinal not in range'), {'message' : '', 'args' : ('ascii', '\xff', 0, 1, - 'ordinal not in range(128)'), + 'ordinal not in range'), 'encoding' : 'ascii', 'object' : '\xff', - 'start' : 0, 'reason' : 'ordinal not in range(128)'}), + 'start' : 0, 'reason' : 'ordinal not in range'}), (UnicodeTranslateError, (u"\u3042", 0, 1, "ouch"), {'message' : '', 'args' : (u'\u3042', 0, 1, 'ouch'), 'object' : u'\u3042', 'reason' : 'ouch', @@ -261,18 +252,14 @@ except NameError: pass - for args in exceptionList: - expected = args[-1] + for exc, args, expected in exceptionList: try: - exc = args[0] - if len(args) == 2: - raise exc - else: - raise exc(*args[1]) + raise exc(*args) except BaseException, e: - if (e is not exc and # needed for sampleUnicode errors - type(e) is not exc): + if type(e) is not exc: raise + # Verify module name + self.assertEquals(type(e).__module__, 'exceptions') # Verify no ref leaks in Exc_str() s = str(e) for checkArgName in expected: @@ -317,6 +304,15 @@ return -1 self.assertRaises(RuntimeError, g) + def testUnicodeStrUsage(self): + # Make sure both instances and classes have a str and unicode + # representation. + self.failUnless(str(Exception)) + self.failUnless(unicode(Exception)) + self.failUnless(str(Exception('a'))) + self.failUnless(unicode(Exception(u'a'))) + + def test_main(): run_unittest(ExceptionTests) Modified: stackless/branches/release25-maint/Lib/test/test_fcntl.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_fcntl.py (original) +++ stackless/branches/release25-maint/Lib/test/test_fcntl.py Wed Sep 13 15:19:16 2006 @@ -25,7 +25,7 @@ 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'bsdos2', 'bsdos3', 'bsdos4', - 'openbsd', 'openbsd2', 'openbsd3'): + 'openbsd', 'openbsd2', 'openbsd3', 'openbsd4'): if struct.calcsize('l') == 8: off_t = 'l' pid_t = 'i' Modified: stackless/branches/release25-maint/Lib/test/test_grammar.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_grammar.py (original) +++ stackless/branches/release25-maint/Lib/test/test_grammar.py Wed Sep 13 15:19:16 2006 @@ -825,6 +825,10 @@ verify([ x for x in range(10) if x % 2 if x % 3 ], [1, 5, 7]) verify((x for x in range(10) if x % 2 if x % 3), [1, 5, 7]) +# Verify unpacking single element tuples in listcomp/genexp. +vereq([x for x, in [(4,), (5,), (6,)]], [4, 5, 6]) +vereq(list(x for x, in [(7,), (8,), (9,)]), [7, 8, 9]) + # Test ifelse expressions in various cases def _checkeval(msg, ret): "helper to check that evaluation of expressions is done correctly" Modified: stackless/branches/release25-maint/Lib/test/test_inspect.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_inspect.py (original) +++ stackless/branches/release25-maint/Lib/test/test_inspect.py Wed Sep 13 15:19:16 2006 @@ -178,7 +178,18 @@ self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n') def test_getmodule(self): + # Check actual module + self.assertEqual(inspect.getmodule(mod), mod) + # Check class (uses __module__ attribute) self.assertEqual(inspect.getmodule(mod.StupidGit), mod) + # Check a method (no __module__ attribute, falls back to filename) + self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod) + # Do it again (check the caching isn't broken) + self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod) + # Check a builtin + self.assertEqual(inspect.getmodule(str), sys.modules["__builtin__"]) + # Check filename override + self.assertEqual(inspect.getmodule(None, modfile), mod) def test_getsource(self): self.assertSourceEqual(git.abuse, 29, 39) Modified: stackless/branches/release25-maint/Lib/test/test_itertools.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_itertools.py (original) +++ stackless/branches/release25-maint/Lib/test/test_itertools.py Wed Sep 13 15:19:16 2006 @@ -371,6 +371,7 @@ # test values of n self.assertRaises(TypeError, tee, 'abc', 'invalid') + self.assertRaises(ValueError, tee, [], -1) for n in xrange(5): result = tee('abc', n) self.assertEqual(type(result), tuple) Modified: stackless/branches/release25-maint/Lib/test/test_multibytecodec.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_multibytecodec.py (original) +++ stackless/branches/release25-maint/Lib/test/test_multibytecodec.py Wed Sep 13 15:19:16 2006 @@ -202,6 +202,12 @@ uni = u':hu4:unit\xe9 de famille' self.assertEqual(iso2022jp2.decode('iso2022-jp-2'), uni) + def test_iso2022_jp_g0(self): + self.failIf('\x0e' in u'\N{SOFT HYPHEN}'.encode('iso-2022-jp-2')) + for encoding in ('iso-2022-jp-2004', 'iso-2022-jp-3'): + e = u'\u3406'.encode(encoding) + self.failIf(filter(lambda x: x >= '\x80', e)) + def test_main(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(Test_MultibyteCodec)) Modified: stackless/branches/release25-maint/Lib/test/test_mutants.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_mutants.py (original) +++ stackless/branches/release25-maint/Lib/test/test_mutants.py Wed Sep 13 15:19:16 2006 @@ -91,12 +91,17 @@ self.hashcode = random.randrange(1000000000) def __hash__(self): + return 42 return self.hashcode def __cmp__(self, other): maybe_mutate() # The point of the test. return cmp(self.i, other.i) + def __eq__(self, other): + maybe_mutate() # The point of the test. + return self.i == other.i + def __repr__(self): return "Horrid(%d)" % self.i @@ -132,7 +137,10 @@ while dict1 and len(dict1) == len(dict2): if verbose: print ".", - c = cmp(dict1, dict2) + if random.random() < 0.5: + c = cmp(dict1, dict2) + else: + c = dict1 == dict2 if verbose: print Modified: stackless/branches/release25-maint/Lib/test/test_pep352.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_pep352.py (original) +++ stackless/branches/release25-maint/Lib/test/test_pep352.py Wed Sep 13 15:19:16 2006 @@ -15,8 +15,7 @@ self.failUnless(issubclass(Exception, object)) def verify_instance_interface(self, ins): - for attr in ("args", "message", "__str__", "__unicode__", "__repr__", - "__getitem__"): + for attr in ("args", "message", "__str__", "__repr__", "__getitem__"): self.failUnless(hasattr(ins, attr), "%s missing %s attribute" % (ins.__class__.__name__, attr)) Modified: stackless/branches/release25-maint/Lib/test/test_sgmllib.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_sgmllib.py (original) +++ stackless/branches/release25-maint/Lib/test/test_sgmllib.py Wed Sep 13 15:19:16 2006 @@ -286,21 +286,6 @@ ('codepoint', 'convert', 42), ]) - def test_attr_values_quoted_markup(self): - """Multi-line and markup in attribute values""" - self.check_events("""text""", - [("starttag", "a", [("title", "foo\n
bar")]), - ("data", "text"), - ("endtag", "a")]) - self.check_events("""text""", - [("starttag", "a", [("title", "less < than")]), - ("data", "text"), - ("endtag", "a")]) - self.check_events("""text""", - [("starttag", "a", [("title", "greater > than")]), - ("data", "text"), - ("endtag", "a")]) - def test_attr_funky_names(self): self.check_events("""""", [ ("starttag", "a", [("a.b", "v"), ("c:d", "v"), ("e-f", "v")]), @@ -376,6 +361,19 @@ ('decl', 'DOCTYPE doc []'), ]) + def test_read_chunks(self): + # SF bug #1541697, this caused sgml parser to hang + # Just verify this code doesn't cause a hang. + CHUNK = 1024 # increasing this to 8212 makes the problem go away + + f = open(test_support.findfile('sgml_input.html')) + fp = sgmllib.SGMLParser() + while 1: + data = f.read(CHUNK) + fp.feed(data) + if len(data) != CHUNK: + break + # XXX These tests have been disabled by prefixing their names with # an underscore. The first two exercise outstanding bugs in the # sgmllib module, and the third exhibits questionable behavior Modified: stackless/branches/release25-maint/Lib/test/test_subprocess.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_subprocess.py (original) +++ stackless/branches/release25-maint/Lib/test/test_subprocess.py Wed Sep 13 15:19:16 2006 @@ -234,6 +234,12 @@ stripped = remove_stderr_debug_decorations(output) self.assertEqual(stripped, "appleorange") + def test_stdout_filedes_of_stdout(self): + # stdout is set to 1 (#1531862). + cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), '.\n'))" + rc = subprocess.call([sys.executable, "-c", cmd], stdout=1) + self.assertEquals(rc, 2) + def test_cwd(self): tmpdir = os.getenv("TEMP", "/tmp") # We cannot use os.path.realpath to canonicalize the path, Modified: stackless/branches/release25-maint/Lib/test/test_tarfile.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_tarfile.py (original) +++ stackless/branches/release25-maint/Lib/test/test_tarfile.py Wed Sep 13 15:19:16 2006 @@ -324,6 +324,27 @@ class WriteStreamTest(WriteTest): sep = '|' + def test_padding(self): + self.dst.close() + + if self.comp == "gz": + f = gzip.GzipFile(self.dstname) + s = f.read() + f.close() + elif self.comp == "bz2": + f = bz2.BZ2Decompressor() + s = file(self.dstname).read() + s = f.decompress(s) + self.assertEqual(len(f.unused_data), 0, "trailing data") + else: + f = file(self.dstname) + s = f.read() + f.close() + + self.assertEqual(s.count("\0"), tarfile.RECORDSIZE, + "incorrect zero padding") + + class WriteGNULongTest(unittest.TestCase): """This testcase checks for correct creation of GNU Longname and Longlink extensions. Modified: stackless/branches/release25-maint/Lib/test/test_tempfile.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_tempfile.py (original) +++ stackless/branches/release25-maint/Lib/test/test_tempfile.py Wed Sep 13 15:19:16 2006 @@ -27,7 +27,7 @@ # number of files that can be opened at one time (see ulimit -n) if sys.platform == 'mac': TEST_FILES = 32 -elif sys.platform == 'openbsd3': +elif sys.platform in ('openbsd3', 'openbsd4'): TEST_FILES = 48 else: TEST_FILES = 100 Modified: stackless/branches/release25-maint/Lib/test/test_unicode.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_unicode.py (original) +++ stackless/branches/release25-maint/Lib/test/test_unicode.py Wed Sep 13 15:19:16 2006 @@ -92,6 +92,10 @@ "\\xfe\\xff'") testrepr = repr(u''.join(map(unichr, xrange(256)))) self.assertEqual(testrepr, latin1repr) + # Test repr works on wide unicode escapes without overflow. + self.assertEqual(repr(u"\U00010000" * 39 + u"\uffff" * 4096), + repr(u"\U00010000" * 39 + u"\uffff" * 4096)) + def test_count(self): string_tests.CommonTest.test_count(self) Modified: stackless/branches/release25-maint/Lib/test/test_urllib2.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_urllib2.py (original) +++ stackless/branches/release25-maint/Lib/test/test_urllib2.py Wed Sep 13 15:19:16 2006 @@ -46,6 +46,69 @@ self.assertEquals(urllib2.parse_http_list(string), list) +def test_request_headers_dict(): + """ + The Request.headers dictionary is not a documented interface. It should + stay that way, because the complete set of headers are only accessible + through the .get_header(), .has_header(), .header_items() interface. + However, .headers pre-dates those methods, and so real code will be using + the dictionary. + + The introduction in 2.4 of those methods was a mistake for the same reason: + code that previously saw all (urllib2 user)-provided headers in .headers + now sees only a subset (and the function interface is ugly and incomplete). + A better change would have been to replace .headers dict with a dict + subclass (or UserDict.DictMixin instance?) that preserved the .headers + interface and also provided access to the "unredirected" headers. It's + probably too late to fix that, though. + + + Check .capitalize() case normalization: + + >>> url = "http://example.com" + >>> Request(url, headers={"Spam-eggs": "blah"}).headers["Spam-eggs"] + 'blah' + >>> Request(url, headers={"spam-EggS": "blah"}).headers["Spam-eggs"] + 'blah' + + Currently, Request(url, "Spam-eggs").headers["Spam-Eggs"] raises KeyError, + but that could be changed in future. + + """ + +def test_request_headers_methods(): + """ + Note the case normalization of header names here, to .capitalize()-case. + This should be preserved for backwards-compatibility. (In the HTTP case, + normalization to .title()-case is done by urllib2 before sending headers to + httplib). + + >>> url = "http://example.com" + >>> r = Request(url, headers={"Spam-eggs": "blah"}) + >>> r.has_header("Spam-eggs") + True + >>> r.header_items() + [('Spam-eggs', 'blah')] + >>> r.add_header("Foo-Bar", "baz") + >>> items = r.header_items() + >>> items.sort() + >>> items + [('Foo-bar', 'baz'), ('Spam-eggs', 'blah')] + + Note that e.g. r.has_header("spam-EggS") is currently False, and + r.get_header("spam-EggS") returns None, but that could be changed in + future. + + >>> r.has_header("Not-there") + False + >>> print r.get_header("Not-there") + None + >>> r.get_header("Not-there", "default") + 'default' + + """ + + def test_password_manager(self): """ >>> mgr = urllib2.HTTPPasswordMgr() @@ -676,11 +739,11 @@ r = MockResponse(200, "OK", {}, "") newreq = h.do_request_(req) if data is None: # GET - self.assert_("Content-Length" not in req.unredirected_hdrs) - self.assert_("Content-Type" not in req.unredirected_hdrs) + self.assert_("Content-length" not in req.unredirected_hdrs) + self.assert_("Content-type" not in req.unredirected_hdrs) else: # POST - self.assertEqual(req.unredirected_hdrs["Content-Length"], "0") - self.assertEqual(req.unredirected_hdrs["Content-Type"], + self.assertEqual(req.unredirected_hdrs["Content-length"], "0") + self.assertEqual(req.unredirected_hdrs["Content-type"], "application/x-www-form-urlencoded") # XXX the details of Host could be better tested self.assertEqual(req.unredirected_hdrs["Host"], "example.com") @@ -692,8 +755,8 @@ req.add_unredirected_header("Host", "baz") req.add_unredirected_header("Spam", "foo") newreq = h.do_request_(req) - self.assertEqual(req.unredirected_hdrs["Content-Length"], "foo") - self.assertEqual(req.unredirected_hdrs["Content-Type"], "bar") + self.assertEqual(req.unredirected_hdrs["Content-length"], "foo") + self.assertEqual(req.unredirected_hdrs["Content-type"], "bar") self.assertEqual(req.unredirected_hdrs["Host"], "baz") self.assertEqual(req.unredirected_hdrs["Spam"], "foo") @@ -847,7 +910,7 @@ 407, 'Proxy-Authenticate: Basic realm="%s"\r\n\r\n' % realm) opener.add_handler(auth_handler) opener.add_handler(http_handler) - self._test_basic_auth(opener, auth_handler, "Proxy-Authorization", + self._test_basic_auth(opener, auth_handler, "Proxy-authorization", realm, http_handler, password_manager, "http://acme.example.com:3128/protected", "proxy.example.com:3128", Modified: stackless/branches/release25-maint/Lib/test/test_uuid.py ============================================================================== --- stackless/branches/release25-maint/Lib/test/test_uuid.py (original) +++ stackless/branches/release25-maint/Lib/test/test_uuid.py Wed Sep 13 15:19:16 2006 @@ -429,7 +429,7 @@ # Make sure the generated UUIDs are actually unique. uuids = {} - for u in [uuid.uuid1() for i in range(1000)]: + for u in [uuid.uuid4() for i in range(1000)]: uuids[u] = 1 equal(len(uuids.keys()), 1000) Modified: stackless/branches/release25-maint/Lib/urllib2.py ============================================================================== --- stackless/branches/release25-maint/Lib/urllib2.py (original) +++ stackless/branches/release25-maint/Lib/urllib2.py Wed Sep 13 15:19:16 2006 @@ -263,11 +263,11 @@ def add_header(self, key, val): # useful for something like authentication - self.headers[key.title()] = val + self.headers[key.capitalize()] = val def add_unredirected_header(self, key, val): # will not be added to a redirected request - self.unredirected_hdrs[key.title()] = val + self.unredirected_hdrs[key.capitalize()] = val def has_header(self, header_name): return (header_name in self.headers or @@ -286,7 +286,7 @@ class OpenerDirector: def __init__(self): client_version = "Python-urllib/%s" % __version__ - self.addheaders = [('User-Agent', client_version)] + self.addheaders = [('User-agent', client_version)] # manage the individual handlers self.handlers = [] self.handle_open = {} @@ -675,7 +675,7 @@ if user and password: user_pass = '%s:%s' % (unquote(user), unquote(password)) creds = base64.encodestring(user_pass).strip() - req.add_header('Proxy-Authorization', 'Basic ' + creds) + req.add_header('Proxy-authorization', 'Basic ' + creds) hostport = unquote(hostport) req.set_proxy(hostport, proxy_type) if orig_type == proxy_type: @@ -819,7 +819,7 @@ class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler): - auth_header = 'Proxy-Authorization' + auth_header = 'Proxy-authorization' def http_error_407(self, req, fp, code, msg, headers): # http_error_auth_reqed requires that there is no userinfo component in @@ -1022,20 +1022,20 @@ if request.has_data(): # POST data = request.get_data() - if not request.has_header('Content-Type'): + if not request.has_header('Content-type'): request.add_unredirected_header( - 'Content-Type', + 'Content-type', 'application/x-www-form-urlencoded') - if not request.has_header('Content-Length'): + if not request.has_header('Content-length'): request.add_unredirected_header( - 'Content-Length', '%d' % len(data)) + 'Content-length', '%d' % len(data)) scheme, sel = splittype(request.get_selector()) sel_host, sel_path = splithost(sel) if not request.has_header('Host'): request.add_unredirected_header('Host', sel_host or host) for name, value in self.parent.addheaders: - name = name.title() + name = name.capitalize() if not request.has_header(name): request.add_unredirected_header(name, value) @@ -1067,6 +1067,8 @@ # So make sure the connection gets closed after the (only) # request. headers["Connection"] = "close" + headers = dict( + (name.title(), val) for name, val in headers.items()) try: h.request(req.get_method(), req.get_selector(), req.data, headers) r = h.getresponse() @@ -1217,7 +1219,7 @@ modified = email.Utils.formatdate(stats.st_mtime, usegmt=True) mtype = mimetypes.guess_type(file)[0] headers = mimetools.Message(StringIO( - 'Content-Type: %s\nContent-Length: %d\nLast-Modified: %s\n' % + 'Content-type: %s\nContent-length: %d\nLast-modified: %s\n' % (mtype or 'text/plain', size, modified))) if host: host, port = splitport(host) @@ -1272,9 +1274,9 @@ headers = "" mtype = mimetypes.guess_type(req.get_full_url())[0] if mtype: - headers += "Content-Type: %s\n" % mtype + headers += "Content-type: %s\n" % mtype if retrlen is not None and retrlen >= 0: - headers += "Content-Length: %d\n" % retrlen + headers += "Content-length: %d\n" % retrlen sf = StringIO(headers) headers = mimetools.Message(sf) return addinfourl(fp, headers, req.get_full_url()) Modified: stackless/branches/release25-maint/Lib/uuid.py ============================================================================== --- stackless/branches/release25-maint/Lib/uuid.py (original) +++ stackless/branches/release25-maint/Lib/uuid.py Wed Sep 13 15:19:16 2006 @@ -488,8 +488,8 @@ # 0x01b21dd213814000 is the number of 100-ns intervals between the # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. timestamp = int(nanoseconds/100) + 0x01b21dd213814000L - if timestamp == _last_timestamp: - timestamp += 1 + if timestamp <= _last_timestamp: + timestamp = _last_timestamp + 1 _last_timestamp = timestamp if clock_seq is None: import random Modified: stackless/branches/release25-maint/Mac/README ============================================================================== --- stackless/branches/release25-maint/Mac/README (original) +++ stackless/branches/release25-maint/Mac/README Wed Sep 13 15:19:16 2006 @@ -75,7 +75,7 @@ This directory contains a Makefile that will create a couple of python-related applications (fullblown OSX .app applications, that is) in -"/Applications/MacPython 2.3", and a hidden helper application Python.app +"/Applications/MacPython 2.5", and a hidden helper application Python.app inside the Python.framework, and unix tools "python" and "pythonw" into /usr/local/bin. In addition it has a target "installmacsubtree" that installs the relevant portions of the Mac subtree into the Python.framework. @@ -90,20 +90,16 @@ 3. make install This sequence will put the framework in /Library/Framework/Python.framework, -the applications in /Applications/MacPython 2.5 and the unix tools in +the applications in "/Applications/MacPython 2.5" and the unix tools in /usr/local/bin. Installing in another place, for instance $HOME/Library/Frameworks if you have no admin privileges on your machine, has only been tested very lightly. This can be done by configuring with --enable-framework=$HOME/Library/Frameworks. -The other two directories, /Applications/MacPython-2.3 and /usr/local/bin, will -then also be deposited in $HOME. This is sub-optimal for the unix tools, which -you would want in $HOME/bin, but there is no easy way to fix this right now. - -Note that there are no references to the actual locations in the code or -resource files, so you are free to move things around afterwards. For example, -you could use --enable-framework=/tmp/newversion/Library/Frameworks and use -/tmp/newversion as the basis for an installer or something. +The other two directories, "/Applications/MacPython 2.5" and /usr/local/bin, +will then also be deposited in $HOME. This is sub-optimal for the unix tools, +which you would want in $HOME/bin, but there is no easy way to fix this right +now. If you want to install some part, but not all, read the main Makefile. The frameworkinstall is composed of a couple of sub-targets that install the @@ -111,7 +107,7 @@ There is an extra target frameworkinstallextras that is not part of the normal frameworkinstall which installs the Demo and Tools directories -into /Applications/MacPython-2.3, this is useful for binary distributions. +into "/Applications/MacPython 2.5", this is useful for binary distributions. What do all these programs do? =============================== Modified: stackless/branches/release25-maint/Misc/ACKS ============================================================================== --- stackless/branches/release25-maint/Misc/ACKS (original) +++ stackless/branches/release25-maint/Misc/ACKS Wed Sep 13 15:19:16 2006 @@ -365,6 +365,7 @@ Soren Larsen Piers Lauder Ben Laurie +Simon Law Chris Lawrence Christopher Lee Inyeol Lee Modified: stackless/branches/release25-maint/Misc/NEWS ============================================================================== --- stackless/branches/release25-maint/Misc/NEWS (original) +++ stackless/branches/release25-maint/Misc/NEWS Wed Sep 13 15:19:16 2006 @@ -4,6 +4,125 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 2.5 release candidate 2? +============================================= + +*Release date: 12-SEP-2006* + +Core and builtins +----------------- + +- Make _PyGILState_NoteThreadState() static, it was not used anywhere + outside of pystate.c and should not be necessary. + +- Bug #1551432: Exceptions do not define an explicit __unicode__ method. This + allows calling unicode() on exceptions classes directly to succeed. + +- Bug #1542051: Exceptions now correctly call PyObject_GC_UnTrack. + Also make sure that every exception class has __module__ set to + 'exceptions'. + +- Bug #1550983: emit better error messages for erroneous relative + imports (if not in package and if beyond toplevel package). + +- Overflow checking code in integer division ran afoul of new gcc + optimizations. Changed to be more standard-conforming. + +- Patch #1541585: fix buffer overrun when performing repr() on + a unicode string in a build with wide unicode (UCS-4) support. + +- Patch #1546288: fix seg fault in dict_equal due to ref counting bug. + +- The return tuple from str.rpartition(sep) is (tail, sep, head) where + head is the original string if sep was not found. + +- Bug #1520864: unpacking singleton tuples in list comprehensions and + generator expressions (x for x, in ... ) works again. Fixing this problem + required changing the .pyc magic number. This means that .pyc files + generated before 2.5c2 will be regenerated. + + +Library +------- + +- Reverted patch #1504333 because it introduced an infinite loop. + +- Patch #1553314: Fix the inspect.py slowdown that was hurting IPython & SAGE + by adding smarter caching in inspect.getmodule(). + +- Fix missing import of the types module in logging.config. + +- Patch #1550886: Fix decimal module context management implementation + to match the localcontext() example from PEP 343. + +- Bug #1541863: uuid.uuid1 failed to generate unique identifiers + on systems with low clock resolution. + +- Bug #1543303, patch #1543897: remove NUL padding from tarfiles. + +- Bug #1531862: Do not close standard file descriptors in subprocess. + + +Extension Modules +----------------- + +- Fix bugs in ctypes: + - anonymous structure fields that have a bit-width specified did not work + - cast function did not accept c_char_p or c_wchar_p instances as first arg + +- Bug #1551427: fix a wrong NULL pointer check in the win32 version + of os.urandom(). + +- Bug #1548092: fix curses.tparm seg fault on invalid input. + +- Bug #1550714: fix SystemError from itertools.tee on negative value for n. + +- Fixed a few bugs on cjkcodecs: + - gbk and gb18030 codec now handle U+30FB KATAKANA MIDDLE DOT correctly. + - iso2022_jp_2 codec now encodes into G0 for KS X 1001, GB2312 + codepoints to conform the standard. + - iso2022_jp_3 and iso2022_jp_2004 codec can encode JIS X 0213:2 + codepoints now. + +Tests +----- + +- Fix bsddb test_basics.test06_Transactions to check the version + number properly. + + +Documentation +------------- + +- Bug #1541682: Fix example in the "Refcount details" API docs. + Additionally, remove a faulty example showing PySequence_SetItem applied + to a newly created list object and add notes that this isn't a good idea. + + +Tools +----- + +- Bug #1546372: Fixed small bugglet in pybench that caused a missing + file not to get reported properly. + + +Build +----- + +- Patch #1540470, for OpenBSD 4.0. + +- Patch #1545507: Exclude ctypes package in Win64 MSI file. + +- Fix OpenSSL debug build process. + + +C API +----- + +- Bug #1542693: remove semi-colon at end of PyImport_ImportModuleEx macro + so it can be used as an expression. + + What's New in Python 2.5 release candidate 1? ============================================= @@ -12,6 +131,10 @@ Core and builtins ----------------- +- Fix infinite recursion when subclassing long and overriding __hash__. + +- Fix concatenation (+=) of long strings. + - Unicode objects will no longer raise an exception when being compared equal or unequal to a string and a UnicodeDecodeError exception occurs, e.g. as result of a decoding failure. @@ -80,7 +203,7 @@ - The __repr__ method of a NULL ctypes.py_object() no longer raises an exception. -- uuid.UUID now has a bytes_le attribute. This returns the UUID in +- uuid.UUID now has a bytes_le attribute. This returns the UUID in little-endian byte order for Windows. In addition, uuid.py gained some workarounds for clocks with low resolution, to stop the code yielding duplicate UUIDs. @@ -108,6 +231,8 @@ Extension Modules ----------------- +- Ignore data that arrives before the opening start tag in C etree. + - Patch #1511317: don't crash on invalid hostname (alias) info. - Patch #1535500: fix segfault in BZ2File.writelines and make sure it @@ -167,10 +292,6 @@ is always 1 (normal) or 0 (if the specified thread wasn't found). -Mac ---- - - What's New in Python 2.5 beta 3? ================================ @@ -243,7 +364,7 @@ - Bug #1002398: The documentation for os.path.sameopenfile now correctly refers to file descriptors, not file objects. -- The renaming of the xml package to xmlcore, and the import hackery done +- The renaming of the xml package to xmlcore, and the import hackery done to make it appear at both names, has been removed. Bug #1511497, #1513611, and probably others. @@ -261,8 +382,8 @@ - Bug #978833: Really close underlying socket in _socketobject.close. -- Bug #1459963: urllib and urllib2 now normalize HTTP header names correctly - with title(). +- Bug #1459963: urllib and urllib2 now normalize HTTP header names with + title(). - Patch #1525766: In pkgutil.walk_packages, correctly pass the onerror callback to recursive calls and call it with the failing package name. 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 13 15:19:16 2006 @@ -33,7 +33,7 @@ ################################# %define name python -%define version 2.5c1 +%define version 2.5c2 %define libvers 2.5 %define release 1pydotorg %define __prefix /usr @@ -52,7 +52,7 @@ Name: %{name}%{binsuffix} Version: %{version} Release: %{release} -Copyright: Modified CNRI Open Source License +License: Python Software Foundation Group: Development/Languages Source: Python-%{version}.tar.bz2 %if %{include_docs} @@ -239,14 +239,16 @@ # REPLACE PATH IN PYDOC if [ ! -z "%{binsuffix}" ] then - ( - cd $RPM_BUILD_ROOT%{__prefix}/bin - mv pydoc pydoc.old - sed 's|#!.*|#!%{__prefix}/bin/env python'%{binsuffix}'|' \ - pydoc.old >pydoc - chmod 755 pydoc - rm -f pydoc.old - ) + for file in pydoc python-config; do + ( + cd $RPM_BUILD_ROOT%{__prefix}/bin + mv "$file" "$file".old + sed 's|#!.*|#!%{__prefix}/bin/env python'%{binsuffix}'|' \ + "$file".old >"$file" + chmod 755 "$file" + rm -f "$file".old + ) + done fi # add the binsuffix @@ -255,8 +257,10 @@ ( cd $RPM_BUILD_ROOT%{__prefix}/bin; rm -f python[0-9a-zA-Z]*; mv -f python python"%{binsuffix}" ) ( cd $RPM_BUILD_ROOT%{__prefix}/man/man1; mv python.1 python%{binsuffix}.1 ) - ( cd $RPM_BUILD_ROOT%{__prefix}/bin; mv -f pydoc pydoc"%{binsuffix}" ) - ( cd $RPM_BUILD_ROOT%{__prefix}/bin; mv -f idle idle"%{binsuffix}" ) + ( cd $RPM_BUILD_ROOT%{__prefix}/bin; mv -f smtpd.py python-smtpd ) + for file in pydoc idle python-config python-smtpd; do + ( cd $RPM_BUILD_ROOT%{__prefix}/bin; mv -f "$file" "$file""%{binsuffix}" ) + done fi ######## @@ -276,13 +280,19 @@ grep -v -e '_tkinter.so$' >mainpkg.files find "$RPM_BUILD_ROOT""%{__prefix}"/bin -type f | sed "s|^${RPM_BUILD_ROOT}|/|" | + grep -v -e '/bin/setup-config%{binsuffix}$' | grep -v -e '/bin/idle%{binsuffix}$' >>mainpkg.files rm -f tools.files find "$RPM_BUILD_ROOT""%{__prefix}"/%{libdirname}/python%{libvers}/idlelib \ "$RPM_BUILD_ROOT""%{__prefix}"/%{libdirname}/python%{libvers}/Tools -type f | + grep -v -e '\.pyc$' -e '\.pyo$' | sed "s|^${RPM_BUILD_ROOT}|/|" >tools.files echo "%{__prefix}"/bin/idle%{binsuffix} >>tools.files +grep '\.py$' tools.files | sed 's/$/c/' | grep -v /idlelib/ >tools.files.tmp +grep '\.py$' tools.files | sed 's/$/o/' | grep -v /idlelib/ >>tools.files.tmp +cat tools.files.tmp >>tools.files +rm tools.files.tmp ###### # Docs @@ -346,7 +356,6 @@ %{__prefix}/%{libdirname}/python%{libvers}/*.txt %{__prefix}/%{libdirname}/python%{libvers}/*.py* %{__prefix}/%{libdirname}/python%{libvers}/pdb.doc -%{__prefix}/%{libdirname}/python%{libvers}/profile.doc %{__prefix}/%{libdirname}/python%{libvers}/curses %{__prefix}/%{libdirname}/python%{libvers}/distutils %{__prefix}/%{libdirname}/python%{libvers}/encodings @@ -355,13 +364,14 @@ %{__prefix}/%{libdirname}/python%{libvers}/test %{__prefix}/%{libdirname}/python%{libvers}/xml %{__prefix}/%{libdirname}/python%{libvers}/email -%{__prefix}/%{libdirname}/python%{libvers}/email/mime %{__prefix}/%{libdirname}/python%{libvers}/sqlite3 %{__prefix}/%{libdirname}/python%{libvers}/compiler %{__prefix}/%{libdirname}/python%{libvers}/bsddb %{__prefix}/%{libdirname}/python%{libvers}/hotshot %{__prefix}/%{libdirname}/python%{libvers}/logging -%{__prefix}/%{libdirname}/python%{libvers}/lib-old +%{__prefix}/%{libdirname}/python%{libvers}/wsgiref +%{__prefix}/%{libdirname}/python%{libvers}/ctypes +%{__prefix}/%{libdirname}/python%{libvers}/wsgiref.egg-info %files devel %defattr(-,root,root) Modified: stackless/branches/release25-maint/Modules/_ctypes/_ctypes.c ============================================================================== --- stackless/branches/release25-maint/Modules/_ctypes/_ctypes.c (original) +++ stackless/branches/release25-maint/Modules/_ctypes/_ctypes.c Wed Sep 13 15:19:16 2006 @@ -672,6 +672,7 @@ return PyInt_FromLong(0); /* NULL pointer */ typedict = PyType_stgdict(type); + assert(typedict); /* Cannot be NULL for pointer types */ /* If we expect POINTER(), but receive a instance, accept it by calling byref(). @@ -3129,6 +3130,13 @@ } ob = PyTuple_GET_ITEM(argtypes, i); dict = PyType_stgdict(ob); + if (dict == NULL) { + /* Cannot happen: _validate_paramflags() + would not accept such an object */ + PyErr_Format(PyExc_RuntimeError, + "NULL stgdict unexpected"); + goto error; + } if (PyString_Check(dict->proto)) { PyErr_Format( PyExc_TypeError, @@ -3726,6 +3734,8 @@ assert(stgdict); /* Cannot be NULL for array object instances */ proto = stgdict->proto; itemdict = PyType_stgdict(proto); + assert(itemdict); /* proto is the item type of the array, a ctypes + type, so this cannot be NULL */ if (itemdict->getfunc == getentry("c")->getfunc) { char *ptr = (char *)self->b_ptr; return PyString_FromStringAndSize(ptr + ilow, len); @@ -4159,6 +4169,9 @@ proto = stgdict->proto; assert(proto); itemdict = PyType_stgdict(proto); + assert(itemdict); /* proto is the item type of the pointer, a ctypes + type, so this cannot be NULL */ + size = itemdict->size; offset = index * itemdict->size; @@ -4194,6 +4207,9 @@ assert(proto); itemdict = PyType_stgdict(proto); + assert(itemdict); /* Cannot be NULL because the itemtype of a pointer + is always a ctypes type */ + size = itemdict->size; offset = index * itemdict->size; @@ -4574,11 +4590,11 @@ if (obj->b_objects == NULL) goto failed; } + Py_XINCREF(obj->b_objects); result->b_objects = obj->b_objects; - if (result->b_objects) { + if (result->b_objects && PyDict_Check(result->b_objects)) { PyObject *index; int rc; - Py_INCREF(obj->b_objects); index = PyLong_FromVoidPtr((void *)src); if (index == NULL) goto failed; Modified: stackless/branches/release25-maint/Modules/_ctypes/stgdict.c ============================================================================== --- stackless/branches/release25-maint/Modules/_ctypes/stgdict.c (original) +++ stackless/branches/release25-maint/Modules/_ctypes/stgdict.c Wed Sep 13 15:19:16 2006 @@ -177,11 +177,11 @@ for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) { PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */ - PyObject *fname, *ftype; + PyObject *fname, *ftype, *bits; CFieldObject *fdescr; CFieldObject *new_descr; /* Convert to PyArg_UnpackTuple... */ - if (!PyArg_ParseTuple(pair, "OO", &fname, &ftype)) { + if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) { Py_DECREF(fieldlist); return -1; } @@ -208,12 +208,12 @@ continue; } new_descr = (CFieldObject *)PyObject_CallObject((PyObject *)&CField_Type, NULL); - assert(new_descr->ob_type == &CField_Type); if (new_descr == NULL) { Py_DECREF(fdescr); Py_DECREF(fieldlist); return -1; } + assert(new_descr->ob_type == &CField_Type); new_descr->size = fdescr->size; new_descr->offset = fdescr->offset + offset; new_descr->index = fdescr->index + index; Modified: stackless/branches/release25-maint/Modules/_cursesmodule.c ============================================================================== --- stackless/branches/release25-maint/Modules/_cursesmodule.c (original) +++ stackless/branches/release25-maint/Modules/_cursesmodule.c Wed Sep 13 15:19:16 2006 @@ -2334,6 +2334,10 @@ } result = tparm(fmt,i1,i2,i3,i4,i5,i6,i7,i8,i9); + if (!result) { + PyErr_SetString(PyCursesError, "tparm() returned NULL"); + return NULL; + } return PyString_FromString(result); } Modified: stackless/branches/release25-maint/Modules/cjkcodecs/_codecs_cn.c ============================================================================== --- stackless/branches/release25-maint/Modules/cjkcodecs/_codecs_cn.c (original) +++ stackless/branches/release25-maint/Modules/cjkcodecs/_codecs_cn.c Wed Sep 13 15:19:16 2006 @@ -15,14 +15,26 @@ #undef hz #endif -#define GBK_PREDECODE(dc1, dc2, assi) \ +/* GBK and GB2312 map differently in few codepoints that are listed below: + * + * gb2312 gbk + * A1A4 U+30FB KATAKANA MIDDLE DOT U+00B7 MIDDLE DOT + * A1AA U+2015 HORIZONTAL BAR U+2014 EM DASH + * A844 undefined U+2015 HORIZONTAL BAR + */ + +#define GBK_DECODE(dc1, dc2, assi) \ if ((dc1) == 0xa1 && (dc2) == 0xaa) (assi) = 0x2014; \ else if ((dc1) == 0xa8 && (dc2) == 0x44) (assi) = 0x2015; \ - else if ((dc1) == 0xa1 && (dc2) == 0xa4) (assi) = 0x00b7; -#define GBK_PREENCODE(code, assi) \ + else if ((dc1) == 0xa1 && (dc2) == 0xa4) (assi) = 0x00b7; \ + else TRYMAP_DEC(gb2312, assi, dc1 ^ 0x80, dc2 ^ 0x80); \ + else TRYMAP_DEC(gbkext, assi, dc1, dc2); + +#define GBK_ENCODE(code, assi) \ if ((code) == 0x2014) (assi) = 0xa1aa; \ else if ((code) == 0x2015) (assi) = 0xa844; \ - else if ((code) == 0x00b7) (assi) = 0xa1a4; + else if ((code) == 0x00b7) (assi) = 0xa1a4; \ + else if ((code) != 0x30fb && TRYMAP_ENC_COND(gbcommon, assi, code)); /* * GB2312 codec @@ -99,8 +111,7 @@ REQUIRE_OUTBUF(2) - GBK_PREENCODE(c, code) - else TRYMAP_ENC(gbcommon, code, c); + GBK_ENCODE(c, code) else return 1; OUT1((code >> 8) | 0x80) @@ -129,9 +140,7 @@ REQUIRE_INBUF(2) - GBK_PREDECODE(c, IN2, **outbuf) - else TRYMAP_DEC(gb2312, **outbuf, c ^ 0x80, IN2 ^ 0x80); - else TRYMAP_DEC(gbkext, **outbuf, c, IN2); + GBK_DECODE(c, IN2, **outbuf) else return 2; NEXT(2, 1) @@ -187,9 +196,7 @@ REQUIRE_OUTBUF(2) - GBK_PREENCODE(c, code) - else TRYMAP_ENC(gbcommon, code, c); - else TRYMAP_ENC(gb18030ext, code, c); + GBK_ENCODE(c, code) else { const struct _gb18030_to_unibmp_ranges *utrrange; @@ -287,9 +294,7 @@ return 4; } - GBK_PREDECODE(c, c2, **outbuf) - else TRYMAP_DEC(gb2312, **outbuf, c ^ 0x80, c2 ^ 0x80); - else TRYMAP_DEC(gbkext, **outbuf, c, c2); + GBK_DECODE(c, c2, **outbuf) else TRYMAP_DEC(gb18030ext, **outbuf, c, c2); else return 2; Modified: stackless/branches/release25-maint/Modules/cjkcodecs/_codecs_iso2022.c ============================================================================== --- stackless/branches/release25-maint/Modules/cjkcodecs/_codecs_iso2022.c (original) +++ stackless/branches/release25-maint/Modules/cjkcodecs/_codecs_iso2022.c Wed Sep 13 15:19:16 2006 @@ -854,7 +854,7 @@ if (coded == MAP_UNMAPPABLE || coded == MAP_MULTIPLE_AVAIL) return coded; else if (coded & 0x8000) - return coded; + return coded & 0x7fff; else return MAP_UNMAPPABLE; } @@ -901,7 +901,7 @@ if (coded == MAP_UNMAPPABLE || coded == MAP_MULTIPLE_AVAIL) return coded; else if (coded & 0x8000) - return coded; + return coded & 0x7fff; else return MAP_UNMAPPABLE; } @@ -992,7 +992,10 @@ /*-*- registry tables -*-*/ -#define REGISTRY_KSX1001 { CHARSET_KSX1001, 1, 2, \ +#define REGISTRY_KSX1001_G0 { CHARSET_KSX1001, 0, 2, \ + ksx1001_init, \ + ksx1001_decoder, ksx1001_encoder } +#define REGISTRY_KSX1001_G1 { CHARSET_KSX1001, 1, 2, \ ksx1001_init, \ ksx1001_decoder, ksx1001_encoder } #define REGISTRY_JISX0201_R { CHARSET_JISX0201_R, 0, 1, \ @@ -1034,7 +1037,7 @@ jisx0213_init, \ jisx0213_2004_2_decoder, \ jisx0213_2004_2_encoder } -#define REGISTRY_GB2312 { CHARSET_GB2312, 1, 2, \ +#define REGISTRY_GB2312 { CHARSET_GB2312, 0, 2, \ gb2312_init, \ gb2312_decoder, gb2312_encoder } #define REGISTRY_CNS11643_1 { CHARSET_CNS11643_1, 1, 2, \ @@ -1054,7 +1057,7 @@ }; static const struct iso2022_designation iso2022_kr_designations[] = { - REGISTRY_KSX1001, REGISTRY_SENTINEL + REGISTRY_KSX1001_G1, REGISTRY_SENTINEL }; CONFIGDEF(kr, 0) @@ -1071,7 +1074,7 @@ CONFIGDEF(jp_1, NO_SHIFT | USE_JISX0208_EXT) static const struct iso2022_designation iso2022_jp_2_designations[] = { - REGISTRY_JISX0208, REGISTRY_JISX0212, REGISTRY_KSX1001, + REGISTRY_JISX0208, REGISTRY_JISX0212, REGISTRY_KSX1001_G0, REGISTRY_GB2312, REGISTRY_JISX0201_R, REGISTRY_JISX0208_O, REGISTRY_ISO8859_1, REGISTRY_ISO8859_7, REGISTRY_SENTINEL }; Modified: stackless/branches/release25-maint/Modules/cjkcodecs/cjkcodecs.h ============================================================================== --- stackless/branches/release25-maint/Modules/cjkcodecs/cjkcodecs.h (original) +++ stackless/branches/release25-maint/Modules/cjkcodecs/cjkcodecs.h Wed Sep 13 15:19:16 2006 @@ -159,29 +159,32 @@ #endif #define _TRYMAP_ENC(m, assi, val) \ - if ((m)->map != NULL && (val) >= (m)->bottom && \ + ((m)->map != NULL && (val) >= (m)->bottom && \ (val)<= (m)->top && ((assi) = (m)->map[(val) - \ (m)->bottom]) != NOCHAR) -#define TRYMAP_ENC(charset, assi, uni) \ +#define TRYMAP_ENC_COND(charset, assi, uni) \ _TRYMAP_ENC(&charset##_encmap[(uni) >> 8], assi, (uni) & 0xff) +#define TRYMAP_ENC(charset, assi, uni) \ + if TRYMAP_ENC_COND(charset, assi, uni) + #define _TRYMAP_DEC(m, assi, val) \ - if ((m)->map != NULL && (val) >= (m)->bottom && \ + ((m)->map != NULL && (val) >= (m)->bottom && \ (val)<= (m)->top && ((assi) = (m)->map[(val) - \ (m)->bottom]) != UNIINV) #define TRYMAP_DEC(charset, assi, c1, c2) \ - _TRYMAP_DEC(&charset##_decmap[c1], assi, c2) + if _TRYMAP_DEC(&charset##_decmap[c1], assi, c2) #define _TRYMAP_ENC_MPLANE(m, assplane, asshi, asslo, val) \ - if ((m)->map != NULL && (val) >= (m)->bottom && \ + ((m)->map != NULL && (val) >= (m)->bottom && \ (val)<= (m)->top && \ ((assplane) = (m)->map[((val) - (m)->bottom)*3]) != 0 && \ (((asshi) = (m)->map[((val) - (m)->bottom)*3 + 1]), 1) && \ (((asslo) = (m)->map[((val) - (m)->bottom)*3 + 2]), 1)) #define TRYMAP_ENC_MPLANE(charset, assplane, asshi, asslo, uni) \ - _TRYMAP_ENC_MPLANE(&charset##_encmap[(uni) >> 8], \ + if _TRYMAP_ENC_MPLANE(&charset##_encmap[(uni) >> 8], \ assplane, asshi, asslo, (uni) & 0xff) #define TRYMAP_DEC_MPLANE(charset, assi, plane, c1, c2) \ - _TRYMAP_DEC(&charset##_decmap[plane][c1], assi, c2) + if _TRYMAP_DEC(&charset##_decmap[plane][c1], assi, c2) #if Py_UNICODE_SIZE == 2 #define DECODE_SURROGATE(c) \ Modified: stackless/branches/release25-maint/Modules/itertoolsmodule.c ============================================================================== --- stackless/branches/release25-maint/Modules/itertoolsmodule.c (original) +++ stackless/branches/release25-maint/Modules/itertoolsmodule.c Wed Sep 13 15:19:16 2006 @@ -618,11 +618,15 @@ static PyObject * tee(PyObject *self, PyObject *args) { - int i, n=2; + Py_ssize_t i, n=2; PyObject *it, *iterable, *copyable, *result; - if (!PyArg_ParseTuple(args, "O|i", &iterable, &n)) + if (!PyArg_ParseTuple(args, "O|n", &iterable, &n)) return NULL; + if (n < 0) { + PyErr_SetString(PyExc_ValueError, "n must be >= 0"); + return NULL; + } result = PyTuple_New(n); if (result == NULL) return NULL; Modified: stackless/branches/release25-maint/Modules/mmapmodule.c ============================================================================== --- stackless/branches/release25-maint/Modules/mmapmodule.c (original) +++ stackless/branches/release25-maint/Modules/mmapmodule.c Wed Sep 13 15:19:16 2006 @@ -470,7 +470,7 @@ mmap_tell_method(mmap_object *self, PyObject *unused) { CHECK_VALID(NULL); - return PyInt_FromLong((long) self->pos); + return PyInt_FromSize_t(self->pos); } static PyObject * Modified: stackless/branches/release25-maint/Modules/posixmodule.c ============================================================================== --- stackless/branches/release25-maint/Modules/posixmodule.c (original) +++ stackless/branches/release25-maint/Modules/posixmodule.c Wed Sep 13 15:19:16 2006 @@ -7877,7 +7877,7 @@ pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress( hAdvAPI32, "CryptGenRandom"); - if (pCryptAcquireContext == NULL) + if (pCryptGenRandom == NULL) return PyErr_Format(PyExc_NotImplementedError, "CryptGenRandom not found"); Modified: stackless/branches/release25-maint/Objects/classobject.c ============================================================================== --- stackless/branches/release25-maint/Objects/classobject.c (original) +++ stackless/branches/release25-maint/Objects/classobject.c Wed Sep 13 15:19:16 2006 @@ -92,8 +92,22 @@ } Py_INCREF(bases); } + + if (getattrstr == NULL) { + getattrstr = PyString_InternFromString("__getattr__"); + if (getattrstr == NULL) + goto alloc_error; + setattrstr = PyString_InternFromString("__setattr__"); + if (setattrstr == NULL) + goto alloc_error; + delattrstr = PyString_InternFromString("__delattr__"); + if (delattrstr == NULL) + goto alloc_error; + } + op = PyObject_GC_New(PyClassObject, &PyClass_Type); if (op == NULL) { +alloc_error: Py_DECREF(bases); return NULL; } @@ -102,17 +116,7 @@ op->cl_dict = dict; Py_XINCREF(name); op->cl_name = name; - if (getattrstr == NULL) { - getattrstr = PyString_InternFromString("__getattr__"); - if (getattrstr == NULL) - return NULL; - setattrstr = PyString_InternFromString("__setattr__"); - if (setattrstr == NULL) - return NULL; - delattrstr = PyString_InternFromString("__delattr__"); - if (delattrstr == NULL) - return NULL; - } + op->cl_getattr = class_lookup(op, getattrstr, &dummy); op->cl_setattr = class_lookup(op, setattrstr, &dummy); op->cl_delattr = class_lookup(op, delattrstr, &dummy); Modified: stackless/branches/release25-maint/Objects/dictobject.c ============================================================================== --- stackless/branches/release25-maint/Objects/dictobject.c (original) +++ stackless/branches/release25-maint/Objects/dictobject.c Wed Sep 13 15:19:16 2006 @@ -1585,7 +1585,10 @@ /* temporarily bump aval's refcount to ensure it stays alive until we're done with it */ Py_INCREF(aval); + /* ditto for key */ + Py_INCREF(key); bval = PyDict_GetItem((PyObject *)b, key); + Py_DECREF(key); if (bval == NULL) { Py_DECREF(aval); return 0; Modified: stackless/branches/release25-maint/Objects/exceptions.c ============================================================================== --- stackless/branches/release25-maint/Objects/exceptions.c (original) +++ stackless/branches/release25-maint/Objects/exceptions.c Wed Sep 13 15:19:16 2006 @@ -81,6 +81,7 @@ static void BaseException_dealloc(PyBaseExceptionObject *self) { + _PyObject_GC_UNTRACK(self); BaseException_clear(self); self->ob_type->tp_free((PyObject *)self); } @@ -174,27 +175,10 @@ Py_RETURN_NONE; } -#ifdef Py_USING_UNICODE -/* while this method generates fairly uninspired output, it a least - * guarantees that we can display exceptions that have unicode attributes - */ -static PyObject * -BaseException_unicode(PyBaseExceptionObject *self) -{ - if (PyTuple_GET_SIZE(self->args) == 0) - return PyUnicode_FromUnicode(NULL, 0); - if (PyTuple_GET_SIZE(self->args) == 1) - return PyObject_Unicode(PyTuple_GET_ITEM(self->args, 0)); - return PyObject_Unicode(self->args); -} -#endif /* Py_USING_UNICODE */ static PyMethodDef BaseException_methods[] = { {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS }, {"__setstate__", (PyCFunction)BaseException_setstate, METH_O }, -#ifdef Py_USING_UNICODE - {"__unicode__", (PyCFunction)BaseException_unicode, METH_NOARGS }, -#endif {NULL, NULL, 0, NULL}, }; @@ -455,6 +439,7 @@ static void SystemExit_dealloc(PySystemExitObject *self) { + _PyObject_GC_UNTRACK(self); SystemExit_clear(self); self->ob_type->tp_free((PyObject *)self); } @@ -570,6 +555,7 @@ static void EnvironmentError_dealloc(PyEnvironmentErrorObject *self) { + _PyObject_GC_UNTRACK(self); EnvironmentError_clear(self); self->ob_type->tp_free((PyObject *)self); } @@ -768,6 +754,7 @@ static void WindowsError_dealloc(PyWindowsErrorObject *self) { + _PyObject_GC_UNTRACK(self); WindowsError_clear(self); self->ob_type->tp_free((PyObject *)self); } @@ -1043,6 +1030,7 @@ static void SyntaxError_dealloc(PySyntaxErrorObject *self) { + _PyObject_GC_UNTRACK(self); SyntaxError_clear(self); self->ob_type->tp_free((PyObject *)self); } @@ -1559,6 +1547,7 @@ static void UnicodeError_dealloc(PyUnicodeErrorObject *self) { + _PyObject_GC_UNTRACK(self); UnicodeError_clear(self); self->ob_type->tp_free((PyObject *)self); } @@ -1645,7 +1634,7 @@ static PyTypeObject _PyExc_UnicodeEncodeError = { PyObject_HEAD_INIT(NULL) 0, - "UnicodeEncodeError", + EXC_MODULE_NAME "UnicodeEncodeError", sizeof(PyUnicodeErrorObject), 0, (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (reprfunc)UnicodeEncodeError_str, 0, 0, 0, @@ -1820,7 +1809,7 @@ (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (reprfunc)UnicodeTranslateError_str, 0, 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse, + PyDoc_STR("Unicode translation error."), (traverseproc)UnicodeError_traverse, (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members, 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict), (initproc)UnicodeTranslateError_init, 0, BaseException_new, Modified: stackless/branches/release25-maint/Objects/fileobject.c ============================================================================== --- stackless/branches/release25-maint/Objects/fileobject.c (original) +++ stackless/branches/release25-maint/Objects/fileobject.c Wed Sep 13 15:19:16 2006 @@ -922,7 +922,7 @@ ndone += nnow; ntodo -= nnow; } - return PyInt_FromLong((long)ndone); + return PyInt_FromSsize_t(ndone); } /************************************************************************** @@ -2016,7 +2016,7 @@ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:file", kwlist, &o_name, &mode, &bufsize)) - return -1; + goto Error; if (fill_file_fields(foself, NULL, o_name, mode, fclose) == NULL) Modified: stackless/branches/release25-maint/Objects/intobject.c ============================================================================== --- stackless/branches/release25-maint/Objects/intobject.c (original) +++ stackless/branches/release25-maint/Objects/intobject.c Wed Sep 13 15:19:16 2006 @@ -564,8 +564,14 @@ "integer division or modulo by zero"); return DIVMOD_ERROR; } - /* (-sys.maxint-1)/-1 is the only overflow case. */ - if (y == -1 && x < 0 && x == -x) + /* (-sys.maxint-1)/-1 is the only overflow case. x is the most + * negative long iff x < 0 and, on a 2's-complement box, x == -x. + * However, -x is undefined (by C) if x /is/ the most negative long + * (it's a signed overflow case), and some compilers care. So we cast + * x to unsigned long first. However, then other compilers warn about + * applying unary minus to an unsigned operand. Hence the weird "0-". + */ + if (y == -1 && x < 0 && (unsigned long)x == 0-(unsigned long)x) return DIVMOD_OVERFLOW; xdivy = x / y; xmody = x - xdivy * y; Modified: stackless/branches/release25-maint/Objects/setobject.c ============================================================================== --- stackless/branches/release25-maint/Objects/setobject.c (original) +++ stackless/branches/release25-maint/Objects/setobject.c Wed Sep 13 15:19:16 2006 @@ -319,8 +319,10 @@ assert(so->fill <= so->mask); /* at least one empty slot */ n_used = so->used; Py_INCREF(entry->key); - if (set_insert_key(so, entry->key, entry->hash) == -1) + if (set_insert_key(so, entry->key, entry->hash) == -1) { + Py_DECREF(entry->key); return -1; + } if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) return 0; return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4); @@ -1142,7 +1144,12 @@ } while (set_next((PySetObject *)other, &pos, &entry)) { - if (set_contains_entry(so, entry)) { + int rv = set_contains_entry(so, entry); + if (rv == -1) { + Py_DECREF(result); + return NULL; + } + if (rv) { if (set_add_entry(result, entry) == -1) { Py_DECREF(result); return NULL; @@ -1159,7 +1166,14 @@ } while ((key = PyIter_Next(it)) != NULL) { - if (set_contains_key(so, key)) { + int rv = set_contains_key(so, key); + if (rv == -1) { + Py_DECREF(it); + Py_DECREF(result); + Py_DECREF(key); + return NULL; + } + if (rv) { if (set_add_key(result, key) == -1) { Py_DECREF(it); Py_DECREF(result); @@ -1236,7 +1250,8 @@ Py_ssize_t pos = 0; while (set_next((PySetObject *)other, &pos, &entry)) - set_discard_entry(so, entry); + if (set_discard_entry(so, entry) == -1) + return -1; } else { PyObject *key, *it; it = PyObject_GetIter(other); @@ -1299,17 +1314,26 @@ entrycopy.hash = entry->hash; entrycopy.key = entry->key; if (!PyDict_Contains(other, entry->key)) { - if (set_add_entry((PySetObject *)result, &entrycopy) == -1) + if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { + Py_DECREF(result); return NULL; + } } } return result; } while (set_next(so, &pos, &entry)) { - if (!set_contains_entry((PySetObject *)other, entry)) { - if (set_add_entry((PySetObject *)result, entry) == -1) + int rv = set_contains_entry((PySetObject *)other, entry); + if (rv == -1) { + Py_DECREF(result); + return NULL; + } + if (!rv) { + if (set_add_entry((PySetObject *)result, entry) == -1) { + Py_DECREF(result); return NULL; + } } } return result; @@ -1468,7 +1492,10 @@ Py_RETURN_FALSE; while (set_next(so, &pos, &entry)) { - if (!set_contains_entry((PySetObject *)other, entry)) + int rv = set_contains_entry((PySetObject *)other, entry); + if (rv == -1) + return NULL; + if (!rv) Py_RETURN_FALSE; } Py_RETURN_TRUE; Modified: stackless/branches/release25-maint/Objects/stringlib/partition.h ============================================================================== --- stackless/branches/release25-maint/Objects/stringlib/partition.h (original) +++ stackless/branches/release25-maint/Objects/stringlib/partition.h Wed Sep 13 15:19:16 2006 @@ -78,12 +78,12 @@ } if (pos < 0) { - Py_INCREF(str_obj); - PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj); Py_INCREF(STRINGLIB_EMPTY); - PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY); + PyTuple_SET_ITEM(out, 0, (PyObject*) STRINGLIB_EMPTY); Py_INCREF(STRINGLIB_EMPTY); - PyTuple_SET_ITEM(out, 2, (PyObject*) STRINGLIB_EMPTY); + PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY); + Py_INCREF(str_obj); + PyTuple_SET_ITEM(out, 2, (PyObject*) str_obj); return out; } Modified: stackless/branches/release25-maint/Objects/stringobject.c ============================================================================== --- stackless/branches/release25-maint/Objects/stringobject.c (original) +++ stackless/branches/release25-maint/Objects/stringobject.c Wed Sep 13 15:19:16 2006 @@ -1543,11 +1543,11 @@ } PyDoc_STRVAR(rpartition__doc__, -"S.rpartition(sep) -> (head, sep, tail)\n\ +"S.rpartition(sep) -> (tail, sep, head)\n\ \n\ Searches for the separator sep in S, starting at the end of S, and returns\n\ the part before it, the separator itself, and the part after it. If the\n\ -separator is not found, returns S and two empty strings."); +separator is not found, returns two empty strings and S."); static PyObject * string_rpartition(PyStringObject *self, PyObject *sep_obj) Modified: stackless/branches/release25-maint/Objects/unicodeobject.c ============================================================================== --- stackless/branches/release25-maint/Objects/unicodeobject.c (original) +++ stackless/branches/release25-maint/Objects/unicodeobject.c Wed Sep 13 15:19:16 2006 @@ -2040,7 +2040,28 @@ static const char *hexdigit = "0123456789abcdef"; - repr = PyString_FromStringAndSize(NULL, 2 + 6*size + 1); + /* Initial allocation is based on the longest-possible unichr + escape. + + In wide (UTF-32) builds '\U00xxxxxx' is 10 chars per source + unichr, so in this case it's the longest unichr escape. In + narrow (UTF-16) builds this is five chars per source unichr + since there are two unichrs in the surrogate pair, so in narrow + (UTF-16) builds it's not the longest unichr escape. + + In wide or narrow builds '\uxxxx' is 6 chars per source unichr, + so in the narrow (UTF-16) build case it's the longest unichr + escape. + */ + + repr = PyString_FromStringAndSize(NULL, + 2 +#ifdef Py_UNICODE_WIDE + + 10*size +#else + + 6*size +#endif + + 1); if (repr == NULL) return NULL; @@ -2065,15 +2086,6 @@ #ifdef Py_UNICODE_WIDE /* Map 21-bit characters to '\U00xxxxxx' */ else if (ch >= 0x10000) { - Py_ssize_t offset = p - PyString_AS_STRING(repr); - - /* Resize the string if necessary */ - if (offset + 12 > PyString_GET_SIZE(repr)) { - if (_PyString_Resize(&repr, PyString_GET_SIZE(repr) + 100)) - return NULL; - p = PyString_AS_STRING(repr) + offset; - } - *p++ = '\\'; *p++ = 'U'; *p++ = hexdigit[(ch >> 28) & 0x0000000F]; @@ -2086,8 +2098,8 @@ *p++ = hexdigit[ch & 0x0000000F]; continue; } -#endif - /* Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes */ +#else + /* Map UTF-16 surrogate pairs to '\U00xxxxxx' */ else if (ch >= 0xD800 && ch < 0xDC00) { Py_UNICODE ch2; Py_UCS4 ucs; @@ -2112,6 +2124,7 @@ s--; size++; } +#endif /* Map 16-bit characters to '\uxxxx' */ if (ch >= 256) { @@ -6695,11 +6708,11 @@ } PyDoc_STRVAR(rpartition__doc__, -"S.rpartition(sep) -> (head, sep, tail)\n\ +"S.rpartition(sep) -> (tail, sep, head)\n\ \n\ Searches for the separator sep in S, starting at the end of S, and returns\n\ the part before it, the separator itself, and the part after it. If the\n\ -separator is not found, returns S and two empty strings."); +separator is not found, returns two empty strings and S."); static PyObject* unicode_rpartition(PyUnicodeObject *self, PyObject *separator) Modified: stackless/branches/release25-maint/PCbuild/build_ssl.py ============================================================================== --- stackless/branches/release25-maint/PCbuild/build_ssl.py (original) +++ stackless/branches/release25-maint/PCbuild/build_ssl.py Wed Sep 13 15:19:16 2006 @@ -139,23 +139,26 @@ try: os.chdir(ssl_dir) # If the ssl makefiles do not exist, we invoke Perl to generate them. - if not os.path.isfile(makefile): + # Due to a bug in this script, the makefile sometimes ended up empty + # Force a regeneration if it is. + if not os.path.isfile(makefile) or os.path.getsize(makefile)==0: print "Creating the makefiles..." sys.stdout.flush() # Put our working Perl at the front of our path os.environ["PATH"] = os.path.dirname(perl) + \ os.pathsep + \ os.environ["PATH"] + run_configure(configure, do_script) if arch=="x86" and debug: # the do_masm script in openssl doesn't generate a debug # build makefile so we generate it here: os.system("perl util\mk1mf.pl debug "+configure+" >"+makefile) - run_configure(configure, do_script) # Now run make. - print "Executing nmake over the ssl makefiles..." + makeCommand = "nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile) + print "Executing ssl makefiles:", makeCommand sys.stdout.flush() - rc = os.system("nmake /nologo PERL=\"%s\" -f \"%s\"" %(perl, makefile)) + rc = os.system(makeCommand) if rc: print "Executing "+makefile+" failed" print rc Modified: stackless/branches/release25-maint/Python/ast.c ============================================================================== --- stackless/branches/release25-maint/Python/ast.c (original) +++ stackless/branches/release25-maint/Python/ast.c Wed Sep 13 15:19:16 2006 @@ -983,17 +983,21 @@ comprehension_ty lc; asdl_seq *t; expr_ty expression; + node *for_ch; REQ(ch, list_for); - t = ast_for_exprlist(c, CHILD(ch, 1), Store); + for_ch = CHILD(ch, 1); + t = ast_for_exprlist(c, for_ch, Store); if (!t) return NULL; expression = ast_for_testlist(c, CHILD(ch, 3)); if (!expression) return NULL; - if (asdl_seq_LEN(t) == 1) + /* Check the # of children rather than the length of t, since + [x for x, in ... ] has 1 element in t, but still requires a Tuple. */ + if (NCH(for_ch) == 1) lc = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, c->c_arena); else @@ -1129,17 +1133,21 @@ comprehension_ty ge; asdl_seq *t; expr_ty expression; + node *for_ch; REQ(ch, gen_for); - t = ast_for_exprlist(c, CHILD(ch, 1), Store); + for_ch = CHILD(ch, 1); + t = ast_for_exprlist(c, for_ch, Store); if (!t) return NULL; expression = ast_for_expr(c, CHILD(ch, 3)); if (!expression) return NULL; - if (asdl_seq_LEN(t) == 1) + /* Check the # of children rather than the length of t, since + (x for x, in ...) has 1 element in t, but still requires a Tuple. */ + if (NCH(for_ch) == 1) ge = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, c->c_arena); else Modified: stackless/branches/release25-maint/Python/bltinmodule.c ============================================================================== --- stackless/branches/release25-maint/Python/bltinmodule.c (original) +++ stackless/branches/release25-maint/Python/bltinmodule.c Wed Sep 13 15:19:16 2006 @@ -613,7 +613,7 @@ Evaluate the source in the context of globals and locals.\n\ The source may be a string representing a Python expression\n\ or a code object as returned by compile().\n\ -The globals must be a dictionary and locals can be any mappping,\n\ +The globals must be a dictionary and locals can be any mapping,\n\ defaulting to the current globals and locals.\n\ If only globals is given, locals defaults to it.\n"); Modified: stackless/branches/release25-maint/Python/import.c ============================================================================== --- stackless/branches/release25-maint/Python/import.c (original) +++ stackless/branches/release25-maint/Python/import.c Wed Sep 13 15:19:16 2006 @@ -64,9 +64,10 @@ Python 2.5b3: 62111 (fix wrong code: x += yield) Python 2.5c1: 62121 (fix wrong lnotab with for loops and storing constants that should have been removed) + Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) . */ -#define MAGIC (62121 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (62131 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the @@ -795,14 +796,16 @@ { PyCodeObject *co = NULL; mod_ty mod; - PyArena *arena = PyArena_New(); + PyArena *arena = PyArena_New(); + if (arena == NULL) + return NULL; mod = PyParser_ASTFromFile(fp, pathname, Py_file_input, 0, 0, 0, NULL, arena); if (mod) { co = PyAST_Compile(mod, pathname, NULL, arena); } - PyArena_Free(arena); + PyArena_Free(arena); return co; } @@ -2113,7 +2116,7 @@ size_t len; if (lastdot == NULL && level > 0) { PyErr_SetString(PyExc_ValueError, - "Relative importpath too deep"); + "Attempted relative import in non-package"); return NULL; } if (lastdot == NULL) @@ -2132,7 +2135,8 @@ char *dot = strrchr(buf, '.'); if (dot == NULL) { PyErr_SetString(PyExc_ValueError, - "Relative importpath too deep"); + "Attempted relative import beyond " + "toplevel package"); return NULL; } *dot = '\0'; Modified: stackless/branches/release25-maint/Python/pystate.c ============================================================================== --- stackless/branches/release25-maint/Python/pystate.c (original) +++ stackless/branches/release25-maint/Python/pystate.c Wed Sep 13 15:19:16 2006 @@ -328,9 +328,14 @@ */ #if defined(Py_DEBUG) && defined(WITH_THREAD) if (newts) { + /* This can be called from PyEval_RestoreThread(). Similar + to it, we need to ensure errno doesn't change. + */ + int err = errno; PyThreadState *check = PyGILState_GetThisThreadState(); if (check && check->interp == newts->interp && check != newts) Py_FatalError("Invalid thread state for this thread"); + errno = err; } #endif return oldts; @@ -523,7 +528,7 @@ it so it doesn't try to create another thread state for the thread (this is a better fix for SF bug #1010677 than the first one attempted). */ -void +static void _PyGILState_NoteThreadState(PyThreadState* tstate) { /* If autoTLSkey is 0, this must be the very first threadstate created Modified: stackless/branches/release25-maint/Python/pythonrun.c ============================================================================== --- stackless/branches/release25-maint/Python/pythonrun.c (original) +++ stackless/branches/release25-maint/Python/pythonrun.c Wed Sep 13 15:19:16 2006 @@ -548,11 +548,15 @@ bimod = _PyImport_FindExtension("__builtin__", "__builtin__"); if (bimod != NULL) { interp->builtins = PyModule_GetDict(bimod); + if (interp->builtins == NULL) + goto handle_error; Py_INCREF(interp->builtins); } sysmod = _PyImport_FindExtension("sys", "sys"); if (bimod != NULL && sysmod != NULL) { interp->sysdict = PyModule_GetDict(sysmod); + if (interp->sysdict == NULL) + goto handle_error; Py_INCREF(interp->sysdict); PySys_SetPath(Py_GetPath()); PyDict_SetItemString(interp->sysdict, "modules", @@ -566,6 +570,7 @@ if (!PyErr_Occurred()) return tstate; +handle_error: /* Oops, it didn't work. Undo it all. */ PyErr_Print(); Modified: stackless/branches/release25-maint/README ============================================================================== --- stackless/branches/release25-maint/README (original) +++ stackless/branches/release25-maint/README Wed Sep 13 15:19:16 2006 @@ -1,4 +1,4 @@ -This is Python version 2.5 rc 1 +This is Python version 2.5 rc 2 =============================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation. Modified: stackless/branches/release25-maint/Tools/buildbot/external.bat ============================================================================== --- stackless/branches/release25-maint/Tools/buildbot/external.bat (original) +++ stackless/branches/release25-maint/Tools/buildbot/external.bat Wed Sep 13 15:19:16 2006 @@ -28,6 +28,7 @@ cd tk8.4.12\win nmake -f makefile.vc TCLDIR=..\..\tcl8.4.12 nmake -f makefile.vc TCLDIR=..\..\tcl8.4.12 INSTALLDIR=..\..\tcltk install + cd ..\.. ) @rem sqlite 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 13 15:19:16 2006 @@ -872,6 +872,12 @@ version=version, language=lang) tmpfiles.append("msvcr71.dll") + # Check if _ctypes.pyd exists + have_ctypes = os.path.exists(srcdir+"/PCBuild/_ctypes.pyd") + if not have_ctypes: + print "WARNING: _ctypes.pyd not found, ctypes will not be included" + extensions.remove("_ctypes.pyd") + # Add all .py files in Lib, except lib-tk, test dirs={} pydirs = [(root,"Lib")] @@ -889,6 +895,8 @@ # data: Lib/email/test # output: Lib/test testsuite.set_current() + elif not have_ctypes and dir == "ctypes": + continue else: default_feature.set_current() lib = PyDirectory(db, cab, parent, dir, dir, "%s|%s" % (parent.make_short(dir), dir)) Modified: stackless/branches/release25-maint/Tools/pybench/pybench.py ============================================================================== --- stackless/branches/release25-maint/Tools/pybench/pybench.py (original) +++ stackless/branches/release25-maint/Tools/pybench/pybench.py Wed Sep 13 15:19:16 2006 @@ -885,7 +885,7 @@ else: bench.print_benchmark(hidenoise=hidenoise, limitnames=limitnames) - except IOError: + except IOError, reason: print '* Error opening/reading file %s: %s' % ( repr(show_bench), reason) @@ -931,8 +931,13 @@ bench.name = reportfile pickle.dump(bench,f) f.close() - except IOError: + except IOError, reason: print '* Error opening/writing reportfile' + except IOError, reason: + print '* Error opening/writing reportfile %s: %s' % ( + reportfile, + reason) + print if __name__ == '__main__': PyBenchCmdline() Modified: stackless/branches/release25-maint/configure ============================================================================== --- stackless/branches/release25-maint/configure (original) +++ stackless/branches/release25-maint/configure Wed Sep 13 15:19:16 2006 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 47267 . +# From configure.in Revision: 51173 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for python 2.5. # @@ -1564,7 +1564,7 @@ # On OpenBSD, select(2) is not available if _XOPEN_SOURCE is defined, # even though select is a POSIX function. Reported by J. Ribbens. # Reconfirmed for OpenBSD 3.3 by Zachary Hamm, for 3.4 by Jason Ish. - OpenBSD/2.* | OpenBSD/3.[0123456789]) + OpenBSD/2.* | OpenBSD/3.[0123456789] | OpenBSD/4.[0]) define_xopen_source=no;; # On Solaris 2.6, sys/wait.h is inconsistent in the usage # of union __?sigval. Reported by Stuart Bishop. Modified: stackless/branches/release25-maint/configure.in ============================================================================== --- stackless/branches/release25-maint/configure.in (original) +++ stackless/branches/release25-maint/configure.in Wed Sep 13 15:19:16 2006 @@ -212,7 +212,7 @@ # On OpenBSD, select(2) is not available if _XOPEN_SOURCE is defined, # even though select is a POSIX function. Reported by J. Ribbens. # Reconfirmed for OpenBSD 3.3 by Zachary Hamm, for 3.4 by Jason Ish. - OpenBSD/2.* | OpenBSD/3.@<:@0123456789@:>@) + OpenBSD/2.* | OpenBSD/3.@<:@0123456789@:>@ | OpenBSD/4.@<:@0@:>@) define_xopen_source=no;; # On Solaris 2.6, sys/wait.h is inconsistent in the usage # of union __?sigval. Reported by Stuart Bishop. _______________________________________________ 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:40:18 2006 From: python-checkins at python.org (richard.tew) Date: Wed, 13 Sep 2006 14:40:18 +0200 (CEST) Subject: [Stackless-checkins] r51870 - stackless/trunk/Stackless/module/taskletobject.c Message-ID: <20060913124018.208A61E4019@bag.python.org> Author: richard.tew Date: Wed Sep 13 14:40:17 2006 New Revision: 51870 Modified: stackless/trunk/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/trunk/Stackless/module/taskletobject.c ============================================================================== --- stackless/trunk/Stackless/module/taskletobject.c (original) +++ stackless/trunk/Stackless/module/taskletobject.c Wed Sep 13 14:40:17 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 Sun Sep 3 21:10:04 2006 From: python-checkins at python.org (richard.tew) Date: Sun, 3 Sep 2006 21:10:04 +0200 (CEST) Subject: [Stackless-checkins] r51701 - in stackless/branches/release25-maint: Makefile.pre.in Stackless/platf/slp_platformselect.h Stackless/platf/switch_arm32_gcc.h Message-ID: <20060903191004.9D82F1E4003@bag.python.org> Author: richard.tew Date: Sun Sep 3 21:10:03 2006 New Revision: 51701 Added: stackless/branches/release25-maint/Stackless/platf/switch_arm32_gcc.h - copied unchanged from r51700, stackless/trunk/Stackless/platf/switch_arm32_gcc.h Modified: stackless/branches/release25-maint/Makefile.pre.in stackless/branches/release25-maint/Stackless/platf/slp_platformselect.h Log: Added Sylvain Baro's switch patch for arm32 support. Ported from 2.4.3 branch via trunk (r51700). Modified: stackless/branches/release25-maint/Makefile.pre.in ============================================================================== --- stackless/branches/release25-maint/Makefile.pre.in (original) +++ stackless/branches/release25-maint/Makefile.pre.in Sun Sep 3 21:10:03 2006 @@ -591,6 +591,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/branches/release25-maint/Stackless/platf/slp_platformselect.h ============================================================================== --- stackless/branches/release25-maint/Stackless/platf/slp_platformselect.h (original) +++ stackless/branches/release25-maint/Stackless/platf/slp_platformselect.h Sun Sep 3 21:10:03 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 */ _______________________________________________ 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:24:42 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 7 Sep 2006 14:24:42 +0200 (CEST) Subject: [Stackless-checkins] r51807 - stackless/trunk/PCbuild/publish_binaries.py Message-ID: <20060907122442.B07C41E4003@bag.python.org> Author: richard.tew Date: Thu Sep 7 14:24:40 2006 New Revision: 51807 Modified: stackless/trunk/PCbuild/publish_binaries.py Log: Adjust the binaries publishing script for special trunk handling. Modified: stackless/trunk/PCbuild/publish_binaries.py ============================================================================== --- stackless/trunk/PCbuild/publish_binaries.py (original) +++ stackless/trunk/PCbuild/publish_binaries.py Thu Sep 7 14:24:40 2006 @@ -1,7 +1,7 @@ from zipfile import * import os, sys, md5 -exp_path = r"..\..\..\binaries-pc" +exp_path = r"..\..\binaries-pc" prog = """ import md5 @@ -16,7 +16,7 @@ fileList = [ r"..\Lib\copy_reg.py", r"..\Lib\pickle.py" ] for debug in ("", "_d"): for suffix in ("dll", "lib", "exp"): - fileList.append("python24%s.%s" % (debug, suffix)) + fileList.append("python25%s.%s" % (debug, suffix)) pathBySuffix = { "dll": "", @@ -26,7 +26,7 @@ } -zname = os.path.join(exp_path, "python24.zip") +zname = os.path.join(exp_path, "python-trunk.zip") z = ZipFile(zname, "w", ZIP_DEFLATED) for fileName in fileList: if os.path.exists(fileName): _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins From python-checkins at python.org Mon Sep 4 23:31:46 2006 From: python-checkins at python.org (andrew.dalke) Date: Mon, 4 Sep 2006 23:31:46 +0200 (CEST) Subject: [Stackless-checkins] r51706 - stackless/sandbox/examples/stacklesssocket.py Message-ID: <20060904213146.6B5831E4004@bag.python.org> Author: andrew.dalke Date: Mon Sep 4 23:31:45 2006 New Revision: 51706 Modified: stackless/sandbox/examples/stacklesssocket.py (contents, props changed) Log: changed to use platform-dependent newline encoding. assign via "globals()" instead of "locals()" Added "getaddrinfo = stdsocket.getaddrinfo" -- XXX BLOCKS! needed for urllib example Added dispatcher methods "makefile" to emulate file behavior from a socket. This required implementing _stackless_fileobject which modifies socket._fileobject to force dispatcher.close() during _fileobject gc. Otherwise the file object is not removed from the asyncore map of active sockets. (Why? The map contains a bound dispatcher method which contains the unclosed socket.) Added "sendall" -- WARNING: will busy-wait until everything is sent. No longer do self.close() on handle_close(). Clients may make multiple recv() requests even when recv() returns 0 so while the foreign side has closed the local side must not do an implicit close. -- changed test cases to reflect change (had assumed recv() on closed socket would raise an error) Added 'fileno' method. Added monkey-patch example using urllib to download from python.org Modified: stackless/sandbox/examples/stacklesssocket.py ============================================================================== --- stackless/sandbox/examples/stacklesssocket.py (original) +++ stackless/sandbox/examples/stacklesssocket.py Mon Sep 4 23:31:45 2006 @@ -1,235 +1,293 @@ -# -# 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 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: + 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 + + +# 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(): + 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) + + def sendall(self, data): + # WARNING: this will busy wait until all data is sent + self.outBuffer += data + while self.outBuffer: + stackless.schedule() + return len(data) + + # Read at most byteCount bytes. + def recv(self, byteCount): + if len(self.readBuffer) < byteCount: + data = self.readChannel.receive() + self.readBuffer += data + ret = self.readBuffer[:byteCount] + self.readBuffer = self.readBuffer[byteCount:] + return ret + + def close(self): + asyncore.dispatcher.close(self) + self.connected = False + self.accepting = False + self.outBuffer = None # breaks the loop in sendall + + # 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) + + # Asyncore says its done but self.readBuffer may be non-empty + # so can't close yet. Do nothing and let 'recv' trigger the close. + def handle_close(self): + pass + + # 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) + + def fileno(self): + return self.socket.fileno() + + def makefile(self, mode='r', bufsize=-1): + return _stackless_fileobject(self, mode, bufsize) + +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) + print "server test", i, "recv" + if currentSocket.recv(4) != "": + print "server recv(1)", i, "FAIL" + currentSocket.close() + break + # multiple empty recvs are fine + if currentSocket.recv(4) != "": + print "server recv(2)", i, "FAIL" + currentSocket.close() + break + + currentSocket.close() + 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() + print "Done server" + + def TestClientConnections(address): + global info, data, dataLength + + # Attempt 1: + clientSocket = socket() + clientSocket.connect(address) + print "client connection", 1, "waiting to recv" + if clientSocket.recv(5) != "": + print "client test", 1, "FAIL" + else: + print "client test", 1, "OK" + clientSocket.close() + + # 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() + + def TestMonkeyPatch(uri): + # replace the system socket with this module + import sys + sys.modules["socket"] = __import__(__name__) + import urllib # must occur after monkey-patching! + f = urllib.urlopen(uri) + if not isinstance(f.fp._sock, dispatcher): + raise AssertionError("failed to apply monkeypatch") + s = f.read() + if len(s) != 0: + print "Fetched", len(s), "bytes via replaced urllib" + else: + raise AssertionError("no text received?") + + stackless.tasklet(ManageListener)(testAddress) + stackless.tasklet(TestClientConnections)(testAddress) + stackless.tasklet(TestMonkeyPatch)("http://python.org/") + 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 Sun Sep 3 20:55:56 2006 From: python-checkins at python.org (richard.tew) Date: Sun, 3 Sep 2006 20:55:56 +0200 (CEST) Subject: [Stackless-checkins] r51700 - in stackless/trunk: Makefile.pre.in Stackless/platf/slp_platformselect.h Stackless/platf/switch_arm32_gcc.h Message-ID: <20060903185556.788BB1E4015@bag.python.org> Author: richard.tew Date: Sun Sep 3 20:55:56 2006 New Revision: 51700 Added: stackless/trunk/Stackless/platf/switch_arm32_gcc.h - copied unchanged from r51699, stackless/Python-2.4.3/dev/Stackless/platf/switch_arm32_gcc.h Modified: stackless/trunk/Makefile.pre.in stackless/trunk/Stackless/platf/slp_platformselect.h Log: Added Sylvain Baro's switch patch for arm32 support. Ported from 2.4.3 dev branch (r51699). Modified: stackless/trunk/Makefile.pre.in ============================================================================== --- stackless/trunk/Makefile.pre.in (original) +++ stackless/trunk/Makefile.pre.in Sun Sep 3 20:55:56 2006 @@ -591,6 +591,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/trunk/Stackless/platf/slp_platformselect.h ============================================================================== --- stackless/trunk/Stackless/platf/slp_platformselect.h (original) +++ stackless/trunk/Stackless/platf/slp_platformselect.h Sun Sep 3 20:55:56 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 */ _______________________________________________ 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:41:34 2006 From: python-checkins at python.org (richard.tew) Date: Tue, 5 Sep 2006 21:41:34 +0200 (CEST) Subject: [Stackless-checkins] r51753 - stackless/sandbox/libraries/slpmonkeypatch/__init__.py Message-ID: <20060905194134.BD6501E4004@bag.python.org> Author: richard.tew Date: Tue Sep 5 21:41:33 2006 New Revision: 51753 Modified: stackless/sandbox/libraries/slpmonkeypatch/__init__.py Log: Clean up initialisation of the stackless._config threading local object. Modified: stackless/sandbox/libraries/slpmonkeypatch/__init__.py ============================================================================== --- stackless/sandbox/libraries/slpmonkeypatch/__init__.py (original) +++ stackless/sandbox/libraries/slpmonkeypatch/__init__.py Tue Sep 5 21:41:33 2006 @@ -4,13 +4,18 @@ 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 + _config = getattr(stackless, "_config", None) + if _config is None: + _config = stackless._config = threading.local() + _config.using_stackless = True + _config.emulation_timeout = 0.1 def monkeypatch(): + # This thread is the only automatically registered one. + stackless.register_thread = register_thread_for_stackless + stackless.register_thread() + # 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__) @@ -37,9 +42,4 @@ import socketmodule sys.modules["socket"] = socketmodule - stackless.register_thread = register_thread_for_stackless - - # This thread is the only automatically registered one. - stackless.register_thread() - _______________________________________________ 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:56:49 2006 From: python-checkins at python.org (richard.tew) Date: Thu, 28 Sep 2006 14:56:49 +0200 (CEST) Subject: [Stackless-checkins] r52027 - in stackless/branches/release25-maint/Stackless: core/slp_transfer.c core/stackless_impl.h module/flextype.c module/flextype.h module/scheduling.c Message-ID: <20060928125649.807251E4006@bag.python.org> Author: richard.tew Date: Thu Sep 28 14:56:48 2006 New Revision: 52027 Modified: stackless/branches/release25-maint/Stackless/core/slp_transfer.c stackless/branches/release25-maint/Stackless/core/stackless_impl.h stackless/branches/release25-maint/Stackless/module/flextype.c stackless/branches/release25-maint/Stackless/module/flextype.h stackless/branches/release25-maint/Stackless/module/scheduling.c Log: Patch by Jeff Senn. Added some casting and changing of 'char' to 'const char' where applicable. Removes annoying compiler warnings. Modified: stackless/branches/release25-maint/Stackless/core/slp_transfer.c ============================================================================== --- stackless/branches/release25-maint/Stackless/core/slp_transfer.c (original) +++ stackless/branches/release25-maint/Stackless/core/slp_transfer.c Thu Sep 28 14:56:48 2006 @@ -28,7 +28,7 @@ intptr_t stsizeb; \ stackref += STACK_MAGIC; \ if (_cstprev != NULL) { \ - if (slp_cstack_new(_cstprev, stackref, _prev) == NULL) __return(-1); \ + if (slp_cstack_new(_cstprev, (intptr_t *)stackref, _prev) == NULL) __return(-1); \ stsizeb = slp_cstack_save(*_cstprev); \ } \ else \ @@ -168,7 +168,7 @@ \ stackref += STACK_MAGIC; \ if (_cstprev != NULL) { \ - if (slp_cstack_new(_cstprev, stackref, _prev) == NULL) \ + if (slp_cstack_new(_cstprev, (intptr_t*)stackref, _prev) == NULL) \ return -1; \ stsizeb = slp_cstack_save(*_cstprev); \ } \ Modified: stackless/branches/release25-maint/Stackless/core/stackless_impl.h ============================================================================== --- stackless/branches/release25-maint/Stackless/core/stackless_impl.h (original) +++ stackless/branches/release25-maint/Stackless/core/stackless_impl.h Thu Sep 28 14:56:48 2006 @@ -356,7 +356,7 @@ PyTaskletObject *next, int stackless); -PyAPI_FUNC(int) initialize_main_and_current(); +PyAPI_FUNC(int) initialize_main_and_current(void); /* setting the tasklet's tempval, optimized for no change */ Modified: stackless/branches/release25-maint/Stackless/module/flextype.c ============================================================================== --- stackless/branches/release25-maint/Stackless/module/flextype.c (original) +++ stackless/branches/release25-maint/Stackless/module/flextype.c Thu Sep 28 14:56:48 2006 @@ -41,7 +41,7 @@ } static PyObject * -builddict(char *modulename, char *doc) +builddict(const char *modulename, const char *doc) { return Py_BuildValue("{s:s,s:s,s:[]}", "__module__", modulename, @@ -145,7 +145,7 @@ static PyTypeObject * -type_clone(PyTypeObject *meta, PyTypeObject *base, char *typename, PyObject *dict, +type_clone(PyTypeObject *meta, PyTypeObject *base, const char *typename, PyObject *dict, size_t type_size, PyCMethodDef *ml) { PyObject *args = Py_BuildValue("(s(O)O)", typename, base, dict); @@ -171,7 +171,7 @@ } static PyTypeObject * -make_meta(char *modulename, char *type_name, size_t type_size) +make_meta(const char *modulename, const char *type_name, size_t type_size) { char metaname[200]; PyObject *dict; @@ -189,8 +189,8 @@ } PyTypeObject * PyFlexType_Build( char *modulename, - char *type_name, - char *doc, + const char *type_name, + const char *doc, PyTypeObject *base, size_t type_size, PyCMethodDef *ml ) Modified: stackless/branches/release25-maint/Stackless/module/flextype.h ============================================================================== --- stackless/branches/release25-maint/Stackless/module/flextype.h (original) +++ stackless/branches/release25-maint/Stackless/module/flextype.h Thu Sep 28 14:56:48 2006 @@ -56,8 +56,8 @@ /* build a new type and its meta-type */ PyAPI_FUNC(PyTypeObject *) PyFlexType_Build( char *modulename, - char *type_name, - char *doc, + const char *type_name, + const char *doc, PyTypeObject *base, size_t type_size, PyCMethodDef *ml ); Modified: stackless/branches/release25-maint/Stackless/module/scheduling.c ============================================================================== --- stackless/branches/release25-maint/Stackless/module/scheduling.c (original) +++ stackless/branches/release25-maint/Stackless/module/scheduling.c Thu Sep 28 14:56:48 2006 @@ -1020,7 +1020,7 @@ } /* defined in pythonrun.c */ -extern void PyStackless_HandleSystemExit(); +extern void PyStackless_HandleSystemExit(void); static PyObject * tasklet_end(PyObject *retval) _______________________________________________ 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:13:44 2006 From: python-checkins at python.org (richard.tew) Date: Fri, 29 Sep 2006 16:13:44 +0200 (CEST) Subject: [Stackless-checkins] r52038 - stackless/branches/release25-maint/Stackless/module/flextype.c stackless/branches/release25-maint/Stackless/module/flextype.h Message-ID: <20060929141344.496881E4008@bag.python.org> Author: richard.tew Date: Fri Sep 29 16:13:43 2006 New Revision: 52038 Modified: stackless/branches/release25-maint/Stackless/module/flextype.c stackless/branches/release25-maint/Stackless/module/flextype.h Log: Patch from Jeff Senn. Add const to char argument in some function prototype to remove build warnings. Modified: stackless/branches/release25-maint/Stackless/module/flextype.c ============================================================================== --- stackless/branches/release25-maint/Stackless/module/flextype.c (original) +++ stackless/branches/release25-maint/Stackless/module/flextype.c Fri Sep 29 16:13:43 2006 @@ -188,7 +188,7 @@ return meta; } -PyTypeObject * PyFlexType_Build( char *modulename, +PyTypeObject * PyFlexType_Build( const char *modulename, const char *type_name, const char *doc, PyTypeObject *base, @@ -232,3 +232,4 @@ return 0; } + Modified: stackless/branches/release25-maint/Stackless/module/flextype.h ============================================================================== --- stackless/branches/release25-maint/Stackless/module/flextype.h (original) +++ stackless/branches/release25-maint/Stackless/module/flextype.h Fri Sep 29 16:13:43 2006 @@ -55,7 +55,7 @@ /* build a new type and its meta-type */ -PyAPI_FUNC(PyTypeObject *) PyFlexType_Build( char *modulename, +PyAPI_FUNC(PyTypeObject *) PyFlexType_Build( const char *modulename, const char *type_name, const char *doc, PyTypeObject *base, _______________________________________________ Stackless-checkins mailing list Stackless-checkins at stackless.com http://www.stackless.com/mailman/listinfo/stackless-checkins