From 2380ac740ecedca7990d7461590e86636a364bad Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 9 Jan 2008 00:17:24 +0000 Subject: Merged revisions 59843-59863 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r59844 | raymond.hettinger | 2008-01-07 21:56:05 +0100 (Mon, 07 Jan 2008) | 1 line Use get() instead of pop() for the optimized version of _replace(). ........ r59847 | raymond.hettinger | 2008-01-07 22:33:51 +0100 (Mon, 07 Jan 2008) | 1 line Documentation nits. ........ r59849 | raymond.hettinger | 2008-01-08 03:02:05 +0100 (Tue, 08 Jan 2008) | 1 line Expand comment. ........ r59850 | raymond.hettinger | 2008-01-08 03:24:15 +0100 (Tue, 08 Jan 2008) | 1 line Docs on named tuple's naming conventions and limits of subclassing ........ r59851 | christian.heimes | 2008-01-08 04:40:04 +0100 (Tue, 08 Jan 2008) | 1 line It's verbose, not debug ........ r59852 | facundo.batista | 2008-01-08 13:25:20 +0100 (Tue, 08 Jan 2008) | 4 lines Issue #1757: The hash of a Decimal instance is no longer affected by the current context. Thanks Mark Dickinson. ........ r59853 | andrew.kuchling | 2008-01-08 15:30:55 +0100 (Tue, 08 Jan 2008) | 1 line Patch 1137: allow assigning to .buffer_size attribute of PyExpat.parser objects ........ r59854 | andrew.kuchling | 2008-01-08 15:56:02 +0100 (Tue, 08 Jan 2008) | 1 line Patch 1114: fix compilation of curses module on 64-bit AIX, and any other LP64 platforms where attr_t isn't a C long ........ r59856 | thomas.heller | 2008-01-08 16:15:09 +0100 (Tue, 08 Jan 2008) | 5 lines Use relative instead of absolute filenames in the C-level tracebacks. This prevents traceback prints pointing to files in this way: File "\loewis\25\python\Modules\_ctypes\callbacks.c", line 206, in 'calling callback function' ........ r59857 | christian.heimes | 2008-01-08 16:46:10 +0100 (Tue, 08 Jan 2008) | 2 lines Added __enter__ and __exit__ functions to HKEY object Added ExpandEnvironmentStrings to the _winreg module. ........ r59858 | georg.brandl | 2008-01-08 17:18:26 +0100 (Tue, 08 Jan 2008) | 2 lines Fix markup errors from r59857 and clarify key.__enter__/__exit__ docs ........ r59860 | georg.brandl | 2008-01-08 20:42:30 +0100 (Tue, 08 Jan 2008) | 2 lines Better method for associating .py files with the interpreter. ........ r59862 | facundo.batista | 2008-01-08 22:10:12 +0100 (Tue, 08 Jan 2008) | 9 lines Issue 846388. Adds a call to PyErr_CheckSignals to SRE_MATCH so that signal handlers can be invoked during long regular expression matches. It also adds a new error return value indicating that an exception occurred in a signal handler during the match, allowing exceptions in the signal handler to propagate up to the main loop. Thanks Josh Hoyt and Ralf Schmitt. ........ --- Doc/library/_winreg.rst | 23 ++++++++ Doc/library/collections.rst | 23 +++++--- Doc/library/pyexpat.rst | 9 +++- Doc/using/windows.rst | 17 +++--- Doc/whatsnew/2.6.rst | 7 +++ Lib/collections.py | 5 +- Lib/decimal.py | 14 +++-- Lib/test/test_decimal.py | 17 ++++++ Lib/test/test_pyexpat.py | 128 +++++++++++++++++++++++++++++++++++++++++++- Lib/test/test_socket.py | 2 +- Lib/test/test_winreg.py | 45 +++++++++------- Misc/ACKS | 1 + Modules/_ctypes/callbacks.c | 2 +- Modules/_ctypes/callproc.c | 2 +- Modules/_cursesmodule.c | 104 ++++++++++++++++++++++++++--------- Modules/_sre.c | 8 +++ Modules/pyexpat.c | 44 +++++++++++++++ PC/_winreg.c | 57 ++++++++++++++++++++ 18 files changed, 436 insertions(+), 72 deletions(-) diff --git a/Doc/library/_winreg.rst b/Doc/library/_winreg.rst index a3fe72b..7ce34b4 100644 --- a/Doc/library/_winreg.rst +++ b/Doc/library/_winreg.rst @@ -131,6 +131,16 @@ This module offers the following functions: +-------+--------------------------------------------+ +.. function:: ExpandEnvironmentStrings(unicode) + + Expands environment strings %NAME% in unicode string like const:`REG_EXPAND_SZ`:: + + >>> ExpandEnvironmentStrings(u"%windir%") + u"C:\\Windows" + + .. versionadded:: 2.6 + + .. function:: FlushKey(key) Writes all the attributes of a key to the registry. @@ -416,3 +426,16 @@ handle, and also disconnect the Windows handle from the handle object. handle is not closed. You would call this function when you need the underlying Win32 handle to exist beyond the lifetime of the handle object. +.. method:: PyHKEY.__enter__() + PyHKEY.__exit__(\*exc_info) + + The HKEY object implements :meth:`__enter__` and :meth:`__exit__` and thus + supports the context protocol for the :keyword:`with` statement:: + + with OpenKey(HKEY_LOCAL_MACHINE, "foo") as key: + # ... work with key ... + + will automatically close *key* when control leaves the :keyword:`with` block. + + .. versionadded:: 2.6 + diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 2b8e279..0c440d6 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -397,8 +397,8 @@ they add the ability to access fields by name instead of position index. method which lists the tuple contents in a ``name=value`` format. The *fieldnames* are a single string with each fieldname separated by whitespace - and/or commas (for example 'x y' or 'x, y'). Alternatively, the *fieldnames* - can be specified with a sequence of strings (such as ['x', 'y']). + and/or commas (for example 'x y' or 'x, y'). Alternatively, *fieldnames* + can be a sequence of strings (such as ['x', 'y']). Any valid Python identifier may be used for a fieldname except for names starting with an underscore. Valid identifiers consist of letters, digits, @@ -477,7 +477,8 @@ by the :mod:`csv` or :mod:`sqlite3` modules:: print emp.name, emp.title In addition to the methods inherited from tuples, named tuples support -three additional methods and one attribute. +three additional methods and one attribute. To prevent conflicts with +field names, the method and attribute names start with an underscore. .. method:: somenamedtuple._make(iterable) @@ -513,7 +514,7 @@ three additional methods and one attribute. .. attribute:: somenamedtuple._fields - Tuple of strings listing the field names. This is useful for introspection + Tuple of strings listing the field names. Useful for introspection and for creating new named tuple types from existing named tuples. :: @@ -532,7 +533,7 @@ function:: >>> getattr(p, 'x') 11 -When casting a dictionary to a named tuple, use the double-star-operator [#]_:: +To cast a dictionary to a named tuple, use the double-star-operator [#]_:: >>> d = {'x': 11, 'y': 22} >>> Point(**d) @@ -557,14 +558,20 @@ a fixed-width print format:: Point: x= 1.286 y= 6.000 hypot= 6.136 Another use for subclassing is to replace performance critcal methods with -faster versions that bypass error-checking and localize variable access:: +faster versions that bypass error-checking and that localize variable access:: >>> class Point(namedtuple('Point', 'x y')): _make = classmethod(tuple.__new__) def _replace(self, _map=map, **kwds): - return self._make(_map(kwds.pop, ('x', 'y'), self)) + return self._make(_map(kwds.get, ('x', 'y'), self)) -Default values can be implemented by using :meth:`_replace`:: to + +Subclassing is not useful for adding new, stored fields. Instead, simply +create a new named tuple type from the :attr:`_fields` attribute:: + + >>> Pixel = namedtuple('Pixel', Point._fields + Color._fields) + +Default values can be implemented by using :meth:`_replace` to customize a prototype instance:: >>> Account = namedtuple('Account', 'owner balance transaction_count') diff --git a/Doc/library/pyexpat.rst b/Doc/library/pyexpat.rst index 29ca540..3a3305c 100644 --- a/Doc/library/pyexpat.rst +++ b/Doc/library/pyexpat.rst @@ -177,8 +177,13 @@ XMLParser Objects .. attribute:: xmlparser.buffer_size - The size of the buffer used when :attr:`buffer_text` is true. This value cannot - be changed at this time. + The size of the buffer used when :attr:`buffer_text` is true. + A new buffer size can be set by assigning a new integer value + to this attribute. + When the size is changed, the buffer will be flushed. + + .. versionchanged:: 2.6 + The buffer size can now be changed. .. attribute:: xmlparser.buffer_text diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 2b52544..1753b6d 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -188,16 +188,17 @@ of your Python installation directory). This suppresses the terminal window on startup. You can also make all ``.py`` scripts execute with :program:`pythonw.exe`, -setting this through the usual facilites, for example (names might differ, -depending on your version of Windows): +setting this through the usual facilites, for example (might require +administrative rights): -#. Open the context menu of a :file:`{*}.py` file. -#. Click :menuselection:`Open with...`. -#. Choose the interpreter of your choice (utilize :guilabel:`Other...` or - :guilabel:`Choose Program...` if it is not in the list of default programs). -#. Check :guilabel:`Always open files with this program`. -#. Click :guilabel:`OK`. +#. Launch a command prompt. +#. Associate the correct file group with ``.py`` scripts:: + + assoc .py=Python.File +#. Redirect all Python files to the new executable:: + + ftype Python.File=C:\Path\to\pythonw.exe "%1" %* Additional modules diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index fee298d..4d90d35 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -875,6 +875,13 @@ complete list of changes, or look through the CVS logs for all the details. changed and :const:`UF_APPEND` to indicate that data can only be appended to the file. (Contributed by M. Levinson.) +* The :mod:`pyexpat` module's :class:`Parser` objects now allow setting + their :attr:`buffer_size` attribute to change the size of the buffer + used to hold character data. + (Contributed by Achim Gaedke.) + + .. Patch 1137 + * The :mod:`random` module's :class:`Random` objects can now be pickled on a 32-bit system and unpickled on a 64-bit system, and vice versa. Unfortunately, this change also means diff --git a/Lib/collections.py b/Lib/collections.py index 2f0d038..e1e9d11 100644 --- a/Lib/collections.py +++ b/Lib/collections.py @@ -34,7 +34,8 @@ def namedtuple(typename, field_names, verbose=False): """ - # Parse and validate the field names + # Parse and validate the field names. Validation serves two purposes, + # generating informative error messages and preventing template injection attacks. if isinstance(field_names, str): field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas field_names = tuple(field_names) @@ -129,7 +130,7 @@ if __name__ == '__main__': 'Point class with optimized _make() and _replace() without error-checking' _make = classmethod(tuple.__new__) def _replace(self, _map=map, **kwds): - return self._make(_map(kwds.pop, ('x', 'y'), self)) + return self._make(_map(kwds.get, ('x', 'y'), self)) print(Point(11, 22)._replace(x=100)) diff --git a/Lib/decimal.py b/Lib/decimal.py index 54e8cb4..1f5ff12 100644 --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -809,8 +809,10 @@ class Decimal(_numbers.Real, _numbers.Inexact): def __hash__(self): """x.__hash__() <==> hash(x)""" # Decimal integers must hash the same as the ints - # Non-integer decimals are normalized and hashed as strings - # Normalization assures that hash(100E-1) == hash(10) + # + # The hash of a nonspecial noninteger Decimal must depend only + # on the value of that Decimal, and not on its representation. + # For example: hash(Decimal("100E-1")) == hash(Decimal("10")). if self._is_special: if self._isnan(): raise TypeError('Cannot hash a NaN value.') @@ -826,7 +828,13 @@ class Decimal(_numbers.Real, _numbers.Inexact): # 2**64-1. So we can replace hash((-1)**s*c*10**e) with # hash((-1)**s*c*pow(10, e, 2**64-1). return hash((-1)**op.sign*op.int*pow(10, op.exp, 2**64-1)) - return hash(str(self.normalize())) + # The value of a nonzero nonspecial Decimal instance is + # faithfully represented by the triple consisting of its sign, + # its adjusted exponent, and its coefficient with trailing + # zeros removed. + return hash((self._sign, + self._exp+len(self._int), + self._int.rstrip('0'))) def as_tuple(self): """Represents the number as a triple tuple. diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 3c64e64..0dd7f00 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -971,6 +971,23 @@ class DecimalUsabilityTest(unittest.TestCase): self.assert_(hash(Decimal('Inf'))) self.assert_(hash(Decimal('-Inf'))) + # check that the value of the hash doesn't depend on the + # current context (issue #1757) + c = getcontext() + old_precision = c.prec + x = Decimal("123456789.1") + + c.prec = 6 + h1 = hash(x) + c.prec = 10 + h2 = hash(x) + c.prec = 16 + h3 = hash(x) + + self.assertEqual(h1, h2) + self.assertEqual(h1, h3) + c.prec = old_precision + def test_min_and_max_methods(self): d1 = Decimal('15.32') diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index cb4e6eb..9fda72d 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -2,6 +2,7 @@ # handler, are obscure and unhelpful. from io import BytesIO +import sys import unittest import pyexpat @@ -385,6 +386,130 @@ class sf1296433Test(unittest.TestCase): self.assertRaises(Exception, parser.Parse, xml) +class ChardataBufferTest(unittest.TestCase): + """ + test setting of chardata buffer size + """ + + def test_1025_bytes(self): + self.assertEquals(self.small_buffer_test(1025), 2) + + def test_1000_bytes(self): + self.assertEquals(self.small_buffer_test(1000), 1) + + def test_wrong_size(self): + parser = expat.ParserCreate() + parser.buffer_text = 1 + def f(size): + parser.buffer_size = size + + self.assertRaises(ValueError, f, -1) + self.assertRaises(ValueError, f, 0) + + def test_unchanged_size(self): + xml1 = ("%s" % ('a' * 512)) + xml2 = 'a'*512 + '' + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_size = 512 + parser.buffer_text = 1 + + # Feed 512 bytes of character data: the handler should be called + # once. + self.n = 0 + parser.Parse(xml1) + self.assertEquals(self.n, 1) + + # Reassign to buffer_size, but assign the same size. + parser.buffer_size = parser.buffer_size + self.assertEquals(self.n, 1) + + # Try parsing rest of the document + parser.Parse(xml2) + self.assertEquals(self.n, 2) + + + def test_disabling_buffer(self): + xml1 = "%s" % ('a' * 512) + xml2 = ('b' * 1024) + xml3 = "%s" % ('c' * 1024) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 1024 + self.assertEquals(parser.buffer_size, 1024) + + # Parse one chunk of XML + self.n = 0 + parser.Parse(xml1, 0) + self.assertEquals(parser.buffer_size, 1024) + self.assertEquals(self.n, 1) + + # Turn off buffering and parse the next chunk. + parser.buffer_text = 0 + self.assertFalse(parser.buffer_text) + self.assertEquals(parser.buffer_size, 1024) + for i in range(10): + parser.Parse(xml2, 0) + self.assertEquals(self.n, 11) + + parser.buffer_text = 1 + self.assertTrue(parser.buffer_text) + self.assertEquals(parser.buffer_size, 1024) + parser.Parse(xml3, 1) + self.assertEquals(self.n, 12) + + + + def make_document(self, bytes): + return ("" + bytes * 'a' + '') + + def counting_handler(self, text): + self.n += 1 + + def small_buffer_test(self, buffer_len): + xml = "%s" % ('a' * buffer_len) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_size = 1024 + parser.buffer_text = 1 + + self.n = 0 + parser.Parse(xml) + return self.n + + def test_change_size_1(self): + xml1 = "%s" % ('a' * 1024) + xml2 = "aaa%s" % ('a' * 1025) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 1024 + self.assertEquals(parser.buffer_size, 1024) + + self.n = 0 + parser.Parse(xml1, 0) + parser.buffer_size *= 2 + self.assertEquals(parser.buffer_size, 2048) + parser.Parse(xml2, 1) + self.assertEquals(self.n, 2) + + def test_change_size_2(self): + xml1 = "a%s" % ('a' * 1023) + xml2 = "aaa%s" % ('a' * 1025) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 2048 + self.assertEquals(parser.buffer_size, 2048) + + self.n=0 + parser.Parse(xml1, 0) + parser.buffer_size = parser.buffer_size // 2 + self.assertEquals(parser.buffer_size, 1024) + parser.Parse(xml2, 1) + self.assertEquals(self.n, 4) + def test_main(): run_unittest(SetAttributeTest, @@ -394,7 +519,8 @@ def test_main(): BufferTextTest, HandlerExceptionTest, PositionTest, - sf1296433Test) + sf1296433Test, + ChardataBufferTest) if __name__ == "__main__": test_main() diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index bc31620..d474206 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1133,7 +1133,7 @@ def isTipcAvailable(): for line in f: if line.startswith("tipc "): return True - if test_support.debug: + if test_support.verbose: print("TIPC module is not loaded, please 'sudo modprobe tipc'") return False diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py index 7b1baf8..3f73c74 100644 --- a/Lib/test/test_winreg.py +++ b/Lib/test/test_winreg.py @@ -73,26 +73,26 @@ class WinregTests(unittest.TestCase): key = OpenKey(root_key, test_key_name) # Read the sub-keys - sub_key = OpenKey(key, subkeystr) - # Check I can enumerate over the values. - index = 0 - while 1: - try: - data = EnumValue(sub_key, index) - except EnvironmentError: - break - self.assertEquals(data in test_data, True, - "Didn't read back the correct test data") - index = index + 1 - self.assertEquals(index, len(test_data), - "Didn't read the correct number of items") - # Check I can directly access each item - for value_name, value_data, value_type in test_data: - read_val, read_typ = QueryValueEx(sub_key, value_name) - self.assertEquals(read_val, value_data, - "Could not directly read the value") - self.assertEquals(read_typ, value_type, - "Could not directly read the value") + with OpenKey(key, "sub_key") as sub_key: + # Check I can enumerate over the values. + index = 0 + while 1: + try: + data = EnumValue(sub_key, index) + except EnvironmentError: + break + self.assertEquals(data in test_data, True, + "Didn't read back the correct test data") + index = index + 1 + self.assertEquals(index, len(test_data), + "Didn't read the correct number of items") + # Check I can directly access each item + for value_name, value_data, value_type in test_data: + read_val, read_typ = QueryValueEx(sub_key, value_name) + self.assertEquals(read_val, value_data, + "Could not directly read the value") + self.assertEquals(read_typ, value_type, + "Could not directly read the value") sub_key.Close() # Enumerate our main key. read_val = EnumKey(key, 0) @@ -155,6 +155,11 @@ class WinregTests(unittest.TestCase): remote_key = ConnectRegistry(self.remote_name, HKEY_CURRENT_USER) self.TestAll(remote_key) + def testExpandEnvironmentStrings(self): + r = ExpandEnvironmentStrings("%windir%\\test") + self.assertEqual(type(r), str) + self.assertEqual(r, os.environ["windir"] + "\\test") + def test_main(): test_support.run_unittest(WinregTests) diff --git a/Misc/ACKS b/Misc/ACKS index aafcf08..8bb35d8 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -227,6 +227,7 @@ Gyro Funch Peter Funk Geoff Furnish Ulisses Furquim +Achim Gaedke Lele Gaifax Santiago Gala Yitzchak Gale diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c index 050a5c1..6a1d2b7 100644 --- a/Modules/_ctypes/callbacks.c +++ b/Modules/_ctypes/callbacks.c @@ -197,7 +197,7 @@ static void _CallPythonObject(void *mem, } #define CHECK(what, x) \ -if (x == NULL) _AddTraceback(what, __FILE__, __LINE__ - 1), PyErr_Print() +if (x == NULL) _AddTraceback(what, "_ctypes/callbacks.c", __LINE__ - 1), PyErr_Print() result = PyObject_CallObject(callable, arglist); CHECK("'calling callback function'", result); diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 8f6b957..c24cb81 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -755,7 +755,7 @@ static PyObject *GetResult(PyObject *restype, void *result, PyObject *checker) v = PyObject_CallFunctionObjArgs(checker, retval, NULL); if (v == NULL) - _AddTraceback("GetResult", __FILE__, __LINE__-2); + _AddTraceback("GetResult", "_ctypes/callproc.c", __LINE__-2); Py_DECREF(retval); return v; } diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 638b388..57f9058 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -322,9 +322,6 @@ Window_NoArg2TupleReturnFunction(getbegyx, int, "ii") Window_NoArg2TupleReturnFunction(getmaxyx, int, "ii") Window_NoArg2TupleReturnFunction(getparyx, int, "ii") -Window_OneArgNoReturnFunction(wattron, attr_t, "l;attr") -Window_OneArgNoReturnFunction(wattroff, attr_t, "l;attr") -Window_OneArgNoReturnFunction(wattrset, attr_t, "l;attr") Window_OneArgNoReturnFunction(clearok, int, "i;True(1) or False(0)") Window_OneArgNoReturnFunction(idlok, int, "i;True(1) or False(0)") #if defined(__NetBSD__) @@ -379,6 +376,7 @@ PyCursesWindow_AddCh(PyCursesWindowObject *self, PyObject *args) PyObject *temp; chtype ch = 0; attr_t attr = A_NORMAL; + long lattr; switch (PyTuple_Size(args)) { case 1: @@ -386,8 +384,9 @@ PyCursesWindow_AddCh(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 2: - if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &temp, &attr)) + if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &temp, &lattr)) return NULL; + attr = lattr; break; case 3: if (!PyArg_ParseTuple(args,"iiO;y,x,ch or int", &y, &x, &temp)) @@ -396,8 +395,9 @@ PyCursesWindow_AddCh(PyCursesWindowObject *self, PyObject *args) break; case 4: if (!PyArg_ParseTuple(args,"iiOl;y,x,ch or int, attr", - &y, &x, &temp, &attr)) + &y, &x, &temp, &lattr)) return NULL; + attr = lattr; use_xy = TRUE; break; default: @@ -425,6 +425,7 @@ PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args) int x, y; char *str; attr_t attr = A_NORMAL , attr_old = A_NORMAL; + long lattr; int use_xy = FALSE, use_attr = FALSE; switch (PyTuple_Size(args)) { @@ -433,8 +434,9 @@ PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 2: - if (!PyArg_ParseTuple(args,"sl;str,attr", &str, &attr)) + if (!PyArg_ParseTuple(args,"sl;str,attr", &str, &lattr)) return NULL; + attr = lattr; use_attr = TRUE; break; case 3: @@ -443,8 +445,9 @@ PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args) use_xy = TRUE; break; case 4: - if (!PyArg_ParseTuple(args,"iisl;int,int,str,attr", &y, &x, &str, &attr)) + if (!PyArg_ParseTuple(args,"iisl;int,int,str,attr", &y, &x, &str, &lattr)) return NULL; + attr = lattr; use_xy = use_attr = TRUE; break; default: @@ -471,6 +474,7 @@ PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args) int rtn, x, y, n; char *str; attr_t attr = A_NORMAL , attr_old = A_NORMAL; + long lattr; int use_xy = FALSE, use_attr = FALSE; switch (PyTuple_Size(args)) { @@ -479,8 +483,9 @@ PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 3: - if (!PyArg_ParseTuple(args,"sil;str,n,attr", &str, &n, &attr)) + if (!PyArg_ParseTuple(args,"sil;str,n,attr", &str, &n, &lattr)) return NULL; + attr = lattr; use_attr = TRUE; break; case 4: @@ -489,8 +494,9 @@ PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args) use_xy = TRUE; break; case 5: - if (!PyArg_ParseTuple(args,"iisil;y,x,str,n,attr", &y, &x, &str, &n, &attr)) + if (!PyArg_ParseTuple(args,"iisil;y,x,str,n,attr", &y, &x, &str, &n, &lattr)) return NULL; + attr = lattr; use_xy = use_attr = TRUE; break; default: @@ -517,6 +523,7 @@ PyCursesWindow_Bkgd(PyCursesWindowObject *self, PyObject *args) PyObject *temp; chtype bkgd; attr_t attr = A_NORMAL; + long lattr; switch (PyTuple_Size(args)) { case 1: @@ -524,8 +531,9 @@ PyCursesWindow_Bkgd(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &attr)) + if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) return NULL; + attr = lattr; break; default: PyErr_SetString(PyExc_TypeError, "bkgd requires 1 or 2 arguments"); @@ -541,11 +549,39 @@ PyCursesWindow_Bkgd(PyCursesWindowObject *self, PyObject *args) } static PyObject * +PyCursesWindow_AttrOff(PyCursesWindowObject *self, PyObject *args) +{ + long lattr; + if (!PyArg_ParseTuple(args,"l;attr", &lattr)) + return NULL; + return PyCursesCheckERR(wattroff(self->win, (attr_t)lattr), "attroff"); +} + +static PyObject * +PyCursesWindow_AttrOn(PyCursesWindowObject *self, PyObject *args) +{ + long lattr; + if (!PyArg_ParseTuple(args,"l;attr", &lattr)) + return NULL; + return PyCursesCheckERR(wattron(self->win, (attr_t)lattr), "attron"); +} + +static PyObject * +PyCursesWindow_AttrSet(PyCursesWindowObject *self, PyObject *args) +{ + long lattr; + if (!PyArg_ParseTuple(args,"l;attr", &lattr)) + return NULL; + return PyCursesCheckERR(wattrset(self->win, (attr_t)lattr), "attrset"); +} + +static PyObject * PyCursesWindow_BkgdSet(PyCursesWindowObject *self, PyObject *args) { PyObject *temp; chtype bkgd; attr_t attr = A_NORMAL; + long lattr; switch (PyTuple_Size(args)) { case 1: @@ -553,8 +589,9 @@ PyCursesWindow_BkgdSet(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &attr)) + if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) return NULL; + attr = lattr; break; default: PyErr_SetString(PyExc_TypeError, "bkgdset requires 1 or 2 arguments"); @@ -742,6 +779,7 @@ PyCursesWindow_EchoChar(PyCursesWindowObject *self, PyObject *args) PyObject *temp; chtype ch; attr_t attr = A_NORMAL; + long lattr; switch (PyTuple_Size(args)) { case 1: @@ -749,8 +787,9 @@ PyCursesWindow_EchoChar(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &attr)) + if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) return NULL; + attr = lattr; break; default: PyErr_SetString(PyExc_TypeError, "echochar requires 1 or 2 arguments"); @@ -916,6 +955,7 @@ PyCursesWindow_Hline(PyCursesWindowObject *self, PyObject *args) chtype ch; int n, x, y, code = OK; attr_t attr = A_NORMAL; + long lattr; switch (PyTuple_Size(args)) { case 2: @@ -923,8 +963,9 @@ PyCursesWindow_Hline(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 3: - if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &attr)) + if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &lattr)) return NULL; + attr = lattr; break; case 4: if (!PyArg_ParseTuple(args, "iiOi;y,x,ch or int,n", &y, &x, &temp, &n)) @@ -933,8 +974,9 @@ PyCursesWindow_Hline(PyCursesWindowObject *self, PyObject *args) break; case 5: if (!PyArg_ParseTuple(args, "iiOil; y,x,ch or int,n,attr", - &y, &x, &temp, &n, &attr)) + &y, &x, &temp, &n, &lattr)) return NULL; + attr = lattr; code = wmove(self->win, y, x); break; default: @@ -960,6 +1002,7 @@ PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) PyObject *temp; chtype ch = 0; attr_t attr = A_NORMAL; + long lattr; switch (PyTuple_Size(args)) { case 1: @@ -967,8 +1010,9 @@ PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 2: - if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &temp, &attr)) + if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &temp, &lattr)) return NULL; + attr = lattr; break; case 3: if (!PyArg_ParseTuple(args,"iiO;y,x,ch or int", &y, &x, &temp)) @@ -976,8 +1020,9 @@ PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) use_xy = TRUE; break; case 4: - if (!PyArg_ParseTuple(args,"iiOl;y,x,ch or int, attr", &y, &x, &temp, &attr)) + if (!PyArg_ParseTuple(args,"iiOl;y,x,ch or int, attr", &y, &x, &temp, &lattr)) return NULL; + attr = lattr; use_xy = TRUE; break; default: @@ -1062,6 +1107,7 @@ PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args) int x, y; char *str; attr_t attr = A_NORMAL , attr_old = A_NORMAL; + long lattr; int use_xy = FALSE, use_attr = FALSE; switch (PyTuple_Size(args)) { @@ -1070,8 +1116,9 @@ PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 2: - if (!PyArg_ParseTuple(args,"sl;str,attr", &str, &attr)) + if (!PyArg_ParseTuple(args,"sl;str,attr", &str, &lattr)) return NULL; + attr = lattr; use_attr = TRUE; break; case 3: @@ -1080,8 +1127,9 @@ PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args) use_xy = TRUE; break; case 4: - if (!PyArg_ParseTuple(args,"iisl;y,x,str,attr", &y, &x, &str, &attr)) + if (!PyArg_ParseTuple(args,"iisl;y,x,str,attr", &y, &x, &str, &lattr)) return NULL; + attr = lattr; use_xy = use_attr = TRUE; break; default: @@ -1108,6 +1156,7 @@ PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args) int rtn, x, y, n; char *str; attr_t attr = A_NORMAL , attr_old = A_NORMAL; + long lattr; int use_xy = FALSE, use_attr = FALSE; switch (PyTuple_Size(args)) { @@ -1116,8 +1165,9 @@ PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 3: - if (!PyArg_ParseTuple(args,"sil;str,n,attr", &str, &n, &attr)) + if (!PyArg_ParseTuple(args,"sil;str,n,attr", &str, &n, &lattr)) return NULL; + attr = lattr; use_attr = TRUE; break; case 4: @@ -1126,8 +1176,9 @@ PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args) use_xy = TRUE; break; case 5: - if (!PyArg_ParseTuple(args,"iisil;y,x,str,n,attr", &y, &x, &str, &n, &attr)) + if (!PyArg_ParseTuple(args,"iisil;y,x,str,n,attr", &y, &x, &str, &n, &lattr)) return NULL; + attr = lattr; use_xy = use_attr = TRUE; break; default: @@ -1470,6 +1521,7 @@ PyCursesWindow_Vline(PyCursesWindowObject *self, PyObject *args) chtype ch; int n, x, y, code = OK; attr_t attr = A_NORMAL; + long lattr; switch (PyTuple_Size(args)) { case 2: @@ -1477,8 +1529,9 @@ PyCursesWindow_Vline(PyCursesWindowObject *self, PyObject *args) return NULL; break; case 3: - if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &attr)) + if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &lattr)) return NULL; + attr = lattr; break; case 4: if (!PyArg_ParseTuple(args, "iiOi;y,x,ch or int,n", &y, &x, &temp, &n)) @@ -1487,8 +1540,9 @@ PyCursesWindow_Vline(PyCursesWindowObject *self, PyObject *args) break; case 5: if (!PyArg_ParseTuple(args, "iiOil; y,x,ch or int,n,attr", - &y, &x, &temp, &n, &attr)) + &y, &x, &temp, &n, &lattr)) return NULL; + attr = lattr; code = wmove(self->win, y, x); break; default: @@ -1511,9 +1565,9 @@ static PyMethodDef PyCursesWindow_Methods[] = { {"addch", (PyCFunction)PyCursesWindow_AddCh, METH_VARARGS}, {"addnstr", (PyCFunction)PyCursesWindow_AddNStr, METH_VARARGS}, {"addstr", (PyCFunction)PyCursesWindow_AddStr, METH_VARARGS}, - {"attroff", (PyCFunction)PyCursesWindow_wattroff, METH_VARARGS}, - {"attron", (PyCFunction)PyCursesWindow_wattron, METH_VARARGS}, - {"attrset", (PyCFunction)PyCursesWindow_wattrset, METH_VARARGS}, + {"attroff", (PyCFunction)PyCursesWindow_AttrOff, METH_VARARGS}, + {"attron", (PyCFunction)PyCursesWindow_AttrOn, METH_VARARGS}, + {"attrset", (PyCFunction)PyCursesWindow_AttrSet, METH_VARARGS}, {"bkgd", (PyCFunction)PyCursesWindow_Bkgd, METH_VARARGS}, {"chgat", (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS}, {"bkgdset", (PyCFunction)PyCursesWindow_BkgdSet, METH_VARARGS}, diff --git a/Modules/_sre.c b/Modules/_sre.c index 19e7bdc..b81a8e2 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -95,6 +95,7 @@ static char copyright[] = #define SRE_ERROR_STATE -2 /* illegal state */ #define SRE_ERROR_RECURSION_LIMIT -3 /* runaway recursion */ #define SRE_ERROR_MEMORY -9 /* out of memory */ +#define SRE_ERROR_INTERRUPTED -10 /* signal handler raised exception */ #if defined(VERBOSE) #define TRACE(v) printf v @@ -805,6 +806,7 @@ SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern) Py_ssize_t alloc_pos, ctx_pos = -1; Py_ssize_t i, ret = 0; Py_ssize_t jump; + unsigned int sigcount=0; SRE_MATCH_CONTEXT* ctx; SRE_MATCH_CONTEXT* nextctx; @@ -833,6 +835,9 @@ entrance: } for (;;) { + ++sigcount; + if ((0 == (sigcount & 0xfff)) && PyErr_CheckSignals()) + RETURN_ERROR(SRE_ERROR_INTERRUPTED); switch (*ctx->pattern++) { @@ -1833,6 +1838,9 @@ pattern_error(int status) case SRE_ERROR_MEMORY: PyErr_NoMemory(); break; + case SRE_ERROR_INTERRUPTED: + /* An exception has already been raised, so let it fly */ + break; default: /* other error codes indicate compiler/engine bugs */ PyErr_SetString( diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index ab917f0..0053201 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1524,6 +1524,50 @@ xmlparse_setattr(xmlparseobject *self, char *name, PyObject *v) self->specified_attributes = 0; return 0; } + + if (strcmp(name, "buffer_size") == 0) { + long new_buffer_size; + if (!PyLong_Check(v)) { + PyErr_SetString(PyExc_TypeError, "buffer_size must be an integer"); + return -1; + } + + new_buffer_size=PyLong_AS_LONG(v); + /* trivial case -- no change */ + if (new_buffer_size == self->buffer_size) { + return 0; + } + + if (new_buffer_size <= 0) { + PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than zero"); + return -1; + } + + /* check maximum */ + if (new_buffer_size > INT_MAX) { + char errmsg[100]; + sprintf(errmsg, "buffer_size must not be greater than %i", INT_MAX); + PyErr_SetString(PyExc_ValueError, errmsg); + return -1; + } + + if (self->buffer != NULL) { + /* there is already a buffer */ + if (self->buffer_used != 0) { + flush_character_buffer(self); + } + /* free existing buffer */ + free(self->buffer); + } + self->buffer = malloc(new_buffer_size); + if (self->buffer == NULL) { + PyErr_NoMemory(); + return -1; + } + self->buffer_size = new_buffer_size; + return 0; + } + if (strcmp(name, "CharacterDataHandler") == 0) { /* If we're changing the character data handler, flush all * cached data with the old handler. Not sure there's a diff --git a/PC/_winreg.c b/PC/_winreg.c index 2fdc5b5..0dcade8 100644 --- a/PC/_winreg.c +++ b/PC/_winreg.c @@ -46,6 +46,7 @@ PyDoc_STRVAR(module_doc, "DeleteValue() - Removes a named value from the specified registry key.\n" "EnumKey() - Enumerates subkeys of the specified open registry key.\n" "EnumValue() - Enumerates values of the specified open registry key.\n" +"ExpandEnvironmentStrings() - Expand the env strings in a REG_EXPAND_SZ string.\n" "FlushKey() - Writes all the attributes of the specified key to the registry.\n" "LoadKey() - Creates a subkey under HKEY_USER or HKEY_LOCAL_MACHINE and stores\n" " registration information from a specified file into that subkey.\n" @@ -145,6 +146,9 @@ PyDoc_STRVAR(EnumValue_doc, " on the underlying registry type.\n" "data_type is an integer that identifies the type of the value data."); +PyDoc_STRVAR(ExpandEnvironmentStrings_doc, +"string = ExpandEnvironmentStrings(string) - Expand environment vars.\n"); + PyDoc_STRVAR(FlushKey_doc, "FlushKey(key) - Writes all the attributes of a key to the registry.\n" "\n" @@ -503,9 +507,27 @@ PyHKEY_DetachMethod(PyObject *self, PyObject *args) return PyLong_FromVoidPtr(ret); } +static PyObject * +PyHKEY_Enter(PyObject *self) +{ + Py_XINCREF(self); + return self; +} + +static PyObject * +PyHKEY_Exit(PyObject *self, PyObject *args) +{ + if (!PyHKEY_Close(self)) + return NULL; + Py_RETURN_NONE; +} + + static struct PyMethodDef PyHKEY_methods[] = { {"Close", PyHKEY_CloseMethod, METH_VARARGS, PyHKEY_Close_doc}, {"Detach", PyHKEY_DetachMethod, METH_VARARGS, PyHKEY_Detach_doc}, + {"__enter__", (PyCFunction)PyHKEY_Enter, METH_NOARGS, NULL}, + {"__exit__", PyHKEY_Exit, METH_VARARGS, NULL}, {NULL} }; @@ -1062,6 +1084,39 @@ PyEnumValue(PyObject *self, PyObject *args) } static PyObject * +PyExpandEnvironmentStrings(PyObject *self, PyObject *args) +{ + Py_UNICODE *retValue = NULL; + Py_UNICODE *src; + DWORD retValueSize; + DWORD rc; + PyObject *o; + + if (!PyArg_ParseTuple(args, "u:ExpandEnvironmentStrings", &src)) + return NULL; + + retValueSize = ExpandEnvironmentStringsW(src, retValue, 0); + if (retValueSize == 0) { + return PyErr_SetFromWindowsErrWithFunction(retValueSize, + "ExpandEnvironmentStrings"); + } + retValue = (Py_UNICODE *)PyMem_Malloc(retValueSize * sizeof(Py_UNICODE)); + if (retValue == NULL) { + return PyErr_NoMemory(); + } + + rc = ExpandEnvironmentStringsW(src, retValue, retValueSize); + if (rc == 0) { + PyMem_Free(retValue); + return PyErr_SetFromWindowsErrWithFunction(retValueSize, + "ExpandEnvironmentStrings"); + } + o = PyUnicode_FromUnicode(retValue, wcslen(retValue)); + PyMem_Free(retValue); + return o; +} + +static PyObject * PyFlushKey(PyObject *self, PyObject *args) { HKEY hKey; @@ -1346,6 +1401,8 @@ static struct PyMethodDef winreg_methods[] = { {"DeleteValue", PyDeleteValue, METH_VARARGS, DeleteValue_doc}, {"EnumKey", PyEnumKey, METH_VARARGS, EnumKey_doc}, {"EnumValue", PyEnumValue, METH_VARARGS, EnumValue_doc}, + {"ExpandEnvironmentStrings", PyExpandEnvironmentStrings, METH_VARARGS, + ExpandEnvironmentStrings_doc }, {"FlushKey", PyFlushKey, METH_VARARGS, FlushKey_doc}, {"LoadKey", PyLoadKey, METH_VARARGS, LoadKey_doc}, {"OpenKey", PyOpenKey, METH_VARARGS, OpenKey_doc}, -- cgit v0.12