From python-3000-checkins at python.org Fri Aug 1 00:56:03 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Fri, 1 Aug 2008 00:56:03 +0200 (CEST) Subject: [Python-3000-checkins] r65341 - in python/branches/py3k: Lib/test/test_exceptions.py Python/errors.c Message-ID: <20080731225603.0C9671E4005@bag.python.org> Author: amaury.forgeotdarc Date: Fri Aug 1 00:56:02 2008 New Revision: 65341 Log: Correct one of the "MemoryError oddities": the traceback would grow each time a MemoryError is raised. Modified: python/branches/py3k/Lib/test/test_exceptions.py python/branches/py3k/Python/errors.c Modified: python/branches/py3k/Lib/test/test_exceptions.py ============================================================================== --- python/branches/py3k/Lib/test/test_exceptions.py (original) +++ python/branches/py3k/Lib/test/test_exceptions.py Fri Aug 1 00:56:02 2008 @@ -596,6 +596,24 @@ "Exception ValueError: ValueError() " "in ignored\n") + + def test_MemoryError(self): + # PyErr_NoMemory always raises the same exception instance. + # Check that the traceback is not doubled. + import traceback + def raiseMemError(): + try: + "a" * (sys.maxsize // 2) + except MemoryError as e: + tb = e.__traceback__ + else: + self.fail("Should have raises a MemoryError") + return traceback.format_tb(tb) + + tb1 = raiseMemError() + tb2 = raiseMemError() + self.assertEqual(tb1, tb2) + def test_main(): run_unittest(ExceptionTests) Modified: python/branches/py3k/Python/errors.c ============================================================================== --- python/branches/py3k/Python/errors.c (original) +++ python/branches/py3k/Python/errors.c Fri Aug 1 00:56:02 2008 @@ -321,7 +321,17 @@ /* raise the pre-allocated instance if it still exists */ if (PyExc_MemoryErrorInst) + { + /* Clear the previous traceback, otherwise it will be appended + * to the current one. + * + * The following statement is not likely to raise any error; + * if it does, we simply discard it. + */ + PyException_SetTraceback(PyExc_MemoryErrorInst, Py_None); + PyErr_SetObject(PyExc_MemoryError, PyExc_MemoryErrorInst); + } else /* this will probably fail since there's no memory and hee, hee, we have to instantiate this class From python-3000-checkins at python.org Fri Aug 1 02:06:50 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Fri, 1 Aug 2008 02:06:50 +0200 (CEST) Subject: [Python-3000-checkins] r65343 - in python/branches/py3k: Lib/os.py Lib/test/test_urllibnet.py Misc/NEWS Message-ID: <20080801000650.22B161E4005@bag.python.org> Author: amaury.forgeotdarc Date: Fri Aug 1 02:06:49 2008 New Revision: 65343 Log: #2491: os.fdopen() is now almost an alias to the builtin open(), and accepts the same parameters. It just checks that the first argument is a file descriptor. Modified: python/branches/py3k/Lib/os.py python/branches/py3k/Lib/test/test_urllibnet.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/os.py ============================================================================== --- python/branches/py3k/Lib/os.py (original) +++ python/branches/py3k/Lib/os.py Fri Aug 1 02:06:49 2008 @@ -651,9 +651,9 @@ def __iter__(self): return iter(self._stream) -# Supply os.fdopen() (used by subprocess!) -def fdopen(fd, mode="r", buffering=-1): +# Supply os.fdopen() +def fdopen(fd, *args, **kwargs): if not isinstance(fd, int): raise TypeError("invalid fd type (%s, expected integer)" % type(fd)) import io - return io.open(fd, mode, buffering) + return io.open(fd, *args, **kwargs) Modified: python/branches/py3k/Lib/test/test_urllibnet.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllibnet.py (original) +++ python/branches/py3k/Lib/test/test_urllibnet.py Fri Aug 1 02:06:49 2008 @@ -113,18 +113,14 @@ self.assertEqual(code, 404) def test_fileno(self): - if (sys.platform in ('win32',) or - not hasattr(os, 'fdopen')): + if sys.platform in ('win32',): # On Windows, socket handles are not file descriptors; this # test can't pass on Windows. return # Make sure fd returned by fileno is valid. open_url = self.urlopen("http://www.python.org/") fd = open_url.fileno() - # XXX(nnorwitz): There is currently no way to pass errors, encoding, - # etc to fdopen. :-( - FILE = os.fdopen(fd) - FILE._errors = 'ignore' + FILE = os.fdopen(fd, encoding='utf-8') try: self.assert_(FILE.read(), "reading from file created using fd " "returned by fileno failed") @@ -156,7 +152,7 @@ file_location,info = self.urlretrieve("http://www.python.org/") self.assert_(os.path.exists(file_location), "file location returned by" " urlretrieve is not a valid path") - FILE = open(file_location, errors='ignore') + FILE = open(file_location, encoding='utf-8') try: self.assert_(FILE.read(), "reading from the file location returned" " by urlretrieve failed") @@ -170,7 +166,7 @@ support.TESTFN) self.assertEqual(file_location, support.TESTFN) self.assert_(os.path.exists(file_location)) - FILE = open(file_location, errors='ignore') + FILE = open(file_location, encoding='utf-8') try: self.assert_(FILE.read(), "reading from temporary file failed") finally: Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Aug 1 02:06:49 2008 @@ -18,6 +18,10 @@ Library ------- +- Issue #2491: os.fdopen is now almost an alias for the built-in open(), and + accepts the same parameters. It just checks that its first argument is an + integer. + - Issue #3394: zipfile.writestr sets external attributes when passed a file name rather than a ZipInfo instance, so files are extracted with mode 0600 rather than 000 under Unix. From python-3000-checkins at python.org Fri Aug 1 02:14:22 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Fri, 1 Aug 2008 02:14:22 +0200 (CEST) Subject: [Python-3000-checkins] r65344 - in python/branches/py3k/Lib/test: test_os.py test_posix.py Message-ID: <20080801001422.BAB0D1E4005@bag.python.org> Author: amaury.forgeotdarc Date: Fri Aug 1 02:14:22 2008 New Revision: 65344 Log: posix.fdopen does not exists any more; and os.fdopen exists on all platforms. Move tests from test_posix to test_os. Modified: python/branches/py3k/Lib/test/test_os.py python/branches/py3k/Lib/test/test_posix.py Modified: python/branches/py3k/Lib/test/test_os.py ============================================================================== --- python/branches/py3k/Lib/test/test_os.py (original) +++ python/branches/py3k/Lib/test/test_os.py Fri Aug 1 02:14:22 2008 @@ -134,6 +134,16 @@ else: self.check_tempfile(name) + def fdopen_helper(self, *args): + fd = os.open(support.TESTFN, os.O_RDONLY) + fp2 = os.fdopen(fd, *args) + fp2.close() + + def test_fdopen(self): + self.fdopen_helper() + self.fdopen_helper('r') + self.fdopen_helper('r', 100) + # Test attributes on return values from os.*stat* family. class StatAttributeTests(unittest.TestCase): def setUp(self): Modified: python/branches/py3k/Lib/test/test_posix.py ============================================================================== --- python/branches/py3k/Lib/test/test_posix.py (original) +++ python/branches/py3k/Lib/test/test_posix.py Fri Aug 1 02:14:22 2008 @@ -89,17 +89,6 @@ fp1.close() fp2.close() - def fdopen_helper(self, *args): - fd = os.open(support.TESTFN, os.O_RDONLY) - fp2 = posix.fdopen(fd, *args) - fp2.close() - - def test_fdopen(self): - if hasattr(posix, 'fdopen'): - self.fdopen_helper() - self.fdopen_helper('r') - self.fdopen_helper('r', 100) - def test_osexlock(self): if hasattr(posix, "O_EXLOCK"): fd = os.open(support.TESTFN, From python-3000-checkins at python.org Fri Aug 1 03:06:32 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Fri, 1 Aug 2008 03:06:32 +0200 (CEST) Subject: [Python-3000-checkins] r65345 - in python/branches/py3k: Lib/test/test_builtin.py Lib/test/test_exceptions.py Lib/test/test_unicode.py Objects/unicodeobject.c Python/bltinmodule.c Message-ID: <20080801010632.C688E1E4005@bag.python.org> Author: amaury.forgeotdarc Date: Fri Aug 1 03:06:32 2008 New Revision: 65345 Log: Merged revisions 65339-65340,65342 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65339 | amaury.forgeotdarc | 2008-07-31 23:28:03 +0200 (jeu., 31 juil. 2008) | 5 lines #3479: unichr(2**32) used to return u'\x00'. The argument was fetched in a long, but PyUnicode_FromOrdinal takes an int. (why doesn't gcc issue a truncation warning in this case?) ........ r65340 | amaury.forgeotdarc | 2008-07-31 23:35:03 +0200 (jeu., 31 juil. 2008) | 2 lines Remove a dummy test that was checked in by mistake ........ r65342 | amaury.forgeotdarc | 2008-08-01 01:39:05 +0200 (ven., 01 ao?t 2008) | 8 lines Correct a crash when two successive unicode allocations fail with a MemoryError: the freelist contained half-initialized objects with freed pointers. The comment /* XXX UNREF/NEWREF interface should be more symmetrical */ was copied from tupleobject.c, and appears in some other places. I sign the petition. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_builtin.py python/branches/py3k/Lib/test/test_exceptions.py python/branches/py3k/Lib/test/test_unicode.py python/branches/py3k/Objects/unicodeobject.c python/branches/py3k/Python/bltinmodule.c Modified: python/branches/py3k/Lib/test/test_builtin.py ============================================================================== --- python/branches/py3k/Lib/test/test_builtin.py (original) +++ python/branches/py3k/Lib/test/test_builtin.py Fri Aug 1 03:06:32 2008 @@ -216,6 +216,7 @@ self.assertEqual(chr(0x0010FFFF), "\U0010FFFF") self.assertRaises(ValueError, chr, -1) self.assertRaises(ValueError, chr, 0x00110000) + self.assertRaises((OverflowError, ValueError), chr, 2**32) def test_cmp(self): self.assertEqual(cmp(-1, 1), -1) Modified: python/branches/py3k/Lib/test/test_exceptions.py ============================================================================== --- python/branches/py3k/Lib/test/test_exceptions.py (original) +++ python/branches/py3k/Lib/test/test_exceptions.py Fri Aug 1 03:06:32 2008 @@ -12,14 +12,6 @@ class ExceptionTests(unittest.TestCase): - def test00(self): - try: - sys.exit(ValueError('aaa')) - except SystemExit: - pass - finally: - pass - def raise_catch(self, exc, excname): try: raise exc("spam") Modified: python/branches/py3k/Lib/test/test_unicode.py ============================================================================== --- python/branches/py3k/Lib/test/test_unicode.py (original) +++ python/branches/py3k/Lib/test/test_unicode.py Fri Aug 1 03:06:32 2008 @@ -1156,6 +1156,20 @@ self.assertRaises(OverflowError, 't\tt\t'.expandtabs, sys.maxsize) + def test_raiseMemError(self): + # Ensure that the freelist contains a consistent object, even + # when a string allocation fails with a MemoryError. + # This used to crash the interpreter, + # or leak references when the number was smaller. + try: + "a" * (sys.maxsize // 2 - 100) + except MemoryError: + pass + try: + "a" * (sys.maxsize // 2 - 100) + except MemoryError: + pass + def test_main(): support.run_unittest(__name__) Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Fri Aug 1 03:06:32 2008 @@ -322,7 +322,7 @@ if ((unicode->length < length) && unicode_resize(unicode, length) < 0) { PyObject_DEL(unicode->str); - goto onError; + unicode->str = NULL; } } else { @@ -360,6 +360,8 @@ return unicode; onError: + /* XXX UNREF/NEWREF interface should be more symmetrical */ + _Py_DEC_REFTOTAL; _Py_ForgetReference((PyObject *)unicode); PyObject_Del(unicode); return NULL; Modified: python/branches/py3k/Python/bltinmodule.c ============================================================================== --- python/branches/py3k/Python/bltinmodule.c (original) +++ python/branches/py3k/Python/bltinmodule.c Fri Aug 1 03:06:32 2008 @@ -454,9 +454,9 @@ static PyObject * builtin_chr(PyObject *self, PyObject *args) { - long x; + int x; - if (!PyArg_ParseTuple(args, "l:chr", &x)) + if (!PyArg_ParseTuple(args, "i:chr", &x)) return NULL; return PyUnicode_FromOrdinal(x); From python-3000-checkins at python.org Fri Aug 1 03:23:09 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Fri, 1 Aug 2008 03:23:09 +0200 (CEST) Subject: [Python-3000-checkins] r65347 - python/branches/py3k Message-ID: <20080801012309.95B681E4005@bag.python.org> Author: brett.cannon Date: Fri Aug 1 03:23:09 2008 New Revision: 65347 Log: Blocked revisions 65346 via svnmerge ........ r65346 | brett.cannon | 2008-07-31 18:21:50 -0700 (Thu, 31 Jul 2008) | 1 line Fix a DeprecationWarning about __getitem__() and exceptions in the 'traceback' module. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 1 03:34:41 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Fri, 1 Aug 2008 03:34:41 +0200 (CEST) Subject: [Python-3000-checkins] r65350 - python/branches/py3k Message-ID: <20080801013441.20D7B1E4005@bag.python.org> Author: brett.cannon Date: Fri Aug 1 03:34:40 2008 New Revision: 65350 Log: Blocked revisions 65349 via svnmerge ........ r65349 | brett.cannon | 2008-07-31 18:34:05 -0700 (Thu, 31 Jul 2008) | 3 lines Remove assignment to True/False to silence the SyntaxWarning that is triggered by -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 1 03:38:48 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Fri, 1 Aug 2008 03:38:48 +0200 (CEST) Subject: [Python-3000-checkins] r65352 - python/branches/py3k Message-ID: <20080801013848.15D101E4005@bag.python.org> Author: brett.cannon Date: Fri Aug 1 03:38:47 2008 New Revision: 65352 Log: Blocked revisions 65351 via svnmerge ........ r65351 | brett.cannon | 2008-07-31 18:36:47 -0700 (Thu, 31 Jul 2008) | 3 lines Remove use of tuple unpacking and dict.has_key() so as to silence SyntaxWarning as triggered by -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 1 03:41:04 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Fri, 1 Aug 2008 03:41:04 +0200 (CEST) Subject: [Python-3000-checkins] r65354 - python/branches/py3k Message-ID: <20080801014104.680061E4005@bag.python.org> Author: brett.cannon Date: Fri Aug 1 03:41:04 2008 New Revision: 65354 Log: Blocked revisions 65353 via svnmerge ........ r65353 | brett.cannon | 2008-07-31 18:40:24 -0700 (Thu, 31 Jul 2008) | 4 lines Silence (Syntax|Deprecation)Warning for 'inspect'. Had to remove tuple unpacking in a parameter list and set some constants by hand that were pulled from the 'compiler' package. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 1 10:16:14 2008 From: python-3000-checkins at python.org (mark.dickinson) Date: Fri, 1 Aug 2008 10:16:14 +0200 (CEST) Subject: [Python-3000-checkins] r65365 - in python/branches/py3k: Doc/library/math.rst Doc/whatsnew/2.6.rst Lib/test/test_math.py Lib/test/test_random.py Modules/mathmodule.c Message-ID: <20080801081614.7FB921E400C@bag.python.org> Author: mark.dickinson Date: Fri Aug 1 10:16:13 2008 New Revision: 65365 Log: Merged revisions 65258,65292,65299,65308-65309,65315,65326 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65258 | mark.dickinson | 2008-07-27 08:15:29 +0100 (Sun, 27 Jul 2008) | 4 lines Remove math.sum tests related to overflow, special values, and behaviour near the extremes of the floating-point range. (The behaviour of math.sum should be regarded as undefined in these cases.) ........ r65292 | mark.dickinson | 2008-07-29 19:45:38 +0100 (Tue, 29 Jul 2008) | 4 lines More modifications to tests for math.sum: replace the Python version of msum by a version using a different algorithm, and use the new float.fromhex method to specify test results exactly. ........ r65299 | mark.dickinson | 2008-07-30 13:01:41 +0100 (Wed, 30 Jul 2008) | 5 lines Fix special-value handling for math.sum. Also minor cleanups to the code: fix tabbing, remove trailing whitespace, and reformat to fit into 80 columns. ........ r65308 | mark.dickinson | 2008-07-30 17:20:10 +0100 (Wed, 30 Jul 2008) | 2 lines Rename math.sum to math.fsum ........ r65309 | mark.dickinson | 2008-07-30 17:25:16 +0100 (Wed, 30 Jul 2008) | 3 lines Replace math.sum with math.fsum in a couple of comments that were missed by r65308 ........ r65315 | mark.dickinson | 2008-07-30 21:23:15 +0100 (Wed, 30 Jul 2008) | 2 lines Add note about problems with math.fsum on x86 hardware. ........ r65326 | mark.dickinson | 2008-07-31 15:48:32 +0100 (Thu, 31 Jul 2008) | 2 lines Rename testSum to testFsum and move it to proper place in test_math.py ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/math.rst python/branches/py3k/Doc/whatsnew/2.6.rst python/branches/py3k/Lib/test/test_math.py python/branches/py3k/Lib/test/test_random.py python/branches/py3k/Modules/mathmodule.c Modified: python/branches/py3k/Doc/library/math.rst ============================================================================== --- python/branches/py3k/Doc/library/math.rst (original) +++ python/branches/py3k/Doc/library/math.rst Fri Aug 1 10:16:13 2008 @@ -76,6 +76,42 @@ apart" the internal representation of a float in a portable way. +.. function:: fsum(iterable) + + Return an accurate floating point sum of values in the iterable. Avoids + loss of precision by tracking multiple intermediate partial sums. The + algorithm's accuracy depends on IEEE-754 arithmetic guarantees and the + typical case where the rounding mode is half-even. + + .. note:: + + On platforms where arithmetic results are not correctly rounded, + :func:`fsum` may occasionally produce incorrect results; these + results should be no less accurate than those from the builtin + :func:`sum` function, but nevertheless may have arbitrarily + large relative error. + + In particular, this affects some older Intel hardware (for + example Pentium and earlier x86 processors) that makes use of + 'extended precision' floating-point registers with 64 bits of + precision instead of the 53 bits of precision provided by a C + double. Arithmetic operations using these registers may be + doubly rounded (rounded first to 64 bits, and then rerounded to + 53 bits), leading to incorrectly rounded results. To test + whether your machine is one of those affected, try the following + at a Python prompt:: + + >>> 1e16 + 2.9999 + 10000000000000002.0 + + Machines subject to the double-rounding problem described above + are likely to print ``10000000000000004.0`` instead of + ``10000000000000002.0``. + + + .. versionadded:: 2.6 + + .. function:: isinf(x) Checks if the float *x* is positive or negative infinite. @@ -100,12 +136,6 @@ Return the fractional and integer parts of *x*. Both results carry the sign of *x*, and both are floats. -.. function:: sum(iterable) - - Return an accurate floating point sum of values in the iterable. Avoids - loss of precision by tracking multiple intermediate partial sums. The - algorithm's accuracy depends on IEEE-754 arithmetic guarantees and the - typical case where the rounding mode is half-even. .. function:: trunc(x) Modified: python/branches/py3k/Doc/whatsnew/2.6.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/2.6.rst (original) +++ python/branches/py3k/Doc/whatsnew/2.6.rst Fri Aug 1 10:16:13 2008 @@ -1537,7 +1537,7 @@ * :func:`~math.factorial` computes the factorial of a number. (Contributed by Raymond Hettinger; :issue:`2138`.) - * :func:`~math.sum` adds up the stream of numbers from an iterable, + * :func:`~math.fsum` adds up the stream of numbers from an iterable, and is careful to avoid loss of precision by calculating partial sums. (Contributed by Jean Brouwers, Raymond Hettinger, and Mark Dickinson; :issue:`2819`.) Modified: python/branches/py3k/Lib/test/test_math.py ============================================================================== --- python/branches/py3k/Lib/test/test_math.py (original) +++ python/branches/py3k/Lib/test/test_math.py Fri Aug 1 10:16:13 2008 @@ -359,6 +359,102 @@ self.assertEquals(math.frexp(NINF)[0], NINF) self.assert_(math.isnan(math.frexp(NAN)[0])) + def testFsum(self): + # math.fsum relies on exact rounding for correct operation. + # There's a known problem with IA32 floating-point that causes + # inexact rounding in some situations, and will cause the + # math.fsum tests below to fail; see issue #2937. On non IEEE + # 754 platforms, and on IEEE 754 platforms that exhibit the + # problem described in issue #2937, we simply skip the whole + # test. + + if not float.__getformat__("double").startswith("IEEE"): + return + + # on IEEE 754 compliant machines, both of the expressions + # below should round to 10000000000000002.0. + if 1e16+2.0 != 1e16+2.9999: + return + + # Python version of math.fsum, for comparison. Uses a + # different algorithm based on frexp, ldexp and integer + # arithmetic. + from sys import float_info + mant_dig = float_info.mant_dig + etiny = float_info.min_exp - mant_dig + + def msum(iterable): + """Full precision summation. Compute sum(iterable) without any + intermediate accumulation of error. Based on the 'lsum' function + at http://code.activestate.com/recipes/393090/ + + """ + tmant, texp = 0, 0 + for x in iterable: + mant, exp = math.frexp(x) + mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig + if texp > exp: + tmant <<= texp-exp + texp = exp + else: + mant <<= exp-texp + tmant += mant + # Round tmant * 2**texp to a float. The original recipe + # used float(str(tmant)) * 2.0**texp for this, but that's + # a little unsafe because str -> float conversion can't be + # relied upon to do correct rounding on all platforms. + tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp) + if tail > 0: + h = 1 << (tail-1) + tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1) + texp += tail + return math.ldexp(tmant, texp) + + test_values = [ + ([], 0.0), + ([0.0], 0.0), + ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100), + ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0), + ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0), + ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0), + ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0), + ([1./n for n in range(1, 1001)], + float.fromhex('0x1.df11f45f4e61ap+2')), + ([(-1.)**n/n for n in range(1, 1001)], + float.fromhex('-0x1.62a2af1bd3624p-1')), + ([1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000], -1.0), + ([1e16, 1., 1e-16], 10000000000000002.0), + ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0), + # exercise code for resizing partials array + ([2.**n - 2.**(n+50) + 2.**(n+52) for n in range(-1074, 972, 2)] + + [-2.**1022], + float.fromhex('0x1.5555555555555p+970')), + ] + + for i, (vals, expected) in enumerate(test_values): + try: + actual = math.fsum(vals) + except OverflowError: + self.fail("test %d failed: got OverflowError, expected %r " + "for math.fsum(%.100r)" % (i, expected, vals)) + except ValueError: + self.fail("test %d failed: got ValueError, expected %r " + "for math.fsum(%.100r)" % (i, expected, vals)) + self.assertEqual(actual, expected) + + from random import random, gauss, shuffle + for j in range(1000): + vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10 + s = 0 + for i in range(200): + v = gauss(0, random()) ** 7 - s + s += v + vals.append(v) + shuffle(vals) + + s = msum(vals) + self.assertEqual(msum(vals), math.fsum(vals)) + def testHypot(self): self.assertRaises(TypeError, math.hypot) self.ftest('hypot(0,0)', math.hypot(0,0), 0) @@ -641,158 +737,6 @@ self.assertRaises(ValueError, math.sqrt, NINF) self.assert_(math.isnan(math.sqrt(NAN))) - def testSum(self): - # math.sum relies on exact rounding for correct operation. - # There's a known problem with IA32 floating-point that causes - # inexact rounding in some situations, and will cause the - # math.sum tests below to fail; see issue #2937. On non IEEE - # 754 platforms, and on IEEE 754 platforms that exhibit the - # problem described in issue #2937, we simply skip the whole - # test. - - if not float.__getformat__("double").startswith("IEEE"): - return - - # on IEEE 754 compliant machines, both of the expressions - # below should round to 10000000000000002.0. - if 1e16+2.999 != 1e16+2.9999: - return - - # Python version of math.sum algorithm, for comparison - def msum(iterable): - """Full precision sum of values in iterable. Returns the value of - the sum, rounded to the nearest representable floating-point number - using the round-half-to-even rule. - - """ - # Stage 1: accumulate partials - partials = [] - for x in iterable: - i = 0 - for y in partials: - if abs(x) < abs(y): - x, y = y, x - hi = x + y - lo = y - (hi - x) - if lo: - partials[i] = lo - i += 1 - x = hi - partials[i:] = [x] if x else [] - - # Stage 2: sum partials - if not partials: - return 0.0 - - # sum from the top, stopping as soon as the sum is inexact. - total = partials.pop() - while partials: - x = partials.pop() - old_total, total = total, total + x - error = x - (total - old_total) - if error != 0.0: - # adjust for correct rounding if necessary - if partials and (partials[-1] > 0.0) == (error > 0.0) and \ - total + 2*error - total == 2*error: - total += 2*error - break - return total - - from sys import float_info - maxfloat = float_info.max - twopow = 2.**(float_info.max_exp - 1) - - test_values = [ - ([], 0.0), - ([0.0], 0.0), - ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100), - ([1e308, 1e308, -1e308], OverflowError), - ([-1e308, 1e308, 1e308], 1e308), - ([1e308, -1e308, 1e308], 1e308), - ([2.0**1023, 2.0**1023, -2.0**1000], OverflowError), - ([twopow, twopow, twopow, twopow, -twopow, -twopow, -twopow], - OverflowError), - ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0), - ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0), - ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0), - - ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0), - ([2.0**1023-2.0**970, -1.0, 2.0**1023], OverflowError), - ([maxfloat, maxfloat*2.**-54], maxfloat), - ([maxfloat, maxfloat*2.**-53], OverflowError), - ([1./n for n in range(1, 1001)], 7.4854708605503451), - ([(-1.)**n/n for n in range(1, 1001)], -0.69264743055982025), - ([1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000], -1.0), - ([INF, -INF, NAN], ValueError), - ([NAN, INF, -INF], ValueError), - ([INF, NAN, INF], ValueError), - - ([INF, INF], OverflowError), - ([INF, -INF], ValueError), - ([-INF, 1e308, 1e308, -INF], OverflowError), - ([2.0**1023-2.0**970, 0.0, 2.0**1023], OverflowError), - ([2.0**1023-2.0**970, 1.0, 2.0**1023], OverflowError), - ([2.0**1023, 2.0**1023], OverflowError), - ([2.0**1023, 2.0**1023, -1.0], OverflowError), - ([twopow, twopow, twopow, twopow, -twopow, -twopow], - OverflowError), - ([twopow, twopow, twopow, twopow, -twopow, twopow], OverflowError), - ([-twopow, -twopow, -twopow, -twopow], OverflowError), - - ([2.**1023, 2.**1023, -2.**971], OverflowError), - ([2.**1023, 2.**1023, -2.**970], OverflowError), - ([-2.**970, 2.**1023, 2.**1023, -2.**-1074], OverflowError), - ([ 2.**1023, 2.**1023, -2.**970, 2.**-1074], OverflowError), - ([-2.**1023, 2.**971, -2.**1023], -maxfloat), - ([-2.**1023, -2.**1023, 2.**970], OverflowError), - ([-2.**1023, -2.**1023, 2.**970, 2.**-1074], OverflowError), - ([-2.**-1074, -2.**1023, -2.**1023, 2.**970], OverflowError), - ([2.**930, -2.**980, 2.**1023, 2.**1023, twopow, -twopow], - OverflowError), - ([2.**1023, 2.**1023, -1e307], OverflowError), - ([1e16, 1., 1e-16], 10000000000000002.0), - ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0), - ] - - for i, (vals, s) in enumerate(test_values): - if isinstance(s, type) and issubclass(s, Exception): - try: - m = math.sum(vals) - except s: - pass - else: - self.fail("test %d failed: got %r, expected %r " - "for math.sum(%.100r)" % - (i, m, s.__name__, vals)) - else: - try: - self.assertEqual(math.sum(vals), s) - except OverflowError: - self.fail("test %d failed: got OverflowError, expected %r " - "for math.sum(%.100r)" % (i, s, vals)) - except ValueError: - self.fail("test %d failed: got ValueError, expected %r " - "for math.sum(%.100r)" % (i, s, vals)) - - # compare with output of msum above, but only when - # result isn't an IEEE special or an exception - if not math.isinf(s) and not math.isnan(s): - self.assertEqual(msum(vals), s) - - from random import random, gauss, shuffle - for j in range(1000): - vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10 - s = 0 - for i in range(200): - v = gauss(0, random()) ** 7 - s - s += v - vals.append(v) - shuffle(vals) - - s = msum(vals) - self.assertEqual(msum(vals), math.sum(vals)) - - def testTan(self): self.assertRaises(TypeError, math.tan) self.ftest('tan(0)', math.tan(0), 0) Modified: python/branches/py3k/Lib/test/test_random.py ============================================================================== --- python/branches/py3k/Lib/test/test_random.py (original) +++ python/branches/py3k/Lib/test/test_random.py Fri Aug 1 10:16:13 2008 @@ -5,7 +5,7 @@ import time import pickle import warnings -from math import log, exp, sqrt, pi, sum as msum +from math import log, exp, sqrt, pi, fsum as msum from test import support class TestBasicOps(unittest.TestCase): Modified: python/branches/py3k/Modules/mathmodule.c ============================================================================== --- python/branches/py3k/Modules/mathmodule.c (original) +++ python/branches/py3k/Modules/mathmodule.c Fri Aug 1 10:16:13 2008 @@ -396,7 +396,7 @@ Note 4: A similar implementation is in Modules/cmathmodule.c. Be sure to update both when making changes. - Note 5: The signature of math.sum() differs from __builtin__.sum() + Note 5: The signature of math.fsum() differs from __builtin__.sum() because the start argument doesn't make sense in the context of accurate summation. Since the partials table is collapsed before returning a result, sum(seq2, start=sum(seq1)) may not equal the @@ -407,7 +407,7 @@ /* Extend the partials array p[] by doubling its size. */ static int /* non-zero on error */ -_sum_realloc(double **p_ptr, Py_ssize_t n, +_fsum_realloc(double **p_ptr, Py_ssize_t n, double *ps, Py_ssize_t *m_ptr) { void *v = NULL; @@ -425,7 +425,7 @@ v = PyMem_Realloc(p, sizeof(double) * m); } if (v == NULL) { /* size overflow or no memory */ - PyErr_SetString(PyExc_MemoryError, "math sum partials"); + PyErr_SetString(PyExc_MemoryError, "math.fsum partials"); return 1; } *p_ptr = (double*) v; @@ -464,18 +464,19 @@ */ static PyObject* -math_sum(PyObject *self, PyObject *seq) +math_fsum(PyObject *self, PyObject *seq) { PyObject *item, *iter, *sum = NULL; Py_ssize_t i, j, n = 0, m = NUM_PARTIALS; double x, y, t, ps[NUM_PARTIALS], *p = ps; + double xsave, special_sum = 0.0, inf_sum = 0.0; volatile double hi, yr, lo; iter = PyObject_GetIter(seq); if (iter == NULL) return NULL; - PyFPE_START_PROTECT("sum", Py_DECREF(iter); return NULL) + PyFPE_START_PROTECT("fsum", Py_DECREF(iter); return NULL) for(;;) { /* for x in iterable */ assert(0 <= n && n <= m); @@ -485,18 +486,19 @@ item = PyIter_Next(iter); if (item == NULL) { if (PyErr_Occurred()) - goto _sum_error; + goto _fsum_error; break; } x = PyFloat_AsDouble(item); Py_DECREF(item); if (PyErr_Occurred()) - goto _sum_error; + goto _fsum_error; + xsave = x; for (i = j = 0; j < n; j++) { /* for y in partials */ y = p[j]; if (fabs(x) < fabs(y)) { - t = x; x = y; y = t; + t = x; x = y; y = t; } hi = x + y; yr = hi - x; @@ -505,59 +507,73 @@ p[i++] = lo; x = hi; } - - n = i; /* ps[i:] = [x] */ + + n = i; /* ps[i:] = [x] */ if (x != 0.0) { - /* If non-finite, reset partials, effectively - adding subsequent items without roundoff - and yielding correct non-finite results, - provided IEEE 754 rules are observed */ - if (! Py_IS_FINITE(x)) + if (! Py_IS_FINITE(x)) { + /* a nonfinite x could arise either as + a result of intermediate overflow, or + as a result of a nan or inf in the + summands */ + if (Py_IS_FINITE(xsave)) { + PyErr_SetString(PyExc_OverflowError, + "intermediate overflow in fsum"); + goto _fsum_error; + } + if (Py_IS_INFINITY(xsave)) + inf_sum += xsave; + special_sum += xsave; + /* reset partials */ n = 0; - else if (n >= m && _sum_realloc(&p, n, ps, &m)) - goto _sum_error; - p[n++] = x; + } + else if (n >= m && _fsum_realloc(&p, n, ps, &m)) + goto _fsum_error; + else + p[n++] = x; } } + if (special_sum != 0.0) { + if (Py_IS_NAN(inf_sum)) + PyErr_SetString(PyExc_ValueError, + "-inf + inf in fsum"); + else + sum = PyFloat_FromDouble(special_sum); + goto _fsum_error; + } + hi = 0.0; if (n > 0) { hi = p[--n]; - if (Py_IS_FINITE(hi)) { - /* sum_exact(ps, hi) from the top, stop when the sum becomes inexact. */ - while (n > 0) { - x = hi; - y = p[--n]; - assert(fabs(y) < fabs(x)); - hi = x + y; - yr = hi - x; - lo = y - yr; - if (lo != 0.0) - break; - } - /* Make half-even rounding work across multiple partials. Needed - so that sum([1e-16, 1, 1e16]) will round-up the last digit to - two instead of down to zero (the 1e-16 makes the 1 slightly - closer to two). With a potential 1 ULP rounding error fixed-up, - math.sum() can guarantee commutativity. */ - if (n > 0 && ((lo < 0.0 && p[n-1] < 0.0) || - (lo > 0.0 && p[n-1] > 0.0))) { - y = lo * 2.0; - x = hi + y; - yr = x - hi; - if (y == yr) - hi = x; - } + /* sum_exact(ps, hi) from the top, stop when the sum becomes + inexact. */ + while (n > 0) { + x = hi; + y = p[--n]; + assert(fabs(y) < fabs(x)); + hi = x + y; + yr = hi - x; + lo = y - yr; + if (lo != 0.0) + break; } - else { /* raise exception corresponding to a special value */ - errno = Py_IS_NAN(hi) ? EDOM : ERANGE; - if (is_error(hi)) - goto _sum_error; + /* Make half-even rounding work across multiple partials. + Needed so that sum([1e-16, 1, 1e16]) will round-up the last + digit to two instead of down to zero (the 1e-16 makes the 1 + slightly closer to two). With a potential 1 ULP rounding + error fixed-up, math.fsum() can guarantee commutativity. */ + if (n > 0 && ((lo < 0.0 && p[n-1] < 0.0) || + (lo > 0.0 && p[n-1] > 0.0))) { + y = lo * 2.0; + x = hi + y; + yr = x - hi; + if (y == yr) + hi = x; } } sum = PyFloat_FromDouble(hi); -_sum_error: +_fsum_error: PyFPE_END_PROTECT(hi) Py_DECREF(iter); if (p != ps) @@ -567,7 +583,7 @@ #undef NUM_PARTIALS -PyDoc_STRVAR(math_sum_doc, +PyDoc_STRVAR(math_fsum_doc, "sum(iterable)\n\n\ Return an accurate floating point sum of values in the iterable.\n\ Assumes IEEE-754 floating point arithmetic."); @@ -1078,6 +1094,7 @@ {"floor", math_floor, METH_O, math_floor_doc}, {"fmod", math_fmod, METH_VARARGS, math_fmod_doc}, {"frexp", math_frexp, METH_O, math_frexp_doc}, + {"fsum", math_fsum, METH_O, math_fsum_doc}, {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, {"isinf", math_isinf, METH_O, math_isinf_doc}, {"isnan", math_isnan, METH_O, math_isnan_doc}, @@ -1091,10 +1108,9 @@ {"sin", math_sin, METH_O, math_sin_doc}, {"sinh", math_sinh, METH_O, math_sinh_doc}, {"sqrt", math_sqrt, METH_O, math_sqrt_doc}, - {"sum", math_sum, METH_O, math_sum_doc}, {"tan", math_tan, METH_O, math_tan_doc}, {"tanh", math_tanh, METH_O, math_tanh_doc}, - {"trunc", math_trunc, METH_O, math_trunc_doc}, + {"trunc", math_trunc, METH_O, math_trunc_doc}, {NULL, NULL} /* sentinel */ }; From python-3000-checkins at python.org Fri Aug 1 11:14:04 2008 From: python-3000-checkins at python.org (mark.dickinson) Date: Fri, 1 Aug 2008 11:14:04 +0200 (CEST) Subject: [Python-3000-checkins] r65367 - in python/branches/py3k: Doc/library/math.rst Message-ID: <20080801091404.087C21E4006@bag.python.org> Author: mark.dickinson Date: Fri Aug 1 11:14:03 2008 New Revision: 65367 Log: Merged revisions 65366 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65366 | mark.dickinson | 2008-08-01 10:13:07 +0100 (Fri, 01 Aug 2008) | 2 lines Tone down math.fsum warning. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/math.rst Modified: python/branches/py3k/Doc/library/math.rst ============================================================================== --- python/branches/py3k/Doc/library/math.rst (original) +++ python/branches/py3k/Doc/library/math.rst Fri Aug 1 11:14:03 2008 @@ -85,29 +85,8 @@ .. note:: - On platforms where arithmetic results are not correctly rounded, - :func:`fsum` may occasionally produce incorrect results; these - results should be no less accurate than those from the builtin - :func:`sum` function, but nevertheless may have arbitrarily - large relative error. - - In particular, this affects some older Intel hardware (for - example Pentium and earlier x86 processors) that makes use of - 'extended precision' floating-point registers with 64 bits of - precision instead of the 53 bits of precision provided by a C - double. Arithmetic operations using these registers may be - doubly rounded (rounded first to 64 bits, and then rerounded to - 53 bits), leading to incorrectly rounded results. To test - whether your machine is one of those affected, try the following - at a Python prompt:: - - >>> 1e16 + 2.9999 - 10000000000000002.0 - - Machines subject to the double-rounding problem described above - are likely to print ``10000000000000004.0`` instead of - ``10000000000000002.0``. - + The accuracy of fsum() may be impaired on builds that use + extended precision addition and then double-round the results. .. versionadded:: 2.6 From python-3000-checkins at python.org Fri Aug 1 16:15:24 2008 From: python-3000-checkins at python.org (martin.v.loewis) Date: Fri, 1 Aug 2008 16:15:24 +0200 (CEST) Subject: [Python-3000-checkins] r65369 - in python/branches/py3k: Makefile.pre.in Misc/NEWS Message-ID: <20080801141524.0D03C1E400D@bag.python.org> Author: martin.v.loewis Date: Fri Aug 1 16:15:22 2008 New Revision: 65369 Log: Merged revisions 65368 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65368 | martin.v.loewis | 2008-08-01 16:10:26 +0200 (Fr, 01 Aug 2008) | 3 lines Generate the PatternGrammar pickle during "make install". Fixes part of #3131. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Makefile.pre.in python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Makefile.pre.in ============================================================================== --- python/branches/py3k/Makefile.pre.in (original) +++ python/branches/py3k/Makefile.pre.in Fri Aug 1 16:15:22 2008 @@ -890,7 +890,7 @@ -d $(LIBDEST)/site-packages -f \ -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - ./$(BUILDPYTHON) -Wi -c "import lib2to3.pygram" + ./$(BUILDPYTHON) -Wi -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" # Create the PLATDIR source directory, if one wasn't distributed.. $(srcdir)/Lib/$(PLATDIR): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Aug 1 16:15:22 2008 @@ -26,9 +26,22 @@ file name rather than a ZipInfo instance, so files are extracted with mode 0600 rather than 000 under Unix. +<<<<<<< .working - Issue #2523: Fix quadratic behaviour when read()ing a binary file without asking for a specific length. +======= +Build +----- +>>>>>>> .merge-right.r65368 + +<<<<<<< .working +======= +- Generate the PatternGrammar pickle during "make install". + +What's New in Python 2.6 beta 2? +================================ +>>>>>>> .merge-right.r65368 What's new in Python 3.0b2? =========================== From python-3000-checkins at python.org Fri Aug 1 18:19:40 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Fri, 1 Aug 2008 18:19:40 +0200 (CEST) Subject: [Python-3000-checkins] r65370 - python/branches/py3k Message-ID: <20080801161940.D51A91E400F@bag.python.org> Author: benjamin.peterson Date: Fri Aug 1 18:19:40 2008 New Revision: 65370 Log: Blocked revisions 65355 via svnmerge ........ r65355 | brett.cannon | 2008-07-31 20:45:49 -0500 (Thu, 31 Jul 2008) | 2 lines Remove a use of callable() to silence the warning triggered under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 1 18:25:13 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Fri, 1 Aug 2008 18:25:13 +0200 (CEST) Subject: [Python-3000-checkins] r65371 - python/branches/py3k/Misc/NEWS Message-ID: <20080801162513.3B0691E4006@bag.python.org> Author: georg.brandl Date: Fri Aug 1 18:25:12 2008 New Revision: 65371 Log: Fix merge conflict. Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Aug 1 18:25:12 2008 @@ -26,22 +26,8 @@ file name rather than a ZipInfo instance, so files are extracted with mode 0600 rather than 000 under Unix. -<<<<<<< .working - Issue #2523: Fix quadratic behaviour when read()ing a binary file without asking for a specific length. -======= -Build ------ ->>>>>>> .merge-right.r65368 - -<<<<<<< .working -======= -- Generate the PatternGrammar pickle during "make install". - - -What's New in Python 2.6 beta 2? -================================ ->>>>>>> .merge-right.r65368 What's new in Python 3.0b2? =========================== From python-3000-checkins at python.org Sat Aug 2 04:03:58 2008 From: python-3000-checkins at python.org (jesse.noller) Date: Sat, 2 Aug 2008 04:03:58 +0200 (CEST) Subject: [Python-3000-checkins] r65381 - in python/branches/py3k: Modules/_multiprocessing/connection.h Modules/_multiprocessing/pipe_connection.c Modules/_multiprocessing/socket_connection.c Message-ID: <20080802020358.BE0921E4003@bag.python.org> Author: jesse.noller Date: Sat Aug 2 04:03:58 2008 New Revision: 65381 Log: Merge 65376 into 3k, fix for issue 3399 Modified: python/branches/py3k/ (props changed) python/branches/py3k/Modules/_multiprocessing/connection.h python/branches/py3k/Modules/_multiprocessing/pipe_connection.c python/branches/py3k/Modules/_multiprocessing/socket_connection.c Modified: python/branches/py3k/Modules/_multiprocessing/connection.h ============================================================================== --- python/branches/py3k/Modules/_multiprocessing/connection.h (original) +++ python/branches/py3k/Modules/_multiprocessing/connection.h Sat Aug 2 04:03:58 2008 @@ -129,9 +129,7 @@ } } - Py_BEGIN_ALLOW_THREADS res = conn_send_string(self, buffer + offset, size); - Py_END_ALLOW_THREADS if (res < 0) return mp_SetError(PyExc_IOError, res); @@ -156,10 +154,8 @@ return NULL; } - Py_BEGIN_ALLOW_THREADS res = conn_recv_string(self, self->buffer, CONNECTION_BUFFER_SIZE, &freeme, maxlength); - Py_END_ALLOW_THREADS if (res < 0) { if (res == MP_BAD_MESSAGE_LENGTH) { @@ -208,10 +204,8 @@ return NULL; } - Py_BEGIN_ALLOW_THREADS res = conn_recv_string(self, buffer+offset, length-offset, &freeme, PY_SSIZE_T_MAX); - Py_END_ALLOW_THREADS if (res < 0) { if (res == MP_BAD_MESSAGE_LENGTH) { @@ -266,9 +260,7 @@ if (PyBytes_AsStringAndSize(pickled_string, &buffer, &length) < 0) goto failure; - Py_BEGIN_ALLOW_THREADS res = conn_send_string(self, buffer, (int)length); - Py_END_ALLOW_THREADS if (res < 0) { mp_SetError(PyExc_IOError, res); @@ -292,10 +284,8 @@ CHECK_READABLE(self); - Py_BEGIN_ALLOW_THREADS res = conn_recv_string(self, self->buffer, CONNECTION_BUFFER_SIZE, &freeme, PY_SSIZE_T_MAX); - Py_END_ALLOW_THREADS if (res < 0) { if (res == MP_BAD_MESSAGE_LENGTH) { Modified: python/branches/py3k/Modules/_multiprocessing/pipe_connection.c ============================================================================== --- python/branches/py3k/Modules/_multiprocessing/pipe_connection.c (original) +++ python/branches/py3k/Modules/_multiprocessing/pipe_connection.c Sat Aug 2 04:03:58 2008 @@ -18,9 +18,12 @@ conn_send_string(ConnectionObject *conn, char *string, size_t length) { DWORD amount_written; + BOOL ret; - return WriteFile(conn->handle, string, length, &amount_written, NULL) - ? MP_SUCCESS : MP_STANDARD_ERROR; + Py_BEGIN_ALLOW_THREADS + ret = WriteFile(conn->handle, string, length, &amount_written, NULL); + Py_END_ALLOW_THREADS + return ret ? MP_SUCCESS : MP_STANDARD_ERROR; } /* @@ -34,11 +37,14 @@ size_t buflength, char **newbuffer, size_t maxlength) { DWORD left, length, full_length, err; - + BOOL ret; *newbuffer = NULL; - if (ReadFile(conn->handle, buffer, MIN(buflength, maxlength), - &length, NULL)) + Py_BEGIN_ALLOW_THREADS + ret = ReadFile(conn->handle, buffer, MIN(buflength, maxlength), + &length, NULL); + Py_END_ALLOW_THREADS + if (ret) return length; err = GetLastError(); @@ -61,7 +67,10 @@ memcpy(*newbuffer, buffer, length); - if (ReadFile(conn->handle, *newbuffer+length, left, &length, NULL)) { + Py_BEGIN_ALLOW_THREADS + ret = ReadFile(conn->handle, *newbuffer+length, left, &length, NULL) + Py_END_ALLOW_THREADS + if (ret) { assert(length == left); return full_length; } else { Modified: python/branches/py3k/Modules/_multiprocessing/socket_connection.c ============================================================================== --- python/branches/py3k/Modules/_multiprocessing/socket_connection.c (original) +++ python/branches/py3k/Modules/_multiprocessing/socket_connection.c Sat Aug 2 04:03:58 2008 @@ -73,6 +73,7 @@ static Py_ssize_t conn_send_string(ConnectionObject *conn, char *string, size_t length) { + Py_ssize_t res; /* The "header" of the message is a 32 bit unsigned number (in network order) which specifies the length of the "body". If the message is shorter than about 16kb then it is quicker to @@ -80,7 +81,6 @@ them at once. */ if (length < (16*1024)) { char *message; - int res; message = PyMem_Malloc(length+4); if (message == NULL) @@ -88,9 +88,10 @@ *(UINT32*)message = htonl((UINT32)length); memcpy(message+4, string, length); + Py_BEGIN_ALLOW_THREADS res = _conn_sendall(conn->handle, message, length+4); + Py_END_ALLOW_THREADS PyMem_Free(message); - return res; } else { UINT32 lenbuff; @@ -98,9 +99,12 @@ return MP_BAD_MESSAGE_LENGTH; lenbuff = htonl((UINT32)length); - return _conn_sendall(conn->handle, (char*)&lenbuff, 4) || + Py_BEGIN_ALLOW_THREADS + res = _conn_sendall(conn->handle, (char*)&lenbuff, 4) || _conn_sendall(conn->handle, string, length); + Py_END_ALLOW_THREADS } + return res; } /* @@ -118,7 +122,9 @@ *newbuffer = NULL; + Py_BEGIN_ALLOW_THREADS res = _conn_recvall(conn->handle, (char*)&ulength, 4); + Py_END_ALLOW_THREADS if (res < 0) return res; @@ -127,13 +133,17 @@ return MP_BAD_MESSAGE_LENGTH; if (ulength <= buflength) { + Py_BEGIN_ALLOW_THREADS res = _conn_recvall(conn->handle, buffer, (size_t)ulength); + Py_END_ALLOW_THREADS return res < 0 ? res : ulength; } else { *newbuffer = PyMem_Malloc((size_t)ulength); if (*newbuffer == NULL) return MP_MEMORY_ERROR; + Py_BEGIN_ALLOW_THREADS res = _conn_recvall(conn->handle, *newbuffer, (size_t)ulength); + Py_END_ALLOW_THREADS return res < 0 ? (Py_ssize_t)res : (Py_ssize_t)ulength; } } From python-3000-checkins at python.org Sat Aug 2 05:08:50 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 2 Aug 2008 05:08:50 +0200 (CEST) Subject: [Python-3000-checkins] r65384 - python/branches/py3k Message-ID: <20080802030850.213971E4003@bag.python.org> Author: benjamin.peterson Date: Sat Aug 2 05:08:49 2008 New Revision: 65384 Log: Blocked revisions 65382-65383 via svnmerge ........ r65382 | benjamin.peterson | 2008-08-01 21:57:17 -0500 (Fri, 01 Aug 2008) | 1 line fix indentation that caused logic bug ........ r65383 | benjamin.peterson | 2008-08-01 22:05:11 -0500 (Fri, 01 Aug 2008) | 1 line revert last revision; code was right ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 2 05:15:59 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sat, 2 Aug 2008 05:15:59 +0200 (CEST) Subject: [Python-3000-checkins] r65388 - python/branches/py3k Message-ID: <20080802031559.0B1481E4003@bag.python.org> Author: brett.cannon Date: Sat Aug 2 05:15:58 2008 New Revision: 65388 Log: Blocked revisions 65386 via svnmerge ........ r65386 | brett.cannon | 2008-08-01 20:13:46 -0700 (Fri, 01 Aug 2008) | 3 lines Remove a tuple unpacking in a parameter list to suppress the SyntaxWarning with -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 2 05:16:32 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sat, 2 Aug 2008 05:16:32 +0200 (CEST) Subject: [Python-3000-checkins] r65389 - python/branches/py3k Message-ID: <20080802031632.747C21E4003@bag.python.org> Author: brett.cannon Date: Sat Aug 2 05:16:31 2008 New Revision: 65389 Log: Blocked revisions 65387 via svnmerge ........ r65387 | brett.cannon | 2008-08-01 20:15:20 -0700 (Fri, 01 Aug 2008) | 3 lines Remove a tuple unpacking in a parameter list to remove a SyntaxWarning raised while running under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 2 05:17:02 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 2 Aug 2008 05:17:02 +0200 (CEST) Subject: [Python-3000-checkins] r65390 - in python/branches/py3k: Modules/_multiprocessing/pipe_connection.c Message-ID: <20080802031703.0A84B1E4003@bag.python.org> Author: benjamin.peterson Date: Sat Aug 2 05:17:02 2008 New Revision: 65390 Log: Merged revisions 65385 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65385 | benjamin.peterson | 2008-08-01 22:11:16 -0500 (Fri, 01 Aug 2008) | 1 line fix compile error on Windows ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Modules/_multiprocessing/pipe_connection.c Modified: python/branches/py3k/Modules/_multiprocessing/pipe_connection.c ============================================================================== --- python/branches/py3k/Modules/_multiprocessing/pipe_connection.c (original) +++ python/branches/py3k/Modules/_multiprocessing/pipe_connection.c Sat Aug 2 05:17:02 2008 @@ -68,7 +68,7 @@ memcpy(*newbuffer, buffer, length); Py_BEGIN_ALLOW_THREADS - ret = ReadFile(conn->handle, *newbuffer+length, left, &length, NULL) + ret = ReadFile(conn->handle, *newbuffer+length, left, &length, NULL); Py_END_ALLOW_THREADS if (ret) { assert(length == left); From python-3000-checkins at python.org Sat Aug 2 05:29:56 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sat, 2 Aug 2008 05:29:56 +0200 (CEST) Subject: [Python-3000-checkins] r65392 - python/branches/py3k Message-ID: <20080802032956.589841E4003@bag.python.org> Author: brett.cannon Date: Sat Aug 2 05:29:56 2008 New Revision: 65392 Log: Blocked revisions 65391 via svnmerge ........ r65391 | brett.cannon | 2008-08-01 20:28:42 -0700 (Fri, 01 Aug 2008) | 2 lines Remove a dict.has_key() use to silence a warning raised under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 2 05:32:49 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sat, 2 Aug 2008 05:32:49 +0200 (CEST) Subject: [Python-3000-checkins] r65394 - python/branches/py3k Message-ID: <20080802033249.5278A1E4003@bag.python.org> Author: brett.cannon Date: Sat Aug 2 05:32:49 2008 New Revision: 65394 Log: Blocked revisions 65393 via svnmerge ........ r65393 | brett.cannon | 2008-08-01 20:32:13 -0700 (Fri, 01 Aug 2008) | 2 lines Remove a dict.has_key() use to silence a warning when running under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 2 05:38:29 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sat, 2 Aug 2008 05:38:29 +0200 (CEST) Subject: [Python-3000-checkins] r65396 - python/branches/py3k Message-ID: <20080802033829.537171E4003@bag.python.org> Author: brett.cannon Date: Sat Aug 2 05:38:29 2008 New Revision: 65396 Log: Blocked revisions 65395 via svnmerge ........ r65395 | brett.cannon | 2008-08-01 20:37:50 -0700 (Fri, 01 Aug 2008) | 3 lines Remove a __getitem__() removal on an exception to silence a warning triggered under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 2 09:23:15 2008 From: python-3000-checkins at python.org (martin.v.loewis) Date: Sat, 2 Aug 2008 09:23:15 +0200 (CEST) Subject: [Python-3000-checkins] r65401 - in python/branches/py3k: Lib/tkinter/__init__.py Message-ID: <20080802072315.73D101E4003@bag.python.org> Author: martin.v.loewis Date: Sat Aug 2 09:23:15 2008 New Revision: 65401 Log: Merged revisions 65399 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65399 | martin.v.loewis | 2008-08-02 09:20:25 +0200 (Sa, 02 Aug 2008) | 3 lines Issue #799428: Fix Tkinter.Misc._nametowidget to unwrap Tcl command objects. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/tkinter/__init__.py Modified: python/branches/py3k/Lib/tkinter/__init__.py ============================================================================== --- python/branches/py3k/Lib/tkinter/__init__.py (original) +++ python/branches/py3k/Lib/tkinter/__init__.py Sat Aug 2 09:23:15 2008 @@ -1063,18 +1063,18 @@ def nametowidget(self, name): """Return the Tkinter instance of a widget identified by its Tcl name NAME.""" + name = str(name).split('.') w = self - if name[0] == '.': + + if not name[0]: w = w._root() name = name[1:] - while name: - i = name.find('.') - if i >= 0: - name, tail = name[:i], name[i+1:] - else: - tail = '' - w = w.children[name] - name = tail + + for n in name: + if not n: + break + w = w.children[n] + return w _nametowidget = nametowidget def _register(self, func, subst=None, needcleanup=1): From python-3000-checkins at python.org Sat Aug 2 13:36:08 2008 From: python-3000-checkins at python.org (lars.gustaebel) Date: Sat, 2 Aug 2008 13:36:08 +0200 (CEST) Subject: [Python-3000-checkins] r65403 - python/branches/py3k Message-ID: <20080802113608.DCDE11E4003@bag.python.org> Author: lars.gustaebel Date: Sat Aug 2 13:36:08 2008 New Revision: 65403 Log: Blocked revisions 65402 via svnmerge ........ r65402 | lars.gustaebel | 2008-08-02 13:26:39 +0200 (Sat, 02 Aug 2008) | 5 lines Issue #3039: Fix TarFileCompat.writestr() which always raised an AttributeError since __slots__ were added to zipfile.ZipInfo in r46967 two years ago. Add a warning about the removal of TarFileCompat in Python 3.0. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 2 13:43:24 2008 From: python-3000-checkins at python.org (lars.gustaebel) Date: Sat, 2 Aug 2008 13:43:24 +0200 (CEST) Subject: [Python-3000-checkins] r65404 - in python/branches/py3k: Doc/library/tarfile.rst Lib/tarfile.py Misc/NEWS Message-ID: <20080802114324.80C551E4003@bag.python.org> Author: lars.gustaebel Date: Sat Aug 2 13:43:24 2008 New Revision: 65404 Log: Remove the TarFileCompat class from tarfile.py. Modified: python/branches/py3k/Doc/library/tarfile.rst python/branches/py3k/Lib/tarfile.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/tarfile.rst ============================================================================== --- python/branches/py3k/Doc/library/tarfile.rst (original) +++ python/branches/py3k/Doc/library/tarfile.rst Sat Aug 2 13:43:24 2008 @@ -119,21 +119,7 @@ module can read. -.. class:: TarFileCompat(filename, mode='r', compression=TAR_PLAIN) - - Class for limited access to tar archives with a :mod:`zipfile`\ -like interface. - Please consult the documentation of the :mod:`zipfile` module for more details. - *compression* must be one of the following constants: - - - .. data:: TAR_PLAIN - - Constant for an uncompressed tar archive. - - - .. data:: TAR_GZIPPED - - Constant for a :mod:`gzip` compressed tar archive. +The :mod:`tarfile` module defines the following exceptions: .. exception:: TarError Modified: python/branches/py3k/Lib/tarfile.py ============================================================================== --- python/branches/py3k/Lib/tarfile.py (original) +++ python/branches/py3k/Lib/tarfile.py Sat Aug 2 13:43:24 2008 @@ -2451,54 +2451,6 @@ self.idx = idx return item -#--------------------------------------------- -# zipfile compatible TarFile class -#--------------------------------------------- -TAR_PLAIN = 0 # zipfile.ZIP_STORED -TAR_GZIPPED = 8 # zipfile.ZIP_DEFLATED -class TarFileCompat: - """TarFile class compatible with standard module zipfile's - ZipFile class. - """ - def __init__(self, file, mode="r", compression=TAR_PLAIN): - if compression == TAR_PLAIN: - self.tarfile = TarFile.taropen(file, mode) - elif compression == TAR_GZIPPED: - self.tarfile = TarFile.gzopen(file, mode) - else: - raise ValueError("unknown compression constant") - if mode[0:1] == "r": - members = self.tarfile.getmembers() - for m in members: - m.filename = m.name - m.file_size = m.size - m.date_time = time.gmtime(m.mtime)[:6] - def namelist(self): - return map(lambda m: m.name, self.infolist()) - def infolist(self): - return filter(lambda m: m.type in REGULAR_TYPES, - self.tarfile.getmembers()) - def printdir(self): - self.tarfile.list() - def testzip(self): - return - def getinfo(self, name): - return self.tarfile.getmember(name) - def read(self, name): - return self.tarfile.extractfile(self.tarfile.getmember(name)).read() - def write(self, filename, arcname=None, compress_type=None): - self.tarfile.add(filename, arcname) - def writestr(self, zinfo, bytes): - from io import StringIO - import calendar - zinfo.name = zinfo.filename - zinfo.size = zinfo.file_size - zinfo.mtime = calendar.timegm(zinfo.date_time) - self.tarfile.addfile(zinfo, StringIO(bytes)) - def close(self): - self.tarfile.close() -#class TarFileCompat - #-------------------- # exported functions #-------------------- Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Aug 2 13:43:24 2008 @@ -18,6 +18,8 @@ Library ------- +- Remove the TarFileCompat class from tarfile.py. + - Issue #2491: os.fdopen is now almost an alias for the built-in open(), and accepts the same parameters. It just checks that its first argument is an integer. From python-3000-checkins at python.org Sat Aug 2 18:34:27 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sat, 2 Aug 2008 18:34:27 +0200 (CEST) Subject: [Python-3000-checkins] r65412 - python/branches/py3k/Doc/library/stdtypes.rst Message-ID: <20080802163427.DD66D1E4003@bag.python.org> Author: georg.brandl Date: Sat Aug 2 18:34:27 2008 New Revision: 65412 Log: str.join() doesn't convert arguments anymore. Modified: python/branches/py3k/Doc/library/stdtypes.rst Modified: python/branches/py3k/Doc/library/stdtypes.rst ============================================================================== --- python/branches/py3k/Doc/library/stdtypes.rst (original) +++ python/branches/py3k/Doc/library/stdtypes.rst Sat Aug 2 18:34:27 2008 @@ -897,11 +897,10 @@ .. method:: str.join(seq) - Return a string which is the concatenation of the values in the sequence - *seq*. Non-string values in *seq* will be converted to a string using their - respective ``str()`` value. If there are any :class:`bytes` objects in - *seq*, a :exc:`TypeError` will be raised. The separator between elements is - the string providing this method. + Return a string which is the concatenation of the strings in the sequence + *seq*. A :exc:`TypeError` will be raised if there are any non-string values + in *seq*, including :class:`bytes` objects. The separator between elements + is the string providing this method. .. method:: str.ljust(width[, fillchar]) From python-3000-checkins at python.org Sat Aug 2 23:02:48 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Sat, 2 Aug 2008 23:02:48 +0200 (CEST) Subject: [Python-3000-checkins] r65420 - in python/branches/py3k: Lib/test/test_bytes.py Lib/test/test_socket.py Objects/bytesobject.c Objects/memoryobject.c Message-ID: <20080802210248.C0F7D1E4003@bag.python.org> Author: antoine.pitrou Date: Sat Aug 2 23:02:48 2008 New Revision: 65420 Log: #2538: bytes objects can only provide read-only buffers Modified: python/branches/py3k/Lib/test/test_bytes.py python/branches/py3k/Lib/test/test_socket.py python/branches/py3k/Objects/bytesobject.c python/branches/py3k/Objects/memoryobject.c Modified: python/branches/py3k/Lib/test/test_bytes.py ============================================================================== --- python/branches/py3k/Lib/test/test_bytes.py (original) +++ python/branches/py3k/Lib/test/test_bytes.py Sat Aug 2 23:02:48 2008 @@ -453,6 +453,11 @@ class BytesTest(BaseBytesTest): type2test = bytes + def test_buffer_is_readonly(self): + with open(sys.stdin.fileno(), "rb", buffering=0) as f: + self.assertRaises(TypeError, f.readinto, b"") + + class ByteArrayTest(BaseBytesTest): type2test = bytearray Modified: python/branches/py3k/Lib/test/test_socket.py ============================================================================== --- python/branches/py3k/Lib/test/test_socket.py (original) +++ python/branches/py3k/Lib/test/test_socket.py Sat Aug 2 23:02:48 2008 @@ -1112,7 +1112,7 @@ SocketConnectedTest.__init__(self, methodName=methodName) def testRecvInto(self): - buf = b" "*1024 + buf = bytearray(1024) nbytes = self.cli_conn.recv_into(buf) self.assertEqual(nbytes, len(MSG)) msg = buf[:len(MSG)] @@ -1123,7 +1123,7 @@ self.serv_conn.send(buf) def testRecvFromInto(self): - buf = b" "*1024 + buf = bytearray(1024) nbytes, addr = self.cli_conn.recvfrom_into(buf) self.assertEqual(nbytes, len(MSG)) msg = buf[:len(MSG)] Modified: python/branches/py3k/Objects/bytesobject.c ============================================================================== --- python/branches/py3k/Objects/bytesobject.c (original) +++ python/branches/py3k/Objects/bytesobject.c Sat Aug 2 23:02:48 2008 @@ -965,7 +965,7 @@ string_buffer_getbuffer(PyBytesObject *self, Py_buffer *view, int flags) { return PyBuffer_FillInfo(view, (void *)self->ob_sval, Py_SIZE(self), - 0, flags); + 1, flags); } static PySequenceMethods string_as_sequence = { Modified: python/branches/py3k/Objects/memoryobject.c ============================================================================== --- python/branches/py3k/Objects/memoryobject.c (original) +++ python/branches/py3k/Objects/memoryobject.c Sat Aug 2 23:02:48 2008 @@ -56,7 +56,7 @@ if (mview == NULL) return NULL; mview->base = NULL; - if (PyObject_GetBuffer(base, &(mview->view), PyBUF_FULL) < 0) { + if (PyObject_GetBuffer(base, &(mview->view), PyBUF_FULL_RO) < 0) { Py_DECREF(mview); return NULL; } @@ -204,9 +204,9 @@ a contiguous buffer if it is not. The view will point to the shadow buffer which can be written to and then will be copied back into the other buffer when the memory - view is de-allocated. While the shadow buffer is - being used, it will have an exclusive write lock on - the original buffer. + view is de-allocated. While the shadow buffer is + being used, it will have an exclusive write lock on + the original buffer. */ PyObject * @@ -528,7 +528,7 @@ /* Return a new memory-view object */ Py_buffer newview; memset(&newview, 0, sizeof(newview)); - /* XXX: This needs to be fixed so it + /* XXX: This needs to be fixed so it actually returns a sub-view */ return PyMemoryView_FromMemory(&newview); From python-3000-checkins at python.org Sun Aug 3 02:51:38 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sun, 3 Aug 2008 02:51:38 +0200 (CEST) Subject: [Python-3000-checkins] r65424 - python/branches/py3k Message-ID: <20080803005138.5010B1E4003@bag.python.org> Author: brett.cannon Date: Sun Aug 3 02:51:38 2008 New Revision: 65424 Log: Blocked revisions 65423 via svnmerge ........ r65423 | brett.cannon | 2008-08-02 17:51:02 -0700 (Sat, 02 Aug 2008) | 3 lines Silence some SyntaxWarnings for tuple unpacking in a parameter list for urlparse when run under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 3 02:59:47 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sun, 3 Aug 2008 02:59:47 +0200 (CEST) Subject: [Python-3000-checkins] r65426 - python/branches/py3k Message-ID: <20080803005947.5DCDC1E4003@bag.python.org> Author: brett.cannon Date: Sun Aug 3 02:59:47 2008 New Revision: 65426 Log: Blocked revisions 65425 via svnmerge ........ r65425 | brett.cannon | 2008-08-02 17:58:51 -0700 (Sat, 02 Aug 2008) | 3 lines Silence SyntaxWarning and DeprecationWarning in pydoc triggered by tuple unpacking in parameter lists and using callable(). Found through -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 3 11:45:51 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sun, 3 Aug 2008 11:45:51 +0200 (CEST) Subject: [Python-3000-checkins] r65431 - python/branches/py3k Message-ID: <20080803094551.930B11E4012@bag.python.org> Author: georg.brandl Date: Sun Aug 3 11:45:51 2008 New Revision: 65431 Log: Blocked revisions 65422 via svnmerge ........ r65422 | antoine.pitrou | 2008-08-02 23:58:05 +0200 (Sat, 02 Aug 2008) | 1 line Preemptively backport the relevant parts of r65420 ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 3 11:47:28 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sun, 3 Aug 2008 11:47:28 +0200 (CEST) Subject: [Python-3000-checkins] r65432 - in python/branches/py3k: Doc/library/site.rst Doc/reference/grammar.rst Doc/reference/index.rst Doc/reference/simple_stmts.rst Message-ID: <20080803094728.084D01E4008@bag.python.org> Author: georg.brandl Date: Sun Aug 3 11:47:27 2008 New Revision: 65432 Log: Merged revisions 65378-65379,65430 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65378 | georg.brandl | 2008-08-01 22:04:43 +0200 (Fri, 01 Aug 2008) | 4 lines Add the grammar to the reference manual, since the new docs don't have the feature of putting all the small EBNF snippets together into one big file. ........ r65379 | georg.brandl | 2008-08-01 22:13:29 +0200 (Fri, 01 Aug 2008) | 2 lines This should really be a comment. ........ r65430 | georg.brandl | 2008-08-03 11:21:18 +0200 (Sun, 03 Aug 2008) | 2 lines #3495: use current version. ........ Added: python/branches/py3k/Doc/reference/grammar.rst Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/site.rst python/branches/py3k/Doc/reference/index.rst python/branches/py3k/Doc/reference/simple_stmts.rst Modified: python/branches/py3k/Doc/library/site.rst ============================================================================== --- python/branches/py3k/Doc/library/site.rst (original) +++ python/branches/py3k/Doc/library/site.rst Sun Aug 3 11:47:27 2008 @@ -61,8 +61,8 @@ Then the following directories are added to ``sys.path``, in this order:: - /usr/local/lib/python2.3/site-packages/bar - /usr/local/lib/python2.3/site-packages/foo + /usr/local/lib/python2.6/site-packages/bar + /usr/local/lib/python2.6/site-packages/foo Note that :file:`bletch` is omitted because it doesn't exist; the :file:`bar` directory precedes the :file:`foo` directory because :file:`bar.pth` comes Added: python/branches/py3k/Doc/reference/grammar.rst ============================================================================== --- (empty file) +++ python/branches/py3k/Doc/reference/grammar.rst Sun Aug 3 11:47:27 2008 @@ -0,0 +1,7 @@ +Full Grammar specification +========================== + +This is the full Python grammar, as it is read by the parser generator and used +to parse Python source files: + +.. literalinclude:: ../../Grammar/Grammar Modified: python/branches/py3k/Doc/reference/index.rst ============================================================================== --- python/branches/py3k/Doc/reference/index.rst (original) +++ python/branches/py3k/Doc/reference/index.rst Sun Aug 3 11:47:27 2008 @@ -27,4 +27,4 @@ simple_stmts.rst compound_stmts.rst toplevel_components.rst - + grammar.rst Modified: python/branches/py3k/Doc/reference/simple_stmts.rst ============================================================================== --- python/branches/py3k/Doc/reference/simple_stmts.rst (original) +++ python/branches/py3k/Doc/reference/simple_stmts.rst Sun Aug 3 11:47:27 2008 @@ -727,10 +727,13 @@ the module search path is carried out differently. The sequence of identifiers up to the last dot is used to find a "package"; the final identifier is then searched inside the package. A package is generally a subdirectory of a -directory on ``sys.path`` that has a file :file:`__init__.py`. [XXX Can't be -bothered to spell this out right now; see the URL -http://www.python.org/doc/essays/packages.html for more details, also about how -the module search works from inside a package.] +directory on ``sys.path`` that has a file :file:`__init__.py`. + +.. + [XXX Can't be + bothered to spell this out right now; see the URL + http://www.python.org/doc/essays/packages.html for more details, also about how + the module search works from inside a package.] .. index:: builtin: __import__ From python-3000-checkins at python.org Sun Aug 3 12:04:14 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sun, 3 Aug 2008 12:04:14 +0200 (CEST) Subject: [Python-3000-checkins] r65433 - python/branches/py3k/Doc/library/site.rst Message-ID: <20080803100414.EBF8E1E4003@bag.python.org> Author: georg.brandl Date: Sun Aug 3 12:04:14 2008 New Revision: 65433 Log: Use version 3.0. Modified: python/branches/py3k/Doc/library/site.rst Modified: python/branches/py3k/Doc/library/site.rst ============================================================================== --- python/branches/py3k/Doc/library/site.rst (original) +++ python/branches/py3k/Doc/library/site.rst Sun Aug 3 12:04:14 2008 @@ -61,8 +61,8 @@ Then the following directories are added to ``sys.path``, in this order:: - /usr/local/lib/python2.6/site-packages/bar - /usr/local/lib/python2.6/site-packages/foo + /usr/local/lib/python3.0/site-packages/bar + /usr/local/lib/python3.0/site-packages/foo Note that :file:`bletch` is omitted because it doesn't exist; the :file:`bar` directory precedes the :file:`foo` directory because :file:`bar.pth` comes From python-3000-checkins at python.org Mon Aug 4 00:35:21 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 00:35:21 +0200 (CEST) Subject: [Python-3000-checkins] r65439 - python/branches/py3k Message-ID: <20080803223521.559B71E4014@bag.python.org> Author: brett.cannon Date: Mon Aug 4 00:35:21 2008 New Revision: 65439 Log: Blocked revisions 65438 via svnmerge ........ r65438 | brett.cannon | 2008-08-03 15:34:25 -0700 (Sun, 03 Aug 2008) | 3 lines Remove a use of list.sort(cmp=) to silence a -3 DeprecationWarning in cookielib. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 00:38:58 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 00:38:58 +0200 (CEST) Subject: [Python-3000-checkins] r65441 - python/branches/py3k Message-ID: <20080803223858.C1C9F1E4002@bag.python.org> Author: brett.cannon Date: Mon Aug 4 00:38:58 2008 New Revision: 65441 Log: Blocked revisions 65440 via svnmerge ........ r65440 | brett.cannon | 2008-08-03 15:38:19 -0700 (Sun, 03 Aug 2008) | 2 lines Remove a dict.has_key() usage in profile to silence a -3 DeprecationWarning. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 00:53:31 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 00:53:31 +0200 (CEST) Subject: [Python-3000-checkins] r65443 - python/branches/py3k Message-ID: <20080803225331.8A9C31E4004@bag.python.org> Author: brett.cannon Date: Mon Aug 4 00:53:31 2008 New Revision: 65443 Log: Blocked revisions 65442 via svnmerge ........ r65442 | brett.cannon | 2008-08-03 15:52:42 -0700 (Sun, 03 Aug 2008) | 3 lines Silence -3 warnings in pstats: a dict.has_key() usage and backport solution to move from list.sort(cmp=) to key=. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 00:58:03 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 00:58:03 +0200 (CEST) Subject: [Python-3000-checkins] r65445 - python/branches/py3k Message-ID: <20080803225803.F0BF21E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 00:58:03 2008 New Revision: 65445 Log: Blocked revisions 65444 via svnmerge ........ r65444 | brett.cannon | 2008-08-03 15:57:23 -0700 (Sun, 03 Aug 2008) | 3 lines Remove a dict.has_key() and callable() usage in SimpleXMLRPCServer as triggered under -3 through test_xmlrpc. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 01:00:33 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 01:00:33 +0200 (CEST) Subject: [Python-3000-checkins] r65447 - python/branches/py3k Message-ID: <20080803230033.4807C1E4010@bag.python.org> Author: brett.cannon Date: Mon Aug 4 01:00:33 2008 New Revision: 65447 Log: Blocked revisions 65446 via svnmerge ........ r65446 | brett.cannon | 2008-08-03 15:59:46 -0700 (Sun, 03 Aug 2008) | 2 lines Remove a dict.has_key() use in DocXMLRPCServer that comes up under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 01:28:14 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 01:28:14 +0200 (CEST) Subject: [Python-3000-checkins] r65450 - python/branches/py3k Message-ID: <20080803232814.437EA1E4012@bag.python.org> Author: brett.cannon Date: Mon Aug 4 01:28:13 2008 New Revision: 65450 Log: Blocked revisions 65449 via svnmerge ........ r65449 | brett.cannon | 2008-08-03 16:27:32 -0700 (Sun, 03 Aug 2008) | 3 lines Remove Barry's love of deprecated syntax to silence warnings in the email package, when run under -3, about using <>. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 01:40:52 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 01:40:52 +0200 (CEST) Subject: [Python-3000-checkins] r65452 - python/branches/py3k Message-ID: <20080803234052.3C11B1E4002@bag.python.org> Author: brett.cannon Date: Mon Aug 4 01:40:51 2008 New Revision: 65452 Log: Blocked revisions 65451 via svnmerge ........ r65451 | brett.cannon | 2008-08-03 16:40:13 -0700 (Sun, 03 Aug 2008) | 2 lines Remove a dict.has_key() usage in email._parseaddr found while running -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 01:47:27 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 01:47:27 +0200 (CEST) Subject: [Python-3000-checkins] r65454 - python/branches/py3k Message-ID: <20080803234727.017891E4002@bag.python.org> Author: brett.cannon Date: Mon Aug 4 01:47:26 2008 New Revision: 65454 Log: Blocked revisions 65453 via svnmerge ........ r65453 | brett.cannon | 2008-08-03 16:46:46 -0700 (Sun, 03 Aug 2008) | 3 lines Move filecmp from using dict.has_key() to dict.__contains__() to silence warnings triggered under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 01:53:13 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 01:53:13 +0200 (CEST) Subject: [Python-3000-checkins] r65456 - python/branches/py3k Message-ID: <20080803235313.5F2BE1E4002@bag.python.org> Author: brett.cannon Date: Mon Aug 4 01:53:13 2008 New Revision: 65456 Log: Blocked revisions 65455 via svnmerge ........ r65455 | brett.cannon | 2008-08-03 16:52:32 -0700 (Sun, 03 Aug 2008) | 2 lines Remove a use of callable() in fileinput to silence a -3 warning. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 02:10:29 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 02:10:29 +0200 (CEST) Subject: [Python-3000-checkins] r65458 - python/branches/py3k Message-ID: <20080804001029.8BC861E4002@bag.python.org> Author: brett.cannon Date: Mon Aug 4 02:10:29 2008 New Revision: 65458 Log: Blocked revisions 65457 via svnmerge ........ r65457 | brett.cannon | 2008-08-03 17:09:43 -0700 (Sun, 03 Aug 2008) | 3 lines Remove dict.has_key() and apply() usage from the logging package to silence warnings when run under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 02:24:38 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 02:24:38 +0200 (CEST) Subject: [Python-3000-checkins] r65463 - python/branches/py3k Message-ID: <20080804002438.56F5D1E4002@bag.python.org> Author: brett.cannon Date: Mon Aug 4 02:24:38 2008 New Revision: 65463 Log: Blocked revisions 65462 via svnmerge ........ r65462 | brett.cannon | 2008-08-03 17:23:58 -0700 (Sun, 03 Aug 2008) | 3 lines Remove dict.has_key() usage in xml.dom.minidom to silence warnings while running under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 02:28:42 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 02:28:42 +0200 (CEST) Subject: [Python-3000-checkins] r65465 - python/branches/py3k Message-ID: <20080804002842.4BC321E4002@bag.python.org> Author: brett.cannon Date: Mon Aug 4 02:28:42 2008 New Revision: 65465 Log: Blocked revisions 65464 via svnmerge ........ r65464 | brett.cannon | 2008-08-03 17:27:29 -0700 (Sun, 03 Aug 2008) | 2 lines Silence warnings under -3 about using dict.has_key() for modulefinder. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 02:51:17 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 02:51:17 +0200 (CEST) Subject: [Python-3000-checkins] r65468 - python/branches/py3k Message-ID: <20080804005117.738221E4002@bag.python.org> Author: brett.cannon Date: Mon Aug 4 02:51:17 2008 New Revision: 65468 Log: Blocked revisions 65467 via svnmerge ........ r65467 | brett.cannon | 2008-08-03 17:50:11 -0700 (Sun, 03 Aug 2008) | 3 lines Remove assignment to True/False and use of dict.has_key() to silence warnings while running under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 09:24:52 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Mon, 4 Aug 2008 09:24:52 +0200 (CEST) Subject: [Python-3000-checkins] r65478 - python/branches/py3k/Doc/library/tempfile.rst Message-ID: <20080804072452.548AF1E4004@bag.python.org> Author: georg.brandl Date: Mon Aug 4 09:24:52 2008 New Revision: 65478 Log: Undocument deprecated module global "template". Modified: python/branches/py3k/Doc/library/tempfile.rst Modified: python/branches/py3k/Doc/library/tempfile.rst ============================================================================== --- python/branches/py3k/Doc/library/tempfile.rst (original) +++ python/branches/py3k/Doc/library/tempfile.rst Mon Aug 4 09:24:52 2008 @@ -207,21 +207,8 @@ the search described above is performed, and the result returned. -.. data:: template - - .. deprecated:: 2.0 - Use :func:`gettempprefix` instead. - - When set to a value other than ``None``, this variable defines the prefix of the - final component of the filenames returned by :func:`mktemp`. A string of six - random letters and digits is appended to the prefix to make the filename unique. - On Windows, the default prefix is :file:`~T`; on all other systems it is - :file:`tmp`. - - .. function:: gettempprefix() Return the filename prefix used to create temporary files. This does not - contain the directory component. Using this function is preferred over reading - the *template* variable directly. + contain the directory component. From python-3000-checkins at python.org Mon Aug 4 09:26:08 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Mon, 4 Aug 2008 09:26:08 +0200 (CEST) Subject: [Python-3000-checkins] r65479 - python/branches/py3k Message-ID: <20080804072608.36EA81E4004@bag.python.org> Author: georg.brandl Date: Mon Aug 4 09:26:07 2008 New Revision: 65479 Log: Blocked revisions 65477 via svnmerge ........ r65477 | georg.brandl | 2008-08-04 07:23:29 +0000 (Mon, 04 Aug 2008) | 2 lines Template is always "tmp". ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 10:25:03 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Mon, 4 Aug 2008 10:25:03 +0200 (CEST) Subject: [Python-3000-checkins] r65482 - in python/branches/py3k: Doc/library/tarfile.rst Lib/tarfile.py Message-ID: <20080804082503.B9B001E4004@bag.python.org> Author: georg.brandl Date: Mon Aug 4 10:25:03 2008 New Revision: 65482 Log: Remove the deprecated posix attribute. Modified: python/branches/py3k/Doc/library/tarfile.rst python/branches/py3k/Lib/tarfile.py Modified: python/branches/py3k/Doc/library/tarfile.rst ============================================================================== --- python/branches/py3k/Doc/library/tarfile.rst (original) +++ python/branches/py3k/Doc/library/tarfile.rst Mon Aug 4 10:25:03 2008 @@ -393,18 +393,6 @@ appended to the archive. -.. attribute:: TarFile.posix - - Setting this to :const:`True` is equivalent to setting the :attr:`format` - attribute to :const:`USTAR_FORMAT`, :const:`False` is equivalent to - :const:`GNU_FORMAT`. - - *posix* defaults to :const:`False`. - - .. deprecated:: 2.6 - Use the :attr:`format` attribute instead. - - .. attribute:: TarFile.pax_headers A dictionary containing key-value pairs of pax global headers. Modified: python/branches/py3k/Lib/tarfile.py ============================================================================== --- python/branches/py3k/Lib/tarfile.py (original) +++ python/branches/py3k/Lib/tarfile.py Mon Aug 4 10:25:03 2008 @@ -1577,17 +1577,6 @@ self.fileobj.write(buf) self.offset += len(buf) - def _getposix(self): - return self.format == USTAR_FORMAT - def _setposix(self, value): - import warnings - warnings.warn("use the format attribute instead", DeprecationWarning) - if value: - self.format = USTAR_FORMAT - else: - self.format = GNU_FORMAT - posix = property(_getposix, _setposix) - #-------------------------------------------------------------------------- # Below are the classmethods which act as alternate constructors to the # TarFile class. The open() method is the only one that is needed for From python-3000-checkins at python.org Mon Aug 4 15:00:16 2008 From: python-3000-checkins at python.org (nick.coghlan) Date: Mon, 4 Aug 2008 15:00:16 +0200 (CEST) Subject: [Python-3000-checkins] r65490 - python/branches/py3k Message-ID: <20080804130016.33F4F1E400C@bag.python.org> Author: nick.coghlan Date: Mon Aug 4 15:00:15 2008 New Revision: 65490 Log: Blocked revisions 65487-65488 via svnmerge ........ r65487 | nick.coghlan | 2008-08-04 22:40:59 +1000 (Mon, 04 Aug 2008) | 1 line Issue 643841: better documentation of the special method lookup process, especially for new-style classes. Also removes the warnings about not being authoritative for new-style classes - the language reference actually covers those fairly well now (albeit in a fashion that isn't always particularly easy to follow). ........ r65488 | nick.coghlan | 2008-08-04 22:47:17 +1000 (Mon, 04 Aug 2008) | 1 line Add missing NEWS entry for r65487 ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:08:43 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:08:43 +0200 (CEST) Subject: [Python-3000-checkins] r65507 - python/branches/py3k Message-ID: <20080804210843.CB7FC1E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:08:43 2008 New Revision: 65507 Log: Blocked revisions 65506 via svnmerge ........ r65506 | brett.cannon | 2008-08-04 14:07:59 -0700 (Mon, 04 Aug 2008) | 2 lines Remove the use of callable() in re to silence warnings under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:13:59 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:13:59 +0200 (CEST) Subject: [Python-3000-checkins] r65509 - python/branches/py3k Message-ID: <20080804211359.75DEC1E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:13:59 2008 New Revision: 65509 Log: Blocked revisions 65508 via svnmerge ........ r65508 | brett.cannon | 2008-08-04 14:10:50 -0700 (Mon, 04 Aug 2008) | 2 lines Remove dict.has_key() usage in xml.sax to silence warnings under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:17:54 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:17:54 +0200 (CEST) Subject: [Python-3000-checkins] r65511 - python/branches/py3k Message-ID: <20080804211754.21B7A1E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:17:53 2008 New Revision: 65511 Log: Blocked revisions 65510 via svnmerge ........ r65510 | brett.cannon | 2008-08-04 14:17:15 -0700 (Mon, 04 Aug 2008) | 2 lines Remove dict.has_key() usage in the shelve module to silence warnings under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:20:30 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:20:30 +0200 (CEST) Subject: [Python-3000-checkins] r65513 - python/branches/py3k Message-ID: <20080804212030.20F861E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:20:29 2008 New Revision: 65513 Log: Blocked revisions 65512 via svnmerge ........ r65512 | brett.cannon | 2008-08-04 14:19:41 -0700 (Mon, 04 Aug 2008) | 2 lines Remove usage of apply() in sqlite3 to silence warnings under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:23:45 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:23:45 +0200 (CEST) Subject: [Python-3000-checkins] r65515 - python/branches/py3k Message-ID: <20080804212345.3144C1E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:23:44 2008 New Revision: 65515 Log: Blocked revisions 65514 via svnmerge ........ r65514 | brett.cannon | 2008-08-04 14:23:07 -0700 (Mon, 04 Aug 2008) | 3 lines Remove a dict.has_key() and list.sort(cmp=) usage from tarfile to silence warnings under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:25:42 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:25:42 +0200 (CEST) Subject: [Python-3000-checkins] r65517 - python/branches/py3k Message-ID: <20080804212542.451E21E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:25:42 2008 New Revision: 65517 Log: Blocked revisions 65516 via svnmerge ........ r65516 | brett.cannon | 2008-08-04 14:24:43 -0700 (Mon, 04 Aug 2008) | 2 lines Remove a use of callable() from Tkinter to silence warnings under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:32:00 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:32:00 +0200 (CEST) Subject: [Python-3000-checkins] r65520 - python/branches/py3k Message-ID: <20080804213200.692351E4012@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:32:00 2008 New Revision: 65520 Log: Blocked revisions 65519 via svnmerge ........ r65519 | brett.cannon | 2008-08-04 14:30:53 -0700 (Mon, 04 Aug 2008) | 2 lines Silence warnings under -3 triggered by wsgiref. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:33:39 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:33:39 +0200 (CEST) Subject: [Python-3000-checkins] r65523 - python/branches/py3k Message-ID: <20080804213339.77CD71E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:33:39 2008 New Revision: 65523 Log: Blocked revisions 65522 via svnmerge ........ r65522 | brett.cannon | 2008-08-04 14:33:00 -0700 (Mon, 04 Aug 2008) | 2 lines Remove tuple parameter unpacking in aifc to silence warnings under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 4 23:35:14 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 4 Aug 2008 23:35:14 +0200 (CEST) Subject: [Python-3000-checkins] r65525 - python/branches/py3k Message-ID: <20080804213514.4DC671E4006@bag.python.org> Author: brett.cannon Date: Mon Aug 4 23:35:14 2008 New Revision: 65525 Log: Blocked revisions 65524 via svnmerge ........ r65524 | brett.cannon | 2008-08-04 14:34:34 -0700 (Mon, 04 Aug 2008) | 2 lines Remove use of callable() from pickle to silence warnings under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Tue Aug 5 11:04:17 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Tue, 5 Aug 2008 11:04:17 +0200 (CEST) Subject: [Python-3000-checkins] r65545 - in python/branches/py3k/Doc/tutorial: controlflow.rst inputoutput.rst introduction.rst modules.rst Message-ID: <20080805090417.7CD671E4009@bag.python.org> Author: georg.brandl Date: Tue Aug 5 11:04:16 2008 New Revision: 65545 Log: #3503: fix print statements in 3k doc. Modified: python/branches/py3k/Doc/tutorial/controlflow.rst python/branches/py3k/Doc/tutorial/inputoutput.rst python/branches/py3k/Doc/tutorial/introduction.rst python/branches/py3k/Doc/tutorial/modules.rst Modified: python/branches/py3k/Doc/tutorial/controlflow.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/controlflow.rst (original) +++ python/branches/py3k/Doc/tutorial/controlflow.rst Tue Aug 5 11:04:16 2008 @@ -434,7 +434,7 @@ def cheeseshop(kind, *arguments, **keywords): print("-- Do you have any", kind, '?') print("-- I'm sorry, we're all out of", kind) - for arg in arguments: print arg + for arg in arguments: print(arg) print('-'*40) keys = sorted(keywords.keys()) for kw in keys: print(kw, ':', keywords[kw]) Modified: python/branches/py3k/Doc/tutorial/inputoutput.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/inputoutput.rst (original) +++ python/branches/py3k/Doc/tutorial/inputoutput.rst Tue Aug 5 11:04:16 2008 @@ -208,7 +208,7 @@ operation. For example:: >>> import math - >>> print 'The value of PI is approximately %5.3f.' % math.pi + >>> print('The value of PI is approximately %5.3f.' % math.pi) The value of PI is approximately 3.142. Since :meth:`str.format` is quite new, a lot of Python code still uses the ``%`` Modified: python/branches/py3k/Doc/tutorial/introduction.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/introduction.rst (original) +++ python/branches/py3k/Doc/tutorial/introduction.rst Tue Aug 5 11:04:16 2008 @@ -599,16 +599,12 @@ >>> print('The value of i is', i) The value of i is 65536 - The keyword end can be used to avoid the newline after the output:: + The keyword *end* can be used to avoid the newline after the output, or end + the output with a different string:: >>> a, b = 0, 1 >>> while b < 1000: - ... print(b, ' ', end='') + ... print(b, end=' ') ... a, b = b, a+b ... - >>> print() 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 - - Note that nothing appeared after the loop ended, until we printed - a newline. - Modified: python/branches/py3k/Doc/tutorial/modules.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/modules.rst (original) +++ python/branches/py3k/Doc/tutorial/modules.rst Tue Aug 5 11:04:16 2008 @@ -32,6 +32,7 @@ while b < n: print(b, end=' ') a, b = b, a+b + print() def fib2(n): # return Fibonacci series up to n result = [] From python-3000-checkins at python.org Wed Aug 6 21:29:14 2008 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 6 Aug 2008 21:29:14 +0200 (CEST) Subject: [Python-3000-checkins] r65559 - in python/branches/py3k: Lib/test/test_urllib.py Lib/urllib/parse.py Modules/_sre.c Message-ID: <20080806192914.B59CA1E400D@bag.python.org> Author: guido.van.rossum Date: Wed Aug 6 21:29:14 2008 New Revision: 65559 Log: Merged revisions 65544 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65544 | guido.van.rossum | 2008-08-04 20:39:21 -0700 (Mon, 04 Aug 2008) | 28 lines Tracker issue 3487: sre "bytecode" verifier. This is a verifier for the binary code used by the _sre module (this is often called bytecode, though to distinguish it from Python bytecode I put it in quotes). I wrote this for Google App Engine, and am making the patch available as open source under the Apache 2 license. Below are the copyright statement and license, for completeness. # Copyright 2008 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. It's not necessary to include these copyrights and bytecode in the source file. Google has signed a contributor's agreement with the PSF already. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_urllib.py python/branches/py3k/Lib/urllib/parse.py python/branches/py3k/Modules/_sre.c Modified: python/branches/py3k/Lib/test/test_urllib.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllib.py (original) +++ python/branches/py3k/Lib/test/test_urllib.py Wed Aug 6 21:29:14 2008 @@ -465,7 +465,7 @@ def test_unquote_with_unicode(self): r = urllib.parse.unquote('br%C3%BCckner_sapporo_20050930.doc') - self.assertEqual(r, 'br\xc3\xbcckner_sapporo_20050930.doc') + self.assertEqual(r, 'br\u00FCckner_sapporo_20050930.doc') class urlencode_Tests(unittest.TestCase): """Tests for urlencode()""" Modified: python/branches/py3k/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k/Lib/urllib/parse.py (original) +++ python/branches/py3k/Lib/urllib/parse.py Wed Aug 6 21:29:14 2008 @@ -261,84 +261,74 @@ return url, '' -_hextochr = dict(('%02x' % i, chr(i)) for i in range(256)) -_hextochr.update(('%02X' % i, chr(i)) for i in range(256)) +def unquote_as_string (s, plus=False, charset=None): + if charset is None: + charset = "UTF-8" + return str(unquote_as_bytes(s, plus=plus), charset, 'strict') -def unquote(s): +def unquote_as_bytes (s, plus=False): """unquote('abc%20def') -> 'abc def'.""" + if plus: + s = s.replace('+', ' ') res = s.split('%') + res[0] = res[0].encode('ASCII', 'strict') for i in range(1, len(res)): - item = res[i] - try: - res[i] = _hextochr[item[:2]] + item[2:] - except KeyError: - res[i] = '%' + item - except UnicodeDecodeError: - res[i] = chr(int(item[:2], 16)) + item[2:] - return "".join(res) - -def unquote_plus(s): - """unquote('%7e/abc+def') -> '~/abc def'""" - s = s.replace('+', ' ') - return unquote(s) - -always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' - 'abcdefghijklmnopqrstuvwxyz' - '0123456789' '_.-') -_safe_quoters= {} - -class Quoter: - def __init__(self, safe): - self.cache = {} - self.safe = safe + always_safe + res[i] = (bytes.fromhex(res[i][:2]) + + res[i][2:].encode('ASCII', 'strict')) + return b''.join(res) + +_always_safe = (b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + b'abcdefghijklmnopqrstuvwxyz' + b'0123456789' + b'_.-') + +_percent_code = ord('%') + +_hextable = b'0123456789ABCDEF' + +def quote_as_bytes(s, safe = '/', plus=False): + """quote(b'abc at def') -> 'abc%40def'""" + + if isinstance(s, str): + s = s.encode("UTF-8", "strict") + if not (isinstance(s, bytes) or isinstance(s, bytearray)): + raise ValueError("Argument to quote must be either bytes " + "or bytearray; string arguments will be " + "converted to UTF-8 bytes") + + safeset = _always_safe + safe.encode('ASCII', 'strict') + if plus: + safeset += b' ' + + result = bytearray() + for i in s: + if i not in safeset: + result.append(_percent_code) + result.append(_hextable[(i >> 4) & 0xF]) + result.append(_hextable[i & 0xF]) + else: + result.append(i) + if plus: + result = result.replace(b' ', b'+') + return result - def __call__(self, c): - try: - return self.cache[c] - except KeyError: - if ord(c) < 256: - res = (c in self.safe) and c or ('%%%02X' % ord(c)) - self.cache[c] = res - return res - else: - return "".join(['%%%02X' % i for i in c.encode("utf-8")]) +def quote_as_string(s, safe = '/', plus=False): + return str(quote_as_bytes(s, safe=safe, plus=plus), 'ASCII', 'strict') -def quote(s, safe = '/'): - """quote('abc def') -> 'abc%20def' +# finally, define defaults for 'quote' and 'unquote' - Each part of a URL, e.g. the path info, the query, etc., has a - different set of reserved characters that must be quoted. +def quote(s, safe='/'): + return quote_as_string(s, safe=safe) - RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists - the following reserved characters. +def quote_plus(s, safe=''): + return quote_as_string(s, safe=safe, plus=True) - reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | - "$" | "," +def unquote(s): + return unquote_as_string(s) - Each of these characters is reserved in some component of a URL, - but not necessarily in all of them. +def unquote_plus(s): + return unquote_as_string(s, plus=True) - By default, the quote function is intended for quoting the path - section of a URL. Thus, it will not encode '/'. This character - is reserved, but in typical usage the quote function is being - called on a path where the existing slash characters are used as - reserved characters. - """ - cachekey = (safe, always_safe) - try: - quoter = _safe_quoters[cachekey] - except KeyError: - quoter = Quoter(safe) - _safe_quoters[cachekey] = quoter - res = map(quoter, s) - return ''.join(res) - -def quote_plus(s, safe = ''): - """Quote the query fragment of a URL; replacing ' ' with '+'""" - if ' ' in s: - s = quote(s, safe + ' ') - return s.replace(' ', '+') - return quote(s, safe) def urlencode(query,doseq=0): """Encode a sequence of two-element tuples or dictionary into a URL query string. @@ -387,7 +377,7 @@ # is there a reasonable way to convert to ASCII? # encode generates a string, but "replace" or "ignore" # lose information and "strict" can raise UnicodeError - v = quote_plus(v.encode("ASCII","replace")) + v = quote_plus(v) l.append(k + '=' + v) else: try: @@ -474,7 +464,8 @@ _userprog = re.compile('^(.*)@(.*)$') match = _userprog.match(host) - if match: return map(unquote, match.group(1, 2)) + if match: + return map(unquote, match.group(1, 2)) return None, host _passwdprog = None Modified: python/branches/py3k/Modules/_sre.c ============================================================================== --- python/branches/py3k/Modules/_sre.c (original) +++ python/branches/py3k/Modules/_sre.c Wed Aug 6 21:29:14 2008 @@ -2637,6 +2637,8 @@ pattern_members, /* tp_members */ }; +static int _validate(PatternObject *self); /* Forward */ + static PyObject * _compile(PyObject* self_, PyObject* args) { @@ -2695,10 +2697,482 @@ self->weakreflist = NULL; + if (!_validate(self)) { + Py_DECREF(self); + return NULL; + } + return (PyObject*) self; } /* -------------------------------------------------------------------- */ +/* Code validation */ + +/* To learn more about this code, have a look at the _compile() function in + Lib/sre_compile.py. The validation functions below checks the code array + for conformance with the code patterns generated there. + + The nice thing about the generated code is that it is position-independent: + all jumps are relative jumps forward. Also, jumps don't cross each other: + the target of a later jump is always earlier than the target of an earlier + jump. IOW, this is okay: + + J---------J-------T--------T + \ \_____/ / + \______________________/ + + but this is not: + + J---------J-------T--------T + \_________\_____/ / + \____________/ + + It also helps that SRE_CODE is always an unsigned type, either 2 bytes or 4 + bytes wide (the latter if Python is compiled for "wide" unicode support). +*/ + +/* Defining this one enables tracing of the validator */ +#undef VVERBOSE + +/* Trace macro for the validator */ +#if defined(VVERBOSE) +#define VTRACE(v) printf v +#else +#define VTRACE(v) +#endif + +/* Report failure */ +#define FAIL do { VTRACE(("FAIL: %d\n", __LINE__)); return 0; } while (0) + +/* Extract opcode, argument, or skip count from code array */ +#define GET_OP \ + do { \ + VTRACE(("%p: ", code)); \ + if (code >= end) FAIL; \ + op = *code++; \ + VTRACE(("%lu (op)\n", (unsigned long)op)); \ + } while (0) +#define GET_ARG \ + do { \ + VTRACE(("%p= ", code)); \ + if (code >= end) FAIL; \ + arg = *code++; \ + VTRACE(("%lu (arg)\n", (unsigned long)arg)); \ + } while (0) +#define GET_SKIP \ + do { \ + VTRACE(("%p= ", code)); \ + if (code >= end) FAIL; \ + skip = *code; \ + VTRACE(("%lu (skip to %p)\n", \ + (unsigned long)skip, code+skip)); \ + if (code+skip < code || code+skip > end) \ + FAIL; \ + code++; \ + } while (0) + +static int +_validate_charset(SRE_CODE *code, SRE_CODE *end) +{ + /* Some variables are manipulated by the macros above */ + SRE_CODE op; + SRE_CODE arg; + SRE_CODE offset; + int i; + + while (code < end) { + GET_OP; + switch (op) { + + case SRE_OP_NEGATE: + break; + + case SRE_OP_LITERAL: + GET_ARG; + break; + + case SRE_OP_RANGE: + GET_ARG; + GET_ARG; + break; + + case SRE_OP_CHARSET: + offset = 32/sizeof(SRE_CODE); /* 32-byte bitmap */ + if (code+offset < code || code+offset > end) + FAIL; + code += offset; + break; + + case SRE_OP_BIGCHARSET: + GET_ARG; /* Number of blocks */ + offset = 256/sizeof(SRE_CODE); /* 256-byte table */ + if (code+offset < code || code+offset > end) + FAIL; + /* Make sure that each byte points to a valid block */ + for (i = 0; i < 256; i++) { + if (((unsigned char *)code)[i] >= arg) + FAIL; + } + code += offset; + offset = arg * 32/sizeof(SRE_CODE); /* 32-byte bitmap times arg */ + if (code+offset < code || code+offset > end) + FAIL; + code += offset; + break; + + case SRE_OP_CATEGORY: + GET_ARG; + switch (arg) { + case SRE_CATEGORY_DIGIT: + case SRE_CATEGORY_NOT_DIGIT: + case SRE_CATEGORY_SPACE: + case SRE_CATEGORY_NOT_SPACE: + case SRE_CATEGORY_WORD: + case SRE_CATEGORY_NOT_WORD: + case SRE_CATEGORY_LINEBREAK: + case SRE_CATEGORY_NOT_LINEBREAK: + case SRE_CATEGORY_LOC_WORD: + case SRE_CATEGORY_LOC_NOT_WORD: + case SRE_CATEGORY_UNI_DIGIT: + case SRE_CATEGORY_UNI_NOT_DIGIT: + case SRE_CATEGORY_UNI_SPACE: + case SRE_CATEGORY_UNI_NOT_SPACE: + case SRE_CATEGORY_UNI_WORD: + case SRE_CATEGORY_UNI_NOT_WORD: + case SRE_CATEGORY_UNI_LINEBREAK: + case SRE_CATEGORY_UNI_NOT_LINEBREAK: + break; + default: + FAIL; + } + break; + + default: + FAIL; + + } + } + + return 1; +} + +static int +_validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) +{ + /* Some variables are manipulated by the macros above */ + SRE_CODE op; + SRE_CODE arg; + SRE_CODE skip; + + VTRACE(("code=%p, end=%p\n", code, end)); + + if (code > end) + FAIL; + + while (code < end) { + GET_OP; + switch (op) { + + case SRE_OP_MARK: + /* We don't check whether marks are properly nested; the + sre_match() code is robust even if they don't, and the worst + you can get is nonsensical match results. */ + GET_ARG; + if (arg > 2*groups+1) { + VTRACE(("arg=%d, groups=%d\n", (int)arg, (int)groups)); + FAIL; + } + break; + + case SRE_OP_LITERAL: + case SRE_OP_NOT_LITERAL: + case SRE_OP_LITERAL_IGNORE: + case SRE_OP_NOT_LITERAL_IGNORE: + GET_ARG; + /* The arg is just a character, nothing to check */ + break; + + case SRE_OP_SUCCESS: + case SRE_OP_FAILURE: + /* Nothing to check; these normally end the matching process */ + break; + + case SRE_OP_AT: + GET_ARG; + switch (arg) { + case SRE_AT_BEGINNING: + case SRE_AT_BEGINNING_STRING: + case SRE_AT_BEGINNING_LINE: + case SRE_AT_END: + case SRE_AT_END_LINE: + case SRE_AT_END_STRING: + case SRE_AT_BOUNDARY: + case SRE_AT_NON_BOUNDARY: + case SRE_AT_LOC_BOUNDARY: + case SRE_AT_LOC_NON_BOUNDARY: + case SRE_AT_UNI_BOUNDARY: + case SRE_AT_UNI_NON_BOUNDARY: + break; + default: + FAIL; + } + break; + + case SRE_OP_ANY: + case SRE_OP_ANY_ALL: + /* These have no operands */ + break; + + case SRE_OP_IN: + case SRE_OP_IN_IGNORE: + GET_SKIP; + /* Stop 1 before the end; we check the FAILURE below */ + if (!_validate_charset(code, code+skip-2)) + FAIL; + if (code[skip-2] != SRE_OP_FAILURE) + FAIL; + code += skip-1; + break; + + case SRE_OP_INFO: + { + /* A minimal info field is + <1=skip> <2=flags> <3=min> <4=max>; + If SRE_INFO_PREFIX or SRE_INFO_CHARSET is in the flags, + more follows. */ + SRE_CODE flags, min, max, i; + SRE_CODE *newcode; + GET_SKIP; + newcode = code+skip-1; + GET_ARG; flags = arg; + GET_ARG; min = arg; + GET_ARG; max = arg; + /* Check that only valid flags are present */ + if ((flags & ~(SRE_INFO_PREFIX | + SRE_INFO_LITERAL | + SRE_INFO_CHARSET)) != 0) + FAIL; + /* PREFIX and CHARSET are mutually exclusive */ + if ((flags & SRE_INFO_PREFIX) && + (flags & SRE_INFO_CHARSET)) + FAIL; + /* LITERAL implies PREFIX */ + if ((flags & SRE_INFO_LITERAL) && + !(flags & SRE_INFO_PREFIX)) + FAIL; + /* Validate the prefix */ + if (flags & SRE_INFO_PREFIX) { + SRE_CODE prefix_len, prefix_skip; + GET_ARG; prefix_len = arg; + GET_ARG; prefix_skip = arg; + /* Here comes the prefix string */ + if (code+prefix_len < code || code+prefix_len > newcode) + FAIL; + code += prefix_len; + /* And here comes the overlap table */ + if (code+prefix_len < code || code+prefix_len > newcode) + FAIL; + /* Each overlap value should be < prefix_len */ + for (i = 0; i < prefix_len; i++) { + if (code[i] >= prefix_len) + FAIL; + } + code += prefix_len; + } + /* Validate the charset */ + if (flags & SRE_INFO_CHARSET) { + if (!_validate_charset(code, newcode-1)) + FAIL; + if (newcode[-1] != SRE_OP_FAILURE) + FAIL; + code = newcode; + } + else if (code != newcode) { + VTRACE(("code=%p, newcode=%p\n", code, newcode)); + FAIL; + } + } + break; + + case SRE_OP_BRANCH: + { + SRE_CODE *target = NULL; + for (;;) { + GET_SKIP; + if (skip == 0) + break; + /* Stop 2 before the end; we check the JUMP below */ + if (!_validate_inner(code, code+skip-3, groups)) + FAIL; + code += skip-3; + /* Check that it ends with a JUMP, and that each JUMP + has the same target */ + GET_OP; + if (op != SRE_OP_JUMP) + FAIL; + GET_SKIP; + if (target == NULL) + target = code+skip-1; + else if (code+skip-1 != target) + FAIL; + } + } + break; + + case SRE_OP_REPEAT_ONE: + case SRE_OP_MIN_REPEAT_ONE: + { + SRE_CODE min, max; + GET_SKIP; + GET_ARG; min = arg; + GET_ARG; max = arg; + if (min > max) + FAIL; +#ifdef Py_UNICODE_WIDE + if (max > 65535) + FAIL; +#endif + if (!_validate_inner(code, code+skip-4, groups)) + FAIL; + code += skip-4; + GET_OP; + if (op != SRE_OP_SUCCESS) + FAIL; + } + break; + + case SRE_OP_REPEAT: + { + SRE_CODE min, max; + GET_SKIP; + GET_ARG; min = arg; + GET_ARG; max = arg; + if (min > max) + FAIL; +#ifdef Py_UNICODE_WIDE + if (max > 65535) + FAIL; +#endif + if (!_validate_inner(code, code+skip-3, groups)) + FAIL; + code += skip-3; + GET_OP; + if (op != SRE_OP_MAX_UNTIL && op != SRE_OP_MIN_UNTIL) + FAIL; + } + break; + + case SRE_OP_GROUPREF: + case SRE_OP_GROUPREF_IGNORE: + GET_ARG; + if (arg >= groups) + FAIL; + break; + + case SRE_OP_GROUPREF_EXISTS: + /* The regex syntax for this is: '(?(group)then|else)', where + 'group' is either an integer group number or a group name, + 'then' and 'else' are sub-regexes, and 'else' is optional. */ + GET_ARG; + if (arg >= groups) + FAIL; + GET_SKIP; + code--; /* The skip is relative to the first arg! */ + /* There are two possibilities here: if there is both a 'then' + part and an 'else' part, the generated code looks like: + + GROUPREF_EXISTS + + + ...then part... + JUMP + + ( jumps here) + ...else part... + ( jumps here) + + If there is only a 'then' part, it looks like: + + GROUPREF_EXISTS + + + ...then part... + ( jumps here) + + There is no direct way to decide which it is, and we don't want + to allow arbitrary jumps anywhere in the code; so we just look + for a JUMP opcode preceding our skip target. + */ + if (skip >= 3 && code+skip-3 >= code && + code[skip-3] == SRE_OP_JUMP) + { + VTRACE(("both then and else parts present\n")); + if (!_validate_inner(code+1, code+skip-3, groups)) + FAIL; + code += skip-2; /* Position after JUMP, at */ + GET_SKIP; + if (!_validate_inner(code, code+skip-1, groups)) + FAIL; + code += skip-1; + } + else { + VTRACE(("only a then part present\n")); + if (!_validate_inner(code+1, code+skip-1, groups)) + FAIL; + code += skip-1; + } + break; + + case SRE_OP_ASSERT: + case SRE_OP_ASSERT_NOT: + GET_SKIP; + GET_ARG; /* 0 for lookahead, width for lookbehind */ + code--; /* Back up over arg to simplify math below */ + if (arg & 0x80000000) + FAIL; /* Width too large */ + /* Stop 1 before the end; we check the SUCCESS below */ + if (!_validate_inner(code+1, code+skip-2, groups)) + FAIL; + code += skip-2; + GET_OP; + if (op != SRE_OP_SUCCESS) + FAIL; + break; + + default: + FAIL; + + } + } + + VTRACE(("okay\n")); + return 1; +} + +static int +_validate_outer(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) +{ + if (groups < 0 || groups > 100 || code >= end || end[-1] != SRE_OP_SUCCESS) + FAIL; + if (groups == 0) /* fix for simplejson */ + groups = 100; /* 100 groups should always be safe */ + return _validate_inner(code, end-1, groups); +} + +static int +_validate(PatternObject *self) +{ + if (!_validate_outer(self->code, self->code+self->codesize, self->groups)) + { + PyErr_SetString(PyExc_RuntimeError, "invalid SRE code"); + return 0; + } + else + VTRACE(("Success!\n")); + return 1; +} + +/* -------------------------------------------------------------------- */ /* match methods */ static void From python-3000-checkins at python.org Wed Aug 6 21:31:35 2008 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 6 Aug 2008 21:31:35 +0200 (CEST) Subject: [Python-3000-checkins] r65560 - in python/branches/py3k/Lib: test/test_urllib.py urllib/parse.py Message-ID: <20080806193135.4D74D1E400D@bag.python.org> Author: guido.van.rossum Date: Wed Aug 6 21:31:34 2008 New Revision: 65560 Log: Revert accidentally committed files. Oops! Modified: python/branches/py3k/Lib/test/test_urllib.py python/branches/py3k/Lib/urllib/parse.py Modified: python/branches/py3k/Lib/test/test_urllib.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllib.py (original) +++ python/branches/py3k/Lib/test/test_urllib.py Wed Aug 6 21:31:34 2008 @@ -465,7 +465,7 @@ def test_unquote_with_unicode(self): r = urllib.parse.unquote('br%C3%BCckner_sapporo_20050930.doc') - self.assertEqual(r, 'br\u00FCckner_sapporo_20050930.doc') + self.assertEqual(r, 'br\xc3\xbcckner_sapporo_20050930.doc') class urlencode_Tests(unittest.TestCase): """Tests for urlencode()""" Modified: python/branches/py3k/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k/Lib/urllib/parse.py (original) +++ python/branches/py3k/Lib/urllib/parse.py Wed Aug 6 21:31:34 2008 @@ -261,74 +261,84 @@ return url, '' -def unquote_as_string (s, plus=False, charset=None): - if charset is None: - charset = "UTF-8" - return str(unquote_as_bytes(s, plus=plus), charset, 'strict') +_hextochr = dict(('%02x' % i, chr(i)) for i in range(256)) +_hextochr.update(('%02X' % i, chr(i)) for i in range(256)) -def unquote_as_bytes (s, plus=False): +def unquote(s): """unquote('abc%20def') -> 'abc def'.""" - if plus: - s = s.replace('+', ' ') res = s.split('%') - res[0] = res[0].encode('ASCII', 'strict') for i in range(1, len(res)): - res[i] = (bytes.fromhex(res[i][:2]) + - res[i][2:].encode('ASCII', 'strict')) - return b''.join(res) - -_always_safe = (b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' - b'abcdefghijklmnopqrstuvwxyz' - b'0123456789' - b'_.-') - -_percent_code = ord('%') - -_hextable = b'0123456789ABCDEF' - -def quote_as_bytes(s, safe = '/', plus=False): - """quote(b'abc at def') -> 'abc%40def'""" - - if isinstance(s, str): - s = s.encode("UTF-8", "strict") - if not (isinstance(s, bytes) or isinstance(s, bytearray)): - raise ValueError("Argument to quote must be either bytes " - "or bytearray; string arguments will be " - "converted to UTF-8 bytes") - - safeset = _always_safe + safe.encode('ASCII', 'strict') - if plus: - safeset += b' ' - - result = bytearray() - for i in s: - if i not in safeset: - result.append(_percent_code) - result.append(_hextable[(i >> 4) & 0xF]) - result.append(_hextable[i & 0xF]) - else: - result.append(i) - if plus: - result = result.replace(b' ', b'+') - return result + item = res[i] + try: + res[i] = _hextochr[item[:2]] + item[2:] + except KeyError: + res[i] = '%' + item + except UnicodeDecodeError: + res[i] = chr(int(item[:2], 16)) + item[2:] + return "".join(res) -def quote_as_string(s, safe = '/', plus=False): - return str(quote_as_bytes(s, safe=safe, plus=plus), 'ASCII', 'strict') +def unquote_plus(s): + """unquote('%7e/abc+def') -> '~/abc def'""" + s = s.replace('+', ' ') + return unquote(s) + +always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789' '_.-') +_safe_quoters= {} + +class Quoter: + def __init__(self, safe): + self.cache = {} + self.safe = safe + always_safe + + def __call__(self, c): + try: + return self.cache[c] + except KeyError: + if ord(c) < 256: + res = (c in self.safe) and c or ('%%%02X' % ord(c)) + self.cache[c] = res + return res + else: + return "".join(['%%%02X' % i for i in c.encode("utf-8")]) -# finally, define defaults for 'quote' and 'unquote' +def quote(s, safe = '/'): + """quote('abc def') -> 'abc%20def' -def quote(s, safe='/'): - return quote_as_string(s, safe=safe) + Each part of a URL, e.g. the path info, the query, etc., has a + different set of reserved characters that must be quoted. -def quote_plus(s, safe=''): - return quote_as_string(s, safe=safe, plus=True) + RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists + the following reserved characters. -def unquote(s): - return unquote_as_string(s) + reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + "$" | "," -def unquote_plus(s): - return unquote_as_string(s, plus=True) + Each of these characters is reserved in some component of a URL, + but not necessarily in all of them. + By default, the quote function is intended for quoting the path + section of a URL. Thus, it will not encode '/'. This character + is reserved, but in typical usage the quote function is being + called on a path where the existing slash characters are used as + reserved characters. + """ + cachekey = (safe, always_safe) + try: + quoter = _safe_quoters[cachekey] + except KeyError: + quoter = Quoter(safe) + _safe_quoters[cachekey] = quoter + res = map(quoter, s) + return ''.join(res) + +def quote_plus(s, safe = ''): + """Quote the query fragment of a URL; replacing ' ' with '+'""" + if ' ' in s: + s = quote(s, safe + ' ') + return s.replace(' ', '+') + return quote(s, safe) def urlencode(query,doseq=0): """Encode a sequence of two-element tuples or dictionary into a URL query string. @@ -377,7 +387,7 @@ # is there a reasonable way to convert to ASCII? # encode generates a string, but "replace" or "ignore" # lose information and "strict" can raise UnicodeError - v = quote_plus(v) + v = quote_plus(v.encode("ASCII","replace")) l.append(k + '=' + v) else: try: @@ -464,8 +474,7 @@ _userprog = re.compile('^(.*)@(.*)$') match = _userprog.match(host) - if match: - return map(unquote, match.group(1, 2)) + if match: return map(unquote, match.group(1, 2)) return None, host _passwdprog = None From guido at python.org Wed Aug 6 21:32:25 2008 From: guido at python.org (Guido van Rossum) Date: Wed, 6 Aug 2008 12:32:25 -0700 Subject: [Python-3000-checkins] r65559 - in python/branches/py3k: Lib/test/test_urllib.py Lib/urllib/parse.py Modules/_sre.c In-Reply-To: <20080806192914.B59CA1E400D@bag.python.org> References: <20080806192914.B59CA1E400D@bag.python.org> Message-ID: Yes, I know the two Lib files shouldn't have been committed. I've already reverted them, r66650. On Wed, Aug 6, 2008 at 12:29 PM, guido.van.rossum wrote: > Author: guido.van.rossum > Date: Wed Aug 6 21:29:14 2008 > New Revision: 65559 > > Log: > Merged revisions 65544 via svnmerge from > svn+ssh://pythondev at svn.python.org/python/trunk > > ........ > r65544 | guido.van.rossum | 2008-08-04 20:39:21 -0700 (Mon, 04 Aug 2008) | 28 lines > > Tracker issue 3487: sre "bytecode" verifier. > > This is a verifier for the binary code used by the _sre module (this > is often called bytecode, though to distinguish it from Python bytecode > I put it in quotes). > > I wrote this for Google App Engine, and am making the patch available as > open source under the Apache 2 license. Below are the copyright > statement and license, for completeness. > > # Copyright 2008 Google Inc. > # > # Licensed under the Apache License, Version 2.0 (the "License"); > # you may not use this file except in compliance with the License. > # You may obtain a copy of the License at > # > # http://www.apache.org/licenses/LICENSE-2.0 > # > # Unless required by applicable law or agreed to in writing, software > # distributed under the License is distributed on an "AS IS" BASIS, > # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > # See the License for the specific language governing permissions and > # limitations under the License. > > It's not necessary to include these copyrights and bytecode in the > source file. Google has signed a contributor's agreement with the PSF > already. > ........ > > > Modified: > python/branches/py3k/ (props changed) > python/branches/py3k/Lib/test/test_urllib.py > python/branches/py3k/Lib/urllib/parse.py > python/branches/py3k/Modules/_sre.c > > Modified: python/branches/py3k/Lib/test/test_urllib.py > ============================================================================== > --- python/branches/py3k/Lib/test/test_urllib.py (original) > +++ python/branches/py3k/Lib/test/test_urllib.py Wed Aug 6 21:29:14 2008 > @@ -465,7 +465,7 @@ > > def test_unquote_with_unicode(self): > r = urllib.parse.unquote('br%C3%BCckner_sapporo_20050930.doc') > - self.assertEqual(r, 'br\xc3\xbcckner_sapporo_20050930.doc') > + self.assertEqual(r, 'br\u00FCckner_sapporo_20050930.doc') > > class urlencode_Tests(unittest.TestCase): > """Tests for urlencode()""" > > Modified: python/branches/py3k/Lib/urllib/parse.py > ============================================================================== > --- python/branches/py3k/Lib/urllib/parse.py (original) > +++ python/branches/py3k/Lib/urllib/parse.py Wed Aug 6 21:29:14 2008 > @@ -261,84 +261,74 @@ > return url, '' > > > -_hextochr = dict(('%02x' % i, chr(i)) for i in range(256)) > -_hextochr.update(('%02X' % i, chr(i)) for i in range(256)) > +def unquote_as_string (s, plus=False, charset=None): > + if charset is None: > + charset = "UTF-8" > + return str(unquote_as_bytes(s, plus=plus), charset, 'strict') > > -def unquote(s): > +def unquote_as_bytes (s, plus=False): > """unquote('abc%20def') -> 'abc def'.""" > + if plus: > + s = s.replace('+', ' ') > res = s.split('%') > + res[0] = res[0].encode('ASCII', 'strict') > for i in range(1, len(res)): > - item = res[i] > - try: > - res[i] = _hextochr[item[:2]] + item[2:] > - except KeyError: > - res[i] = '%' + item > - except UnicodeDecodeError: > - res[i] = chr(int(item[:2], 16)) + item[2:] > - return "".join(res) > - > -def unquote_plus(s): > - """unquote('%7e/abc+def') -> '~/abc def'""" > - s = s.replace('+', ' ') > - return unquote(s) > - > -always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' > - 'abcdefghijklmnopqrstuvwxyz' > - '0123456789' '_.-') > -_safe_quoters= {} > - > -class Quoter: > - def __init__(self, safe): > - self.cache = {} > - self.safe = safe + always_safe > + res[i] = (bytes.fromhex(res[i][:2]) + > + res[i][2:].encode('ASCII', 'strict')) > + return b''.join(res) > + > +_always_safe = (b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' > + b'abcdefghijklmnopqrstuvwxyz' > + b'0123456789' > + b'_.-') > + > +_percent_code = ord('%') > + > +_hextable = b'0123456789ABCDEF' > + > +def quote_as_bytes(s, safe = '/', plus=False): > + """quote(b'abc at def') -> 'abc%40def'""" > + > + if isinstance(s, str): > + s = s.encode("UTF-8", "strict") > + if not (isinstance(s, bytes) or isinstance(s, bytearray)): > + raise ValueError("Argument to quote must be either bytes " > + "or bytearray; string arguments will be " > + "converted to UTF-8 bytes") > + > + safeset = _always_safe + safe.encode('ASCII', 'strict') > + if plus: > + safeset += b' ' > + > + result = bytearray() > + for i in s: > + if i not in safeset: > + result.append(_percent_code) > + result.append(_hextable[(i >> 4) & 0xF]) > + result.append(_hextable[i & 0xF]) > + else: > + result.append(i) > + if plus: > + result = result.replace(b' ', b'+') > + return result > > - def __call__(self, c): > - try: > - return self.cache[c] > - except KeyError: > - if ord(c) < 256: > - res = (c in self.safe) and c or ('%%%02X' % ord(c)) > - self.cache[c] = res > - return res > - else: > - return "".join(['%%%02X' % i for i in c.encode("utf-8")]) > +def quote_as_string(s, safe = '/', plus=False): > + return str(quote_as_bytes(s, safe=safe, plus=plus), 'ASCII', 'strict') > > -def quote(s, safe = '/'): > - """quote('abc def') -> 'abc%20def' > +# finally, define defaults for 'quote' and 'unquote' > > - Each part of a URL, e.g. the path info, the query, etc., has a > - different set of reserved characters that must be quoted. > +def quote(s, safe='/'): > + return quote_as_string(s, safe=safe) > > - RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists > - the following reserved characters. > +def quote_plus(s, safe=''): > + return quote_as_string(s, safe=safe, plus=True) > > - reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | > - "$" | "," > +def unquote(s): > + return unquote_as_string(s) > > - Each of these characters is reserved in some component of a URL, > - but not necessarily in all of them. > +def unquote_plus(s): > + return unquote_as_string(s, plus=True) > > - By default, the quote function is intended for quoting the path > - section of a URL. Thus, it will not encode '/'. This character > - is reserved, but in typical usage the quote function is being > - called on a path where the existing slash characters are used as > - reserved characters. > - """ > - cachekey = (safe, always_safe) > - try: > - quoter = _safe_quoters[cachekey] > - except KeyError: > - quoter = Quoter(safe) > - _safe_quoters[cachekey] = quoter > - res = map(quoter, s) > - return ''.join(res) > - > -def quote_plus(s, safe = ''): > - """Quote the query fragment of a URL; replacing ' ' with '+'""" > - if ' ' in s: > - s = quote(s, safe + ' ') > - return s.replace(' ', '+') > - return quote(s, safe) > > def urlencode(query,doseq=0): > """Encode a sequence of two-element tuples or dictionary into a URL query string. > @@ -387,7 +377,7 @@ > # is there a reasonable way to convert to ASCII? > # encode generates a string, but "replace" or "ignore" > # lose information and "strict" can raise UnicodeError > - v = quote_plus(v.encode("ASCII","replace")) > + v = quote_plus(v) > l.append(k + '=' + v) > else: > try: > @@ -474,7 +464,8 @@ > _userprog = re.compile('^(.*)@(.*)$') > > match = _userprog.match(host) > - if match: return map(unquote, match.group(1, 2)) > + if match: > + return map(unquote, match.group(1, 2)) > return None, host > > _passwdprog = None > > Modified: python/branches/py3k/Modules/_sre.c > ============================================================================== > --- python/branches/py3k/Modules/_sre.c (original) > +++ python/branches/py3k/Modules/_sre.c Wed Aug 6 21:29:14 2008 > @@ -2637,6 +2637,8 @@ > pattern_members, /* tp_members */ > }; > > +static int _validate(PatternObject *self); /* Forward */ > + > static PyObject * > _compile(PyObject* self_, PyObject* args) > { > @@ -2695,10 +2697,482 @@ > > self->weakreflist = NULL; > > + if (!_validate(self)) { > + Py_DECREF(self); > + return NULL; > + } > + > return (PyObject*) self; > } > > /* -------------------------------------------------------------------- */ > +/* Code validation */ > + > +/* To learn more about this code, have a look at the _compile() function in > + Lib/sre_compile.py. The validation functions below checks the code array > + for conformance with the code patterns generated there. > + > + The nice thing about the generated code is that it is position-independent: > + all jumps are relative jumps forward. Also, jumps don't cross each other: > + the target of a later jump is always earlier than the target of an earlier > + jump. IOW, this is okay: > + > + J---------J-------T--------T > + \ \_____/ / > + \______________________/ > + > + but this is not: > + > + J---------J-------T--------T > + \_________\_____/ / > + \____________/ > + > + It also helps that SRE_CODE is always an unsigned type, either 2 bytes or 4 > + bytes wide (the latter if Python is compiled for "wide" unicode support). > +*/ > + > +/* Defining this one enables tracing of the validator */ > +#undef VVERBOSE > + > +/* Trace macro for the validator */ > +#if defined(VVERBOSE) > +#define VTRACE(v) printf v > +#else > +#define VTRACE(v) > +#endif > + > +/* Report failure */ > +#define FAIL do { VTRACE(("FAIL: %d\n", __LINE__)); return 0; } while (0) > + > +/* Extract opcode, argument, or skip count from code array */ > +#define GET_OP \ > + do { \ > + VTRACE(("%p: ", code)); \ > + if (code >= end) FAIL; \ > + op = *code++; \ > + VTRACE(("%lu (op)\n", (unsigned long)op)); \ > + } while (0) > +#define GET_ARG \ > + do { \ > + VTRACE(("%p= ", code)); \ > + if (code >= end) FAIL; \ > + arg = *code++; \ > + VTRACE(("%lu (arg)\n", (unsigned long)arg)); \ > + } while (0) > +#define GET_SKIP \ > + do { \ > + VTRACE(("%p= ", code)); \ > + if (code >= end) FAIL; \ > + skip = *code; \ > + VTRACE(("%lu (skip to %p)\n", \ > + (unsigned long)skip, code+skip)); \ > + if (code+skip < code || code+skip > end) \ > + FAIL; \ > + code++; \ > + } while (0) > + > +static int > +_validate_charset(SRE_CODE *code, SRE_CODE *end) > +{ > + /* Some variables are manipulated by the macros above */ > + SRE_CODE op; > + SRE_CODE arg; > + SRE_CODE offset; > + int i; > + > + while (code < end) { > + GET_OP; > + switch (op) { > + > + case SRE_OP_NEGATE: > + break; > + > + case SRE_OP_LITERAL: > + GET_ARG; > + break; > + > + case SRE_OP_RANGE: > + GET_ARG; > + GET_ARG; > + break; > + > + case SRE_OP_CHARSET: > + offset = 32/sizeof(SRE_CODE); /* 32-byte bitmap */ > + if (code+offset < code || code+offset > end) > + FAIL; > + code += offset; > + break; > + > + case SRE_OP_BIGCHARSET: > + GET_ARG; /* Number of blocks */ > + offset = 256/sizeof(SRE_CODE); /* 256-byte table */ > + if (code+offset < code || code+offset > end) > + FAIL; > + /* Make sure that each byte points to a valid block */ > + for (i = 0; i < 256; i++) { > + if (((unsigned char *)code)[i] >= arg) > + FAIL; > + } > + code += offset; > + offset = arg * 32/sizeof(SRE_CODE); /* 32-byte bitmap times arg */ > + if (code+offset < code || code+offset > end) > + FAIL; > + code += offset; > + break; > + > + case SRE_OP_CATEGORY: > + GET_ARG; > + switch (arg) { > + case SRE_CATEGORY_DIGIT: > + case SRE_CATEGORY_NOT_DIGIT: > + case SRE_CATEGORY_SPACE: > + case SRE_CATEGORY_NOT_SPACE: > + case SRE_CATEGORY_WORD: > + case SRE_CATEGORY_NOT_WORD: > + case SRE_CATEGORY_LINEBREAK: > + case SRE_CATEGORY_NOT_LINEBREAK: > + case SRE_CATEGORY_LOC_WORD: > + case SRE_CATEGORY_LOC_NOT_WORD: > + case SRE_CATEGORY_UNI_DIGIT: > + case SRE_CATEGORY_UNI_NOT_DIGIT: > + case SRE_CATEGORY_UNI_SPACE: > + case SRE_CATEGORY_UNI_NOT_SPACE: > + case SRE_CATEGORY_UNI_WORD: > + case SRE_CATEGORY_UNI_NOT_WORD: > + case SRE_CATEGORY_UNI_LINEBREAK: > + case SRE_CATEGORY_UNI_NOT_LINEBREAK: > + break; > + default: > + FAIL; > + } > + break; > + > + default: > + FAIL; > + > + } > + } > + > + return 1; > +} > + > +static int > +_validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) > +{ > + /* Some variables are manipulated by the macros above */ > + SRE_CODE op; > + SRE_CODE arg; > + SRE_CODE skip; > + > + VTRACE(("code=%p, end=%p\n", code, end)); > + > + if (code > end) > + FAIL; > + > + while (code < end) { > + GET_OP; > + switch (op) { > + > + case SRE_OP_MARK: > + /* We don't check whether marks are properly nested; the > + sre_match() code is robust even if they don't, and the worst > + you can get is nonsensical match results. */ > + GET_ARG; > + if (arg > 2*groups+1) { > + VTRACE(("arg=%d, groups=%d\n", (int)arg, (int)groups)); > + FAIL; > + } > + break; > + > + case SRE_OP_LITERAL: > + case SRE_OP_NOT_LITERAL: > + case SRE_OP_LITERAL_IGNORE: > + case SRE_OP_NOT_LITERAL_IGNORE: > + GET_ARG; > + /* The arg is just a character, nothing to check */ > + break; > + > + case SRE_OP_SUCCESS: > + case SRE_OP_FAILURE: > + /* Nothing to check; these normally end the matching process */ > + break; > + > + case SRE_OP_AT: > + GET_ARG; > + switch (arg) { > + case SRE_AT_BEGINNING: > + case SRE_AT_BEGINNING_STRING: > + case SRE_AT_BEGINNING_LINE: > + case SRE_AT_END: > + case SRE_AT_END_LINE: > + case SRE_AT_END_STRING: > + case SRE_AT_BOUNDARY: > + case SRE_AT_NON_BOUNDARY: > + case SRE_AT_LOC_BOUNDARY: > + case SRE_AT_LOC_NON_BOUNDARY: > + case SRE_AT_UNI_BOUNDARY: > + case SRE_AT_UNI_NON_BOUNDARY: > + break; > + default: > + FAIL; > + } > + break; > + > + case SRE_OP_ANY: > + case SRE_OP_ANY_ALL: > + /* These have no operands */ > + break; > + > + case SRE_OP_IN: > + case SRE_OP_IN_IGNORE: > + GET_SKIP; > + /* Stop 1 before the end; we check the FAILURE below */ > + if (!_validate_charset(code, code+skip-2)) > + FAIL; > + if (code[skip-2] != SRE_OP_FAILURE) > + FAIL; > + code += skip-1; > + break; > + > + case SRE_OP_INFO: > + { > + /* A minimal info field is > + <1=skip> <2=flags> <3=min> <4=max>; > + If SRE_INFO_PREFIX or SRE_INFO_CHARSET is in the flags, > + more follows. */ > + SRE_CODE flags, min, max, i; > + SRE_CODE *newcode; > + GET_SKIP; > + newcode = code+skip-1; > + GET_ARG; flags = arg; > + GET_ARG; min = arg; > + GET_ARG; max = arg; > + /* Check that only valid flags are present */ > + if ((flags & ~(SRE_INFO_PREFIX | > + SRE_INFO_LITERAL | > + SRE_INFO_CHARSET)) != 0) > + FAIL; > + /* PREFIX and CHARSET are mutually exclusive */ > + if ((flags & SRE_INFO_PREFIX) && > + (flags & SRE_INFO_CHARSET)) > + FAIL; > + /* LITERAL implies PREFIX */ > + if ((flags & SRE_INFO_LITERAL) && > + !(flags & SRE_INFO_PREFIX)) > + FAIL; > + /* Validate the prefix */ > + if (flags & SRE_INFO_PREFIX) { > + SRE_CODE prefix_len, prefix_skip; > + GET_ARG; prefix_len = arg; > + GET_ARG; prefix_skip = arg; > + /* Here comes the prefix string */ > + if (code+prefix_len < code || code+prefix_len > newcode) > + FAIL; > + code += prefix_len; > + /* And here comes the overlap table */ > + if (code+prefix_len < code || code+prefix_len > newcode) > + FAIL; > + /* Each overlap value should be < prefix_len */ > + for (i = 0; i < prefix_len; i++) { > + if (code[i] >= prefix_len) > + FAIL; > + } > + code += prefix_len; > + } > + /* Validate the charset */ > + if (flags & SRE_INFO_CHARSET) { > + if (!_validate_charset(code, newcode-1)) > + FAIL; > + if (newcode[-1] != SRE_OP_FAILURE) > + FAIL; > + code = newcode; > + } > + else if (code != newcode) { > + VTRACE(("code=%p, newcode=%p\n", code, newcode)); > + FAIL; > + } > + } > + break; > + > + case SRE_OP_BRANCH: > + { > + SRE_CODE *target = NULL; > + for (;;) { > + GET_SKIP; > + if (skip == 0) > + break; > + /* Stop 2 before the end; we check the JUMP below */ > + if (!_validate_inner(code, code+skip-3, groups)) > + FAIL; > + code += skip-3; > + /* Check that it ends with a JUMP, and that each JUMP > + has the same target */ > + GET_OP; > + if (op != SRE_OP_JUMP) > + FAIL; > + GET_SKIP; > + if (target == NULL) > + target = code+skip-1; > + else if (code+skip-1 != target) > + FAIL; > + } > + } > + break; > + > + case SRE_OP_REPEAT_ONE: > + case SRE_OP_MIN_REPEAT_ONE: > + { > + SRE_CODE min, max; > + GET_SKIP; > + GET_ARG; min = arg; > + GET_ARG; max = arg; > + if (min > max) > + FAIL; > +#ifdef Py_UNICODE_WIDE > + if (max > 65535) > + FAIL; > +#endif > + if (!_validate_inner(code, code+skip-4, groups)) > + FAIL; > + code += skip-4; > + GET_OP; > + if (op != SRE_OP_SUCCESS) > + FAIL; > + } > + break; > + > + case SRE_OP_REPEAT: > + { > + SRE_CODE min, max; > + GET_SKIP; > + GET_ARG; min = arg; > + GET_ARG; max = arg; > + if (min > max) > + FAIL; > +#ifdef Py_UNICODE_WIDE > + if (max > 65535) > + FAIL; > +#endif > + if (!_validate_inner(code, code+skip-3, groups)) > + FAIL; > + code += skip-3; > + GET_OP; > + if (op != SRE_OP_MAX_UNTIL && op != SRE_OP_MIN_UNTIL) > + FAIL; > + } > + break; > + > + case SRE_OP_GROUPREF: > + case SRE_OP_GROUPREF_IGNORE: > + GET_ARG; > + if (arg >= groups) > + FAIL; > + break; > + > + case SRE_OP_GROUPREF_EXISTS: > + /* The regex syntax for this is: '(?(group)then|else)', where > + 'group' is either an integer group number or a group name, > + 'then' and 'else' are sub-regexes, and 'else' is optional. */ > + GET_ARG; > + if (arg >= groups) > + FAIL; > + GET_SKIP; > + code--; /* The skip is relative to the first arg! */ > + /* There are two possibilities here: if there is both a 'then' > + part and an 'else' part, the generated code looks like: > + > + GROUPREF_EXISTS > + > + > + ...then part... > + JUMP > + > + ( jumps here) > + ...else part... > + ( jumps here) > + > + If there is only a 'then' part, it looks like: > + > + GROUPREF_EXISTS > + > + > + ...then part... > + ( jumps here) > + > + There is no direct way to decide which it is, and we don't want > + to allow arbitrary jumps anywhere in the code; so we just look > + for a JUMP opcode preceding our skip target. > + */ > + if (skip >= 3 && code+skip-3 >= code && > + code[skip-3] == SRE_OP_JUMP) > + { > + VTRACE(("both then and else parts present\n")); > + if (!_validate_inner(code+1, code+skip-3, groups)) > + FAIL; > + code += skip-2; /* Position after JUMP, at */ > + GET_SKIP; > + if (!_validate_inner(code, code+skip-1, groups)) > + FAIL; > + code += skip-1; > + } > + else { > + VTRACE(("only a then part present\n")); > + if (!_validate_inner(code+1, code+skip-1, groups)) > + FAIL; > + code += skip-1; > + } > + break; > + > + case SRE_OP_ASSERT: > + case SRE_OP_ASSERT_NOT: > + GET_SKIP; > + GET_ARG; /* 0 for lookahead, width for lookbehind */ > + code--; /* Back up over arg to simplify math below */ > + if (arg & 0x80000000) > + FAIL; /* Width too large */ > + /* Stop 1 before the end; we check the SUCCESS below */ > + if (!_validate_inner(code+1, code+skip-2, groups)) > + FAIL; > + code += skip-2; > + GET_OP; > + if (op != SRE_OP_SUCCESS) > + FAIL; > + break; > + > + default: > + FAIL; > + > + } > + } > + > + VTRACE(("okay\n")); > + return 1; > +} > + > +static int > +_validate_outer(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups) > +{ > + if (groups < 0 || groups > 100 || code >= end || end[-1] != SRE_OP_SUCCESS) > + FAIL; > + if (groups == 0) /* fix for simplejson */ > + groups = 100; /* 100 groups should always be safe */ > + return _validate_inner(code, end-1, groups); > +} > + > +static int > +_validate(PatternObject *self) > +{ > + if (!_validate_outer(self->code, self->code+self->codesize, self->groups)) > + { > + PyErr_SetString(PyExc_RuntimeError, "invalid SRE code"); > + return 0; > + } > + else > + VTRACE(("Success!\n")); > + return 1; > +} > + > +/* -------------------------------------------------------------------- */ > /* match methods */ > > static void > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > -- --Guido van Rossum (home page: http://www.python.org/~guido/) From python-3000-checkins at python.org Thu Aug 7 00:29:03 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Thu, 7 Aug 2008 00:29:03 +0200 (CEST) Subject: [Python-3000-checkins] r65564 - python/branches/py3k Message-ID: <20080806222903.688FB1E400D@bag.python.org> Author: brett.cannon Date: Thu Aug 7 00:28:55 2008 New Revision: 65564 Log: Blocked revisions 65563 via svnmerge ........ r65563 | brett.cannon | 2008-08-06 15:28:09 -0700 (Wed, 06 Aug 2008) | 3 lines Add imp.reload(). This to help with transitioning to 3.0 the reload() built-in has been removed there. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Thu Aug 7 20:47:29 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Thu, 7 Aug 2008 20:47:29 +0200 (CEST) Subject: [Python-3000-checkins] r65580 - python/branches/py3k Message-ID: <20080807184729.3DA1B1E4010@bag.python.org> Author: antoine.pitrou Date: Thu Aug 7 20:47:28 2008 New Revision: 65580 Log: Blocked revisions 65578 via svnmerge ........ r65578 | antoine.pitrou | 2008-08-07 20:42:40 +0200 (jeu., 07 ao?t 2008) | 3 lines #1288615: Python code.interact() and non-ASCII input ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Thu Aug 7 20:54:36 2008 From: python-3000-checkins at python.org (marc-andre.lemburg) Date: Thu, 7 Aug 2008 20:54:36 +0200 (CEST) Subject: [Python-3000-checkins] r65582 - in python/branches/py3k: Include/object.h Include/unicodeobject.h Misc/NEWS Modules/_ctypes/_ctypes.c Modules/_ctypes/callproc.c Modules/_ctypes/stgdict.c Modules/_elementtree.c Modules/_gestalt.c Modules/_hashopenssl.c Modules/_lsprof.c Modules/_pickle.c Modules/_sqlite/connection.c Modules/_sqlite/cursor.c Modules/_sqlite/row.c Modules/_sqlite/statement.c Modules/_ssl.c Modules/_struct.c Modules/_testcapimodule.c Modules/_tkinter.c Modules/cjkcodecs/cjkcodecs.h Modules/cjkcodecs/multibytecodec.c Modules/datetimemodule.c Modules/grpmodule.c Modules/operator.c Modules/ossaudiodev.c Modules/parsermodule.c Modules/posixmodule.c Modules/pyexpat.c Modules/readline.c Modules/socketmodule.c Modules/syslogmodule.c Modules/timemodule.c Modules/zipimport.c Objects/bytesobject.c Objects/codeobject.c Objects/exceptions.c Objects/floatobject.c Objects/funcobject.c Objects/moduleobject.c Objects/object.c Objects/setobject.c Objects/structseq.c Objects/typeobject.c Objects/unicodeobject.c Objects/weakrefobject.c Parser/tokenizer.c Python/_warnings.c Python/ast.c Python/bltinmodule.c Python/ceval.c Python/compile.c Python/errors.c Python/future.c Python/getargs.c Python/import.c Python/peephole.c Python/pythonrun.c Python/structmember.c Python/symtable.c Python/traceback.c Message-ID: <20080807185436.0C3DE1E400D@bag.python.org> Author: marc-andre.lemburg Date: Thu Aug 7 20:54:33 2008 New Revision: 65582 Log: Rename PyUnicode_AsString -> _PyUnicode_AsString and PyUnicode_AsStringAndSize -> _PyUnicode_AsStringAndSize to mark them for interpreter internal use only. We'll have to rework these APIs or create new ones for the purpose of accessing the UTF-8 representation of Unicode objects for 3.1. Modified: python/branches/py3k/Include/object.h python/branches/py3k/Include/unicodeobject.h python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_ctypes/_ctypes.c python/branches/py3k/Modules/_ctypes/callproc.c python/branches/py3k/Modules/_ctypes/stgdict.c python/branches/py3k/Modules/_elementtree.c python/branches/py3k/Modules/_gestalt.c python/branches/py3k/Modules/_hashopenssl.c python/branches/py3k/Modules/_lsprof.c python/branches/py3k/Modules/_pickle.c python/branches/py3k/Modules/_sqlite/connection.c python/branches/py3k/Modules/_sqlite/cursor.c python/branches/py3k/Modules/_sqlite/row.c python/branches/py3k/Modules/_sqlite/statement.c python/branches/py3k/Modules/_ssl.c python/branches/py3k/Modules/_struct.c python/branches/py3k/Modules/_testcapimodule.c python/branches/py3k/Modules/_tkinter.c python/branches/py3k/Modules/cjkcodecs/cjkcodecs.h python/branches/py3k/Modules/cjkcodecs/multibytecodec.c python/branches/py3k/Modules/datetimemodule.c python/branches/py3k/Modules/grpmodule.c python/branches/py3k/Modules/operator.c python/branches/py3k/Modules/ossaudiodev.c python/branches/py3k/Modules/parsermodule.c python/branches/py3k/Modules/posixmodule.c python/branches/py3k/Modules/pyexpat.c python/branches/py3k/Modules/readline.c python/branches/py3k/Modules/socketmodule.c python/branches/py3k/Modules/syslogmodule.c python/branches/py3k/Modules/timemodule.c python/branches/py3k/Modules/zipimport.c python/branches/py3k/Objects/bytesobject.c python/branches/py3k/Objects/codeobject.c python/branches/py3k/Objects/exceptions.c python/branches/py3k/Objects/floatobject.c python/branches/py3k/Objects/funcobject.c python/branches/py3k/Objects/moduleobject.c python/branches/py3k/Objects/object.c python/branches/py3k/Objects/setobject.c python/branches/py3k/Objects/structseq.c python/branches/py3k/Objects/typeobject.c python/branches/py3k/Objects/unicodeobject.c python/branches/py3k/Objects/weakrefobject.c python/branches/py3k/Parser/tokenizer.c python/branches/py3k/Python/_warnings.c python/branches/py3k/Python/ast.c python/branches/py3k/Python/bltinmodule.c python/branches/py3k/Python/ceval.c python/branches/py3k/Python/compile.c python/branches/py3k/Python/errors.c python/branches/py3k/Python/future.c python/branches/py3k/Python/getargs.c python/branches/py3k/Python/import.c python/branches/py3k/Python/peephole.c python/branches/py3k/Python/pythonrun.c python/branches/py3k/Python/structmember.c python/branches/py3k/Python/symtable.c python/branches/py3k/Python/traceback.c Modified: python/branches/py3k/Include/object.h ============================================================================== --- python/branches/py3k/Include/object.h (original) +++ python/branches/py3k/Include/object.h Thu Aug 7 20:54:33 2008 @@ -466,7 +466,7 @@ PyAPI_FUNC(long) _Py_HashPointer(void*); /* Helper for passing objects to printf and the like */ -#define PyObject_REPR(obj) PyUnicode_AsString(PyObject_Repr(obj)) +#define PyObject_REPR(obj) _PyUnicode_AsString(PyObject_Repr(obj)) /* Flag bits for printing: */ #define Py_PRINT_RAW 1 /* No string quotes etc. */ Modified: python/branches/py3k/Include/unicodeobject.h ============================================================================== --- python/branches/py3k/Include/unicodeobject.h (original) +++ python/branches/py3k/Include/unicodeobject.h Thu Aug 7 20:54:33 2008 @@ -704,9 +704,15 @@ In case of an error, no *size is set. + *** This API is for interpreter INTERNAL USE ONLY and will likely + *** be removed or changed for Python 3.1. + + *** If you need to access the Unicode object as UTF-8 bytes string, + *** please use PyUnicode_AsUTF8String() instead. + */ -PyAPI_FUNC(char *) PyUnicode_AsStringAndSize( +PyAPI_FUNC(char *) _PyUnicode_AsStringAndSize( PyObject *unicode, Py_ssize_t *size); @@ -714,12 +720,17 @@ Unicode object unicode. Use of this API is DEPRECATED since no size information can be - extracted from the returned data. Use PyUnicode_AsStringAndSize() - instead. + extracted from the returned data. + + *** This API is for interpreter INTERNAL USE ONLY and will likely + *** be removed or changed for Python 3.1. + + *** If you need to access the Unicode object as UTF-8 bytes string, + *** please use PyUnicode_AsUTF8String() instead. */ -PyAPI_FUNC(char *) PyUnicode_AsString(PyObject *unicode); +PyAPI_FUNC(char *) _PyUnicode_AsString(PyObject *unicode); /* Returns the currently active default encoding. Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Aug 7 20:54:33 2008 @@ -15,6 +15,14 @@ - Issue #1819: function calls with several named parameters are now on average 35% faster (as measured by pybench). +- The undocumented C APIs PyUnicode_AsString() and + PyUnicode_AsStringAndSize() were made private to the interpreter, in + order to be able to refine their interfaces for Python 3.1. + + If you need to access the UTF-8 representation of a Unicode object + as bytes string, please use PyUnicode_AsUTF8String() instead. + + Library ------- Modified: python/branches/py3k/Modules/_ctypes/_ctypes.c ============================================================================== --- python/branches/py3k/Modules/_ctypes/_ctypes.c (original) +++ python/branches/py3k/Modules/_ctypes/_ctypes.c Thu Aug 7 20:54:33 2008 @@ -683,8 +683,8 @@ return -1; if (value && PyUnicode_Check(key) && - /* XXX struni PyUnicode_AsString can fail (also in other places)! */ - 0 == strcmp(PyUnicode_AsString(key), "_fields_")) + /* XXX struni _PyUnicode_AsString can fail (also in other places)! */ + 0 == strcmp(_PyUnicode_AsString(key), "_fields_")) return StructUnionType_update_stgdict(self, value, 1); return 0; } @@ -698,7 +698,7 @@ return -1; if (PyUnicode_Check(key) && - 0 == strcmp(PyUnicode_AsString(key), "_fields_")) + 0 == strcmp(_PyUnicode_AsString(key), "_fields_")) return StructUnionType_update_stgdict(self, value, 0); return 0; } @@ -1681,7 +1681,7 @@ if (stgd && CDataObject_Check(value) && stgd->proto && PyUnicode_Check(stgd->proto)) { PyCArgObject *parg; - switch (PyUnicode_AsString(stgd->proto)[0]) { + switch (_PyUnicode_AsString(stgd->proto)[0]) { case 'z': /* c_char_p */ case 'Z': /* c_wchar_p */ parg = new_CArgObject(); @@ -1791,7 +1791,7 @@ dict = PyObject_stgdict((PyObject *)self); assert(dict); /* Cannot be NULL for CDataObject instances */ - fmt = PyUnicode_AsString(dict->proto); + fmt = _PyUnicode_AsString(dict->proto); assert(fmt); fd = getentry(fmt); @@ -2012,7 +2012,7 @@ assert(dict); /* I think we can rely on this being a one-character string */ - fmt = PyUnicode_AsString(dict->proto); + fmt = _PyUnicode_AsString(dict->proto); assert(fmt); fd = getentry(fmt); @@ -3058,7 +3058,7 @@ /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ && PyUnicode_Check(dict->proto) /* We only allow c_void_p, c_char_p and c_wchar_p as a simple output parameter type */ - && (strchr("PzZ", PyUnicode_AsString(dict->proto)[0]))) { + && (strchr("PzZ", _PyUnicode_AsString(dict->proto)[0]))) { return 1; } @@ -3148,7 +3148,7 @@ return *pname ? 1 : 0; } if (PyUnicode_Check(obj)) { - *pname = PyUnicode_AsString(obj); + *pname = _PyUnicode_AsString(obj); return *pname ? 1 : 0; } PyErr_SetString(PyExc_TypeError, @@ -5127,7 +5127,7 @@ dict = PyType_stgdict(arg); if (dict) { if (PyUnicode_Check(dict->proto) - && (strchr("sPzUZXO", PyUnicode_AsString(dict->proto)[0]))) { + && (strchr("sPzUZXO", _PyUnicode_AsString(dict->proto)[0]))) { /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ return 1; } Modified: python/branches/py3k/Modules/_ctypes/callproc.c ============================================================================== --- python/branches/py3k/Modules/_ctypes/callproc.c (original) +++ python/branches/py3k/Modules/_ctypes/callproc.c Thu Aug 7 20:54:33 2008 @@ -1750,7 +1750,7 @@ return result; } if (PyUnicode_CheckExact(cls)) { - char *name = PyUnicode_AsString(cls); + char *name = _PyUnicode_AsString(cls); buf = alloca(strlen(name) + 3 + 1); sprintf(buf, "LP_%s", name); result = PyObject_CallFunction((PyObject *)Py_TYPE(&Pointer_Type), Modified: python/branches/py3k/Modules/_ctypes/stgdict.c ============================================================================== --- python/branches/py3k/Modules/_ctypes/stgdict.c (original) +++ python/branches/py3k/Modules/_ctypes/stgdict.c Thu Aug 7 20:54:33 2008 @@ -479,7 +479,7 @@ bitsize = 0; if (isStruct && !isPacked) { char *fieldfmt = dict->format ? dict->format : "B"; - char *fieldname = PyUnicode_AsString(name); + char *fieldname = _PyUnicode_AsString(name); char *ptr; Py_ssize_t len = strlen(fieldname) + strlen(fieldfmt); char *buf = alloca(len + 2 + 1); Modified: python/branches/py3k/Modules/_elementtree.c ============================================================================== --- python/branches/py3k/Modules/_elementtree.c (original) +++ python/branches/py3k/Modules/_elementtree.c Thu Aug 7 20:54:33 2008 @@ -1303,7 +1303,7 @@ char *name = ""; if (PyUnicode_Check(nameobj)) - name = PyUnicode_AsString(nameobj); + name = _PyUnicode_AsString(nameobj); if (strcmp(name, "tag") == 0) res = self->tag; @@ -2529,7 +2529,7 @@ char *name = ""; if (PyUnicode_Check(nameobj)) - name = PyUnicode_AsString(nameobj); + name = _PyUnicode_AsString(nameobj); PyErr_Clear(); Modified: python/branches/py3k/Modules/_gestalt.c ============================================================================== --- python/branches/py3k/Modules/_gestalt.c (original) +++ python/branches/py3k/Modules/_gestalt.c Thu Aug 7 20:54:33 2008 @@ -38,7 +38,7 @@ "OSType arg must be string of 4 chars"); return 0; } - memcpy((char *)&tmp, PyUnicode_AsString(v), 4); + memcpy((char *)&tmp, _PyUnicode_AsString(v), 4); *pr = (OSType)ntohl(tmp); return 1; } Modified: python/branches/py3k/Modules/_hashopenssl.c ============================================================================== --- python/branches/py3k/Modules/_hashopenssl.c (original) +++ python/branches/py3k/Modules/_hashopenssl.c Thu Aug 7 20:54:33 2008 @@ -241,7 +241,7 @@ { char buf[100]; PyOS_snprintf(buf, sizeof(buf), "<%s HASH object @ %p>", - PyUnicode_AsString(((EVPobject *)self)->name), self); + _PyUnicode_AsString(((EVPobject *)self)->name), self); return PyUnicode_FromString(buf); } Modified: python/branches/py3k/Modules/_lsprof.c ============================================================================== --- python/branches/py3k/Modules/_lsprof.c (original) +++ python/branches/py3k/Modules/_lsprof.c Thu Aug 7 20:54:33 2008 @@ -180,7 +180,7 @@ PyObject *mod = fn->m_module; const char *modname; if (mod && PyUnicode_Check(mod)) { - modname = PyUnicode_AsString(mod); + modname = _PyUnicode_AsString(mod); } else if (mod && PyModule_Check(mod)) { modname = PyModule_GetName(mod); Modified: python/branches/py3k/Modules/_pickle.c ============================================================================== --- python/branches/py3k/Modules/_pickle.c (original) +++ python/branches/py3k/Modules/_pickle.c Thu Aug 7 20:54:33 2008 @@ -927,7 +927,7 @@ repr = PyUnicode_FromStringAndSize(NULL, (int)nbytes); if (repr == NULL) goto error; - pdata = (unsigned char *)PyUnicode_AsString(repr); + pdata = (unsigned char *)_PyUnicode_AsString(repr); i = _PyLong_AsByteArray((PyLongObject *)obj, pdata, nbytes, 1 /* little endian */ , 1 /* signed */ ); @@ -972,7 +972,7 @@ if (repr == NULL) goto error; - string = PyUnicode_AsStringAndSize(repr, &size); + string = _PyUnicode_AsStringAndSize(repr, &size); if (string == NULL) goto error; @@ -1869,7 +1869,7 @@ /* XXX: Should it check whether the persistent id only contains ASCII characters? And what if the pid contains embedded newlines? */ - pid_ascii_bytes = PyUnicode_AsStringAndSize(pid_str, &size); + pid_ascii_bytes = _PyUnicode_AsStringAndSize(pid_str, &size); Py_DECREF(pid_str); if (pid_ascii_bytes == NULL) goto error; Modified: python/branches/py3k/Modules/_sqlite/connection.c ============================================================================== --- python/branches/py3k/Modules/_sqlite/connection.c (original) +++ python/branches/py3k/Modules/_sqlite/connection.c Thu Aug 7 20:54:33 2008 @@ -434,7 +434,7 @@ } else if (PyFloat_Check(py_val)) { sqlite3_result_double(context, PyFloat_AsDouble(py_val)); } else if (PyUnicode_Check(py_val)) { - sqlite3_result_text(context, PyUnicode_AsString(py_val), -1, SQLITE_TRANSIENT); + sqlite3_result_text(context, _PyUnicode_AsString(py_val), -1, SQLITE_TRANSIENT); } else if (PyObject_CheckBuffer(py_val)) { if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) { PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); @@ -901,7 +901,7 @@ return -1; } - statement = PyUnicode_AsStringAndSize(begin_statement, &size); + statement = _PyUnicode_AsStringAndSize(begin_statement, &size); if (!statement) { Py_DECREF(statement); return -1; @@ -1194,7 +1194,7 @@ goto finally; } - chk = PyUnicode_AsString(uppercase_name); + chk = _PyUnicode_AsString(uppercase_name); while (*chk) { if ((*chk >= '0' && *chk <= '9') || (*chk >= 'A' && *chk <= 'Z') @@ -1219,7 +1219,7 @@ } rc = sqlite3_create_collation(self->db, - PyUnicode_AsString(uppercase_name), + _PyUnicode_AsString(uppercase_name), SQLITE_UTF8, (callable != Py_None) ? callable : NULL, (callable != Py_None) ? pysqlite_collation_callback : NULL); Modified: python/branches/py3k/Modules/_sqlite/cursor.c ============================================================================== --- python/branches/py3k/Modules/_sqlite/cursor.c (original) +++ python/branches/py3k/Modules/_sqlite/cursor.c Thu Aug 7 20:54:33 2008 @@ -490,7 +490,7 @@ rc = pysqlite_statement_reset(self->statement); } - operation_cstr = PyUnicode_AsStringAndSize(operation, &operation_len); + operation_cstr = _PyUnicode_AsStringAndSize(operation, &operation_len); if (operation == NULL) goto error; @@ -793,7 +793,7 @@ } if (PyUnicode_Check(script_obj)) { - script_cstr = PyUnicode_AsString(script_obj); + script_cstr = _PyUnicode_AsString(script_obj); if (!script_cstr) { return NULL; } Modified: python/branches/py3k/Modules/_sqlite/row.c ============================================================================== --- python/branches/py3k/Modules/_sqlite/row.c (original) +++ python/branches/py3k/Modules/_sqlite/row.c Thu Aug 7 20:54:33 2008 @@ -82,12 +82,12 @@ Py_XINCREF(item); return item; } else if (PyUnicode_Check(idx)) { - key = PyUnicode_AsString(idx); + key = _PyUnicode_AsString(idx); nitems = PyTuple_Size(self->description); for (i = 0; i < nitems; i++) { - compare_key = PyUnicode_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)); + compare_key = _PyUnicode_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)); if (!compare_key) { return NULL; } Modified: python/branches/py3k/Modules/_sqlite/statement.c ============================================================================== --- python/branches/py3k/Modules/_sqlite/statement.c (original) +++ python/branches/py3k/Modules/_sqlite/statement.c Thu Aug 7 20:54:33 2008 @@ -59,7 +59,7 @@ self->st = NULL; self->in_use = 0; - sql_cstr = PyUnicode_AsStringAndSize(sql, &sql_cstr_len); + sql_cstr = _PyUnicode_AsStringAndSize(sql, &sql_cstr_len); if (sql_cstr == NULL) { rc = PYSQLITE_SQL_WRONG_TYPE; return rc; @@ -140,7 +140,7 @@ rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter)); break; case TYPE_UNICODE: - string = PyUnicode_AsString(parameter); + string = _PyUnicode_AsString(parameter); rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT); break; case TYPE_BUFFER: @@ -296,7 +296,7 @@ Py_ssize_t sql_len; sqlite3_stmt* new_st; - sql_cstr = PyUnicode_AsStringAndSize(self->sql, &sql_len); + sql_cstr = _PyUnicode_AsStringAndSize(self->sql, &sql_len); if (sql_cstr == NULL) { rc = PYSQLITE_SQL_WRONG_TYPE; return rc; Modified: python/branches/py3k/Modules/_ssl.c ============================================================================== --- python/branches/py3k/Modules/_ssl.c (original) +++ python/branches/py3k/Modules/_ssl.c Thu Aug 7 20:54:33 2008 @@ -1461,7 +1461,7 @@ return PyErr_Format(PyExc_TypeError, "RAND_egd() expected string, found %s", Py_TYPE(arg)->tp_name); - bytes = RAND_egd(PyUnicode_AsString(arg)); + bytes = RAND_egd(_PyUnicode_AsString(arg)); if (bytes == -1) { PyErr_SetString(PySSLErrorObject, "EGD connection failed or EGD did not return " Modified: python/branches/py3k/Modules/_struct.c ============================================================================== --- python/branches/py3k/Modules/_struct.c (original) +++ python/branches/py3k/Modules/_struct.c Thu Aug 7 20:54:33 2008 @@ -406,7 +406,7 @@ if (msg == NULL) return -1; rval = PyErr_WarnEx(PyExc_DeprecationWarning, - PyUnicode_AsString(msg), 2); + _PyUnicode_AsString(msg), 2); Py_DECREF(msg); if (rval == 0) return 0; Modified: python/branches/py3k/Modules/_testcapimodule.c ============================================================================== --- python/branches/py3k/Modules/_testcapimodule.c (original) +++ python/branches/py3k/Modules/_testcapimodule.c Thu Aug 7 20:54:33 2008 @@ -788,7 +788,7 @@ result = PyUnicode_FromFormat(FORMAT, (TYPE)1); \ if (result == NULL) \ return NULL; \ - if (strcmp(PyUnicode_AsString(result), "1")) { \ + if (strcmp(_PyUnicode_AsString(result), "1")) { \ msg = FORMAT " failed at 1"; \ goto Fail; \ } \ Modified: python/branches/py3k/Modules/_tkinter.c ============================================================================== --- python/branches/py3k/Modules/_tkinter.c (original) +++ python/branches/py3k/Modules/_tkinter.c Thu Aug 7 20:54:33 2008 @@ -1424,7 +1424,7 @@ return 1; } if (PyUnicode_Check(in)) { - *out = PyUnicode_AsString(in); + *out = _PyUnicode_AsString(in); return 1; } if (PyTclObject_Check(in)) { Modified: python/branches/py3k/Modules/cjkcodecs/cjkcodecs.h ============================================================================== --- python/branches/py3k/Modules/cjkcodecs/cjkcodecs.h (original) +++ python/branches/py3k/Modules/cjkcodecs/cjkcodecs.h Thu Aug 7 20:54:33 2008 @@ -266,7 +266,7 @@ "encoding name must be a string."); return NULL; } - enc = PyUnicode_AsString(encoding); + enc = _PyUnicode_AsString(encoding); if (enc == NULL) return NULL; Modified: python/branches/py3k/Modules/cjkcodecs/multibytecodec.c ============================================================================== --- python/branches/py3k/Modules/cjkcodecs/multibytecodec.c (original) +++ python/branches/py3k/Modules/cjkcodecs/multibytecodec.c Thu Aug 7 20:54:33 2008 @@ -95,7 +95,7 @@ const char *str; assert(PyUnicode_Check(errors)); - str = PyUnicode_AsString(errors); + str = _PyUnicode_AsString(errors); if (str == NULL) return NULL; cb = PyCodec_LookupError(str); @@ -148,7 +148,7 @@ return -1; } - str = PyUnicode_AsString(value); + str = _PyUnicode_AsString(value); if (str == NULL) return -1; Modified: python/branches/py3k/Modules/datetimemodule.c ============================================================================== --- python/branches/py3k/Modules/datetimemodule.c (original) +++ python/branches/py3k/Modules/datetimemodule.c Thu Aug 7 20:54:33 2008 @@ -1219,7 +1219,7 @@ assert(object && format && timetuple); assert(PyUnicode_Check(format)); /* Convert the input format to a C string and size */ - pin = PyUnicode_AsStringAndSize(format, &flen); + pin = _PyUnicode_AsStringAndSize(format, &flen); if (!pin) return NULL; @@ -1312,7 +1312,7 @@ } assert(Zreplacement != NULL); assert(PyUnicode_Check(Zreplacement)); - ptoappend = PyUnicode_AsStringAndSize(Zreplacement, + ptoappend = _PyUnicode_AsStringAndSize(Zreplacement, &ntoappend); ntoappend = Py_SIZE(Zreplacement); } Modified: python/branches/py3k/Modules/grpmodule.c ============================================================================== --- python/branches/py3k/Modules/grpmodule.c (original) +++ python/branches/py3k/Modules/grpmodule.c Thu Aug 7 20:54:33 2008 @@ -113,7 +113,7 @@ py_str_name = PyObject_Str(pyo_name); if (!py_str_name) return NULL; - name = PyUnicode_AsString(py_str_name); + name = _PyUnicode_AsString(py_str_name); if ((p = getgrnam(name)) == NULL) { PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %s", name); Modified: python/branches/py3k/Modules/operator.c ============================================================================== --- python/branches/py3k/Modules/operator.c (original) +++ python/branches/py3k/Modules/operator.c Thu Aug 7 20:54:33 2008 @@ -449,7 +449,7 @@ return NULL; } - s = PyUnicode_AsString(attr); + s = _PyUnicode_AsString(attr); Py_INCREF(obj); for (;;) { PyObject *newobj, *str; Modified: python/branches/py3k/Modules/ossaudiodev.c ============================================================================== --- python/branches/py3k/Modules/ossaudiodev.c (original) +++ python/branches/py3k/Modules/ossaudiodev.c Thu Aug 7 20:54:33 2008 @@ -809,7 +809,7 @@ PyObject * rval = NULL; if (PyUnicode_Check(nameobj)) - name = PyUnicode_AsString(nameobj); + name = _PyUnicode_AsString(nameobj); if (strcmp(name, "closed") == 0) { rval = (self->fd == -1) ? Py_True : Py_False; Modified: python/branches/py3k/Modules/parsermodule.c ============================================================================== --- python/branches/py3k/Modules/parsermodule.c (original) +++ python/branches/py3k/Modules/parsermodule.c Thu Aug 7 20:54:33 2008 @@ -718,7 +718,7 @@ Py_DECREF(o); } } - temp_str = PyUnicode_AsStringAndSize(temp, &len); + temp_str = _PyUnicode_AsStringAndSize(temp, &len); strn = (char *)PyObject_MALLOC(len + 1); if (strn != NULL) (void) memcpy(strn, temp_str, len + 1); @@ -807,7 +807,7 @@ if (res && encoding) { Py_ssize_t len; const char *temp; - temp = PyUnicode_AsStringAndSize(encoding, &len); + temp = _PyUnicode_AsStringAndSize(encoding, &len); res->n_str = (char *)PyObject_MALLOC(len + 1); if (res->n_str != NULL && temp != NULL) (void) memcpy(res->n_str, temp, len + 1); Modified: python/branches/py3k/Modules/posixmodule.c ============================================================================== --- python/branches/py3k/Modules/posixmodule.c (original) +++ python/branches/py3k/Modules/posixmodule.c Thu Aug 7 20:54:33 2008 @@ -5566,7 +5566,7 @@ "configuration names must be strings or integers"); return 0; } - confname = PyUnicode_AsString(arg); + confname = _PyUnicode_AsString(arg); if (confname == NULL) return 0; while (lo < hi) { @@ -5897,7 +5897,7 @@ if ((unsigned int)len >= sizeof(buffer)) { result = PyUnicode_FromStringAndSize(NULL, len-1); if (result != NULL) - confstr(name, PyUnicode_AsString(result), len); + confstr(name, _PyUnicode_AsString(result), len); } else result = PyUnicode_FromStringAndSize(buffer, len-1); Modified: python/branches/py3k/Modules/pyexpat.c ============================================================================== --- python/branches/py3k/Modules/pyexpat.c (original) +++ python/branches/py3k/Modules/pyexpat.c Thu Aug 7 20:54:33 2008 @@ -1338,7 +1338,7 @@ int handlernum = -1; if (PyUnicode_Check(nameobj)) - name = PyUnicode_AsString(nameobj); + name = _PyUnicode_AsString(nameobj); handlernum = handlername2int(name); Modified: python/branches/py3k/Modules/readline.c ============================================================================== --- python/branches/py3k/Modules/readline.c (original) +++ python/branches/py3k/Modules/readline.c Thu Aug 7 20:54:33 2008 @@ -724,7 +724,7 @@ result = NULL; } else { - char *s = PyUnicode_AsString(r); + char *s = _PyUnicode_AsString(r); if (s == NULL) goto error; result = strdup(s); Modified: python/branches/py3k/Modules/socketmodule.c ============================================================================== --- python/branches/py3k/Modules/socketmodule.c (original) +++ python/branches/py3k/Modules/socketmodule.c Thu Aug 7 20:54:33 2008 @@ -3744,7 +3744,7 @@ PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", value); pptr = pbuf; } else if (PyUnicode_Check(pobj)) { - pptr = PyUnicode_AsString(pobj); + pptr = _PyUnicode_AsString(pobj); } else if (PyBytes_Check(pobj)) { pptr = PyBytes_AsString(pobj); } else if (pobj == Py_None) { Modified: python/branches/py3k/Modules/syslogmodule.c ============================================================================== --- python/branches/py3k/Modules/syslogmodule.c (original) +++ python/branches/py3k/Modules/syslogmodule.c Thu Aug 7 20:54:33 2008 @@ -72,7 +72,7 @@ S_ident_o = new_S_ident_o; Py_INCREF(S_ident_o); - ident = PyUnicode_AsString(S_ident_o); + ident = _PyUnicode_AsString(S_ident_o); if (ident == NULL) return NULL; openlog(ident, logopt, facility); @@ -97,7 +97,7 @@ return NULL; } - message = PyUnicode_AsString(message_object); + message = _PyUnicode_AsString(message_object); if (message == NULL) return NULL; Py_BEGIN_ALLOW_THREADS; Modified: python/branches/py3k/Modules/timemodule.c ============================================================================== --- python/branches/py3k/Modules/timemodule.c (original) +++ python/branches/py3k/Modules/timemodule.c Thu Aug 7 20:54:33 2008 @@ -509,7 +509,7 @@ } /* Convert the unicode string to an ascii one */ - fmt = PyUnicode_AsString(format); + fmt = _PyUnicode_AsString(format); fmtlen = strlen(fmt); Modified: python/branches/py3k/Modules/zipimport.c ============================================================================== --- python/branches/py3k/Modules/zipimport.c (original) +++ python/branches/py3k/Modules/zipimport.c Thu Aug 7 20:54:33 2008 @@ -180,9 +180,9 @@ char *prefix = ""; if (self->archive != NULL && PyUnicode_Check(self->archive)) - archive = PyUnicode_AsString(self->archive); + archive = _PyUnicode_AsString(self->archive); if (self->prefix != NULL && PyUnicode_Check(self->prefix)) - prefix = PyUnicode_AsString(self->prefix); + prefix = _PyUnicode_AsString(self->prefix); if (prefix != NULL && *prefix) return PyUnicode_FromFormat("", archive, SEP, prefix); @@ -248,7 +248,7 @@ subname = get_subname(fullname); - len = make_filename(PyUnicode_AsString(self->prefix), subname, path); + len = make_filename(_PyUnicode_AsString(self->prefix), subname, path); if (len < 0) return MI_ERROR; @@ -321,12 +321,12 @@ /* add __path__ to the module *before* the code gets executed */ PyObject *pkgpath, *fullpath; - char *prefix = PyUnicode_AsString(self->prefix); + char *prefix = _PyUnicode_AsString(self->prefix); char *subname = get_subname(fullname); int err; fullpath = PyUnicode_FromFormat("%s%c%s%s", - PyUnicode_AsString(self->archive), + _PyUnicode_AsString(self->archive), SEP, prefix ? prefix : "", subname); @@ -404,7 +404,7 @@ } path = buf; #endif - archive_str = PyUnicode_AsStringAndSize(self->archive, &len); + archive_str = _PyUnicode_AsStringAndSize(self->archive, &len); if ((size_t)len < strlen(path) && strncmp(path, archive_str, len) == 0 && path[len] == SEP) { @@ -453,7 +453,7 @@ } subname = get_subname(fullname); - len = make_filename(PyUnicode_AsString(self->prefix), subname, path); + len = make_filename(_PyUnicode_AsString(self->prefix), subname, path); if (len < 0) return NULL; @@ -466,7 +466,7 @@ toc_entry = PyDict_GetItemString(self->files, path); if (toc_entry != NULL) { - PyObject *bytes = get_data(PyUnicode_AsString(self->archive), toc_entry); + PyObject *bytes = get_data(_PyUnicode_AsString(self->archive), toc_entry); PyObject *res = PyUnicode_FromString(PyByteArray_AsString(bytes)); Py_XDECREF(bytes); return res; @@ -1053,7 +1053,7 @@ { PyObject *data, *code; char *modpath; - char *archive = PyUnicode_AsString(self->archive); + char *archive = _PyUnicode_AsString(self->archive); if (archive == NULL) return NULL; @@ -1062,7 +1062,7 @@ if (data == NULL) return NULL; - modpath = PyUnicode_AsString(PyTuple_GetItem(toc_entry, 0)); + modpath = _PyUnicode_AsString(PyTuple_GetItem(toc_entry, 0)); if (isbytecode) { code = unmarshal_code(modpath, data, mtime); @@ -1087,7 +1087,7 @@ subname = get_subname(fullname); - len = make_filename(PyUnicode_AsString(self->prefix), subname, path); + len = make_filename(_PyUnicode_AsString(self->prefix), subname, path); if (len < 0) return NULL; @@ -1097,7 +1097,7 @@ strcpy(path + len, zso->suffix); if (Py_VerboseFlag > 1) PySys_WriteStderr("# trying %s%c%s\n", - PyUnicode_AsString(self->archive), + _PyUnicode_AsString(self->archive), SEP, path); toc_entry = PyDict_GetItemString(self->files, path); if (toc_entry != NULL) { @@ -1119,7 +1119,7 @@ continue; } if (code != NULL && p_modpath != NULL) - *p_modpath = PyUnicode_AsString( + *p_modpath = _PyUnicode_AsString( PyTuple_GetItem(toc_entry, 0)); return code; } Modified: python/branches/py3k/Objects/bytesobject.c ============================================================================== --- python/branches/py3k/Objects/bytesobject.c (original) +++ python/branches/py3k/Objects/bytesobject.c Thu Aug 7 20:54:33 2008 @@ -3230,7 +3230,7 @@ if (!result) return NULL; - buf = PyUnicode_AsString(result); + buf = _PyUnicode_AsString(result); if (!buf) { Py_DECREF(result); return NULL; Modified: python/branches/py3k/Objects/codeobject.c ============================================================================== --- python/branches/py3k/Objects/codeobject.c (original) +++ python/branches/py3k/Objects/codeobject.c Thu Aug 7 20:54:33 2008 @@ -296,7 +296,7 @@ if (co->co_firstlineno != 0) lineno = co->co_firstlineno; if (co->co_filename && PyUnicode_Check(co->co_filename)) - filename = PyUnicode_AsString(co->co_filename); + filename = _PyUnicode_AsString(co->co_filename); return PyUnicode_FromFormat( "", co->co_name, co, filename, lineno); Modified: python/branches/py3k/Objects/exceptions.c ============================================================================== --- python/branches/py3k/Objects/exceptions.c (original) +++ python/branches/py3k/Objects/exceptions.c Thu Aug 7 20:54:33 2008 @@ -943,7 +943,7 @@ lineno here */ if (self->filename && PyUnicode_Check(self->filename)) { - filename = PyUnicode_AsString(self->filename); + filename = _PyUnicode_AsString(self->filename); } have_lineno = (self->lineno != NULL) && PyLong_CheckExact(self->lineno); Modified: python/branches/py3k/Objects/floatobject.c ============================================================================== --- python/branches/py3k/Objects/floatobject.c (original) +++ python/branches/py3k/Objects/floatobject.c Thu Aug 7 20:54:33 2008 @@ -1229,7 +1229,7 @@ * exp+4*ndigits and exp-4*ndigits are within the range of a long. */ - s = PyUnicode_AsStringAndSize(arg, &length); + s = _PyUnicode_AsStringAndSize(arg, &length); if (s == NULL) return NULL; s_end = s + length; @@ -1597,7 +1597,7 @@ Py_TYPE(arg)->tp_name); return NULL; } - s = PyUnicode_AsString(arg); + s = _PyUnicode_AsString(arg); if (s == NULL) return NULL; if (strcmp(s, "double") == 0) { Modified: python/branches/py3k/Objects/funcobject.c ============================================================================== --- python/branches/py3k/Objects/funcobject.c (original) +++ python/branches/py3k/Objects/funcobject.c Thu Aug 7 20:54:33 2008 @@ -297,7 +297,7 @@ PyErr_Format(PyExc_ValueError, "%s() requires a code object with %zd free vars," " not %zd", - PyUnicode_AsString(op->func_name), + _PyUnicode_AsString(op->func_name), nclosure, nfree); return -1; } Modified: python/branches/py3k/Objects/moduleobject.c ============================================================================== --- python/branches/py3k/Objects/moduleobject.c (original) +++ python/branches/py3k/Objects/moduleobject.c Thu Aug 7 20:54:33 2008 @@ -187,7 +187,7 @@ PyErr_SetString(PyExc_SystemError, "nameless module"); return NULL; } - return PyUnicode_AsString(nameobj); + return _PyUnicode_AsString(nameobj); } const char * @@ -207,7 +207,7 @@ PyErr_SetString(PyExc_SystemError, "module filename missing"); return NULL; } - return PyUnicode_AsString(fileobj); + return _PyUnicode_AsString(fileobj); } PyModuleDef* @@ -252,7 +252,7 @@ pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - const char *s = PyUnicode_AsString(key); + const char *s = _PyUnicode_AsString(key); if (s[0] == '_' && s[1] != '_') { if (Py_VerboseFlag > 1) PySys_WriteStderr("# clear[1] %s\n", s); @@ -265,7 +265,7 @@ pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - const char *s = PyUnicode_AsString(key); + const char *s = _PyUnicode_AsString(key); if (s[0] != '_' || strcmp(s, "__builtins__") != 0) { if (Py_VerboseFlag > 1) PySys_WriteStderr("# clear[2] %s\n", s); Modified: python/branches/py3k/Objects/object.c ============================================================================== --- python/branches/py3k/Objects/object.c (original) +++ python/branches/py3k/Objects/object.c Thu Aug 7 20:54:33 2008 @@ -856,7 +856,7 @@ if (tp->tp_getattro != NULL) return (*tp->tp_getattro)(v, name); if (tp->tp_getattr != NULL) - return (*tp->tp_getattr)(v, PyUnicode_AsString(name)); + return (*tp->tp_getattr)(v, _PyUnicode_AsString(name)); PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%U'", tp->tp_name, name); @@ -896,7 +896,7 @@ return err; } if (tp->tp_setattr != NULL) { - err = (*tp->tp_setattr)(v, PyUnicode_AsString(name), value); + err = (*tp->tp_setattr)(v, _PyUnicode_AsString(name), value); Py_DECREF(name); return err; } @@ -1062,7 +1062,7 @@ PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", - tp->tp_name, PyUnicode_AsString(name)); + tp->tp_name, _PyUnicode_AsString(name)); done: Py_DECREF(name); return res; Modified: python/branches/py3k/Objects/setobject.c ============================================================================== --- python/branches/py3k/Objects/setobject.c (original) +++ python/branches/py3k/Objects/setobject.c Thu Aug 7 20:54:33 2008 @@ -2390,7 +2390,7 @@ /* Exercise direct iteration */ i = 0, count = 0; while (_PySet_NextEntry((PyObject *)dup, &i, &x, &hash)) { - s = PyUnicode_AsString(x); + s = _PyUnicode_AsString(x); assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c')); count++; } Modified: python/branches/py3k/Objects/structseq.c ============================================================================== --- python/branches/py3k/Objects/structseq.c (original) +++ python/branches/py3k/Objects/structseq.c Thu Aug 7 20:54:33 2008 @@ -270,7 +270,7 @@ Py_DECREF(tup); return NULL; } - crepr = PyUnicode_AsString(repr); + crepr = _PyUnicode_AsString(repr); if (crepr == NULL) { Py_DECREF(tup); Py_DECREF(repr); Modified: python/branches/py3k/Objects/typeobject.c ============================================================================== --- python/branches/py3k/Objects/typeobject.c (original) +++ python/branches/py3k/Objects/typeobject.c Thu Aug 7 20:54:33 2008 @@ -258,7 +258,7 @@ } Py_DECREF(tmp); - tp_name = PyUnicode_AsString(value); + tp_name = _PyUnicode_AsString(value); if (tp_name == NULL) return -1; @@ -1255,7 +1255,7 @@ o = class_name(o); PyErr_Format(PyExc_TypeError, "duplicate base class %.400s", - o ? PyUnicode_AsString(o) : "?"); + o ? _PyUnicode_AsString(o) : "?"); Py_XDECREF(o); return -1; } @@ -1301,7 +1301,7 @@ while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) { PyObject *name = class_name(k); off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s", - name ? PyUnicode_AsString(name) : "?"); + name ? _PyUnicode_AsString(name) : "?"); Py_XDECREF(name); if (--n && (size_t)(off+1) < sizeof(buf)) { buf[off++] = ','; @@ -2094,7 +2094,7 @@ type->tp_as_sequence = &et->as_sequence; type->tp_as_mapping = &et->as_mapping; type->tp_as_buffer = &et->as_buffer; - type->tp_name = PyUnicode_AsString(name); + type->tp_name = _PyUnicode_AsString(name); if (!type->tp_name) { Py_DECREF(type); return NULL; @@ -2136,7 +2136,7 @@ char *doc_str; char *tp_doc; - doc_str = PyUnicode_AsStringAndSize(doc, &len); + doc_str = _PyUnicode_AsStringAndSize(doc, &len); if (doc_str == NULL) { Py_DECREF(type); return NULL; @@ -2175,7 +2175,7 @@ slotoffset = base->tp_basicsize; if (slots != NULL) { for (i = 0; i < nslots; i++, mp++) { - mp->name = PyUnicode_AsString( + mp->name = _PyUnicode_AsString( PyTuple_GET_ITEM(slots, i)); mp->type = T_OBJECT_EX; mp->offset = slotoffset; Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Thu Aug 7 20:54:33 2008 @@ -1452,7 +1452,7 @@ } char* -PyUnicode_AsStringAndSize(PyObject *unicode, Py_ssize_t *psize) +_PyUnicode_AsStringAndSize(PyObject *unicode, Py_ssize_t *psize) { PyObject *bytes; if (!PyUnicode_Check(unicode)) { @@ -1468,9 +1468,9 @@ } char* -PyUnicode_AsString(PyObject *unicode) +_PyUnicode_AsString(PyObject *unicode) { - return PyUnicode_AsStringAndSize(unicode, NULL); + return _PyUnicode_AsStringAndSize(unicode, NULL); } Py_UNICODE *PyUnicode_AsUnicode(PyObject *unicode) Modified: python/branches/py3k/Objects/weakrefobject.c ============================================================================== --- python/branches/py3k/Objects/weakrefobject.c (original) +++ python/branches/py3k/Objects/weakrefobject.c Thu Aug 7 20:54:33 2008 @@ -167,7 +167,7 @@ if (nameobj == NULL) PyErr_Clear(); else if (PyUnicode_Check(nameobj)) - name = PyUnicode_AsString(nameobj); + name = _PyUnicode_AsString(nameobj); PyOS_snprintf(buffer, sizeof(buffer), name ? "" : "", Modified: python/branches/py3k/Parser/tokenizer.c ============================================================================== --- python/branches/py3k/Parser/tokenizer.c (original) +++ python/branches/py3k/Parser/tokenizer.c Thu Aug 7 20:54:33 2008 @@ -391,7 +391,7 @@ } if (PyUnicode_CheckExact(bufobj)) { - buf = PyUnicode_AsStringAndSize(bufobj, &buflen); + buf = _PyUnicode_AsStringAndSize(bufobj, &buflen); if (buf == NULL) { goto error; } Modified: python/branches/py3k/Python/_warnings.c ============================================================================== --- python/branches/py3k/Python/_warnings.c (original) +++ python/branches/py3k/Python/_warnings.c Thu Aug 7 20:54:33 2008 @@ -132,7 +132,7 @@ return NULL; if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) - return PyUnicode_AsString(action); + return _PyUnicode_AsString(action); } m = PyImport_ImportModule(MODULE_NAME); @@ -144,7 +144,7 @@ return NULL; action = PyDict_GetItemString(d, DEFAULT_ACTION_NAME); if (action != NULL) - return PyUnicode_AsString(action); + return _PyUnicode_AsString(action); PyErr_SetString(PyExc_ValueError, MODULE_NAME "." DEFAULT_ACTION_NAME " not found"); @@ -186,7 +186,7 @@ else if (rc == 0) return PyUnicode_FromString(""); - mod_str = PyUnicode_AsString(filename); + mod_str = _PyUnicode_AsString(filename); if (mod_str == NULL) return NULL; len = PyUnicode_GetSize(filename); @@ -257,7 +257,7 @@ /* Print " source_line\n" */ if (sourceline) { - char *source_line_str = PyUnicode_AsString(sourceline); + char *source_line_str = _PyUnicode_AsString(sourceline); while (*source_line_str == ' ' || *source_line_str == '\t' || *source_line_str == '\014') source_line_str++; @@ -266,7 +266,7 @@ PyFile_WriteString("\n", f_stderr); } else - _Py_DisplaySourceLine(f_stderr, PyUnicode_AsString(filename), + _Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename), lineno, 2); PyErr_Clear(); } @@ -367,7 +367,7 @@ const char *err_str = "???"; if (to_str != NULL) - err_str = PyUnicode_AsString(to_str); + err_str = _PyUnicode_AsString(to_str); PyErr_Format(PyExc_RuntimeError, "Unrecognized action (%s) in warnings.filters:\n %s", action, err_str); @@ -388,7 +388,7 @@ else { const char *msg = "functions overriding warnings.showwarning() " "must support the 'line' argument"; - const char *text_char = PyUnicode_AsString(text); + const char *text_char = _PyUnicode_AsString(text); if (strcmp(msg, text_char) == 0) { /* Prevent infinite recursion by using built-in implementation @@ -503,7 +503,7 @@ *filename = PyDict_GetItemString(globals, "__file__"); if (*filename != NULL) { Py_ssize_t len = PyUnicode_GetSize(*filename); - const char *file_str = PyUnicode_AsString(*filename); + const char *file_str = _PyUnicode_AsString(*filename); if (file_str == NULL || (len < 0 && PyErr_Occurred())) goto handle_error; @@ -523,7 +523,7 @@ Py_INCREF(*filename); } else { - const char *module_str = PyUnicode_AsString(*module); + const char *module_str = _PyUnicode_AsString(*module); if (module_str && strcmp(module_str, "__main__") == 0) { PyObject *argv = PySys_GetObject("argv"); if (argv != NULL && PyList_Size(argv) > 0) { Modified: python/branches/py3k/Python/ast.c ============================================================================== --- python/branches/py3k/Python/ast.c (original) +++ python/branches/py3k/Python/ast.c Thu Aug 7 20:54:33 2008 @@ -1324,7 +1324,7 @@ if (errstr) { char *s = ""; char buf[128]; - s = PyUnicode_AsString(errstr); + s = _PyUnicode_AsString(errstr); PyOS_snprintf(buf, sizeof(buf), "(unicode error) %s", s); ast_error(n, buf); } else { Modified: python/branches/py3k/Python/bltinmodule.c ============================================================================== --- python/branches/py3k/Python/bltinmodule.c (original) +++ python/branches/py3k/Python/bltinmodule.c Thu Aug 7 20:54:33 2008 @@ -1606,7 +1606,7 @@ Py_DECREF(stdin_encoding); return NULL; } - prompt = PyUnicode_AsString(po); + prompt = _PyUnicode_AsString(po); if (prompt == NULL) { Py_DECREF(stdin_encoding); Py_DECREF(po); @@ -1639,7 +1639,7 @@ else { result = PyUnicode_Decode (s, len-1, - PyUnicode_AsString(stdin_encoding), + _PyUnicode_AsString(stdin_encoding), NULL); } } Modified: python/branches/py3k/Python/ceval.c ============================================================================== --- python/branches/py3k/Python/ceval.c (original) +++ python/branches/py3k/Python/ceval.c Thu Aug 7 20:54:33 2008 @@ -859,7 +859,7 @@ lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; #endif #if defined(Py_DEBUG) || defined(LLTRACE) - filename = PyUnicode_AsString(co->co_filename); + filename = _PyUnicode_AsString(co->co_filename); #endif why = WHY_NOT; @@ -3291,7 +3291,7 @@ if (PyMethod_Check(func)) return PyEval_GetFuncName(PyMethod_GET_FUNCTION(func)); else if (PyFunction_Check(func)) - return PyUnicode_AsString(((PyFunctionObject*)func)->func_name); + return _PyUnicode_AsString(((PyFunctionObject*)func)->func_name); else if (PyCFunction_Check(func)) return ((PyCFunctionObject*)func)->m_ml->ml_name; else @@ -3527,7 +3527,7 @@ "for keyword argument '%.200s'", PyEval_GetFuncName(func), PyEval_GetFuncDesc(func), - PyUnicode_AsString(key)); + _PyUnicode_AsString(key)); Py_DECREF(key); Py_DECREF(value); Py_DECREF(kwdict); @@ -3874,7 +3874,7 @@ if (!obj) return; - obj_str = PyUnicode_AsString(obj); + obj_str = _PyUnicode_AsString(obj); if (!obj_str) return; Modified: python/branches/py3k/Python/compile.c ============================================================================== --- python/branches/py3k/Python/compile.c (original) +++ python/branches/py3k/Python/compile.c Thu Aug 7 20:54:33 2008 @@ -1300,7 +1300,7 @@ PyObject_REPR(name), PyBytes_AS_STRING(c->u->u_name), reftype, arg, - PyUnicode_AsString(co->co_name), + _PyUnicode_AsString(co->co_name), PyObject_REPR(co->co_freevars)); Py_FatalError("compiler_make_closure()"); } Modified: python/branches/py3k/Python/errors.c ============================================================================== --- python/branches/py3k/Python/errors.c (original) +++ python/branches/py3k/Python/errors.c Thu Aug 7 20:54:33 2008 @@ -709,7 +709,7 @@ if (moduleName == NULL) PyFile_WriteString("", f); else { - char* modstr = PyUnicode_AsString(moduleName); + char* modstr = _PyUnicode_AsString(moduleName); if (modstr && strcmp(modstr, "builtins") != 0) { Modified: python/branches/py3k/Python/future.c ============================================================================== --- python/branches/py3k/Python/future.c (original) +++ python/branches/py3k/Python/future.c Thu Aug 7 20:54:33 2008 @@ -20,7 +20,7 @@ names = s->v.ImportFrom.names; for (i = 0; i < asdl_seq_LEN(names); i++) { alias_ty name = (alias_ty)asdl_seq_GET(names, i); - const char *feature = PyUnicode_AsString(name->name); + const char *feature = _PyUnicode_AsString(name->name); if (!feature) return 0; if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) { Modified: python/branches/py3k/Python/getargs.c ============================================================================== --- python/branches/py3k/Python/getargs.c (original) +++ python/branches/py3k/Python/getargs.c Thu Aug 7 20:54:33 2008 @@ -1537,7 +1537,7 @@ "keywords must be strings"); return cleanreturn(0, freelist); } - ks = PyUnicode_AsString(key); + ks = _PyUnicode_AsString(key); for (i = 0; i < len; i++) { if (!strcmp(ks, kwlist[i])) { match = 1; Modified: python/branches/py3k/Python/import.c ============================================================================== --- python/branches/py3k/Python/import.c (original) +++ python/branches/py3k/Python/import.c Thu Aug 7 20:54:33 2008 @@ -470,7 +470,7 @@ if (value->ob_refcnt != 1) continue; if (PyUnicode_Check(key) && PyModule_Check(value)) { - name = PyUnicode_AsString(key); + name = _PyUnicode_AsString(key); if (strcmp(name, "builtins") == 0) continue; if (strcmp(name, "sys") == 0) @@ -489,7 +489,7 @@ pos = 0; while (PyDict_Next(modules, &pos, &key, &value)) { if (PyUnicode_Check(key) && PyModule_Check(value)) { - name = PyUnicode_AsString(key); + name = _PyUnicode_AsString(key); if (strcmp(name, "builtins") == 0) continue; if (strcmp(name, "sys") == 0) @@ -1296,7 +1296,7 @@ if (path != NULL && PyUnicode_Check(path)) { /* The only type of submodule allowed inside a "frozen" package are other frozen modules or packages. */ - char *p = PyUnicode_AsString(path); + char *p = _PyUnicode_AsString(path); if (strlen(p) + 1 + strlen(name) >= (size_t)buflen) { PyErr_SetString(PyExc_ImportError, "full frozen module name too long"); @@ -2197,7 +2197,7 @@ "__package__ set to non-string"); return NULL; } - pkgname_str = PyUnicode_AsStringAndSize(pkgname, &len); + pkgname_str = _PyUnicode_AsStringAndSize(pkgname, &len); if (len == 0) { if (level > 0) { PyErr_SetString(PyExc_ValueError, @@ -2225,7 +2225,7 @@ Py_ssize_t len; int error; - modname_str = PyUnicode_AsStringAndSize(modname, &len); + modname_str = _PyUnicode_AsStringAndSize(modname, &len); if (len > MAXPATHLEN) { PyErr_SetString(PyExc_ValueError, "Module name too long"); @@ -2240,7 +2240,7 @@ } } else { /* Normal module, so work out the package name if any */ - char *start = PyUnicode_AsString(modname); + char *start = _PyUnicode_AsString(modname); char *lastdot = strrchr(start, '.'); size_t len; int error; @@ -2635,7 +2635,7 @@ if (parent == NULL) { PyErr_Format(PyExc_ImportError, "reload(): parent %.200s not in sys.modules", - PyUnicode_AsString(parentname)); + _PyUnicode_AsString(parentname)); Py_DECREF(parentname); imp_modules_reloading_clear(); return NULL; Modified: python/branches/py3k/Python/peephole.c ============================================================================== --- python/branches/py3k/Python/peephole.c (original) +++ python/branches/py3k/Python/peephole.c Thu Aug 7 20:54:33 2008 @@ -407,7 +407,7 @@ case LOAD_NAME: case LOAD_GLOBAL: j = GETARG(codestr, i); - name = PyUnicode_AsString(PyTuple_GET_ITEM(names, j)); + name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j)); h = load_global(codestr, i, name, consts); if (h < 0) goto exitUnchanged; Modified: python/branches/py3k/Python/pythonrun.c ============================================================================== --- python/branches/py3k/Python/pythonrun.c (original) +++ python/branches/py3k/Python/pythonrun.c Thu Aug 7 20:54:33 2008 @@ -803,7 +803,7 @@ encoding_attr = PyObject_GetAttrString(std, "encoding"); if (encoding_attr != NULL) { const char * encoding; - encoding = PyUnicode_AsString(encoding_attr); + encoding = _PyUnicode_AsString(encoding_attr); if (encoding != NULL) { _PyCodec_Lookup(encoding); } @@ -909,7 +909,7 @@ oenc = PyObject_GetAttrString(v, "encoding"); if (!oenc) return -1; - enc = PyUnicode_AsString(oenc); + enc = _PyUnicode_AsString(oenc); } v = PySys_GetObject("ps1"); if (v != NULL) { @@ -917,7 +917,7 @@ if (v == NULL) PyErr_Clear(); else if (PyUnicode_Check(v)) - ps1 = PyUnicode_AsString(v); + ps1 = _PyUnicode_AsString(v); } w = PySys_GetObject("ps2"); if (w != NULL) { @@ -925,7 +925,7 @@ if (w == NULL) PyErr_Clear(); else if (PyUnicode_Check(w)) - ps2 = PyUnicode_AsString(w); + ps2 = _PyUnicode_AsString(w); } arena = PyArena_New(); if (arena == NULL) { @@ -1101,7 +1101,7 @@ goto finally; if (v == Py_None) *filename = NULL; - else if (! (*filename = PyUnicode_AsString(v))) + else if (! (*filename = _PyUnicode_AsString(v))) goto finally; Py_DECREF(v); @@ -1134,7 +1134,7 @@ if (v == Py_None) *text = NULL; else if (!PyUnicode_Check(v) || - !(*text = PyUnicode_AsString(v))) + !(*text = _PyUnicode_AsString(v))) goto finally; Py_DECREF(v); return 1; @@ -1357,7 +1357,7 @@ err = PyFile_WriteString("", f); } else { - char* modstr = PyUnicode_AsString(moduleName); + char* modstr = _PyUnicode_AsString(moduleName); if (modstr && strcmp(modstr, "builtins")) { err = PyFile_WriteString(modstr, f); @@ -1806,7 +1806,7 @@ if (value != NULL) { u = PyObject_Str(value); if (u != NULL) { - msg = PyUnicode_AsString(u); + msg = _PyUnicode_AsString(u); } } if (msg == NULL) Modified: python/branches/py3k/Python/structmember.c ============================================================================== --- python/branches/py3k/Python/structmember.c (original) +++ python/branches/py3k/Python/structmember.c Thu Aug 7 20:54:33 2008 @@ -247,7 +247,7 @@ PyErr_BadArgument(); return -1; } - string = PyUnicode_AsStringAndSize(v, &len); + string = _PyUnicode_AsStringAndSize(v, &len); if (len != 1) { PyErr_BadArgument(); return -1; Modified: python/branches/py3k/Python/symtable.c ============================================================================== --- python/branches/py3k/Python/symtable.c (original) +++ python/branches/py3k/Python/symtable.c Thu Aug 7 20:54:33 2008 @@ -1142,7 +1142,7 @@ asdl_seq *seq = s->v.Global.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = PyUnicode_AsString(name); + char *c_name = _PyUnicode_AsString(name); long cur = symtable_lookup(st, name); if (cur < 0) return 0; @@ -1169,7 +1169,7 @@ asdl_seq *seq = s->v.Nonlocal.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = PyUnicode_AsString(name); + char *c_name = _PyUnicode_AsString(name); long cur = symtable_lookup(st, name); if (cur < 0) return 0; Modified: python/branches/py3k/Python/traceback.c ============================================================================== --- python/branches/py3k/Python/traceback.c (original) +++ python/branches/py3k/Python/traceback.c Thu Aug 7 20:54:33 2008 @@ -257,10 +257,10 @@ while (tb != NULL && err == 0) { if (depth <= limit) { err = tb_displayline(f, - PyUnicode_AsString( + _PyUnicode_AsString( tb->tb_frame->f_code->co_filename), tb->tb_lineno, - PyUnicode_AsString(tb->tb_frame->f_code->co_name)); + _PyUnicode_AsString(tb->tb_frame->f_code->co_name)); } depth--; tb = tb->tb_next; From python-3000-checkins at python.org Thu Aug 7 23:50:42 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Thu, 7 Aug 2008 23:50:42 +0200 (CEST) Subject: [Python-3000-checkins] r65583 - in python/branches/py3k: Misc/NEWS Objects/unicodeobject.c Message-ID: <20080807215042.156051E400D@bag.python.org> Author: antoine.pitrou Date: Thu Aug 7 23:50:41 2008 New Revision: 65583 Log: issue #3460: PyUnicode_Join() implementation can be simplified in py3k Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/unicodeobject.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Aug 7 23:50:41 2008 @@ -22,6 +22,10 @@ If you need to access the UTF-8 representation of a Unicode object as bytes string, please use PyUnicode_AsUTF8String() instead. +- Issue #3460: PyUnicode_Join() implementation is 10% to 80% faster thanks + to Python 3.0's stricter semantics which allow to avoid successive + reallocations of the result string (this also affects str.join()). + Library ------- Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Thu Aug 7 23:50:41 2008 @@ -5619,78 +5619,70 @@ PyObject * PyUnicode_Join(PyObject *separator, PyObject *seq) { - PyObject *internal_separator = NULL; const Py_UNICODE blank = ' '; const Py_UNICODE *sep = ␣ Py_ssize_t seplen = 1; PyUnicodeObject *res = NULL; /* the result */ - Py_ssize_t res_alloc = 100; /* # allocated bytes for string in res */ - Py_ssize_t res_used; /* # used bytes */ Py_UNICODE *res_p; /* pointer to free byte in res's string area */ PyObject *fseq; /* PySequence_Fast(seq) */ - Py_ssize_t seqlen; /* len(fseq) -- number of items in sequence */ + Py_ssize_t seqlen; /* len(fseq) -- number of items in sequence */ + PyObject **items; PyObject *item; - Py_ssize_t i; + Py_ssize_t sz, i; fseq = PySequence_Fast(seq, ""); if (fseq == NULL) { return NULL; } - /* Grrrr. A codec may be invoked to convert str objects to - * Unicode, and so it's possible to call back into Python code - * during PyUnicode_FromObject(), and so it's possible for a sick - * codec to change the size of fseq (if seq is a list). Therefore - * we have to keep refetching the size -- can't assume seqlen - * is invariant. + /* NOTE: the following code can't call back into Python code, + * so we are sure that fseq won't be mutated. */ + seqlen = PySequence_Fast_GET_SIZE(fseq); /* If empty sequence, return u"". */ if (seqlen == 0) { res = _PyUnicode_New(0); /* empty sequence; return u"" */ goto Done; } + items = PySequence_Fast_ITEMS(fseq); /* If singleton sequence with an exact Unicode, return that. */ if (seqlen == 1) { - item = PySequence_Fast_GET_ITEM(fseq, 0); + item = items[0]; if (PyUnicode_CheckExact(item)) { Py_INCREF(item); res = (PyUnicodeObject *)item; goto Done; } } - - /* At least two items to join, or one that isn't exact Unicode. */ - if (seqlen > 1) { - /* Set up sep and seplen -- they're needed. */ - if (separator == NULL) { - sep = ␣ - seplen = 1; - } - else { - internal_separator = PyUnicode_FromObject(separator); - if (internal_separator == NULL) - goto onError; - sep = PyUnicode_AS_UNICODE(internal_separator); - seplen = PyUnicode_GET_SIZE(internal_separator); - /* In case PyUnicode_FromObject() mutated seq. */ - seqlen = PySequence_Fast_GET_SIZE(fseq); + else { + /* Set up sep and seplen */ + if (separator == NULL) { + sep = ␣ + seplen = 1; + } + else { + if (!PyUnicode_Check(separator)) { + PyErr_Format(PyExc_TypeError, + "separator: expected str instance," + " %.80s found", + Py_TYPE(separator)->tp_name); + goto onError; + } + sep = PyUnicode_AS_UNICODE(separator); + seplen = PyUnicode_GET_SIZE(separator); } } - /* Get space. */ - res = _PyUnicode_New(res_alloc); - if (res == NULL) - goto onError; - res_p = PyUnicode_AS_UNICODE(res); - res_used = 0; - - for (i = 0; i < seqlen; ++i) { - Py_ssize_t itemlen; - Py_ssize_t new_res_used; - - item = PySequence_Fast_GET_ITEM(fseq, i); - /* Convert item to Unicode. */ + /* There are at least two things to join, or else we have a subclass + * of str in the sequence. + * Do a pre-pass to figure out the total amount of space we'll + * need (sz), and see whether all argument are strings. + */ + sz = 0; + for (i = 0; i < seqlen; i++) { + const Py_ssize_t old_sz = sz; + item = items[i]; if (!PyUnicode_Check(item)) { PyErr_Format(PyExc_TypeError, "sequence item %zd: expected str instance," @@ -5698,68 +5690,40 @@ i, Py_TYPE(item)->tp_name); goto onError; } - item = PyUnicode_FromObject(item); - if (item == NULL) - goto onError; - /* We own a reference to item from here on. */ - - /* In case PyUnicode_FromObject() mutated seq. */ - seqlen = PySequence_Fast_GET_SIZE(fseq); + sz += PyUnicode_GET_SIZE(item); + if (i != 0) + sz += seplen; + if (sz < old_sz || sz > PY_SSIZE_T_MAX) { + PyErr_SetString(PyExc_OverflowError, + "join() result is too long for a Python string"); + goto onError; + } + } - /* Make sure we have enough space for the separator and the item. */ - itemlen = PyUnicode_GET_SIZE(item); - new_res_used = res_used + itemlen; - if (new_res_used < 0) - goto Overflow; - if (i < seqlen - 1) { - new_res_used += seplen; - if (new_res_used < 0) - goto Overflow; - } - if (new_res_used > res_alloc) { - /* double allocated size until it's big enough */ - do { - res_alloc += res_alloc; - if (res_alloc <= 0) - goto Overflow; - } while (new_res_used > res_alloc); - if (_PyUnicode_Resize(&res, res_alloc) < 0) { - Py_DECREF(item); - goto onError; - } - res_p = PyUnicode_AS_UNICODE(res) + res_used; - } + res = _PyUnicode_New(sz); + if (res == NULL) + goto onError; + /* Catenate everything. */ + res_p = PyUnicode_AS_UNICODE(res); + for (i = 0; i < seqlen; ++i) { + Py_ssize_t itemlen; + item = items[i]; + itemlen = PyUnicode_GET_SIZE(item); /* Copy item, and maybe the separator. */ - Py_UNICODE_COPY(res_p, PyUnicode_AS_UNICODE(item), itemlen); - res_p += itemlen; - if (i < seqlen - 1) { + if (i) { Py_UNICODE_COPY(res_p, sep, seplen); res_p += seplen; } - Py_DECREF(item); - res_used = new_res_used; + Py_UNICODE_COPY(res_p, PyUnicode_AS_UNICODE(item), itemlen); + res_p += itemlen; } - /* Shrink res to match the used area; this probably can't fail, - * but it's cheap to check. - */ - if (_PyUnicode_Resize(&res, res_used) < 0) - goto onError; - Done: - Py_XDECREF(internal_separator); Py_DECREF(fseq); return (PyObject *)res; - Overflow: - PyErr_SetString(PyExc_OverflowError, - "join() result is too long for a Python string"); - Py_DECREF(item); - /* fall through */ - onError: - Py_XDECREF(internal_separator); Py_DECREF(fseq); Py_XDECREF(res); return NULL; From python-3000-checkins at python.org Fri Aug 8 06:16:58 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Fri, 8 Aug 2008 06:16:58 +0200 (CEST) Subject: [Python-3000-checkins] r65585 - python/branches/py3k Message-ID: <20080808041658.E0B7D1E400D@bag.python.org> Author: brett.cannon Date: Fri Aug 8 06:16:58 2008 New Revision: 65585 Log: Blocked revisions 65584 via svnmerge ........ r65584 | brett.cannon | 2008-08-07 21:15:53 -0700 (Thu, 07 Aug 2008) | 3 lines Change the warning emitted for using the buffer() object; memoryview() in 3.0 is not an equivalent. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 8 06:20:32 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Fri, 8 Aug 2008 06:20:32 +0200 (CEST) Subject: [Python-3000-checkins] r65587 - python/branches/py3k Message-ID: <20080808042032.925691E400D@bag.python.org> Author: brett.cannon Date: Fri Aug 8 06:20:32 2008 New Revision: 65587 Log: Blocked revisions 65586 via svnmerge ........ r65586 | brett.cannon | 2008-08-07 21:19:32 -0700 (Thu, 07 Aug 2008) | 5 lines Remove warnings generated for the suprocess module when run under -3. Required commenting out True/False compatbility stuff, remove a use of apply(), and remove a use of buffer() (just pulled the solution used in 3.0 which is direct slicing). ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 8 06:28:30 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Fri, 8 Aug 2008 06:28:30 +0200 (CEST) Subject: [Python-3000-checkins] r65589 - python/branches/py3k Message-ID: <20080808042830.76C871E400D@bag.python.org> Author: brett.cannon Date: Fri Aug 8 06:28:30 2008 New Revision: 65589 Log: Blocked revisions 65588 via svnmerge ........ r65588 | brett.cannon | 2008-08-07 21:27:28 -0700 (Thu, 07 Aug 2008) | 3 lines Remove buffer() usage in the socket module by just slicing directly on the object. This removes all warnings for the module caused by running under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 8 08:44:14 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Fri, 8 Aug 2008 08:44:14 +0200 (CEST) Subject: [Python-3000-checkins] r65592 - python/branches/py3k/Doc/tutorial/datastructures.rst Message-ID: <20080808064414.E8C231E400D@bag.python.org> Author: georg.brandl Date: Fri Aug 8 08:44:14 2008 New Revision: 65592 Log: #3522: zip() returns an iterator. Modified: python/branches/py3k/Doc/tutorial/datastructures.rst Modified: python/branches/py3k/Doc/tutorial/datastructures.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/datastructures.rst (original) +++ python/branches/py3k/Doc/tutorial/datastructures.rst Fri Aug 8 08:44:14 2008 @@ -257,7 +257,7 @@ In real world, you should prefer builtin functions to complex flow statements. The :func:`zip` function would do a great job for this use case:: - >>> zip(*mat) + >>> list(zip(*mat)) [(1, 4, 7), (2, 5, 8), (3, 6, 9)] See :ref:`tut-unpacking-arguments` for details on the asterisk in this line. From python-3000-checkins at python.org Fri Aug 8 08:45:01 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Fri, 8 Aug 2008 08:45:01 +0200 (CEST) Subject: [Python-3000-checkins] r65593 - python/branches/py3k/Doc/tutorial/inputoutput.rst Message-ID: <20080808064501.811B11E400D@bag.python.org> Author: georg.brandl Date: Fri Aug 8 08:45:01 2008 New Revision: 65593 Log: #3523: no backquotes any more. Modified: python/branches/py3k/Doc/tutorial/inputoutput.rst Modified: python/branches/py3k/Doc/tutorial/inputoutput.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/inputoutput.rst (original) +++ python/branches/py3k/Doc/tutorial/inputoutput.rst Fri Aug 8 08:45:01 2008 @@ -34,9 +34,7 @@ One question remains, of course: how do you convert values to strings? Luckily, Python has ways to convert any value to a string: pass it to the :func:`repr` -or :func:`str` functions. Reverse quotes (``````) are equivalent to -:func:`repr`, but they are no longer used in modern Python code and are removed -in future versions of the language. +or :func:`str` functions. The :func:`str` function is meant to return representations of values which are fairly human-readable, while :func:`repr` is meant to generate representations @@ -71,9 +69,6 @@ >>> # The argument to repr() may be any Python object: ... repr((x, y, ('spam', 'eggs'))) "(32.5, 40000, ('spam', 'eggs'))" - >>> # reverse quotes are convenient in interactive sessions: - ... `x, y, ('spam', 'eggs')` - "(32.5, 40000, ('spam', 'eggs'))" Here are two ways to write a table of squares and cubes:: From python-3000-checkins at python.org Fri Aug 8 08:50:57 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Fri, 8 Aug 2008 08:50:57 +0200 (CEST) Subject: [Python-3000-checkins] r65594 - in python/branches/py3k/Doc/tutorial: classes.rst errors.rst Message-ID: <20080808065057.26AAC1E400D@bag.python.org> Author: georg.brandl Date: Fri Aug 8 08:50:56 2008 New Revision: 65594 Log: #3525: 3.0 exception changes in tutorial. Modified: python/branches/py3k/Doc/tutorial/classes.rst python/branches/py3k/Doc/tutorial/errors.rst Modified: python/branches/py3k/Doc/tutorial/classes.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/classes.rst (original) +++ python/branches/py3k/Doc/tutorial/classes.rst Fri Aug 8 08:50:56 2008 @@ -671,7 +671,7 @@ listing a derived class is not compatible with a base class). For example, the following code will print B, C, D in that order:: - class B: + class B(Exception): pass class C(B): pass Modified: python/branches/py3k/Doc/tutorial/errors.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/errors.rst (original) +++ python/branches/py3k/Doc/tutorial/errors.rst Fri Aug 8 08:50:56 2008 @@ -1,4 +1,4 @@ -. _tut-errors: +.. _tut-errors: ********************* Errors and Exceptions @@ -131,8 +131,8 @@ f = open('myfile.txt') s = f.readline() i = int(s.strip()) - except IOError as (errno, strerror): - print("I/O error({0}): {1}".format(errno, strerror)) + except IOError as err: + print("I/O error: {0}".format(err)) except ValueError: print("Could not convert data to an integer.") except: @@ -162,25 +162,21 @@ exception's *argument*. The presence and type of the argument depend on the exception type. -The except clause may specify a variable after the exception name (or tuple). -The variable is bound to an exception instance with the arguments stored in +The except clause may specify a variable after the exception name. The +variable is bound to an exception instance with the arguments stored in ``instance.args``. For convenience, the exception instance defines -:meth:`__getitem__` and :meth:`__str__` so the arguments can be accessed or -printed directly without having to reference ``.args``. - -But use of ``.args`` is discouraged. Instead, the preferred use is to pass a -single argument to an exception (which can be a tuple if multiple arguments are -needed) and have it bound to the ``message`` attribute. One may also -instantiate an exception first before raising it and add any attributes to it as -desired. :: +:meth:`__str__` so the arguments can be printed directly without having to +reference ``.args``. One may also instantiate an exception first before +raising it and add any attributes to it as desired. :: >>> try: ... raise Exception('spam', 'eggs') ... except Exception as inst: ... print(type(inst)) # the exception instance ... print(inst.args) # arguments stored in .args - ... print(inst) # __str__ allows args to be printed directly - ... x, y = inst # __getitem__ allows args to be unpacked directly + ... print(inst) # __str__ allows args to be printed directly, + ... # but may be overridden in exception subclasses + ... x, y = inst.args # unpack args ... print('x =', x) ... print('y =', y) ... @@ -190,7 +186,7 @@ x = spam y = eggs -If an exception has an argument, it is printed as the last part ('detail') of +If an exception has arguments, they are printed as the last part ('detail') of the message for unhandled exceptions. Exception handlers don't just handle exceptions if they occur immediately in the @@ -202,10 +198,10 @@ ... >>> try: ... this_fails() - ... except ZeroDivisionError as detail: - ... print('Handling run-time error:', detail) + ... except ZeroDivisionError as err: + ... print('Handling run-time error:', err) ... - Handling run-time error: integer division or modulo by zero + Handling run-time error: int division or modulo by zero .. _tut-raising: From python-3000-checkins at python.org Fri Aug 8 09:04:39 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Fri, 8 Aug 2008 09:04:39 +0200 (CEST) Subject: [Python-3000-checkins] r65595 - python/branches/py3k/Doc/tutorial/inputoutput.rst Message-ID: <20080808070439.2613E1E400D@bag.python.org> Author: georg.brandl Date: Fri Aug 8 09:04:38 2008 New Revision: 65595 Log: #3524: fix up some old-style IO descriptions. Modified: python/branches/py3k/Doc/tutorial/inputoutput.rst Modified: python/branches/py3k/Doc/tutorial/inputoutput.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/inputoutput.rst (original) +++ python/branches/py3k/Doc/tutorial/inputoutput.rst Fri Aug 8 09:04:38 2008 @@ -228,6 +228,9 @@ :: >>> f = open('/tmp/workfile', 'w') + +.. XXX str(f) is + >>> print(f) @@ -240,19 +243,18 @@ writing. The *mode* argument is optional; ``'r'`` will be assumed if it's omitted. -On Windows and the Macintosh, ``'b'`` appended to the mode opens the file in -binary mode, so there are also modes like ``'rb'``, ``'wb'``, and ``'r+b'``. -Windows makes a distinction between text and binary files; the end-of-line -characters in text files are automatically altered slightly when data is read or -written. This behind-the-scenes modification to file data is fine for ASCII -text files, but it'll corrupt binary data like that in :file:`JPEG` or -:file:`EXE` files. Be very careful to use binary mode when reading and writing -such files. On Unix, it doesn't hurt to append a ``'b'`` to the mode, so -you can use it platform-independently for all binary files. - -This behind-the-scenes modification to file data is fine for text files, but -will corrupt binary data like that in :file:`JPEG` or :file:`EXE` files. Be -very careful to use binary mode when reading and writing such files. +Normally, files are opened in :dfn:`text mode`, that means, you read and write +strings from and to the file, which are encoded in a specific encoding (the +default being UTF-8). ``'b'`` appended to the mode opens the file in +:dfn:`binary mode`: now the data is read and written in the form of bytes +objects. This mode should be used for all files that don't contain text. + +In text mode, the default is to convert platform-specific line endings (``\n`` +on Unix, ``\r\n`` on Windows) to just ``\n`` on reading and ``\n`` back to +platform-specific line endings on writing. This behind-the-scenes modification +to file data is fine for text files, but will corrupt binary data like that in +:file:`JPEG` or :file:`EXE` files. Be very careful to use binary mode when +reading and writing such files. .. _tut-filemethods: @@ -264,12 +266,12 @@ ``f`` has already been created. To read a file's contents, call ``f.read(size)``, which reads some quantity of -data and returns it as a string. *size* is an optional numeric argument. When -*size* is omitted or negative, the entire contents of the file will be read and -returned; it's your problem if the file is twice as large as your machine's -memory. Otherwise, at most *size* bytes are read and returned. If the end of -the file has been reached, ``f.read()`` will return an empty string (``""``). -:: +data and returns it as a string or bytes object. *size* is an optional numeric +argument. When *size* is omitted or negative, the entire contents of the file +will be read and returned; it's your problem if the file is twice as large as +your machine's memory. Otherwise, at most *size* bytes are read and returned. +If the end of the file has been reached, ``f.read()`` will return an empty +string (``''``). :: >>> f.read() 'This is the entire file.\n' @@ -281,7 +283,7 @@ file if the file doesn't end in a newline. This makes the return value unambiguous; if ``f.readline()`` returns an empty string, the end of the file has been reached, while a blank line is represented by ``'\n'``, a string -containing only a single newline. :: +containing only a single newline. :: >>> f.readline() 'This is the first line of the file.\n' @@ -304,8 +306,8 @@ memory efficient, fast, and leads to simpler code:: >>> for line in f: - print(line, end='') - + ... print(line, end='') + ... This is the first line of the file. Second line of the file @@ -314,9 +316,10 @@ should not be mixed. ``f.write(string)`` writes the contents of *string* to the file, returning -``None``. :: +the number of characters written. :: >>> f.write('This is a test\n') + 15 To write something other than a string, it needs to be converted to a string first:: @@ -324,6 +327,7 @@ >>> value = ('the answer', 42) >>> s = str(value) >>> f.write(s) + 18 ``f.tell()`` returns an integer giving the file object's current position in the file, measured in bytes from the beginning of the file. To change the file @@ -334,15 +338,22 @@ the reference point. *from_what* can be omitted and defaults to 0, using the beginning of the file as the reference point. :: - >>> f = open('/tmp/workfile', 'r+') - >>> f.write('0123456789abcdef') + >>> f = open('/tmp/workfile', 'rb+') + >>> f.write(b'0123456789abcdef') + 16 >>> f.seek(5) # Go to the 6th byte in the file + 5 >>> f.read(1) - '5' + b'5' >>> f.seek(-3, 2) # Go to the 3rd byte before the end + 13 >>> f.read(1) - 'd' + b'd' +In text files (those opened without a ``b`` in the mode string), only seeks +relative to the beginning of the file are allowed (the exception being seeking +to the very file end with ``seek(0, 2)``). + When you're done with a file, call ``f.close()`` to close it and free up any system resources taken up by the open file. After calling ``f.close()``, attempts to use the file object will automatically fail. :: From musiccomposition at gmail.com Fri Aug 8 16:11:26 2008 From: musiccomposition at gmail.com (Benjamin Peterson) Date: Fri, 8 Aug 2008 08:11:26 -0600 Subject: [Python-3000-checkins] r65593 - python/branches/py3k/Doc/tutorial/inputoutput.rst In-Reply-To: <20080808064501.811B11E400D@bag.python.org> References: <20080808064501.811B11E400D@bag.python.org> Message-ID: <1afaf6160808080711l50765acag375a1a4b7c20c387@mail.gmail.com> On Fri, Aug 8, 2008 at 12:45 AM, georg.brandl wrote: > Author: georg.brandl > Date: Fri Aug 8 08:45:01 2008 > New Revision: 65593 > > Log: > #3523: no backquotes any more. You might do this modification in the trunk too, so people don't get into a habit that gets instantly quashed in 3.0. :) -- Cheers, Benjamin Peterson "There's no place like 127.0.0.1." From python-3000-checkins at python.org Sat Aug 9 14:47:13 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Sat, 9 Aug 2008 14:47:13 +0200 (CEST) Subject: [Python-3000-checkins] r65607 - python/branches/py3k Message-ID: <20080809124713.E8A731E4002@bag.python.org> Author: antoine.pitrou Date: Sat Aug 9 14:47:13 2008 New Revision: 65607 Log: Blocked revisions 65606 via svnmerge ........ r65606 | antoine.pitrou | 2008-08-09 14:43:23 +0200 (sam., 09 ao?t 2008) | 3 lines Fix slightly misleading statement in the NEWS file. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 9 21:44:23 2008 From: python-3000-checkins at python.org (skip.montanaro) Date: Sat, 9 Aug 2008 21:44:23 +0200 (CEST) Subject: [Python-3000-checkins] r65611 - in python/branches/py3k: Doc/library/csv.rst Lib/csv.py Lib/test/test_csv.py Message-ID: <20080809194423.333FD1E4002@bag.python.org> Author: skip.montanaro Date: Sat Aug 9 21:44:22 2008 New Revision: 65611 Log: Merged revisions 65605 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65605 | skip.montanaro | 2008-08-08 17:52:51 -0500 (Fri, 08 Aug 2008) | 1 line accept issue 3436 ........ Modified: python/branches/py3k/Doc/library/csv.rst python/branches/py3k/Lib/csv.py python/branches/py3k/Lib/test/test_csv.py Modified: python/branches/py3k/Doc/library/csv.rst ============================================================================== --- python/branches/py3k/Doc/library/csv.rst (original) +++ python/branches/py3k/Doc/library/csv.rst Sat Aug 9 21:44:22 2008 @@ -372,6 +372,18 @@ +DictReader objects have the following public attribute: + + +.. attribute:: csvreader.fieldnames + + If not passed as a parameter when creating the object, this attribute is + initialized upon first access or when the first record is read from the + file. + + .. versionchanged:: 2.6 + + Writer Objects -------------- Modified: python/branches/py3k/Lib/csv.py ============================================================================== --- python/branches/py3k/Lib/csv.py (original) +++ python/branches/py3k/Lib/csv.py Sat Aug 9 21:44:22 2008 @@ -68,7 +68,7 @@ class DictReader: def __init__(self, f, fieldnames=None, restkey=None, restval=None, dialect="excel", *args, **kwds): - self.fieldnames = fieldnames # list of keys for the dict + self._fieldnames = fieldnames # list of keys for the dict self.restkey = restkey # key to catch long rows self.restval = restval # default value for short rows self.reader = reader(f, dialect, *args, **kwds) @@ -78,11 +78,25 @@ def __iter__(self): return self + @property + def fieldnames(self): + if self._fieldnames is None: + try: + self._fieldnames = next(self.reader) + except StopIteration: + pass + self.line_num = self.reader.line_num + return self._fieldnames + + @fieldnames.setter + def fieldnames(self, value): + self._fieldnames = value + def __next__(self): + if self.line_num == 0: + # Used only for its side effect. + self.fieldnames row = next(self.reader) - if self.fieldnames is None: - self.fieldnames = row - row = next(self.reader) self.line_num = self.reader.line_num # unlike the basic reader, we prefer not to return blanks, Modified: python/branches/py3k/Lib/test/test_csv.py ============================================================================== --- python/branches/py3k/Lib/test/test_csv.py (original) +++ python/branches/py3k/Lib/test/test_csv.py Sat Aug 9 21:44:22 2008 @@ -544,6 +544,29 @@ fileobj.seek(0) reader = csv.DictReader(fileobj) self.assertEqual(next(reader), {"f1": '1', "f2": '2', "f3": 'abc'}) + self.assertEqual(reader.fieldnames, ["f1", "f2", "f3"]) + + # Two test cases to make sure existing ways of implicitly setting + # fieldnames continue to work. Both arise from discussion in issue3436. + def test_read_dict_fieldnames_from_file(self): + with TemporaryFile("w+") as fileobj: + fileobj.write("f1,f2,f3\r\n1,2,abc\r\n") + fileobj.seek(0) + reader = csv.DictReader(fileobj, + fieldnames=next(csv.reader(fileobj))) + self.assertEqual(reader.fieldnames, ["f1", "f2", "f3"]) + self.assertEqual(next(reader), {"f1": '1', "f2": '2', "f3": 'abc'}) + + def test_read_dict_fieldnames_chain(self): + import itertools + with TemporaryFile("w+") as fileobj: + fileobj.write("f1,f2,f3\r\n1,2,abc\r\n") + fileobj.seek(0) + reader = csv.DictReader(fileobj) + first = next(reader) + for row in itertools.chain([first], reader): + self.assertEqual(reader.fieldnames, ["f1", "f2", "f3"]) + self.assertEqual(row, {"f1": '1', "f2": '2', "f3": 'abc'}) def test_read_long(self): with TemporaryFile("w+") as fileobj: @@ -568,6 +591,7 @@ fileobj.write("f1,f2\r\n1,2,abc,4,5,6\r\n") fileobj.seek(0) reader = csv.DictReader(fileobj, restkey="_rest") + self.assertEqual(reader.fieldnames, ["f1", "f2"]) self.assertEqual(next(reader), {"f1": '1', "f2": '2', "_rest": ["abc", "4", "5", "6"]}) From python-3000-checkins at python.org Sat Aug 9 23:26:45 2008 From: python-3000-checkins at python.org (skip.montanaro) Date: Sat, 9 Aug 2008 23:26:45 +0200 (CEST) Subject: [Python-3000-checkins] r65612 - python/branches/py3k Message-ID: <20080809212645.DFB761E4014@bag.python.org> Author: skip.montanaro Date: Sat Aug 9 23:26:45 2008 New Revision: 65612 Log: prop change? Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 10 01:08:15 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sun, 10 Aug 2008 01:08:15 +0200 (CEST) Subject: [Python-3000-checkins] r65614 - python/branches/py3k Message-ID: <20080809230815.AEFFB1E4002@bag.python.org> Author: brett.cannon Date: Sun Aug 10 01:08:15 2008 New Revision: 65614 Log: Blocked revisions 65613 via svnmerge ........ r65613 | brett.cannon | 2008-08-09 16:06:16 -0700 (Sat, 09 Aug 2008) | 4 lines Suppress the warning in asynchat from using buffer() when running udner -3. Naively removing the usage causes a large number of test failures, so it was just easier to suppress the warning. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 10 01:32:13 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sun, 10 Aug 2008 01:32:13 +0200 (CEST) Subject: [Python-3000-checkins] r65616 - python/branches/py3k Message-ID: <20080809233213.99F2A1E4002@bag.python.org> Author: brett.cannon Date: Sun Aug 10 01:32:13 2008 New Revision: 65616 Log: Blocked revisions 65615 via svnmerge ........ r65615 | brett.cannon | 2008-08-09 16:30:55 -0700 (Sat, 09 Aug 2008) | 3 lines Copy reduce() to _functools so to have functools.reduce() not raise a warning from usage under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 10 01:35:24 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sun, 10 Aug 2008 01:35:24 +0200 (CEST) Subject: [Python-3000-checkins] r65618 - python/branches/py3k Message-ID: <20080809233524.C71671E4002@bag.python.org> Author: brett.cannon Date: Sun Aug 10 01:35:24 2008 New Revision: 65618 Log: Blocked revisions 65617 via svnmerge ........ r65617 | brett.cannon | 2008-08-09 16:34:11 -0700 (Sat, 09 Aug 2008) | 3 lines Use functools.reduce() in difflib instead of __builtin__.reduce() to silence warnings when running under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 10 01:40:18 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sun, 10 Aug 2008 01:40:18 +0200 (CEST) Subject: [Python-3000-checkins] r65620 - python/branches/py3k Message-ID: <20080809234018.874521E4002@bag.python.org> Author: brett.cannon Date: Sun Aug 10 01:40:18 2008 New Revision: 65620 Log: Blocked revisions 65619 via svnmerge ........ r65619 | brett.cannon | 2008-08-09 16:39:11 -0700 (Sat, 09 Aug 2008) | 3 lines Silence warnings in csv about using reduce() when run under -3 by using functools.reduce() instead. ........ Modified: python/branches/py3k/ (props changed) From musiccomposition at gmail.com Sun Aug 10 02:20:10 2008 From: musiccomposition at gmail.com (Benjamin Peterson) Date: Sat, 9 Aug 2008 18:20:10 -0600 Subject: [Python-3000-checkins] r65620 - python/branches/py3k In-Reply-To: <20080809234018.874521E4002@bag.python.org> References: <20080809234018.874521E4002@bag.python.org> Message-ID: <1afaf6160808091720h1094210bo67d6a204c1819203@mail.gmail.com> Brett, You know that you can block multiply revisions at the same time, right? It seems you are now blocking each revision separately. On Sat, Aug 9, 2008 at 5:40 PM, brett.cannon wrote: > Author: brett.cannon > Date: Sun Aug 10 01:40:18 2008 > New Revision: 65620 > > Log: > Blocked revisions 65619 via svnmerge > > ........ > r65619 | brett.cannon | 2008-08-09 16:39:11 -0700 (Sat, 09 Aug 2008) | 3 lines > > Silence warnings in csv about using reduce() when run under -3 by using > functools.reduce() instead. > ........ > > > Modified: > python/branches/py3k/ (props changed) > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > -- Cheers, Benjamin Peterson "There's no place like 127.0.0.1." From ncoghlan at gmail.com Sun Aug 10 04:21:15 2008 From: ncoghlan at gmail.com (Nick Coghlan) Date: Sun, 10 Aug 2008 12:21:15 +1000 Subject: [Python-3000-checkins] r65620 - python/branches/py3k In-Reply-To: <1afaf6160808091720h1094210bo67d6a204c1819203@mail.gmail.com> References: <20080809234018.874521E4002@bag.python.org> <1afaf6160808091720h1094210bo67d6a204c1819203@mail.gmail.com> Message-ID: <489E509B.5020408@gmail.com> Benjamin Peterson wrote: > Brett, > You know that you can block multiply revisions at the same time, > right? It seems you are now blocking each revision separately. Sometimes its useful to do one task completely (fix in 2.6, commit, block in 3.0, commit) to make sure you don't miss anything, rather than save all the block commands up to the end. This also keeps the source tree is as consistent a state as possible, so it doesn't matter if Brett gets interrupted while working on his next fix and someone does an svnmerge before he gets back to it. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org From brett at python.org Sun Aug 10 07:12:51 2008 From: brett at python.org (Brett Cannon) Date: Sat, 9 Aug 2008 22:12:51 -0700 Subject: [Python-3000-checkins] r65620 - python/branches/py3k In-Reply-To: <489E509B.5020408@gmail.com> References: <20080809234018.874521E4002@bag.python.org> <1afaf6160808091720h1094210bo67d6a204c1819203@mail.gmail.com> <489E509B.5020408@gmail.com> Message-ID: On Sat, Aug 9, 2008 at 7:21 PM, Nick Coghlan wrote: > Benjamin Peterson wrote: >> >> Brett, >> You know that you can block multiply revisions at the same time, >> right? It seems you are now blocking each revision separately. > Yes, I do, but I don't mind. It's two commands with a copy-and-paste that occurs while I am doing other stuff. > Sometimes its useful to do one task completely (fix in 2.6, commit, block in > 3.0, commit) to make sure you don't miss anything, rather than save all the > block commands up to the end. > > This also keeps the source tree is as consistent a state as possible, so it > doesn't matter if Brett gets interrupted while working on his next fix and > someone does an svnmerge before he gets back to it. > Exactly what Nick said. I treat each fix as an atomic commit that happens to span to branches in svn. That way I never forget anything. Plus I have actually been committing when someone else was doing a large merge into Py3K, so this helps prevent all of my commits from suddenly causing someone else grief. -Brett From g.brandl at gmx.net Sun Aug 10 12:14:03 2008 From: g.brandl at gmx.net (Georg Brandl) Date: Sun, 10 Aug 2008 10:14:03 +0000 Subject: [Python-3000-checkins] r65620 - python/branches/py3k In-Reply-To: References: <20080809234018.874521E4002@bag.python.org> <1afaf6160808091720h1094210bo67d6a204c1819203@mail.gmail.com> <489E509B.5020408@gmail.com> Message-ID: Brett Cannon schrieb: >> Sometimes its useful to do one task completely (fix in 2.6, commit, block in >> 3.0, commit) to make sure you don't miss anything, rather than save all the >> block commands up to the end. >> >> This also keeps the source tree is as consistent a state as possible, so it >> doesn't matter if Brett gets interrupted while working on his next fix and >> someone does an svnmerge before he gets back to it. >> > > Exactly what Nick said. I treat each fix as an atomic commit that > happens to span to branches in svn. That way I never forget anything. It's not like we're short of revision numbers. :) > Plus I have actually been committing when someone else was doing a > large merge into Py3K, so this helps prevent all of my commits from > suddenly causing someone else grief. This is always a problem whenever you merge/commit something to Py3k while a large merge is done. It could only be helped if the one doing the merge could somehow lock the branch from other updates. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out. From python-3000-checkins at python.org Sun Aug 10 13:28:17 2008 From: python-3000-checkins at python.org (robert.schuppenies) Date: Sun, 10 Aug 2008 13:28:17 +0200 (CEST) Subject: [Python-3000-checkins] r65626 - in python/branches/py3k: Lib/tkinter/__init__.py Misc/NEWS Message-ID: <20080810112817.C9F9E1E4002@bag.python.org> Author: robert.schuppenies Date: Sun Aug 10 13:28:17 2008 New Revision: 65626 Log: Merged revisions 65622 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65622 | robert.schuppenies | 2008-08-10 13:01:53 +0200 (Sun, 10 Aug 2008) | 4 lines Issue #1342811: Fix leak in Tkinter.Menu.delete. Commands associated to menu entries were not deleted. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/tkinter/__init__.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/tkinter/__init__.py ============================================================================== --- python/branches/py3k/Lib/tkinter/__init__.py (original) +++ python/branches/py3k/Lib/tkinter/__init__.py Sun Aug 10 13:28:17 2008 @@ -2651,7 +2651,18 @@ self.insert(index, 'separator', cnf or kw) def delete(self, index1, index2=None): """Delete menu items between INDEX1 and INDEX2 (not included).""" + if index2 is None: + index2 = index1 + cmds = [] + for i in range(self.index(index1), self.index(index2)+1): + if 'command' in self.entryconfig(i): + c = str(self.entrycget(i, 'command')) + if c in self._tclCommands: + cmds.append(c) self.tk.call(self._w, 'delete', index1, index2) + for c in cmds: + self.deletecommand(c) + def entrycget(self, index, option): """Return the resource value of an menu item for OPTION at INDEX.""" return self.tk.call(self._w, 'entrycget', index, '-' + option) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 10 13:28:17 2008 @@ -30,6 +30,9 @@ Library ------- +- Issue #1342811: Fix leak in Tkinter.Menu.delete. Commands associated to + menu entries were not deleted. + - Remove the TarFileCompat class from tarfile.py. - Issue #2491: os.fdopen is now almost an alias for the built-in open(), and From python-3000-checkins at python.org Sun Aug 10 14:16:45 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sun, 10 Aug 2008 14:16:45 +0200 (CEST) Subject: [Python-3000-checkins] r65627 - python/branches/py3k/Doc/tutorial/floatingpoint.rst Message-ID: <20080810121645.EE6641E4002@bag.python.org> Author: georg.brandl Date: Sun Aug 10 14:16:45 2008 New Revision: 65627 Log: Remove long integer output. Modified: python/branches/py3k/Doc/tutorial/floatingpoint.rst Modified: python/branches/py3k/Doc/tutorial/floatingpoint.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/floatingpoint.rst (original) +++ python/branches/py3k/Doc/tutorial/floatingpoint.rst Sun Aug 10 14:16:45 2008 @@ -173,24 +173,24 @@ the best value for *N* is 56:: >>> 2**52 - 4503599627370496L + 4503599627370496 >>> 2**53 - 9007199254740992L + 9007199254740992 >>> 2**56/10 - 7205759403792793L + 7205759403792794.0 That is, 56 is the only value for *N* that leaves *J* with exactly 53 bits. The best possible value for *J* is then that quotient rounded:: >>> q, r = divmod(2**56, 10) >>> r - 6L + 6 Since the remainder is more than half of 10, the best approximation is obtained by rounding up:: >>> q+1 - 7205759403792794L + 7205759403792794 Therefore the best possible approximation to 1/10 in 754 double precision is that over 2\*\*56, or :: @@ -211,7 +211,7 @@ its 30 most significant decimal digits:: >>> 7205759403792794 * 10**30 / 2**56 - 100000000000000005551115123125L + 100000000000000005551115123125 meaning that the exact number stored in the computer is approximately equal to the decimal value 0.100000000000000005551115123125. Rounding that to 17 From python-3000-checkins at python.org Mon Aug 11 17:49:04 2008 From: python-3000-checkins at python.org (nick.coghlan) Date: Mon, 11 Aug 2008 17:49:04 +0200 (CEST) Subject: [Python-3000-checkins] r65643 - python/branches/py3k Message-ID: <20080811154904.172A01E4002@bag.python.org> Author: nick.coghlan Date: Mon Aug 11 17:49:03 2008 New Revision: 65643 Log: Blocked revisions 65642 via svnmerge ........ r65642 | nick.coghlan | 2008-08-12 01:45:58 +1000 (Tue, 12 Aug 2008) | 1 line Issue 2235: Py3k warnings are now emitted for classes that will no longer inherit a__hash__ implementation from a parent class in Python 3.x. The standard library and test suite have been updated to not emit these warnings. ........ Modified: python/branches/py3k/ (props changed) From nnorwitz at gmail.com Fri Aug 8 14:40:14 2008 From: nnorwitz at gmail.com (Neal Norwitz) Date: Fri, 8 Aug 2008 08:40:14 -0400 Subject: [Python-3000-checkins] Python Regression Test Failures doc (1) Message-ID: <20080808124014.GA27667@python.psfb.org> svn update tools/sphinx U tools/sphinx/quickstart.py U tools/sphinx/_jinja.py U tools/sphinx/static/sphinxdoc.css U tools/sphinx/static/default.css U tools/sphinx/environment.py U tools/sphinx/config.py D tools/sphinx/templates/web U tools/sphinx/templates/page.html U tools/sphinx/templates/layout.html U tools/sphinx/templates/genindex-single.html U tools/sphinx/templates/genindex.html U tools/sphinx/templates/opensearch.xml U tools/sphinx/templates/changes/versionchanges.html U tools/sphinx/templates/changes/frameset.html U tools/sphinx/templates/changes/rstsource.html U tools/sphinx/templates/search.html U tools/sphinx/templates/defindex.html U tools/sphinx/templates/modindex.html U tools/sphinx/templates/genindex-split.html A tools/sphinx/locale A tools/sphinx/locale/de A tools/sphinx/locale/de/LC_MESSAGES A tools/sphinx/locale/de/LC_MESSAGES/sphinx.mo A tools/sphinx/locale/de/LC_MESSAGES/sphinx.po A tools/sphinx/locale/sphinx.pot U tools/sphinx/latexwriter.py U tools/sphinx/builder.py Updated to revision 65598. svn update tools/docutils At revision 65598. svn update tools/jinja At revision 65598. svn update tools/pygments At revision 65598. mkdir -p build/html build/doctrees python2.5 tools/sphinx-build.py -b html -d build/doctrees -D latex_paper_size= . build/html Sphinx v0.5, building html loading translations [en]... Exception occurred: File "/home/neal/python/py3k/Doc/tools/sphinx/builder.py", line 183, in load_i18n self.info('selected locale not available' % self.config.language) TypeError: not all arguments converted during string formatting The full traceback has been saved in /tmp/sphinx-err-9heJNE.log, if you want to report the issue to the author. Please also report this if it was a user error, so that a better error message can be provided next time. Send reports to sphinx-dev at googlegroups.com. Thanks! make: *** [build] Error 1 From python-3000-checkins at python.org Tue Aug 12 10:18:18 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Tue, 12 Aug 2008 10:18:18 +0200 (CEST) Subject: [Python-3000-checkins] r65647 - in python/branches/py3k: Doc/library/mailbox.rst Doc/library/select.rst Doc/library/subprocess.rst Doc/reference/expressions.rst Doc/whatsnew/2.6.rst Lib/multiprocessing/connection.py Lib/test/test_multiprocessing.py Misc/developers.txt Message-ID: <20080812081818.A4AA31E4003@bag.python.org> Author: georg.brandl Date: Tue Aug 12 10:18:18 2008 New Revision: 65647 Log: Merged revisions 65437,65469,65476,65480,65502,65528,65539,65543,65558,65561-65562,65565,65591,65601,65608,65610,65639 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65437 | georg.brandl | 2008-08-03 22:28:55 +0000 (Sun, 03 Aug 2008) | 2 lines Note the removal of several committers. ........ r65469 | gregory.p.smith | 2008-08-04 01:03:50 +0000 (Mon, 04 Aug 2008) | 3 lines issue1606: Add warnings to the subprocess documentation about common pitfalls of using pipes that cause deadlocks. ........ r65476 | georg.brandl | 2008-08-04 06:29:36 +0000 (Mon, 04 Aug 2008) | 2 lines Fix markup. ........ r65480 | georg.brandl | 2008-08-04 07:31:50 +0000 (Mon, 04 Aug 2008) | 3 lines Clarify the meaning of the select() parameters and sync names with docstring. ........ r65502 | gregory.p.smith | 2008-08-04 18:34:07 +0000 (Mon, 04 Aug 2008) | 2 lines more cleanup ups of the recently added warnings in the subprocess docs. ........ r65528 | brett.cannon | 2008-08-04 21:52:25 +0000 (Mon, 04 Aug 2008) | 4 lines Add a note about all the modules/packages changed to silence -3 warnings. More changes are needed once some decisions are made, but this is the work up to this point. ........ r65539 | andrew.kuchling | 2008-08-05 01:38:08 +0000 (Tue, 05 Aug 2008) | 6 lines #3367 from Kristjan Valur Jonsson: If a PyTokenizer_FromString() is called with an empty string, the tokenizer's line_start member never gets initialized. Later, it is compared with the token pointer 'a' in parsetok.c:193 and that behavior can result in undefined behavior. ........ r65543 | andrew.kuchling | 2008-08-05 02:05:23 +0000 (Tue, 05 Aug 2008) | 1 line #3367: revert rev. 65539: this change causes test_parser to fail ........ r65558 | georg.brandl | 2008-08-06 17:20:41 +0000 (Wed, 06 Aug 2008) | 2 lines Fix longstringitem definition. #3505. ........ r65561 | mark.dickinson | 2008-08-06 20:12:30 +0000 (Wed, 06 Aug 2008) | 2 lines Docstring typo ........ r65562 | mark.dickinson | 2008-08-06 21:36:57 +0000 (Wed, 06 Aug 2008) | 2 lines Remove duplicate import ........ r65565 | andrew.kuchling | 2008-08-07 01:47:34 +0000 (Thu, 07 Aug 2008) | 1 line Add some items ........ r65591 | georg.brandl | 2008-08-08 06:42:20 +0000 (Fri, 08 Aug 2008) | 2 lines #3519: callee is an expression too. ........ r65601 | georg.brandl | 2008-08-08 15:34:34 +0000 (Fri, 08 Aug 2008) | 2 lines Remove mention of backquotes in the tutorial. ........ r65608 | guido.van.rossum | 2008-08-09 14:55:34 +0000 (Sat, 09 Aug 2008) | 2 lines Add news item about _sre.compile() re-bytecode validator. ........ r65610 | antoine.pitrou | 2008-08-09 17:27:23 +0000 (Sat, 09 Aug 2008) | 3 lines move NEWS entry to the appropriate section (oops!) ........ r65639 | georg.brandl | 2008-08-11 10:27:31 +0000 (Mon, 11 Aug 2008) | 2 lines #3540: fix exception name. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/mailbox.rst python/branches/py3k/Doc/library/select.rst python/branches/py3k/Doc/library/subprocess.rst python/branches/py3k/Doc/reference/expressions.rst python/branches/py3k/Doc/whatsnew/2.6.rst python/branches/py3k/Lib/multiprocessing/connection.py python/branches/py3k/Lib/test/test_multiprocessing.py python/branches/py3k/Misc/developers.txt Modified: python/branches/py3k/Doc/library/mailbox.rst ============================================================================== --- python/branches/py3k/Doc/library/mailbox.rst (original) +++ python/branches/py3k/Doc/library/mailbox.rst Tue Aug 12 10:18:18 2008 @@ -1478,7 +1478,7 @@ parameter set to ``False``), or when opening a folder that does not exist. -.. exception:: NotEmptyErrorError() +.. exception:: NotEmptyError() Raised when a mailbox is not empty but is expected to be, such as when deleting a folder that contains messages. Modified: python/branches/py3k/Doc/library/select.rst ============================================================================== --- python/branches/py3k/Doc/library/select.rst (original) +++ python/branches/py3k/Doc/library/select.rst Tue Aug 12 10:18:18 2008 @@ -52,19 +52,24 @@ :ref:`kevent-objects` below for the methods supported by kqueue objects. -.. function:: select(iwtd, owtd, ewtd[, timeout]) +.. function:: select(rlist, wlist, xlist[, timeout]) This is a straightforward interface to the Unix :cfunc:`select` system call. The first three arguments are sequences of 'waitable objects': either integers representing file descriptors or objects with a parameterless method - named :meth:`fileno` returning such an integer. The three sequences of - waitable objects are for input, output and 'exceptional conditions', - respectively. Empty sequences are allowed, but acceptance of three empty - sequences is platform-dependent. (It is known to work on Unix but not on - Windows.) The optional *timeout* argument specifies a time-out as a floating - point number in seconds. When the *timeout* argument is omitted the function - blocks until at least one file descriptor is ready. A time-out value of zero - specifies a poll and never blocks. + named :meth:`fileno` returning such an integer: + + * *rlist*: wait until ready for reading + * *wlist*: wait until ready for writing + * *xlist*: wait for an "exceptional condition" (see the manual page for what + your system considers such a condition) + + Empty sequences are allowed, but acceptance of three empty sequences is + platform-dependent. (It is known to work on Unix but not on Windows.) The + optional *timeout* argument specifies a time-out as a floating point number + in seconds. When the *timeout* argument is omitted the function blocks until + at least one file descriptor is ready. A time-out value of zero specifies a + poll and never blocks. The return value is a triple of lists of objects that are ready: subsets of the first three arguments. When the time-out is reached without a file descriptor @@ -84,9 +89,10 @@ .. index:: single: WinSock - File objects on Windows are not acceptable, but sockets are. On Windows, the - underlying :cfunc:`select` function is provided by the WinSock library, and does - not handle file descriptors that don't originate from WinSock. + File objects on Windows are not acceptable, but sockets are. On Windows, + the underlying :cfunc:`select` function is provided by the WinSock + library, and does not handle file descriptors that don't originate from + WinSock. .. _epoll-objects: Modified: python/branches/py3k/Doc/library/subprocess.rst ============================================================================== --- python/branches/py3k/Doc/library/subprocess.rst (original) +++ python/branches/py3k/Doc/library/subprocess.rst Tue Aug 12 10:18:18 2008 @@ -215,6 +215,12 @@ Wait for child process to terminate. Set and return :attr:`returncode` attribute. + .. warning:: + + This will deadlock if the child process generates enough output to a + stdout or stderr pipe such that it blocks waiting for the OS pipe buffer + to accept more data. Use :meth:`communicate` to avoid that. + .. method:: Popen.communicate(input=None) @@ -261,6 +267,14 @@ The following attributes are also available: +.. warning:: + + Use :meth:`communicate` rather than :meth:`.stdin.write`, + :meth:`.stdout.read` or :meth:`.stderr.read` to avoid deadlocks due + to any of the other OS pipe buffers filling up and blocking the child + process. + + .. attribute:: Popen.stdin If the *stdin* argument is ``PIPE``, this attribute is a file object that Modified: python/branches/py3k/Doc/reference/expressions.rst ============================================================================== --- python/branches/py3k/Doc/reference/expressions.rst (original) +++ python/branches/py3k/Doc/reference/expressions.rst Tue Aug 12 10:18:18 2008 @@ -1212,7 +1212,7 @@ (expr1, expr2, expr3, expr4) {expr1: expr2, expr3: expr4} expr1 + expr2 * (expr3 - expr4) - func(expr1, expr2, *expr3, **expr4) + expr1(expr2, expr3, *expr4, **expr5) expr3, expr4 = expr1, expr2 Modified: python/branches/py3k/Doc/whatsnew/2.6.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/2.6.rst (original) +++ python/branches/py3k/Doc/whatsnew/2.6.rst Tue Aug 12 10:18:18 2008 @@ -785,7 +785,7 @@ '%' - Percentage. Multiplies the number by 100 and displays in fixed ('f') format, followed by a percent sign. -Classes and types can define a __format__ method to control how they're +Classes and types can define a :meth:`__format__` method to control how they're formatted. It receives a single argument, the format specifier:: def __format__(self, format_spec): @@ -1515,10 +1515,22 @@ :func:`isnan`, return true if their floating-point argument is infinite or Not A Number. (:issue:`1640`) - The float type has a new instance method :meth:`float.hex` and a - corresponding new class method :meth:`float.fromhex` to convert - floating-point numbers to and from hexadecimal strings, - respectively. (:issue:`3008`) + Conversion functions were added to convert floating-point numbers + into hexadecimal strings. (:issue:`3008`) These functions lets you + convert floats to and from a string representation without + introducing rounding errors from the conversion between decimal and + binary. Floats have a :meth:`hex` method that returns a string + representation, and the ``float.fromhex()`` method converts a string + back into a number:: + + >>> a = 3.75 + >>> a.hex() + '0x1.e000000000000p+1' + >>> float.fromhex('0x1.e000000000000p+1') + 3.75 + >>> b=1./3 + >>> b.hex() + '0x1.5555555555555p-2' * The :mod:`math` module has a number of new functions, and the existing functions have been improved to give more consistent behaviour @@ -1633,6 +1645,12 @@ (Original optimization implemented by Armin Rigo, updated for Python 2.6 by Kevin Jacobs; :issue:`1700288`.) +* Function calls that use keyword arguments + are significantly faster thanks to a patch that does a quick pointer + comparison, usually saving the time of a full string comparison. + (Contributed by Raymond Hettinger, after an initial implementation by + Antoine Pitrou; :issue:`1819`.) + * All of the functions in the :mod:`struct` module have been rewritten in C, thanks to work at the Need For Speed sprint. (Contributed by Raymond Hettinger.) Modified: python/branches/py3k/Lib/multiprocessing/connection.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/connection.py (original) +++ python/branches/py3k/Lib/multiprocessing/connection.py Tue Aug 12 10:18:18 2008 @@ -209,7 +209,7 @@ class SocketListener(object): ''' - Represtation of a socket which is bound to an address and listening + Representation of a socket which is bound to an address and listening ''' def __init__(self, address, family, backlog=1): self._socket = socket.socket(getattr(socket, family)) Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Tue Aug 12 10:18:18 2008 @@ -22,7 +22,6 @@ import multiprocessing.connection import multiprocessing.managers import multiprocessing.heap -import multiprocessing.managers import multiprocessing.pool import _multiprocessing Modified: python/branches/py3k/Misc/developers.txt ============================================================================== --- python/branches/py3k/Misc/developers.txt (original) +++ python/branches/py3k/Misc/developers.txt Tue Aug 12 10:18:18 2008 @@ -20,7 +20,7 @@ - Antoine Pitrou was given SVN access on July 16 2008, by recommendation from GvR, for general contributions to Python. -- Jesse Noller was given SVN access on 16 June 2008 by Georg Brandl, +- Jesse Noller was given SVN access on 16 June 2008 by GFB, for work on the multiprocessing module. - Gregor Lingl was given SVN access on 10 June 2008 by MvL, @@ -45,13 +45,13 @@ for work on branches (ast/optimizer related). - Jeroen Ruigrok van der Werven was given SVN access on 12 April 2008 - by Georg Brandl, for documentation work. + by GFB, for documentation work. -- Josiah Carlson was given SVN access on 26 March 2008 by Georg Brandl, +- Josiah Carlson was given SVN access on 26 March 2008 by GFB, for work on asyncore/asynchat. -- Benjamin Peterson was given SVN access on 25 March 2008 by Georg - Brandl, for bug triage work. +- Benjamin Peterson was given SVN access on 25 March 2008 by GFB, + for bug triage work. - Jerry Seutter was given SVN access on 20 March 2008 by BAC, for general contributions to Python. @@ -196,6 +196,12 @@ Permissions Dropped on Request ------------------------------ +- Roy Smith, Matt Fleming and Richard Emslie sent drop requests. + 4 Aug 2008 GFB + +- Per note from Andrew Kuchling, the permissions for Gregory K Johnson + and the Summer Of Code project are no longer needed. 4 Aug 2008 GFB + - Per note from Andrew Kuchling, the permissions for Gregory K Johnson and the Summer Of Code project are no longer needed. AMK will make any future checkins directly. 16 Oct 2005 RDH @@ -235,3 +241,4 @@ TGP: Tim Peters DJG: David Goodger MvL: Martin v. Loewis +GFB: Georg Brandl From python-3000-checkins at python.org Tue Aug 12 10:35:53 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Tue, 12 Aug 2008 10:35:53 +0200 (CEST) Subject: [Python-3000-checkins] r65648 - in python/branches/py3k: Lib/mailbox.py Lib/multiprocessing/connection.py Lib/shutil.py Lib/subprocess.py Lib/test/test_dict.py Lib/test/test_long.py Lib/test/test_mailbox.py Modules/bz2module.c Modules/fcntlmodule.c Objects/dictobject.c Objects/longobject.c Python/pystate.c Python/thread.c Message-ID: <20080812083553.3DFC71E4003@bag.python.org> Author: georg.brandl Date: Tue Aug 12 10:35:52 2008 New Revision: 65648 Log: Merged revisions 65459,65472,65481,65518,65536,65581,65609,65637,65641,65644-65645 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65459 | gregory.p.smith | 2008-08-04 00:13:29 +0000 (Mon, 04 Aug 2008) | 4 lines - Issue #1857: subprocess.Popen.poll gained an additional _deadstate keyword argument in python 2.5, this broke code that subclassed Popen to include its own poll method. Fixed my moving _deadstate to an _internal_poll method. ........ r65472 | andrew.kuchling | 2008-08-04 01:43:43 +0000 (Mon, 04 Aug 2008) | 3 lines Bug 3228: Explicitly supply the file mode to avoid creating executable files, and add corresponding tests. Possible 2.5 backport candidate ........ r65481 | gregory.p.smith | 2008-08-04 07:33:37 +0000 (Mon, 04 Aug 2008) | 22 lines Adds a sanity check to avoid a *very rare* infinite loop due to a corrupt tls key list data structure in the thread startup path. This change is a companion to r60148 which already successfully dealt with a similar issue on thread shutdown. In particular this loop has been observed happening from this call path: #0 in find_key () #1 in PyThread_set_key_value () #2 in _PyGILState_NoteThreadState () #3 in PyThreadState_New () #4 in t_bootstrap () #5 in pthread_start_thread () I don't know how this happens but it does, *very* rarely. On more than one hardware platform. I have not been able to reproduce it manually. (A flaky mutex implementation on the system in question is one hypothesis). As with r60148, the spinning we managed to observe in the wild was due to a single list element pointing back upon itself. ........ r65518 | mark.dickinson | 2008-08-04 21:30:09 +0000 (Mon, 04 Aug 2008) | 7 lines Issue #1481296: (again!) Make conversion of a float NaN to an int or long raise ValueError instead of returning 0. Also, change the error message for conversion of an infinity to an integer, replacing 'long' by 'integer', so that it's appropriate for both long(float('inf')) and int(float('inf')). ........ r65536 | andrew.kuchling | 2008-08-05 01:00:57 +0000 (Tue, 05 Aug 2008) | 1 line Bug 3228: take a test from Niels Gustaebel's patch, and based on his patch, check for having os.stat available ........ r65581 | guido.van.rossum | 2008-08-07 18:51:38 +0000 (Thu, 07 Aug 2008) | 3 lines Patch by Ian Charnas from issue 3517. Add F_FULLFSYNC if it exists (OS X only so far). ........ r65609 | antoine.pitrou | 2008-08-09 17:22:25 +0000 (Sat, 09 Aug 2008) | 3 lines #3205: bz2 iterator fails silently on MemoryError ........ r65637 | georg.brandl | 2008-08-11 09:07:59 +0000 (Mon, 11 Aug 2008) | 3 lines - Issue #3537: Fix an assertion failure when an empty but presized dict object was stored in the freelist. ........ r65641 | jesse.noller | 2008-08-11 14:28:07 +0000 (Mon, 11 Aug 2008) | 2 lines Remove the fqdn call for issue 3270 ........ r65644 | antoine.pitrou | 2008-08-11 17:21:36 +0000 (Mon, 11 Aug 2008) | 3 lines #3134: shutil referenced undefined WindowsError symbol ........ r65645 | jesse.noller | 2008-08-11 19:00:15 +0000 (Mon, 11 Aug 2008) | 2 lines Fix the connection refused error part of issue 3419, use errno module instead of a static list of possible connection refused messages. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/mailbox.py python/branches/py3k/Lib/multiprocessing/connection.py python/branches/py3k/Lib/shutil.py python/branches/py3k/Lib/subprocess.py python/branches/py3k/Lib/test/test_dict.py python/branches/py3k/Lib/test/test_long.py python/branches/py3k/Lib/test/test_mailbox.py python/branches/py3k/Modules/bz2module.c python/branches/py3k/Modules/fcntlmodule.c python/branches/py3k/Objects/dictobject.c python/branches/py3k/Objects/longobject.c python/branches/py3k/Python/pystate.c python/branches/py3k/Python/thread.c Modified: python/branches/py3k/Lib/mailbox.py ============================================================================== --- python/branches/py3k/Lib/mailbox.py (original) +++ python/branches/py3k/Lib/mailbox.py Tue Aug 12 10:35:52 2008 @@ -394,7 +394,8 @@ result = Maildir(path, factory=self._factory) maildirfolder_path = os.path.join(path, 'maildirfolder') if not os.path.exists(maildirfolder_path): - os.close(os.open(maildirfolder_path, os.O_CREAT | os.O_WRONLY)) + os.close(os.open(maildirfolder_path, os.O_CREAT | os.O_WRONLY, + 0o666)) return result def remove_folder(self, folder): @@ -1900,7 +1901,7 @@ def _create_carefully(path): """Create a file if it doesn't exist and open for reading and writing.""" - fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR) + fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0o666) try: return open(path, 'r+', newline='') finally: Modified: python/branches/py3k/Lib/multiprocessing/connection.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/connection.py (original) +++ python/branches/py3k/Lib/multiprocessing/connection.py Tue Aug 12 10:35:52 2008 @@ -11,6 +11,7 @@ import os import sys import socket +import errno import time import tempfile import itertools @@ -215,10 +216,7 @@ self._socket = socket.socket(getattr(socket, family)) self._socket.bind(address) self._socket.listen(backlog) - address = self._socket.getsockname() - if type(address) is tuple: - address = (socket.getfqdn(address[0]),) + address[1:] - self._address = address + self._address = self._socket.getsockname() self._family = family self._last_accepted = None @@ -253,7 +251,7 @@ try: s.connect(address) except socket.error as e: - if e.args[0] != 10061: # 10061 => connection refused + if e.args[0] != errno.ECONNREFUSED: # connection refused debug('failed to connect to address %s', address) raise time.sleep(0.01) Modified: python/branches/py3k/Lib/shutil.py ============================================================================== --- python/branches/py3k/Lib/shutil.py (original) +++ python/branches/py3k/Lib/shutil.py Tue Aug 12 10:35:52 2008 @@ -16,6 +16,11 @@ class Error(EnvironmentError): pass +try: + WindowsError +except NameError: + WindowsError = None + def copyfileobj(fsrc, fdst, length=16*1024): """copy data from file-like object fsrc to file-like object fdst""" while 1: @@ -162,11 +167,12 @@ errors.extend(err.args[0]) try: copystat(src, dst) - except WindowsError: - # can't copy file access times on Windows - pass except OSError as why: - errors.extend((src, dst, str(why))) + if WindowsError is not None and isinstance(why, WindowsError): + # Copying file access times may fail on Windows + pass + else: + errors.extend((src, dst, str(why))) if errors: raise Error(errors) Modified: python/branches/py3k/Lib/subprocess.py ============================================================================== --- python/branches/py3k/Lib/subprocess.py (original) +++ python/branches/py3k/Lib/subprocess.py Tue Aug 12 10:35:52 2008 @@ -375,7 +375,7 @@ def _cleanup(): for inst in _active[:]: - res = inst.poll(_deadstate=sys.maxsize) + res = inst._internal_poll(_deadstate=sys.maxsize) if res is not None and res >= 0: try: _active.remove(inst) @@ -635,7 +635,7 @@ # We didn't get to successfully create a child process. return # In case the child hasn't been waited on, check if it's done. - self.poll(_deadstate=sys.maxsize) + self._internal_poll(_deadstate=sys.maxsize) if self.returncode is None and _active is not None: # Child is still running, keep us alive until we can wait on it. _active.append(self) @@ -671,6 +671,10 @@ return self._communicate(input) + def poll(self): + return self._internal_poll() + + if mswindows: # # Windows methods @@ -842,7 +846,7 @@ errwrite.Close() - def poll(self, _deadstate=None): + def _internal_poll(self, _deadstate=None): """Check if child process has terminated. Returns returncode attribute.""" if self.returncode is None: @@ -1103,7 +1107,7 @@ raise RuntimeError("Unknown child exit status!") - def poll(self, _deadstate=None): + def _internal_poll(self, _deadstate=None): """Check if child process has terminated. Returns returncode attribute.""" if self.returncode is None: Modified: python/branches/py3k/Lib/test/test_dict.py ============================================================================== --- python/branches/py3k/Lib/test/test_dict.py (original) +++ python/branches/py3k/Lib/test/test_dict.py Tue Aug 12 10:35:52 2008 @@ -638,6 +638,17 @@ resizing = True d[9] = 6 + def test_empty_presized_dict_in_freelist(self): + # Bug #3537: if an empty but presized dict with a size larger + # than 7 was in the freelist, it triggered an assertion failure + try: + d = {'a': 1/0, 'b': None, 'c': None, 'd': None, 'e': None, + 'f': None, 'g': None, 'h': None} + except ZeroDivisionError: + pass + d = {} + + from test import mapping_tests Modified: python/branches/py3k/Lib/test/test_long.py ============================================================================== --- python/branches/py3k/Lib/test/test_long.py (original) +++ python/branches/py3k/Lib/test/test_long.py Tue Aug 12 10:35:52 2008 @@ -768,7 +768,8 @@ def test_nan_inf(self): self.assertRaises(OverflowError, int, float('inf')) - self.assertRaises(OverflowError, int, float('nan')) + self.assertRaises(OverflowError, int, float('-inf')) + self.assertRaises(ValueError, int, float('nan')) def test_true_division(self): huge = 1 << 40000 Modified: python/branches/py3k/Lib/test/test_mailbox.py ============================================================================== --- python/branches/py3k/Lib/test/test_mailbox.py (original) +++ python/branches/py3k/Lib/test/test_mailbox.py Tue Aug 12 10:35:52 2008 @@ -709,6 +709,38 @@ for msg in self._box: pass + def test_file_permissions(self): + # Verify that message files are created without execute permissions + if not hasattr(os, "stat") or not hasattr(os, "umask"): + return + msg = mailbox.MaildirMessage(self._template % 0) + orig_umask = os.umask(0) + try: + key = self._box.add(msg) + finally: + os.umask(orig_umask) + path = os.path.join(self._path, self._box._lookup(key)) + mode = os.stat(path).st_mode + self.assert_(mode & 0o111 == 0) + + def test_folder_file_perms(self): + # From bug #3228, we want to verify that the file created inside a Maildir + # subfolder isn't marked as executable. + if not hasattr(os, "stat") or not hasattr(os, "umask"): + return + + orig_umask = os.umask(0) + try: + subfolder = self._box.add_folder('subfolder') + finally: + os.umask(orig_umask) + + path = os.path.join(subfolder._path, 'maildirfolder') + st = os.stat(path) + perms = st.st_mode + self.assertFalse((perms & 0o111)) # Execute bits should all be off. + + class _TestMboxMMDF(TestMailbox): def tearDown(self): @@ -800,11 +832,28 @@ self._box.close() - class TestMbox(_TestMboxMMDF): _factory = lambda self, path, factory=None: mailbox.mbox(path, factory) + def test_file_perms(self): + # From bug #3228, we want to verify that the mailbox file isn't executable, + # even if the umask is set to something that would leave executable bits set. + # We only run this test on platforms that support umask. + if hasattr(os, 'umask') and hasattr(os, 'stat'): + try: + old_umask = os.umask(0o077) + self._box.close() + os.unlink(self._path) + self._box = mailbox.mbox(self._path, create=True) + self._box.add('') + self._box.close() + finally: + os.umask(old_umask) + + st = os.stat(self._path) + perms = st.st_mode + self.assertFalse((perms & 0o111)) # Execute bits should all be off. class TestMMDF(_TestMboxMMDF): Modified: python/branches/py3k/Modules/bz2module.c ============================================================================== --- python/branches/py3k/Modules/bz2module.c (original) +++ python/branches/py3k/Modules/bz2module.c Tue Aug 12 10:35:52 2008 @@ -317,6 +317,7 @@ return 0; } if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) { + PyErr_NoMemory(); return -1; } Py_BEGIN_ALLOW_THREADS Modified: python/branches/py3k/Modules/fcntlmodule.c ============================================================================== --- python/branches/py3k/Modules/fcntlmodule.c (original) +++ python/branches/py3k/Modules/fcntlmodule.c Tue Aug 12 10:35:52 2008 @@ -530,6 +530,11 @@ if (ins(d, "F_SHLCK", (long)F_SHLCK)) return -1; #endif +/* OS X (and maybe others) let you tell the storage device to flush to physical media */ +#ifdef F_FULLFSYNC + if (ins(d, "F_FULLFSYNC", (long)F_FULLFSYNC)) return -1; +#endif + /* For F_{GET|SET}FL */ #ifdef FD_CLOEXEC if (ins(d, "FD_CLOEXEC", (long)FD_CLOEXEC)) return -1; Modified: python/branches/py3k/Objects/dictobject.c ============================================================================== --- python/branches/py3k/Objects/dictobject.c (original) +++ python/branches/py3k/Objects/dictobject.c Tue Aug 12 10:35:52 2008 @@ -242,6 +242,10 @@ _Py_NewReference((PyObject *)mp); if (mp->ma_fill) { EMPTY_TO_MINSIZE(mp); + } else { + /* At least set ma_table and ma_mask; these are wrong + if an empty but presized dict is added to freelist */ + INIT_NONZERO_DICT_SLOTS(mp); } assert (mp->ma_used == 0); assert (mp->ma_table == mp->ma_smalltable); Modified: python/branches/py3k/Objects/longobject.c ============================================================================== --- python/branches/py3k/Objects/longobject.c (original) +++ python/branches/py3k/Objects/longobject.c Tue Aug 12 10:35:52 2008 @@ -271,12 +271,12 @@ neg = 0; if (Py_IS_INFINITY(dval)) { PyErr_SetString(PyExc_OverflowError, - "cannot convert float infinity to int"); + "cannot convert float infinity to integer"); return NULL; } if (Py_IS_NAN(dval)) { - PyErr_SetString(PyExc_OverflowError, - "cannot convert float NaN to int"); + PyErr_SetString(PyExc_ValueError, + "cannot convert float NaN to integer"); return NULL; } if (dval < 0.0) { Modified: python/branches/py3k/Python/pystate.c ============================================================================== --- python/branches/py3k/Python/pystate.c (original) +++ python/branches/py3k/Python/pystate.c Tue Aug 12 10:35:52 2008 @@ -291,6 +291,10 @@ "PyThreadState_Delete: invalid tstate"); if (*p == tstate) break; + /* Sanity check. These states should never happen but if + * they do we must abort. Otherwise we'll end up spinning in + * in a tight loop with the lock held. A similar check is done + * in thread.c find_key(). */ if (*p == prev_p) Py_FatalError( "PyThreadState_Delete: small circular list(!)" Modified: python/branches/py3k/Python/thread.c ============================================================================== --- python/branches/py3k/Python/thread.c (original) +++ python/branches/py3k/Python/thread.c Tue Aug 12 10:35:52 2008 @@ -260,15 +260,25 @@ static struct key * find_key(int key, void *value) { - struct key *p; + struct key *p, *prev_p; long id = PyThread_get_thread_ident(); if (!keymutex) return NULL; PyThread_acquire_lock(keymutex, 1); + prev_p = NULL; for (p = keyhead; p != NULL; p = p->next) { if (p->id == id && p->key == key) goto Done; + /* Sanity check. These states should never happen but if + * they do we must abort. Otherwise we'll end up spinning in + * in a tight loop with the lock held. A similar check is done + * in pystate.c tstate_delete_common(). */ + if (p == prev_p) + Py_FatalError("tls find_key: small circular list(!)"); + prev_p = p; + if (p->next == keyhead) + Py_FatalError("tls find_key: circular list(!)"); } if (value == NULL) { assert(p == NULL); From python-3000-checkins at python.org Tue Aug 12 18:56:25 2008 From: python-3000-checkins at python.org (bill.janssen) Date: Tue, 12 Aug 2008 18:56:25 +0200 (CEST) Subject: [Python-3000-checkins] r65656 - in python/branches/py3k: Lib/ssl.py Lib/test/test_ssl.py Modules/_ssl.c Message-ID: <20080812165625.8E5EE1E4004@bag.python.org> Author: bill.janssen Date: Tue Aug 12 18:56:25 2008 New Revision: 65656 Log: clean up ssl.py; expose unwrap and add test for it Modified: python/branches/py3k/Lib/ssl.py python/branches/py3k/Lib/test/test_ssl.py python/branches/py3k/Modules/_ssl.c Modified: python/branches/py3k/Lib/ssl.py ============================================================================== --- python/branches/py3k/Lib/ssl.py (original) +++ python/branches/py3k/Lib/ssl.py Tue Aug 12 18:56:25 2008 @@ -75,10 +75,10 @@ SSL_ERROR_INVALID_ERROR_CODE, ) -from socket import socket, AF_INET, SOCK_STREAM, error from socket import getnameinfo as _getnameinfo from socket import error as socket_error from socket import dup as _dup +from socket import socket, AF_INET, SOCK_STREAM import base64 # for DER-to-PEM translation import traceback @@ -296,6 +296,14 @@ self._sslobj = None socket.shutdown(self, how) + def unwrap (self): + if self._sslobj: + s = self._sslobj.shutdown() + self._sslobj = None + return s + else: + raise ValueError("No SSL wrapper around " + str(self)) + def _real_close(self): self._sslobj = None # self._closed = True Modified: python/branches/py3k/Lib/test/test_ssl.py ============================================================================== --- python/branches/py3k/Lib/test/test_ssl.py (original) +++ python/branches/py3k/Lib/test/test_ssl.py Tue Aug 12 18:56:25 2008 @@ -279,6 +279,15 @@ self.write("OK\n".encode("ASCII", "strict")) if not self.wrap_conn(): return + elif (self.server.starttls_server and self.sslconn + and amsg.strip() == 'ENDTLS'): + if support.verbose and self.server.connectionchatty: + sys.stdout.write(" server: read ENDTLS from client, sending OK...\n") + self.write("OK\n".encode("ASCII", "strict")) + self.sock = self.sslconn.unwrap() + self.sslconn = None + if support.verbose and self.server.connectionchatty: + sys.stdout.write(" server: connection is now unencrypted...\n") else: if (support.verbose and self.server.connectionchatty): @@ -868,7 +877,7 @@ def testSTARTTLS (self): - msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4") + msgs = ("msg 1", "MSG 2", "STARTTLS", "MSG 3", "msg 4", "ENDTLS", "msg 5", "msg 6") server = ThreadedEchoServer(CERTFILE, ssl_version=ssl.PROTOCOL_TLSv1, @@ -910,8 +919,16 @@ " client: read %s from server, starting TLS...\n" % repr(msg)) conn = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1) - wrapped = True + elif (indata == "ENDTLS" and + str(outdata, 'ASCII', 'replace').strip().lower().startswith("ok")): + if support.verbose: + msg = str(outdata, 'ASCII', 'replace') + sys.stdout.write( + " client: read %s from server, ending TLS...\n" + % repr(msg)) + s = conn.unwrap() + wrapped = False else: if support.verbose: msg = str(outdata, 'ASCII', 'replace') @@ -922,7 +939,7 @@ if wrapped: conn.write("over\n".encode("ASCII", "strict")) else: - s.send("over\n") + s.send("over\n".encode("ASCII", "strict")) if wrapped: conn.close() else: Modified: python/branches/py3k/Modules/_ssl.c ============================================================================== --- python/branches/py3k/Modules/_ssl.c (original) +++ python/branches/py3k/Modules/_ssl.c Tue Aug 12 18:56:25 2008 @@ -1370,6 +1370,42 @@ \n\ Read up to len bytes from the SSL socket."); +static PyObject *PySSL_SSLshutdown(PySSLObject *self) +{ + int err; + PySocketSockObject *sock + = (PySocketSockObject *) PyWeakref_GetObject(self->Socket); + + /* Guard against closed socket */ + if ((((PyObject*)sock) == Py_None) || (sock->sock_fd < 0)) { + _setSSLError("Underlying socket connection gone", + PY_SSL_ERROR_NO_SOCKET, __FILE__, __LINE__); + return NULL; + } + + PySSL_BEGIN_ALLOW_THREADS + err = SSL_shutdown(self->ssl); + if (err == 0) { + /* we need to call it again to finish the shutdown */ + err = SSL_shutdown(self->ssl); + } + PySSL_END_ALLOW_THREADS + + if (err < 0) + return PySSL_SetError(self, err, __FILE__, __LINE__); + else { + Py_INCREF(sock); + return (PyObject *) sock; + } +} + +PyDoc_STRVAR(PySSL_SSLshutdown_doc, +"shutdown(s) -> socket\n\ +\n\ +Does the SSL shutdown handshake with the remote end, and returns\n\ +the underlying socket object."); + + static PyMethodDef PySSLMethods[] = { {"do_handshake", (PyCFunction)PySSL_SSLdo_handshake, METH_NOARGS}, {"write", (PyCFunction)PySSL_SSLwrite, METH_VARARGS, @@ -1381,6 +1417,8 @@ {"peer_certificate", (PyCFunction)PySSL_peercert, METH_VARARGS, PySSL_peercert_doc}, {"cipher", (PyCFunction)PySSL_cipher, METH_NOARGS}, + {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS, + PySSL_SSLshutdown_doc}, {NULL, NULL} }; @@ -1480,6 +1518,8 @@ #endif + + /* List of functions exported by this module. */ static PyMethodDef PySSL_methods[] = { From python-3000-checkins at python.org Tue Aug 12 19:09:27 2008 From: python-3000-checkins at python.org (bill.janssen) Date: Tue, 12 Aug 2008 19:09:27 +0200 (CEST) Subject: [Python-3000-checkins] r65657 - python/branches/py3k/Doc/library/ssl.rst Message-ID: <20080812170927.901761E4003@bag.python.org> Author: bill.janssen Date: Tue Aug 12 19:09:27 2008 New Revision: 65657 Log: update ssl documentation Modified: python/branches/py3k/Doc/library/ssl.rst Modified: python/branches/py3k/Doc/library/ssl.rst ============================================================================== --- python/branches/py3k/Doc/library/ssl.rst (original) +++ python/branches/py3k/Doc/library/ssl.rst Tue Aug 12 19:09:27 2008 @@ -279,6 +279,15 @@ else: raise +.. method:: SSLSocket.unwrap() + + Performs the SSL shutdown handshake, which removes the TLS layer + from the underlying socket, and returns the underlying socket + object. This can be used to go from encrypted operation over a + connection to unencrypted. The returned socket should always be + used for further communication with the other side of the + connection, rather than the original socket + .. method:: SSLSocket.getpeercert(binary_form=False) If there is no certificate for the peer on the other end of the From python-3000-checkins at python.org Wed Aug 13 17:53:09 2008 From: python-3000-checkins at python.org (martin.v.loewis) Date: Wed, 13 Aug 2008 17:53:09 +0200 (CEST) Subject: [Python-3000-checkins] r65661 - in python/branches/py3k: Doc/c-api/arg.rst Doc/whatsnew/2.6.rst Include/abstract.h Include/object.h Lib/test/test_sys.py Modules/_bsddb.c Modules/_codecsmodule.c Modules/_ctypes/_ctypes.c Modules/_fileio.c Modules/_hashopenssl.c Modules/_json.c Modules/_multiprocessing/connection.h Modules/_sre.c Modules/_struct.c Modules/arraymodule.c Modules/audioop.c Modules/binascii.c Modules/bz2module.c Modules/cjkcodecs/multibytecodec.c Modules/fcntlmodule.c Modules/mmapmodule.c Modules/posixmodule.c Modules/socketmodule.c Modules/zlibmodule.c Objects/abstract.c Objects/bytearrayobject.c Objects/bytesobject.c Objects/memoryobject.c Objects/unicodeobject.c PC/winreg.c Python/getargs.c Python/marshal.c Message-ID: <20080813155309.5E8DA1E4019@bag.python.org> Author: martin.v.loewis Date: Wed Aug 13 17:53:07 2008 New Revision: 65661 Log: Merged revisions 65654 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65654 | martin.v.loewis | 2008-08-12 16:49:50 +0200 (Tue, 12 Aug 2008) | 6 lines Issue #3139: Make buffer-interface thread-safe wrt. PyArg_ParseTuple, by denying s# to parse objects that have a releasebuffer procedure, and introducing s*. More module might need to get converted to use s*. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/c-api/arg.rst python/branches/py3k/Doc/whatsnew/2.6.rst python/branches/py3k/Include/abstract.h python/branches/py3k/Include/object.h python/branches/py3k/Lib/test/test_sys.py python/branches/py3k/Modules/_bsddb.c python/branches/py3k/Modules/_codecsmodule.c python/branches/py3k/Modules/_ctypes/_ctypes.c python/branches/py3k/Modules/_fileio.c python/branches/py3k/Modules/_hashopenssl.c python/branches/py3k/Modules/_json.c python/branches/py3k/Modules/_multiprocessing/connection.h python/branches/py3k/Modules/_sre.c python/branches/py3k/Modules/_struct.c python/branches/py3k/Modules/arraymodule.c python/branches/py3k/Modules/audioop.c python/branches/py3k/Modules/binascii.c python/branches/py3k/Modules/bz2module.c python/branches/py3k/Modules/cjkcodecs/multibytecodec.c python/branches/py3k/Modules/fcntlmodule.c python/branches/py3k/Modules/mmapmodule.c python/branches/py3k/Modules/posixmodule.c python/branches/py3k/Modules/socketmodule.c python/branches/py3k/Modules/zlibmodule.c python/branches/py3k/Objects/abstract.c python/branches/py3k/Objects/bytearrayobject.c python/branches/py3k/Objects/bytesobject.c python/branches/py3k/Objects/memoryobject.c python/branches/py3k/Objects/unicodeobject.c python/branches/py3k/PC/winreg.c python/branches/py3k/Python/getargs.c python/branches/py3k/Python/marshal.c Modified: python/branches/py3k/Doc/c-api/arg.rst ============================================================================== --- python/branches/py3k/Doc/c-api/arg.rst (original) +++ python/branches/py3k/Doc/c-api/arg.rst Wed Aug 13 17:53:07 2008 @@ -40,6 +40,12 @@ other read-buffer compatible objects pass back a reference to the raw internal data representation. +``s*`` (string, Unicode, or any buffer compatible object) [Py_buffer \*] + Similar to ``s#``, this code fills a Py_buffer structure provided by the caller. + The buffer gets locked, so that the caller can subsequently use the buffer even + inside a ``Py_BEGIN_ALLOW_THREADS`` block; the caller is responsible for calling + ``PyBuffer_Release`` with the structure after it has processed the data. + ``y`` (bytes object) [const char \*] This variant on ``s`` convert a Python bytes object to a C pointer to a character string. The bytes object must not contain embedded NUL bytes; if it @@ -49,6 +55,9 @@ This variant on ``s#`` stores into two C variables, the first one a pointer to a character string, the second one its length. This only accepts bytes objects. +``y*`` (bytes object) [Py_buffer \*] + This is to ``s*`` as ``y`` is to ``s``. + ``z`` (string or ``None``) [const char \*] Like ``s``, but the Python object may also be ``None``, in which case the C pointer is set to *NULL*. @@ -56,6 +65,9 @@ ``z#`` (string or ``None`` or any read buffer compatible object) [const char \*, int] This is to ``s#`` as ``z`` is to ``s``. +``z*`` (string or ``None`` or any buffer compatible object) [Py_buffer*] + This is to ``s*`` as ``z`` is to ``s``. + ``u`` (Unicode object) [Py_UNICODE \*] Convert a Python Unicode object to a C pointer to a NUL-terminated buffer of 16-bit Unicode (UTF-16) data. As with ``s``, there is no need to provide @@ -244,6 +256,9 @@ single-segment buffer objects are accepted; :exc:`TypeError` is raised for all others. +``w*`` (read-write byte-oriented buffer) [Py_buffer \*] + This is to ``w`` what ``s*`` is to ``s``. + ``(items)`` (tuple) [*matching-items*] The object must be a Python sequence whose length is the number of format units in *items*. The C arguments must correspond to the individual format units in Modified: python/branches/py3k/Doc/whatsnew/2.6.rst ============================================================================== --- python/branches/py3k/Doc/whatsnew/2.6.rst (original) +++ python/branches/py3k/Doc/whatsnew/2.6.rst Wed Aug 13 17:53:07 2008 @@ -1064,7 +1064,7 @@ can use this operation to lock memory in place while an external caller could be modifying the contents, so there's a corresponding -``PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view)`` to +``PyBuffer_Release(Py_buffer *view)`` to indicate that the external caller is done. The **flags** argument to :cfunc:`PyObject_GetBuffer` specifies @@ -2841,7 +2841,7 @@ * The new buffer interface, previously described in `the PEP 3118 section <#pep-3118-revised-buffer-protocol>`__, - adds :cfunc:`PyObject_GetBuffer` and :cfunc:`PyObject_ReleaseBuffer`, + adds :cfunc:`PyObject_GetBuffer` and :cfunc:`PyBuffer_Release`, as well as a few other functions. * Python's use of the C stdio library is now thread-safe, or at least Modified: python/branches/py3k/Include/abstract.h ============================================================================== --- python/branches/py3k/Include/abstract.h (original) +++ python/branches/py3k/Include/abstract.h Wed Aug 13 17:53:07 2008 @@ -526,24 +526,6 @@ */ - PyAPI_FUNC(void) PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view); - - - /* C-API version of the releasebuffer function call. It - checks to make sure the object has the required function - pointer and issues the call. The obj must have the buffer - interface or this function will cause a segfault (i.e. it - is assumed to be called only after a corresponding - getbuffer which already verified the existence of the - tp_as_buffer pointer). - - Returns 0 on success and -1 (with an error raised) on - failure. This function always succeeds (as a NO-OP) if - there is no releasebuffer function for the object so that - it can always be called when the consumer is done with the - buffer - */ - PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices); /* Get the memory area pointed to by the indices for the buffer given. @@ -600,7 +582,7 @@ per element. */ - PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, void *buf, + PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, PyObject *o, void *buf, Py_ssize_t len, int readonly, int flags); @@ -610,6 +592,10 @@ and -1 (with raising an error) on error. */ + PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view); + + /* Releases a Py_buffer obtained from getbuffer ParseTuple's s*. + */ PyAPI_FUNC(PyObject *) PyObject_Format(PyObject* obj, PyObject *format_spec); Modified: python/branches/py3k/Include/object.h ============================================================================== --- python/branches/py3k/Include/object.h (original) +++ python/branches/py3k/Include/object.h Wed Aug 13 17:53:07 2008 @@ -142,7 +142,8 @@ /* buffer interface */ typedef struct bufferinfo { - void *buf; + void *buf; + PyObject *obj; /* borrowed reference */ Py_ssize_t len; Py_ssize_t itemsize; /* This is Py_ssize_t so it can be pointed to by strides in simple case.*/ Modified: python/branches/py3k/Lib/test/test_sys.py ============================================================================== --- python/branches/py3k/Lib/test/test_sys.py (original) +++ python/branches/py3k/Lib/test/test_sys.py Wed Aug 13 17:53:07 2008 @@ -550,7 +550,7 @@ check(32768*32768-1, size(vh) + 2*self.H) check(32768*32768, size(vh) + 3*self.H) # memory - check(memoryview(b''), size(h + 'P P2P2i5P')) + check(memoryview(b''), size(h + 'P PP2P2i5P')) # module check(unittest, size(h + '3P')) # None Modified: python/branches/py3k/Modules/_bsddb.c ============================================================================== --- python/branches/py3k/Modules/_bsddb.c (original) +++ python/branches/py3k/Modules/_bsddb.c Wed Aug 13 17:53:07 2008 @@ -288,7 +288,7 @@ static void free_buf_view(PyObject *obj, Py_buffer *view) { if (view) { - PyObject_ReleaseBuffer(obj, view); + PyBuffer_Release(view); PyMem_Free(view); } } @@ -319,7 +319,7 @@ if (view->ndim > 1) { PyErr_SetString(PyExc_BufferError, "buffers must be single dimension"); - PyObject_ReleaseBuffer(obj, view); + PyBuffer_Release(view); PyMem_Free(view); return NULL; } Modified: python/branches/py3k/Modules/_codecsmodule.c ============================================================================== --- python/branches/py3k/Modules/_codecsmodule.c (original) +++ python/branches/py3k/Modules/_codecsmodule.c Wed Aug 13 17:53:07 2008 @@ -252,20 +252,20 @@ utf_7_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int final = 0; Py_ssize_t consumed; PyObject *decoded = NULL; - if (!PyArg_ParseTuple(args, "t#|zi:utf_7_decode", - &data, &size, &errors, &final)) - return NULL; - consumed = size; + if (!PyArg_ParseTuple(args, "s*|zi:utf_7_decode", + &pbuf, &errors, &final)) + return NULL; + consumed = pbuf.len; - decoded = PyUnicode_DecodeUTF7Stateful(data, size, errors, - final ? NULL : &consumed); + decoded = PyUnicode_DecodeUTF7Stateful(pbuf.buf, pbuf.len, errors, + final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (decoded == NULL) return NULL; return codec_tuple(decoded, consumed); @@ -275,24 +275,20 @@ utf_8_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int final = 0; Py_ssize_t consumed; PyObject *decoded = NULL; - if (!PyArg_ParseTuple(args, "t#|zi:utf_8_decode", - &data, &size, &errors, &final)) + if (!PyArg_ParseTuple(args, "s*|zi:utf_8_decode", + &pbuf, &errors, &final)) return NULL; - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; - - decoded = PyUnicode_DecodeUTF8Stateful(data, size, errors, + consumed = pbuf.len; + + decoded = PyUnicode_DecodeUTF8Stateful(pbuf.buf, pbuf.len, errors, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (decoded == NULL) return NULL; return codec_tuple(decoded, consumed); @@ -302,24 +298,20 @@ utf_16_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int byteorder = 0; int final = 0; Py_ssize_t consumed; PyObject *decoded; - if (!PyArg_ParseTuple(args, "t#|zi:utf_16_decode", - &data, &size, &errors, &final)) + if (!PyArg_ParseTuple(args, "s*|zi:utf_16_decode", + &pbuf, &errors, &final)) return NULL; - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, - final ? NULL : &consumed); + consumed = pbuf.len; /* This is overwritten unless final is true. */ + decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, + &byteorder, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (decoded == NULL) return NULL; return codec_tuple(decoded, consumed); @@ -329,53 +321,45 @@ utf_16_le_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int byteorder = -1; int final = 0; Py_ssize_t consumed; PyObject *decoded = NULL; - if (!PyArg_ParseTuple(args, "t#|zi:utf_16_le_decode", - &data, &size, &errors, &final)) + if (!PyArg_ParseTuple(args, "s*|zi:utf_16_le_decode", + &pbuf, &errors, &final)) return NULL; - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, + consumed = pbuf.len; /* This is overwritten unless final is true. */ + decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, &byteorder, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (decoded == NULL) return NULL; return codec_tuple(decoded, consumed); - } static PyObject * utf_16_be_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int byteorder = 1; int final = 0; Py_ssize_t consumed; PyObject *decoded = NULL; - if (!PyArg_ParseTuple(args, "t#|zi:utf_16_be_decode", - &data, &size, &errors, &final)) + if (!PyArg_ParseTuple(args, "s*|zi:utf_16_be_decode", + &pbuf, &errors, &final)) return NULL; - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(data, size, errors, + + consumed = pbuf.len; /* This is overwritten unless final is true. */ + decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, &byteorder, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (decoded == NULL) return NULL; return codec_tuple(decoded, consumed); @@ -393,24 +377,20 @@ utf_16_ex_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int byteorder = 0; PyObject *unicode, *tuple; int final = 0; Py_ssize_t consumed; - if (!PyArg_ParseTuple(args, "t#|zii:utf_16_ex_decode", - &data, &size, &errors, &byteorder, &final)) + if (!PyArg_ParseTuple(args, "s*|zii:utf_16_ex_decode", + &pbuf, &errors, &byteorder, &final)) return NULL; - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; /* This is overwritten unless final is true. */ - unicode = PyUnicode_DecodeUTF16Stateful(data, size, errors, &byteorder, - final ? NULL : &consumed); + consumed = pbuf.len; /* This is overwritten unless final is true. */ + unicode = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, + &byteorder, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (unicode == NULL) return NULL; tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); @@ -422,24 +402,20 @@ utf_32_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int byteorder = 0; int final = 0; Py_ssize_t consumed; PyObject *decoded; - if (!PyArg_ParseTuple(args, "t#|zi:utf_32_decode", - &data, &size, &errors, &final)) + if (!PyArg_ParseTuple(args, "s*|zi:utf_32_decode", + &pbuf, &errors, &final)) return NULL; - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder, - final ? NULL : &consumed); + consumed = pbuf.len; /* This is overwritten unless final is true. */ + decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, + &byteorder, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (decoded == NULL) return NULL; return codec_tuple(decoded, consumed); @@ -449,53 +425,43 @@ utf_32_le_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int byteorder = -1; int final = 0; Py_ssize_t consumed; - PyObject *decoded = NULL; + PyObject *decoded; - if (!PyArg_ParseTuple(args, "t#|zi:utf_32_le_decode", - &data, &size, &errors, &final)) + if (!PyArg_ParseTuple(args, "s*|zi:utf_32_le_decode", + &pbuf, &errors, &final)) return NULL; - - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors, - &byteorder, final ? NULL : &consumed); + consumed = pbuf.len; /* This is overwritten unless final is true. */ + decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, + &byteorder, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (decoded == NULL) return NULL; return codec_tuple(decoded, consumed); - } static PyObject * utf_32_be_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int byteorder = 1; int final = 0; Py_ssize_t consumed; - PyObject *decoded = NULL; + PyObject *decoded; - if (!PyArg_ParseTuple(args, "t#|zi:utf_32_be_decode", - &data, &size, &errors, &final)) + if (!PyArg_ParseTuple(args, "s*|zi:utf_32_be_decode", + &pbuf, &errors, &final)) return NULL; - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(data, size, errors, - &byteorder, final ? NULL : &consumed); + consumed = pbuf.len; /* This is overwritten unless final is true. */ + decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, + &byteorder, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (decoded == NULL) return NULL; return codec_tuple(decoded, consumed); @@ -513,24 +479,20 @@ utf_32_ex_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; int byteorder = 0; PyObject *unicode, *tuple; int final = 0; Py_ssize_t consumed; - if (!PyArg_ParseTuple(args, "t#|zii:utf_32_ex_decode", - &data, &size, &errors, &byteorder, &final)) + if (!PyArg_ParseTuple(args, "s*|zii:utf_32_ex_decode", + &pbuf, &errors, &byteorder, &final)) return NULL; - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative argument"); - return 0; - } - consumed = size; /* This is overwritten unless final is true. */ - unicode = PyUnicode_DecodeUTF32Stateful(data, size, errors, &byteorder, - final ? NULL : &consumed); + consumed = pbuf.len; /* This is overwritten unless final is true. */ + unicode = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, + &byteorder, final ? NULL : &consumed); + PyBuffer_Release(&pbuf); if (unicode == NULL) return NULL; tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); @@ -542,83 +504,88 @@ unicode_escape_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; + PyObject *unicode; - if (!PyArg_ParseTuple(args, "t#|z:unicode_escape_decode", - &data, &size, &errors)) + if (!PyArg_ParseTuple(args, "s*|z:unicode_escape_decode", + &pbuf, &errors)) return NULL; - return codec_tuple(PyUnicode_DecodeUnicodeEscape(data, size, errors), - size); + unicode = PyUnicode_DecodeUnicodeEscape(pbuf.buf, pbuf.len, errors); + PyBuffer_Release(&pbuf); + return codec_tuple(unicode, pbuf.len); } static PyObject * raw_unicode_escape_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; const char *errors = NULL; + PyObject *unicode; - if (!PyArg_ParseTuple(args, "t#|z:raw_unicode_escape_decode", - &data, &size, &errors)) + if (!PyArg_ParseTuple(args, "s*|z:raw_unicode_escape_decode", + &pbuf, &errors)) return NULL; - return codec_tuple(PyUnicode_DecodeRawUnicodeEscape(data, size, errors), - size); + unicode = PyUnicode_DecodeRawUnicodeEscape(pbuf.buf, pbuf.len, errors); + PyBuffer_Release(&pbuf); + return codec_tuple(unicode, pbuf.len); } static PyObject * latin_1_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; + PyObject *unicode; const char *errors = NULL; - if (!PyArg_ParseTuple(args, "t#|z:latin_1_decode", - &data, &size, &errors)) + if (!PyArg_ParseTuple(args, "s*|z:latin_1_decode", + &pbuf, &errors)) return NULL; - return codec_tuple(PyUnicode_DecodeLatin1(data, size, errors), - size); + unicode = PyUnicode_DecodeLatin1(pbuf.buf, pbuf.len, errors); + PyBuffer_Release(&pbuf); + return codec_tuple(unicode, pbuf.len); } static PyObject * ascii_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; + PyObject *unicode; const char *errors = NULL; - if (!PyArg_ParseTuple(args, "t#|z:ascii_decode", - &data, &size, &errors)) + if (!PyArg_ParseTuple(args, "s*|z:ascii_decode", + &pbuf, &errors)) return NULL; - return codec_tuple(PyUnicode_DecodeASCII(data, size, errors), - size); + unicode = PyUnicode_DecodeASCII(pbuf.buf, pbuf.len, errors); + PyBuffer_Release(&pbuf); + return codec_tuple(unicode, pbuf.len); } static PyObject * charmap_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size; + Py_buffer pbuf; + PyObject *unicode; const char *errors = NULL; PyObject *mapping = NULL; - if (!PyArg_ParseTuple(args, "t#|zO:charmap_decode", - &data, &size, &errors, &mapping)) + if (!PyArg_ParseTuple(args, "s*|zO:charmap_decode", + &pbuf, &errors, &mapping)) return NULL; if (mapping == Py_None) mapping = NULL; - return codec_tuple(PyUnicode_DecodeCharmap(data, size, mapping, errors), - size); + unicode = PyUnicode_DecodeCharmap(pbuf.buf, pbuf.len, mapping, errors); + PyBuffer_Release(&pbuf); + return codec_tuple(unicode, pbuf.len); } #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) @@ -627,21 +594,23 @@ mbcs_decode(PyObject *self, PyObject *args) { - const char *data; - Py_ssize_t size, consumed; + Py_buffer pbuf; const char *errors = NULL; int final = 0; - PyObject *decoded; + Py_ssize_t consumed; + PyObject *decoded = NULL; - if (!PyArg_ParseTuple(args, "t#|zi:mbcs_decode", - &data, &size, &errors, &final)) + if (!PyArg_ParseTuple(args, "s*|zi:mbcs_decode", + &pbuf, &errors, &final)) return NULL; + consumed = pbuf.len; - decoded = PyUnicode_DecodeMBCSStateful( - data, size, errors, final ? NULL : &consumed); - if (!decoded) + decoded = PyUnicode_DecodeMBCSStateful(pbuf.buf, pbuf.len, errors, + final ? NULL : &consumed); + PyBuffer_Release(&pbuf); + if (decoded == NULL) return NULL; - return codec_tuple(decoded, final ? size : consumed); + return codec_tuple(decoded, consumed); } #endif /* MS_WINDOWS */ @@ -652,15 +621,21 @@ readbuffer_encode(PyObject *self, PyObject *args) { + Py_buffer pdata; const char *data; Py_ssize_t size; const char *errors = NULL; + PyObject *result; - if (!PyArg_ParseTuple(args, "s#|z:readbuffer_encode", - &data, &size, &errors)) + if (!PyArg_ParseTuple(args, "s*|z:readbuffer_encode", + &pdata, &errors)) return NULL; + data = pdata.buf; + size = pdata.len; - return codec_tuple(PyBytes_FromStringAndSize(data, size), size); + result = PyBytes_FromStringAndSize(data, size); + PyBuffer_Release(&pdata); + return codec_tuple(result, size); } static PyObject * Modified: python/branches/py3k/Modules/_ctypes/_ctypes.c ============================================================================== --- python/branches/py3k/Modules/_ctypes/_ctypes.c (original) +++ python/branches/py3k/Modules/_ctypes/_ctypes.c Wed Aug 13 17:53:07 2008 @@ -1050,10 +1050,10 @@ memcpy(self->b_ptr, ptr, size); - PyObject_ReleaseBuffer(value, &view); + PyBuffer_Release(&view); return 0; fail: - PyObject_ReleaseBuffer(value, &view); + PyBuffer_Release(&view); return -1; } @@ -2462,6 +2462,8 @@ if (view == NULL) return 0; view->buf = self->b_ptr; + view->obj = _self; + Py_INCREF(_self); view->len = self->b_size; view->readonly = 0; /* use default format character if not set */ Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Wed Aug 13 17:53:07 2008 @@ -357,7 +357,7 @@ static PyObject * fileio_readinto(PyFileIOObject *self, PyObject *args) { - char *ptr; + Py_buffer pbuf; Py_ssize_t n; if (self->fd < 0) @@ -365,13 +365,14 @@ if (!self->readable) return err_mode("reading"); - if (!PyArg_ParseTuple(args, "w#", &ptr, &n)) + if (!PyArg_ParseTuple(args, "w*", &pbuf)) return NULL; Py_BEGIN_ALLOW_THREADS errno = 0; - n = read(self->fd, ptr, n); + n = read(self->fd, pbuf.buf, pbuf.len); Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); if (n < 0) { if (errno == EAGAIN) Py_RETURN_NONE; @@ -489,22 +490,24 @@ static PyObject * fileio_write(PyFileIOObject *self, PyObject *args) { + Py_buffer pbuf; Py_ssize_t n; - char *ptr; if (self->fd < 0) return err_closed(); if (!self->writable) return err_mode("writing"); - if (!PyArg_ParseTuple(args, "s#", &ptr, &n)) + if (!PyArg_ParseTuple(args, "s*", &pbuf)) return NULL; Py_BEGIN_ALLOW_THREADS errno = 0; - n = write(self->fd, ptr, n); + n = write(self->fd, pbuf.buf, pbuf.len); Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); + if (n < 0) { if (errno == EAGAIN) Py_RETURN_NONE; Modified: python/branches/py3k/Modules/_hashopenssl.c ============================================================================== --- python/branches/py3k/Modules/_hashopenssl.c (original) +++ python/branches/py3k/Modules/_hashopenssl.c Wed Aug 13 17:53:07 2008 @@ -164,7 +164,7 @@ if ((viewp)->ndim > 1) { \ PyErr_SetString(PyExc_BufferError, \ "Buffer must be single dimension"); \ - PyObject_ReleaseBuffer((obj), (viewp)); \ + PyBuffer_Release((viewp)); \ return NULL; \ } \ } while(0); @@ -186,7 +186,7 @@ EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf, Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); - PyObject_ReleaseBuffer(obj, &view); + PyBuffer_Release(&view); Py_INCREF(Py_None); return Py_None; @@ -267,7 +267,7 @@ if (!PyArg_Parse(name_obj, "s", &nameStr)) { PyErr_SetString(PyExc_TypeError, "name must be a string"); if (data_obj) - PyObject_ReleaseBuffer(data_obj, &view); + PyBuffer_Release(&view); return -1; } @@ -275,7 +275,7 @@ if (!digest) { PyErr_SetString(PyExc_ValueError, "unknown hash function"); if (data_obj) - PyObject_ReleaseBuffer(data_obj, &view); + PyBuffer_Release(&view); return -1; } EVP_DigestInit(&self->ctx, digest); @@ -286,7 +286,7 @@ if (data_obj) { EVP_DigestUpdate(&self->ctx, (unsigned char*)view.buf, Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); - PyObject_ReleaseBuffer(data_obj, &view); + PyBuffer_Release(&view); } return 0; @@ -421,7 +421,7 @@ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); if (data_obj) - PyObject_ReleaseBuffer(data_obj, &view); + PyBuffer_Release(&view); return ret_obj; } @@ -455,7 +455,7 @@ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); \ \ if (data_obj) \ - PyObject_ReleaseBuffer(data_obj, &view); \ + PyBuffer_Release(&view); \ return ret_obj; \ } Modified: python/branches/py3k/Modules/_json.c ============================================================================== --- python/branches/py3k/Modules/_json.c (original) +++ python/branches/py3k/Modules/_json.c Wed Aug 13 17:53:07 2008 @@ -261,7 +261,7 @@ /* Pick up this chunk if it's not zero length */ if (next != end) { PyObject *strchunk; - if (PyBuffer_FillInfo(&info, &buf[end], next - end, 1, 0) < 0) { + if (PyBuffer_FillInfo(&info, NULL, &buf[end], next - end, 1, 0) < 0) { goto bail; } strchunk = PyMemoryView_FromMemory(&info); Modified: python/branches/py3k/Modules/_multiprocessing/connection.h ============================================================================== --- python/branches/py3k/Modules/_multiprocessing/connection.h (original) +++ python/branches/py3k/Modules/_multiprocessing/connection.h Wed Aug 13 17:53:07 2008 @@ -96,21 +96,26 @@ static PyObject * connection_sendbytes(ConnectionObject *self, PyObject *args) { + Py_buffer pbuffer; char *buffer; Py_ssize_t length, offset=0, size=PY_SSIZE_T_MIN; int res; - if (!PyArg_ParseTuple(args, F_RBUFFER "#|" F_PY_SSIZE_T F_PY_SSIZE_T, - &buffer, &length, &offset, &size)) + if (!PyArg_ParseTuple(args, F_RBUFFER "*|" F_PY_SSIZE_T F_PY_SSIZE_T, + &pbuffer, &offset, &size)) return NULL; + buffer = pbuffer.buf; + length = pbuffer.len; - CHECK_WRITABLE(self); + CHECK_WRITABLE(self); /* XXX release buffer in case of failure */ if (offset < 0) { + PyBuffer_Release(&pbuffer); PyErr_SetString(PyExc_ValueError, "offset is negative"); return NULL; } if (length < offset) { + PyBuffer_Release(&pbuffer); PyErr_SetString(PyExc_ValueError, "buffer length < offset"); return NULL; } @@ -119,10 +124,12 @@ size = length - offset; } else { if (size < 0) { + PyBuffer_Release(&pbuffer); PyErr_SetString(PyExc_ValueError, "size is negative"); return NULL; } if (offset + size > length) { + PyBuffer_Release(&pbuffer); PyErr_SetString(PyExc_ValueError, "buffer length < offset + size"); return NULL; @@ -131,6 +138,7 @@ res = conn_send_string(self, buffer + offset, size); + PyBuffer_Release(&pbuffer); if (res < 0) return mp_SetError(PyExc_IOError, res); @@ -187,21 +195,25 @@ char *freeme = NULL, *buffer = NULL; Py_ssize_t res, length, offset = 0; PyObject *result = NULL; + Py_buffer pbuf; - if (!PyArg_ParseTuple(args, "w#|" F_PY_SSIZE_T, - &buffer, &length, &offset)) + CHECK_READABLE(self); + + if (!PyArg_ParseTuple(args, "w*|" F_PY_SSIZE_T, + &pbuf, &offset)) return NULL; - CHECK_READABLE(self); + buffer = pbuf.buf; + length = pbuf.len; if (offset < 0) { PyErr_SetString(PyExc_ValueError, "negative offset"); - return NULL; + goto _error; } if (offset > length) { PyErr_SetString(PyExc_ValueError, "offset too large"); - return NULL; + goto _error; } res = conn_recv_string(self, buffer+offset, length-offset, @@ -231,11 +243,17 @@ PyErr_SetObject(BufferTooShort, result); Py_DECREF(result); } - return NULL; + goto _error; } } +_cleanup: + PyBuffer_Release(&pbuf); return result; + +_error: + result = NULL; + goto _cleanup; } /* Modified: python/branches/py3k/Modules/_sre.c ============================================================================== --- python/branches/py3k/Modules/_sre.c (original) +++ python/branches/py3k/Modules/_sre.c Wed Aug 13 17:53:07 2008 @@ -1704,7 +1704,7 @@ /* Release the buffer immediately --- possibly dangerous but doing something else would require some re-factoring */ - PyObject_ReleaseBuffer(string, &view); + PyBuffer_Release(&view); if (bytes < 0) { PyErr_SetString(PyExc_TypeError, "buffer has negative size"); Modified: python/branches/py3k/Modules/_struct.c ============================================================================== --- python/branches/py3k/Modules/_struct.c (original) +++ python/branches/py3k/Modules/_struct.c Wed Aug 13 17:53:07 2008 @@ -1567,11 +1567,11 @@ PyErr_Format(StructError, "unpack requires a bytes argument of length %zd", soself->s_size); - PyObject_ReleaseBuffer(input, &vbuf); + PyBuffer_Release(&vbuf); return NULL; } result = s_unpack_internal(soself, vbuf.buf); - PyObject_ReleaseBuffer(input, &vbuf); + PyBuffer_Release(&vbuf); return result; } @@ -1609,11 +1609,11 @@ PyErr_Format(StructError, "unpack_from requires a buffer of at least %zd bytes", soself->s_size); - PyObject_ReleaseBuffer(input, &vbuf); + PyBuffer_Release(&vbuf); return NULL; } result = s_unpack_internal(soself, (char*)vbuf.buf + offset); - PyObject_ReleaseBuffer(input, &vbuf); + PyBuffer_Release(&vbuf); return result; } Modified: python/branches/py3k/Modules/arraymodule.c ============================================================================== --- python/branches/py3k/Modules/arraymodule.c (original) +++ python/branches/py3k/Modules/arraymodule.c Wed Aug 13 17:53:07 2008 @@ -1820,6 +1820,8 @@ if (view==NULL) goto finish; view->buf = (void *)self->ob_item; + view->obj = (PyObject*)self; + Py_INCREF(self); if (view->buf == NULL) view->buf = (void *)emptybuf; view->len = (Py_SIZE(self)) * self->ob_descr->itemsize; Modified: python/branches/py3k/Modules/audioop.c ============================================================================== --- python/branches/py3k/Modules/audioop.c (original) +++ python/branches/py3k/Modules/audioop.c Wed Aug 13 17:53:07 2008 @@ -783,20 +783,24 @@ static PyObject * audioop_tomono(PyObject *self, PyObject *args) { + Py_buffer pcp; signed char *cp, *ncp; int len, size, val1 = 0, val2 = 0; double fac1, fac2, fval, maxval; PyObject *rv; int i; - if ( !PyArg_ParseTuple(args, "s#idd:tomono", - &cp, &len, &size, &fac1, &fac2 ) ) + if ( !PyArg_ParseTuple(args, "s*idd:tomono", + &pcp, &size, &fac1, &fac2 ) ) return 0; + cp = pcp.buf; + len = pcp.len; if ( size == 1 ) maxval = (double) 0x7f; else if ( size == 2 ) maxval = (double) 0x7fff; else if ( size == 4 ) maxval = (double) 0x7fffffff; else { + PyBuffer_Release(&pcp); PyErr_SetString(AudioopError, "Size should be 1, 2 or 4"); return 0; } @@ -822,6 +826,7 @@ else if ( size == 2 ) *SHORTP(ncp, i/2) = (short)val1; else if ( size == 4 ) *LONGP(ncp, i/2)= (Py_Int32)val1; } + PyBuffer_Release(&pcp); return rv; } Modified: python/branches/py3k/Modules/binascii.c ============================================================================== --- python/branches/py3k/Modules/binascii.c (original) +++ python/branches/py3k/Modules/binascii.c Wed Aug 13 17:53:07 2008 @@ -188,6 +188,7 @@ static PyObject * binascii_a2b_uu(PyObject *self, PyObject *args) { + Py_buffer pascii; unsigned char *ascii_data, *bin_data; int leftbits = 0; unsigned char this_ch; @@ -195,8 +196,10 @@ PyObject *rv; Py_ssize_t ascii_len, bin_len; - if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) ) + if ( !PyArg_ParseTuple(args, "y*:a2b_uu", &pascii) ) return NULL; + ascii_data = pascii.buf; + ascii_len = pascii.len; assert(ascii_len >= 0); @@ -205,8 +208,10 @@ ascii_len--; /* Allocate the buffer */ - if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) + if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) { + PyBuffer_Release(&pascii); return NULL; + } bin_data = (unsigned char *)PyBytes_AS_STRING(rv); for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) { @@ -258,6 +263,7 @@ return NULL; } } + PyBuffer_Release(&pascii); return rv; } @@ -266,6 +272,7 @@ static PyObject * binascii_b2a_uu(PyObject *self, PyObject *args) { + Py_buffer pbin; unsigned char *ascii_data, *bin_data; int leftbits = 0; unsigned char this_ch; @@ -273,17 +280,22 @@ PyObject *rv; Py_ssize_t bin_len; - if ( !PyArg_ParseTuple(args, "s#:b2a_uu", &bin_data, &bin_len) ) + if ( !PyArg_ParseTuple(args, "s*:b2a_uu", &pbin) ) return NULL; + bin_data = pbin.buf; + bin_len = pbin.len; if ( bin_len > 45 ) { /* The 45 is a limit that appears in all uuencode's */ PyErr_SetString(Error, "At most 45 bytes at once"); + PyBuffer_Release(&pbin); return NULL; } /* We're lazy and allocate to much (fixed up later) */ - if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2+2)) == NULL ) + if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2+2)) == NULL ) { + PyBuffer_Release(&pbin); return NULL; + } ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); /* Store the length */ @@ -312,6 +324,7 @@ Py_DECREF(rv); rv = NULL; } + PyBuffer_Release(&pbin); return rv; } @@ -346,6 +359,7 @@ static PyObject * binascii_a2b_base64(PyObject *self, PyObject *args) { + Py_buffer pascii; unsigned char *ascii_data, *bin_data; int leftbits = 0; unsigned char this_ch; @@ -354,19 +368,25 @@ Py_ssize_t ascii_len, bin_len; int quad_pos = 0; - if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) ) + if ( !PyArg_ParseTuple(args, "y*:a2b_base64", &pascii) ) return NULL; + ascii_data = pascii.buf; + ascii_len = pascii.len; assert(ascii_len >= 0); - if (ascii_len > PY_SSIZE_T_MAX - 3) + if (ascii_len > PY_SSIZE_T_MAX - 3) { + PyBuffer_Release(&pascii); return PyErr_NoMemory(); + } bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */ /* Allocate the buffer */ - if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) + if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) { + PyBuffer_Release(&pascii); return NULL; + } bin_data = (unsigned char *)PyBytes_AS_STRING(rv); bin_len = 0; @@ -419,6 +439,7 @@ } if (leftbits != 0) { + PyBuffer_Release(&pascii); PyErr_SetString(Error, "Incorrect padding"); Py_DECREF(rv); return NULL; @@ -438,6 +459,7 @@ Py_DECREF(rv); rv = PyBytes_FromStringAndSize("", 0); } + PyBuffer_Release(&pascii); return rv; } @@ -446,6 +468,7 @@ static PyObject * binascii_b2a_base64(PyObject *self, PyObject *args) { + Py_buffer pbuf; unsigned char *ascii_data, *bin_data; int leftbits = 0; unsigned char this_ch; @@ -453,21 +476,26 @@ PyObject *rv; Py_ssize_t bin_len; - if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) ) + if ( !PyArg_ParseTuple(args, "s*:b2a_base64", &pbuf) ) return NULL; + bin_data = pbuf.buf; + bin_len = pbuf.len; assert(bin_len >= 0); if ( bin_len > BASE64_MAXBIN ) { PyErr_SetString(Error, "Too much data for base64 line"); + PyBuffer_Release(&pbuf); return NULL; } /* We're lazy and allocate too much (fixed up later). "+3" leaves room for up to two pad characters and a trailing newline. Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */ - if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL ) + if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL ) { + PyBuffer_Release(&pbuf); return NULL; + } ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); for( ; bin_len > 0 ; bin_len--, bin_data++ ) { @@ -498,6 +526,7 @@ Py_DECREF(rv); rv = NULL; } + PyBuffer_Release(&pbuf); return rv; } @@ -581,22 +610,29 @@ static PyObject * binascii_rlecode_hqx(PyObject *self, PyObject *args) { + Py_buffer pbuf; unsigned char *in_data, *out_data; PyObject *rv; unsigned char ch; Py_ssize_t in, inend, len; - if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) ) + if ( !PyArg_ParseTuple(args, "s*:rlecode_hqx", &pbuf) ) return NULL; + in_data = pbuf.buf; + len = pbuf.len; assert(len >= 0); - if (len > PY_SSIZE_T_MAX / 2 - 2) + if (len > PY_SSIZE_T_MAX / 2 - 2) { + PyBuffer_Release(&pbuf); return PyErr_NoMemory(); + } /* Worst case: output is twice as big as input (fixed later) */ - if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) + if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) { + PyBuffer_Release(&pbuf); return NULL; + } out_data = (unsigned char *)PyBytes_AS_STRING(rv); for( in=0; in= 0); - if (len > PY_SSIZE_T_MAX / 2 - 2) + if (len > PY_SSIZE_T_MAX / 2 - 2) { + PyBuffer_Release(&pbin); return PyErr_NoMemory(); + } /* Allocate a buffer that is at least large enough */ - if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) + if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) { + PyBuffer_Release(&pbin); return NULL; + } ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); for( ; len > 0 ; len--, bin_data++ ) { @@ -678,6 +722,7 @@ Py_DECREF(rv); rv = NULL; } + PyBuffer_Release(&pbin); return rv; } @@ -686,26 +731,35 @@ static PyObject * binascii_rledecode_hqx(PyObject *self, PyObject *args) { + Py_buffer pin; unsigned char *in_data, *out_data; unsigned char in_byte, in_repeat; PyObject *rv; Py_ssize_t in_len, out_len, out_len_left; - if ( !PyArg_ParseTuple(args, "s#:rledecode_hqx", &in_data, &in_len) ) + if ( !PyArg_ParseTuple(args, "s*:rledecode_hqx", &pin) ) return NULL; + in_data = pin.buf; + in_len = pin.len; assert(in_len >= 0); /* Empty string is a special case */ - if ( in_len == 0 ) + if ( in_len == 0 ) { + PyBuffer_Release(&pin); return PyBytes_FromStringAndSize("", 0); - else if (in_len > PY_SSIZE_T_MAX / 2) + } + else if (in_len > PY_SSIZE_T_MAX / 2) { + PyBuffer_Release(&pin); return PyErr_NoMemory(); + } /* Allocate a buffer of reasonable size. Resized when needed */ out_len = in_len*2; - if ( (rv=PyBytes_FromStringAndSize(NULL, out_len)) == NULL ) + if ( (rv=PyBytes_FromStringAndSize(NULL, out_len)) == NULL ) { + PyBuffer_Release(&pin); return NULL; + } out_len_left = out_len; out_data = (unsigned char *)PyBytes_AS_STRING(rv); @@ -718,6 +772,7 @@ if ( --in_len < 0 ) { \ PyErr_SetString(Incomplete, ""); \ Py_DECREF(rv); \ + PyBuffer_Release(&pin); \ return NULL; \ } \ b = *in_data++; \ @@ -728,7 +783,7 @@ if ( --out_len_left < 0 ) { \ if ( out_len > PY_SSIZE_T_MAX / 2) return PyErr_NoMemory(); \ if (_PyBytes_Resize(&rv, 2*out_len) < 0) \ - { Py_DECREF(rv); return NULL; } \ + { Py_DECREF(rv); PyBuffer_Release(&pin); return NULL; } \ out_data = (unsigned char *)PyBytes_AS_STRING(rv) \ + out_len; \ out_len_left = out_len-1; \ @@ -783,6 +838,7 @@ Py_DECREF(rv); rv = NULL; } + PyBuffer_Release(&pin); return rv; } @@ -792,17 +848,21 @@ static PyObject * binascii_crc_hqx(PyObject *self, PyObject *args) { + Py_buffer pin; unsigned char *bin_data; unsigned int crc; Py_ssize_t len; - if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) ) + if ( !PyArg_ParseTuple(args, "s*i:crc_hqx", &pin, &crc) ) return NULL; + bin_data = pin.buf; + len = pin.len; while(len-- > 0) { crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++]; } + PyBuffer_Release(&pin); return Py_BuildValue("i", crc); } @@ -815,13 +875,17 @@ binascii_crc32(PyObject *self, PyObject *args) { unsigned int crc32val = 0; /* crc32(0L, Z_NULL, 0) */ + Py_buffer pbuf; Byte *buf; Py_ssize_t len; int signed_val; - if (!PyArg_ParseTuple(args, "s#|I:crc32", &buf, &len, &crc32val)) + if (!PyArg_ParseTuple(args, "s*|I:crc32", &pbuf, &crc32val)) return NULL; + buf = (Byte*)pbuf.buf; + len = pbuf.len; signed_val = crc32(crc32val, buf, len); + PyBuffer_Release(&pbuf); return PyLong_FromUnsignedLong(signed_val & 0xffffffffU); } #else /* USE_ZLIB_CRC32 */ @@ -946,13 +1010,16 @@ static PyObject * binascii_crc32(PyObject *self, PyObject *args) { /* By Jim Ahlstrom; All rights transferred to CNRI */ + Py_buffer pbin; unsigned char *bin_data; unsigned int crc = 0; /* initial value of CRC */ Py_ssize_t len; unsigned int result; - if ( !PyArg_ParseTuple(args, "s#|I:crc32", &bin_data, &len, &crc) ) + if ( !PyArg_ParseTuple(args, "s*|I:crc32", &pbin, &crc) ) return NULL; + bin_data = pbin.buf; + len = pbin.len; crc = ~ crc; while (len-- > 0) { @@ -961,6 +1028,7 @@ } result = (crc ^ 0xFFFFFFFF); + PyBuffer_Release(&pbuf); return PyLong_FromUnsignedLong(result & 0xffffffff); } #endif /* USE_ZLIB_CRC32 */ @@ -969,22 +1037,29 @@ static PyObject * binascii_hexlify(PyObject *self, PyObject *args) { + Py_buffer parg; char* argbuf; Py_ssize_t arglen; PyObject *retval; char* retbuf; Py_ssize_t i, j; - if (!PyArg_ParseTuple(args, "s#:b2a_hex", &argbuf, &arglen)) + if (!PyArg_ParseTuple(args, "s*:b2a_hex", &parg)) return NULL; + argbuf = parg.buf; + arglen = parg.len; assert(arglen >= 0); - if (arglen > PY_SSIZE_T_MAX / 2) + if (arglen > PY_SSIZE_T_MAX / 2) { + PyBuffer_Release(&parg); return PyErr_NoMemory(); + } retval = PyBytes_FromStringAndSize(NULL, arglen*2); - if (!retval) + if (!retval) { + PyBuffer_Release(&parg); return NULL; + } retbuf = PyBytes_AS_STRING(retval); /* make hex version of string, taken from shamodule.c */ @@ -997,6 +1072,7 @@ c = (c>9) ? c+'a'-10 : c + '0'; retbuf[j++] = c; } + PyBuffer_Release(&parg); return retval; } @@ -1024,14 +1100,17 @@ static PyObject * binascii_unhexlify(PyObject *self, PyObject *args) { + Py_buffer parg; char* argbuf; Py_ssize_t arglen; PyObject *retval; char* retbuf; Py_ssize_t i, j; - if (!PyArg_ParseTuple(args, "s#:a2b_hex", &argbuf, &arglen)) + if (!PyArg_ParseTuple(args, "s*:a2b_hex", &parg)) return NULL; + argbuf = parg.buf; + arglen = parg.len; assert(arglen >= 0); @@ -1040,13 +1119,16 @@ * raise an exception. */ if (arglen % 2) { + PyBuffer_Release(&parg); PyErr_SetString(Error, "Odd-length string"); return NULL; } retval = PyBytes_FromStringAndSize(NULL, (arglen/2)); - if (!retval) + if (!retval) { + PyBuffer_Release(&parg); return NULL; + } retbuf = PyBytes_AS_STRING(retval); for (i=j=0; i < arglen; i += 2) { @@ -1059,9 +1141,11 @@ } retbuf[j++] = (top << 4) + bot; } + PyBuffer_Release(&parg); return retval; finally: + PyBuffer_Release(&parg); Py_DECREF(retval); return NULL; } @@ -1094,15 +1178,18 @@ { Py_ssize_t in, out; char ch; + Py_buffer pdata; unsigned char *data, *odata; Py_ssize_t datalen = 0; PyObject *rv; static char *kwlist[] = {"data", "header", NULL}; int header = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", kwlist, &data, - &datalen, &header)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|i", kwlist, &pdata, + &header)) return NULL; + data = pdata.buf; + datalen = pdata.len; /* We allocate the output same size as input, this is overkill. * The previous implementation used calloc() so we'll zero out the @@ -1110,6 +1197,7 @@ */ odata = (unsigned char *) PyMem_Malloc(datalen); if (odata == NULL) { + PyBuffer_Release(&pdata); PyErr_NoMemory(); return NULL; } @@ -1160,9 +1248,11 @@ } } if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) { + PyBuffer_Release(&pdata); PyMem_Free(odata); return NULL; } + PyBuffer_Release(&pdata); PyMem_Free(odata); return rv; } @@ -1193,6 +1283,7 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs) { Py_ssize_t in, out; + Py_buffer pdata; unsigned char *data, *odata; Py_ssize_t datalen = 0, odatalen = 0; PyObject *rv; @@ -1206,9 +1297,11 @@ int crlf = 0; unsigned char *p; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iii", kwlist, &data, - &datalen, "etabs, &istext, &header)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|iii", kwlist, &pdata, + "etabs, &istext, &header)) return NULL; + data = pdata.buf; + datalen = pdata.len; /* See if this string is using CRLF line ends */ /* XXX: this function has the side effect of converting all of @@ -1286,6 +1379,7 @@ */ odata = (unsigned char *) PyMem_Malloc(odatalen); if (odata == NULL) { + PyBuffer_Release(&pdata); PyErr_NoMemory(); return NULL; } @@ -1360,9 +1454,11 @@ } } if ((rv = PyBytes_FromStringAndSize((char *)odata, out)) == NULL) { + PyBuffer_Release(&pdata); PyMem_Free(odata); return NULL; } + PyBuffer_Release(&pdata); PyMem_Free(odata); return rv; } Modified: python/branches/py3k/Modules/bz2module.c ============================================================================== --- python/branches/py3k/Modules/bz2module.c (original) +++ python/branches/py3k/Modules/bz2module.c Wed Aug 13 17:53:07 2008 @@ -691,12 +691,15 @@ BZ2File_write(BZ2FileObject *self, PyObject *args) { PyObject *ret = NULL; + Py_buffer pbuf; char *buf; int len; int bzerror; - if (!PyArg_ParseTuple(args, "y#:write", &buf, &len)) + if (!PyArg_ParseTuple(args, "y*:write", &pbuf)) return NULL; + buf = pbuf.buf; + len = pbuf.len; ACQUIRE_LOCK(self); switch (self->mode) { @@ -728,6 +731,7 @@ ret = Py_None; cleanup: + PyBuffer_Release(&pbuf); RELEASE_LOCK(self); return ret; } @@ -1353,6 +1357,7 @@ static PyObject * BZ2Comp_compress(BZ2CompObject *self, PyObject *args) { + Py_buffer pdata; char *data; int datasize; int bufsize = SMALLCHUNK; @@ -1361,11 +1366,15 @@ bz_stream *bzs = &self->bzs; int bzerror; - if (!PyArg_ParseTuple(args, "y#:compress", &data, &datasize)) + if (!PyArg_ParseTuple(args, "y*:compress", &pdata)) return NULL; + data = pdata.buf; + datasize = pdata.len; - if (datasize == 0) + if (datasize == 0) { + PyBuffer_Release(&pdata); return PyBytes_FromStringAndSize("", 0); + } ACQUIRE_LOCK(self); if (!self->running) { @@ -1412,10 +1421,12 @@ goto error; RELEASE_LOCK(self); + PyBuffer_Release(&pdata); return ret; error: RELEASE_LOCK(self); + PyBuffer_Release(&pdata); Py_XDECREF(ret); return NULL; } @@ -1642,6 +1653,7 @@ static PyObject * BZ2Decomp_decompress(BZ2DecompObject *self, PyObject *args) { + Py_buffer pdata; char *data; int datasize; int bufsize = SMALLCHUNK; @@ -1650,8 +1662,10 @@ bz_stream *bzs = &self->bzs; int bzerror; - if (!PyArg_ParseTuple(args, "y#:decompress", &data, &datasize)) + if (!PyArg_ParseTuple(args, "y*:decompress", &pdata)) return NULL; + data = pdata.buf; + datasize = pdata.len; ACQUIRE_LOCK(self); if (!self->running) { @@ -1711,10 +1725,12 @@ } RELEASE_LOCK(self); + PyBuffer_Release(&pdata); return ret; error: RELEASE_LOCK(self); + PyBuffer_Release(&pdata); Py_XDECREF(ret); return NULL; } @@ -1853,6 +1869,7 @@ bz2_compress(PyObject *self, PyObject *args, PyObject *kwargs) { int compresslevel=9; + Py_buffer pdata; char *data; int datasize; int bufsize; @@ -1862,14 +1879,17 @@ int bzerror; static char *kwlist[] = {"data", "compresslevel", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y#|i", - kwlist, &data, &datasize, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|i", + kwlist, &pdata, &compresslevel)) return NULL; + data = pdata.buf; + datasize = pdata.len; if (compresslevel < 1 || compresslevel > 9) { PyErr_SetString(PyExc_ValueError, "compresslevel must be between 1 and 9"); + PyBuffer_Release(&pdata); return NULL; } @@ -1878,8 +1898,10 @@ bufsize = datasize + (datasize/100+1) + 600; ret = PyBytes_FromStringAndSize(NULL, bufsize); - if (!ret) + if (!ret) { + PyBuffer_Release(&pdata); return NULL; + } memset(bzs, 0, sizeof(bz_stream)); @@ -1891,6 +1913,7 @@ bzerror = BZ2_bzCompressInit(bzs, compresslevel, 0, 0); if (bzerror != BZ_OK) { Util_CatchBZ2Error(bzerror); + PyBuffer_Release(&pdata); Py_DECREF(ret); return NULL; } @@ -1904,6 +1927,7 @@ } else if (bzerror != BZ_FINISH_OK) { BZ2_bzCompressEnd(bzs); Util_CatchBZ2Error(bzerror); + PyBuffer_Release(&pdata); Py_DECREF(ret); return NULL; } @@ -1911,6 +1935,7 @@ bufsize = Util_NewBufferSize(bufsize); if (_PyBytes_Resize(&ret, bufsize) < 0) { BZ2_bzCompressEnd(bzs); + PyBuffer_Release(&pdata); return NULL; } bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs); @@ -1925,6 +1950,7 @@ } BZ2_bzCompressEnd(bzs); + PyBuffer_Release(&pdata); return ret; } @@ -1938,6 +1964,7 @@ static PyObject * bz2_decompress(PyObject *self, PyObject *args) { + Py_buffer pdata; char *data; int datasize; int bufsize = SMALLCHUNK; @@ -1946,15 +1973,21 @@ bz_stream *bzs = &_bzs; int bzerror; - if (!PyArg_ParseTuple(args, "y#:decompress", &data, &datasize)) + if (!PyArg_ParseTuple(args, "y*:decompress", &pdata)) return NULL; + data = pdata.buf; + datasize = pdata.len; - if (datasize == 0) + if (datasize == 0) { + PyBuffer_Release(&pdata); return PyBytes_FromStringAndSize("", 0); + } ret = PyBytes_FromStringAndSize(NULL, bufsize); - if (!ret) + if (!ret) { + PyBuffer_Release(&pdata); return NULL; + } memset(bzs, 0, sizeof(bz_stream)); @@ -1967,6 +2000,7 @@ if (bzerror != BZ_OK) { Util_CatchBZ2Error(bzerror); Py_DECREF(ret); + PyBuffer_Release(&pdata); return NULL; } @@ -1979,6 +2013,7 @@ } else if (bzerror != BZ_OK) { BZ2_bzDecompressEnd(bzs); Util_CatchBZ2Error(bzerror); + PyBuffer_Release(&pdata); Py_DECREF(ret); return NULL; } @@ -1986,6 +2021,7 @@ BZ2_bzDecompressEnd(bzs); PyErr_SetString(PyExc_ValueError, "couldn't find end of stream"); + PyBuffer_Release(&pdata); Py_DECREF(ret); return NULL; } @@ -1993,6 +2029,7 @@ bufsize = Util_NewBufferSize(bufsize); if (_PyBytes_Resize(&ret, bufsize) < 0) { BZ2_bzDecompressEnd(bzs); + PyBuffer_Release(&pdata); return NULL; } bzs->next_out = BUF(ret) + BZS_TOTAL_OUT(bzs); @@ -2006,6 +2043,7 @@ } } BZ2_bzDecompressEnd(bzs); + PyBuffer_Release(&pdata); return ret; } Modified: python/branches/py3k/Modules/cjkcodecs/multibytecodec.c ============================================================================== --- python/branches/py3k/Modules/cjkcodecs/multibytecodec.c (original) +++ python/branches/py3k/Modules/cjkcodecs/multibytecodec.c Wed Aug 13 17:53:07 2008 @@ -608,18 +608,24 @@ MultibyteCodec_State state; MultibyteDecodeBuffer buf; PyObject *errorcb; + Py_buffer pdata; const char *data, *errors = NULL; Py_ssize_t datalen, finalsize; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|z:decode", - codeckwarglist, &data, &datalen, &errors)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|z:decode", + codeckwarglist, &pdata, &errors)) return NULL; + data = pdata.buf; + datalen = pdata.len; errorcb = internal_error_callback(errors); - if (errorcb == NULL) + if (errorcb == NULL) { + PyBuffer_Release(&pdata); return NULL; + } if (datalen == 0) { + PyBuffer_Release(&pdata); ERROR_DECREF(errorcb); return make_tuple(PyUnicode_FromUnicode(NULL, 0), 0); } @@ -659,11 +665,13 @@ if (PyUnicode_Resize(&buf.outobj, finalsize) == -1) goto errorexit; + PyBuffer_Release(&pdata); Py_XDECREF(buf.excobj); ERROR_DECREF(errorcb); return make_tuple(buf.outobj, datalen); errorexit: + PyBuffer_Release(&pdata); ERROR_DECREF(errorcb); Py_XDECREF(buf.excobj); Py_XDECREF(buf.outobj); Modified: python/branches/py3k/Modules/fcntlmodule.c ============================================================================== --- python/branches/py3k/Modules/fcntlmodule.c (original) +++ python/branches/py3k/Modules/fcntlmodule.c Wed Aug 13 17:53:07 2008 @@ -113,15 +113,18 @@ unsigned int code; int arg; int ret; + Py_buffer pstr; char *str; Py_ssize_t len; int mutate_arg = 1; char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */ - if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl", + if (PyArg_ParseTuple(args, "O&Iw*|i:ioctl", conv_descriptor, &fd, &code, - &str, &len, &mutate_arg)) { + &pstr, &mutate_arg)) { char *arg; + str = pstr.buf; + len = pstr.len; if (mutate_arg) { if (len <= IOCTL_BUFSZ) { @@ -135,6 +138,7 @@ } else { if (len > IOCTL_BUFSZ) { + PyBuffer_Release(&pstr); PyErr_SetString(PyExc_ValueError, "ioctl string arg too long"); return NULL; @@ -156,6 +160,7 @@ if (mutate_arg && (len < IOCTL_BUFSZ)) { memcpy(str, buf, len); } + PyBuffer_Release(&pstr); /* No further access to str below this point */ if (ret < 0) { PyErr_SetFromErrno(PyExc_IOError); return NULL; @@ -169,9 +174,12 @@ } PyErr_Clear(); - if (PyArg_ParseTuple(args, "O&Is#:ioctl", - conv_descriptor, &fd, &code, &str, &len)) { + if (PyArg_ParseTuple(args, "O&Is*:ioctl", + conv_descriptor, &fd, &code, &pstr)) { + str = pstr.buf; + len = pstr.len; if (len > IOCTL_BUFSZ) { + PyBuffer_Release(&pstr); PyErr_SetString(PyExc_ValueError, "ioctl string arg too long"); return NULL; @@ -182,9 +190,11 @@ ret = ioctl(fd, code, buf); Py_END_ALLOW_THREADS if (ret < 0) { + PyBuffer_Release(&pstr); PyErr_SetFromErrno(PyExc_IOError); return NULL; } + PyBuffer_Release(&pstr); return PyBytes_FromStringAndSize(buf, len); } Modified: python/branches/py3k/Modules/mmapmodule.c ============================================================================== --- python/branches/py3k/Modules/mmapmodule.c (original) +++ python/branches/py3k/Modules/mmapmodule.c Wed Aug 13 17:53:07 2008 @@ -651,7 +651,7 @@ mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags) { CHECK_VALID(-1); - if (PyBuffer_FillInfo(view, self->data, self->size, + if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size, (self->access == ACCESS_READ), flags) < 0) return -1; self->exports++; @@ -843,7 +843,7 @@ if (vbuf.len != slicelen) { PyErr_SetString(PyExc_IndexError, "mmap slice assignment is wrong size"); - PyObject_ReleaseBuffer(value, &vbuf); + PyBuffer_Release(&vbuf); return -1; } @@ -862,7 +862,7 @@ self->data[cur] = ((char *)vbuf.buf)[i]; } } - PyObject_ReleaseBuffer(value, &vbuf); + PyBuffer_Release(&vbuf); return 0; } else { Modified: python/branches/py3k/Modules/posixmodule.c ============================================================================== --- python/branches/py3k/Modules/posixmodule.c (original) +++ python/branches/py3k/Modules/posixmodule.c Wed Aug 13 17:53:07 2008 @@ -4894,15 +4894,16 @@ static PyObject * posix_write(PyObject *self, PyObject *args) { + Py_buffer pbuf; int fd; Py_ssize_t size; - char *buffer; - if (!PyArg_ParseTuple(args, "is#:write", &fd, &buffer, &size)) + if (!PyArg_ParseTuple(args, "is*:write", &fd, &pbuf)) return NULL; Py_BEGIN_ALLOW_THREADS - size = write(fd, buffer, (size_t)size); + size = write(fd, pbuf.buf, (size_t)pbuf.len); Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); if (size < 0) return posix_error(); return PyLong_FromSsize_t(size); Modified: python/branches/py3k/Modules/socketmodule.c ============================================================================== --- python/branches/py3k/Modules/socketmodule.c (original) +++ python/branches/py3k/Modules/socketmodule.c Wed Aug 13 17:53:07 2008 @@ -2251,15 +2251,19 @@ int recvlen = 0, flags = 0; ssize_t readlen; + Py_buffer pbuf; char *buf; int buflen; /* Get the buffer's memory */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recv_into", kwlist, - &buf, &buflen, &recvlen, &flags)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ii:recv_into", kwlist, + &pbuf, &recvlen, &flags)) return NULL; + buf = pbuf.buf; + buflen = pbuf.len; if (recvlen < 0) { + PyBuffer_Release(&pbuf); PyErr_SetString(PyExc_ValueError, "negative buffersize in recv_into"); return NULL; @@ -2271,6 +2275,7 @@ /* Check if the buffer is large enough */ if (buflen < recvlen) { + PyBuffer_Release(&pbuf); PyErr_SetString(PyExc_ValueError, "buffer too small for requested bytes"); return NULL; @@ -2280,9 +2285,11 @@ readlen = sock_recv_guts(s, buf, recvlen, flags); if (readlen < 0) { /* Return an error. */ + PyBuffer_Release(&pbuf); return NULL; } + PyBuffer_Release(&pbuf); /* Return the number of bytes read. Note that we do not do anything special here in the case that readlen < recvlen. */ return PyLong_FromSsize_t(readlen); @@ -2424,18 +2431,22 @@ int recvlen = 0, flags = 0; ssize_t readlen; + Py_buffer pbuf; char *buf; int buflen; PyObject *addr = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recvfrom_into", - kwlist, &buf, &buflen, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "w*|ii:recvfrom_into", + kwlist, &pbuf, &recvlen, &flags)) return NULL; + buf = pbuf.buf; + buflen = pbuf.len; assert(buf != 0 && buflen > 0); if (recvlen < 0) { + PyBuffer_Release(&pbuf); PyErr_SetString(PyExc_ValueError, "negative buffersize in recvfrom_into"); return NULL; @@ -2447,11 +2458,13 @@ readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr); if (readlen < 0) { + PyBuffer_Release(&pbuf); /* Return an error */ Py_XDECREF(addr); return NULL; } + PyBuffer_Release(&pbuf); /* Return the number of bytes read and the address. Note that we do not do anything special here in the case that readlen < recvlen. */ return Py_BuildValue("lN", readlen, addr); @@ -2470,12 +2483,17 @@ { char *buf; int len, n = -1, flags = 0, timeout; + Py_buffer pbuf; - if (!PyArg_ParseTuple(args, "y#|i:send", &buf, &len, &flags)) + if (!PyArg_ParseTuple(args, "y*|i:send", &pbuf, &flags)) return NULL; - if (!IS_SELECTABLE(s)) + if (!IS_SELECTABLE(s)) { + PyBuffer_Release(&pbuf); return select_error(); + } + buf = pbuf.buf; + len = pbuf.len; Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 1); @@ -2487,6 +2505,8 @@ #endif Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); + if (timeout == 1) { PyErr_SetString(socket_timeout, "timed out"); return NULL; @@ -2511,12 +2531,17 @@ { char *buf; int len, n = -1, flags = 0, timeout; + Py_buffer pbuf; - if (!PyArg_ParseTuple(args, "y#|i:sendall", &buf, &len, &flags)) + if (!PyArg_ParseTuple(args, "y*|i:sendall", &pbuf, &flags)) return NULL; + buf = pbuf.buf; + len = pbuf.len; - if (!IS_SELECTABLE(s)) + if (!IS_SELECTABLE(s)) { + PyBuffer_Release(&pbuf); return select_error(); + } Py_BEGIN_ALLOW_THREADS do { @@ -2535,6 +2560,7 @@ len -= n; } while (len > 0); Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); if (timeout == 1) { PyErr_SetString(socket_timeout, "timed out"); @@ -2561,24 +2587,32 @@ static PyObject * sock_sendto(PySocketSockObject *s, PyObject *args) { + Py_buffer pbuf; PyObject *addro; char *buf; + Py_ssize_t len; sock_addr_t addrbuf; - int addrlen, len, n = -1, flags, timeout; + int addrlen, n = -1, flags, timeout; flags = 0; - if (!PyArg_ParseTuple(args, "y#O:sendto", &buf, &len, &addro)) { + if (!PyArg_ParseTuple(args, "y*O:sendto", &pbuf, &addro)) { PyErr_Clear(); - if (!PyArg_ParseTuple(args, "y#iO:sendto", - &buf, &len, &flags, &addro)) + if (!PyArg_ParseTuple(args, "y*iO:sendto", + &pbuf, &flags, &addro)) return NULL; } + buf = pbuf.buf; + len = pbuf.len; - if (!IS_SELECTABLE(s)) + if (!IS_SELECTABLE(s)) { + PyBuffer_Release(&pbuf); return select_error(); + } - if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) + if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) { + PyBuffer_Release(&pbuf); return NULL; + } Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 1); @@ -2586,6 +2620,7 @@ n = sendto(s->sock_fd, buf, len, flags, SAS2SA(&addrbuf), addrlen); Py_END_ALLOW_THREADS + PyBuffer_Release(&pbuf); if (timeout == 1) { PyErr_SetString(socket_timeout, "timed out"); return NULL; Modified: python/branches/py3k/Modules/zlibmodule.c ============================================================================== --- python/branches/py3k/Modules/zlibmodule.c (original) +++ python/branches/py3k/Modules/zlibmodule.c Wed Aug 13 17:53:07 2008 @@ -118,18 +118,22 @@ PyZlib_compress(PyObject *self, PyObject *args) { PyObject *ReturnVal = NULL; + Py_buffer pinput; Byte *input, *output; int length, level=Z_DEFAULT_COMPRESSION, err; z_stream zst; /* require Python string object, optional 'level' arg */ - if (!PyArg_ParseTuple(args, "s#|i:compress", &input, &length, &level)) + if (!PyArg_ParseTuple(args, "s*|i:compress", &pinput, &level)) return NULL; + input = pinput.buf; + length = pinput.len; zst.avail_out = length + length/1000 + 12 + 1; output = (Byte*)malloc(zst.avail_out); if (output == NULL) { + PyBuffer_Release(&pinput); PyErr_SetString(PyExc_MemoryError, "Can't allocate memory to compress data"); return NULL; @@ -180,6 +184,7 @@ zlib_error(zst, err, "while finishing compression"); error: + PyBuffer_Release(&pinput); free(output); return ReturnVal; @@ -195,15 +200,18 @@ PyZlib_decompress(PyObject *self, PyObject *args) { PyObject *result_str; + Py_buffer pinput; Byte *input; int length, err; int wsize=DEF_WBITS; Py_ssize_t r_strlen=DEFAULTALLOC; z_stream zst; - if (!PyArg_ParseTuple(args, "s#|in:decompress", - &input, &length, &wsize, &r_strlen)) + if (!PyArg_ParseTuple(args, "s*|in:decompress", + &pinput, &wsize, &r_strlen)) return NULL; + input = pinput.buf; + length = pinput.len; if (r_strlen <= 0) r_strlen = 1; @@ -211,8 +219,10 @@ zst.avail_in = length; zst.avail_out = r_strlen; - if (!(result_str = PyByteArray_FromStringAndSize(NULL, r_strlen))) + if (!(result_str = PyByteArray_FromStringAndSize(NULL, r_strlen))) { + PyBuffer_Release(&pinput); return NULL; + } zst.zalloc = (alloc_func)NULL; zst.zfree = (free_func)Z_NULL; @@ -281,9 +291,11 @@ if (PyByteArray_Resize(result_str, zst.total_out) < 0) goto error; + PyBuffer_Release(&pinput); return result_str; error: + PyBuffer_Release(&pinput); Py_XDECREF(result_str); return NULL; } @@ -396,14 +408,19 @@ { int err, inplen, length = DEFAULTALLOC; PyObject *RetVal; + Py_buffer pinput; Byte *input; unsigned long start_total_out; - if (!PyArg_ParseTuple(args, "s#:compress", &input, &inplen)) + if (!PyArg_ParseTuple(args, "s*:compress", &pinput)) return NULL; + input = pinput.buf; + inplen = pinput.len; - if (!(RetVal = PyByteArray_FromStringAndSize(NULL, length))) + if (!(RetVal = PyByteArray_FromStringAndSize(NULL, length))) { + PyBuffer_Release(&pinput); return NULL; + } ENTER_ZLIB @@ -452,6 +469,7 @@ error: LEAVE_ZLIB + PyBuffer_Release(&pinput); return RetVal; } @@ -472,13 +490,17 @@ int err, inplen, old_length, length = DEFAULTALLOC; int max_length = 0; PyObject *RetVal; + Py_buffer pinput; Byte *input; unsigned long start_total_out; - if (!PyArg_ParseTuple(args, "s#|i:decompress", &input, - &inplen, &max_length)) + if (!PyArg_ParseTuple(args, "s*|i:decompress", &pinput, + &max_length)) return NULL; + input = pinput.buf; + inplen = pinput.len; if (max_length < 0) { + PyBuffer_Release(&pinput); PyErr_SetString(PyExc_ValueError, "max_length must be greater than zero"); return NULL; @@ -487,8 +509,10 @@ /* limit amount of data allocated to max_length */ if (max_length && length > max_length) length = max_length; - if (!(RetVal = PyByteArray_FromStringAndSize(NULL, length))) + if (!(RetVal = PyByteArray_FromStringAndSize(NULL, length))) { + PyBuffer_Release(&pinput); return NULL; + } ENTER_ZLIB @@ -577,7 +601,7 @@ error: LEAVE_ZLIB - + PyBuffer_Release(&pinput); return RetVal; } @@ -916,12 +940,13 @@ PyZlib_crc32(PyObject *self, PyObject *args) { unsigned int crc32val = 0; /* crc32(0L, Z_NULL, 0) */ - Byte *buf; - int len, signed_val; + Py_buffer pbuf; + int signed_val; - if (!PyArg_ParseTuple(args, "s#|I:crc32", &buf, &len, &crc32val)) + if (!PyArg_ParseTuple(args, "s*|I:crc32", &pbuf, &crc32val)) return NULL; - signed_val = crc32(crc32val, buf, len); + signed_val = crc32(crc32val, pbuf.buf, pbuf.len); + PyBuffer_Release(&pbuf); return PyLong_FromUnsignedLong(signed_val & 0xffffffffU); } Modified: python/branches/py3k/Objects/abstract.c ============================================================================== --- python/branches/py3k/Objects/abstract.c (original) +++ python/branches/py3k/Objects/abstract.c Wed Aug 13 17:53:07 2008 @@ -349,16 +349,6 @@ return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags); } -void -PyObject_ReleaseBuffer(PyObject *obj, Py_buffer *view) -{ - if (obj->ob_type->tp_as_buffer != NULL && - obj->ob_type->tp_as_buffer->bf_releasebuffer != NULL) { - (*(obj->ob_type->tp_as_buffer->bf_releasebuffer))(obj, view); - } -} - - static int _IsFortranContiguous(Py_buffer *view) { @@ -590,15 +580,15 @@ if (PyObject_GetBuffer(dest, &view_dest, PyBUF_FULL) != 0) return -1; if (PyObject_GetBuffer(src, &view_src, PyBUF_FULL_RO) != 0) { - PyObject_ReleaseBuffer(dest, &view_dest); + PyBuffer_Release(&view_dest); return -1; } if (view_dest.len < view_src.len) { PyErr_SetString(PyExc_BufferError, "destination is too small to receive data from source"); - PyObject_ReleaseBuffer(dest, &view_dest); - PyObject_ReleaseBuffer(src, &view_src); + PyBuffer_Release(&view_dest); + PyBuffer_Release(&view_src); return -1; } @@ -608,8 +598,8 @@ PyBuffer_IsContiguous(&view_src, 'F'))) { /* simplest copy is all that is needed */ memcpy(view_dest.buf, view_src.buf, view_src.len); - PyObject_ReleaseBuffer(dest, &view_dest); - PyObject_ReleaseBuffer(src, &view_src); + PyBuffer_Release(&view_dest); + PyBuffer_Release(&view_src); return 0; } @@ -619,8 +609,8 @@ indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim); if (indices == NULL) { PyErr_NoMemory(); - PyObject_ReleaseBuffer(dest, &view_dest); - PyObject_ReleaseBuffer(src, &view_src); + PyBuffer_Release(&view_dest); + PyBuffer_Release(&view_src); return -1; } for (k=0; kobj = obj; view->buf = buf; view->len = len; view->readonly = readonly; @@ -698,6 +689,17 @@ return 0; } +void +PyBuffer_Release(Py_buffer *view) +{ + PyObject *obj = view->obj; + if (!obj || !Py_TYPE(obj)->tp_as_buffer || !Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer) + /* Unmanaged buffer */ + return; + Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view); + +} + PyObject * PyObject_Format(PyObject *obj, PyObject *format_spec) { Modified: python/branches/py3k/Objects/bytearrayobject.c ============================================================================== --- python/branches/py3k/Objects/bytearrayobject.c (original) +++ python/branches/py3k/Objects/bytearrayobject.c Wed Aug 13 17:53:07 2008 @@ -69,7 +69,7 @@ ptr = ""; else ptr = obj->ob_bytes; - ret = PyBuffer_FillInfo(view, ptr, Py_SIZE(obj), 0, flags); + ret = PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags); if (ret >= 0) { obj->ob_exports++; } @@ -248,9 +248,9 @@ done: if (va.len != -1) - PyObject_ReleaseBuffer(a, &va); + PyBuffer_Release(&va); if (vb.len != -1) - PyObject_ReleaseBuffer(b, &vb); + PyBuffer_Release(&vb); return (PyObject *)result; } @@ -278,7 +278,7 @@ mysize = Py_SIZE(self); size = mysize + vo.len; if (size < 0) { - PyObject_ReleaseBuffer(other, &vo); + PyBuffer_Release(&vo); return PyErr_NoMemory(); } if (size < self->ob_alloc) { @@ -286,11 +286,11 @@ self->ob_bytes[Py_SIZE(self)] = '\0'; /* Trailing null byte */ } else if (PyByteArray_Resize((PyObject *)self, size) < 0) { - PyObject_ReleaseBuffer(other, &vo); + PyBuffer_Release(&vo); return NULL; } memcpy(self->ob_bytes + mysize, vo.buf, vo.len); - PyObject_ReleaseBuffer(other, &vo); + PyBuffer_Release(&vo); Py_INCREF(self); return (PyObject *)self; } @@ -501,7 +501,7 @@ finish: if (vbytes.len != -1) - PyObject_ReleaseBuffer(values, &vbytes); + PyBuffer_Release(&vbytes); return res; } @@ -767,10 +767,10 @@ if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail; if (PyBuffer_ToContiguous(self->ob_bytes, &view, size, 'C') < 0) goto fail; - PyObject_ReleaseBuffer(arg, &view); + PyBuffer_Release(&view); return 0; fail: - PyObject_ReleaseBuffer(arg, &view); + PyBuffer_Release(&view); return -1; } @@ -954,7 +954,7 @@ other_size = _getbuffer(other, &other_bytes); if (other_size < 0) { PyErr_Clear(); - PyObject_ReleaseBuffer(self, &self_bytes); + PyBuffer_Release(&self_bytes); Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -989,8 +989,8 @@ } res = cmp ? Py_True : Py_False; - PyObject_ReleaseBuffer(self, &self_bytes); - PyObject_ReleaseBuffer(other, &other_bytes); + PyBuffer_Release(&self_bytes); + PyBuffer_Release(&other_bytes); Py_INCREF(res); return res; } @@ -998,6 +998,11 @@ static void bytes_dealloc(PyByteArrayObject *self) { + if (self->ob_exports > 0) { + PyErr_SetString(PyExc_SystemError, + "deallocated bytearray object has exported buffers"); + PyErr_Print(); + } if (self->ob_bytes != 0) { PyMem_Free(self->ob_bytes); } @@ -1065,7 +1070,7 @@ res = stringlib_rfind_slice( PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), subbuf.buf, subbuf.len, start, end); - PyObject_ReleaseBuffer(subobj, &subbuf); + PyBuffer_Release(&subbuf); return res; } @@ -1115,7 +1120,7 @@ count_obj = PyLong_FromSsize_t( stringlib_count(str + start, end - start, vsub.buf, vsub.len) ); - PyObject_ReleaseBuffer(sub_obj, &vsub); + PyBuffer_Release(&vsub); return count_obj; } @@ -1191,7 +1196,7 @@ return -1; pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self), varg.buf, varg.len, 0); - PyObject_ReleaseBuffer(arg, &varg); + PyBuffer_Release(&varg); return pos >= 0; } if (ival < 0 || ival >= 256) { @@ -1241,7 +1246,7 @@ rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len); done: - PyObject_ReleaseBuffer(substr, &vsubstr); + PyBuffer_Release(&vsubstr); return rv; } @@ -1421,9 +1426,9 @@ PyByteArray_Resize(result, output - output_start); done: - PyObject_ReleaseBuffer(tableobj, &vtable); + PyBuffer_Release(&vtable); if (delobj != NULL) - PyObject_ReleaseBuffer(delobj, &vdel); + PyBuffer_Release(&vdel); return result; } @@ -2042,7 +2047,7 @@ if (_getbuffer(from, &vfrom) < 0) return NULL; if (_getbuffer(to, &vto) < 0) { - PyObject_ReleaseBuffer(from, &vfrom); + PyBuffer_Release(&vfrom); return NULL; } @@ -2050,8 +2055,8 @@ vfrom.buf, vfrom.len, vto.buf, vto.len, count); - PyObject_ReleaseBuffer(from, &vfrom); - PyObject_ReleaseBuffer(to, &vto); + PyBuffer_Release(&vfrom); + PyBuffer_Release(&vto); return res; } @@ -2207,7 +2212,7 @@ if (n == 0) { PyErr_SetString(PyExc_ValueError, "empty separator"); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } if (n == 1) @@ -2215,7 +2220,7 @@ list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) { - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } @@ -2243,12 +2248,12 @@ #endif SPLIT_ADD(s, i, len); FIX_PREALLOC_SIZE(list); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return list; onError: Py_DECREF(list); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } @@ -2439,7 +2444,7 @@ if (n == 0) { PyErr_SetString(PyExc_ValueError, "empty separator"); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } else if (n == 1) @@ -2447,7 +2452,7 @@ list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) { - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } @@ -2468,12 +2473,12 @@ FIX_PREALLOC_SIZE(list); if (PyList_Reverse(list) < 0) goto onError; - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return list; onError: Py_DECREF(list); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } @@ -2749,7 +2754,7 @@ else right = rstrip_helper(myptr, mysize, argptr, argsize); if (arg != Py_None) - PyObject_ReleaseBuffer(arg, &varg); + PyBuffer_Release(&varg); return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left); } @@ -2783,7 +2788,7 @@ left = lstrip_helper(myptr, mysize, argptr, argsize); right = mysize; if (arg != Py_None) - PyObject_ReleaseBuffer(arg, &varg); + PyBuffer_Release(&varg); return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left); } @@ -2817,7 +2822,7 @@ left = 0; right = rstrip_helper(myptr, mysize, argptr, argsize); if (arg != Py_None) - PyObject_ReleaseBuffer(arg, &varg); + PyBuffer_Release(&varg); return PyByteArray_FromStringAndSize(self->ob_bytes + left, right - left); } Modified: python/branches/py3k/Objects/bytesobject.c ============================================================================== --- python/branches/py3k/Objects/bytesobject.c (original) +++ python/branches/py3k/Objects/bytesobject.c Wed Aug 13 17:53:07 2008 @@ -710,9 +710,9 @@ done: if (va.len != -1) - PyObject_ReleaseBuffer(a, &va); + PyBuffer_Release(&va); if (vb.len != -1) - PyObject_ReleaseBuffer(b, &vb); + PyBuffer_Release(&vb); return result; } @@ -781,7 +781,7 @@ return -1; pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self), varg.buf, varg.len, 0); - PyObject_ReleaseBuffer(arg, &varg); + PyBuffer_Release(&varg); return pos >= 0; } if (ival < 0 || ival >= 256) { @@ -964,7 +964,7 @@ static int string_buffer_getbuffer(PyBytesObject *self, Py_buffer *view, int flags) { - return PyBuffer_FillInfo(view, (void *)self->ob_sval, Py_SIZE(self), + return PyBuffer_FillInfo(view, (PyObject*)self, (void *)self->ob_sval, Py_SIZE(self), 1, flags); } @@ -1160,7 +1160,7 @@ if (n == 0) { PyErr_SetString(PyExc_ValueError, "empty separator"); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } else if (n == 1) @@ -1168,7 +1168,7 @@ list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) { - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } @@ -1196,12 +1196,12 @@ #endif SPLIT_ADD(s, i, len); FIX_PREALLOC_SIZE(list); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return list; onError: Py_DECREF(list); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } @@ -1376,7 +1376,7 @@ if (n == 0) { PyErr_SetString(PyExc_ValueError, "empty separator"); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } else if (n == 1) @@ -1384,7 +1384,7 @@ list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) { - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } @@ -1406,12 +1406,12 @@ FIX_PREALLOC_SIZE(list); if (PyList_Reverse(list) < 0) goto onError; - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return list; onError: Py_DECREF(list); - PyObject_ReleaseBuffer(subobj, &vsub); + PyBuffer_Release(&vsub); return NULL; } @@ -1690,7 +1690,7 @@ j++; } - PyObject_ReleaseBuffer(sepobj, &vsep); + PyBuffer_Release(&vsep); if (i == 0 && j == len && PyBytes_CheckExact(self)) { Py_INCREF(self); @@ -2945,11 +2945,11 @@ if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval, &view, view.len, 'C') < 0) goto fail; - PyObject_ReleaseBuffer(x, &view); + PyBuffer_Release(&view); return new; fail: Py_XDECREF(new); - PyObject_ReleaseBuffer(x, &view); + PyBuffer_Release(&view); return NULL; } Modified: python/branches/py3k/Objects/memoryobject.c ============================================================================== --- python/branches/py3k/Objects/memoryobject.c (original) +++ python/branches/py3k/Objects/memoryobject.c Wed Aug 13 17:53:07 2008 @@ -6,19 +6,21 @@ static int memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) { - if (view != NULL) + if (view != NULL) { + if (self->view.obj) + Py_INCREF(self->view.obj); *view = self->view; - if (self->base == NULL) + } + if (self->view.obj == NULL) return 0; - return self->base->ob_type->tp_as_buffer->bf_getbuffer(self->base, NULL, + return self->view.obj->ob_type->tp_as_buffer->bf_getbuffer(self->base, NULL, PyBUF_FULL); } static void memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view) { - if (self->base != NULL) - PyObject_ReleaseBuffer(self->base, NULL); + PyBuffer_Release(&self->view); } PyDoc_STRVAR(memory_doc, @@ -36,6 +38,8 @@ if (mview == NULL) return NULL; mview->base = NULL; mview->view = *info; + if (info->obj) + Py_INCREF(mview->view.obj); return (PyObject *)mview; } @@ -256,7 +260,7 @@ } bytes = PyByteArray_FromStringAndSize(NULL, view->len); if (bytes == NULL) { - PyObject_ReleaseBuffer(obj, view); + PyBuffer_Release(view); return NULL; } dest = PyByteArray_AS_STRING(bytes); @@ -271,7 +275,7 @@ else { if (_indirect_copy_nd(dest, view, fort) < 0) { Py_DECREF(bytes); - PyObject_ReleaseBuffer(obj, view); + PyBuffer_Release(view); return NULL; } } @@ -281,12 +285,12 @@ mem->base = PyTuple_Pack(2, obj, bytes); Py_DECREF(bytes); if (mem->base == NULL) { - PyObject_ReleaseBuffer(obj, view); + PyBuffer_Release(view); return NULL; } } else { - PyObject_ReleaseBuffer(obj, view); + PyBuffer_Release(view); /* steal the reference */ mem->base = bytes; } @@ -407,7 +411,7 @@ static void memory_dealloc(PyMemoryViewObject *self) { - if (self->base != NULL) { + if (self->view.obj != NULL) { if (PyTuple_Check(self->base)) { /* Special case when first element is generic object with buffer interface and the second element is a @@ -424,11 +428,10 @@ be "locked" and was locked and will be unlocked again after this call. */ - PyObject_ReleaseBuffer(PyTuple_GET_ITEM(self->base,0), - &(self->view)); + PyBuffer_Release(&(self->view)); } else { - PyObject_ReleaseBuffer(self->base, &(self->view)); + PyBuffer_Release(&(self->view)); } Py_CLEAR(self->base); } @@ -453,7 +456,7 @@ res = PyByteArray_FromStringAndSize(NULL, view.len); PyBuffer_ToContiguous(PyByteArray_AS_STRING(res), &view, view.len, 'C'); - PyObject_ReleaseBuffer((PyObject *)self, &view); + PyBuffer_Release(&view); return res; } @@ -466,7 +469,7 @@ if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0) return -1; - PyObject_ReleaseBuffer((PyObject *)self, &view); + PyBuffer_Release(&view); return view.len; } Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Wed Aug 13 17:53:07 2008 @@ -1198,7 +1198,7 @@ /* Decode via the codec registry */ buffer = NULL; - if (PyBuffer_FillInfo(&info, (void *)s, size, 1, PyBUF_SIMPLE) < 0) + if (PyBuffer_FillInfo(&info, NULL, (void *)s, size, 1, PyBUF_SIMPLE) < 0) goto onError; buffer = PyMemoryView_FromMemory(&info); if (buffer == NULL) Modified: python/branches/py3k/PC/winreg.c ============================================================================== --- python/branches/py3k/PC/winreg.c (original) +++ python/branches/py3k/PC/winreg.c Wed Aug 13 17:53:07 2008 @@ -814,13 +814,13 @@ *retDataBuf = (BYTE *)PyMem_NEW(char, view.len); if (*retDataBuf==NULL){ - PyObject_ReleaseBuffer(value, &view); + PyBuffer_Release(&view); PyErr_NoMemory(); return FALSE; } *retDataSize = view.len; memcpy(*retDataBuf, view.buf, view.len); - PyObject_ReleaseBuffer(value, &view); + PyBuffer_Release(&view); } break; } Modified: python/branches/py3k/Python/getargs.c ============================================================================== --- python/branches/py3k/Python/getargs.c (original) +++ python/branches/py3k/Python/getargs.c Wed Aug 13 17:53:07 2008 @@ -44,6 +44,7 @@ static char *convertsimple(PyObject *, const char **, va_list *, int, char *, size_t, PyObject **); static Py_ssize_t convertbuffer(PyObject *, void **p, char **); +static int getbuffer(PyObject *, Py_buffer *, char**); static int vgetargskeywords(PyObject *, PyObject *, const char *, char **, va_list *, int); @@ -789,7 +790,25 @@ need to be cleaned up! */ case 's': {/* text string */ - if (*format == '#') { + if (*format == '*') { + Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); + + if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + PyBuffer_FillInfo(p, arg, + PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), + 1, 0); + } + else { /* any buffer-like object */ + char *buf; + if (getbuffer(arg, p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + } + format++; + } else if (*format == '#') { void **p = (void **)va_arg(*p_va, char **); FETCH_SIZE; @@ -832,10 +851,17 @@ case 'y': {/* any buffer-like object, but not PyUnicode */ void **p = (void **)va_arg(*p_va, char **); char *buf; - Py_ssize_t count = convertbuffer(arg, p, &buf); + Py_ssize_t count; + if (*format == '*') { + if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + format++; + break; + } + count = convertbuffer(arg, p, &buf); if (count < 0) return converterr(buf, arg, msgbuf, bufsize); - if (*format == '#') { + else if (*format == '#') { FETCH_SIZE; STORE_SIZE(count); format++; @@ -844,7 +870,27 @@ } case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */ - if (*format == '#') { /* any buffer-like object */ + if (*format == '*') { + Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); + + if (arg == Py_None) + PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + PyBuffer_FillInfo(p, arg, + PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), + 1, 0); + } + else { /* any buffer-like object */ + char *buf; + if (getbuffer(arg, p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + } + format++; + } else if (*format == '#') { /* any buffer-like object */ void **p = (void **)va_arg(*p_va, char **); FETCH_SIZE; @@ -1189,6 +1235,26 @@ int temp=-1; Py_buffer view; + if (pb && pb->bf_releasebuffer && *format != '*') + /* Buffer must be released, yet caller does not use + the Py_buffer protocol. */ + return converterr("pinned buffer", arg, msgbuf, bufsize); + + + if (pb && pb->bf_getbuffer && *format == '*') { + /* Caller is interested in Py_buffer, and the object + supports it directly. */ + format++; + if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + PyErr_Clear(); + return converterr("read-write buffer", arg, msgbuf, bufsize); + } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) + return converterr("contiguous buffer", arg, msgbuf, bufsize); + break; + } + + /* Here we have processed w*, only w and w# remain. */ if (pb == NULL || pb->bf_getbuffer == NULL || ((temp = (*pb->bf_getbuffer)(arg, &view, @@ -1209,8 +1275,6 @@ STORE_SIZE(count); format++; } - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(arg, &view); break; } @@ -1237,10 +1301,11 @@ count = view.len; *p = view.buf; - /* XXX : shouldn't really release buffer, but it should be O.K. - */ - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(arg, &view); + if (pb->bf_releasebuffer) + return converterr( + "string or pinned buffer", + arg, msgbuf, bufsize); + if (count < 0) return converterr("(unspecified)", arg, msgbuf, bufsize); { @@ -1269,7 +1334,8 @@ *errmsg = NULL; *p = NULL; if (pb == NULL || - pb->bf_getbuffer == NULL) { + pb->bf_getbuffer == NULL || + pb->bf_releasebuffer != NULL) { *errmsg = "bytes or read-only buffer"; return -1; } @@ -1285,6 +1351,35 @@ return count; } +/* XXX for 3.x, getbuffer and convertbuffer can probably + be merged again. */ +static int +getbuffer(PyObject *arg, Py_buffer *view, char**errmsg) +{ + void *buf; + Py_ssize_t count; + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + if (pb == NULL) { + *errmsg = "string or buffer"; + return -1; + } + if (pb->bf_getbuffer) { + if (pb->bf_getbuffer(arg, view, 0) < 0) + return -1; + if (!PyBuffer_IsContiguous(view, 'C')) { + *errmsg = "contiguous buffer"; + return -1; + } + return 0; + } + + count = convertbuffer(arg, &buf, errmsg); + if (count < 0) + return count; + PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); + return 0; +} + /* Support for keyword arguments donated by Geoff Philbrick */ @@ -1624,6 +1719,8 @@ else (void) va_arg(*p_va, int *); format++; + } else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') { + format++; } break; } Modified: python/branches/py3k/Python/marshal.c ============================================================================== --- python/branches/py3k/Python/marshal.c (original) +++ python/branches/py3k/Python/marshal.c Wed Aug 13 17:53:07 2008 @@ -1168,11 +1168,14 @@ marshal_loads(PyObject *self, PyObject *args) { RFILE rf; + Py_buffer p; char *s; Py_ssize_t n; PyObject* result; - if (!PyArg_ParseTuple(args, "s#:loads", &s, &n)) + if (!PyArg_ParseTuple(args, "s*:loads", &p)) return NULL; + s = p.buf; + n = p.len; rf.fp = NULL; rf.ptr = s; rf.end = s + n; @@ -1180,6 +1183,7 @@ rf.depth = 0; result = read_object(&rf); Py_DECREF(rf.strings); + PyBuffer_Release(&p); return result; } From python-3000-checkins at python.org Thu Aug 14 03:40:45 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Thu, 14 Aug 2008 03:40:45 +0200 (CEST) Subject: [Python-3000-checkins] r65664 - in python/branches/py3k/PC/VC6: _bsddb.dsp _sqlite3.dsp python.dsp pythoncore.dsp readme.txt Message-ID: <20080814014045.B2C9C1E4008@bag.python.org> Author: hirokazu.yamamoto Date: Thu Aug 14 03:40:45 2008 New Revision: 65664 Log: Issue #2065: VC6 related fix. - PC/VC6/_bsddb.dsp: removed '/nodefaultlib:"msvcrt"' to fix linker error. - PC/VC6/_sqlite3.dsp: /D "MODULE_NAME=\"sqlite3\"" caused extra leading space like #define MODULE_NAME " sqlite3" so uses /D MODULE_NAME=\"sqlite3\" instead. - PC/VC6/python.dsp: changed the way of modifying stack size Modified: python/branches/py3k/PC/VC6/_bsddb.dsp python/branches/py3k/PC/VC6/_sqlite3.dsp python/branches/py3k/PC/VC6/python.dsp python/branches/py3k/PC/VC6/pythoncore.dsp python/branches/py3k/PC/VC6/readme.txt Modified: python/branches/py3k/PC/VC6/_bsddb.dsp ============================================================================== --- python/branches/py3k/PC/VC6/_bsddb.dsp (original) +++ python/branches/py3k/PC/VC6/_bsddb.dsp Thu Aug 14 03:40:45 2008 @@ -54,7 +54,7 @@ # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 user32.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\..\..\db-4.4.20\build_win32\Release\libdb44s.lib /nologo /base:"0x1e180000" /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"msvcrt" /out:"./_bsddb.pyd" +# ADD LINK32 user32.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\..\..\db-4.4.20\build_win32\Release\libdb44s.lib /nologo /base:"0x1e180000" /subsystem:windows /dll /debug /machine:I386 /out:"./_bsddb.pyd" # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "_bsddb - Win32 Debug" Modified: python/branches/py3k/PC/VC6/_sqlite3.dsp ============================================================================== --- python/branches/py3k/PC/VC6/_sqlite3.dsp (original) +++ python/branches/py3k/PC/VC6/_sqlite3.dsp Thu Aug 14 03:40:45 2008 @@ -44,7 +44,7 @@ # PROP Target_Dir "" F90=df.exe # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\..\Include" /I ".." /I "..\..\..\sqlite-source-3.3.4" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "MODULE_NAME=\"sqlite3\"" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\..\Include" /I ".." /I "..\..\..\sqlite-source-3.3.4" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D MODULE_NAME=\"sqlite3\" /YX /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" @@ -72,7 +72,7 @@ # PROP Target_Dir "" F90=df.exe # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\Include" /I ".." /I "..\..\..\sqlite-source-3.3.4" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "MODULE_NAME=\"sqlite3\"" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\Include" /I ".." /I "..\..\..\sqlite-source-3.3.4" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D MODULE_NAME=\"sqlite3\" /YX /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" Modified: python/branches/py3k/PC/VC6/python.dsp ============================================================================== --- python/branches/py3k/PC/VC6/python.dsp (original) +++ python/branches/py3k/PC/VC6/python.dsp Thu Aug 14 03:40:45 2008 @@ -75,13 +75,8 @@ # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x1d000000" /subsystem:console /debug /machine:I386 /out:"./python_d.exe" /pdbtype:sept +# ADD LINK32 odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x1d000000" /stack:0x200000 /subsystem:console /debug /machine:I386 /out:"./python_d.exe" /pdbtype:sept # SUBTRACT LINK32 /pdb:none -# Begin Special Build Tool -SOURCE="$(InputPath)" -PostBuild_Desc=Changing stack size... -PostBuild_Cmds=editbin /STACK:0x200000 python_d.exe -# End Special Build Tool !ENDIF Modified: python/branches/py3k/PC/VC6/pythoncore.dsp ============================================================================== --- python/branches/py3k/PC/VC6/pythoncore.dsp (original) +++ python/branches/py3k/PC/VC6/pythoncore.dsp Thu Aug 14 03:40:45 2008 @@ -185,11 +185,15 @@ # End Source File # Begin Source File -SOURCE=..\..\Modules\_weakref.c +SOURCE=..\..\Modules\_threadmodule.c # End Source File # Begin Source File -SOURCE=..\winreg.c +SOURCE=..\..\Python\_warnings.c +# End Source File +# Begin Source File + +SOURCE=..\..\Modules\_weakref.c # End Source File # Begin Source File @@ -209,10 +213,6 @@ # End Source File # Begin Source File -SOURCE=..\..\Python\_warnings.c -# End Source File -# Begin Source File - SOURCE=..\..\Python\asdl.c # End Source File # Begin Source File @@ -313,14 +313,6 @@ # End Source File # Begin Source File -SOURCE=..\..\Modules\zlib\gzio.c -# End Source File -# Begin Source File - -SOURCE=..\..\Modules\zlib\infback.c -# End Source File -# Begin Source File - SOURCE=..\..\Objects\descrobject.c # End Source File # Begin Source File @@ -442,6 +434,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Modules\zlib\gzio.c +# End Source File +# Begin Source File + SOURCE=..\..\Python\import.c # End Source File # Begin Source File @@ -455,6 +451,10 @@ # End Source File # Begin Source File +SOURCE=..\..\Modules\zlib\infback.c +# End Source File +# Begin Source File + SOURCE=..\..\Modules\zlib\inffast.c # End Source File # Begin Source File @@ -503,11 +503,11 @@ # End Source File # Begin Source File -SOURCE=..\..\Parser\metagrammar.c +SOURCE=..\..\Objects\memoryobject.c # End Source File # Begin Source File -SOURCE=..\..\Objects\memoryobject.c +SOURCE=..\..\Parser\metagrammar.c # End Source File # Begin Source File @@ -631,15 +631,15 @@ # End Source File # Begin Source File -SOURCE=..\..\Modules\sha256module.c +SOURCE=..\..\Modules\sha1module.c # End Source File # Begin Source File -SOURCE=..\..\Modules\sha512module.c +SOURCE=..\..\Modules\sha256module.c # End Source File # Begin Source File -SOURCE=..\..\Modules\sha1module.c +SOURCE=..\..\Modules\sha512module.c # End Source File # Begin Source File @@ -675,10 +675,6 @@ # End Source File # Begin Source File -SOURCE=..\..\Modules\_threadmodule.c -# End Source File -# Begin Source File - SOURCE=..\..\Modules\timemodule.c # End Source File # Begin Source File @@ -695,15 +691,15 @@ # End Source File # Begin Source File -SOURCE=..\..\Modules\zlib\uncompr.c +SOURCE=..\..\Objects\tupleobject.c # End Source File # Begin Source File -SOURCE=..\..\Objects\tupleobject.c +SOURCE=..\..\Objects\typeobject.c # End Source File # Begin Source File -SOURCE=..\..\Objects\typeobject.c +SOURCE=..\..\Modules\zlib\uncompr.c # End Source File # Begin Source File @@ -719,6 +715,10 @@ # End Source File # Begin Source File +SOURCE=..\winreg.c +# End Source File +# Begin Source File + SOURCE=..\..\Modules\xxsubtype.c # End Source File # Begin Source File Modified: python/branches/py3k/PC/VC6/readme.txt ============================================================================== --- python/branches/py3k/PC/VC6/readme.txt (original) +++ python/branches/py3k/PC/VC6/readme.txt Thu Aug 14 03:40:45 2008 @@ -1,7 +1,9 @@ Building Python using VC++ 6.0 or 5.0 ------------------------------------- This directory is used to build Python for Win32 platforms, e.g. Windows -95, 98 and NT. It requires Microsoft Visual C++ 6.x or 5.x. +2000 and XP. It requires Microsoft Visual C++ 6.x or 5.x and Platform +SDK February 2003 Edition (Core SDK). You can download this SDK from +http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm. (For other Windows platforms and compilers, see ../readme.txt.) All you need to do is open the workspace "pcbuild.dsw" in MSVC++, select @@ -11,9 +13,7 @@ The proper order to build subprojects: 1) pythoncore (this builds the main Python DLL and library files, - python21.{dll, lib} in Release mode) - NOTE: in previous releases, this subproject was - named after the release number, e.g. python20. + python30.{dll, lib} in Release mode) 2) python (this builds the main Python executable, python.exe in Release mode) @@ -24,7 +24,7 @@ to the subsystems they implement; see SUBPROJECTS below) When using the Debug setting, the output files have a _d added to -their name: python21_d.dll, python_d.exe, parser_d.pyd, and so on. +their name: python30_d.dll, python_d.exe, pyexpat_d.pyd, and so on. SUBPROJECTS ----------- @@ -39,6 +39,8 @@ .exe pythonw pythonw.exe, a variant of python.exe that doesn't pop up a DOS box +_msi + _msi.c. You need to install Windows Installer SDK to build this module. _socket socketmodule.c _testcapi @@ -177,6 +179,17 @@ XXX threads are invisible to unittest). +_sqlite3 + Python wrapper for SQLite library. + + Get the source code through + + svn export http://svn.python.org/projects/external/sqlite-source-3.3.4 + + To use the extension module in a Python build tree, copy sqlite3.dll into + the PC/VC6 folder. + + _ssl Python wrapper for the secure sockets library. From python-3000-checkins at python.org Thu Aug 14 07:01:01 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Thu, 14 Aug 2008 07:01:01 +0200 (CEST) Subject: [Python-3000-checkins] r65666 - python/branches/py3k Message-ID: <20080814050101.BACAA1E4005@bag.python.org> Author: brett.cannon Date: Thu Aug 14 07:01:01 2008 New Revision: 65666 Log: Blocked revisions 65665 via svnmerge ........ r65665 | brett.cannon | 2008-08-13 22:00:03 -0700 (Wed, 13 Aug 2008) | 11 lines Silence the DeprecationWarning of rfc822 triggered by its importation in mimetools. This has an unfortunate side-effect of potentially not letting any warning about rfc822's deprecation be seen by user-visible code if rfc822 is not imported before mimetools. This is because modules are cached in sys.modules and thus do not have their deprecation triggered more than once. But this silencing would have happened by other code that silences the use of mimetools or rfc822 anyway in the stdlib or user code, and thus seems justified to be done here. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Thu Aug 14 07:59:39 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Thu, 14 Aug 2008 07:59:39 +0200 (CEST) Subject: [Python-3000-checkins] r65669 - in python/branches/py3k: Doc/reference/datamodel.rst Message-ID: <20080814055939.DBD1B1E4007@bag.python.org> Author: brett.cannon Date: Thu Aug 14 07:59:39 2008 New Revision: 65669 Log: Merged revisions 65668 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65668 | brett.cannon | 2008-08-13 22:55:18 -0700 (Wed, 13 Aug 2008) | 4 lines Fix markup for various binary operation examples where the operands were bolded and the operator was made literal, leading to non-valid reST. Changed to have the entire expression just be a literal bit of text. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/reference/datamodel.rst Modified: python/branches/py3k/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k/Doc/reference/datamodel.rst (original) +++ python/branches/py3k/Doc/reference/datamodel.rst Thu Aug 14 07:59:39 2008 @@ -1710,7 +1710,7 @@ These methods are called to implement the binary arithmetic operations (``+``, ``-``, ``*``, ``//``, ``%``, :func:`divmod`, :func:`pow`, ``**``, ``<<``, ``>>``, ``&``, ``^``, ``|``). For instance, to evaluate the expression - *x*``+``*y*, where *x* is an instance of a class that has an :meth:`__add__` + ``x + y``, where *x* is an instance of a class that has an :meth:`__add__` method, ``x.__add__(y)`` is called. The :meth:`__divmod__` method should be the equivalent to using :meth:`__floordiv__` and :meth:`__mod__`; it should not be related to :meth:`__truediv__` (described below). Note that :meth:`__pow__` @@ -1755,7 +1755,7 @@ ``&``, ``^``, ``|``) with reflected (swapped) operands. These functions are only called if the left operand does not support the corresponding operation and the operands are of different types. [#]_ For instance, to evaluate the - expression *x*``-``*y*, where *y* is an instance of a class that has an + expression ``x - y``, where *y* is an instance of a class that has an :meth:`__rsub__` method, ``y.__rsub__(x)`` is called if ``x.__sub__(y)`` returns *NotImplemented*. @@ -1792,10 +1792,10 @@ in-place (modifying *self*) and return the result (which could be, but does not have to be, *self*). If a specific method is not defined, the augmented operation falls back to the normal methods. For instance, to evaluate the - expression *x*``+=``*y*, where *x* is an instance of a class that has an + expression ``x += y``, where *x* is an instance of a class that has an :meth:`__iadd__` method, ``x.__iadd__(y)`` is called. If *x* is an instance of a class that does not define a :meth:`__iadd__` method, ``x.__add__(y)`` - and ``y.__radd__(x)`` are considered, as with the evaluation of *x*``+``*y*. + and ``y.__radd__(x)`` are considered, as with the evaluation of ``x + y``. .. method:: object.__neg__(self) From python-3000-checkins at python.org Thu Aug 14 09:35:14 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Thu, 14 Aug 2008 09:35:14 +0200 (CEST) Subject: [Python-3000-checkins] r65670 - in python/branches/py3k: Lib/distutils/command/build_ext.py Message-ID: <20080814073514.8954C1E4017@bag.python.org> Author: hirokazu.yamamoto Date: Thu Aug 14 09:35:13 2008 New Revision: 65670 Log: Merged revisions 65667 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65667 | hirokazu.yamamoto | 2008-08-14 14:50:43 +0900 | 1 line Fixed test_distutils error (test_build_ext) on VC6. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/distutils/command/build_ext.py Modified: python/branches/py3k/Lib/distutils/command/build_ext.py ============================================================================== --- python/branches/py3k/Lib/distutils/command/build_ext.py (original) +++ python/branches/py3k/Lib/distutils/command/build_ext.py Thu Aug 14 09:35:13 2008 @@ -205,9 +205,12 @@ elif MSVC_VERSION == 8: self.library_dirs.append(os.path.join(sys.exec_prefix, 'PC', 'VS8.0', 'win32release')) - else: + elif MSVC_VERSION == 7: self.library_dirs.append(os.path.join(sys.exec_prefix, 'PC', 'VS7.1')) + else: + self.library_dirs.append(os.path.join(sys.exec_prefix, + 'PC', 'VC6')) # OS/2 (EMX) doesn't support Debug vs Release builds, but has the # import libraries in its "Config" subdirectory From python-3000-checkins at python.org Thu Aug 14 09:37:15 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Thu, 14 Aug 2008 09:37:15 +0200 (CEST) Subject: [Python-3000-checkins] r65671 - python/branches/py3k Message-ID: <20080814073715.DF9EB1E4007@bag.python.org> Author: hirokazu.yamamoto Date: Thu Aug 14 09:37:15 2008 New Revision: 65671 Log: Blocked revisions 65663 via svnmerge ........ r65663 | hirokazu.yamamoto | 2008-08-14 10:33:44 +0900 | 19 lines Issue #2065: VC6 related fix. - PC/VC6/_bsddb.dsp: removed '/nodefaultlib:"msvcrt"' to fix linker error. - PC/VC6/_msi.dsp, PC/VC6/pcbuild.dsw: added new module support. - PC/VC6/_sqlite3.dsp: /D "MODULE_NAME=\"sqlite3\"" caused extra leading space like #define MODULE_NAME " sqlite3" so uses /D MODULE_NAME=\"sqlite3\" instead. - PC/VC6/python.dsp: changed stack size to 2MB to avoid stack overflow on some tests. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Thu Aug 14 13:34:49 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Thu, 14 Aug 2008 13:34:49 +0200 (CEST) Subject: [Python-3000-checkins] r65673 - in python/branches/py3k: PC/VC6/_multiprocessing.dsp PC/VC6/pcbuild.dsw Message-ID: <20080814113449.4DAD11E4007@bag.python.org> Author: hirokazu.yamamoto Date: Thu Aug 14 13:34:49 2008 New Revision: 65673 Log: Merged revisions 65672 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65672 | hirokazu.yamamoto | 2008-08-14 20:26:34 +0900 | 1 line Added _multiprocessing module support. (VC6) ........ Added: python/branches/py3k/PC/VC6/_multiprocessing.dsp - copied unchanged from r65672, /python/trunk/PC/VC6/_multiprocessing.dsp Modified: python/branches/py3k/ (props changed) python/branches/py3k/PC/VC6/pcbuild.dsw Modified: python/branches/py3k/PC/VC6/pcbuild.dsw ============================================================================== --- python/branches/py3k/PC/VC6/pcbuild.dsw (original) +++ python/branches/py3k/PC/VC6/pcbuild.dsw Thu Aug 14 13:34:49 2008 @@ -72,6 +72,21 @@ ############################################################################### +Project: "_multiprocessing"=".\_multiprocessing.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name pythoncore + End Project Dependency +}}} + +############################################################################### + Project: "_socket"=".\_socket.dsp" - Package Owner=<4> Package=<5> From python-3000-checkins at python.org Thu Aug 14 13:50:32 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Thu, 14 Aug 2008 13:50:32 +0200 (CEST) Subject: [Python-3000-checkins] r65674 - python/branches/py3k/Doc/library/socket.rst Message-ID: <20080814115032.C58421E4007@bag.python.org> Author: georg.brandl Date: Thu Aug 14 13:50:32 2008 New Revision: 65674 Log: #3550: socket APIs use bytes, not strings. Modified: python/branches/py3k/Doc/library/socket.rst Modified: python/branches/py3k/Doc/library/socket.rst ============================================================================== --- python/branches/py3k/Doc/library/socket.rst (original) +++ python/branches/py3k/Doc/library/socket.rst Thu Aug 14 13:50:32 2008 @@ -372,7 +372,7 @@ .. function:: inet_aton(ip_string) Convert an IPv4 address from dotted-quad string format (for example, - '123.45.67.89') to 32-bit packed binary format, as a string four characters in + '123.45.67.89') to 32-bit packed binary format, as a bytes object four characters in length. This is useful when conversing with a program that uses the standard C library and needs objects of type :ctype:`struct in_addr`, which is the C type for the 32-bit packed binary this function returns. @@ -387,23 +387,25 @@ .. function:: inet_ntoa(packed_ip) - Convert a 32-bit packed IPv4 address (a string four characters in length) to its - standard dotted-quad string representation (for example, '123.45.67.89'). This - is useful when conversing with a program that uses the standard C library and - needs objects of type :ctype:`struct in_addr`, which is the C type for the - 32-bit packed binary data this function takes as an argument. - - If the string passed to this function is not exactly 4 bytes in length, - :exc:`socket.error` will be raised. :func:`inet_ntoa` does not support IPv6, and - :func:`getnameinfo` should be used instead for IPv4/v6 dual stack support. + Convert a 32-bit packed IPv4 address (a bytes object four characters in + length) to its standard dotted-quad string representation (for example, + '123.45.67.89'). This is useful when conversing with a program that uses the + standard C library and needs objects of type :ctype:`struct in_addr`, which + is the C type for the 32-bit packed binary data this function takes as an + argument. + + If the byte sequence passed to this function is not exactly 4 bytes in + length, :exc:`socket.error` will be raised. :func:`inet_ntoa` does not + support IPv6, and :func:`getnameinfo` should be used instead for IPv4/v6 dual + stack support. .. function:: inet_pton(address_family, ip_string) - Convert an IP address from its family-specific string format to a packed, binary - format. :func:`inet_pton` is useful when a library or network protocol calls for - an object of type :ctype:`struct in_addr` (similar to :func:`inet_aton`) or - :ctype:`struct in6_addr`. + Convert an IP address from its family-specific string format to a packed, + binary format. :func:`inet_pton` is useful when a library or network protocol + calls for an object of type :ctype:`struct in_addr` (similar to + :func:`inet_aton`) or :ctype:`struct in6_addr`. Supported values for *address_family* are currently :const:`AF_INET` and :const:`AF_INET6`. If the IP address string *ip_string* is invalid, @@ -416,9 +418,9 @@ .. function:: inet_ntop(address_family, packed_ip) - Convert a packed IP address (a string of some number of characters) to its + Convert a packed IP address (a bytes object of some number of characters) to its standard, family-specific string representation (for example, ``'7.10.0.5'`` or - ``'5aef:2b::8'``) :func:`inet_ntop` is useful when a library or network protocol + ``'5aef:2b::8'``). :func:`inet_ntop` is useful when a library or network protocol returns an object of type :ctype:`struct in_addr` (similar to :func:`inet_ntoa`) or :ctype:`struct in6_addr`. @@ -534,9 +536,9 @@ are defined in this module. If *buflen* is absent, an integer option is assumed and its integer value is returned by the function. If *buflen* is present, it specifies the maximum length of the buffer used to receive the option in, and - this buffer is returned as a string. It is up to the caller to decode the + this buffer is returned as a bytes object. It is up to the caller to decode the contents of the buffer (see the optional built-in module :mod:`struct` for a way - to decode C structures encoded as strings). + to decode C structures encoded as byte strings). .. method:: socket.ioctl(control, option) @@ -569,7 +571,7 @@ .. method:: socket.recv(bufsize[, flags]) - Receive data from the socket. The return value is a string representing the + Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by *bufsize*. See the Unix manual page :manpage:`recv(2)` for the meaning of the optional argument *flags*; it defaults to zero. @@ -582,8 +584,8 @@ .. method:: socket.recvfrom(bufsize[, flags]) - Receive data from the socket. The return value is a pair ``(string, address)`` - where *string* is a string representing the data received and *address* is the + Receive data from the socket. The return value is a pair ``(bytes, address)`` + where *bytes* is a bytes object representing the data received and *address* is the address of the socket sending the data. See the Unix manual page :manpage:`recv(2)` for the meaning of the optional argument *flags*; it defaults to zero. (The format of *address* depends on the address family --- see above.) @@ -591,8 +593,8 @@ .. method:: socket.recvfrom_into(buffer[, nbytes[, flags]]) - Receive data from the socket, writing it into *buffer* instead of creating a - new string. The return value is a pair ``(nbytes, address)`` where *nbytes* is + Receive data from the socket, writing it into *buffer* instead of creating a + new bytestring. The return value is a pair ``(nbytes, address)`` where *nbytes* is the number of bytes received and *address* is the address of the socket sending the data. See the Unix manual page :manpage:`recv(2)` for the meaning of the optional argument *flags*; it defaults to zero. (The format of *address* @@ -602,13 +604,13 @@ .. method:: socket.recv_into(buffer[, nbytes[, flags]]) Receive up to *nbytes* bytes from the socket, storing the data into a buffer - rather than creating a new string. If *nbytes* is not specified (or 0), + rather than creating a new bytestring. If *nbytes* is not specified (or 0), receive up to the size available in the given buffer. See the Unix manual page :manpage:`recv(2)` for the meaning of the optional argument *flags*; it defaults to zero. -.. method:: socket.send(string[, flags]) +.. method:: socket.send(bytes[, flags]) Send data to the socket. The socket must be connected to a remote socket. The optional *flags* argument has the same meaning as for :meth:`recv` above. @@ -617,17 +619,17 @@ application needs to attempt delivery of the remaining data. -.. method:: socket.sendall(string[, flags]) +.. method:: socket.sendall(bytes[, flags]) Send data to the socket. The socket must be connected to a remote socket. The optional *flags* argument has the same meaning as for :meth:`recv` above. - Unlike :meth:`send`, this method continues to send data from *string* until + Unlike :meth:`send`, this method continues to send data from *bytes* until either all data has been sent or an error occurs. ``None`` is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent. -.. method:: socket.sendto(string[, flags], address) +.. method:: socket.sendto(bytes[, flags], address) Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by *address*. The optional *flags* @@ -693,9 +695,9 @@ Set the value of the given socket option (see the Unix manual page :manpage:`setsockopt(2)`). The needed symbolic constants are defined in the :mod:`socket` module (:const:`SO_\*` etc.). The value can be an integer or a - string representing a buffer. In the latter case it is up to the caller to - ensure that the string contains the proper bits (see the optional built-in - module :mod:`struct` for a way to encode C structures as strings). + bytes object representing a buffer. In the latter case it is up to the caller to + ensure that the bytestring contains the proper bits (see the optional built-in + module :mod:`struct` for a way to encode C structures as bytestrings). .. method:: socket.shutdown(how) @@ -768,7 +770,7 @@ PORT = 50007 # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) - s.send('Hello, world') + s.send(b'Hello, world') data = s.recv(1024) s.close() print('Received', repr(data)) @@ -787,7 +789,8 @@ HOST = None # Symbolic name meaning all available interfaces PORT = 50007 # Arbitrary non-privileged port s = None - for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): + for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, + socket.SOCK_STREAM, 0, socket.AI_PASSIVE): af, socktype, proto, canonname, sa = res try: s = socket.socket(af, socktype, proto) @@ -839,7 +842,7 @@ if s is None: print('could not open socket') sys.exit(1) - s.send('Hello, world') + s.send(b'Hello, world') data = s.recv(1024) s.close() print('Received', repr(data)) From python-3000-checkins at python.org Thu Aug 14 17:52:24 2008 From: python-3000-checkins at python.org (martin.v.loewis) Date: Thu, 14 Aug 2008 17:52:24 +0200 (CEST) Subject: [Python-3000-checkins] r65676 - in python/branches/py3k/Modules: md5module.c sha1module.c Message-ID: <20080814155224.125631E400F@bag.python.org> Author: martin.v.loewis Date: Thu Aug 14 17:52:23 2008 New Revision: 65676 Log: Use s* to receive data. Fixes #3552. Modified: python/branches/py3k/Modules/md5module.c python/branches/py3k/Modules/sha1module.c Modified: python/branches/py3k/Modules/md5module.c ============================================================================== --- python/branches/py3k/Modules/md5module.c (original) +++ python/branches/py3k/Modules/md5module.c Thu Aug 14 17:52:23 2008 @@ -411,14 +411,14 @@ static PyObject * MD5_update(MD5object *self, PyObject *args) { - unsigned char *cp; - int len; - - if (!PyArg_ParseTuple(args, "s#:update", &cp, &len)) + Py_buffer buf; + + if (!PyArg_ParseTuple(args, "s*:update", &buf)) return NULL; - md5_process(&self->hash_state, cp, len); + md5_process(&self->hash_state, buf.buf, buf.len); + PyBuffer_Release(&buf); Py_INCREF(Py_None); return Py_None; } @@ -511,11 +511,11 @@ { static char *kwlist[] = {"string", NULL}; MD5object *new; - unsigned char *cp = NULL; - int len; + Py_buffer buf; + buf.buf = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, - &cp, &len)) { + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s*:new", kwlist, + &buf)) { return NULL; } @@ -528,8 +528,10 @@ Py_DECREF(new); return NULL; } - if (cp) - md5_process(&new->hash_state, cp, len); + if (buf.buf) { + md5_process(&new->hash_state, buf.buf, buf.len); + PyBuffer_Release(&buf); + } return (PyObject *)new; } Modified: python/branches/py3k/Modules/sha1module.c ============================================================================== --- python/branches/py3k/Modules/sha1module.c (original) +++ python/branches/py3k/Modules/sha1module.c Thu Aug 14 17:52:23 2008 @@ -387,14 +387,14 @@ static PyObject * SHA1_update(SHA1object *self, PyObject *args) { - unsigned char *cp; - int len; + Py_buffer buf; - if (!PyArg_ParseTuple(args, "s#:update", &cp, &len)) + if (!PyArg_ParseTuple(args, "s*:update", &buf)) return NULL; - sha1_process(&self->hash_state, cp, len); + sha1_process(&self->hash_state, buf.buf, buf.len); + PyBuffer_Release(&buf); Py_INCREF(Py_None); return Py_None; } @@ -487,11 +487,10 @@ { static char *kwlist[] = {"string", NULL}; SHA1object *new; - unsigned char *cp = NULL; - int len; + Py_buffer buf; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, - &cp, &len)) { + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s*:new", kwlist, + &buf)) { return NULL; } @@ -504,8 +503,10 @@ Py_DECREF(new); return NULL; } - if (cp) - sha1_process(&new->hash_state, cp, len); + if (buf.buf) { + sha1_process(&new->hash_state, buf.buf, buf.len); + PyBuffer_Release(&buf); + } return (PyObject *)new; } From python-3000-checkins at python.org Thu Aug 14 18:55:14 2008 From: python-3000-checkins at python.org (facundo.batista) Date: Thu, 14 Aug 2008 18:55:14 +0200 (CEST) Subject: [Python-3000-checkins] r65680 - in python/branches/py3k/Lib: test/test_urlparse.py urllib/parse.py Message-ID: <20080814165514.B794D1E4010@bag.python.org> Author: facundo.batista Date: Thu Aug 14 18:55:14 2008 New Revision: 65680 Log: Issue 1432. Fixes a bug caused because of the evolution of the RFC that describes the behaviour. Note that we now have the same behaviour than the current browsers. Modified: python/branches/py3k/Lib/test/test_urlparse.py python/branches/py3k/Lib/urllib/parse.py Modified: python/branches/py3k/Lib/test/test_urlparse.py ============================================================================== --- python/branches/py3k/Lib/test/test_urlparse.py (original) +++ python/branches/py3k/Lib/test/test_urlparse.py Thu Aug 14 18:55:14 2008 @@ -6,6 +6,7 @@ RFC1808_BASE = "http://a/b/c/d;p?q#f" RFC2396_BASE = "http://a/b/c/d;p?q" +RFC3986_BASE = "http://a/b/c/d;p?q" class UrlParseTestCase(unittest.TestCase): @@ -167,8 +168,6 @@ def test_RFC2396(self): # cases from RFC 2396 - self.checkJoin(RFC2396_BASE, '?y', 'http://a/b/c/?y') - self.checkJoin(RFC2396_BASE, ';x', 'http://a/b/c/;x') self.checkJoin(RFC2396_BASE, 'g:h', 'g:h') self.checkJoin(RFC2396_BASE, 'g', 'http://a/b/c/g') @@ -210,6 +209,14 @@ self.checkJoin(RFC2396_BASE, 'g#s/./x', 'http://a/b/c/g#s/./x') self.checkJoin(RFC2396_BASE, 'g#s/../x', 'http://a/b/c/g#s/../x') + #The following scenarios have been updated in RFC3986 + #self.checkJoin(RFC2396_BASE, '?y', 'http://a/b/c/?y') + #self.checkJoin(RFC2396_BASE, ';x', 'http://a/b/c/;x') + + def test_RFC3986(self): + self.checkJoin(RFC3986_BASE, '?y','http://a/b/c/d;p?y') + self.checkJoin(RFC2396_BASE, ';x', 'http://a/b/c/;x') + def test_urldefrag(self): for url, defrag, frag in [ ('http://python.org#frag', 'http://python.org', 'frag'), Modified: python/branches/py3k/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k/Lib/urllib/parse.py (original) +++ python/branches/py3k/Lib/urllib/parse.py Thu Aug 14 18:55:14 2008 @@ -219,9 +219,18 @@ if path[:1] == '/': return urlunparse((scheme, netloc, path, params, query, fragment)) - if not (path or params or query): - return urlunparse((scheme, netloc, bpath, - bparams, bquery, fragment)) + if not path: + path = bpath + if not params: + params = bparams + else: + path = path[:-1] + return urlunparse((scheme, netloc, path, + params, query, fragment)) + if not query: + query = bquery + return urlunparse((scheme, netloc, path, + params, query, fragment)) segments = bpath.split('/')[:-1] + path.split('/') # XXX The stuff below is bogus in various ways... if segments[-1] == '.': From python-3000-checkins at python.org Thu Aug 14 22:32:30 2008 From: python-3000-checkins at python.org (martin.v.loewis) Date: Thu, 14 Aug 2008 22:32:30 +0200 (CEST) Subject: [Python-3000-checkins] r65685 - in python/branches/py3k: Objects/abstract.c Message-ID: <20080814203230.8567C1E4007@bag.python.org> Author: martin.v.loewis Date: Thu Aug 14 22:32:30 2008 New Revision: 65685 Log: Merged revisions 65677-65678,65683 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65677 | martin.v.loewis | 2008-08-14 17:54:27 +0200 (Do, 14 Aug 2008) | 3 lines Make obj an owned reference in Py_buffer; this checkin was missing from the patch for #3139. ........ r65678 | martin.v.loewis | 2008-08-14 17:56:07 +0200 (Do, 14 Aug 2008) | 2 lines Properly INCREF reference in Py_buffer. ........ r65683 | martin.v.loewis | 2008-08-14 22:12:06 +0200 (Do, 14 Aug 2008) | 2 lines Fix memory leak: Always DECREF obj in PyBuffer_Release. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Objects/abstract.c Modified: python/branches/py3k/Objects/abstract.c ============================================================================== --- python/branches/py3k/Objects/abstract.c (original) +++ python/branches/py3k/Objects/abstract.c Thu Aug 14 22:32:30 2008 @@ -670,6 +670,8 @@ } view->obj = obj; + if (obj) + Py_INCREF(obj); view->buf = buf; view->len = len; view->readonly = readonly; @@ -693,11 +695,10 @@ PyBuffer_Release(Py_buffer *view) { PyObject *obj = view->obj; - if (!obj || !Py_TYPE(obj)->tp_as_buffer || !Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer) - /* Unmanaged buffer */ - return; - Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view); - + if (obj && Py_TYPE(obj)->tp_as_buffer && Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer) + Py_TYPE(obj)->tp_as_buffer->bf_releasebuffer(obj, view); + Py_XDECREF(obj); + view->obj = NULL; } PyObject * From python-3000-checkins at python.org Fri Aug 15 00:44:29 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Fri, 15 Aug 2008 00:44:29 +0200 (CEST) Subject: [Python-3000-checkins] r65687 - in python/branches/py3k: Lib/io.py Lib/test/test_cmd_line.py Lib/test/test_io.py Misc/NEWS Message-ID: <20080814224429.B7A421E4007@bag.python.org> Author: antoine.pitrou Date: Fri Aug 15 00:44:29 2008 New Revision: 65687 Log: Merged revisions 65686 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65686 | antoine.pitrou | 2008-08-14 23:04:30 +0200 (jeu., 14 ao?t 2008) | 3 lines Issue #3476: make BufferedReader and BufferedWriter thread-safe ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/io.py python/branches/py3k/Lib/test/test_cmd_line.py python/branches/py3k/Lib/test/test_io.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/io.py ============================================================================== --- python/branches/py3k/Lib/io.py (original) +++ python/branches/py3k/Lib/io.py Fri Aug 15 00:44:29 2008 @@ -61,6 +61,7 @@ import codecs import _fileio import warnings +import threading # open() uses st_blksize whenever we can DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes @@ -895,6 +896,7 @@ _BufferedIOMixin.__init__(self, raw) self.buffer_size = buffer_size self._reset_read_buf() + self._read_lock = threading.Lock() def _reset_read_buf(self): self._read_buf = b"" @@ -908,6 +910,10 @@ mode. If n is negative, read until EOF or until read() would block. """ + with self._read_lock: + return self._read_unlocked(n) + + def _read_unlocked(self, n=None): nodata_val = b"" empty_values = (b"", None) buf = self._read_buf @@ -960,6 +966,10 @@ do at most one raw read to satisfy it. We never return more than self.buffer_size. """ + with self._read_lock: + return self._peek_unlocked(n) + + def _peek_unlocked(self, n=0): want = min(n, self.buffer_size) have = len(self._read_buf) - self._read_pos if have < want: @@ -976,18 +986,21 @@ # only return buffered bytes. Otherwise, we do one raw read. if n <= 0: return b"" - self.peek(1) - return self.read(min(n, len(self._read_buf) - self._read_pos)) + with self._read_lock: + self._peek_unlocked(1) + return self._read_unlocked( + min(n, len(self._read_buf) - self._read_pos)) def tell(self): return self.raw.tell() - len(self._read_buf) + self._read_pos def seek(self, pos, whence=0): - if whence == 1: - pos -= len(self._read_buf) - self._read_pos - pos = self.raw.seek(pos, whence) - self._reset_read_buf() - return pos + with self._read_lock: + if whence == 1: + pos -= len(self._read_buf) - self._read_pos + pos = self.raw.seek(pos, whence) + self._reset_read_buf() + return pos class BufferedWriter(_BufferedIOMixin): @@ -1009,43 +1022,51 @@ if max_buffer_size is None else max_buffer_size) self._write_buf = bytearray() + self._write_lock = threading.Lock() def write(self, b): if self.closed: raise ValueError("write to closed file") if isinstance(b, str): raise TypeError("can't write str to binary stream") - # XXX we can implement some more tricks to try and avoid partial writes - if len(self._write_buf) > self.buffer_size: - # We're full, so let's pre-flush the buffer - try: - self.flush() - except BlockingIOError as e: - # We can't accept anything else. - # XXX Why not just let the exception pass through? - raise BlockingIOError(e.errno, e.strerror, 0) - before = len(self._write_buf) - self._write_buf.extend(b) - written = len(self._write_buf) - before - if len(self._write_buf) > self.buffer_size: - try: - self.flush() - except BlockingIOError as e: - if (len(self._write_buf) > self.max_buffer_size): - # We've hit max_buffer_size. We have to accept a partial - # write and cut back our buffer. - overage = len(self._write_buf) - self.max_buffer_size - self._write_buf = self._write_buf[:self.max_buffer_size] - raise BlockingIOError(e.errno, e.strerror, overage) - return written + with self._write_lock: + # XXX we can implement some more tricks to try and avoid + # partial writes + if len(self._write_buf) > self.buffer_size: + # We're full, so let's pre-flush the buffer + try: + self._flush_unlocked() + except BlockingIOError as e: + # We can't accept anything else. + # XXX Why not just let the exception pass through? + raise BlockingIOError(e.errno, e.strerror, 0) + before = len(self._write_buf) + self._write_buf.extend(b) + written = len(self._write_buf) - before + if len(self._write_buf) > self.buffer_size: + try: + self._flush_unlocked() + except BlockingIOError as e: + if len(self._write_buf) > self.max_buffer_size: + # We've hit max_buffer_size. We have to accept a + # partial write and cut back our buffer. + overage = len(self._write_buf) - self.max_buffer_size + self._write_buf = self._write_buf[:self.max_buffer_size] + raise BlockingIOError(e.errno, e.strerror, overage) + return written def truncate(self, pos=None): - self.flush() - if pos is None: - pos = self.raw.tell() - return self.raw.truncate(pos) + with self._write_lock: + self._flush_unlocked() + if pos is None: + pos = self.raw.tell() + return self.raw.truncate(pos) def flush(self): + with self._write_lock: + self._flush_unlocked() + + def _flush_unlocked(self): if self.closed: raise ValueError("flush of closed file") written = 0 @@ -1064,8 +1085,9 @@ return self.raw.tell() + len(self._write_buf) def seek(self, pos, whence=0): - self.flush() - return self.raw.seek(pos, whence) + with self._write_lock: + self._flush_unlocked() + return self.raw.seek(pos, whence) class BufferedRWPair(BufferedIOBase): @@ -1155,7 +1177,8 @@ # First do the raw seek, then empty the read buffer, so that # if the raw seek fails, we don't lose buffered data forever. pos = self.raw.seek(pos, whence) - self._reset_read_buf() + with self._read_lock: + self._reset_read_buf() return pos def tell(self): @@ -1192,8 +1215,9 @@ def write(self, b): if self._read_buf: # Undo readahead - self.raw.seek(self._read_pos - len(self._read_buf), 1) - self._reset_read_buf() + with self._read_lock: + self.raw.seek(self._read_pos - len(self._read_buf), 1) + self._reset_read_buf() return BufferedWriter.write(self, b) Modified: python/branches/py3k/Lib/test/test_cmd_line.py ============================================================================== --- python/branches/py3k/Lib/test/test_cmd_line.py (original) +++ python/branches/py3k/Lib/test/test_cmd_line.py Fri Aug 15 00:44:29 2008 @@ -3,11 +3,15 @@ # See test_cmd_line_script.py for testing of script execution import test.support, unittest +import os import sys import subprocess def _spawn_python(*args): - cmd_line = [sys.executable, '-E'] + cmd_line = [sys.executable] + # When testing -S, we need PYTHONPATH to work (see test_site_flag()) + if '-S' not in args: + cmd_line.append('-E') cmd_line.extend(args) return subprocess.Popen(cmd_line, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -59,6 +63,16 @@ self.verify_valid_flag('-Qwarnall') def test_site_flag(self): + if os.name == 'posix': + # Workaround bug #586680 by adding the extension dir to PYTHONPATH + from distutils.util import get_platform + s = "./build/lib.%s-%.3s" % (get_platform(), sys.version) + if hasattr(sys, 'gettotalrefcount'): + s += '-pydebug' + p = os.environ.get('PYTHONPATH', '') + if p: + p += ':' + os.environ['PYTHONPATH'] = p + s self.verify_valid_flag('-S') def test_usage(self): Modified: python/branches/py3k/Lib/test/test_io.py ============================================================================== --- python/branches/py3k/Lib/test/test_io.py (original) +++ python/branches/py3k/Lib/test/test_io.py Fri Aug 15 00:44:29 2008 @@ -4,8 +4,10 @@ import sys import time import array +import threading +import random import unittest -from itertools import chain +from itertools import chain, cycle from test import support import codecs @@ -390,6 +392,49 @@ # this test. Else, write it. pass + def testThreads(self): + try: + # Write out many bytes with exactly the same number of 0's, + # 1's... 255's. This will help us check that concurrent reading + # doesn't duplicate or forget contents. + N = 1000 + l = list(range(256)) * N + random.shuffle(l) + s = bytes(bytearray(l)) + with io.open(support.TESTFN, "wb") as f: + f.write(s) + with io.open(support.TESTFN, "rb", buffering=0) as raw: + bufio = io.BufferedReader(raw, 8) + errors = [] + results = [] + def f(): + try: + # Intra-buffer read then buffer-flushing read + for n in cycle([1, 19]): + s = bufio.read(n) + if not s: + break + # list.append() is atomic + results.append(s) + except Exception as e: + errors.append(e) + raise + threads = [threading.Thread(target=f) for x in range(20)] + for t in threads: + t.start() + time.sleep(0.02) # yield + for t in threads: + t.join() + self.assertFalse(errors, + "the following exceptions were caught: %r" % errors) + s = b''.join(results) + for i in range(256): + c = bytes(bytearray([i])) + self.assertEqual(s.count(c), N) + finally: + support.unlink(support.TESTFN) + + class BufferedWriterTest(unittest.TestCase): @@ -446,6 +491,38 @@ self.assertEquals(b"abc", writer._write_stack[0]) + def testThreads(self): + # BufferedWriter should not raise exceptions or crash + # when called from multiple threads. + try: + # We use a real file object because it allows us to + # exercise situations where the GIL is released before + # writing the buffer to the raw streams. This is in addition + # to concurrency issues due to switching threads in the middle + # of Python code. + with io.open(support.TESTFN, "wb", buffering=0) as raw: + bufio = io.BufferedWriter(raw, 8) + errors = [] + def f(): + try: + # Write enough bytes to flush the buffer + s = b"a" * 19 + for i in range(50): + bufio.write(s) + except Exception as e: + errors.append(e) + raise + threads = [threading.Thread(target=f) for x in range(20)] + for t in threads: + t.start() + time.sleep(0.02) # yield + for t in threads: + t.join() + self.assertFalse(errors, + "the following exceptions were caught: %r" % errors) + finally: + support.unlink(support.TESTFN) + class BufferedRWPairTest(unittest.TestCase): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Aug 15 00:44:29 2008 @@ -30,6 +30,9 @@ Library ------- +- Issue #3476: binary buffered reading through the new "io" library is now + thread-safe. + - Issue #1342811: Fix leak in Tkinter.Menu.delete. Commands associated to menu entries were not deleted. From python-3000-checkins at python.org Fri Aug 15 02:06:00 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Fri, 15 Aug 2008 02:06:00 +0200 (CEST) Subject: [Python-3000-checkins] r65688 - python/branches/py3k/Lib/io.py Message-ID: <20080815000600.618451E4007@bag.python.org> Author: antoine.pitrou Date: Fri Aug 15 02:05:08 2008 New Revision: 65688 Log: Fix build from a blank checkout by using the _thread module instead of threading in io.py (thanks Christian!) Modified: python/branches/py3k/Lib/io.py Modified: python/branches/py3k/Lib/io.py ============================================================================== --- python/branches/py3k/Lib/io.py (original) +++ python/branches/py3k/Lib/io.py Fri Aug 15 02:05:08 2008 @@ -61,7 +61,7 @@ import codecs import _fileio import warnings -import threading +from _thread import allocate_lock as Lock # open() uses st_blksize whenever we can DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes @@ -896,7 +896,7 @@ _BufferedIOMixin.__init__(self, raw) self.buffer_size = buffer_size self._reset_read_buf() - self._read_lock = threading.Lock() + self._read_lock = Lock() def _reset_read_buf(self): self._read_buf = b"" @@ -1022,7 +1022,7 @@ if max_buffer_size is None else max_buffer_size) self._write_buf = bytearray() - self._write_lock = threading.Lock() + self._write_lock = Lock() def write(self, b): if self.closed: From python-3000-checkins at python.org Fri Aug 15 05:07:48 2008 From: python-3000-checkins at python.org (alexandre.vassalotti) Date: Fri, 15 Aug 2008 05:07:48 +0200 (CEST) Subject: [Python-3000-checkins] r65689 - in python/branches/py3k: Lib/test/pickletester.py Modules/_pickle.c Message-ID: <20080815030748.7FE9E1E4007@bag.python.org> Author: alexandre.vassalotti Date: Fri Aug 15 05:07:47 2008 New Revision: 65689 Log: Issue 3514: Fixed segfault dues to infinite loop in __getattr__. Modified: python/branches/py3k/Lib/test/pickletester.py python/branches/py3k/Modules/_pickle.c Modified: python/branches/py3k/Lib/test/pickletester.py ============================================================================== --- python/branches/py3k/Lib/test/pickletester.py (original) +++ python/branches/py3k/Lib/test/pickletester.py Fri Aug 15 05:07:47 2008 @@ -868,6 +868,14 @@ y = self.loads(s) self.assertEqual(y._reduce_called, 1) + def test_bad_getattr(self): + x = BadGetattr() + for proto in 0, 1: + self.assertRaises(RuntimeError, self.dumps, x, proto) + # protocol 2 don't raise a RuntimeError. + d = self.dumps(x, 2) + self.assertRaises(RuntimeError, self.loads, d) + # Test classes for reduce_ex class REX_one(object): @@ -949,6 +957,10 @@ # raise an error, to make sure this isn't called raise TypeError("SimpleNewObj.__init__() didn't expect to get called") +class BadGetattr: + def __getattr__(self, key): + self.foo + class AbstractPickleModuleTests(unittest.TestCase): def test_dump_closed_file(self): Modified: python/branches/py3k/Modules/_pickle.c ============================================================================== --- python/branches/py3k/Modules/_pickle.c (original) +++ python/branches/py3k/Modules/_pickle.c Fri Aug 15 05:07:47 2008 @@ -3834,8 +3834,11 @@ inst = self->stack->data[self->stack->length - 1]; setstate = PyObject_GetAttrString(inst, "__setstate__"); - if (setstate == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); + if (setstate == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + return -1; } else { PyObject *result; From python-3000-checkins at python.org Fri Aug 15 08:27:18 2008 From: python-3000-checkins at python.org (martin.v.loewis) Date: Fri, 15 Aug 2008 08:27:18 +0200 (CEST) Subject: [Python-3000-checkins] r65690 - python/branches/py3k/Modules/sha1module.c Message-ID: <20080815062718.136A11E4007@bag.python.org> Author: martin.v.loewis Date: Fri Aug 15 08:27:17 2008 New Revision: 65690 Log: Zero-initialize buf. Fixes #3557. Modified: python/branches/py3k/Modules/sha1module.c Modified: python/branches/py3k/Modules/sha1module.c ============================================================================== --- python/branches/py3k/Modules/sha1module.c (original) +++ python/branches/py3k/Modules/sha1module.c Fri Aug 15 08:27:17 2008 @@ -488,6 +488,7 @@ static char *kwlist[] = {"string", NULL}; SHA1object *new; Py_buffer buf; + buf.buf = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s*:new", kwlist, &buf)) { From python-3000-checkins at python.org Fri Aug 15 16:51:48 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Fri, 15 Aug 2008 16:51:48 +0200 (CEST) Subject: [Python-3000-checkins] r65692 - python/branches/py3k/Modules/binascii.c Message-ID: <20080815145148.B18D01E4019@bag.python.org> Author: antoine.pitrou Date: Fri Aug 15 16:51:48 2008 New Revision: 65692 Log: Fix building binascii when not using the zlib's crc32 (build failure on Windows buildbots) Modified: python/branches/py3k/Modules/binascii.c Modified: python/branches/py3k/Modules/binascii.c ============================================================================== --- python/branches/py3k/Modules/binascii.c (original) +++ python/branches/py3k/Modules/binascii.c Fri Aug 15 16:51:48 2008 @@ -1028,7 +1028,7 @@ } result = (crc ^ 0xFFFFFFFF); - PyBuffer_Release(&pbuf); + PyBuffer_Release(&pbin); return PyLong_FromUnsignedLong(result & 0xffffffff); } #endif /* USE_ZLIB_CRC32 */ From python-3000-checkins at python.org Fri Aug 15 20:43:03 2008 From: python-3000-checkins at python.org (christian.heimes) Date: Fri, 15 Aug 2008 20:43:03 +0200 (CEST) Subject: [Python-3000-checkins] r65694 - in python/branches/py3k/Lib: io.py warnings.py Message-ID: <20080815184303.B87101E4009@bag.python.org> Author: christian.heimes Date: Fri Aug 15 20:43:03 2008 New Revision: 65694 Log: Removed some unused imports to decrease the amount of loaded modules during startup. Added fallback to _dummy_thread for OSs w/o thread support. Modified: python/branches/py3k/Lib/io.py python/branches/py3k/Lib/warnings.py Modified: python/branches/py3k/Lib/io.py ============================================================================== --- python/branches/py3k/Lib/io.py (original) +++ python/branches/py3k/Lib/io.py Fri Aug 15 20:43:03 2008 @@ -60,8 +60,12 @@ import sys import codecs import _fileio -import warnings -from _thread import allocate_lock as Lock +# Import _thread instead of threading to reduce startup cost +try: + from _thread import allocate_lock as Lock +except ImportError: + from _dummy_thread import allocate_lock as Lock + # open() uses st_blksize whenever we can DEFAULT_BUFFER_SIZE = 8 * 1024 # bytes Modified: python/branches/py3k/Lib/warnings.py ============================================================================== --- python/branches/py3k/Lib/warnings.py (original) +++ python/branches/py3k/Lib/warnings.py Fri Aug 15 20:43:03 2008 @@ -5,7 +5,6 @@ # See bug 683658. import linecache import sys -import types __all__ = ["warn", "showwarning", "formatwarning", "filterwarnings", "resetwarnings"] From python-3000-checkins at python.org Sat Aug 16 01:56:02 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 16 Aug 2008 01:56:02 +0200 (CEST) Subject: [Python-3000-checkins] r65704 - in python/branches/py3k: Lib/lib2to3 Lib/lib2to3/fixes/fix_imports.py Message-ID: <20080815235602.6EA731E4008@bag.python.org> Author: benjamin.peterson Date: Sat Aug 16 01:56:02 2008 New Revision: 65704 Log: Merged revisions 65703 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ................ r65703 | benjamin.peterson | 2008-08-15 18:51:24 -0500 (Fri, 15 Aug 2008) | 11 lines Merged revisions 65397 via svnmerge from svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3/lib2to3 ........ r65397 | collin.winter | 2008-08-01 22:39:06 -0500 (Fri, 01 Aug 2008) | 5 lines Patch #3480 by Nick Edds. Dramatically simplifies the fix_imports pattern, resulting in a reduction of the test_all_fixers runtime from 122+ secs to 59 secs (a good predictor of 2to3 performance). ........ ................ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/lib2to3/ (props changed) python/branches/py3k/Lib/lib2to3/fixes/fix_imports.py Modified: python/branches/py3k/Lib/lib2to3/fixes/fix_imports.py ============================================================================== --- python/branches/py3k/Lib/lib2to3/fixes/fix_imports.py (original) +++ python/branches/py3k/Lib/lib2to3/fixes/fix_imports.py Sat Aug 16 01:56:02 2008 @@ -61,24 +61,23 @@ def build_pattern(mapping=MAPPING): - bare = set() - for old_module, new_module in mapping.items(): - bare.add(old_module) - yield """import_name< 'import' (module=%r - | dotted_as_names< any* module=%r any* >) > - """ % (old_module, old_module) - yield """import_from< 'from' module_name=%r 'import' - ( any | import_as_name< any 'as' any > | - import_as_names< any* >) > - """ % old_module - yield """import_name< 'import' - dotted_as_name< module_name=%r 'as' any > > - """ % old_module - # Find usages of module members in code e.g. urllib.foo(bar) - yield """power< module_name=%r - trailer<'.' any > any* > - """ % old_module - yield """bare_name=%s""" % alternates(bare) + mod_list = ' | '.join(["module='" + key + "'" for key in mapping.keys()]) + mod_name_list = ' | '.join(["module_name='" + key + "'" for key in mapping.keys()]) + yield """import_name< 'import' ((%s) + | dotted_as_names< any* (%s) any* >) > + """ % (mod_list, mod_list) + yield """import_from< 'from' (%s) 'import' + ( any | import_as_name< any 'as' any > | + import_as_names< any* >) > + """ % mod_name_list + yield """import_name< 'import' + dotted_as_name< (%s) 'as' any > > + """ % mod_name_list + # Find usages of module members in code e.g. urllib.foo(bar) + yield """power< (%s) + trailer<'.' any > any* > + """ % mod_name_list + yield """bare_name=%s""" % alternates(mapping.keys()) class FixImports(fixer_base.BaseFix): PATTERN = "|".join(build_pattern()) From python-3000-checkins at python.org Sat Aug 16 04:59:56 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 16 Aug 2008 04:59:56 +0200 (CEST) Subject: [Python-3000-checkins] r65705 - in python/branches/py3k/Doc/library: ast.rst csv.rst ctypes.rst inspect.rst logging.rst math.rst pdb.rst reprlib.rst stdtypes.rst sys.rst textwrap.rst Message-ID: <20080816025956.04D051E4008@bag.python.org> Author: benjamin.peterson Date: Sat Aug 16 04:59:55 2008 New Revision: 65705 Log: murder some versionadded and versionchanged directives in their beds Modified: python/branches/py3k/Doc/library/ast.rst python/branches/py3k/Doc/library/csv.rst python/branches/py3k/Doc/library/ctypes.rst python/branches/py3k/Doc/library/inspect.rst python/branches/py3k/Doc/library/logging.rst python/branches/py3k/Doc/library/math.rst python/branches/py3k/Doc/library/pdb.rst python/branches/py3k/Doc/library/reprlib.rst python/branches/py3k/Doc/library/stdtypes.rst python/branches/py3k/Doc/library/sys.rst python/branches/py3k/Doc/library/textwrap.rst Modified: python/branches/py3k/Doc/library/ast.rst ============================================================================== --- python/branches/py3k/Doc/library/ast.rst (original) +++ python/branches/py3k/Doc/library/ast.rst Sat Aug 16 04:59:55 2008 @@ -9,12 +9,6 @@ .. sectionauthor:: Martin v. L?wis .. sectionauthor:: Georg Brandl -.. versionadded:: 2.5 - The low-level ``_ast`` module containing only the node classes. - -.. versionadded:: 2.6 - The high-level ``ast`` module containing all helpers. - The :mod:`ast` module helps Python applications to process trees of the Python abstract syntax grammar. The abstract syntax itself might change with each @@ -113,8 +107,6 @@ :mod:`ast` Helpers ------------------ -.. versionadded:: 2.6 - Apart from the node classes, :mod:`ast` module defines these utility functions and classes for traversing abstract syntax trees: Modified: python/branches/py3k/Doc/library/csv.rst ============================================================================== --- python/branches/py3k/Doc/library/csv.rst (original) +++ python/branches/py3k/Doc/library/csv.rst Sat Aug 16 04:59:55 2008 @@ -381,7 +381,6 @@ initialized upon first access or when the first record is read from the file. - .. versionchanged:: 2.6 Writer Objects Modified: python/branches/py3k/Doc/library/ctypes.rst ============================================================================== --- python/branches/py3k/Doc/library/ctypes.rst (original) +++ python/branches/py3k/Doc/library/ctypes.rst Sat Aug 16 04:59:55 2008 @@ -1859,10 +1859,6 @@ The exact functionality is system dependent. - .. versionchanged:: 2.6 - Windows only: ``find_library("m")`` or - ``find_library("c")`` return the result of a call to - ``find_msvcrt()``. .. function:: find_msvcrt() :module: ctypes.util Modified: python/branches/py3k/Doc/library/inspect.rst ============================================================================== --- python/branches/py3k/Doc/library/inspect.rst (original) +++ python/branches/py3k/Doc/library/inspect.rst Sat Aug 16 04:59:55 2008 @@ -364,8 +364,6 @@ of code. Any whitespace that can be uniformly removed from the second line onwards is removed. Also, all tabs are expanded to spaces. - .. versionadded:: 2.6 - .. _inspect-classes-functions: Modified: python/branches/py3k/Doc/library/logging.rst ============================================================================== --- python/branches/py3k/Doc/library/logging.rst (original) +++ python/branches/py3k/Doc/library/logging.rst Sat Aug 16 04:59:55 2008 @@ -2315,10 +2315,6 @@ in the ``logging`` package's namespace). The ``level`` is interpreted as for loggers, and ``NOTSET`` is taken to mean "log everything". -.. versionchanged:: 2.6 - Added support for resolving the handler's class as a dotted module and class - name. - The ``formatter`` entry indicates the key name of the formatter for this handler. If blank, a default formatter (``logging._defaultFormatter``) is used. If a name is specified, it must appear in the ``[formatters]`` section and have Modified: python/branches/py3k/Doc/library/math.rst ============================================================================== --- python/branches/py3k/Doc/library/math.rst (original) +++ python/branches/py3k/Doc/library/math.rst Sat Aug 16 04:59:55 2008 @@ -88,8 +88,6 @@ The accuracy of fsum() may be impaired on builds that use extended precision addition and then double-round the results. - .. versionadded:: 2.6 - .. function:: isinf(x) Modified: python/branches/py3k/Doc/library/pdb.rst ============================================================================== --- python/branches/py3k/Doc/library/pdb.rst (original) +++ python/branches/py3k/Doc/library/pdb.rst Sat Aug 16 04:59:55 2008 @@ -265,8 +265,6 @@ Continue execution until the line with the the line number greater than the current one is reached or when returning from current frame. - .. versionadded:: 2.6 - r(eturn) Continue execution until the current function returns. Modified: python/branches/py3k/Doc/library/reprlib.rst ============================================================================== --- python/branches/py3k/Doc/library/reprlib.rst (original) +++ python/branches/py3k/Doc/library/reprlib.rst Sat Aug 16 04:59:55 2008 @@ -62,9 +62,6 @@ default is ``4`` for :attr:`maxdict`, ``5`` for :attr:`maxarray`, and ``6`` for the others. - .. versionadded:: 2.4 - :attr:`maxset`, :attr:`maxfrozenset`, and :attr:`set`. - .. attribute:: Repr.maxlong Modified: python/branches/py3k/Doc/library/stdtypes.rst ============================================================================== --- python/branches/py3k/Doc/library/stdtypes.rst (original) +++ python/branches/py3k/Doc/library/stdtypes.rst Sat Aug 16 04:59:55 2008 @@ -1651,25 +1651,16 @@ Update the set, adding elements from *other*. - .. versionchanged:: 2.6 - Accepts multiple input iterables. - .. method:: intersection_update(other, ...) set &= other & ... Update the set, keeping only elements found in it and *other*. - .. versionchanged:: 2.6 - Accepts multiple input iterables. - .. method:: difference_update(other, ...) set -= other | ... Update the set, removing elements found in others. - .. versionchanged:: 2.6 - Accepts multiple input iterables. - .. method:: symmetric_difference_update(other) set ^= other Modified: python/branches/py3k/Doc/library/sys.rst ============================================================================== --- python/branches/py3k/Doc/library/sys.rst (original) +++ python/branches/py3k/Doc/library/sys.rst Sat Aug 16 04:59:55 2008 @@ -332,8 +332,6 @@ func:`getsizeof` calls the object's __sizeof__ method and adds an additional garbage collector overhead if the object is managed by the garbage collector. - .. versionadded:: 2.6 - .. function:: _getframe([depth]) Modified: python/branches/py3k/Doc/library/textwrap.rst ============================================================================== --- python/branches/py3k/Doc/library/textwrap.rst (original) +++ python/branches/py3k/Doc/library/textwrap.rst Sat Aug 16 04:59:55 2008 @@ -181,8 +181,6 @@ you want truly insecable words. Default behaviour in previous versions was to always allow breaking hyphenated words. - .. versionadded:: 2.6 - :class:`TextWrapper` also provides two public methods, analogous to the module-level convenience functions: From python-3000-checkins at python.org Sat Aug 16 15:02:57 2008 From: python-3000-checkins at python.org (martin.v.loewis) Date: Sat, 16 Aug 2008 15:02:57 +0200 (CEST) Subject: [Python-3000-checkins] r65709 - in python/branches/py3k: Misc/NEWS PC/_msi.c Message-ID: <20080816130257.A99601E4009@bag.python.org> Author: martin.v.loewis Date: Sat Aug 16 15:02:57 2008 New Revision: 65709 Log: Bug #3542: Support Unicode strings in _msi module. Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/PC/_msi.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Aug 16 15:02:57 2008 @@ -49,6 +49,11 @@ - Issue #2523: Fix quadratic behaviour when read()ing a binary file without asking for a specific length. +Extension Modules +----------------- + +- Bug #3542: Support Unicode strings in _msi module. + What's new in Python 3.0b2? =========================== Modified: python/branches/py3k/PC/_msi.c ============================================================================== --- python/branches/py3k/PC/_msi.c (original) +++ python/branches/py3k/PC/_msi.c Sat Aug 16 15:02:57 2008 @@ -18,7 +18,7 @@ uuidcreate(PyObject* obj, PyObject*args) { UUID result; - char *cresult; + RPC_WSTR cresult; PyObject *oresult; /* May return ok, local only, and no address. @@ -30,13 +30,13 @@ return NULL; } - if (UuidToString(&result, &cresult) == RPC_S_OUT_OF_MEMORY) { + if (UuidToStringW(&result, &cresult) == RPC_S_OUT_OF_MEMORY) { PyErr_SetString(PyExc_MemoryError, "out of memory in uuidgen"); return NULL; } - oresult = PyBytes_FromString(cresult); - RpcStringFree(&cresult); + oresult = PyUnicode_FromUnicode(cresult, wcslen(cresult)); + RpcStringFreeW(&cresult); return oresult; } @@ -359,23 +359,23 @@ { unsigned int field; unsigned int status; - char buf[2000]; - char *res = buf; + WCHAR buf[2000]; + WCHAR *res = buf; DWORD size = sizeof(buf); PyObject* string; if (!PyArg_ParseTuple(args, "I:GetString", &field)) return NULL; - status = MsiRecordGetString(record->h, field, res, &size); + status = MsiRecordGetStringW(record->h, field, res, &size); if (status == ERROR_MORE_DATA) { - res = (char*) malloc(size + 1); + res = (WCHAR*) malloc((size + 1)*sizeof(WCHAR)); if (res == NULL) return PyErr_NoMemory(); - status = MsiRecordGetString(record->h, field, res, &size); + status = MsiRecordGetStringW(record->h, field, res, &size); } if (status != ERROR_SUCCESS) return msierror((int) status); - string = PyUnicode_FromString(res); + string = PyUnicode_FromUnicode(res, size); if (buf != res) free(res); return string; @@ -397,12 +397,12 @@ { int status; int field; - char *data; + Py_UNICODE *data; - if (!PyArg_ParseTuple(args, "is:SetString", &field, &data)) + if (!PyArg_ParseTuple(args, "iu:SetString", &field, &data)) return NULL; - if ((status = MsiRecordSetString(record->h, field, data)) != ERROR_SUCCESS) + if ((status = MsiRecordSetStringW(record->h, field, data)) != ERROR_SUCCESS) return msierror(status); Py_INCREF(Py_None); @@ -414,12 +414,12 @@ { int status; int field; - char *data; + Py_UNICODE *data; - if (!PyArg_ParseTuple(args, "is:SetStream", &field, &data)) + if (!PyArg_ParseTuple(args, "iu:SetStream", &field, &data)) return NULL; - if ((status = MsiRecordSetStream(record->h, field, data)) != ERROR_SUCCESS) + if ((status = MsiRecordSetStreamW(record->h, field, data)) != ERROR_SUCCESS) return msierror(status); Py_INCREF(Py_None); @@ -586,9 +586,9 @@ if (!PyArg_ParseTuple(args, "iO:SetProperty", &field, &data)) return NULL; - if (PyBytes_Check(data)) { - status = MsiSummaryInfoSetProperty(si->h, field, VT_LPSTR, - 0, NULL, PyBytes_AsString(data)); + if (PyUnicode_Check(data)) { + status = MsiSummaryInfoSetPropertyW(si->h, field, VT_LPSTR, + 0, NULL, PyUnicode_AsUnicode(data)); } else if (PyLong_CheckExact(data)) { long value = PyLong_AsLong(data); if (value == -1 && PyErr_Occurred()) { From python-3000-checkins at python.org Sat Aug 16 16:44:33 2008 From: python-3000-checkins at python.org (facundo.batista) Date: Sat, 16 Aug 2008 16:44:33 +0200 (CEST) Subject: [Python-3000-checkins] r65711 - in python/branches/py3k/Lib: test/test_urllib2.py urllib/request.py Message-ID: <20080816144433.2E51B1E4009@bag.python.org> Author: facundo.batista Date: Sat Aug 16 16:44:32 2008 New Revision: 65711 Log: Issue #2776: fixed small issue when handling an URL with double slash after a 302 response in the case of not going through a proxy. Modified: python/branches/py3k/Lib/test/test_urllib2.py python/branches/py3k/Lib/urllib/request.py Modified: python/branches/py3k/Lib/test/test_urllib2.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllib2.py (original) +++ python/branches/py3k/Lib/test/test_urllib2.py Sat Aug 16 16:44:32 2008 @@ -770,6 +770,34 @@ self.assertEqual(req.unredirected_hdrs["Host"], "baz") self.assertEqual(req.unredirected_hdrs["Spam"], "foo") + def test_http_doubleslash(self): + # Checks the presence of any unnecessary double slash in url does not + # break anything. Previously, a double slash directly after the host + # could could cause incorrect parsing. + h = urllib.request.AbstractHTTPHandler() + o = h.parent = MockOpener() + + data = "" + ds_urls = [ + "http://example.com/foo/bar/baz.html", + "http://example.com//foo/bar/baz.html", + "http://example.com/foo//bar/baz.html", + "http://example.com/foo/bar//baz.html" + ] + + for ds_url in ds_urls: + ds_req = Request(ds_url, data) + + # Check whether host is determined correctly if there is no proxy + np_ds_req = h.do_request_(ds_req) + self.assertEqual(np_ds_req.unredirected_hdrs["Host"],"example.com") + + # Check whether host is determined correctly if there is a proxy + ds_req.set_proxy("someproxy:3128",None) + p_ds_req = h.do_request_(ds_req) + self.assertEqual(p_ds_req.unredirected_hdrs["Host"],"example.com") + + def test_errors(self): h = urllib.request.HTTPErrorProcessor() o = h.parent = MockOpener() Modified: python/branches/py3k/Lib/urllib/request.py ============================================================================== --- python/branches/py3k/Lib/urllib/request.py (original) +++ python/branches/py3k/Lib/urllib/request.py Sat Aug 16 16:44:32 2008 @@ -231,6 +231,9 @@ self.host, self.type = host, type self.__r_host = self.__original + def has_proxy(self): + return self.__r_host == self.__original + def get_origin_req_host(self): return self.origin_req_host @@ -1010,10 +1013,12 @@ request.add_unredirected_header( 'Content-length', '%d' % len(data)) - scheme, sel = splittype(request.get_selector()) - sel_host, sel_path = splithost(sel) + sel_host = host + if request.has_proxy(): + 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) + request.add_unredirected_header('Host', sel_host) for name, value in self.parent.addheaders: name = name.capitalize() if not request.has_header(name): From python-3000-checkins at python.org Sat Aug 16 18:11:03 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 16 Aug 2008 18:11:03 +0200 (CEST) Subject: [Python-3000-checkins] r65712 - in python/branches/py3k: Lib/test/test_exceptions.py Modules/_testcapimodule.c Message-ID: <20080816161103.C54681E4009@bag.python.org> Author: benjamin.peterson Date: Sat Aug 16 18:11:03 2008 New Revision: 65712 Log: add _testcapi.raise_memoryerror to make test_exceptions.test_MemoryError simpler Modified: python/branches/py3k/Lib/test/test_exceptions.py python/branches/py3k/Modules/_testcapimodule.c Modified: python/branches/py3k/Lib/test/test_exceptions.py ============================================================================== --- python/branches/py3k/Lib/test/test_exceptions.py (original) +++ python/branches/py3k/Lib/test/test_exceptions.py Sat Aug 16 18:11:03 2008 @@ -593,9 +593,10 @@ # PyErr_NoMemory always raises the same exception instance. # Check that the traceback is not doubled. import traceback + from _testcapi import raise_memoryerror def raiseMemError(): try: - "a" * (sys.maxsize // 2) + raise_memoryerror() except MemoryError as e: tb = e.__traceback__ else: Modified: python/branches/py3k/Modules/_testcapimodule.c ============================================================================== --- python/branches/py3k/Modules/_testcapimodule.c (original) +++ python/branches/py3k/Modules/_testcapimodule.c Sat Aug 16 18:11:03 2008 @@ -971,8 +971,19 @@ + +/* reliably raise a MemoryError */ +static PyObject * +raise_memoryerror(PyObject *self) +{ + PyErr_NoMemory(); + return NULL; +} + + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, + {"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS}, {"test_config", (PyCFunction)test_config, METH_NOARGS}, {"test_list_api", (PyCFunction)test_list_api, METH_NOARGS}, {"test_dict_iteration", (PyCFunction)test_dict_iteration,METH_NOARGS}, From python-3000-checkins at python.org Sat Aug 16 18:48:16 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 16 Aug 2008 18:48:16 +0200 (CEST) Subject: [Python-3000-checkins] r65714 - in python/branches/py3k: Lib/imghdr.py Message-ID: <20080816164816.C18F31E4002@bag.python.org> Author: benjamin.peterson Date: Sat Aug 16 18:48:16 2008 New Revision: 65714 Log: Merged revisions 65713 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65713 | benjamin.peterson | 2008-08-16 11:29:02 -0500 (Sat, 16 Aug 2008) | 1 line #3424 rearrange the order of tests in imghdr to place more common types first ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/imghdr.py Modified: python/branches/py3k/Lib/imghdr.py ============================================================================== --- python/branches/py3k/Lib/imghdr.py (original) +++ python/branches/py3k/Lib/imghdr.py Sat Aug 16 18:48:16 2008 @@ -34,12 +34,18 @@ tests = [] -def test_rgb(h, f): - """SGI image library""" - if h.startswith(b'\001\332'): - return 'rgb' +def test_jpeg(h, f): + """JPEG data in JFIF or Exif format""" + if h[6:10] in (b'JFIF', b'Exif'): + return 'jpeg' -tests.append(test_rgb) +tests.append(test_jpeg) + +def test_png(h, f): + if h.startswith(b'\211PNG\r\n\032\n'): + return 'png' + +tests.append(test_png) def test_gif(h, f): """GIF ('87 and '89 variants)""" @@ -48,6 +54,20 @@ tests.append(test_gif) +def test_tiff(h, f): + """TIFF (can be in Motorola or Intel byte order)""" + if h[:2] in (b'MM', b'II'): + return 'tiff' + +tests.append(test_tiff) + +def test_rgb(h, f): + """SGI image library""" + if h.startswith(b'\001\332'): + return 'rgb' + +tests.append(test_rgb) + def test_pbm(h, f): """PBM (portable bitmap)""" if len(h) >= 3 and \ @@ -72,13 +92,6 @@ tests.append(test_ppm) -def test_tiff(h, f): - """TIFF (can be in Motorola or Intel byte order)""" - if h[:2] in (b'MM', b'II'): - return 'tiff' - -tests.append(test_tiff) - def test_rast(h, f): """Sun raster file""" if h.startswith(b'\x59\xA6\x6A\x95'): @@ -93,25 +106,12 @@ tests.append(test_xbm) -def test_jpeg(h, f): - """JPEG data in JFIF or Exif format""" - if h[6:10] in (b'JFIF', b'Exif'): - return 'jpeg' - -tests.append(test_jpeg) - def test_bmp(h, f): if h.startswith(b'BM'): return 'bmp' tests.append(test_bmp) -def test_png(h, f): - if h.startswith(b'\211PNG\r\n\032\n'): - return 'png' - -tests.append(test_png) - #--------------------# # Small test program # #--------------------# From python-3000-checkins at python.org Sat Aug 16 23:48:09 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sat, 16 Aug 2008 23:48:09 +0200 (CEST) Subject: [Python-3000-checkins] r65717 - python/branches/py3k Message-ID: <20080816214809.974181E4002@bag.python.org> Author: brett.cannon Date: Sat Aug 16 23:48:09 2008 New Revision: 65717 Log: Blocked revisions 65716 via svnmerge ........ r65716 | brett.cannon | 2008-08-16 14:47:07 -0700 (Sat, 16 Aug 2008) | 5 lines Silence the DeprecationWarning raised by importing mimetools in BaseHTTPServer. This does have an unfortunate side-effect of silencing the warning for all subsequent code that imports mimetools as well since the warning is only executed upon the first import of mimetools. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 16 23:59:25 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sat, 16 Aug 2008 23:59:25 +0200 (CEST) Subject: [Python-3000-checkins] r65720 - python/branches/py3k Message-ID: <20080816215925.41FCD1E4002@bag.python.org> Author: brett.cannon Date: Sat Aug 16 23:59:25 2008 New Revision: 65720 Log: Blocked revisions 65719 via svnmerge ........ r65719 | brett.cannon | 2008-08-16 14:56:03 -0700 (Sat, 16 Aug 2008) | 2 lines Silence the DeprecationWarning raised in httplib when mimetools is imported. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 00:01:29 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sun, 17 Aug 2008 00:01:29 +0200 (CEST) Subject: [Python-3000-checkins] r65722 - python/branches/py3k Message-ID: <20080816220129.C2BAB1E4002@bag.python.org> Author: brett.cannon Date: Sun Aug 17 00:01:29 2008 New Revision: 65722 Log: Blocked revisions 65721 via svnmerge ........ r65721 | brett.cannon | 2008-08-16 15:00:27 -0700 (Sat, 16 Aug 2008) | 2 lines Silence DeprecationWarning raised by mimetools and rfc822 in cgi. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 00:03:18 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Sun, 17 Aug 2008 00:03:18 +0200 (CEST) Subject: [Python-3000-checkins] r65723 - python/branches/py3k/Lib/test/test_os.py Message-ID: <20080816220318.379EF1E4002@bag.python.org> Author: antoine.pitrou Date: Sun Aug 17 00:03:17 2008 New Revision: 65723 Log: #3571: try to fix recurrent buildbot failures by strenghtening test_os.test_closerange Modified: python/branches/py3k/Lib/test/test_os.py Modified: python/branches/py3k/Lib/test/test_os.py ============================================================================== --- python/branches/py3k/Lib/test/test_os.py (original) +++ python/branches/py3k/Lib/test/test_os.py Sun Aug 17 00:03:17 2008 @@ -21,10 +21,27 @@ self.assert_(os.access(support.TESTFN, os.W_OK)) def test_closerange(self): - f = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR) + first = os.open(support.TESTFN, os.O_CREAT|os.O_RDWR) + # We must allocate two consecutive file descriptors, otherwise + # it will mess up other file descriptors (perhaps even the three + # standard ones). + second = os.dup(first) + try: + retries = 0 + while second != first + 1: + os.close(first) + retries += 1 + if retries > 10: + # XXX test skipped + print("couldn't allocate two consecutive fds, " + "skipping test_closerange", file=sys.stderr) + return + first, second = second, os.dup(second) + finally: + os.close(second) # close a fd that is open, and one that isn't - os.closerange(f, f+2) - self.assertRaises(OSError, os.write, f, "a") + os.closerange(first, first + 2) + self.assertRaises(OSError, os.write, first, "a") class TemporaryFileTests(unittest.TestCase): def setUp(self): From python-3000-checkins at python.org Sun Aug 17 01:28:45 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Sun, 17 Aug 2008 01:28:45 +0200 (CEST) Subject: [Python-3000-checkins] r65731 - python/branches/py3k/Lib/test/test_bytes.py Message-ID: <20080816232845.2EDCA1E4002@bag.python.org> Author: antoine.pitrou Date: Sun Aug 17 01:28:44 2008 New Revision: 65731 Log: Issue #3571: test_bytes mistakingly closed stdin Modified: python/branches/py3k/Lib/test/test_bytes.py Modified: python/branches/py3k/Lib/test/test_bytes.py ============================================================================== --- python/branches/py3k/Lib/test/test_bytes.py (original) +++ python/branches/py3k/Lib/test/test_bytes.py Sun Aug 17 01:28:44 2008 @@ -454,7 +454,8 @@ type2test = bytes def test_buffer_is_readonly(self): - with open(sys.stdin.fileno(), "rb", buffering=0) as f: + fd = os.dup(sys.stdin.fileno()) + with open(fd, "rb", buffering=0) as f: self.assertRaises(TypeError, f.readinto, b"") From musiccomposition at gmail.com Sun Aug 17 01:30:36 2008 From: musiccomposition at gmail.com (Benjamin Peterson) Date: Sat, 16 Aug 2008 18:30:36 -0500 Subject: [Python-3000-checkins] r65731 - python/branches/py3k/Lib/test/test_bytes.py In-Reply-To: <20080816232845.2EDCA1E4002@bag.python.org> References: <20080816232845.2EDCA1E4002@bag.python.org> Message-ID: <1afaf6160808161630g78d399aeh56be9b21dbbef6b8@mail.gmail.com> On Sat, Aug 16, 2008 at 6:28 PM, antoine.pitrou wrote: > Author: antoine.pitrou > Date: Sun Aug 17 01:28:44 2008 > New Revision: 65731 > > Log: > Issue #3571: test_bytes mistakingly closed stdin Is this applicable to the trunk? > > > > Modified: > python/branches/py3k/Lib/test/test_bytes.py > > Modified: python/branches/py3k/Lib/test/test_bytes.py > ============================================================================== > --- python/branches/py3k/Lib/test/test_bytes.py (original) > +++ python/branches/py3k/Lib/test/test_bytes.py Sun Aug 17 01:28:44 2008 > @@ -454,7 +454,8 @@ > type2test = bytes > > def test_buffer_is_readonly(self): > - with open(sys.stdin.fileno(), "rb", buffering=0) as f: > + fd = os.dup(sys.stdin.fileno()) > + with open(fd, "rb", buffering=0) as f: > self.assertRaises(TypeError, f.readinto, b"") > > > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > -- Cheers, Benjamin Peterson "There's no place like 127.0.0.1." From solipsis at pitrou.net Sun Aug 17 01:56:31 2008 From: solipsis at pitrou.net (Antoine Pitrou) Date: Sat, 16 Aug 2008 23:56:31 +0000 (UTC) Subject: [Python-3000-checkins] =?utf-8?q?r65731_-=09python/branches/py3k/?= =?utf-8?q?Lib/test/test=5Fbytes=2Epy?= References: <20080816232845.2EDCA1E4002@bag.python.org> <1afaf6160808161630g78d399aeh56be9b21dbbef6b8@mail.gmail.com> Message-ID: Benjamin Peterson gmail.com> writes: > > On Sat, Aug 16, 2008 at 6:28 PM, antoine.pitrou > python.org> wrote: > > Author: antoine.pitrou > > Date: Sun Aug 17 01:28:44 2008 > > New Revision: 65731 > > > > Log: > > Issue #3571: test_bytes mistakingly closed stdin > > Is this applicable to the trunk? No, it was only affecting py3k. cheers Antoine. From python-3000-checkins at python.org Sun Aug 17 02:38:32 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Sun, 17 Aug 2008 02:38:32 +0200 (CEST) Subject: [Python-3000-checkins] r65734 - in python/branches/py3k/Lib: sunau.py test/test_ossaudiodev.py Message-ID: <20080817003832.DE6D11E4002@bag.python.org> Author: antoine.pitrou Date: Sun Aug 17 02:38:32 2008 New Revision: 65734 Log: #3567: fix sunau for running with -bb and make test_ossaudiodev work. Modified: python/branches/py3k/Lib/sunau.py python/branches/py3k/Lib/test/test_ossaudiodev.py Modified: python/branches/py3k/Lib/sunau.py ============================================================================== --- python/branches/py3k/Lib/sunau.py (original) +++ python/branches/py3k/Lib/sunau.py Sun Aug 17 02:38:32 2008 @@ -135,7 +135,7 @@ x = 0 for i in range(4): byte = file.read(1) - if byte == '': + if not byte: raise EOFError x = x*256 + ord(byte) return x @@ -144,10 +144,9 @@ data = [] for i in range(4): d, m = divmod(x, 256) - data.insert(0, m) + data.insert(0, int(m)) x = d - for i in range(4): - file.write(chr(int(data[i]))) + file.write(bytes(data)) class Au_read: @@ -198,7 +197,7 @@ if self._hdr_size > 24: self._info = file.read(self._hdr_size - 24) for i in range(len(self._info)): - if self._info[i] == '\0': + if self._info[i] == b'\0': self._info = self._info[:i] break else: @@ -451,7 +450,7 @@ _write_u32(self._file, self._framerate) _write_u32(self._file, self._nchannels) self._file.write(self._info) - self._file.write('\0'*(header_size - len(self._info) - 24)) + self._file.write(b'\0'*(header_size - len(self._info) - 24)) def _patchheader(self): self._file.seek(8) Modified: python/branches/py3k/Lib/test/test_ossaudiodev.py ============================================================================== --- python/branches/py3k/Lib/test/test_ossaudiodev.py (original) +++ python/branches/py3k/Lib/test/test_ossaudiodev.py Sun Aug 17 02:38:32 2008 @@ -57,7 +57,7 @@ dsp.fileno() # Make sure the read-only attributes work. - self.failUnless(dsp.close) + self.failIf(dsp.closed) self.assertEqual(dsp.name, "/dev/dsp") self.assertEqual(dsp.mode, "w", "bad dsp.mode: %r" % dsp.mode) @@ -65,7 +65,7 @@ for attr in ('closed', 'name', 'mode'): try: setattr(dsp, attr, 42) - except TypeError: + except (TypeError, AttributeError): pass else: self.fail("dsp.%s not read-only" % attr) @@ -75,7 +75,7 @@ # set parameters based on .au file headers dsp.setparameters(AFMT_S16_NE, nchannels, rate) - self.assertEquals("%.2f" % expected_time, "2.93") + self.assertTrue(abs(expected_time - 2.94) < 1e-2, expected_time) t1 = time.time() dsp.write(data) dsp.close() From python-3000-checkins at python.org Sun Aug 17 02:39:46 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Sun, 17 Aug 2008 02:39:46 +0200 (CEST) Subject: [Python-3000-checkins] r65735 - python/branches/py3k Message-ID: <20080817003946.613831E4002@bag.python.org> Author: antoine.pitrou Date: Sun Aug 17 02:39:46 2008 New Revision: 65735 Log: Blocked revisions 65733 via svnmerge ........ r65733 | antoine.pitrou | 2008-08-17 02:36:03 +0200 (dim., 17 ao?t 2008) | 3 lines Make test_ossaudiodev work. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 05:36:03 2008 From: python-3000-checkins at python.org (facundo.batista) Date: Sun, 17 Aug 2008 05:36:03 +0200 (CEST) Subject: [Python-3000-checkins] r65740 - python/branches/py3k/Lib/urllib/request.py Message-ID: <20080817033603.999D21E4011@bag.python.org> Author: facundo.batista Date: Sun Aug 17 05:36:03 2008 New Revision: 65740 Log: Issue 2464. Supports a malformation in the URL received in a redirect. Modified: python/branches/py3k/Lib/urllib/request.py Modified: python/branches/py3k/Lib/urllib/request.py ============================================================================== --- python/branches/py3k/Lib/urllib/request.py (original) +++ python/branches/py3k/Lib/urllib/request.py Sun Aug 17 05:36:03 2008 @@ -100,7 +100,7 @@ from urllib.parse import ( urlparse, urlsplit, urljoin, unwrap, quote, unquote, splittype, splithost, splitport, splituser, splitpasswd, - splitattr, splitquery, splitvalue, to_bytes) + splitattr, splitquery, splitvalue, to_bytes, urlunparse) from urllib.response import addinfourl, addclosehook # check for SSL @@ -535,6 +535,14 @@ newurl = headers["uri"] else: return + + # fix a possible malformed URL + urlparts = urlparse(newurl) + if not urlparts.path: + urlparts = list(urlparts) + urlparts[2] = "/" + newurl = urlunparse(urlparts) + newurl = urljoin(req.get_full_url(), newurl) # XXX Probably want to forget about the state of the current From python-3000-checkins at python.org Sun Aug 17 06:28:14 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Sun, 17 Aug 2008 06:28:14 +0200 (CEST) Subject: [Python-3000-checkins] r65743 - python/branches/py3k Message-ID: <20080817042814.D79CE1E4002@bag.python.org> Author: brett.cannon Date: Sun Aug 17 06:28:14 2008 New Revision: 65743 Log: Blocked revisions 65742 via svnmerge ........ r65742 | brett.cannon | 2008-08-16 21:16:04 -0700 (Sat, 16 Aug 2008) | 2 lines Update distutils so that it triggers no warnings when run under -3. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 09:26:26 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Sun, 17 Aug 2008 09:26:26 +0200 (CEST) Subject: [Python-3000-checkins] r65744 - python/branches/py3k/PC/_msi.c Message-ID: <20080817072626.869601E400A@bag.python.org> Author: hirokazu.yamamoto Date: Sun Aug 17 09:26:26 2008 New Revision: 65744 Log: RPC_WSTR is not available Visual Studio 2003 or earlier. (Maybe I should have defined RPC_WSTR on old compiler, but uuidcreate() is only place using it, so I simply replaced with unsigned short *) Modified: python/branches/py3k/PC/_msi.c Modified: python/branches/py3k/PC/_msi.c ============================================================================== --- python/branches/py3k/PC/_msi.c (original) +++ python/branches/py3k/PC/_msi.c Sun Aug 17 09:26:26 2008 @@ -18,7 +18,7 @@ uuidcreate(PyObject* obj, PyObject*args) { UUID result; - RPC_WSTR cresult; + unsigned short *cresult; PyObject *oresult; /* May return ok, local only, and no address. From python-3000-checkins at python.org Sun Aug 17 11:30:16 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Sun, 17 Aug 2008 11:30:16 +0200 (CEST) Subject: [Python-3000-checkins] r65746 - in python/branches/py3k: Modules/posixmodule.c Message-ID: <20080817093016.4F40B1E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sun Aug 17 11:30:15 2008 New Revision: 65746 Log: Merged revisions 65745 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65745 | hirokazu.yamamoto | 2008-08-17 18:19:52 +0900 | 2 lines Issue #2222: Fixed reference leak when occured os.rename() fails unicode conversion on 2nd parameter. (windows only) ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Modules/posixmodule.c Modified: python/branches/py3k/Modules/posixmodule.c ============================================================================== --- python/branches/py3k/Modules/posixmodule.c (original) +++ python/branches/py3k/Modules/posixmodule.c Sun Aug 17 11:30:15 2008 @@ -503,24 +503,18 @@ { } -/* Function suitable for O& conversion */ static int -convert_to_unicode(PyObject *arg, void* _param) +convert_to_unicode(PyObject **param) { - PyObject **param = (PyObject**)_param; - if (PyUnicode_CheckExact(arg)) { - Py_INCREF(arg); - *param = arg; - } - else if (PyUnicode_Check(arg)) { + if (PyUnicode_CheckExact(*param)) + Py_INCREF(*param); + else if (PyUnicode_Check(*param)) /* For a Unicode subtype that's not a Unicode object, return a true Unicode object with the same data. */ - *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(arg), - PyUnicode_GET_SIZE(arg)); - return *param != NULL; - } + *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(*param), + PyUnicode_GET_SIZE(*param)); else - *param = PyUnicode_FromEncodedObject(arg, + *param = PyUnicode_FromEncodedObject(*param, Py_FileSystemDefaultEncoding, "strict"); return (*param) != NULL; @@ -2568,22 +2562,26 @@ char *p1, *p2; BOOL result; if (unicode_file_names()) { - if (!PyArg_ParseTuple(args, "O&O&:rename", - convert_to_unicode, &o1, - convert_to_unicode, &o2)) - PyErr_Clear(); - else { - Py_BEGIN_ALLOW_THREADS - result = MoveFileW(PyUnicode_AsUnicode(o1), - PyUnicode_AsUnicode(o2)); - Py_END_ALLOW_THREADS - Py_DECREF(o1); - Py_DECREF(o2); - if (!result) - return win32_error("rename", NULL); - Py_INCREF(Py_None); - return Py_None; + if (!PyArg_ParseTuple(args, "OO:rename", &o1, &o2)) + goto error; + if (!convert_to_unicode(&o1)) + goto error; + if (!convert_to_unicode(&o2)) { + Py_DECREF(o1); + goto error; } + Py_BEGIN_ALLOW_THREADS + result = MoveFileW(PyUnicode_AsUnicode(o1), + PyUnicode_AsUnicode(o2)); + Py_END_ALLOW_THREADS + Py_DECREF(o1); + Py_DECREF(o2); + if (!result) + return win32_error("rename", NULL); + Py_INCREF(Py_None); + return Py_None; +error: + PyErr_Clear(); } if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2)) return NULL; From python-3000-checkins at python.org Sun Aug 17 11:52:29 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Sun, 17 Aug 2008 11:52:29 +0200 (CEST) Subject: [Python-3000-checkins] r65750 - python/branches/py3k/Misc/NEWS Message-ID: <20080817095229.3BF351E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sun Aug 17 11:52:28 2008 New Revision: 65750 Log: I forgot to update NEWS. Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 17 11:52:28 2008 @@ -30,6 +30,9 @@ Library ------- +- Issue #2222: Fixed reference leak when occured os.rename() + fails unicode conversion on 2nd parameter. (windows only) + - Issue #3476: binary buffered reading through the new "io" library is now thread-safe. From python-3000-checkins at python.org Sun Aug 17 11:57:45 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Sun, 17 Aug 2008 11:57:45 +0200 (CEST) Subject: [Python-3000-checkins] r65751 - python/branches/py3k Message-ID: <20080817095745.871D11E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sun Aug 17 11:57:45 2008 New Revision: 65751 Log: Blocked revisions 65748 via svnmerge ........ r65748 | hirokazu.yamamoto | 2008-08-17 18:46:56 +0900 | 1 line I forgot to update NEWS. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 14:59:58 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Sun, 17 Aug 2008 14:59:58 +0200 (CEST) Subject: [Python-3000-checkins] r65760 - in python/branches/py3k: Misc/NEWS Modules/cjkcodecs/multibytecodec.c Message-ID: <20080817125958.139931E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sun Aug 17 14:59:57 2008 New Revision: 65760 Log: Issue #3575: Incremental decoder's decode function now takes bytearray by using 's*' instead of 't#' Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/cjkcodecs/multibytecodec.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 17 14:59:57 2008 @@ -30,6 +30,9 @@ Library ------- +- Issue #3575: Incremental decoder's decode function now takes bytearray + by using 's*' instead of 't#'. + - Issue #2222: Fixed reference leak when occured os.rename() fails unicode conversion on 2nd parameter. (windows only) Modified: python/branches/py3k/Modules/cjkcodecs/multibytecodec.c ============================================================================== --- python/branches/py3k/Modules/cjkcodecs/multibytecodec.c (original) +++ python/branches/py3k/Modules/cjkcodecs/multibytecodec.c Sun Aug 17 14:59:57 2008 @@ -1034,12 +1034,15 @@ { MultibyteDecodeBuffer buf; char *data, *wdata = NULL; + Py_buffer pdata; Py_ssize_t wsize, finalsize = 0, size, origpending; int final = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "t#|i:decode", - incrementalkwarglist, &data, &size, &final)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|i:decode", + incrementalkwarglist, &pdata, &final)) return NULL; + data = pdata.buf; + size = pdata.len; buf.outobj = buf.excobj = NULL; origpending = self->pendingsize; @@ -1088,12 +1091,14 @@ if (PyUnicode_Resize(&buf.outobj, finalsize) == -1) goto errorexit; + PyBuffer_Release(&pdata); if (wdata != data) PyMem_Del(wdata); Py_XDECREF(buf.excobj); return buf.outobj; errorexit: + PyBuffer_Release(&pdata); if (wdata != NULL && wdata != data) PyMem_Del(wdata); Py_XDECREF(buf.excobj); From g.brandl at gmx.net Sun Aug 17 16:19:03 2008 From: g.brandl at gmx.net (Georg Brandl) Date: Sun, 17 Aug 2008 16:19:03 +0200 Subject: [Python-3000-checkins] r65750 - python/branches/py3k/Misc/NEWS In-Reply-To: <20080817095229.3BF351E4002@bag.python.org> References: <20080817095229.3BF351E4002@bag.python.org> Message-ID: hirokazu.yamamoto schrieb: > Author: hirokazu.yamamoto > Date: Sun Aug 17 11:52:28 2008 > New Revision: 65750 > > Log: > I forgot to update NEWS. > > Modified: > python/branches/py3k/Misc/NEWS > > Modified: python/branches/py3k/Misc/NEWS > ============================================================================== > --- python/branches/py3k/Misc/NEWS (original) > +++ python/branches/py3k/Misc/NEWS Sun Aug 17 11:52:28 2008 > @@ -30,6 +30,9 @@ > Library > ------- > > +- Issue #2222: Fixed reference leak when occured os.rename() > + fails unicode conversion on 2nd parameter. (windows only) > + > - Issue #3476: binary buffered reading through the new "io" library is now > thread-safe. NEWS items from 2.6 don't need to be merged to 3.0. Georg -- Thus spake the Lord: Thou shalt indent with four spaces. No more, no less. Four shall be the number of spaces thou shalt indent, and the number of thy indenting shall be four. Eight shalt thou not indent, nor either indent thou two, excepting that thou then proceed to four. Tabs are right out. From python-3000-checkins at python.org Sun Aug 17 16:44:35 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Sun, 17 Aug 2008 16:44:35 +0200 (CEST) Subject: [Python-3000-checkins] r65769 - python/branches/py3k Message-ID: <20080817144435.8DE781E4002@bag.python.org> Author: antoine.pitrou Date: Sun Aug 17 16:44:35 2008 New Revision: 65769 Log: Blocked revisions 65768 via svnmerge ........ r65768 | antoine.pitrou | 2008-08-17 16:43:41 +0200 (dim., 17 ao?t 2008) | 3 lines backport r65723: strengthen test_os.test_closerange ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 17:16:18 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Sun, 17 Aug 2008 17:16:18 +0200 (CEST) Subject: [Python-3000-checkins] r65770 - python/branches/py3k Message-ID: <20080817151618.7493D1E4011@bag.python.org> Author: hirokazu.yamamoto Date: Sun Aug 17 17:16:18 2008 New Revision: 65770 Log: Blocked revisions 65762 via svnmerge ........ r65762 | hirokazu.yamamoto | 2008-08-17 22:10:46 +0900 | 2 lines Backport r65661, r65760: Issue #3575: Incremental decoder's decode function now takes bytearray by using 's*' instead of 't#'. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 17:24:17 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Sun, 17 Aug 2008 17:24:17 +0200 (CEST) Subject: [Python-3000-checkins] r65771 - python/branches/py3k/Misc/NEWS Message-ID: <20080817152417.60CD31E4002@bag.python.org> Author: hirokazu.yamamoto Date: Sun Aug 17 17:24:17 2008 New Revision: 65771 Log: NEWS items from 2.6 don't need to be merged to 3.0. http://mail.python.org/pipermail/python-3000-checkins/2008-August/004301.html Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 17 17:24:17 2008 @@ -30,12 +30,6 @@ Library ------- -- Issue #3575: Incremental decoder's decode function now takes bytearray - by using 's*' instead of 't#'. - -- Issue #2222: Fixed reference leak when occured os.rename() - fails unicode conversion on 2nd parameter. (windows only) - - Issue #3476: binary buffered reading through the new "io" library is now thread-safe. From python-3000-checkins at python.org Sun Aug 17 19:06:51 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Sun, 17 Aug 2008 19:06:51 +0200 (CEST) Subject: [Python-3000-checkins] r65774 - in python/branches/py3k: Lib/test/test_unicode.py Message-ID: <20080817170651.EF6AE1E400A@bag.python.org> Author: antoine.pitrou Date: Sun Aug 17 19:06:51 2008 New Revision: 65774 Log: Merged revisions 65773 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65773 | antoine.pitrou | 2008-08-17 19:01:49 +0200 (dim., 17 ao?t 2008) | 3 lines #3556: test_raiseMemError consumes an insane amount of memory ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_unicode.py Modified: python/branches/py3k/Lib/test/test_unicode.py ============================================================================== --- python/branches/py3k/Lib/test/test_unicode.py (original) +++ python/branches/py3k/Lib/test/test_unicode.py Sun Aug 17 19:06:51 2008 @@ -1155,20 +1155,15 @@ return self.assertRaises(OverflowError, 't\tt\t'.expandtabs, sys.maxsize) - def test_raiseMemError(self): # Ensure that the freelist contains a consistent object, even # when a string allocation fails with a MemoryError. # This used to crash the interpreter, # or leak references when the number was smaller. - try: - "a" * (sys.maxsize // 2 - 100) - except MemoryError: - pass - try: - "a" * (sys.maxsize // 2 - 100) - except MemoryError: - pass + alloc = lambda: "a" * (sys.maxsize - 100) + self.assertRaises(MemoryError, alloc) + self.assertRaises(MemoryError, alloc) + def test_main(): support.run_unittest(__name__) From python-3000-checkins at python.org Sun Aug 17 19:15:26 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sun, 17 Aug 2008 19:15:26 +0200 (CEST) Subject: [Python-3000-checkins] r65776 - python/branches/py3k Message-ID: <20080817171526.1B0421E400A@bag.python.org> Author: benjamin.peterson Date: Sun Aug 17 19:15:25 2008 New Revision: 65776 Log: Blocked revisions 65741 via svnmerge ........ r65741 | facundo.batista | 2008-08-16 22:38:39 -0500 (Sat, 16 Aug 2008) | 4 lines Issue 2464. Supports a malformation in the URL received in a redirect. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 20:02:45 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sun, 17 Aug 2008 20:02:45 +0200 (CEST) Subject: [Python-3000-checkins] r65777 - in python/branches/py3k: Doc/library/language.rst Doc/library/symtable.rst Include/symtable.h Lib/symtable.py Lib/test/test_symtable.py Modules/symtablemodule.c Python/symtable.c Message-ID: <20080817180245.63DBB1E400A@bag.python.org> Author: benjamin.peterson Date: Sun Aug 17 20:02:44 2008 New Revision: 65777 Log: Merged revisions 65715,65724,65726,65732,65736-65739,65775 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65715 | benjamin.peterson | 2008-08-16 16:04:16 -0500 (Sat, 16 Aug 2008) | 1 line add some documentation for symtable ........ r65724 | benjamin.peterson | 2008-08-16 17:11:33 -0500 (Sat, 16 Aug 2008) | 2 lines include filename and line number in SyntaxError ........ r65726 | georg.brandl | 2008-08-16 17:37:05 -0500 (Sat, 16 Aug 2008) | 2 lines Review symtable docs. ........ r65732 | benjamin.peterson | 2008-08-16 18:29:40 -0500 (Sat, 16 Aug 2008) | 1 line PySTEntry's constructor is static; there's no point in a fancy API name ........ r65736 | benjamin.peterson | 2008-08-16 20:09:17 -0500 (Sat, 16 Aug 2008) | 1 line expose PySTEntry.nested so the symtable module will work ........ r65737 | benjamin.peterson | 2008-08-16 20:17:15 -0500 (Sat, 16 Aug 2008) | 1 line a few improvements ........ r65738 | benjamin.peterson | 2008-08-16 20:27:30 -0500 (Sat, 16 Aug 2008) | 1 line fix compile errors ........ r65739 | benjamin.peterson | 2008-08-16 21:23:43 -0500 (Sat, 16 Aug 2008) | 1 line uhh PySTEntry->ste_unoptimized has to be exposed too ........ r65775 | benjamin.peterson | 2008-08-17 12:13:26 -0500 (Sun, 17 Aug 2008) | 5 lines get the symtable module back in working order - Fix broken functions - Add (hopefully) extensive tests - Modernize a little ........ Added: python/branches/py3k/Doc/library/symtable.rst - copied, changed from r65715, /python/trunk/Doc/library/symtable.rst Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/language.rst python/branches/py3k/Include/symtable.h python/branches/py3k/Lib/symtable.py python/branches/py3k/Lib/test/test_symtable.py python/branches/py3k/Modules/symtablemodule.c python/branches/py3k/Python/symtable.c Modified: python/branches/py3k/Doc/library/language.rst ============================================================================== --- python/branches/py3k/Doc/library/language.rst (original) +++ python/branches/py3k/Doc/library/language.rst Sun Aug 17 20:02:44 2008 @@ -16,6 +16,7 @@ parser.rst ast.rst + symtable.rst symbol.rst token.rst keyword.rst Copied: python/branches/py3k/Doc/library/symtable.rst (from r65715, /python/trunk/Doc/library/symtable.rst) ============================================================================== --- /python/trunk/Doc/library/symtable.rst (original) +++ python/branches/py3k/Doc/library/symtable.rst Sun Aug 17 20:02:44 2008 @@ -1,6 +1,5 @@ - -:mod:`symtable` -- Access to the compiler's symbol tables -========================================================= +:mod:`symtable` --- Access to the compiler's symbol tables +========================================================== .. module:: symtable :synopsis: Interface to the compiler's internal symbol tables. @@ -20,7 +19,7 @@ .. function:: symtable(code, filename, compile_type) - Return the toplevel :class:`SymbolTable` for the Python source, *code*. + Return the toplevel :class:`SymbolTable` for the Python source *code*. *filename* is the name of the file containing the code. *compile_type* is like the *mode* argument to :func:`compile`. @@ -32,7 +31,6 @@ A namespace table for a block. The constructor is not public. - .. method:: get_type() Return the type of the symbol table. Possible values are ``'class'``, @@ -46,7 +44,7 @@ Return the table's name. This is the name of the class if the table is for a class, the name of the function if the table is for a function, or - ``'top'`` if the table is global. + ``'top'`` if the table is global (:meth:`get_type` returns ``'module'``). .. method:: get_lineno() @@ -58,7 +56,7 @@ .. method:: is_nested() - Return ``True`` if the block is nested in another. + Return ``True`` if the block is a nested class or function. .. method:: has_children() @@ -71,7 +69,7 @@ .. method:: has_import_start() - Return ``True`` if the block uses a starred import. + Return ``True`` if the block uses a starred from-import. .. method:: get_identifiers() @@ -95,7 +93,6 @@ A namespace for a function or method. This class inherits :class:`SymbolTable`. - .. method:: get_parameters() Return a tuple containing names of parameters to this function. @@ -124,7 +121,7 @@ .. class:: Symbol - An entry in a :class:`SymbolTable` corresponding to a identifier in the + An entry in a :class:`SymbolTable` corresponding to an identifier in the source. The constructor is not public. .. method:: get_name() @@ -153,7 +150,8 @@ .. method:: is_kewordarg() - Return ``True`` if symbol is a starred arg (receives keywrod arguments). + Return ``True`` if the symbol is a two-star arg (receives keyword + arguments). .. method:: is_local() @@ -161,7 +159,8 @@ .. method:: is_free() - Return ``True`` if the symbol is used in its block, but not declared. + Return ``True`` if the symbol is referenced in its block, but not assigned + to. .. method:: is_assigned() Modified: python/branches/py3k/Include/symtable.h ============================================================================== --- python/branches/py3k/Include/symtable.h (original) +++ python/branches/py3k/Include/symtable.h Sun Aug 17 20:02:44 2008 @@ -36,7 +36,7 @@ PyObject *ste_children; /* list of child blocks */ _Py_block_ty ste_type; /* module, class, or function */ int ste_unoptimized; /* false if namespace is optimized */ - unsigned ste_nested : 1; /* true if block is nested */ + int ste_nested; /* true if block is nested */ unsigned ste_free : 1; /* true if block has free variables */ unsigned ste_child_free : 1; /* true if a child block has free vars, including free refs to globals */ Modified: python/branches/py3k/Lib/symtable.py ============================================================================== --- python/branches/py3k/Lib/symtable.py (original) +++ python/branches/py3k/Lib/symtable.py Sun Aug 17 20:02:44 2008 @@ -1,10 +1,11 @@ """Interface to the compiler's internal symbol tables""" import _symtable -from _symtable import USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM, \ - DEF_STAR, DEF_DOUBLESTAR, DEF_INTUPLE, DEF_FREE, \ - DEF_FREE_GLOBAL, DEF_FREE_CLASS, DEF_IMPORT, DEF_BOUND, \ - OPT_IMPORT_STAR +from _symtable import (USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM, + DEF_STAR, DEF_DOUBLESTAR, DEF_INTUPLE, DEF_FREE, + DEF_FREE_GLOBAL, DEF_FREE_CLASS, DEF_IMPORT, DEF_BOUND, + OPT_IMPORT_STAR, SCOPE_OFF, SCOPE_MASK, FREE, + GLOBAL_IMPLICIT, GLOBAL_EXPLICIT) import weakref @@ -38,15 +39,9 @@ newSymbolTable = SymbolTableFactory() -def is_free(flags): - if (flags & (USE | DEF_FREE)) \ - and (flags & (DEF_LOCAL | DEF_PARAM | DEF_GLOBAL)): - return True - if flags & DEF_FREE_CLASS: - return True - return False -class SymbolTable: +class SymbolTable(object): + def __init__(self, raw_table, filename): self._table = raw_table self._filename = filename @@ -59,10 +54,11 @@ kind = "%s " % self.__class__.__name__ if self._table.name == "global": - return "<%sSymbolTable for module %s>" % (kind, self._filename) + return "<{0}SymbolTable for module {1}>".format(kind, self._filename) else: - return "<%sSymbolTable for %s in %s>" % (kind, self._table.name, - self._filename) + return "<{0}SymbolTable for {1} in {2}>".format(kind, + self._table.name, + self._filename) def get_type(self): if self._table.type == _symtable.TYPE_MODULE: @@ -72,7 +68,7 @@ if self._table.type == _symtable.TYPE_CLASS: return "class" assert self._table.type in (1, 2, 3), \ - "unexpected type: %s" % self._table.type + "unexpected type: {0}".format(self._table.type) def get_id(self): return self._table.id @@ -124,6 +120,7 @@ return [newSymbolTable(st, self._filename) for st in self._table.children] + class Function(SymbolTable): # Default values for instance variables @@ -148,15 +145,18 @@ def get_globals(self): if self.__globals is None: - glob = DEF_GLOBAL | DEF_FREE_GLOBAL - self.__globals = self.__idents_matching(lambda x:x & glob) + glob = (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT) + test = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) in glob + self.__globals = self.__idents_matching(test) return self.__globals def get_frees(self): if self.__frees is None: + is_free = lambda x:((x >> SCOPE_OFF) & SCOPE_MASK) == FREE self.__frees = self.__idents_matching(is_free) return self.__frees + class Class(SymbolTable): __methods = None @@ -169,14 +169,17 @@ self.__methods = tuple(d) return self.__methods -class Symbol: + +class Symbol(object): + def __init__(self, name, flags, namespaces=None): self.__name = name self.__flags = flags + self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope() self.__namespaces = namespaces or () def __repr__(self): - return "" % self.__name + return "".format(self.__name) def get_name(self): return self.__name @@ -188,8 +191,7 @@ return bool(self.__flags & DEF_PARAM) def is_global(self): - return bool((self.__flags & DEF_GLOBAL) - or (self.__flags & DEF_FREE_GLOBAL)) + return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)) def is_vararg(self): return bool(self.__flags & DEF_STAR) @@ -201,12 +203,7 @@ return bool(self.__flags & DEF_BOUND) def is_free(self): - if (self.__flags & (USE | DEF_FREE)) \ - and (self.__flags & (DEF_LOCAL | DEF_PARAM | DEF_GLOBAL)): - return True - if self.__flags & DEF_FREE_CLASS: - return True - return False + return bool(self.__scope == FREE) def is_imported(self): return bool(self.__flags & DEF_IMPORT) Modified: python/branches/py3k/Lib/test/test_symtable.py ============================================================================== --- python/branches/py3k/Lib/test/test_symtable.py (original) +++ python/branches/py3k/Lib/test/test_symtable.py Sun Aug 17 20:02:44 2008 @@ -1,31 +1,161 @@ -from test import support - +""" +Test the API of the symtable module. +""" import symtable import unittest +from test import support + + +TEST_CODE = """ +import sys -## XXX -## Test disabled because symtable module needs to be rewritten for new compiler +glob = 42 -##vereq(symbols[0].name, "global") -##vereq(len([ste for ste in symbols.values() if ste.name == "f"]), 1) +class Mine: + instance_var = 24 + def a_method(p1, p2): + pass + +def spam(a, b, *var, **kw): + global bar + bar = 47 + x = 23 + glob + def internal(): + return x + return internal + +def foo(): + pass + +def namespace_test(): pass +def namespace_test(): pass +""" + + +def find_block(block, name): + for ch in block.get_children(): + if ch.get_name() == name: + return ch -### Bug tickler: SyntaxError file name correct whether error raised -### while parsing or building symbol table. -##def checkfilename(brokencode): -## try: -## _symtable.symtable(brokencode, "spam", "exec") -## except SyntaxError, e: -## vereq(e.filename, "spam") -## else: -## raise TestFailed("no SyntaxError for %r" % (brokencode,)) -##checkfilename("def f(x): foo)(") # parse-time -##checkfilename("def f(x): global x") # symtable-build-time class SymtableTest(unittest.TestCase): - def test_invalid_args(self): - self.assertRaises(TypeError, symtable.symtable, "42") - self.assertRaises(ValueError, symtable.symtable, "42", "?", "") + + top = symtable.symtable(TEST_CODE, "?", "exec") + # These correspond to scopes in TEST_CODE + Mine = find_block(top, "Mine") + a_method = find_block(Mine, "a_method") + spam = find_block(top, "spam") + internal = find_block(spam, "internal") + foo = find_block(top, "foo") + + def test_type(self): + self.assertEqual(self.top.get_type(), "module") + self.assertEqual(self.Mine.get_type(), "class") + self.assertEqual(self.a_method.get_type(), "function") + self.assertEqual(self.spam.get_type(), "function") + self.assertEqual(self.internal.get_type(), "function") + + def test_optimized(self): + self.assertFalse(self.top.is_optimized()) + self.assertFalse(self.top.has_exec()) + + self.assertTrue(self.spam.is_optimized()) + + def test_nested(self): + self.assertFalse(self.top.is_nested()) + self.assertFalse(self.Mine.is_nested()) + self.assertFalse(self.spam.is_nested()) + self.assertTrue(self.internal.is_nested()) + + def test_children(self): + self.assertTrue(self.top.has_children()) + self.assertTrue(self.Mine.has_children()) + self.assertFalse(self.foo.has_children()) + + def test_lineno(self): + self.assertEqual(self.top.get_lineno(), 0) + self.assertEqual(self.spam.get_lineno(), 11) + + def test_function_info(self): + func = self.spam + self.assertEqual(func.get_parameters(), ("a", "b", "kw", "var")) + self.assertEqual(func.get_locals(), + ("a", "b", "bar", "glob", "internal", "kw", "var", "x")) + self.assertEqual(func.get_globals(), ("bar", "glob")) + self.assertEqual(self.internal.get_frees(), ("x",)) + + def test_globals(self): + self.assertTrue(self.spam.lookup("glob").is_global()) + self.assertTrue(self.spam.lookup("bar").is_global()) + self.assertFalse(self.internal.lookup("x").is_global()) + self.assertFalse(self.Mine.lookup("instance_var").is_global()) + + def test_local(self): + self.assertTrue(self.spam.lookup("x").is_local()) + self.assertFalse(self.internal.lookup("x").is_local()) + + def test_referenced(self): + self.assertTrue(self.internal.lookup("x").is_referenced()) + self.assertTrue(self.spam.lookup("internal").is_referenced()) + self.assertFalse(self.spam.lookup("x").is_referenced()) + + def test_parameters(self): + for sym in ("a", "var", "kw"): + self.assertTrue(self.spam.lookup(sym).is_parameter()) + self.assertFalse(self.spam.lookup("x").is_parameter()) + + def test_symbol_lookup(self): + self.assertEqual(len(self.top.get_identifiers()), + len(self.top.get_symbols())) + + self.assertRaises(KeyError, self.top.lookup, "not_here") + + def test_namespaces(self): + self.assertTrue(self.top.lookup("Mine").is_namespace()) + self.assertTrue(self.Mine.lookup("a_method").is_namespace()) + self.assertTrue(self.top.lookup("spam").is_namespace()) + self.assertTrue(self.spam.lookup("internal").is_namespace()) + self.assertTrue(self.top.lookup("namespace_test").is_namespace()) + self.assertFalse(self.spam.lookup("x").is_namespace()) + + self.assert_(self.top.lookup("spam").get_namespace() is self.spam) + ns_test = self.top.lookup("namespace_test") + self.assertEqual(len(ns_test.get_namespaces()), 2) + self.assertRaises(ValueError, ns_test.get_namespace) + + def test_assigned(self): + self.assertTrue(self.spam.lookup("x").is_assigned()) + self.assertTrue(self.spam.lookup("bar").is_assigned()) + self.assertTrue(self.top.lookup("spam").is_assigned()) + self.assertTrue(self.Mine.lookup("a_method").is_assigned()) + self.assertFalse(self.internal.lookup("x").is_assigned()) + + def test_imported(self): + self.assertTrue(self.top.lookup("sys").is_imported()) + + def test_name(self): + self.assertEqual(self.top.get_name(), "top") + self.assertEqual(self.spam.get_name(), "spam") + self.assertEqual(self.spam.lookup("x").get_name(), "x") + self.assertEqual(self.Mine.get_name(), "Mine") + + def test_class_info(self): + self.assertEqual(self.Mine.get_methods(), ('a_method',)) + + def test_filename_correct(self): + ### Bug tickler: SyntaxError file name correct whether error raised + ### while parsing or building symbol table. + def checkfilename(brokencode): + try: + symtable.symtable(brokencode, "spam", "exec") + except SyntaxError as e: + self.assertEqual(e.filename, "spam") + else: + self.fail("no SyntaxError for %r" % (brokencode,)) + checkfilename("def f(x): foo)(") # parse-time + checkfilename("def f(x): global x") # symtable-build-time def test_eval(self): symbols = symtable.symtable("42", "?", "eval") Modified: python/branches/py3k/Modules/symtablemodule.c ============================================================================== --- python/branches/py3k/Modules/symtablemodule.c (original) +++ python/branches/py3k/Modules/symtablemodule.c Sun Aug 17 20:02:44 2008 @@ -92,6 +92,10 @@ PyModule_AddIntConstant(m, "GLOBAL_IMPLICIT", GLOBAL_IMPLICIT); PyModule_AddIntConstant(m, "FREE", FREE); PyModule_AddIntConstant(m, "CELL", CELL); + + PyModule_AddIntConstant(m, "SCOPE_OFF", SCOPE_OFFSET); + PyModule_AddIntConstant(m, "SCOPE_MASK", SCOPE_MASK); + if (PyErr_Occurred()) { Py_DECREF(m); m = 0; Modified: python/branches/py3k/Python/symtable.c ============================================================================== --- python/branches/py3k/Python/symtable.c (original) +++ python/branches/py3k/Python/symtable.c Sun Aug 17 20:02:44 2008 @@ -22,9 +22,9 @@ #define RETURN_VAL_IN_GENERATOR \ "'return' with argument inside generator" -/* XXX(nnorwitz): change name since static? */ + static PySTEntryObject * -PySTEntry_New(struct symtable *st, identifier name, _Py_block_ty block, +ste_new(struct symtable *st, identifier name, _Py_block_ty block, void *key, int lineno) { PySTEntryObject *ste = NULL; @@ -114,6 +114,8 @@ {"symbols", T_OBJECT, OFF(ste_symbols), READONLY}, {"varnames", T_OBJECT, OFF(ste_varnames), READONLY}, {"children", T_OBJECT, OFF(ste_children), READONLY}, + {"optimized",T_INT, OFF(ste_unoptimized), READONLY}, + {"nested", T_INT, OFF(ste_nested), READONLY}, {"type", T_INT, OFF(ste_type), READONLY}, {"lineno", T_INT, OFF(ste_lineno), READONLY}, {NULL} @@ -388,6 +390,9 @@ PyErr_Format(PyExc_SyntaxError, "name '%U' is parameter and global", name); + PyErr_SyntaxLocation(ste->ste_table->st_filename, + ste->ste_lineno); + return 0; } if (flags & DEF_NONLOCAL) { @@ -788,7 +793,7 @@ return 1; } -/* symtable_enter_block() gets a reference via PySTEntry_New(). +/* symtable_enter_block() gets a reference via ste_new. This reference is released when the block is exited, via the DECREF in symtable_exit_block(). */ @@ -825,7 +830,7 @@ } Py_DECREF(st->st_cur); } - st->st_cur = PySTEntry_New(st, name, block, ast, lineno); + st->st_cur = ste_new(st, name, block, ast, lineno); if (st->st_cur == NULL) return 0; if (name == GET_IDENTIFIER(top)) From python-3000-checkins at python.org Sun Aug 17 20:57:58 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sun, 17 Aug 2008 20:57:58 +0200 (CEST) Subject: [Python-3000-checkins] r65778 - python/branches/py3k/Doc/c-api/init.rst Message-ID: <20080817185758.9E4E01E400A@bag.python.org> Author: benjamin.peterson Date: Sun Aug 17 20:57:58 2008 New Revision: 65778 Log: correct return type Modified: python/branches/py3k/Doc/c-api/init.rst Modified: python/branches/py3k/Doc/c-api/init.rst ============================================================================== --- python/branches/py3k/Doc/c-api/init.rst (original) +++ python/branches/py3k/Doc/c-api/init.rst Sun Aug 17 20:57:58 2008 @@ -180,7 +180,7 @@ interpreter will change the contents of this storage. -.. cfunction:: char* Py_GetProgramName() +.. cfunction:: wchar* Py_GetProgramName() .. index:: single: Py_SetProgramName() From python-3000-checkins at python.org Sun Aug 17 21:28:19 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sun, 17 Aug 2008 21:28:19 +0200 (CEST) Subject: [Python-3000-checkins] r65779 - python/branches/py3k Message-ID: <20080817192819.8B4431E400A@bag.python.org> Author: benjamin.peterson Date: Sun Aug 17 21:28:19 2008 New Revision: 65779 Log: Blocked revisions 65679,65710 via svnmerge ........ r65679 | facundo.batista | 2008-08-14 11:51:00 -0500 (Thu, 14 Aug 2008) | 5 lines Issue 1432. Fixes a bug caused because of the evolution of the RFC that describes the behaviour. Note that we now have the same behaviour than the current browsers. ........ r65710 | facundo.batista | 2008-08-16 09:44:07 -0500 (Sat, 16 Aug 2008) | 4 lines Issue #2776: fixed small issue when handling an URL with double slash after a 302 response in the case of not going through a proxy. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 17 22:23:47 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sun, 17 Aug 2008 22:23:47 +0200 (CEST) Subject: [Python-3000-checkins] r65781 - in python/branches/py3k: Doc/library/os.rst Doc/reference/expressions.rst Lib/email/message.py Lib/zipfile.py Misc/NEWS Misc/developers.txt Message-ID: <20080817202347.4DCC21E400A@bag.python.org> Author: benjamin.peterson Date: Sun Aug 17 22:23:46 2008 New Revision: 65781 Log: Merged revisions 65659,65693,65700,65702,65706-65707,65761 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65659 | martin.v.loewis | 2008-08-12 15:45:21 -0500 (Tue, 12 Aug 2008) | 2 lines Add Hirokazu Yamamoto. ........ r65693 | georg.brandl | 2008-08-15 13:35:09 -0500 (Fri, 15 Aug 2008) | 2 lines #3558: Attribute reference binds more tightly than subscription and call. ........ r65700 | antoine.pitrou | 2008-08-15 16:03:21 -0500 (Fri, 15 Aug 2008) | 3 lines #2676: email/message.py [Message.get_content_type]: Trivial regex hangs on pathological input ........ r65702 | gregory.p.smith | 2008-08-15 18:14:00 -0500 (Fri, 15 Aug 2008) | 2 lines document that waitpid raises OSError ........ r65706 | benjamin.peterson | 2008-08-15 22:02:41 -0500 (Fri, 15 Aug 2008) | 1 line fix markup ........ r65707 | benjamin.peterson | 2008-08-15 22:13:07 -0500 (Fri, 15 Aug 2008) | 1 line note how os.utime should be used for emulating touch ........ r65761 | antoine.pitrou | 2008-08-17 08:06:29 -0500 (Sun, 17 Aug 2008) | 3 lines fix ZipFile.testzip() to work with very large embedded files ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/os.rst python/branches/py3k/Doc/reference/expressions.rst python/branches/py3k/Lib/email/message.py python/branches/py3k/Lib/zipfile.py python/branches/py3k/Misc/NEWS python/branches/py3k/Misc/developers.txt Modified: python/branches/py3k/Doc/library/os.rst ============================================================================== --- python/branches/py3k/Doc/library/os.rst (original) +++ python/branches/py3k/Doc/library/os.rst Sun Aug 17 22:23:46 2008 @@ -1076,15 +1076,16 @@ .. function:: utime(path, times) - Set the access and modified times of the file specified by *path*. If *times* is - ``None``, then the file's access and modified times are set to the current time. - Otherwise, *times* must be a 2-tuple of numbers, of the form ``(atime, mtime)`` - which is used to set the access and modified times, respectively. Whether a - directory can be given for *path* depends on whether the operating system - implements directories as files (for example, Windows does not). Note that the - exact times you set here may not be returned by a subsequent :func:`stat` call, - depending on the resolution with which your operating system records access and - modification times; see :func:`stat`. + Set the access and modified times of the file specified by *path*. If *times* + is ``None``, then the file's access and modified times are set to the current + time. (The effect is similar to running the Unix program :program:`touch` on + the path.) Otherwise, *times* must be a 2-tuple of numbers, of the form + ``(atime, mtime)`` which is used to set the access and modified times, + respectively. Whether a directory can be given for *path* depends on whether + the operating system implements directories as files (for example, Windows + does not). Note that the exact times you set here may not be returned by a + subsequent :func:`stat` call, depending on the resolution with which your + operating system records access and modification times; see :func:`stat`. Availability: Macintosh, Unix, Windows. @@ -1596,6 +1597,9 @@ ``-1``, status is requested for any process in the process group ``-pid`` (the absolute value of *pid*). + An :exc:`OSError` is raised with the value of errno when the syscall + returns -1. + On Windows: Wait for completion of a process given by process handle *pid*, and return a tuple containing *pid*, and its exit status shifted left by 8 bits (shifting makes cross-platform use of the function easier). A *pid* less than or Modified: python/branches/py3k/Doc/reference/expressions.rst ============================================================================== --- python/branches/py3k/Doc/reference/expressions.rst (original) +++ python/branches/py3k/Doc/reference/expressions.rst Sun Aug 17 22:23:46 2008 @@ -1266,13 +1266,13 @@ +----------------------------------------------+-------------------------------------+ | ``**`` | Exponentiation | +----------------------------------------------+-------------------------------------+ -| ``x.attribute`` | Attribute reference | -+----------------------------------------------+-------------------------------------+ | ``x[index]`` | Subscription | +----------------------------------------------+-------------------------------------+ | ``x[index:index]`` | Slicing | +----------------------------------------------+-------------------------------------+ -| ``f(arguments...)`` | Function call | +| ``x(arguments...)`` | Call | ++----------------------------------------------|-------------------------------------+ +| ``x.attribute`` | Attribute reference | +----------------------------------------------+-------------------------------------+ | ``(expressions...)`` | Binding, tuple display, generator | | | expressions | Modified: python/branches/py3k/Lib/email/message.py ============================================================================== --- python/branches/py3k/Lib/email/message.py (original) +++ python/branches/py3k/Lib/email/message.py Sun Aug 17 22:23:46 2008 @@ -20,18 +20,22 @@ SEMISPACE = '; ' -# Regular expression used to split header parameters. BAW: this may be too -# simple. It isn't strictly RFC 2045 (section 5.1) compliant, but it catches -# most headers found in the wild. We may eventually need a full fledged -# parser eventually. -paramre = re.compile(r'\s*;\s*') # Regular expression that matches `special' characters in parameters, the # existance of which force quoting of the parameter value. tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') - # Helper functions +def _splitparam(param): + # Split header parameters. BAW: this may be too simple. It isn't + # strictly RFC 2045 (section 5.1) compliant, but it catches most headers + # found in the wild. We may eventually need a full fledged parser + # eventually. + a, sep, b = param.partition(';') + if not sep: + return a.strip(), None + return a.strip(), b.strip() + def _formatparam(param, value=None, quote=True): """Convenience function to format and return a key=value pair. @@ -443,7 +447,7 @@ if value is missing: # This should have no parameters return self.get_default_type() - ctype = paramre.split(value)[0].lower().strip() + ctype = _splitparam(value)[0].lower() # RFC 2045, section 5.2 says if its invalid, use text/plain if ctype.count('/') != 1: return 'text/plain' Modified: python/branches/py3k/Lib/zipfile.py ============================================================================== --- python/branches/py3k/Lib/zipfile.py (original) +++ python/branches/py3k/Lib/zipfile.py Sun Aug 17 22:23:46 2008 @@ -813,9 +813,14 @@ def testzip(self): """Read all the files and check the CRC.""" + chunk_size = 2 ** 20 for zinfo in self.filelist: try: - self.read(zinfo.filename) # Check CRC-32 + # Read by chunks, to avoid an OverflowError or a + # MemoryError with very large embedded files. + f = self.open(zinfo.filename, "r") + while f.read(chunk_size): # Check CRC-32 + pass except BadZipfile: return zinfo.filename Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 17 22:23:46 2008 @@ -30,6 +30,10 @@ Library ------- +- Issue #2676: in the email package, content-type parsing was hanging on + pathological input because of quadratic or exponential behaviour of a + regular expression. + - Issue #3476: binary buffered reading through the new "io" library is now thread-safe. Modified: python/branches/py3k/Misc/developers.txt ============================================================================== --- python/branches/py3k/Misc/developers.txt (original) +++ python/branches/py3k/Misc/developers.txt Sun Aug 17 22:23:46 2008 @@ -17,6 +17,9 @@ Permissions History ------------------- +- Hirokazu Yamamoto was given SVN access on August 12 2008 by MvL, + for contributions to the Windows build. + - Antoine Pitrou was given SVN access on July 16 2008, by recommendation from GvR, for general contributions to Python. From python-3000-checkins at python.org Sun Aug 17 22:34:29 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sun, 17 Aug 2008 22:34:29 +0200 (CEST) Subject: [Python-3000-checkins] r65783 - python/branches/py3k/Doc/reference/expressions.rst Message-ID: <20080817203429.B9B7F1E400A@bag.python.org> Author: benjamin.peterson Date: Sun Aug 17 22:34:29 2008 New Revision: 65783 Log: fix markup Modified: python/branches/py3k/Doc/reference/expressions.rst Modified: python/branches/py3k/Doc/reference/expressions.rst ============================================================================== --- python/branches/py3k/Doc/reference/expressions.rst (original) +++ python/branches/py3k/Doc/reference/expressions.rst Sun Aug 17 22:34:29 2008 @@ -1271,7 +1271,7 @@ | ``x[index:index]`` | Slicing | +----------------------------------------------+-------------------------------------+ | ``x(arguments...)`` | Call | -+----------------------------------------------|-------------------------------------+ ++----------------------------------------------+-------------------------------------+ | ``x.attribute`` | Attribute reference | +----------------------------------------------+-------------------------------------+ | ``(expressions...)`` | Binding, tuple display, generator | From python-3000-checkins at python.org Mon Aug 18 00:31:16 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 18 Aug 2008 00:31:16 +0200 (CEST) Subject: [Python-3000-checkins] r65788 - in python/branches/py3k: Lib/_dummy_thread.py Lib/filecmp.py Lib/shelve.py Message-ID: <20080817223116.1AD271E400A@bag.python.org> Author: brett.cannon Date: Mon Aug 18 00:31:15 2008 New Revision: 65788 Log: Merged revisions 65787 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65787 | brett.cannon | 2008-08-17 15:10:11 -0700 (Sun, 17 Aug 2008) | 3 lines Remove imports of 'warnings' that are no longer needed in dummy_thread, filecmp, and shelve. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/_dummy_thread.py python/branches/py3k/Lib/filecmp.py python/branches/py3k/Lib/shelve.py Modified: python/branches/py3k/Lib/_dummy_thread.py ============================================================================== --- python/branches/py3k/Lib/_dummy_thread.py (original) +++ python/branches/py3k/Lib/_dummy_thread.py Mon Aug 18 00:31:15 2008 @@ -17,7 +17,6 @@ 'interrupt_main', 'LockType'] import traceback as _traceback -import warnings class error(Exception): """Dummy implementation of _thread.error.""" Modified: python/branches/py3k/Lib/filecmp.py ============================================================================== --- python/branches/py3k/Lib/filecmp.py (original) +++ python/branches/py3k/Lib/filecmp.py Mon Aug 18 00:31:15 2008 @@ -11,7 +11,6 @@ import os import stat -import warnings from itertools import filterfalse __all__ = ["cmp","dircmp","cmpfiles"] Modified: python/branches/py3k/Lib/shelve.py ============================================================================== --- python/branches/py3k/Lib/shelve.py (original) +++ python/branches/py3k/Lib/shelve.py Mon Aug 18 00:31:15 2008 @@ -60,7 +60,6 @@ from io import BytesIO import collections -import warnings __all__ = ["Shelf","BsdDbShelf","DbfilenameShelf","open"] From python-3000-checkins at python.org Mon Aug 18 02:39:30 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 18 Aug 2008 02:39:30 +0200 (CEST) Subject: [Python-3000-checkins] r65792 - in python/branches/py3k: Lib/io.py Message-ID: <20080818003930.8E7B11E400A@bag.python.org> Author: brett.cannon Date: Mon Aug 18 02:39:30 2008 New Revision: 65792 Log: Merged revisions 65791 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65791 | brett.cannon | 2008-08-17 17:36:52 -0700 (Sun, 17 Aug 2008) | 2 lines Remove two unneeded imports in 'io'. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/io.py Modified: python/branches/py3k/Lib/io.py ============================================================================== --- python/branches/py3k/Lib/io.py (original) +++ python/branches/py3k/Lib/io.py Mon Aug 18 02:39:30 2008 @@ -57,7 +57,6 @@ import os import abc -import sys import codecs import _fileio # Import _thread instead of threading to reduce startup cost From python-3000-checkins at python.org Mon Aug 18 02:43:03 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 18 Aug 2008 02:43:03 +0200 (CEST) Subject: [Python-3000-checkins] r65794 - in python/branches/py3k: Lib/inspect.py Message-ID: <20080818004303.ED26C1E400A@bag.python.org> Author: brett.cannon Date: Mon Aug 18 02:43:03 2008 New Revision: 65794 Log: Merged revisions 65793 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65793 | brett.cannon | 2008-08-17 17:41:11 -0700 (Sun, 17 Aug 2008) | 2 lines Remove an unneeded import of abc.ABCMeta from 'inspect'. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/inspect.py Modified: python/branches/py3k/Lib/inspect.py ============================================================================== --- python/branches/py3k/Lib/inspect.py (original) +++ python/branches/py3k/Lib/inspect.py Mon Aug 18 02:43:03 2008 @@ -39,7 +39,6 @@ import imp import tokenize import linecache -from abc import ABCMeta from operator import attrgetter from collections import namedtuple # These constants are from Include/code.h. From python-3000-checkins at python.org Mon Aug 18 02:51:20 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 18 Aug 2008 02:51:20 +0200 (CEST) Subject: [Python-3000-checkins] r65796 - in python/branches/py3k: Lib/csv.py Lib/os.py Lib/weakref.py Message-ID: <20080818005120.3BAF31E400A@bag.python.org> Author: brett.cannon Date: Mon Aug 18 02:51:19 2008 New Revision: 65796 Log: Merged revisions 65795 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65795 | brett.cannon | 2008-08-17 17:46:22 -0700 (Sun, 17 Aug 2008) | 3 lines Update __all__ for cookielib, csv, os, and urllib2 for objects imported into the module but exposed as part of the API. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/csv.py python/branches/py3k/Lib/os.py python/branches/py3k/Lib/weakref.py Modified: python/branches/py3k/Lib/csv.py ============================================================================== --- python/branches/py3k/Lib/csv.py (original) +++ python/branches/py3k/Lib/csv.py Mon Aug 18 02:51:19 2008 @@ -14,7 +14,8 @@ from io import StringIO __all__ = [ "QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_NONE", - "Error", "Dialect", "excel", "excel_tab", "reader", "writer", + "Error", "Dialect", "__doc__", "excel", "excel_tab", + "field_size_limit", "reader", "writer", "register_dialect", "get_dialect", "list_dialects", "Sniffer", "unregister_dialect", "__version__", "DictReader", "DictWriter" ] Modified: python/branches/py3k/Lib/os.py ============================================================================== --- python/branches/py3k/Lib/os.py (original) +++ python/branches/py3k/Lib/os.py Mon Aug 18 02:51:19 2008 @@ -27,7 +27,7 @@ _names = sys.builtin_module_names # Note: more names are added to __all__ later. -__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep", +__all__ = ["altsep", "curdir", "pardir", "sep", "extsep", "pathsep", "linesep", "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR", "SEEK_END"] Modified: python/branches/py3k/Lib/weakref.py ============================================================================== --- python/branches/py3k/Lib/weakref.py (original) +++ python/branches/py3k/Lib/weakref.py Mon Aug 18 02:51:19 2008 @@ -25,7 +25,7 @@ ProxyTypes = (ProxyType, CallableProxyType) __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", - "WeakKeyDictionary", "ReferenceType", "ProxyType", + "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType", "CallableProxyType", "ProxyTypes", "WeakValueDictionary", "WeakSet"] From python-3000-checkins at python.org Mon Aug 18 03:05:25 2008 From: python-3000-checkins at python.org (gregory.p.smith) Date: Mon, 18 Aug 2008 03:05:25 +0200 (CEST) Subject: [Python-3000-checkins] r65797 - python/branches/py3k/Objects/floatobject.c Message-ID: <20080818010525.9A2D01E401D@bag.python.org> Author: gregory.p.smith Date: Mon Aug 18 03:05:25 2008 New Revision: 65797 Log: fix cut and paste error in a comment Modified: python/branches/py3k/Objects/floatobject.c Modified: python/branches/py3k/Objects/floatobject.c ============================================================================== --- python/branches/py3k/Objects/floatobject.c (original) +++ python/branches/py3k/Objects/floatobject.c Mon Aug 18 03:05:25 2008 @@ -1918,7 +1918,7 @@ PyFloatObject *p; PyFloatBlock *list, *next; int i; - int u; /* remaining unfreed ints per block */ + int u; /* remaining unfreed floats per block */ int freelist_size = 0; list = block_list; From python-3000-checkins at python.org Mon Aug 18 03:27:33 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 03:27:33 +0200 (CEST) Subject: [Python-3000-checkins] r65799 - python/branches/py3k/Demo/embed/Makefile Message-ID: <20080818012733.185FF1E400A@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 03:27:32 2008 New Revision: 65799 Log: correct version Modified: python/branches/py3k/Demo/embed/Makefile Modified: python/branches/py3k/Demo/embed/Makefile ============================================================================== --- python/branches/py3k/Demo/embed/Makefile (original) +++ python/branches/py3k/Demo/embed/Makefile Mon Aug 18 03:27:32 2008 @@ -10,7 +10,7 @@ srcdir= ../.. # Python version -VERSION= 2.5 +VERSION= 3.0 # Compiler flags OPT= -g From python-3000-checkins at python.org Mon Aug 18 03:29:54 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 03:29:54 +0200 (CEST) Subject: [Python-3000-checkins] r65800 - python/branches/py3k Message-ID: <20080818012954.A92591E400A@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 03:29:54 2008 New Revision: 65800 Log: Blocked revisions 65798 via svnmerge ........ r65798 | benjamin.peterson | 2008-08-17 20:27:05 -0500 (Sun, 17 Aug 2008) | 1 line correct version ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 18 03:45:30 2008 From: python-3000-checkins at python.org (brett.cannon) Date: Mon, 18 Aug 2008 03:45:30 +0200 (CEST) Subject: [Python-3000-checkins] r65801 - python/branches/py3k/Lib/os.py Message-ID: <20080818014530.1D1671E400A@bag.python.org> Author: brett.cannon Date: Mon Aug 18 03:45:29 2008 New Revision: 65801 Log: Partially revert r65795 by undoing change to 'os'. Modified: python/branches/py3k/Lib/os.py Modified: python/branches/py3k/Lib/os.py ============================================================================== --- python/branches/py3k/Lib/os.py (original) +++ python/branches/py3k/Lib/os.py Mon Aug 18 03:45:29 2008 @@ -27,7 +27,7 @@ _names = sys.builtin_module_names # Note: more names are added to __all__ later. -__all__ = ["altsep", "curdir", "pardir", "sep", "extsep", "pathsep", "linesep", +__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep", "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR", "SEEK_END"] From python-3000-checkins at python.org Mon Aug 18 04:15:14 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 04:15:14 +0200 (CEST) Subject: [Python-3000-checkins] r65804 - python/branches/py3k Message-ID: <20080818021514.595511E4015@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 04:15:14 2008 New Revision: 65804 Log: Blocked revisions 65802-65803 via svnmerge ........ r65802 | benjamin.peterson | 2008-08-17 21:01:21 -0500 (Sun, 17 Aug 2008) | 1 line follup to #3473: don't duplicate the reduce code ........ r65803 | benjamin.peterson | 2008-08-17 21:12:23 -0500 (Sun, 17 Aug 2008) | 1 line add a test for reduce's move ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 18 05:41:47 2008 From: python-3000-checkins at python.org (gregory.p.smith) Date: Mon, 18 Aug 2008 05:41:47 +0200 (CEST) Subject: [Python-3000-checkins] r65805 - python/branches/py3k/Lib/weakref.py Message-ID: <20080818034147.2DFD91E400A@bag.python.org> Author: gregory.p.smith Date: Mon Aug 18 05:41:46 2008 New Revision: 65805 Log: ReferenceError is undefined. causes test___all__.py to fail. remove it from __all__ Modified: python/branches/py3k/Lib/weakref.py Modified: python/branches/py3k/Lib/weakref.py ============================================================================== --- python/branches/py3k/Lib/weakref.py (original) +++ python/branches/py3k/Lib/weakref.py Mon Aug 18 05:41:46 2008 @@ -25,7 +25,7 @@ ProxyTypes = (ProxyType, CallableProxyType) __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", - "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType", + "WeakKeyDictionary", "ReferenceType", "ProxyType", "CallableProxyType", "ProxyTypes", "WeakValueDictionary", "WeakSet"] From python-3000-checkins at python.org Mon Aug 18 14:31:53 2008 From: python-3000-checkins at python.org (nick.coghlan) Date: Mon, 18 Aug 2008 14:31:53 +0200 (CEST) Subject: [Python-3000-checkins] r65808 - in python/branches/py3k: Lib/numbers.py Misc/NEWS Message-ID: <20080818123153.037D91E4009@bag.python.org> Author: nick.coghlan Date: Mon Aug 18 14:31:52 2008 New Revision: 65808 Log: Forward port only Py3k relevant change in r65642 (giving it a Py3k NEWS entry anyway because of the difference in the changes between the two branches) Modified: python/branches/py3k/Lib/numbers.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/numbers.py ============================================================================== --- python/branches/py3k/Lib/numbers.py (original) +++ python/branches/py3k/Lib/numbers.py Mon Aug 18 14:31:52 2008 @@ -15,6 +15,8 @@ If you just want to check if an argument x is a number, without caring what kind, use isinstance(x, Number). """ + # Concrete numeric types must provide their own hash implementation + __hash__ = None ## Notes on Decimal Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Aug 18 14:31:52 2008 @@ -30,6 +30,12 @@ Library ------- +- Issue #2235: numbers.Number now blocks inheritance of the default id() + based hash because that hash mechanism is not correct for numeric types. + All concrete numeric types that inherit from Number (rather than just + registering with it) must explicitly provide a hash implementation in + order for their instances to be hashable. + - Issue #2676: in the email package, content-type parsing was hanging on pathological input because of quadratic or exponential behaviour of a regular expression. From python-3000-checkins at python.org Mon Aug 18 15:18:16 2008 From: python-3000-checkins at python.org (nick.coghlan) Date: Mon, 18 Aug 2008 15:18:16 +0200 (CEST) Subject: [Python-3000-checkins] r65811 - in python/branches/py3k: Doc/c-api/object.rst Doc/c-api/typeobj.rst Message-ID: <20080818131816.C0D491E4016@bag.python.org> Author: nick.coghlan Date: Mon Aug 18 15:18:16 2008 New Revision: 65811 Log: Merged revisions 65810 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65810 | nick.coghlan | 2008-08-18 23:14:22 +1000 (Mon, 18 Aug 2008) | 1 line Issue 2235: document PyObject_HashNotImplemented ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/c-api/object.rst python/branches/py3k/Doc/c-api/typeobj.rst Modified: python/branches/py3k/Doc/c-api/object.rst ============================================================================== --- python/branches/py3k/Doc/c-api/object.rst (original) +++ python/branches/py3k/Doc/c-api/object.rst Mon Aug 18 15:18:16 2008 @@ -257,6 +257,16 @@ This is the equivalent of the Python expression ``hash(o)``. +.. cfunction:: long PyObject_HashNotImplemented(PyObject *o) + + Set a TypeError indicating that ``type(o)`` is not hashable and return ``-1``. + This function receives special treatment when stored in a ``tp_hash`` slot, + allowing a type to explicit indicate to the interpreter that it is not + hashable. + + .. versionadded:: 2.6 + + .. cfunction:: int PyObject_IsTrue(PyObject *o) Returns ``1`` if the object *o* is considered to be true, and ``0`` otherwise. Modified: python/branches/py3k/Doc/c-api/typeobj.rst ============================================================================== --- python/branches/py3k/Doc/c-api/typeobj.rst (original) +++ python/branches/py3k/Doc/c-api/typeobj.rst Mon Aug 18 15:18:16 2008 @@ -321,6 +321,14 @@ error occurs during the computation of the hash value, the function should set an exception and return ``-1``. + This field can be set explicitly to :cfunc:`PyObject_HashNotImplemented` to + block inheritance of the hash method from a parent type. This is interpreted + as the equivalent of ``__hash__ = None`` at the Python level, causing + ``isinstance(o, collections.Hashable)`` to correctly return ``False``. Note + that the converse is also true - setting ``__hash__ = None`` on a class at + the Python level will result in the ``tp_hash`` slot being set to + :cfunc:`PyObject_HashNotImplemented`. + When this field is not set, two possibilities exist: if the :attr:`tp_compare` and :attr:`tp_richcompare` fields are both *NULL*, a default hash value based on the object's address is returned; otherwise, a :exc:`TypeError` is raised. From python-3000-checkins at python.org Mon Aug 18 18:08:02 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 18:08:02 +0200 (CEST) Subject: [Python-3000-checkins] r65817 - python/branches/py3k/Makefile.pre.in Message-ID: <20080818160802.7D2001E4003@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 18:08:02 2008 New Revision: 65817 Log: fix dependencies after rename Modified: python/branches/py3k/Makefile.pre.in Modified: python/branches/py3k/Makefile.pre.in ============================================================================== --- python/branches/py3k/Makefile.pre.in (original) +++ python/branches/py3k/Makefile.pre.in Mon Aug 18 18:08:02 2008 @@ -556,9 +556,9 @@ $(srcdir)/Objects/stringlib/unicodedefs.h \ $(srcdir)/Objects/stringlib/localeutil.h -Objects/stringobject.o: $(srcdir)/Objects/stringobject.c $(BYTESTR_DEPS) +Objects/stringobject.o: $(srcdir)/Objects/bytesobject.c $(BYTESTR_DEPS) -Objects/bytesobject.o: $(srcdir)/Objects/bytesobject.c $(BYTESTR_DEPS) +Objects/bytesobject.o: $(srcdir)/Objects/bytearrayobject.c $(BYTESTR_DEPS) Objects/unicodeobject.o: $(srcdir)/Objects/unicodeobject.c \ $(BYTESTR_DEPS) \ From python-3000-checkins at python.org Mon Aug 18 18:45:32 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 18:45:32 +0200 (CEST) Subject: [Python-3000-checkins] r65819 - in python/branches/py3k: Doc/library/threading.rst Lib/test/test_threading.py Lib/threading.py Message-ID: <20080818164532.4714C1E4009@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 18:45:31 2008 New Revision: 65819 Log: Merged revisions 65818 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65818 | benjamin.peterson | 2008-08-18 11:40:03 -0500 (Mon, 18 Aug 2008) | 4 lines change threading.getIdent to a property This is new in 2.6 so now need to worry about backwards compatibility :) ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/threading.rst python/branches/py3k/Lib/test/test_threading.py python/branches/py3k/Lib/threading.py Modified: python/branches/py3k/Doc/library/threading.rst ============================================================================== --- python/branches/py3k/Doc/library/threading.rst (original) +++ python/branches/py3k/Doc/library/threading.rst Mon Aug 18 18:45:31 2008 @@ -643,12 +643,12 @@ constructor. -.. method:: Thread.get_ident() +.. attribute:: Thread.ident - Return the 'thread identifier' of this thread or None if the thread has not - been started. This is a nonzero integer. See the :func:`thread.get_ident()` + The 'thread identifier' of this thread or ``None`` if the thread has not been + started. This is a nonzero integer. See the :func:`thread.get_ident()` function. Thread identifiers may be recycled when a thread exits and another - thread is created. The identifier is returned even after the thread has + thread is created. The identifier is available even after the thread has exited. Modified: python/branches/py3k/Lib/test/test_threading.py ============================================================================== --- python/branches/py3k/Lib/test/test_threading.py (original) +++ python/branches/py3k/Lib/test/test_threading.py Mon Aug 18 18:45:31 2008 @@ -74,7 +74,7 @@ for i in range(NUMTASKS): t = TestThread(""%i, self, sema, mutex, numrunning) threads.append(t) - self.failUnlessEqual(t.get_ident(), None) + self.failUnlessEqual(t.ident, None) self.assert_(re.match('', repr(t))) t.start() @@ -83,7 +83,7 @@ for t in threads: t.join(NUMTASKS) self.assert_(not t.is_alive()) - self.failIfEqual(t.get_ident(), 0) + self.failIfEqual(t.ident, 0) self.assert_(re.match('', repr(t))) if verbose: print('all tasks done') Modified: python/branches/py3k/Lib/threading.py ============================================================================== --- python/branches/py3k/Lib/threading.py (original) +++ python/branches/py3k/Lib/threading.py Mon Aug 18 18:45:31 2008 @@ -629,7 +629,8 @@ assert self._initialized, "Thread.__init__() not called" self._name = str(name) - def get_ident(self): + @property + def ident(self): assert self._initialized, "Thread.__init__() not called" return self._ident From python-3000-checkins at python.org Mon Aug 18 19:16:20 2008 From: python-3000-checkins at python.org (eric.smith) Date: Mon, 18 Aug 2008 19:16:20 +0200 (CEST) Subject: [Python-3000-checkins] r65820 - python/branches/py3k Message-ID: <20080818171620.65CCC1E4006@bag.python.org> Author: eric.smith Date: Mon Aug 18 19:16:20 2008 New Revision: 65820 Log: Blocked revisions 65814 via svnmerge ........ r65814 | eric.smith | 2008-08-18 10:27:38 -0400 (Mon, 18 Aug 2008) | 12 lines Backport of r63826. Optimization of str.format() for cases with str, unicode, int, long, and float arguments. This gives about 30% speed improvement for the simplest (but most common) cases. This patch skips the __format__ dispatch, and also avoids creating an object to hold the format_spec. Unfortunately there's a complication in 2.6 with int, long, and float because they always expect str format_specs. So in the unicode version of this optimization, just check for unicode objects. int, float, long, and str can be added later, if needed. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 18 19:33:47 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 19:33:47 +0200 (CEST) Subject: [Python-3000-checkins] r65821 - in python/branches/py3k/Lib: test/test_threading.py threading.py Message-ID: <20080818173347.B4D8A1E4003@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 19:33:47 2008 New Revision: 65821 Log: change is_daemon, set_daemon, get_name, and set_name to properties I'm add add warnings and backport this to 2.6 soon Modified: python/branches/py3k/Lib/test/test_threading.py python/branches/py3k/Lib/threading.py Modified: python/branches/py3k/Lib/test/test_threading.py ============================================================================== --- python/branches/py3k/Lib/test/test_threading.py (original) +++ python/branches/py3k/Lib/test/test_threading.py Mon Aug 18 19:33:47 2008 @@ -34,7 +34,7 @@ delay = random.random() / 10000.0 if verbose: print('task %s will run for %.1f usec' % - (self.get_name(), delay * 1e6)) + (self.name, delay * 1e6)) with self.sema: with self.mutex: @@ -45,14 +45,14 @@ time.sleep(delay) if verbose: - print('task', self.get_name(), 'done') + print('task', self.name, 'done') with self.mutex: self.nrunning.dec() self.testcase.assert_(self.nrunning.get() >= 0) if verbose: print('%s is finished. %d tasks are running' % - (self.get_name(), self.nrunning.get())) + (self.name, self.nrunning.get())) class ThreadTests(unittest.TestCase): @@ -173,7 +173,7 @@ worker_saw_exception.set() t = Worker() - t.set_daemon(True) # so if this fails, we don't hang Python at shutdown + t.daemon = True # so if this fails, we don't hang Python at shutdown t.start() if verbose: print(" started worker thread") @@ -259,7 +259,7 @@ print('program blocked; aborting') os._exit(2) t = threading.Thread(target=killer) - t.set_daemon(True) + t.daemon = True t.start() # This is the trace function @@ -437,7 +437,7 @@ def test_daemonize_active_thread(self): thread = threading.Thread() thread.start() - self.assertRaises(RuntimeError, thread.set_daemon, True) + self.assertRaises(RuntimeError, setattr, thread, "daemon", True) def test_main(): Modified: python/branches/py3k/Lib/threading.py ============================================================================== --- python/branches/py3k/Lib/threading.py (original) +++ python/branches/py3k/Lib/threading.py Mon Aug 18 19:33:47 2008 @@ -40,7 +40,7 @@ if self._verbose: format = format % args format = "%s: %s\n" % ( - current_thread().get_name(), format) + current_thread().name, format) _sys.stderr.write(format) else: @@ -83,7 +83,7 @@ owner = self._owner return "<%s(%s, %d)>" % ( self.__class__.__name__, - owner and owner.get_name(), + owner and owner.name, self._count) def acquire(self, blocking=1): @@ -412,7 +412,7 @@ def _set_daemon(self): # Overridden in _MainThread and _DummyThread - return current_thread().is_daemon() + return current_thread().daemon def __repr__(self): assert self._initialized, "Thread.__init__() was not called" @@ -502,7 +502,7 @@ # self. if _sys: _sys.stderr.write("Exception in thread %s:\n%s\n" % - (self.get_name(), _format_exc())) + (self.name, _format_exc())) else: # Do the best job possible w/o a huge amt. of code to # approximate a traceback (code ideas from @@ -510,7 +510,7 @@ exc_type, exc_value, exc_tb = self._exc_info() try: print(( - "Exception in thread " + self.get_name() + + "Exception in thread " + self.name + " (most likely raised during interpreter shutdown):"), file=self._stderr) print(( "Traceback (most recent call last):"), file=self._stderr) @@ -621,11 +621,13 @@ finally: self._block.release() - def get_name(self): + @property + def name(self): assert self._initialized, "Thread.__init__() not called" return self._name - def set_name(self, name): + @name.setter + def name(self, name): assert self._initialized, "Thread.__init__() not called" self._name = str(name) @@ -638,11 +640,13 @@ assert self._initialized, "Thread.__init__() not called" return self._started.is_set() and not self._stopped - def is_daemon(self): + @property + def daemon(self): assert self._initialized, "Thread.__init__() not called" return self._daemonic - def set_daemon(self, daemonic): + @daemon.setter + def daemon(self, daemonic): if not self._initialized: raise RuntimeError("Thread.__init__() not called") if self._started.is_set(): @@ -710,7 +714,7 @@ def _pickSomeNonDaemonThread(): for t in enumerate(): - if not t.is_daemon() and t.is_alive(): + if not t.daemon and t.is_alive(): return t return None @@ -863,7 +867,7 @@ counter = 0 while counter < self.quota: counter = counter + 1 - self.queue.put("%s.%d" % (self.get_name(), counter)) + self.queue.put("%s.%d" % (self.name, counter)) _sleep(random() * 0.00001) @@ -888,7 +892,7 @@ P = [] for i in range(NP): t = ProducerThread(Q, NI) - t.set_name("Producer-%d" % (i+1)) + t.name = "Producer-%d" % (i+1) P.append(t) C = ConsumerThread(Q, NI*NP) for t in P: From python-3000-checkins at python.org Mon Aug 18 19:52:22 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 19:52:22 +0200 (CEST) Subject: [Python-3000-checkins] r65823 - python/branches/py3k Message-ID: <20080818175222.DEC941E4003@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 19:52:22 2008 New Revision: 65823 Log: Blocked revisions 65822 via svnmerge ........ r65822 | benjamin.peterson | 2008-08-18 12:45:09 -0500 (Mon, 18 Aug 2008) | 1 line backport threading property changes ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 18 20:09:22 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 20:09:22 +0200 (CEST) Subject: [Python-3000-checkins] r65825 - in python/branches/py3k: Lib/logging/__init__.py Lib/multiprocessing/managers.py Lib/multiprocessing/queues.py Lib/test/test_dummy_threading.py Lib/test/test_multiprocessing.py Lib/test/test_socketserver.py Message-ID: <20080818180922.65B361E4003@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 20:09:21 2008 New Revision: 65825 Log: Merged revisions 65824 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65824 | benjamin.peterson | 2008-08-18 13:01:43 -0500 (Mon, 18 Aug 2008) | 1 line change a few uses of the threading APIs ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/logging/__init__.py python/branches/py3k/Lib/multiprocessing/managers.py python/branches/py3k/Lib/multiprocessing/queues.py python/branches/py3k/Lib/test/test_dummy_threading.py python/branches/py3k/Lib/test/test_multiprocessing.py python/branches/py3k/Lib/test/test_socketserver.py Modified: python/branches/py3k/Lib/logging/__init__.py ============================================================================== --- python/branches/py3k/Lib/logging/__init__.py (original) +++ python/branches/py3k/Lib/logging/__init__.py Mon Aug 18 20:09:21 2008 @@ -258,7 +258,7 @@ self.relativeCreated = (self.created - _startTime) * 1000 if logThreads and thread: self.thread = thread.get_ident() - self.threadName = threading.current_thread().get_name() + self.threadName = threading.current_thread().name else: self.thread = None self.threadName = None Modified: python/branches/py3k/Lib/multiprocessing/managers.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/managers.py (original) +++ python/branches/py3k/Lib/multiprocessing/managers.py Mon Aug 18 20:09:21 2008 @@ -207,7 +207,7 @@ Handle requests from the proxies in a particular process/thread ''' util.debug('starting server thread to service %r', - threading.current_thread().get_name()) + threading.current_thread().name) recv = conn.recv send = conn.send @@ -257,7 +257,7 @@ except EOFError: util.debug('got EOF -- exiting thread serving %r', - threading.current_thread().get_name()) + threading.current_thread().name) sys.exit(0) except Exception: @@ -270,7 +270,7 @@ send(('#UNSERIALIZABLE', repr(msg))) except Exception as e: util.info('exception in thread serving %r', - threading.current_thread().get_name()) + threading.current_thread().name) util.info(' ... message was %r', msg) util.info(' ... exception was %r', e) conn.close() @@ -392,7 +392,7 @@ ''' Spawn a new thread to serve this connection ''' - threading.current_thread().set_name(name) + threading.current_thread().name = name c.send(('#RETURN', None)) self.serve_client(c) @@ -706,8 +706,8 @@ def _connect(self): util.debug('making connection to manager') name = current_process().get_name() - if threading.current_thread().get_name() != 'MainThread': - name += '|' + threading.current_thread().get_name() + if threading.current_thread().name != 'MainThread': + name += '|' + threading.current_thread().name conn = self._Client(self._token.address, authkey=self._authkey) dispatch(conn, None, 'accept_connection', (name,)) self._tls.connection = conn @@ -720,7 +720,7 @@ conn = self._tls.connection except AttributeError: util.debug('thread %r does not own a connection', - threading.current_thread().get_name()) + threading.current_thread().name) self._connect() conn = self._tls.connection @@ -781,7 +781,7 @@ # the process owns no more references to objects for this manager if not idset and hasattr(tls, 'connection'): util.debug('thread %r has no more proxies so closing conn', - threading.current_thread().get_name()) + threading.current_thread().name) tls.connection.close() del tls.connection Modified: python/branches/py3k/Lib/multiprocessing/queues.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/queues.py (original) +++ python/branches/py3k/Lib/multiprocessing/queues.py Mon Aug 18 20:09:21 2008 @@ -155,7 +155,7 @@ self._wlock, self._writer.close), name='QueueFeederThread' ) - self._thread.set_daemon(True) + self._thread.daemon = True debug('doing self._thread.start()') self._thread.start() Modified: python/branches/py3k/Lib/test/test_dummy_threading.py ============================================================================== --- python/branches/py3k/Lib/test/test_dummy_threading.py (original) +++ python/branches/py3k/Lib/test/test_dummy_threading.py Mon Aug 18 20:09:21 2008 @@ -16,7 +16,7 @@ #delay = random.random() * 2 delay = 0 if support.verbose: - print('task', self.get_name(), 'will run for', delay, 'sec') + print('task', self.name, 'will run for', delay, 'sec') sema.acquire() mutex.acquire() running += 1 @@ -25,11 +25,11 @@ mutex.release() time.sleep(delay) if support.verbose: - print('task', self.get_name(), 'done') + print('task', self.name, 'done') mutex.acquire() running -= 1 if support.verbose: - print(self.get_name(), 'is finished.', running, 'tasks are running') + print(self.name, 'is finished.', running, 'tasks are running') mutex.release() sema.release() Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Mon Aug 18 20:09:21 2008 @@ -671,7 +671,7 @@ t = threading.Thread(target=self.f, args=(cond, sleeping, woken, TIMEOUT1)) - t.set_daemon(True) + t.daemon = True t.start() # wait for them all to sleep @@ -693,7 +693,7 @@ p.start() t = threading.Thread(target=self.f, args=(cond, sleeping, woken)) - t.set_daemon(True) + t.daemon = True t.start() # wait for them to all sleep Modified: python/branches/py3k/Lib/test/test_socketserver.py ============================================================================== --- python/branches/py3k/Lib/test/test_socketserver.py (original) +++ python/branches/py3k/Lib/test/test_socketserver.py Mon Aug 18 20:09:21 2008 @@ -139,7 +139,7 @@ # Time between requests is short enough that we won't wake # up spuriously too many times. kwargs={'poll_interval':0.01}) - t.set_daemon(True) # In case this function raises. + t.daemon = True # In case this function raises. t.start() if verbose: print("server running") for i in range(3): From python-3000-checkins at python.org Mon Aug 18 20:16:46 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 20:16:46 +0200 (CEST) Subject: [Python-3000-checkins] r65827 - in python/branches/py3k: Lib/threading.py Message-ID: <20080818181646.D8A7A1E4003@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 20:16:46 2008 New Revision: 65827 Log: Merged revisions 65826 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65826 | benjamin.peterson | 2008-08-18 13:13:17 -0500 (Mon, 18 Aug 2008) | 1 line bring back the old API ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/threading.py Modified: python/branches/py3k/Lib/threading.py ============================================================================== --- python/branches/py3k/Lib/threading.py (original) +++ python/branches/py3k/Lib/threading.py Mon Aug 18 20:16:46 2008 @@ -653,6 +653,18 @@ raise RuntimeError("cannot set daemon status of active thread"); self._daemonic = daemonic + def isDaemon(self): + return self.daemon + + def setDaemon(self, daemonic): + self.daemon = daemonic + + def getName(self): + return self.name + + def setName(self, name): + self.name = name + # The timer class was contributed by Itamar Shtull-Trauring def Timer(*args, **kwargs): From python-3000-checkins at python.org Mon Aug 18 20:40:09 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 20:40:09 +0200 (CEST) Subject: [Python-3000-checkins] r65830 - in python/branches/py3k: Lib/multiprocessing/dummy/__init__.py Lib/multiprocessing/managers.py Lib/multiprocessing/pool.py Lib/test/test_multiprocessing.py Message-ID: <20080818184009.713D11E4003@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 20:40:08 2008 New Revision: 65830 Log: Merged revisions 65828 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65828 | benjamin.peterson | 2008-08-18 13:31:58 -0500 (Mon, 18 Aug 2008) | 1 line patch up multiprocessing until it's API can be changed too ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/multiprocessing/dummy/__init__.py python/branches/py3k/Lib/multiprocessing/managers.py python/branches/py3k/Lib/multiprocessing/pool.py python/branches/py3k/Lib/test/test_multiprocessing.py Modified: python/branches/py3k/Lib/multiprocessing/dummy/__init__.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/dummy/__init__.py (original) +++ python/branches/py3k/Lib/multiprocessing/dummy/__init__.py Mon Aug 18 20:40:08 2008 @@ -53,12 +53,11 @@ else: return None - is_alive = threading.Thread.is_alive - get_name = threading.Thread.get_name - set_name = threading.Thread.set_name - is_daemon = threading.Thread.is_daemon - set_daemon = threading.Thread.set_daemon + get_name = threading.Thread.getName + set_name = threading.Thread.setName + is_daemon = threading.Thread.isDaemon + set_daemon = threading.Thread.setDaemon # # Modified: python/branches/py3k/Lib/multiprocessing/managers.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/managers.py (original) +++ python/branches/py3k/Lib/multiprocessing/managers.py Mon Aug 18 20:40:08 2008 @@ -160,7 +160,7 @@ except (OSError, IOError): continue t = threading.Thread(target=self.handle_request, args=(c,)) - t.set_daemon(True) + t.daemon = True t.start() except (KeyboardInterrupt, SystemExit): pass Modified: python/branches/py3k/Lib/multiprocessing/pool.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/pool.py (original) +++ python/branches/py3k/Lib/multiprocessing/pool.py Mon Aug 18 20:40:08 2008 @@ -99,15 +99,15 @@ args=(self._inqueue, self._outqueue, initializer, initargs) ) self._pool.append(w) - w.set_name(w.get_name().replace('Process', 'PoolWorker')) - w.set_daemon(True) + w.name = w.get_name().replace('Process', 'PoolWorker') + w.daemon = True w.start() self._task_handler = threading.Thread( target=Pool._handle_tasks, args=(self._taskqueue, self._quick_put, self._outqueue, self._pool) ) - self._task_handler.set_daemon(True) + self._task_handler.daemon = True self._task_handler._state = RUN self._task_handler.start() @@ -115,7 +115,7 @@ target=Pool._handle_results, args=(self._outqueue, self._quick_get, self._cache) ) - self._result_handler.set_daemon(True) + self._result_handler.daemon = True self._result_handler._state = RUN self._result_handler.start() Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Mon Aug 18 20:40:08 2008 @@ -620,11 +620,17 @@ woken = self.Semaphore(0) p = self.Process(target=self.f, args=(cond, sleeping, woken)) - p.set_daemon(True) + try: + p.set_daemon(True) + except AttributeError: + p.daemon = True p.start() p = threading.Thread(target=self.f, args=(cond, sleeping, woken)) - p.set_daemon(True) + try: + p.set_daemon(True) + except AttributeError: + p.daemon = True p.start() # wait for both children to start sleeping From python-3000-checkins at python.org Mon Aug 18 20:41:21 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 20:41:21 +0200 (CEST) Subject: [Python-3000-checkins] r65831 - python/branches/py3k Message-ID: <20080818184121.7B8351E4003@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 20:41:21 2008 New Revision: 65831 Log: Blocked revisions 65829 via svnmerge ........ r65829 | benjamin.peterson | 2008-08-18 13:39:57 -0500 (Mon, 18 Aug 2008) | 1 line fix old API names in test_ssl ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 18 21:01:21 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 21:01:21 +0200 (CEST) Subject: [Python-3000-checkins] r65832 - python/branches/py3k/Lib/bsddb/test/test_lock.py Message-ID: <20080818190121.1A1EC1E4006@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 21:01:20 2008 New Revision: 65832 Log: fix bsddb get_name and set_daemon usage Modified: python/branches/py3k/Lib/bsddb/test/test_lock.py Modified: python/branches/py3k/Lib/bsddb/test/test_lock.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_lock.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_lock.py Mon Aug 18 21:01:20 2008 @@ -117,7 +117,7 @@ deadlock_detection.end=False deadlock_detection.count=0 t=Thread(target=deadlock_detection) - t.set_daemon(True) + t.daemon = True t.start() self.env.set_timeout(100000, db.DB_SET_LOCK_TIMEOUT) anID = self.env.lock_id() @@ -143,7 +143,7 @@ self.assertTrue(deadlock_detection.count>0) def theThread(self, sleepTime, lockType): - name = current_thread().get_name() + name = current_thread().name if lockType == db.DB_LOCK_WRITE: lt = "write" else: From python-3000-checkins at python.org Mon Aug 18 21:08:51 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 21:08:51 +0200 (CEST) Subject: [Python-3000-checkins] r65833 - python/branches/py3k/Lib/subprocess.py Message-ID: <20080818190851.9EEBC1E4006@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 21:08:51 2008 New Revision: 65833 Log: fix set_daemon usage in subprocess Modified: python/branches/py3k/Lib/subprocess.py Modified: python/branches/py3k/Lib/subprocess.py ============================================================================== --- python/branches/py3k/Lib/subprocess.py (original) +++ python/branches/py3k/Lib/subprocess.py Mon Aug 18 21:08:51 2008 @@ -876,13 +876,13 @@ stdout = [] stdout_thread = threading.Thread(target=self._readerthread, args=(self.stdout, stdout)) - stdout_thread.set_daemon(True) + stdout_thread.daemon = True stdout_thread.start() if self.stderr: stderr = [] stderr_thread = threading.Thread(target=self._readerthread, args=(self.stderr, stderr)) - stderr_thread.set_daemon(True) + stderr_thread.daemon = True stderr_thread.start() if self.stdin: From python-3000-checkins at python.org Mon Aug 18 23:02:27 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 23:02:27 +0200 (CEST) Subject: [Python-3000-checkins] r65836 - python/branches/py3k Message-ID: <20080818210227.09B2B1E4006@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 23:02:26 2008 New Revision: 65836 Log: Unblocked revisions 65829 via svnmerge ........ r65829 | benjamin.peterson | 2008-08-18 13:39:57 -0500 (Mon, 18 Aug 2008) | 1 line fix old API names in test_ssl ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Mon Aug 18 23:11:09 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 23:11:09 +0200 (CEST) Subject: [Python-3000-checkins] r65837 - in python/branches/py3k: Lib/test/test_ssl.py Message-ID: <20080818211109.DDDC31E4006@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 23:11:09 2008 New Revision: 65837 Log: Merged revisions 65829 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65829 | benjamin.peterson | 2008-08-18 13:39:57 -0500 (Mon, 18 Aug 2008) | 1 line fix old API names in test_ssl ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_ssl.py Modified: python/branches/py3k/Lib/test/test_ssl.py ============================================================================== --- python/branches/py3k/Lib/test/test_ssl.py (original) +++ python/branches/py3k/Lib/test/test_ssl.py Mon Aug 18 23:11:09 2008 @@ -201,7 +201,7 @@ self.sock.setblocking(1) self.sslconn = None threading.Thread.__init__(self) - self.set_daemon(True) + self.daemon = True def wrap_conn (self): try: @@ -326,7 +326,7 @@ self.flag = None self.active = False threading.Thread.__init__(self) - self.set_daemon(False) + self.daemon = True def start (self, flag=None): self.flag = flag @@ -482,7 +482,7 @@ self.server = self.HTTPSServer( (HOST, self.port), self.RootedHTTPRequestHandler, certfile) threading.Thread.__init__(self) - self.set_daemon(True) + self.daemon = True def __str__(self): return "<%s %s>" % (self.__class__.__name__, self.server) @@ -568,7 +568,7 @@ self.port = support.find_unused_port() self.server = self.EchoServer(self.port, certfile) threading.Thread.__init__(self) - self.set_daemon(True) + self.daemon = True def __str__(self): return "<%s %s>" % (self.__class__.__name__, self.server) From python-3000-checkins at python.org Mon Aug 18 23:44:30 2008 From: python-3000-checkins at python.org (guido.van.rossum) Date: Mon, 18 Aug 2008 23:44:30 +0200 (CEST) Subject: [Python-3000-checkins] r65838 - in python/branches/py3k: Doc/library/urllib.parse.rst Lib/email/utils.py Lib/test/test_cgi.py Lib/test/test_http_cookiejar.py Lib/test/test_urllib.py Lib/test/test_wsgiref.py Lib/urllib/parse.py Misc/NEWS Message-ID: <20080818214430.E55D31E4018@bag.python.org> Author: guido.van.rossum Date: Mon Aug 18 23:44:30 2008 New Revision: 65838 Log: - Issue #3300: make urllib.parse.[un]quote() default to UTF-8. Code contributed by Matt Giuca. quote() now encodes the input before quoting, unquote() decodes after unquoting. There are new arguments to change the encoding and errors settings. There are also new APIs to skip the encode/decode steps. [un]quote_plus() are also affected. Modified: python/branches/py3k/Doc/library/urllib.parse.rst python/branches/py3k/Lib/email/utils.py python/branches/py3k/Lib/test/test_cgi.py python/branches/py3k/Lib/test/test_http_cookiejar.py python/branches/py3k/Lib/test/test_urllib.py python/branches/py3k/Lib/test/test_wsgiref.py python/branches/py3k/Lib/urllib/parse.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/urllib.parse.rst ============================================================================== --- python/branches/py3k/Doc/library/urllib.parse.rst (original) +++ python/branches/py3k/Doc/library/urllib.parse.rst Mon Aug 18 23:44:30 2008 @@ -182,36 +182,84 @@ string. If there is no fragment identifier in *url*, return *url* unmodified and an empty string. -.. function:: quote(string[, safe]) +.. function:: quote(string[, safe[, encoding[, errors]]]) Replace special characters in *string* using the ``%xx`` escape. Letters, digits, and the characters ``'_.-'`` are never quoted. The optional *safe* - parameter specifies additional characters that should not be quoted --- its - default value is ``'/'``. + parameter specifies additional ASCII characters that should not be quoted + --- its default value is ``'/'``. - Example: ``quote('/~connolly/')`` yields ``'/%7econnolly/'``. + *string* may be either a :class:`str` or a :class:`bytes`. + The optional *encoding* and *errors* parameters specify how to deal with + non-ASCII characters, as accepted by the :meth:`str.encode` method. + *encoding* defaults to ``'utf-8'``. + *errors* defaults to ``'strict'``, meaning unsupported characters raise a + :class:`UnicodeEncodeError`. + *encoding* and *errors* must not be supplied if *string* is a + :class:`bytes`, or a :class:`TypeError` is raised. -.. function:: quote_plus(string[, safe]) + Note that ``quote(string, safe, encoding, errors)`` is equivalent to + ``quote_from_bytes(string.encode(encoding, errors), safe)``. + + Example: ``quote('/El Ni?o/')`` yields ``'/El%20Ni%C3%B1o/'``. + + +.. function:: quote_plus(string[, safe[, encoding[, errors]]]) Like :func:`quote`, but also replace spaces by plus signs, as required for quoting HTML form values. Plus signs in the original string are escaped unless they are included in *safe*. It also does not have *safe* default to ``'/'``. + Example: ``quote_plus('/El Ni?o/')`` yields ``'%2FEl+Ni%C3%B1o%2F'``. + +.. function:: quote_from_bytes(bytes[, safe]) -.. function:: unquote(string) + Like :func:`quote`, but accepts a :class:`bytes` object rather than a + :class:`str`, and does not perform string-to-bytes encoding. + + Example: ``quote_from_bytes(b'a&\xef')`` yields + ``'a%26%EF'``. + +.. function:: unquote(string[, encoding[, errors]]) Replace ``%xx`` escapes by their single-character equivalent. + The optional *encoding* and *errors* parameters specify how to decode + percent-encoded sequences into Unicode characters, as accepted by the + :meth:`bytes.decode` method. + + *string* must be a :class:`str`. + + *encoding* defaults to ``'utf-8'``. + *errors* defaults to ``'replace'``, meaning invalid sequences are replaced + by a placeholder character. - Example: ``unquote('/%7Econnolly/')`` yields ``'/~connolly/'``. + Example: ``unquote('/El%20Ni%C3%B1o/')`` yields ``'/El Ni?o/'``. -.. function:: unquote_plus(string) +.. function:: unquote_plus(string[, encoding[, errors]]) Like :func:`unquote`, but also replace plus signs by spaces, as required for unquoting HTML form values. + *string* must be a :class:`str`. + + Example: ``unquote_plus('/El+Ni%C3%B1o/')`` yields ``'/El Ni?o/'``. + +.. function:: unquote_to_bytes(string) + + Replace ``%xx`` escapes by their single-octet equivalent, and return a + :class:`bytes` object. + + *string* may be either a :class:`str` or a :class:`bytes`. + + If it is a :class:`str`, unescaped non-ASCII characters in *string* + are encoded into UTF-8 bytes. + + Example: ``unquote_to_bytes('a%26%EF')`` yields + ``b'a&\xef'``. + .. function:: urlencode(query[, doseq]) Modified: python/branches/py3k/Lib/email/utils.py ============================================================================== --- python/branches/py3k/Lib/email/utils.py (original) +++ python/branches/py3k/Lib/email/utils.py Mon Aug 18 23:44:30 2008 @@ -219,7 +219,7 @@ charset is given but not language, the string is encoded using the empty string for language. """ - s = urllib.parse.quote(s, safe='') + s = urllib.parse.quote(s, safe='', encoding=charset or 'ascii') if charset is None and language is None: return s if language is None: @@ -271,7 +271,10 @@ # language specifiers at the beginning of the string. for num, s, encoded in continuations: if encoded: - s = urllib.parse.unquote(s) + # Decode as "latin-1", so the characters in s directly + # represent the percent-encoded octet values. + # collapse_rfc2231_value treats this as an octet sequence. + s = urllib.parse.unquote(s, encoding="latin-1") extended = True value.append(s) value = quote(EMPTYSTRING.join(value)) Modified: python/branches/py3k/Lib/test/test_cgi.py ============================================================================== --- python/branches/py3k/Lib/test/test_cgi.py (original) +++ python/branches/py3k/Lib/test/test_cgi.py Mon Aug 18 23:44:30 2008 @@ -68,6 +68,8 @@ ("&a=b", [('a', 'b')]), ("a=a+b&b=b+c", [('a', 'a b'), ('b', 'b c')]), ("a=1&a=2", [('a', '1'), ('a', '2')]), + ("a=%26&b=%3D", [('a', '&'), ('b', '=')]), + ("a=%C3%BC&b=%CA%83", [('a', '\xfc'), ('b', '\u0283')]), ] parse_strict_test_cases = [ Modified: python/branches/py3k/Lib/test/test_http_cookiejar.py ============================================================================== --- python/branches/py3k/Lib/test/test_http_cookiejar.py (original) +++ python/branches/py3k/Lib/test/test_http_cookiejar.py Mon Aug 18 23:44:30 2008 @@ -539,6 +539,8 @@ # unquoted unsafe ("/foo\031/bar", "/foo%19/bar"), ("/\175foo/bar", "/%7Dfoo/bar"), + # unicode, latin-1 range + ("/foo/bar\u00fc", "/foo/bar%C3%BC"), # UTF-8 encoded # unicode ("/foo/bar\uabcd", "/foo/bar%EA%AF%8D"), # UTF-8 encoded ] @@ -1444,7 +1446,8 @@ # Try some URL encodings of the PATHs. # (the behaviour here has changed from libwww-perl) c = CookieJar(DefaultCookiePolicy(rfc2965=True)) - interact_2965(c, "http://www.acme.com/foo%2f%25/%3c%3c%0Anew%E5/%E5", + interact_2965(c, "http://www.acme.com/foo%2f%25/" + "%3c%3c%0Anew%C3%A5/%C3%A5", "foo = bar; version = 1") cookie = interact_2965( Modified: python/branches/py3k/Lib/test/test_urllib.py ============================================================================== --- python/branches/py3k/Lib/test/test_urllib.py (original) +++ python/branches/py3k/Lib/test/test_urllib.py Mon Aug 18 23:44:30 2008 @@ -336,10 +336,10 @@ "_.-"]) result = urllib.parse.quote(do_not_quote) self.assertEqual(do_not_quote, result, - "using quote(): %s != %s" % (do_not_quote, result)) + "using quote(): %r != %r" % (do_not_quote, result)) result = urllib.parse.quote_plus(do_not_quote) self.assertEqual(do_not_quote, result, - "using quote_plus(): %s != %s" % (do_not_quote, result)) + "using quote_plus(): %r != %r" % (do_not_quote, result)) def test_default_safe(self): # Test '/' is default value for 'safe' parameter @@ -350,11 +350,28 @@ quote_by_default = "<>" result = urllib.parse.quote(quote_by_default, safe=quote_by_default) self.assertEqual(quote_by_default, result, - "using quote(): %s != %s" % (quote_by_default, result)) + "using quote(): %r != %r" % (quote_by_default, result)) result = urllib.parse.quote_plus(quote_by_default, safe=quote_by_default) self.assertEqual(quote_by_default, result, - "using quote_plus(): %s != %s" % + "using quote_plus(): %r != %r" % (quote_by_default, result)) + # Safe expressed as bytes rather than str + result = urllib.parse.quote(quote_by_default, safe=b"<>") + self.assertEqual(quote_by_default, result, + "using quote(): %r != %r" % (quote_by_default, result)) + # "Safe" non-ASCII characters should have no effect + # (Since URIs are not allowed to have non-ASCII characters) + result = urllib.parse.quote("a\xfcb", encoding="latin-1", safe="\xfc") + expect = urllib.parse.quote("a\xfcb", encoding="latin-1", safe="") + self.assertEqual(expect, result, + "using quote(): %r != %r" % + (expect, result)) + # Same as above, but using a bytes rather than str + result = urllib.parse.quote("a\xfcb", encoding="latin-1", safe=b"\xfc") + expect = urllib.parse.quote("a\xfcb", encoding="latin-1", safe="") + self.assertEqual(expect, result, + "using quote(): %r != %r" % + (expect, result)) def test_default_quoting(self): # Make sure all characters that should be quoted are by default sans @@ -378,34 +395,98 @@ expected = "ab%5B%5Dcd" result = urllib.parse.quote(partial_quote) self.assertEqual(expected, result, - "using quote(): %s != %s" % (expected, result)) + "using quote(): %r != %r" % (expected, result)) self.assertEqual(expected, result, - "using quote_plus(): %s != %s" % (expected, result)) + "using quote_plus(): %r != %r" % (expected, result)) def test_quoting_space(self): # Make sure quote() and quote_plus() handle spaces as specified in # their unique way result = urllib.parse.quote(' ') self.assertEqual(result, hexescape(' '), - "using quote(): %s != %s" % (result, hexescape(' '))) + "using quote(): %r != %r" % (result, hexescape(' '))) result = urllib.parse.quote_plus(' ') self.assertEqual(result, '+', - "using quote_plus(): %s != +" % result) + "using quote_plus(): %r != +" % result) given = "a b cd e f" expect = given.replace(' ', hexescape(' ')) result = urllib.parse.quote(given) self.assertEqual(expect, result, - "using quote(): %s != %s" % (expect, result)) + "using quote(): %r != %r" % (expect, result)) expect = given.replace(' ', '+') result = urllib.parse.quote_plus(given) self.assertEqual(expect, result, - "using quote_plus(): %s != %s" % (expect, result)) + "using quote_plus(): %r != %r" % (expect, result)) def test_quoting_plus(self): self.assertEqual(urllib.parse.quote_plus('alpha+beta gamma'), 'alpha%2Bbeta+gamma') self.assertEqual(urllib.parse.quote_plus('alpha+beta gamma', '+'), 'alpha+beta+gamma') + # Test with bytes + self.assertEqual(urllib.parse.quote_plus(b'alpha+beta gamma'), + 'alpha%2Bbeta+gamma') + # Test with safe bytes + self.assertEqual(urllib.parse.quote_plus('alpha+beta gamma', b'+'), + 'alpha+beta+gamma') + + def test_quote_bytes(self): + # Bytes should quote directly to percent-encoded values + given = b"\xa2\xd8ab\xff" + expect = "%A2%D8ab%FF" + result = urllib.parse.quote(given) + self.assertEqual(expect, result, + "using quote(): %r != %r" % (expect, result)) + # Encoding argument should raise type error on bytes input + self.assertRaises(TypeError, urllib.parse.quote, given, + encoding="latin-1") + # quote_from_bytes should work the same + result = urllib.parse.quote_from_bytes(given) + self.assertEqual(expect, result, + "using quote_from_bytes(): %r != %r" + % (expect, result)) + + def test_quote_with_unicode(self): + # Characters in Latin-1 range, encoded by default in UTF-8 + given = "\xa2\xd8ab\xff" + expect = "%C2%A2%C3%98ab%C3%BF" + result = urllib.parse.quote(given) + self.assertEqual(expect, result, + "using quote(): %r != %r" % (expect, result)) + # Characters in Latin-1 range, encoded by with None (default) + result = urllib.parse.quote(given, encoding=None, errors=None) + self.assertEqual(expect, result, + "using quote(): %r != %r" % (expect, result)) + # Characters in Latin-1 range, encoded with Latin-1 + given = "\xa2\xd8ab\xff" + expect = "%A2%D8ab%FF" + result = urllib.parse.quote(given, encoding="latin-1") + self.assertEqual(expect, result, + "using quote(): %r != %r" % (expect, result)) + # Characters in BMP, encoded by default in UTF-8 + given = "\u6f22\u5b57" # "Kanji" + expect = "%E6%BC%A2%E5%AD%97" + result = urllib.parse.quote(given) + self.assertEqual(expect, result, + "using quote(): %r != %r" % (expect, result)) + # Characters in BMP, encoded with Latin-1 + given = "\u6f22\u5b57" + self.assertRaises(UnicodeEncodeError, urllib.parse.quote, given, + encoding="latin-1") + # Characters in BMP, encoded with Latin-1, with replace error handling + given = "\u6f22\u5b57" + expect = "%3F%3F" # "??" + result = urllib.parse.quote(given, encoding="latin-1", + errors="replace") + self.assertEqual(expect, result, + "using quote(): %r != %r" % (expect, result)) + # Characters in BMP, Latin-1, with xmlcharref error handling + given = "\u6f22\u5b57" + expect = "%26%2328450%3B%26%2323383%3B" # "漢字" + result = urllib.parse.quote(given, encoding="latin-1", + errors="xmlcharrefreplace") + self.assertEqual(expect, result, + "using quote(): %r != %r" % (expect, result)) class UnquotingTests(unittest.TestCase): """Tests for unquote() and unquote_plus() @@ -422,23 +503,62 @@ expect = chr(num) result = urllib.parse.unquote(given) self.assertEqual(expect, result, - "using unquote(): %s != %s" % (expect, result)) + "using unquote(): %r != %r" % (expect, result)) result = urllib.parse.unquote_plus(given) self.assertEqual(expect, result, - "using unquote_plus(): %s != %s" % + "using unquote_plus(): %r != %r" % (expect, result)) escape_list.append(given) escape_string = ''.join(escape_list) del escape_list result = urllib.parse.unquote(escape_string) self.assertEqual(result.count('%'), 1, - "using quote(): not all characters escaped; %s" % - result) - result = urllib.parse.unquote(escape_string) - self.assertEqual(result.count('%'), 1, "using unquote(): not all characters escaped: " "%s" % result) + def test_unquoting_badpercent(self): + # Test unquoting on bad percent-escapes + given = '%xab' + expect = given + result = urllib.parse.unquote(given) + self.assertEqual(expect, result, "using unquote(): %r != %r" + % (expect, result)) + given = '%x' + expect = given + result = urllib.parse.unquote(given) + self.assertEqual(expect, result, "using unquote(): %r != %r" + % (expect, result)) + given = '%' + expect = given + result = urllib.parse.unquote(given) + self.assertEqual(expect, result, "using unquote(): %r != %r" + % (expect, result)) + # unquote_to_bytes + given = '%xab' + expect = bytes(given, 'ascii') + result = urllib.parse.unquote_to_bytes(given) + self.assertEqual(expect, result, "using unquote_to_bytes(): %r != %r" + % (expect, result)) + given = '%x' + expect = bytes(given, 'ascii') + result = urllib.parse.unquote_to_bytes(given) + self.assertEqual(expect, result, "using unquote_to_bytes(): %r != %r" + % (expect, result)) + given = '%' + expect = bytes(given, 'ascii') + result = urllib.parse.unquote_to_bytes(given) + self.assertEqual(expect, result, "using unquote_to_bytes(): %r != %r" + % (expect, result)) + + def test_unquoting_mixed_case(self): + # Test unquoting on mixed-case hex digits in the percent-escapes + given = '%Ab%eA' + expect = b'\xab\xea' + result = urllib.parse.unquote_to_bytes(given) + self.assertEqual(expect, result, + "using unquote_to_bytes(): %r != %r" + % (expect, result)) + def test_unquoting_parts(self): # Make sure unquoting works when have non-quoted characters # interspersed @@ -446,10 +566,10 @@ expect = "abcd" result = urllib.parse.unquote(given) self.assertEqual(expect, result, - "using quote(): %s != %s" % (expect, result)) + "using quote(): %r != %r" % (expect, result)) result = urllib.parse.unquote_plus(given) self.assertEqual(expect, result, - "using unquote_plus(): %s != %s" % (expect, result)) + "using unquote_plus(): %r != %r" % (expect, result)) def test_unquoting_plus(self): # Test difference between unquote() and unquote_plus() @@ -457,15 +577,100 @@ expect = given result = urllib.parse.unquote(given) self.assertEqual(expect, result, - "using unquote(): %s != %s" % (expect, result)) + "using unquote(): %r != %r" % (expect, result)) expect = given.replace('+', ' ') result = urllib.parse.unquote_plus(given) self.assertEqual(expect, result, - "using unquote_plus(): %s != %s" % (expect, result)) + "using unquote_plus(): %r != %r" % (expect, result)) + + def test_unquote_to_bytes(self): + given = 'br%C3%BCckner_sapporo_20050930.doc' + expect = b'br\xc3\xbcckner_sapporo_20050930.doc' + result = urllib.parse.unquote_to_bytes(given) + self.assertEqual(expect, result, + "using unquote_to_bytes(): %r != %r" + % (expect, result)) + # Test on a string with unescaped non-ASCII characters + # (Technically an invalid URI; expect those characters to be UTF-8 + # encoded). + result = urllib.parse.unquote_to_bytes("\u6f22%C3%BC") + expect = b'\xe6\xbc\xa2\xc3\xbc' # UTF-8 for "\u6f22\u00fc" + self.assertEqual(expect, result, + "using unquote_to_bytes(): %r != %r" + % (expect, result)) + # Test with a bytes as input + given = b'%A2%D8ab%FF' + expect = b'\xa2\xd8ab\xff' + result = urllib.parse.unquote_to_bytes(given) + self.assertEqual(expect, result, + "using unquote_to_bytes(): %r != %r" + % (expect, result)) + # Test with a bytes as input, with unescaped non-ASCII bytes + # (Technically an invalid URI; expect those bytes to be preserved) + given = b'%A2\xd8ab%FF' + expect = b'\xa2\xd8ab\xff' + result = urllib.parse.unquote_to_bytes(given) + self.assertEqual(expect, result, + "using unquote_to_bytes(): %r != %r" + % (expect, result)) def test_unquote_with_unicode(self): - r = urllib.parse.unquote('br%C3%BCckner_sapporo_20050930.doc') - self.assertEqual(r, 'br\xc3\xbcckner_sapporo_20050930.doc') + # Characters in the Latin-1 range, encoded with UTF-8 + given = 'br%C3%BCckner_sapporo_20050930.doc' + expect = 'br\u00fcckner_sapporo_20050930.doc' + result = urllib.parse.unquote(given) + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) + # Characters in the Latin-1 range, encoded with None (default) + result = urllib.parse.unquote(given, encoding=None, errors=None) + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) + + # Characters in the Latin-1 range, encoded with Latin-1 + result = urllib.parse.unquote('br%FCckner_sapporo_20050930.doc', + encoding="latin-1") + expect = 'br\u00fcckner_sapporo_20050930.doc' + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) + + # Characters in BMP, encoded with UTF-8 + given = "%E6%BC%A2%E5%AD%97" + expect = "\u6f22\u5b57" # "Kanji" + result = urllib.parse.unquote(given) + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) + + # Decode with UTF-8, invalid sequence + given = "%F3%B1" + expect = "\ufffd" # Replacement character + result = urllib.parse.unquote(given) + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) + + # Decode with UTF-8, invalid sequence, replace errors + result = urllib.parse.unquote(given, errors="replace") + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) + + # Decode with UTF-8, invalid sequence, ignoring errors + given = "%F3%B1" + expect = "" + result = urllib.parse.unquote(given, errors="ignore") + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) + + # A mix of non-ASCII and percent-encoded characters, UTF-8 + result = urllib.parse.unquote("\u6f22%C3%BC") + expect = '\u6f22\u00fc' + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) + + # A mix of non-ASCII and percent-encoded characters, Latin-1 + # (Note, the string contains non-Latin-1-representable characters) + result = urllib.parse.unquote("\u6f22%FC", encoding="latin-1") + expect = '\u6f22\u00fc' + self.assertEqual(expect, result, + "using unquote(): %r != %r" % (expect, result)) class urlencode_Tests(unittest.TestCase): """Tests for urlencode()""" Modified: python/branches/py3k/Lib/test/test_wsgiref.py ============================================================================== --- python/branches/py3k/Lib/test/test_wsgiref.py (original) +++ python/branches/py3k/Lib/test/test_wsgiref.py Mon Aug 18 23:44:30 2008 @@ -291,6 +291,7 @@ def testAppURIs(self): self.checkAppURI("http://127.0.0.1/") self.checkAppURI("http://127.0.0.1/spam", SCRIPT_NAME="/spam") + self.checkAppURI("http://127.0.0.1/sp%C3%A4m", SCRIPT_NAME="/sp?m") self.checkAppURI("http://spam.example.com:2071/", HTTP_HOST="spam.example.com:2071", SERVER_PORT="2071") self.checkAppURI("http://spam.example.com/", @@ -304,6 +305,7 @@ def testReqURIs(self): self.checkReqURI("http://127.0.0.1/") self.checkReqURI("http://127.0.0.1/spam", SCRIPT_NAME="/spam") + self.checkReqURI("http://127.0.0.1/sp%C3%A4m", SCRIPT_NAME="/sp?m") self.checkReqURI("http://127.0.0.1/spammity/spam", SCRIPT_NAME="/spammity", PATH_INFO="/spam") self.checkReqURI("http://127.0.0.1/spammity/spam?say=ni", Modified: python/branches/py3k/Lib/urllib/parse.py ============================================================================== --- python/branches/py3k/Lib/urllib/parse.py (original) +++ python/branches/py3k/Lib/urllib/parse.py Mon Aug 18 23:44:30 2008 @@ -5,9 +5,12 @@ """ import sys +import collections __all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag", - "urlsplit", "urlunsplit"] + "urlsplit", "urlunsplit", + "quote", "quote_plus", "quote_from_bytes", + "unquote", "unquote_plus", "unquote_to_bytes"] # A classification of schemes ('' means apply by default) uses_relative = ['ftp', 'http', 'gopher', 'nntp', 'imap', @@ -269,50 +272,101 @@ else: return url, '' +def unquote_to_bytes(string): + """unquote_to_bytes('abc%20def') -> b'abc def'.""" + # Note: strings are encoded as UTF-8. This is only an issue if it contains + # unescaped non-ASCII characters, which URIs should not. + if isinstance(string, str): + string = string.encode('utf-8') + res = string.split(b'%') + res[0] = res[0] + for i in range(1, len(res)): + item = res[i] + try: + res[i] = bytes([int(item[:2], 16)]) + item[2:] + except ValueError: + res[i] = b'%' + item + return b''.join(res) -_hextochr = dict(('%02x' % i, chr(i)) for i in range(256)) -_hextochr.update(('%02X' % i, chr(i)) for i in range(256)) +def unquote(string, encoding='utf-8', errors='replace'): + """Replace %xx escapes by their single-character equivalent. The optional + encoding and errors parameters specify how to decode percent-encoded + sequences into Unicode characters, as accepted by the bytes.decode() + method. + By default, percent-encoded sequences are decoded with UTF-8, and invalid + sequences are replaced by a placeholder character. -def unquote(s): - """unquote('abc%20def') -> 'abc def'.""" - res = s.split('%') + unquote('abc%20def') -> 'abc def'. + """ + if encoding is None: encoding = 'utf-8' + if errors is None: errors = 'replace' + # pct_sequence: contiguous sequence of percent-encoded bytes, decoded + # (list of single-byte bytes objects) + pct_sequence = [] + res = string.split('%') for i in range(1, len(res)): item = res[i] try: - res[i] = _hextochr[item[:2]] + item[2:] - except KeyError: - res[i] = '%' + item - except UnicodeDecodeError: - res[i] = chr(int(item[:2], 16)) + item[2:] - return "".join(res) - -def unquote_plus(s): - """unquote('%7e/abc+def') -> '~/abc def'""" - s = s.replace('+', ' ') - return unquote(s) - -always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' - 'abcdefghijklmnopqrstuvwxyz' - '0123456789' '_.-') + if not item: raise ValueError + pct_sequence.append(bytes.fromhex(item[:2])) + rest = item[2:] + except ValueError: + rest = '%' + item + if not rest: + # This segment was just a single percent-encoded character. + # May be part of a sequence of code units, so delay decoding. + # (Stored in pct_sequence). + res[i] = '' + else: + # Encountered non-percent-encoded characters. Flush the current + # pct_sequence. + res[i] = b''.join(pct_sequence).decode(encoding, errors) + rest + pct_sequence = [] + if pct_sequence: + # Flush the final pct_sequence + # res[-1] will always be empty if pct_sequence != [] + assert not res[-1], "string=%r, res=%r" % (string, res) + res[-1] = b''.join(pct_sequence).decode(encoding, errors) + return ''.join(res) + +def unquote_plus(string, encoding='utf-8', errors='replace'): + """Like unquote(), but also replace plus signs by spaces, as required for + unquoting HTML form values. + + unquote_plus('%7e/abc+def') -> '~/abc def' + """ + string = string.replace('+', ' ') + return unquote(string, encoding, errors) + +_ALWAYS_SAFE = frozenset(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + b'abcdefghijklmnopqrstuvwxyz' + b'0123456789' + b'_.-') _safe_quoters= {} -class Quoter: +class Quoter(collections.defaultdict): + """A mapping from bytes (in range(0,256)) to strings. + + String values are percent-encoded byte values, unless the key < 128, and + in the "safe" set (either the specified safe set, or default set). + """ + # Keeps a cache internally, using defaultdict, for efficiency (lookups + # of cached keys don't call Python code at all). def __init__(self, safe): - self.cache = {} - self.safe = safe + always_safe + """safe: bytes object.""" + self.safe = _ALWAYS_SAFE.union(c for c in safe if c < 128) - def __call__(self, c): - try: - return self.cache[c] - except KeyError: - if ord(c) < 256: - res = (c in self.safe) and c or ('%%%02X' % ord(c)) - self.cache[c] = res - return res - else: - return "".join(['%%%02X' % i for i in c.encode("utf-8")]) + def __repr__(self): + # Without this, will just display as a defaultdict + return "" % dict(self) + + def __missing__(self, b): + # Handle a cache miss. Store quoted string in cache and return. + res = b in self.safe and chr(b) or ('%%%02X' % b) + self[b] = res + return res -def quote(s, safe = '/'): +def quote(string, safe='/', encoding=None, errors=None): """quote('abc def') -> 'abc%20def' Each part of a URL, e.g. the path info, the query, etc., has a @@ -332,22 +386,57 @@ is reserved, but in typical usage the quote function is being called on a path where the existing slash characters are used as reserved characters. + + string and safe may be either str or bytes objects. encoding must + not be specified if string is a str. + + The optional encoding and errors parameters specify how to deal with + non-ASCII characters, as accepted by the str.encode method. + By default, encoding='utf-8' (characters are encoded with UTF-8), and + errors='strict' (unsupported characters raise a UnicodeEncodeError). """ - cachekey = (safe, always_safe) + if isinstance(string, str): + if encoding is None: + encoding = 'utf-8' + if errors is None: + errors = 'strict' + string = string.encode(encoding, errors) + else: + if encoding is not None: + raise TypeError("quote() doesn't support 'encoding' for bytes") + if errors is not None: + raise TypeError("quote() doesn't support 'errors' for bytes") + return quote_from_bytes(string, safe) + +def quote_plus(string, safe='', encoding=None, errors=None): + """Like quote(), but also replace ' ' with '+', as required for quoting + HTML form values. Plus signs in the original string are escaped unless + they are included in safe. It also does not have safe default to '/'. + """ + # Check if ' ' in string, where string may either be a str or bytes + if ' ' in string if isinstance(string, str) else b' ' in string: + string = quote(string, + safe + ' ' if isinstance(safe, str) else safe + b' ') + return string.replace(' ', '+') + return quote(string, safe, encoding, errors) + +def quote_from_bytes(bs, safe='/'): + """Like quote(), but accepts a bytes object rather than a str, and does + not perform string-to-bytes encoding. It always returns an ASCII string. + quote_from_bytes(b'abc def\xab') -> 'abc%20def%AB' + """ + if isinstance(safe, str): + # Normalize 'safe' by converting to bytes and removing non-ASCII chars + safe = safe.encode('ascii', 'ignore') + cachekey = bytes(safe) # In case it was a bytearray + if not (isinstance(bs, bytes) or isinstance(bs, bytearray)): + raise TypeError("quote_from_bytes() expected a bytes") try: quoter = _safe_quoters[cachekey] except KeyError: quoter = Quoter(safe) _safe_quoters[cachekey] = quoter - res = map(quoter, s) - return ''.join(res) - -def quote_plus(s, safe = ''): - """Quote the query fragment of a URL; replacing ' ' with '+'""" - if ' ' in s: - s = quote(s, safe + ' ') - return s.replace(' ', '+') - return quote(s, safe) + return ''.join(map(quoter.__getitem__, bs)) def urlencode(query,doseq=0): """Encode a sequence of two-element tuples or dictionary into a URL query string. Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Aug 18 23:44:30 2008 @@ -30,6 +30,13 @@ Library ------- +- Issue #3300: make urllib.parse.[un]quote() default to UTF-8. + Code contributed by Matt Giuca. quote() now encodes the input + before quoting, unquote() decodes after unquoting. There are + new arguments to change the encoding and errors settings. + There are also new APIs to skip the encode/decode steps. + [un]quote_plus() are also affected. + - Issue #2235: numbers.Number now blocks inheritance of the default id() based hash because that hash mechanism is not correct for numeric types. All concrete numeric types that inherit from Number (rather than just From python-3000-checkins at python.org Mon Aug 18 23:55:16 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 18 Aug 2008 23:55:16 +0200 (CEST) Subject: [Python-3000-checkins] r65840 - python/branches/py3k Message-ID: <20080818215516.190991E400F@bag.python.org> Author: benjamin.peterson Date: Mon Aug 18 23:55:15 2008 New Revision: 65840 Log: Blocked revisions 65839 via svnmerge ........ r65839 | benjamin.peterson | 2008-08-18 16:53:29 -0500 (Mon, 18 Aug 2008) | 4 lines add py3k warnings for old threading APIs they will still live in 3.0 but it can't hurt ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Tue Aug 19 00:10:13 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 00:10:13 +0200 (CEST) Subject: [Python-3000-checkins] r65841 - in python/branches/py3k/Lib: test/test_threading.py threading.py Message-ID: <20080818221013.D29EE1E4006@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 00:10:13 2008 New Revision: 65841 Log: add full deprecation warnings for old threading APIs Modified: python/branches/py3k/Lib/test/test_threading.py python/branches/py3k/Lib/threading.py Modified: python/branches/py3k/Lib/test/test_threading.py ============================================================================== --- python/branches/py3k/Lib/test/test_threading.py (original) +++ python/branches/py3k/Lib/test/test_threading.py Tue Aug 19 00:10:13 2008 @@ -1,7 +1,7 @@ # Very rudimentary test of threading module import test.support -from test.support import verbose +from test.support import verbose, catch_warning import random import re import sys @@ -323,6 +323,43 @@ msg=('%d references still around' % sys.getrefcount(weak_raising_cyclic_object()))) + def test_pep8ified_threading(self): + import threading + + def check(_, w, msg): + self.assertEqual(str(w.message), msg) + + t = threading.Thread() + with catch_warning() as w: + msg = "isDaemon() is deprecated in favor of the " \ + "Thread.daemon property" + check(t.isDaemon(), w, msg) + w.reset() + msg = "setDaemon() is deprecated in favor of the " \ + "Thread.daemon property" + check(t.setDaemon(True), w, msg) + w.reset() + msg = "getName() is deprecated in favor of the " \ + "Thread.name property" + check(t.getName(), w, msg) + w.reset() + msg = "setName() is deprecated in favor of the " \ + "Thread.name property" + check(t.setName("name"), w, msg) + w.reset() + msg = "isAlive() is deprecated in favor of is_alive()" + check(t.isAlive(), w, msg) + w.reset() + e = threading.Event() + msg = "isSet() is deprecated in favor of is_set()" + check(e.isSet(), w, msg) + w.reset() + msg = "currentThread() is deprecated in favor of current_thread()" + check(threading.currentThread(), w, msg) + w.reset() + msg = "activeCount() is deprecated in favor of active_count()" + check(threading.activeCount(), w, msg) + class ThreadJoinOnShutdown(unittest.TestCase): Modified: python/branches/py3k/Lib/threading.py ============================================================================== --- python/branches/py3k/Lib/threading.py (original) +++ python/branches/py3k/Lib/threading.py Tue Aug 19 00:10:13 2008 @@ -2,6 +2,7 @@ import sys as _sys import _thread +import warnings from time import time as _time, sleep as _sleep from traceback import format_exc as _format_exc @@ -340,6 +341,11 @@ def is_set(self): return self._flag + def isSet(self): + warnings.warn("isSet() is deprecated in favor of is_set()", + DeprecationWarning) + return self.is_set() + def set(self): self._cond.acquire() try: @@ -640,6 +646,11 @@ assert self._initialized, "Thread.__init__() not called" return self._started.is_set() and not self._stopped + def isAlive(self): + warnings.warn("isAlive() is deprecated in favor of is_alive()", + DeprecationWarning) + return self.is_alive() + @property def daemon(self): assert self._initialized, "Thread.__init__() not called" @@ -654,15 +665,23 @@ self._daemonic = daemonic def isDaemon(self): + warnings.warn("isDaemon() is deprecated in favor of the " \ + "Thread.daemon property", DeprecationWarning) return self.daemon def setDaemon(self, daemonic): + warnings.warn("setDaemon() is deprecated in favor of the " \ + "Thread.daemon property", DeprecationWarning) self.daemon = daemonic def getName(self): + warnings.warn("getName() is deprecated in favor of the " \ + "Thread.name property", DeprecationWarning) return self.name def setName(self, name): + warnings.warn("setName() is deprecated in favor of the " \ + "Thread.name property", DeprecationWarning) self.name = name # The timer class was contributed by Itamar Shtull-Trauring @@ -771,12 +790,21 @@ ##print "current_thread(): no current thread for", _get_ident() return _DummyThread() +def currentThread(): + warnings.warn("currentThread() is deprecated in favor of current_thread()", + DeprecationWarning) + def active_count(): _active_limbo_lock.acquire() count = len(_active) + len(_limbo) _active_limbo_lock.release() return count +def activeCount(): + warnings.warn("activeCount() is deprecated in favor of active_count()", + DeprecationWarning) + return active_count() + def enumerate(): _active_limbo_lock.acquire() active = list(_active.values()) + list(_limbo.values()) From python-3000-checkins at python.org Tue Aug 19 00:40:25 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 00:40:25 +0200 (CEST) Subject: [Python-3000-checkins] r65844 - python/branches/py3k/Misc/NEWS Message-ID: <20080818224025.97C551E4006@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 00:40:25 2008 New Revision: 65844 Log: update NEWS Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Aug 19 00:40:25 2008 @@ -327,7 +327,8 @@ - The test.test_support module has been renamed to test.support. -- The threading module API was renamed to be PEP 8 complaint. +- The threading module API was renamed to be PEP 8 complaint. The old names are + still present, but will be removed in the near future. Tools/Demos ----------- From python-3000-checkins at python.org Tue Aug 19 01:07:41 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Tue, 19 Aug 2008 01:07:41 +0200 (CEST) Subject: [Python-3000-checkins] r65845 - python/branches/py3k/Misc/NEWS Message-ID: <20080818230742.01BC21E4020@bag.python.org> Author: georg.brandl Date: Tue Aug 19 01:07:41 2008 New Revision: 65845 Log: Fix typo. Modified: python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Aug 19 01:07:41 2008 @@ -327,8 +327,8 @@ - The test.test_support module has been renamed to test.support. -- The threading module API was renamed to be PEP 8 complaint. The old names are - still present, but will be removed in the near future. +- The threading module API was renamed to be PEP 8 compliant. The + old names are still present, but will be removed in the near future. Tools/Demos ----------- From python-3000-checkins at python.org Tue Aug 19 01:15:52 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 01:15:52 +0200 (CEST) Subject: [Python-3000-checkins] r65847 - python/branches/py3k/Lib/bsddb/test/test_thread.py Message-ID: <20080818231552.7F4F21E4011@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 01:15:52 2008 New Revision: 65847 Log: fix get_name usage Modified: python/branches/py3k/Lib/bsddb/test/test_thread.py Modified: python/branches/py3k/Lib/bsddb/test/test_thread.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_thread.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_thread.py Tue Aug 19 01:15:52 2008 @@ -89,20 +89,20 @@ self._writerThread(*args, **kwargs) except db.DBLockDeadlockError: if verbose: - print(current_thread().get_name(), 'died from', e) + print(current_thread().name, 'died from', e) else: if verbose: - print(current_thread().get_name(), "finished.") + print(current_thread().name, "finished.") def readerThread(self, *args, **kwargs): try: self._readerThread(*args, **kwargs) except db.DBLockDeadlockError as e: if verbose: - print(current_thread().get_name(), 'died from', e) + print(current_thread().name, 'died from', e) else: if verbose: - print(current_thread().get_name(), "finished.") + print(current_thread().name, "finished.") @@ -143,7 +143,7 @@ t.join() def _writerThread(self, d, howMany): - name = current_thread().get_name() + name = current_thread().name start = 0 stop = howMany if verbose: @@ -172,7 +172,7 @@ def _readerThread(self, d, readerNum): time.sleep(0.01 * readerNum) - name = current_thread().get_name() + name = current_thread().name for loop in range(5): c = d.cursor() @@ -240,7 +240,7 @@ t.join() def _writerThread(self, d, howMany, writerNum): - name = current_thread().get_name() + name = current_thread().name start = howMany * writerNum stop = howMany * (writerNum + 1) - 1 if verbose: @@ -286,7 +286,7 @@ def _readerThread(self, d, readerNum): time.sleep(0.01 * readerNum) - name = current_thread().get_name() + name = current_thread().name for loop in range(5): c = d.cursor() @@ -385,7 +385,7 @@ time.sleep(0.05) def _writerThread(self, d, howMany, writerNum): - name = current_thread().get_name() + name = current_thread().name start = howMany * writerNum stop = howMany * (writerNum + 1) - 1 if verbose: @@ -427,7 +427,7 @@ def _readerThread(self, d, readerNum): time.sleep(0.01 * readerNum + 0.05) - name = current_thread().get_name() + name = current_thread().name for loop in range(5): finished = False From python-3000-checkins at python.org Tue Aug 19 03:34:34 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 03:34:34 +0200 (CEST) Subject: [Python-3000-checkins] r65848 - python/branches/py3k/Lib/test/test_threading.py Message-ID: <20080819013434.CB84B1E4004@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 03:34:34 2008 New Revision: 65848 Log: make test more robust Modified: python/branches/py3k/Lib/test/test_threading.py Modified: python/branches/py3k/Lib/test/test_threading.py ============================================================================== --- python/branches/py3k/Lib/test/test_threading.py (original) +++ python/branches/py3k/Lib/test/test_threading.py Tue Aug 19 03:34:34 2008 @@ -324,13 +324,14 @@ sys.getrefcount(weak_raising_cyclic_object()))) def test_pep8ified_threading(self): - import threading + import warnings def check(_, w, msg): self.assertEqual(str(w.message), msg) t = threading.Thread() with catch_warning() as w: + warnings.simplefilter("always", DeprecationWarning) msg = "isDaemon() is deprecated in favor of the " \ "Thread.daemon property" check(t.isDaemon(), w, msg) From python-3000-checkins at python.org Tue Aug 19 08:36:52 2008 From: python-3000-checkins at python.org (thomas.heller) Date: Tue, 19 Aug 2008 08:36:52 +0200 (CEST) Subject: [Python-3000-checkins] r65849 - python/branches/py3k/Lib/ctypes/test/test_frombuffer.py Message-ID: <20080819063652.97C061E4013@bag.python.org> Author: thomas.heller Date: Tue Aug 19 08:36:52 2008 New Revision: 65849 Log: Fix and enable a test that now works. Modified: python/branches/py3k/Lib/ctypes/test/test_frombuffer.py Modified: python/branches/py3k/Lib/ctypes/test/test_frombuffer.py ============================================================================== --- python/branches/py3k/Lib/ctypes/test/test_frombuffer.py (original) +++ python/branches/py3k/Lib/ctypes/test/test_frombuffer.py Tue Aug 19 08:36:52 2008 @@ -43,7 +43,7 @@ self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a, sizeof(c_int))) self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 * sizeof(c_int))) - def BROKEN_test_from_buffer_copy(self): + def test_from_buffer_copy(self): a = array.array("i", range(16)) x = (c_int * 16).from_buffer_copy(a) @@ -64,8 +64,8 @@ del a; gc.collect(); gc.collect(); gc.collect() self.assertEqual(x[:], list(range(16))) - x = (c_char * 16).from_buffer_copy("a" * 16) - self.assertEqual(x[:], "a" * 16) + x = (c_char * 16).from_buffer_copy(b"a" * 16) + self.assertEqual(x[:], b"a" * 16) def test_fom_buffer_copy_with_offset(self): a = array.array("i", range(16)) From python-3000-checkins at python.org Tue Aug 19 08:38:12 2008 From: python-3000-checkins at python.org (thomas.heller) Date: Tue, 19 Aug 2008 08:38:12 +0200 (CEST) Subject: [Python-3000-checkins] r65850 - in python/branches/py3k: Lib/ctypes/__init__.py Lib/ctypes/test/test_memfunctions.py Misc/NEWS Message-ID: <20080819063812.CCBBE1E4004@bag.python.org> Author: thomas.heller Date: Tue Aug 19 08:38:12 2008 New Revision: 65850 Log: Merged revisions 65681-65682,65684 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65681 | thomas.heller | 2008-08-14 21:10:48 +0200 (Do, 14 Aug 2008) | 4 lines issue #3554: ctypes.string_at and ctypes.wstring_at must use the pythonapi calling convention so that the GIL is held and error return values are checked. ........ r65682 | thomas.heller | 2008-08-14 22:04:38 +0200 (Do, 14 Aug 2008) | 2 lines Try to fix the test on 64-bit platforms. ........ r65684 | thomas.heller | 2008-08-14 22:19:18 +0200 (Do, 14 Aug 2008) | 2 lines Disable the test until I have one that works. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/ctypes/__init__.py python/branches/py3k/Lib/ctypes/test/test_memfunctions.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/ctypes/__init__.py ============================================================================== --- python/branches/py3k/Lib/ctypes/__init__.py (original) +++ python/branches/py3k/Lib/ctypes/__init__.py Tue Aug 19 08:38:12 2008 @@ -485,7 +485,7 @@ def cast(obj, typ): return _cast(obj, obj, typ) -_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) +_string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) def string_at(ptr, size=-1): """string_at(addr[, size]) -> string @@ -497,7 +497,7 @@ except ImportError: pass else: - _wstring_at = CFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) + _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) def wstring_at(ptr, size=-1): """wstring_at(addr[, size]) -> string Modified: python/branches/py3k/Lib/ctypes/test/test_memfunctions.py ============================================================================== --- python/branches/py3k/Lib/ctypes/test/test_memfunctions.py (original) +++ python/branches/py3k/Lib/ctypes/test/test_memfunctions.py Tue Aug 19 08:38:12 2008 @@ -3,6 +3,16 @@ from ctypes import * class MemFunctionsTest(unittest.TestCase): +## def test_overflow(self): +## # string_at and wstring_at must use the Python calling +## # convention (which acquires the GIL and checks the Python +## # error flag). Provoke an error and catch it; see also issue +## # #3554: +## self.assertRaises((OverflowError, MemoryError, SystemError), +## lambda: wstring_at(u"foo", sys.maxint - 1)) +## self.assertRaises((OverflowError, MemoryError, SystemError), +## lambda: string_at("foo", sys.maxint - 1)) + def test_memmove(self): # large buffers apparently increase the chance that the memory # is allocated in high address space. Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Aug 19 08:38:12 2008 @@ -103,6 +103,12 @@ - Removed the sunaudio module. Use sunau instead. +- Issue #3554: ctypes.string_at and ctypes.wstring_at did call Python + api functions without holding the GIL, which could lead to a fatal + error when they failed. + +- Issue #799428: Fix Tkinter.Misc._nametowidget to unwrap Tcl command objects. + - Removed "ast" function aliases from the parser module. - Issue #3313: Fixed a crash when a failed dlopen() call does not set From python-3000-checkins at python.org Tue Aug 19 16:12:01 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 16:12:01 +0200 (CEST) Subject: [Python-3000-checkins] r65851 - python/branches/py3k/Lib/test/test_threading.py Message-ID: <20080819141201.A16AB1E4006@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 16:12:01 2008 New Revision: 65851 Log: make test_threading more robust for real Modified: python/branches/py3k/Lib/test/test_threading.py Modified: python/branches/py3k/Lib/test/test_threading.py ============================================================================== --- python/branches/py3k/Lib/test/test_threading.py (original) +++ python/branches/py3k/Lib/test/test_threading.py Tue Aug 19 16:12:01 2008 @@ -324,14 +324,12 @@ sys.getrefcount(weak_raising_cyclic_object()))) def test_pep8ified_threading(self): - import warnings - def check(_, w, msg): self.assertEqual(str(w.message), msg) t = threading.Thread() with catch_warning() as w: - warnings.simplefilter("always", DeprecationWarning) + del threading.__warningregistry__ msg = "isDaemon() is deprecated in favor of the " \ "Thread.daemon property" check(t.isDaemon(), w, msg) From python-3000-checkins at python.org Tue Aug 19 16:32:56 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 16:32:56 +0200 (CEST) Subject: [Python-3000-checkins] r65852 - python/branches/py3k/Lib/test/test_threading.py Message-ID: <20080819143256.E7EC61E4006@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 16:32:56 2008 New Revision: 65852 Log: fix possible error Modified: python/branches/py3k/Lib/test/test_threading.py Modified: python/branches/py3k/Lib/test/test_threading.py ============================================================================== --- python/branches/py3k/Lib/test/test_threading.py (original) +++ python/branches/py3k/Lib/test/test_threading.py Tue Aug 19 16:32:56 2008 @@ -329,7 +329,10 @@ t = threading.Thread() with catch_warning() as w: - del threading.__warningregistry__ + try: + del threading.__warningregistry__ + except AttributeError: + pass msg = "isDaemon() is deprecated in favor of the " \ "Thread.daemon property" check(t.isDaemon(), w, msg) From python-3000-checkins at python.org Tue Aug 19 18:49:40 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 18:49:40 +0200 (CEST) Subject: [Python-3000-checkins] r65856 - in python/branches/py3k: Lib/lib2to3 Lib/lib2to3/refactor.py Tools/scripts/2to3 Message-ID: <20080819164940.0E3B31E4009@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 18:49:39 2008 New Revision: 65856 Log: Merged revisions 65855 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ................ r65855 | benjamin.peterson | 2008-08-19 11:41:34 -0500 (Tue, 19 Aug 2008) | 13 lines Merged revisions 65853-65854 via svnmerge from svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3/lib2to3 ........ r65853 | benjamin.peterson | 2008-08-19 11:09:09 -0500 (Tue, 19 Aug 2008) | 1 line apply a patch for #3131. this solves the problem for the moment, but we should do some refactoring to get display logic out of RefactoringTool ........ r65854 | benjamin.peterson | 2008-08-19 11:37:38 -0500 (Tue, 19 Aug 2008) | 1 line another quick fix to get lib2to3 to work ........ ................ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/lib2to3/ (props changed) python/branches/py3k/Lib/lib2to3/refactor.py python/branches/py3k/Tools/scripts/2to3 Modified: python/branches/py3k/Lib/lib2to3/refactor.py ============================================================================== --- python/branches/py3k/Lib/lib2to3/refactor.py (original) +++ python/branches/py3k/Lib/lib2to3/refactor.py Tue Aug 19 18:49:39 2008 @@ -172,9 +172,11 @@ want a pre-order AST traversal, and post_order is the list that want post-order traversal. """ - fixer_pkg = self.fixer_dir.replace(os.path.sep, ".") - if os.path.altsep: - fixer_pkg = fixer_pkg.replace(os.path.altsep, ".") + if os.path.isabs(self.fixer_dir): + fixer_pkg = os.path.relpath(self.fixer_dir, os.path.join(os.path.dirname(__file__), '..')) + else: + fixer_pkg = self.fixer_dir + fixer_pkg = fixer_pkg.replace(os.path.sep, ".") pre_order_fixers = [] post_order_fixers = [] fix_names = self.options.fix Modified: python/branches/py3k/Tools/scripts/2to3 ============================================================================== --- python/branches/py3k/Tools/scripts/2to3 (original) +++ python/branches/py3k/Tools/scripts/2to3 Tue Aug 19 18:49:39 2008 @@ -1,5 +1,7 @@ #!/usr/bin/env python from lib2to3 import refactor import sys +import os -sys.exit(refactor.main("lib2to3/fixes")) +fixers = os.path.join(os.path.dirname(refactor.__file__), "fixes") +sys.exit(refactor.main(fixers)) From python-3000-checkins at python.org Tue Aug 19 19:16:56 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 19:16:56 +0200 (CEST) Subject: [Python-3000-checkins] r65857 - in python/branches/py3k: configure configure.in Message-ID: <20080819171656.C52031E4006@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 19:16:56 2008 New Revision: 65857 Log: Merged revisions 65652-65653 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65652 | ronald.oussoren | 2008-08-12 07:29:13 -0500 (Tue, 12 Aug 2008) | 2 lines Fix typo in the `arch` commandline ........ r65653 | ronald.oussoren | 2008-08-12 07:41:45 -0500 (Tue, 12 Aug 2008) | 3 lines Another fix for 4-way universal builds, use the right #ifndef guard to detect the OSX 10.5 SDK. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/configure python/branches/py3k/configure.in Modified: python/branches/py3k/configure ============================================================================== --- python/branches/py3k/configure (original) +++ python/branches/py3k/configure Tue Aug 19 19:16:56 2008 @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 65034 . +# From configure.in Revision: 65206 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 3.0. # @@ -4601,7 +4601,7 @@ elif test "$UNIVERSAL_ARCHS" = "all" ; then UNIVERSAL_ARCH_FLAGS="-arch i386 -arch ppc -arch ppc64 -arch x86_64" - ARCH_RUN_32BIT="arch -386 -ppc" + ARCH_RUN_32BIT="arch -i386 -ppc" else { { echo "$as_me:$LINENO: error: proper usage is --with-universalarch=32-bit|64-bit|all" >&5 Modified: python/branches/py3k/configure.in ============================================================================== --- python/branches/py3k/configure.in (original) +++ python/branches/py3k/configure.in Tue Aug 19 19:16:56 2008 @@ -871,7 +871,7 @@ elif test "$UNIVERSAL_ARCHS" = "all" ; then UNIVERSAL_ARCH_FLAGS="-arch i386 -arch ppc -arch ppc64 -arch x86_64" - ARCH_RUN_32BIT="arch -386 -ppc" + ARCH_RUN_32BIT="arch -i386 -ppc" else AC_MSG_ERROR([proper usage is --with-universalarch=32-bit|64-bit|all]) From python-3000-checkins at python.org Tue Aug 19 19:56:34 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Tue, 19 Aug 2008 19:56:34 +0200 (CEST) Subject: [Python-3000-checkins] r65860 - in python/branches/py3k: Doc/library/re.rst Lib/_strptime.py Lib/base64.py Lib/decimal.py Lib/distutils/cygwinccompiler.py Lib/distutils/emxccompiler.py Lib/distutils/sysconfig.py Lib/distutils/util.py Lib/distutils/version.py Lib/distutils/versionpredicate.py Lib/email/quoprimime.py Lib/email/utils.py Lib/encodings/idna.py Lib/ftplib.py Lib/html/parser.py Lib/http/cookiejar.py Lib/http/cookies.py Lib/imaplib.py Lib/json/decoder.py Lib/logging/handlers.py Lib/platform.py Lib/plistlib.py Lib/posixpath.py Lib/py_compile.py Lib/re.py Lib/sre_constants.py Lib/sre_parse.py Lib/tarfile.py Lib/test/re_tests.py Lib/test/test_bytes.py Lib/test/test_mmap.py Lib/test/test_re.py Lib/tokenize.py Lib/urllib/request.py Misc/NEWS Modules/_sre.c Modules/sre.h Message-ID: <20080819175634.F3BBE1E4006@bag.python.org> Author: antoine.pitrou Date: Tue Aug 19 19:56:33 2008 New Revision: 65860 Log: #2834: Change re module semantics, so that str and bytes mixing is forbidden, and str (unicode) patterns get full unicode matching by default. The re.ASCII flag is also introduced to ask for ASCII matching instead. Modified: python/branches/py3k/Doc/library/re.rst python/branches/py3k/Lib/_strptime.py python/branches/py3k/Lib/base64.py python/branches/py3k/Lib/decimal.py python/branches/py3k/Lib/distutils/cygwinccompiler.py python/branches/py3k/Lib/distutils/emxccompiler.py python/branches/py3k/Lib/distutils/sysconfig.py python/branches/py3k/Lib/distutils/util.py python/branches/py3k/Lib/distutils/version.py python/branches/py3k/Lib/distutils/versionpredicate.py python/branches/py3k/Lib/email/quoprimime.py python/branches/py3k/Lib/email/utils.py python/branches/py3k/Lib/encodings/idna.py python/branches/py3k/Lib/ftplib.py python/branches/py3k/Lib/html/parser.py python/branches/py3k/Lib/http/cookiejar.py python/branches/py3k/Lib/http/cookies.py python/branches/py3k/Lib/imaplib.py python/branches/py3k/Lib/json/decoder.py python/branches/py3k/Lib/logging/handlers.py python/branches/py3k/Lib/platform.py python/branches/py3k/Lib/plistlib.py python/branches/py3k/Lib/posixpath.py python/branches/py3k/Lib/py_compile.py python/branches/py3k/Lib/re.py python/branches/py3k/Lib/sre_constants.py python/branches/py3k/Lib/sre_parse.py python/branches/py3k/Lib/tarfile.py python/branches/py3k/Lib/test/re_tests.py python/branches/py3k/Lib/test/test_bytes.py python/branches/py3k/Lib/test/test_mmap.py python/branches/py3k/Lib/test/test_re.py python/branches/py3k/Lib/tokenize.py python/branches/py3k/Lib/urllib/request.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_sre.c python/branches/py3k/Modules/sre.h Modified: python/branches/py3k/Doc/library/re.rst ============================================================================== --- python/branches/py3k/Doc/library/re.rst (original) +++ python/branches/py3k/Doc/library/re.rst Tue Aug 19 19:56:33 2008 @@ -11,9 +11,13 @@ This module provides regular expression matching operations similar to -those found in Perl. Both patterns and strings to be searched can be -Unicode strings as well as 8-bit strings. The :mod:`re` module is -always available. +those found in Perl. The :mod:`re` module is always available. + +Both patterns and strings to be searched can be Unicode strings as well as +8-bit strings. However, Unicode strings and 8-bit strings cannot be mixed: +that is, you cannot match an Unicode string with a byte pattern or +vice-versa; similarly, when asking for a substition, the replacement +string must be of the same type as both the pattern and the search string. Regular expressions use the backslash character (``'\'``) to indicate special forms or to allow special characters to be used without invoking @@ -212,12 +216,12 @@ group; ``(?P...)`` is the only exception to this rule. Following are the currently supported extensions. -``(?iLmsux)`` - (One or more letters from the set ``'i'``, ``'L'``, ``'m'``, ``'s'``, - ``'u'``, ``'x'``.) The group matches the empty string; the letters - set the corresponding flags: :const:`re.I` (ignore case), - :const:`re.L` (locale dependent), :const:`re.M` (multi-line), - :const:`re.S` (dot matches all), :const:`re.U` (Unicode dependent), +``(?aiLmsux)`` + (One or more letters from the set ``'a'``, ``'i'``, ``'L'``, ``'m'``, + ``'s'``, ``'u'``, ``'x'``.) The group matches the empty string; the + letters set the corresponding flags: :const:`re.a` (ASCII-only matching), + :const:`re.I` (ignore case), :const:`re.L` (locale dependent), + :const:`re.M` (multi-line), :const:`re.S` (dot matches all), and :const:`re.X` (verbose), for the entire regular expression. (The flags are described in :ref:`contents-of-module-re`.) This is useful if you wish to include the flags as part of the regular @@ -324,56 +328,62 @@ word is indicated by whitespace or a non-alphanumeric, non-underscore character. Note that ``\b`` is defined as the boundary between ``\w`` and ``\ W``, so the precise set of characters deemed to be alphanumeric depends on the values of the - ``UNICODE`` and ``LOCALE`` flags. Inside a character range, ``\b`` represents + ``ASCII`` and ``LOCALE`` flags. Inside a character range, ``\b`` represents the backspace character, for compatibility with Python's string literals. ``\B`` Matches the empty string, but only when it is *not* at the beginning or end of a word. This is just the opposite of ``\b``, so is also subject to the settings - of ``LOCALE`` and ``UNICODE``. + of ``ASCII`` and ``LOCALE`` . ``\d`` - When the :const:`UNICODE` flag is not specified, matches any decimal digit; this - is equivalent to the set ``[0-9]``. With :const:`UNICODE`, it will match - whatever is classified as a digit in the Unicode character properties database. + For Unicode (str) patterns: + When the :const:`ASCII` flag is specified, matches any decimal digit; this + is equivalent to the set ``[0-9]``. Otherwise, it will match whatever + is classified as a digit in the Unicode character properties database + (but this does include the standard ASCII digits and is thus a superset + of [0-9]). + For 8-bit (bytes) patterns: + Matches any decimal digit; this is equivalent to the set ``[0-9]``. ``\D`` - When the :const:`UNICODE` flag is not specified, matches any non-digit - character; this is equivalent to the set ``[^0-9]``. With :const:`UNICODE`, it - will match anything other than character marked as digits in the Unicode - character properties database. + Matches any character which is not a decimal digit. This is the + opposite of ``\d`` and is therefore similarly subject to the settings of + ``ASCII`` and ``LOCALE``. ``\s`` - When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, matches - any whitespace character; this is equivalent to the set ``[ \t\n\r\f\v]``. With - :const:`LOCALE`, it will match this set plus whatever characters are defined as - space for the current locale. If :const:`UNICODE` is set, this will match the - characters ``[ \t\n\r\f\v]`` plus whatever is classified as space in the Unicode - character properties database. + For Unicode (str) patterns: + When the :const:`ASCII` flag is specified, matches only ASCII whitespace + characters; this is equivalent to the set ``[ \t\n\r\f\v]``. Otherwise, + it will match this set whatever is classified as space in the Unicode + character properties database (including for example the non-breaking + spaces mandated by typography rules in many languages). + For 8-bit (bytes) patterns: + Matches characters considered whitespace in the ASCII character set; + this is equivalent to the set ``[ \t\n\r\f\v]``. ``\S`` - When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, matches - any non-whitespace character; this is equivalent to the set ``[^ \t\n\r\f\v]`` - With :const:`LOCALE`, it will match any character not in this set, and not - defined as space in the current locale. If :const:`UNICODE` is set, this will - match anything other than ``[ \t\n\r\f\v]`` and characters marked as space in - the Unicode character properties database. + Matches any character which is not a whitespace character. This is the + opposite of ``\s`` and is therefore similarly subject to the settings of + ``ASCII`` and ``LOCALE``. ``\w`` - When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, matches - any alphanumeric character and the underscore; this is equivalent to the set - ``[a-zA-Z0-9_]``. With :const:`LOCALE`, it will match the set ``[0-9_]`` plus - whatever characters are defined as alphanumeric for the current locale. If - :const:`UNICODE` is set, this will match the characters ``[0-9_]`` plus whatever - is classified as alphanumeric in the Unicode character properties database. + For Unicode (str) patterns: + When the :const:`ASCII` flag is specified, this is equivalent to the set + ``[a-zA-Z0-9_]``. Otherwise, it will match whatever is classified as + alphanumeric in the Unicode character properties database (it will + include most characters that can be part of a word in whatever language, + as well as numbers and the underscore sign). + For 8-bit (bytes) patterns: + Matches characters considered alphanumeric in the ASCII character set; + this is equivalent to the set ``[a-zA-Z0-9_]``. With :const:`LOCALE`, + it will additionally match whatever characters are defined as + alphanumeric for the current locale. ``\W`` - When the :const:`LOCALE` and :const:`UNICODE` flags are not specified, matches - any non-alphanumeric character; this is equivalent to the set ``[^a-zA-Z0-9_]``. - With :const:`LOCALE`, it will match any character not in the set ``[0-9_]``, and - not defined as alphanumeric for the current locale. If :const:`UNICODE` is set, - this will match anything other than ``[0-9_]`` and characters marked as - alphanumeric in the Unicode character properties database. + Matches any character which is not an alphanumeric character. This is the + opposite of ``\w`` and is therefore similarly subject to the settings of + ``ASCII`` and ``LOCALE``. ``\Z`` Matches only at the end of the string. @@ -454,6 +464,25 @@ expression at a time needn't worry about compiling regular expressions.) +.. data:: A + ASCII + + Make ``\w``, ``\W``, ``\b``, ``\B``, ``\s`` and ``\S`` perform ASCII-only + matching instead of full Unicode matching. This is only meaningful for + Unicode patterns, and is ignored for byte patterns. + + Note that the :const:`re.U` flag still exists (as well as its synonym + :const:`re.UNICODE` and its embedded counterpart ``(?u)``), but it has + become useless in Python 3.0. + In previous Python versions, it was used to specify that + matching had to be Unicode dependent (the default was ASCII matching in + all circumstances). Starting from Python 3.0, the default is Unicode + matching for Unicode strings (which can be changed by specifying the + ``'a'`` flag), and ASCII matching for 8-bit strings. Further, Unicode + dependent matching for 8-bit strings isn't allowed anymore and results + in a ValueError. + + .. data:: I IGNORECASE @@ -465,7 +494,10 @@ LOCALE Make ``\w``, ``\W``, ``\b``, ``\B``, ``\s`` and ``\S`` dependent on the - current locale. + current locale. The use of this flag is discouraged as the locale mechanism + is very unreliable, and it only handles one "culture" at a time anyway; + you should use Unicode matching instead, which is the default in Python 3.0 + for Unicode (str) patterns. .. data:: M @@ -486,13 +518,6 @@ newline; without this flag, ``'.'`` will match anything *except* a newline. -.. data:: U - UNICODE - - Make ``\w``, ``\W``, ``\b``, ``\B``, ``\d``, ``\D``, ``\s`` and ``\S`` dependent - on the Unicode character properties database. - - .. data:: X VERBOSE @@ -511,6 +536,8 @@ b = re.compile(r"\d+\.\d*") + + .. function:: search(pattern, string[, flags]) Scan through *string* looking for a location where the regular expression Modified: python/branches/py3k/Lib/_strptime.py ============================================================================== --- python/branches/py3k/Lib/_strptime.py (original) +++ python/branches/py3k/Lib/_strptime.py Tue Aug 19 19:56:33 2008 @@ -14,7 +14,7 @@ import locale import calendar from re import compile as re_compile -from re import IGNORECASE +from re import IGNORECASE, ASCII from re import escape as re_escape from datetime import date as datetime_date try: @@ -262,7 +262,7 @@ def compile(self, format): """Return a compiled re object for the format string.""" - return re_compile(self.pattern(format), IGNORECASE) + return re_compile(self.pattern(format), IGNORECASE | ASCII) _cache_lock = _thread_allocate_lock() # DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock Modified: python/branches/py3k/Lib/base64.py ============================================================================== --- python/branches/py3k/Lib/base64.py (original) +++ python/branches/py3k/Lib/base64.py Tue Aug 19 19:56:33 2008 @@ -39,7 +39,7 @@ return s.translate(translation) - + # Base64 encoding/decoding uses binascii def b64encode(s, altchars=None): @@ -126,7 +126,7 @@ return b64decode(s, b'-_') - + # Base32 encoding/decoding must be done in Python _b32alphabet = { 0: b'A', 9: b'J', 18: b'S', 27: b'3', @@ -225,7 +225,7 @@ # characters because this will tell us how many null bytes to remove from # the end of the decoded string. padchars = 0 - mo = re.search('(?P[=]*)$', s) + mo = re.search(b'(?P[=]*)$', s) if mo: padchars = len(mo.group('pad')) if padchars > 0: @@ -262,7 +262,7 @@ return b''.join(parts) - + # RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns # lowercase. The RFC also recommends against accepting input case # insensitively. @@ -291,12 +291,12 @@ raise TypeError("expected bytes, not %s" % s.__class__.__name__) if casefold: s = s.upper() - if re.search('[^0-9A-F]', s): + if re.search(b'[^0-9A-F]', s): raise binascii.Error('Non-base16 digit found') return binascii.unhexlify(s) - + # Legacy interface. This code could be cleaned up since I don't believe # binascii has any line length limitations. It just doesn't seem worth it # though. The files should be opened in binary mode. @@ -353,7 +353,7 @@ return binascii.a2b_base64(s) - + # Usable as a script... def main(): """Small main program""" Modified: python/branches/py3k/Lib/decimal.py ============================================================================== --- python/branches/py3k/Lib/decimal.py (original) +++ python/branches/py3k/Lib/decimal.py Tue Aug 19 19:56:33 2008 @@ -5415,7 +5415,7 @@ # 2. For finite numbers (not infinities and NaNs) the body of the # number between the optional sign and the optional exponent must have # at least one decimal digit, possibly after the decimal point. The -# lookahead expression '(?=\d|\.\d)' checks this. +# lookahead expression '(?=[0-9]|\.[0-9])' checks this. # # As the flag UNICODE is not enabled here, we're explicitly avoiding any # other meaning for \d than the numbers [0-9]. Modified: python/branches/py3k/Lib/distutils/cygwinccompiler.py ============================================================================== --- python/branches/py3k/Lib/distutils/cygwinccompiler.py (original) +++ python/branches/py3k/Lib/distutils/cygwinccompiler.py Tue Aug 19 19:56:33 2008 @@ -409,7 +409,7 @@ out = os.popen(gcc_exe + ' -dumpversion','r') out_string = out.read() out.close() - result = re.search('(\d+\.\d+(\.\d+)*)',out_string) + result = re.search('(\d+\.\d+(\.\d+)*)', out_string, re.ASCII) if result: gcc_version = StrictVersion(result.group(1)) else: @@ -421,7 +421,7 @@ out = os.popen(ld_exe + ' -v','r') out_string = out.read() out.close() - result = re.search('(\d+\.\d+(\.\d+)*)',out_string) + result = re.search('(\d+\.\d+(\.\d+)*)', out_string, re.ASCII) if result: ld_version = StrictVersion(result.group(1)) else: @@ -433,7 +433,7 @@ out = os.popen(dllwrap_exe + ' --version','r') out_string = out.read() out.close() - result = re.search(' (\d+\.\d+(\.\d+)*)',out_string) + result = re.search(' (\d+\.\d+(\.\d+)*)', out_string, re.ASCII) if result: dllwrap_version = StrictVersion(result.group(1)) else: Modified: python/branches/py3k/Lib/distutils/emxccompiler.py ============================================================================== --- python/branches/py3k/Lib/distutils/emxccompiler.py (original) +++ python/branches/py3k/Lib/distutils/emxccompiler.py Tue Aug 19 19:56:33 2008 @@ -300,7 +300,7 @@ out = os.popen(gcc_exe + ' -dumpversion','r') out_string = out.read() out.close() - result = re.search('(\d+\.\d+\.\d+)',out_string) + result = re.search('(\d+\.\d+\.\d+)', out_string, re.ASCII) if result: gcc_version = StrictVersion(result.group(1)) else: Modified: python/branches/py3k/Lib/distutils/sysconfig.py ============================================================================== --- python/branches/py3k/Lib/distutils/sysconfig.py (original) +++ python/branches/py3k/Lib/distutils/sysconfig.py Tue Aug 19 19:56:33 2008 @@ -512,7 +512,7 @@ # patched up as well. 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): flags = _config_vars[key] - flags = re.sub('-arch\s+\w+\s', ' ', flags) + flags = re.sub('-arch\s+\w+\s', ' ', flags, re.ASCII) flags = re.sub('-isysroot [^ \t]*', ' ', flags) _config_vars[key] = flags Modified: python/branches/py3k/Lib/distutils/util.py ============================================================================== --- python/branches/py3k/Lib/distutils/util.py (original) +++ python/branches/py3k/Lib/distutils/util.py Tue Aug 19 19:56:33 2008 @@ -81,7 +81,7 @@ return "%s-%s.%s" % (osname, version, release) elif osname[:6] == "cygwin": osname = "cygwin" - rel_re = re.compile (r'[\d.]+') + rel_re = re.compile (r'[\d.]+', re.ASCII) m = rel_re.match(release) if m: release = m.group() Modified: python/branches/py3k/Lib/distutils/version.py ============================================================================== --- python/branches/py3k/Lib/distutils/version.py (original) +++ python/branches/py3k/Lib/distutils/version.py Tue Aug 19 19:56:33 2008 @@ -134,7 +134,7 @@ """ version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', - re.VERBOSE) + re.VERBOSE | re.ASCII) def parse (self, vstring): Modified: python/branches/py3k/Lib/distutils/versionpredicate.py ============================================================================== --- python/branches/py3k/Lib/distutils/versionpredicate.py (original) +++ python/branches/py3k/Lib/distutils/versionpredicate.py Tue Aug 19 19:56:33 2008 @@ -5,7 +5,8 @@ import operator -re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)") +re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)", + re.ASCII) # (package) (rest) re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses @@ -153,7 +154,8 @@ global _provision_rx if _provision_rx is None: _provision_rx = re.compile( - "([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$") + "([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$", + re.ASCII) value = value.strip() m = _provision_rx.match(value) if not m: Modified: python/branches/py3k/Lib/email/quoprimime.py ============================================================================== --- python/branches/py3k/Lib/email/quoprimime.py (original) +++ python/branches/py3k/Lib/email/quoprimime.py Tue Aug 19 19:56:33 2008 @@ -70,7 +70,7 @@ _QUOPRI_BODY_MAP[c] = chr(c) - + # Helpers def header_check(octet): """Return True if the octet should be escaped with header quopri.""" @@ -125,7 +125,7 @@ return '=%02X' % ord(c) - + def header_encode(header_bytes, charset='iso-8859-1'): """Encode a single header line with quoted-printable (like) encoding. @@ -149,7 +149,7 @@ return '=?%s?q?%s?=' % (charset, EMPTYSTRING.join(encoded)) - + def body_encode(body, maxlinelen=76, eol=NL): """Encode with quoted-printable, wrapping at maxlinelen characters. @@ -225,7 +225,7 @@ return encoded_body - + # BAW: I'm not sure if the intent was for the signature of this function to be # the same as base64MIME.decode() or not... def decode(encoded, eol=NL): @@ -280,7 +280,7 @@ decodestring = decode - + def _unquote_match(match): """Turn a match in the form =AB to the ASCII character with value 0xab""" s = match.group(0) @@ -296,4 +296,4 @@ the high level email.Header class for that functionality. """ s = s.replace('_', ' ') - return re.sub(r'=\w{2}', _unquote_match, s) + return re.sub(r'=\w{2}', _unquote_match, s, re.ASCII) Modified: python/branches/py3k/Lib/email/utils.py ============================================================================== --- python/branches/py3k/Lib/email/utils.py (original) +++ python/branches/py3k/Lib/email/utils.py Tue Aug 19 19:56:33 2008 @@ -52,7 +52,7 @@ escapesre = re.compile(r'[][\\()"]') - + # Helpers def formataddr(pair): @@ -73,7 +73,7 @@ return address - + def getaddresses(fieldvalues): """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" all = COMMASPACE.join(fieldvalues) @@ -81,7 +81,7 @@ return a.addresslist - + ecre = re.compile(r''' =\? # literal =? (?P[^?]*?) # non-greedy up to the next ? is the charset @@ -93,7 +93,7 @@ ''', re.VERBOSE | re.IGNORECASE) - + def formatdate(timeval=None, localtime=False, usegmt=False): """Returns a date string as specified by RFC 2822, e.g.: @@ -146,7 +146,7 @@ zone) - + def make_msgid(idstring=None): """Returns a string suitable for RFC 2822 compliant Message-ID, e.g: @@ -168,7 +168,7 @@ return msgid - + # These functions are in the standalone mimelib version only because they've # subsequently been fixed in the latest Python versions. We use this to worm # around broken older Pythons. @@ -202,7 +202,7 @@ return str - + # RFC2231-related functions - parameter encoding and decoding def decode_rfc2231(s): """Decode string according to RFC 2231""" @@ -227,7 +227,8 @@ return "%s'%s'%s" % (charset, language, s) -rfc2231_continuation = re.compile(r'^(?P\w+)\*((?P[0-9]+)\*?)?$') +rfc2231_continuation = re.compile(r'^(?P\w+)\*((?P[0-9]+)\*?)?$', + re.ASCII) def decode_params(params): """Decode parameters list according to RFC 2231. Modified: python/branches/py3k/Lib/encodings/idna.py ============================================================================== --- python/branches/py3k/Lib/encodings/idna.py (original) +++ python/branches/py3k/Lib/encodings/idna.py Tue Aug 19 19:56:33 2008 @@ -176,12 +176,10 @@ return "", 0 # IDNA allows decoding to operate on Unicode strings, too. - if isinstance(input, bytes): - labels = dots.split(input) - else: - # Force to bytes + if not isinstance(input, bytes): + # XXX obviously wrong, see #3232 input = bytes(input) - labels = input.split(b".") + labels = input.split(b".") if labels and len(labels[-1]) == 0: trailing_dot = '.' Modified: python/branches/py3k/Lib/ftplib.py ============================================================================== --- python/branches/py3k/Lib/ftplib.py (original) +++ python/branches/py3k/Lib/ftplib.py Tue Aug 19 19:56:33 2008 @@ -590,7 +590,8 @@ global _150_re if _150_re is None: import re - _150_re = re.compile("150 .* \((\d+) bytes\)", re.IGNORECASE) + _150_re = re.compile( + "150 .* \((\d+) bytes\)", re.IGNORECASE | re.ASCII) m = _150_re.match(resp) if not m: return None @@ -613,7 +614,7 @@ global _227_re if _227_re is None: import re - _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)') + _227_re = re.compile(r'(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)', re.ASCII) m = _227_re.search(resp) if not m: raise error_proto(resp) Modified: python/branches/py3k/Lib/html/parser.py ============================================================================== --- python/branches/py3k/Lib/html/parser.py (original) +++ python/branches/py3k/Lib/html/parser.py Tue Aug 19 19:56:33 2008 @@ -385,4 +385,4 @@ return '&'+s+';' return re.sub(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));", - replaceEntities, s) + replaceEntities, s, re.ASCII) Modified: python/branches/py3k/Lib/http/cookiejar.py ============================================================================== --- python/branches/py3k/Lib/http/cookiejar.py (original) +++ python/branches/py3k/Lib/http/cookiejar.py Tue Aug 19 19:56:33 2008 @@ -121,7 +121,7 @@ UTC_ZONES = {"GMT": None, "UTC": None, "UT": None, "Z": None} -TIMEZONE_RE = re.compile(r"^([-+])?(\d\d?):?(\d\d)?$") +TIMEZONE_RE = re.compile(r"^([-+])?(\d\d?):?(\d\d)?$", re.ASCII) def offset_from_tz_string(tz): offset = None if tz in UTC_ZONES: @@ -191,9 +191,9 @@ STRICT_DATE_RE = re.compile( r"^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) " - "(\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$") + "(\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$", re.ASCII) WEEKDAY_RE = re.compile( - r"^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*", re.I) + r"^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*", re.I | re.ASCII) LOOSE_HTTP_DATE_RE = re.compile( r"""^ (\d\d?) # day @@ -210,7 +210,7 @@ ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone \s* (?:\(\w+\))? # ASCII representation of timezone in parens. - \s*$""", re.X) + \s*$""", re.X | re.ASCII) def http2time(text): """Returns time in seconds since epoch of time represented by a string. @@ -282,7 +282,7 @@ \s* ([-+]?\d\d?:?(:?\d\d)? |Z|z)? # timezone (Z is "zero meridian", i.e. GMT) - \s*$""", re.X) + \s*$""", re.X | re. ASCII) def iso2time(text): """ As for http2time, but parses the ISO 8601 formats: @@ -489,7 +489,7 @@ return result -IPV4_RE = re.compile(r"\.\d+$") +IPV4_RE = re.compile(r"\.\d+$", re.ASCII) def is_HDN(text): """Return True if text is a host domain name.""" # XXX @@ -574,7 +574,7 @@ return True return False -cut_port_re = re.compile(r":\d+$") +cut_port_re = re.compile(r":\d+$", re.ASCII) def request_host(request): """Return request-host, as defined by RFC 2965. @@ -1207,7 +1207,7 @@ domain_re = re.compile(r"[^.]*") dots_re = re.compile(r"^\.+") - magic_re = r"^\#LWP-Cookies-(\d+\.\d+)" + magic_re = re.compile(r"^\#LWP-Cookies-(\d+\.\d+)", re.ASCII) def __init__(self, policy=None): if policy is None: @@ -1856,7 +1856,7 @@ def _really_load(self, f, filename, ignore_discard, ignore_expires): magic = f.readline() - if not re.search(self.magic_re, magic): + if not self.magic_re.search(magic): msg = ("%r does not look like a Set-Cookie3 (LWP) format " "file" % filename) raise LoadError(msg) @@ -1965,7 +1965,7 @@ header by default (Mozilla can cope with that). """ - magic_re = "#( Netscape)? HTTP Cookie File" + magic_re = re.compile("#( Netscape)? HTTP Cookie File") header = """\ # Netscape HTTP Cookie File # http://www.netscape.com/newsref/std/cookie_spec.html @@ -1977,7 +1977,7 @@ now = time.time() magic = f.readline() - if not re.search(self.magic_re, magic): + if not self.magic_re.search(magic): f.close() raise LoadError( "%r does not look like a Netscape format cookies file" % Modified: python/branches/py3k/Lib/http/cookies.py ============================================================================== --- python/branches/py3k/Lib/http/cookies.py (original) +++ python/branches/py3k/Lib/http/cookies.py Tue Aug 19 19:56:33 2008 @@ -445,7 +445,7 @@ ""+ _LegalCharsPatt +"*" # Any word or empty string r")" # End of group 'val' r"\s*;?" # Probably ending in a semi-colon - ) + , re.ASCII) # May be removed if safe. # At long last, here is the cookie class. Modified: python/branches/py3k/Lib/imaplib.py ============================================================================== --- python/branches/py3k/Lib/imaplib.py (original) +++ python/branches/py3k/Lib/imaplib.py Tue Aug 19 19:56:33 2008 @@ -88,11 +88,12 @@ r' (?P[0-9][0-9]):(?P[0-9][0-9]):(?P[0-9][0-9])' r' (?P[-+])(?P[0-9][0-9])(?P[0-9][0-9])' r'"') -Literal = re.compile(r'.*{(?P\d+)}$') +Literal = re.compile(r'.*{(?P\d+)}$', re.ASCII) MapCRLF = re.compile(r'\r\n|\r|\n') Response_code = re.compile(r'\[(?P[A-Z-]+)( (?P[^\]]*))?\]') Untagged_response = re.compile(r'\* (?P[A-Z-]+)( (?P.*))?') -Untagged_status = re.compile(r'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?') +Untagged_status = re.compile( + r'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?', re.ASCII) @@ -146,7 +147,7 @@ class abort(error): pass # Service errors - close and retry class readonly(abort): pass # Mailbox status changed to READ-ONLY - mustquote = re.compile(r"[^\w!#$%&'*+,.:;<=>?^`|~-]") + mustquote = re.compile(r"[^\w!#$%&'*+,.:;<=>?^`|~-]", re.ASCII) def __init__(self, host = '', port = IMAP4_PORT): self.debug = Debug @@ -168,7 +169,7 @@ self.tagpre = Int2AP(random.randint(4096, 65535)) self.tagre = re.compile(r'(?P' + self.tagpre - + r'\d+) (?P[A-Z]+) (?P.*)') + + r'\d+) (?P[A-Z]+) (?P.*)', re.ASCII) # Get server welcome message, # request and store CAPABILITY response. Modified: python/branches/py3k/Lib/json/decoder.py ============================================================================== --- python/branches/py3k/Lib/json/decoder.py (original) +++ python/branches/py3k/Lib/json/decoder.py Tue Aug 19 19:56:33 2008 @@ -67,7 +67,7 @@ fn = getattr(context, 'parse_int', None) or int res = fn(integer) return res, None -pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber) +pattern(r'(-?(?:0|[1-9][0-9]*))(\.[0-9]+)?([eE][-+]?[0-9]+)?')(JSONNumber) STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) Modified: python/branches/py3k/Lib/logging/handlers.py ============================================================================== --- python/branches/py3k/Lib/logging/handlers.py (original) +++ python/branches/py3k/Lib/logging/handlers.py Tue Aug 19 19:56:33 2008 @@ -199,7 +199,7 @@ else: raise ValueError("Invalid rollover interval specified: %s" % self.when) - self.extMatch = re.compile(self.extMatch) + self.extMatch = re.compile(self.extMatch, re.ASCII) self.interval = self.interval * interval # multiply by units requested self.rolloverAt = currentTime + self.interval Modified: python/branches/py3k/Lib/platform.py ============================================================================== --- python/branches/py3k/Lib/platform.py (original) +++ python/branches/py3k/Lib/platform.py Tue Aug 19 19:56:33 2008 @@ -118,7 +118,7 @@ '|' '(GLIBC_([0-9.]+))' '|' - '(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)') + '(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)', re.ASCII) def libc_ver(executable=sys.executable,lib='',version='', @@ -223,15 +223,15 @@ return distname,version,id -_release_filename = re.compile(r'(\w+)[-_](release|version)') +_release_filename = re.compile(r'(\w+)[-_](release|version)', re.ASCII) _lsb_release_version = re.compile(r'(.+)' ' release ' '([\d.]+)' - '[^(]*(?:\((.+)\))?') + '[^(]*(?:\((.+)\))?', re.ASCII) _release_version = re.compile(r'([^0-9]+)' '(?: release )?' '([\d.]+)' - '[^(]*(?:\((.+)\))?') + '[^(]*(?:\((.+)\))?', re.ASCII) # See also http://www.novell.com/coolsolutions/feature/11251.html # and http://linuxmafia.com/faq/Admin/release-files.html @@ -464,7 +464,7 @@ _ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) ' '.*' - 'Version ([\d.]+))') + 'Version ([\d.]+))', re.ASCII) def _syscmd_ver(system='', release='', version='', @@ -1253,16 +1253,16 @@ _sys_version_parser = re.compile( r'([\w.+]+)\s*' '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*' - '\[([^\]]+)\]?') + '\[([^\]]+)\]?', re.ASCII) _jython_sys_version_parser = re.compile( - r'([\d\.]+)') + r'([\d\.]+)', re.ASCII) _ironpython_sys_version_parser = re.compile( r'IronPython\s*' '([\d\.]+)' '(?: \(([\d\.]+)\))?' - ' on (.NET [\d\.]+)') + ' on (.NET [\d\.]+)', re.ASCII) _sys_version_cache = {} Modified: python/branches/py3k/Lib/plistlib.py ============================================================================== --- python/branches/py3k/Lib/plistlib.py (original) +++ python/branches/py3k/Lib/plistlib.py Tue Aug 19 19:56:33 2008 @@ -147,7 +147,7 @@ # Contents should conform to a subset of ISO 8601 # (in particular, YYYY '-' MM '-' DD 'T' HH ':' MM ':' SS 'Z'. Smaller units may be omitted with # a loss of precision) -_dateParser = re.compile(r"(?P\d\d\d\d)(?:-(?P\d\d)(?:-(?P\d\d)(?:T(?P\d\d)(?::(?P\d\d)(?::(?P\d\d))?)?)?)?)?Z") +_dateParser = re.compile(r"(?P\d\d\d\d)(?:-(?P\d\d)(?:-(?P\d\d)(?:T(?P\d\d)(?::(?P\d\d)(?::(?P\d\d))?)?)?)?)?Z", re.ASCII) def _dateFromString(s): order = ('year', 'month', 'day', 'hour', 'minute', 'second') Modified: python/branches/py3k/Lib/posixpath.py ============================================================================== --- python/branches/py3k/Lib/posixpath.py (original) +++ python/branches/py3k/Lib/posixpath.py Tue Aug 19 19:56:33 2008 @@ -241,7 +241,7 @@ return path if not _varprog: import re - _varprog = re.compile(r'\$(\w+|\{[^}]*\})') + _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII) i = 0 while True: m = _varprog.search(path, i) Modified: python/branches/py3k/Lib/py_compile.py ============================================================================== --- python/branches/py3k/Lib/py_compile.py (original) +++ python/branches/py3k/Lib/py_compile.py Tue Aug 19 19:56:33 2008 @@ -86,7 +86,7 @@ line = f.readline() if not line: break - m = re.match(r".*\bcoding:\s*(\S+)\b", line) + m = re.match(br".*\bcoding:\s*(\S+)\b", line) if m: return m.group(1).decode("ascii") return default Modified: python/branches/py3k/Lib/re.py ============================================================================== --- python/branches/py3k/Lib/re.py (original) +++ python/branches/py3k/Lib/re.py Tue Aug 19 19:56:33 2008 @@ -44,7 +44,7 @@ "|" A|B, creates an RE that will match either A or B. (...) Matches the RE inside the parentheses. The contents can be retrieved or matched later in the string. - (?iLmsux) Set the I, L, M, S, U, or X flag for the RE (see below). + (?aiLmsux) Set the A, I, L, M, S, U, or X flag for the RE (see below). (?:...) Non-grouping version of regular parentheses. (?P...) The substring matched by the group is accessible by name. (?P=name) Matches the text matched earlier by the group named name. @@ -64,11 +64,18 @@ \Z Matches only at the end of the string. \b Matches the empty string, but only at the start or end of a word. \B Matches the empty string, but not at the start or end of a word. - \d Matches any decimal digit; equivalent to the set [0-9]. - \D Matches any non-digit character; equivalent to the set [^0-9]. + \d Matches any decimal digit; equivalent to the set [0-9] in + bytes patterns or string patterns with the ASCII flag. + In string patterns without the ASCII flag, it will match the whole + range of Unicode digits. + \D Matches any non-digit character; equivalent to [^\d]. \s Matches any whitespace character; equivalent to [ \t\n\r\f\v]. \S Matches any non-whitespace character; equiv. to [^ \t\n\r\f\v]. - \w Matches any alphanumeric character; equivalent to [a-zA-Z0-9_]. + \w Matches any alphanumeric character; equivalent to [a-zA-Z0-9_] + in bytes patterns or string patterns with the ASCII flag. + In string patterns without the ASCII flag, it will match the + range of Unicode alphanumeric characters (letters plus digits + plus underscore). With LOCALE, it will match the set [0-9_] plus characters defined as letters for the current locale. \W Matches the complement of \w. @@ -87,6 +94,12 @@ escape Backslash all non-alphanumerics in a string. Some of the functions in this module takes flags as optional parameters: + A ASCII For string patterns, make \w, \W, \b, \B, \d, \D + match the corresponding ASCII character categories + (rather than the whole Unicode categories, which is the + default). + For bytes patterns, this flag is the only available + behaviour and needn't be specified. I IGNORECASE Perform case-insensitive matching. L LOCALE Make \w, \W, \b, \B, dependent on the current locale. M MULTILINE "^" matches the beginning of lines (after a newline) @@ -95,7 +108,8 @@ as the end of the string. S DOTALL "." matches any character at all, including the newline. X VERBOSE Ignore whitespace and comments for nicer looking RE's. - U UNICODE Make \w, \W, \b, \B, dependent on the Unicode locale. + U UNICODE For compatibility only. Ignored for string patterns (it + is the default), and forbidden for bytes patterns. This module also defines an exception 'error'. @@ -107,16 +121,17 @@ # public symbols __all__ = [ "match", "search", "sub", "subn", "split", "findall", - "compile", "purge", "template", "escape", "I", "L", "M", "S", "X", - "U", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE", + "compile", "purge", "template", "escape", "A", "I", "L", "M", "S", "X", + "U", "ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE", "UNICODE", "error" ] __version__ = "2.2.1" # flags +A = ASCII = sre_compile.SRE_FLAG_ASCII # assume ascii "locale" I = IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE # ignore case L = LOCALE = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale -U = UNICODE = sre_compile.SRE_FLAG_UNICODE # assume unicode locale +U = UNICODE = sre_compile.SRE_FLAG_UNICODE # assume unicode "locale" M = MULTILINE = sre_compile.SRE_FLAG_MULTILINE # make anchors look for newline S = DOTALL = sre_compile.SRE_FLAG_DOTALL # make dot match newline X = VERBOSE = sre_compile.SRE_FLAG_VERBOSE # ignore whitespace and comments Modified: python/branches/py3k/Lib/sre_constants.py ============================================================================== --- python/branches/py3k/Lib/sre_constants.py (original) +++ python/branches/py3k/Lib/sre_constants.py Tue Aug 19 19:56:33 2008 @@ -207,9 +207,10 @@ SRE_FLAG_LOCALE = 4 # honour system locale SRE_FLAG_MULTILINE = 8 # treat target as multiline string SRE_FLAG_DOTALL = 16 # treat target as a single string -SRE_FLAG_UNICODE = 32 # use unicode locale +SRE_FLAG_UNICODE = 32 # use unicode "locale" SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments SRE_FLAG_DEBUG = 128 # debugging +SRE_FLAG_ASCII = 256 # use ascii "locale" # flags for INFO primitive SRE_INFO_PREFIX = 1 # has prefix Modified: python/branches/py3k/Lib/sre_parse.py ============================================================================== --- python/branches/py3k/Lib/sre_parse.py (original) +++ python/branches/py3k/Lib/sre_parse.py Tue Aug 19 19:56:33 2008 @@ -64,6 +64,7 @@ "s": SRE_FLAG_DOTALL, "x": SRE_FLAG_VERBOSE, # extensions + "a": SRE_FLAG_ASCII, "t": SRE_FLAG_TEMPLATE, "u": SRE_FLAG_UNICODE, } @@ -672,6 +673,18 @@ return subpattern +def fix_flags(src, flags): + # Check and fix flags according to the type of pattern (str or bytes) + if isinstance(src, str): + if not flags & SRE_FLAG_ASCII: + flags |= SRE_FLAG_UNICODE + elif flags & SRE_FLAG_UNICODE: + raise ValueError("ASCII and UNICODE flags are incompatible") + else: + if flags & SRE_FLAG_UNICODE: + raise ValueError("can't use UNICODE flag with a bytes pattern") + return flags + def parse(str, flags=0, pattern=None): # parse 're' pattern into list of (opcode, argument) tuples @@ -683,6 +696,7 @@ pattern.str = str p = _parse_sub(source, pattern, 0) + p.pattern.flags = fix_flags(str, p.pattern.flags) tail = source.get() if tail == ")": Modified: python/branches/py3k/Lib/tarfile.py ============================================================================== --- python/branches/py3k/Lib/tarfile.py (original) +++ python/branches/py3k/Lib/tarfile.py Tue Aug 19 19:56:33 2008 @@ -1368,7 +1368,7 @@ # "%d %s=%s\n" % (length, keyword, value). length is the size # of the complete record including the length field itself and # the newline. keyword and value are both UTF-8 encoded strings. - regex = re.compile(r"(\d+) ([^=]+)=", re.U) + regex = re.compile(br"(\d+) ([^=]+)=") pos = 0 while True: match = regex.match(buf, pos) Modified: python/branches/py3k/Lib/test/re_tests.py ============================================================================== --- python/branches/py3k/Lib/test/re_tests.py (original) +++ python/branches/py3k/Lib/test/re_tests.py Tue Aug 19 19:56:33 2008 @@ -667,4 +667,4 @@ (r'\b.\b', 'a', SUCCEED, 'found', 'a'), (r'(?u)\b.\b', u, SUCCEED, 'found', u), (r'(?u)\w', u, SUCCEED, 'found', u), - ]) +]) Modified: python/branches/py3k/Lib/test/test_bytes.py ============================================================================== --- python/branches/py3k/Lib/test/test_bytes.py (original) +++ python/branches/py3k/Lib/test/test_bytes.py Tue Aug 19 19:56:33 2008 @@ -506,7 +506,7 @@ def by(s): return bytearray(map(ord, s)) b = by("Hello, world") - self.assertEqual(re.findall(r"\w+", b), [by("Hello"), by("world")]) + self.assertEqual(re.findall(br"\w+", b), [by("Hello"), by("world")]) def test_setitem(self): b = bytearray([1, 2, 3]) Modified: python/branches/py3k/Lib/test/test_mmap.py ============================================================================== --- python/branches/py3k/Lib/test/test_mmap.py (original) +++ python/branches/py3k/Lib/test/test_mmap.py Tue Aug 19 19:56:33 2008 @@ -54,7 +54,7 @@ m.flush() # Test doing a regular expression match in an mmap'ed file - match = re.search('[A-Za-z]+', m) + match = re.search(b'[A-Za-z]+', m) if match is None: self.fail('regex match on mmap failed!') else: Modified: python/branches/py3k/Lib/test/test_re.py ============================================================================== --- python/branches/py3k/Lib/test/test_re.py (original) +++ python/branches/py3k/Lib/test/test_re.py Tue Aug 19 19:56:33 2008 @@ -83,23 +83,6 @@ self.assertEqual(re.sub('\r\n', '\n', 'abc\r\ndef\r\n'), 'abc\ndef\n') - def test_bug_1140(self): - # re.sub(x, y, b'') should return b'', not '', and - # re.sub(x, y, '') should return '', not b''. - # Also: - # re.sub(x, y, str(x)) should return str(y), and - # re.sub(x, y, bytes(x)) should return - # str(y) if isinstance(y, str) else unicode(y). - for x in 'x', b'x': - for y in 'y', b'y': - z = re.sub(x, y, b'') - self.assertEqual(z, b'') - self.assertEqual(type(z), bytes) - # - z = re.sub(x, y, '') - self.assertEqual(z, '') - self.assertEqual(type(z), str) - def test_bug_1661(self): # Verify that flags do not get silently ignored with compiled patterns pattern = re.compile('.') @@ -327,7 +310,7 @@ def test_getattr(self): self.assertEqual(re.compile("(?i)(a)(b)").pattern, "(?i)(a)(b)") - self.assertEqual(re.compile("(?i)(a)(b)").flags, re.I) + self.assertEqual(re.compile("(?i)(a)(b)").flags, re.I | re.U) self.assertEqual(re.compile("(?i)(a)(b)").groups, 2) self.assertEqual(re.compile("(?i)(a)(b)").groupindex, {}) self.assertEqual(re.compile("(?i)(?Pa)(?Pb)").groupindex, @@ -614,8 +597,8 @@ import array for typecode in 'bBuhHiIlLfd': a = array.array(typecode) - self.assertEqual(re.compile("bla").match(a), None) - self.assertEqual(re.compile("").match(a).groups(), ()) + self.assertEqual(re.compile(b"bla").match(a), None) + self.assertEqual(re.compile(b"").match(a).groups(), ()) def test_inline_flags(self): # Bug #1700 @@ -658,6 +641,48 @@ self.assertEqual(pattern.sub('#', 'a\nb\nc'), 'a#\nb#\nc#') self.assertEqual(pattern.sub('#', '\n'), '#\n#') + def test_bytes_str_mixing(self): + # Mixing str and bytes is disallowed + pat = re.compile('.') + bpat = re.compile(b'.') + self.assertRaises(TypeError, pat.match, b'b') + self.assertRaises(TypeError, bpat.match, 'b') + self.assertRaises(TypeError, pat.sub, b'b', 'c') + self.assertRaises(TypeError, pat.sub, 'b', b'c') + self.assertRaises(TypeError, pat.sub, b'b', b'c') + self.assertRaises(TypeError, bpat.sub, b'b', 'c') + self.assertRaises(TypeError, bpat.sub, 'b', b'c') + self.assertRaises(TypeError, bpat.sub, 'b', 'c') + + def test_ascii_and_unicode_flag(self): + # String patterns + for flags in (0, re.UNICODE): + pat = re.compile('\xc0', flags | re.IGNORECASE) + self.assertNotEqual(pat.match('\xe0'), None) + pat = re.compile('\w', flags) + self.assertNotEqual(pat.match('\xe0'), None) + pat = re.compile('\xc0', re.ASCII | re.IGNORECASE) + self.assertEqual(pat.match('\xe0'), None) + pat = re.compile('(?a)\xc0', re.IGNORECASE) + self.assertEqual(pat.match('\xe0'), None) + pat = re.compile('\w', re.ASCII) + self.assertEqual(pat.match('\xe0'), None) + pat = re.compile('(?a)\w') + self.assertEqual(pat.match('\xe0'), None) + # Bytes patterns + for flags in (0, re.ASCII): + pat = re.compile(b'\xc0', re.IGNORECASE) + self.assertEqual(pat.match(b'\xe0'), None) + pat = re.compile(b'\w') + self.assertEqual(pat.match(b'\xe0'), None) + # Incompatibilities + self.assertRaises(ValueError, re.compile, b'\w', re.UNICODE) + self.assertRaises(ValueError, re.compile, b'(?u)\w') + self.assertRaises(ValueError, re.compile, '\w', re.UNICODE | re.ASCII) + self.assertRaises(ValueError, re.compile, '(?u)\w', re.ASCII) + self.assertRaises(ValueError, re.compile, '(?a)\w', re.UNICODE) + self.assertRaises(ValueError, re.compile, '(?au)\w') + def run_re_tests(): from test.re_tests import benchmarks, tests, SUCCEED, FAIL, SYNTAX_ERROR Modified: python/branches/py3k/Lib/tokenize.py ============================================================================== --- python/branches/py3k/Lib/tokenize.py (original) +++ python/branches/py3k/Lib/tokenize.py Tue Aug 19 19:56:33 2008 @@ -47,21 +47,23 @@ def any(*choices): return group(*choices) + '*' def maybe(*choices): return group(*choices) + '?' +# Note: we use unicode matching for names ("\w") but ascii matching for +# number literals. Whitespace = r'[ \f\t]*' Comment = r'#[^\r\n]*' Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment) Name = r'[a-zA-Z_]\w*' -Hexnumber = r'0[xX][\da-fA-F]+' +Hexnumber = r'0[xX][0-9a-fA-F]+' Binnumber = r'0[bB][01]+' Octnumber = r'0[oO][0-7]+' -Decnumber = r'(?:0+|[1-9]\d*)' +Decnumber = r'(?:0+|[1-9][0-9]*)' Intnumber = group(Hexnumber, Binnumber, Octnumber, Decnumber) -Exponent = r'[eE][-+]?\d+' -Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent) -Expfloat = r'\d+' + Exponent +Exponent = r'[eE][-+]?[0-9]+' +Pointfloat = group(r'[0-9]+\.[0-9]*', r'\.[0-9]+') + maybe(Exponent) +Expfloat = r'[0-9]+' + Exponent Floatnumber = group(Pointfloat, Expfloat) -Imagnumber = group(r'\d+[jJ]', Floatnumber + r'[jJ]') +Imagnumber = group(r'[0-9]+[jJ]', Floatnumber + r'[jJ]') Number = group(Imagnumber, Floatnumber, Intnumber) # Tail end of ' string. Modified: python/branches/py3k/Lib/urllib/request.py ============================================================================== --- python/branches/py3k/Lib/urllib/request.py (original) +++ python/branches/py3k/Lib/urllib/request.py Tue Aug 19 19:56:33 2008 @@ -141,7 +141,7 @@ _opener = None # copied from cookielib.py -_cut_port_re = re.compile(r":\d+$") +_cut_port_re = re.compile(r":\d+$", re.ASCII) def request_host(request): """Return request-host, as defined by RFC 2965. Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Aug 19 19:56:33 2008 @@ -30,6 +30,14 @@ Library ------- +- Issue #2834: update the regular expression library to match the unicode + standards of py3k. In other words, mixing bytes and unicode strings + (be it as pattern, search string or replacement string) raises a TypeError. + Moreover, the re.UNICODE flag is enabled automatically for unicode patterns, + and can be disabled by specifying a new re.ASCII flag; as for bytes + patterns, ASCII matching is the only option and trying to specify re.UNICODE + for such patterns raises a ValueError. + - Issue #3300: make urllib.parse.[un]quote() default to UTF-8. Code contributed by Matt Giuca. quote() now encodes the input before quoting, unquote() decodes after unquoting. There are Modified: python/branches/py3k/Modules/_sre.c ============================================================================== --- python/branches/py3k/Modules/_sre.c (original) +++ python/branches/py3k/Modules/_sre.c Tue Aug 19 19:56:33 2008 @@ -1691,7 +1691,7 @@ /* get pointer to string buffer */ view.len = -1; buffer = Py_TYPE(string)->tp_as_buffer; - if (!buffer || !buffer->bf_getbuffer || + if (!buffer || !buffer->bf_getbuffer || (*buffer->bf_getbuffer)(string, &view, PyBUF_SIMPLE) < 0) { PyErr_SetString(PyExc_TypeError, "expected string or buffer"); return NULL; @@ -1717,7 +1717,7 @@ if (PyBytes_Check(string) || bytes == size) charsize = 1; #if defined(HAVE_UNICODE) - else if (bytes == (Py_ssize_t) (size * sizeof(Py_UNICODE))) + else if (bytes == (Py_ssize_t) (size * sizeof(Py_UNICODE))) charsize = sizeof(Py_UNICODE); #endif else { @@ -1729,7 +1729,7 @@ *p_charsize = charsize; if (ptr == NULL) { - PyErr_SetString(PyExc_ValueError, + PyErr_SetString(PyExc_ValueError, "Buffer is NULL"); } return ptr; @@ -1754,6 +1754,17 @@ if (!ptr) return NULL; + if (charsize == 1 && pattern->charsize > 1) { + PyErr_SetString(PyExc_TypeError, + "can't use a string pattern on a bytes-like object"); + return NULL; + } + if (charsize > 1 && pattern->charsize == 1) { + PyErr_SetString(PyExc_TypeError, + "can't use a bytes pattern on a string-like object"); + return NULL; + } + /* adjust boundaries */ if (start < 0) start = 0; @@ -2682,6 +2693,16 @@ return NULL; } + if (pattern == Py_None) + self->charsize = -1; + else { + Py_ssize_t p_length; + if (!getstring(pattern, &p_length, &self->charsize)) { + PyObject_DEL(self); + return NULL; + } + } + Py_INCREF(pattern); self->pattern = pattern; Modified: python/branches/py3k/Modules/sre.h ============================================================================== --- python/branches/py3k/Modules/sre.h (original) +++ python/branches/py3k/Modules/sre.h Tue Aug 19 19:56:33 2008 @@ -30,6 +30,7 @@ PyObject* pattern; /* pattern source (or None) */ int flags; /* flags used when compiling pattern source */ PyObject *weakreflist; /* List of weak references */ + int charsize; /* pattern charsize (or -1) */ /* pattern code */ Py_ssize_t codesize; SRE_CODE code[1]; From python-3000-checkins at python.org Tue Aug 19 20:22:14 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Tue, 19 Aug 2008 20:22:14 +0200 (CEST) Subject: [Python-3000-checkins] r65862 - in python/branches/py3k: Include/memoryobject.h Misc/NEWS Modules/_json.c Objects/memoryobject.c Objects/unicodeobject.c Message-ID: <20080819182214.8BB641E4006@bag.python.org> Author: antoine.pitrou Date: Tue Aug 19 20:22:14 2008 New Revision: 65862 Log: #3560: cleanup C memoryview API Modified: python/branches/py3k/Include/memoryobject.h python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_json.c python/branches/py3k/Objects/memoryobject.c python/branches/py3k/Objects/unicodeobject.c Modified: python/branches/py3k/Include/memoryobject.h ============================================================================== --- python/branches/py3k/Include/memoryobject.h (original) +++ python/branches/py3k/Include/memoryobject.h Tue Aug 19 20:22:14 2008 @@ -1,5 +1,4 @@ - -/* Memory object interface */ +/* Memory view object. In Python this is available as "memoryview". */ #ifndef Py_MEMORYOBJECT_H #define Py_MEMORYOBJECT_H @@ -7,19 +6,15 @@ extern "C" { #endif -typedef struct { - PyObject_HEAD - PyObject *base; - Py_buffer view; -} PyMemoryViewObject; - - PyAPI_DATA(PyTypeObject) PyMemoryView_Type; -#define PyMemory_Check(op) (Py_TYPE(op) == &PyMemoryView_Type) -#define PyMemoryView(op) (((PyMemoryViewObject *)(op))->view) +#define PyMemoryView_Check(op) (Py_TYPE(op) == &PyMemoryView_Type) + +/* Get a pointer to the underlying Py_buffer of a memoryview object. */ +#define PyMemoryView_GET_BUFFER(op) (&((PyMemoryViewObject *)(op))->view) +/* Get a pointer to the PyObject from which originates a memoryview object. */ +#define PyMemoryView_GET_BASE(op) (((PyMemoryViewObject *)(op))->view.obj) -#define Py_END_OF_MEMORY (-1) PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base, int buffertype, @@ -58,10 +53,21 @@ PyAPI_FUNC(PyObject *) PyMemoryView_FromObject(PyObject *base); -PyAPI_FUNC(PyObject *) PyMemoryView_FromMemory(Py_buffer *info); +PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(Py_buffer *info); /* create new if bufptr is NULL will be a new bytesobject in base */ + +/* The struct is declared here so that macros can work, but it shouldn't + be considered public. Don't access those fields directly, use the macros + and functions instead! */ +typedef struct { + PyObject_HEAD + PyObject *base; + Py_buffer view; +} PyMemoryViewObject; + + #ifdef __cplusplus } #endif Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Aug 19 20:22:14 2008 @@ -12,6 +12,12 @@ Core and Builtins ----------------- +- Issue #3560: clean up the new C PyMemoryView API so that naming is + internally consistent; add macros PyMemoryView_GET_BASE() and + PyMemoryView_GET_BUFFER() to access useful properties of a memory views + without relying on a particular implementation; remove the ill-named + PyMemoryView() function (PyMemoryView_GET_BUFFER() can be used instead). + - Issue #1819: function calls with several named parameters are now on average 35% faster (as measured by pybench). Modified: python/branches/py3k/Modules/_json.c ============================================================================== --- python/branches/py3k/Modules/_json.c (original) +++ python/branches/py3k/Modules/_json.c Tue Aug 19 20:22:14 2008 @@ -264,7 +264,7 @@ if (PyBuffer_FillInfo(&info, NULL, &buf[end], next - end, 1, 0) < 0) { goto bail; } - strchunk = PyMemoryView_FromMemory(&info); + strchunk = PyMemoryView_FromBuffer(&info); if (strchunk == NULL) { goto bail; } Modified: python/branches/py3k/Objects/memoryobject.c ============================================================================== --- python/branches/py3k/Objects/memoryobject.c (original) +++ python/branches/py3k/Objects/memoryobject.c Tue Aug 19 20:22:14 2008 @@ -29,7 +29,7 @@ Create a new memoryview object which references the given object."); PyObject * -PyMemoryView_FromMemory(Py_buffer *info) +PyMemoryView_FromBuffer(Py_buffer *info) { PyMemoryViewObject *mview; @@ -231,7 +231,7 @@ mem = PyObject_New(PyMemoryViewObject, &PyMemoryView_Type); if (mem == NULL) return NULL; - view = &PyMemoryView(mem); + view = &mem->view; flags = PyBUF_FULL_RO; switch(buffertype) { case PyBUF_WRITE: @@ -534,7 +534,7 @@ /* XXX: This needs to be fixed so it actually returns a sub-view */ - return PyMemoryView_FromMemory(&newview); + return PyMemoryView_FromBuffer(&newview); } } Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Tue Aug 19 20:22:14 2008 @@ -1200,7 +1200,7 @@ buffer = NULL; if (PyBuffer_FillInfo(&info, NULL, (void *)s, size, 1, PyBUF_SIMPLE) < 0) goto onError; - buffer = PyMemoryView_FromMemory(&info); + buffer = PyMemoryView_FromBuffer(&info); if (buffer == NULL) goto onError; unicode = PyCodec_Decode(buffer, encoding, errors); From brett at python.org Tue Aug 19 20:38:26 2008 From: brett at python.org (Brett Cannon) Date: Tue, 19 Aug 2008 11:38:26 -0700 Subject: [Python-3000-checkins] r65852 - python/branches/py3k/Lib/test/test_threading.py In-Reply-To: <20080819143256.E7EC61E4006@bag.python.org> References: <20080819143256.E7EC61E4006@bag.python.org> Message-ID: On Tue, Aug 19, 2008 at 7:32 AM, benjamin.peterson wrote: > Author: benjamin.peterson > Date: Tue Aug 19 16:32:56 2008 > New Revision: 65852 > > Log: > fix possible error > > Modified: > python/branches/py3k/Lib/test/test_threading.py > > Modified: python/branches/py3k/Lib/test/test_threading.py > ============================================================================== > --- python/branches/py3k/Lib/test/test_threading.py (original) > +++ python/branches/py3k/Lib/test/test_threading.py Tue Aug 19 16:32:56 2008 > @@ -329,7 +329,10 @@ > > t = threading.Thread() > with catch_warning() as w: > - del threading.__warningregistry__ > + try: > + del threading.__warningregistry__ > + except AttributeError: > + pass > msg = "isDaemon() is deprecated in favor of the " \ > "Thread.daemon property" > check(t.isDaemon(), w, msg) Isn't testing warnings fun? =) -Brett From musiccomposition at gmail.com Tue Aug 19 20:47:48 2008 From: musiccomposition at gmail.com (Benjamin Peterson) Date: Tue, 19 Aug 2008 13:47:48 -0500 Subject: [Python-3000-checkins] r65852 - python/branches/py3k/Lib/test/test_threading.py In-Reply-To: References: <20080819143256.E7EC61E4006@bag.python.org> Message-ID: <1afaf6160808191147j23bd200fm7196f8dc57d33fdf@mail.gmail.com> On Tue, Aug 19, 2008 at 1:38 PM, Brett Cannon wrote: > Isn't testing warnings fun? =) Infuriatingly so... > > -Brett > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > -- Cheers, Benjamin Peterson "There's no place like 127.0.0.1." From python-3000-checkins at python.org Tue Aug 19 20:57:57 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 20:57:57 +0200 (CEST) Subject: [Python-3000-checkins] r65863 - in python/branches/py3k: Demo/parser/unparse.py Doc/c-api/object.rst Doc/library/threading.rst Lib/distutils/cygwinccompiler.py Lib/test/test_os.py Modules/mmapmodule.c Objects/bytearrayobject.c Tools/scripts/idle Message-ID: <20080819185757.66B011E4006@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 20:57:56 2008 New Revision: 65863 Log: Merged revisions 65780,65782,65785,65809,65812,65834,65846,65859,65861 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65780 | antoine.pitrou | 2008-08-17 15:15:07 -0500 (Sun, 17 Aug 2008) | 3 lines #3580: fix a failure in test_os ........ r65782 | benjamin.peterson | 2008-08-17 15:33:45 -0500 (Sun, 17 Aug 2008) | 1 line set svn:executable on a script ........ r65785 | amaury.forgeotdarc | 2008-08-17 16:05:18 -0500 (Sun, 17 Aug 2008) | 3 lines Fix a refleak in bytearray.split and bytearray.rsplit, detected by regrtest.py -R:: test_bytes ........ r65809 | nick.coghlan | 2008-08-18 07:42:46 -0500 (Mon, 18 Aug 2008) | 1 line Belated NEWS entry for r65642 ........ r65812 | nick.coghlan | 2008-08-18 08:32:19 -0500 (Mon, 18 Aug 2008) | 1 line Fix typo ........ r65834 | amaury.forgeotdarc | 2008-08-18 14:23:47 -0500 (Mon, 18 Aug 2008) | 4 lines #2234 distutils failed with mingw binutils 2.18.50.20080109. Be less strict when parsing these version numbers, they don't necessarily follow the python numbering scheme. ........ r65846 | georg.brandl | 2008-08-18 18:09:49 -0500 (Mon, 18 Aug 2008) | 2 lines Fix grammar. ........ r65859 | thomas.heller | 2008-08-19 12:47:13 -0500 (Tue, 19 Aug 2008) | 2 lines Fix strange character in the docstring. ........ r65861 | benjamin.peterson | 2008-08-19 12:59:23 -0500 (Tue, 19 Aug 2008) | 1 line get unparse to at least unparse its self ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Demo/parser/unparse.py python/branches/py3k/Doc/c-api/object.rst python/branches/py3k/Doc/library/threading.rst python/branches/py3k/Lib/distutils/cygwinccompiler.py python/branches/py3k/Lib/test/test_os.py python/branches/py3k/Modules/mmapmodule.c python/branches/py3k/Objects/bytearrayobject.c python/branches/py3k/Tools/scripts/idle (props changed) Modified: python/branches/py3k/Demo/parser/unparse.py ============================================================================== --- python/branches/py3k/Demo/parser/unparse.py (original) +++ python/branches/py3k/Demo/parser/unparse.py Tue Aug 19 20:57:56 2008 @@ -186,7 +186,7 @@ self.dispatch(t.finalbody) self.leave() - def _excepthandler(self, t): + def _ExceptHandler(self, t): self.fill("except") if t.type: self.write(" ") @@ -213,7 +213,7 @@ def _FunctionDef(self, t): self.write("\n") - for deco in t.decorators: + for deco in t.decorator_list: self.fill("@") self.dispatch(deco) self.fill("def "+t.name + "(") Modified: python/branches/py3k/Doc/c-api/object.rst ============================================================================== --- python/branches/py3k/Doc/c-api/object.rst (original) +++ python/branches/py3k/Doc/c-api/object.rst Tue Aug 19 20:57:56 2008 @@ -261,7 +261,7 @@ Set a TypeError indicating that ``type(o)`` is not hashable and return ``-1``. This function receives special treatment when stored in a ``tp_hash`` slot, - allowing a type to explicit indicate to the interpreter that it is not + allowing a type to explicitly indicate to the interpreter that it is not hashable. .. versionadded:: 2.6 Modified: python/branches/py3k/Doc/library/threading.rst ============================================================================== --- python/branches/py3k/Doc/library/threading.rst (original) +++ python/branches/py3k/Doc/library/threading.rst Tue Aug 19 20:57:56 2008 @@ -14,7 +14,7 @@ .. note:: - Some name ``camelCase`` names have been converted to their underscored + Some ``camelCase`` names have been converted to their underscored equivalents. Others have been replaced by properties. Using the old methods in 2.6 will trigger a :exc:`DeprecationWarning` when Python is run with the :option:`-3` flag and a full :exc:`DeprecationWarning` in 3.0. The old names Modified: python/branches/py3k/Lib/distutils/cygwinccompiler.py ============================================================================== --- python/branches/py3k/Lib/distutils/cygwinccompiler.py (original) +++ python/branches/py3k/Lib/distutils/cygwinccompiler.py Tue Aug 19 20:57:56 2008 @@ -400,7 +400,7 @@ """ Try to find out the versions of gcc, ld and dllwrap. If not possible it returns None for it. """ - from distutils.version import StrictVersion + from distutils.version import LooseVersion from distutils.spawn import find_executable import re @@ -411,7 +411,7 @@ out.close() result = re.search('(\d+\.\d+(\.\d+)*)', out_string, re.ASCII) if result: - gcc_version = StrictVersion(result.group(1)) + gcc_version = LooseVersion(result.group(1)) else: gcc_version = None else: @@ -423,7 +423,7 @@ out.close() result = re.search('(\d+\.\d+(\.\d+)*)', out_string, re.ASCII) if result: - ld_version = StrictVersion(result.group(1)) + ld_version = LooseVersion(result.group(1)) else: ld_version = None else: @@ -435,7 +435,7 @@ out.close() result = re.search(' (\d+\.\d+(\.\d+)*)', out_string, re.ASCII) if result: - dllwrap_version = StrictVersion(result.group(1)) + dllwrap_version = LooseVersion(result.group(1)) else: dllwrap_version = None else: Modified: python/branches/py3k/Lib/test/test_os.py ============================================================================== --- python/branches/py3k/Lib/test/test_os.py (original) +++ python/branches/py3k/Lib/test/test_os.py Tue Aug 19 20:57:56 2008 @@ -318,7 +318,7 @@ try: os.stat(r"c:\pagefile.sys") except WindowsError as e: - if e == 2: # file does not exist; cannot run test + if e.errno == 2: # file does not exist; cannot run test return self.fail("Could not stat pagefile.sys") Modified: python/branches/py3k/Modules/mmapmodule.c ============================================================================== --- python/branches/py3k/Modules/mmapmodule.c (original) +++ python/branches/py3k/Modules/mmapmodule.c Tue Aug 19 20:57:56 2008 @@ -913,7 +913,7 @@ will be the current size of the file when mmap is called.\n\ flags specifies the nature of the mapping. MAP_PRIVATE creates a\n\ private copy-on-write mapping, so changes to the contents of the mmap\n\ -object will be private to this process, and MAP_SHARED`creates a mapping\n\ +object will be private to this process, and MAP_SHARED creates a mapping\n\ that's shared with all other processes mapping the same areas of the file.\n\ The default value is MAP_SHARED.\n\ \n\ Modified: python/branches/py3k/Objects/bytearrayobject.c ============================================================================== --- python/branches/py3k/Objects/bytearrayobject.c (original) +++ python/branches/py3k/Objects/bytearrayobject.c Tue Aug 19 20:57:56 2008 @@ -2215,8 +2215,11 @@ PyBuffer_Release(&vsub); return NULL; } - if (n == 1) - return split_char(s, len, sub[0], maxsplit); + if (n == 1) { + list = split_char(s, len, sub[0], maxsplit); + PyBuffer_Release(&vsub); + return list; + } list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) { @@ -2447,8 +2450,11 @@ PyBuffer_Release(&vsub); return NULL; } - else if (n == 1) - return rsplit_char(s, len, sub[0], maxsplit); + else if (n == 1) { + list = rsplit_char(s, len, sub[0], maxsplit); + PyBuffer_Release(&vsub); + return list; + } list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) { From python-3000-checkins at python.org Tue Aug 19 21:09:05 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 21:09:05 +0200 (CEST) Subject: [Python-3000-checkins] r65866 - python/branches/py3k Message-ID: <20080819190905.30DAF1E4006@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 21:09:04 2008 New Revision: 65866 Log: Blocked revisions 65865 via svnmerge ........ r65865 | benjamin.peterson | 2008-08-19 14:07:38 -0500 (Tue, 19 Aug 2008) | 1 line silence callable warning in hmac ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Tue Aug 19 21:17:39 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 21:17:39 +0200 (CEST) Subject: [Python-3000-checkins] r65867 - in python/branches/py3k: Doc/includes/mp_distributing.py Doc/includes/mp_pool.py Doc/includes/mp_synchronize.py Doc/includes/mp_webserver.py Doc/includes/mp_workers.py Doc/library/multiprocessing.rst Lib/multiprocessing/dummy/__init__.py Lib/multiprocessing/forking.py Lib/multiprocessing/managers.py Lib/multiprocessing/pool.py Lib/multiprocessing/process.py Lib/multiprocessing/reduction.py Lib/multiprocessing/synchronize.py Lib/multiprocessing/util.py Lib/test/test_multiprocessing.py Message-ID: <20080819191739.AFE311E4006@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 21:17:39 2008 New Revision: 65867 Log: Merged revisions 65864 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65864 | jesse.noller | 2008-08-19 14:06:19 -0500 (Tue, 19 Aug 2008) | 2 lines issue3352: clean up the multiprocessing API to remove many get_/set_ methods and convert them to properties. Update the docs and the examples included. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/includes/mp_distributing.py python/branches/py3k/Doc/includes/mp_pool.py python/branches/py3k/Doc/includes/mp_synchronize.py python/branches/py3k/Doc/includes/mp_webserver.py python/branches/py3k/Doc/includes/mp_workers.py python/branches/py3k/Doc/library/multiprocessing.rst python/branches/py3k/Lib/multiprocessing/dummy/__init__.py python/branches/py3k/Lib/multiprocessing/forking.py python/branches/py3k/Lib/multiprocessing/managers.py python/branches/py3k/Lib/multiprocessing/pool.py python/branches/py3k/Lib/multiprocessing/process.py python/branches/py3k/Lib/multiprocessing/reduction.py python/branches/py3k/Lib/multiprocessing/synchronize.py python/branches/py3k/Lib/multiprocessing/util.py python/branches/py3k/Lib/test/test_multiprocessing.py Modified: python/branches/py3k/Doc/includes/mp_distributing.py ============================================================================== --- python/branches/py3k/Doc/includes/mp_distributing.py (original) +++ python/branches/py3k/Doc/includes/mp_distributing.py Tue Aug 19 21:17:39 2008 @@ -17,10 +17,10 @@ import subprocess import logging import itertools -import Queue +import queue try: - import cPickle as pickle + import pickle as pickle except ImportError: import pickle @@ -152,7 +152,7 @@ def LocalProcess(**kwds): p = Process(**kwds) - p.set_name('localhost/' + p.get_name()) + p.set_name('localhost/' + p.name) return p class Cluster(managers.SyncManager): @@ -210,7 +210,7 @@ self._base_shutdown() def Process(self, group=None, target=None, name=None, args=(), kwargs={}): - slot = self._slot_iterator.next() + slot = next(self._slot_iterator) return slot.Process( group=group, target=target, name=name, args=args, kwargs=kwargs ) @@ -231,7 +231,7 @@ # Queue subclass used by distributed pool # -class SettableQueue(Queue.Queue): +class SettableQueue(queue.Queue): def empty(self): return not self.queue def full(self): @@ -243,7 +243,7 @@ try: self.queue.clear() self.queue.extend(contents) - self.not_empty.notify_all() + self.not_empty.notifyAll() finally: self.not_empty.release() Modified: python/branches/py3k/Doc/includes/mp_pool.py ============================================================================== --- python/branches/py3k/Doc/includes/mp_pool.py (original) +++ python/branches/py3k/Doc/includes/mp_pool.py Tue Aug 19 21:17:39 2008 @@ -14,7 +14,7 @@ def calculate(func, args): result = func(*args) return '%s says that %s%s = %s' % ( - multiprocessing.current_process().get_name(), + multiprocessing.current_process().name, func.__name__, args, result ) Modified: python/branches/py3k/Doc/includes/mp_synchronize.py ============================================================================== --- python/branches/py3k/Doc/includes/mp_synchronize.py (original) +++ python/branches/py3k/Doc/includes/mp_synchronize.py Tue Aug 19 21:17:39 2008 @@ -224,7 +224,7 @@ p.start() p.join() - assert p.get_exitcode() == 0 + assert p.exitcode == 0 #### Modified: python/branches/py3k/Doc/includes/mp_webserver.py ============================================================================== --- python/branches/py3k/Doc/includes/mp_webserver.py (original) +++ python/branches/py3k/Doc/includes/mp_webserver.py Tue Aug 19 21:17:39 2008 @@ -21,7 +21,7 @@ def note(format, *args): - sys.stderr.write('[%s]\t%s\n' % (current_process().get_name(),format%args)) + sys.stderr.write('[%s]\t%s\n' % (current_process().name, format%args)) class RequestHandler(SimpleHTTPRequestHandler): Modified: python/branches/py3k/Doc/includes/mp_workers.py ============================================================================== --- python/branches/py3k/Doc/includes/mp_workers.py (original) +++ python/branches/py3k/Doc/includes/mp_workers.py Tue Aug 19 21:17:39 2008 @@ -29,7 +29,7 @@ def calculate(func, args): result = func(*args) return '%s says that %s%s = %s' % \ - (current_process().get_name(), func.__name__, args, result) + (current_process().name, func.__name__, args, result) # # Functions referenced by tasks Modified: python/branches/py3k/Doc/library/multiprocessing.rst ============================================================================== --- python/branches/py3k/Doc/library/multiprocessing.rst (original) +++ python/branches/py3k/Doc/library/multiprocessing.rst Tue Aug 19 21:17:39 2008 @@ -290,11 +290,11 @@ A process cannot join itself because this would cause a deadlock. It is an error to attempt to join a process before it has been started. - .. method:: get_name() + .. attribute:: Process.name Return the process's name. - .. method:: set_name(name) + .. attribute:: Process.name = name Set the process's name. @@ -309,11 +309,11 @@ Roughly, a process object is alive from the moment the :meth:`start` method returns until the child process terminates. - .. method:: is_daemon() + .. attribute:: Process.daemon - Return the process's daemon flag. + Return the process's daemon flag., this is a boolean. - .. method:: set_daemon(daemonic) + .. attribute:: Process.daemon = daemonic Set the process's daemon flag to the Boolean value *daemonic*. This must be called before :meth:`start` is called. @@ -329,18 +329,18 @@ In addition process objects also support the following methods: - .. method:: get_pid() + .. attribute:: Process.pid Return the process ID. Before the process is spawned, this will be ``None``. - .. method:: get_exit_code() + .. attribute:: Process.exitcode Return the child's exit code. This will be ``None`` if the process has not yet terminated. A negative value *-N* indicates that the child was terminated by signal *N*. - .. method:: get_auth_key() + .. attribute:: Process.authkey Return the process's authentication key (a byte string). @@ -349,11 +349,11 @@ When a :class:`Process` object is created, it will inherit the authentication key of its parent process, although this may be changed - using :meth:`set_auth_key` below. + using :attr:`Process.authkey` below. See :ref:`multiprocessing-auth-keys`. - .. method:: set_auth_key(authkey) + .. attribute:: Process.authkey = authkey Set the process's authentication key which must be a byte string. Modified: python/branches/py3k/Lib/multiprocessing/dummy/__init__.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/dummy/__init__.py (original) +++ python/branches/py3k/Lib/multiprocessing/dummy/__init__.py Tue Aug 19 21:17:39 2008 @@ -47,7 +47,8 @@ self._parent._children[self] = None threading.Thread.start(self) - def get_exitcode(self): + @property + def exitcode(self): if self._start_called and not self.is_alive(): return 0 else: Modified: python/branches/py3k/Lib/multiprocessing/forking.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/forking.py (original) +++ python/branches/py3k/Lib/multiprocessing/forking.py Tue Aug 19 21:17:39 2008 @@ -315,7 +315,7 @@ sys_argv=sys.argv, log_to_stderr=_log_to_stderr, orig_dir=process.ORIGINAL_DIR, - authkey=process.current_process().get_authkey(), + authkey=process.current_process().authkey, ) if _logger is not None: @@ -363,7 +363,7 @@ old_main_modules.append(sys.modules['__main__']) if 'name' in data: - process.current_process().set_name(data['name']) + process.current_process().name = data['name'] if 'authkey' in data: process.current_process()._authkey = data['authkey'] Modified: python/branches/py3k/Lib/multiprocessing/managers.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/managers.py (original) +++ python/branches/py3k/Lib/multiprocessing/managers.py Tue Aug 19 21:17:39 2008 @@ -450,7 +450,7 @@ def __init__(self, address=None, authkey=None, serializer='pickle'): if authkey is None: - authkey = current_process().get_authkey() + authkey = current_process().authkey self._address = address # XXX not final address if eg ('', 0) self._authkey = AuthenticationString(authkey) self._state = State() @@ -495,7 +495,7 @@ self._serializer, writer), ) ident = ':'.join(str(i) for i in self._process._identity) - self._process.set_name(type(self).__name__ + '-' + ident) + self._process.name = type(self).__name__ + '-' + ident self._process.start() # get address of server @@ -696,7 +696,7 @@ elif self._manager is not None: self._authkey = self._manager._authkey else: - self._authkey = current_process().get_authkey() + self._authkey = current_process().authkey if incref: self._incref() @@ -705,7 +705,7 @@ def _connect(self): util.debug('making connection to manager') - name = current_process().get_name() + name = current_process().name if threading.current_thread().name != 'MainThread': name += '|' + threading.current_thread().name conn = self._Client(self._token.address, authkey=self._authkey) @@ -886,7 +886,7 @@ if authkey is None and manager is not None: authkey = manager._authkey if authkey is None: - authkey = current_process().get_authkey() + authkey = current_process().authkey ProxyType = MakeProxyType('AutoProxy[%s]' % token.typeid, exposed) proxy = ProxyType(token, serializer, manager=manager, authkey=authkey, Modified: python/branches/py3k/Lib/multiprocessing/pool.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/pool.py (original) +++ python/branches/py3k/Lib/multiprocessing/pool.py Tue Aug 19 21:17:39 2008 @@ -99,7 +99,7 @@ args=(self._inqueue, self._outqueue, initializer, initargs) ) self._pool.append(w) - w.name = w.get_name().replace('Process', 'PoolWorker') + w.name = w.name.replace('Process', 'PoolWorker') w.daemon = True w.start() Modified: python/branches/py3k/Lib/multiprocessing/process.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/process.py (original) +++ python/branches/py3k/Lib/multiprocessing/process.py Tue Aug 19 21:17:39 2008 @@ -132,45 +132,43 @@ self._popen.poll() return self._popen.returncode is None - def get_name(self): - ''' - Return name of process - ''' + @property + def name(self): return self._name - def set_name(self, name): - ''' - Set name of process - ''' + @name.setter + def name(self, name): assert isinstance(name, str), 'name must be a string' self._name = name - def is_daemon(self): + @property + def daemon(self): ''' Return whether process is a daemon ''' return self._daemonic - def set_daemon(self, daemonic): + @daemon.setter + def daemon(self, daemonic): ''' Set whether process is a daemon ''' assert self._popen is None, 'process has already started' self._daemonic = daemonic - def get_authkey(self): - ''' - Return authorization key of process - ''' + @property + def authkey(self): return self._authkey - def set_authkey(self, authkey): + @authkey.setter + def authkey(self, authkey): ''' Set authorization key of process ''' self._authkey = AuthenticationString(authkey) - def get_exitcode(self): + @property + def exitcode(self): ''' Return exit code of process or `None` if it has yet to stop ''' @@ -178,7 +176,8 @@ return self._popen return self._popen.poll() - def get_ident(self): + @property + def ident(self): ''' Return indentifier (PID) of process or `None` if it has yet to start ''' @@ -187,7 +186,7 @@ else: return self._popen and self._popen.pid - pid = property(get_ident) + pid = ident def __repr__(self): if self is _current_process: @@ -198,7 +197,7 @@ status = 'initial' else: if self._popen.poll() is not None: - status = self.get_exitcode() + status = self.exitcode else: status = 'started' @@ -245,7 +244,7 @@ except: exitcode = 1 import traceback - sys.stderr.write('Process %s:\n' % self.get_name()) + sys.stderr.write('Process %s:\n' % self.name) sys.stderr.flush() traceback.print_exc() Modified: python/branches/py3k/Lib/multiprocessing/reduction.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/reduction.py (original) +++ python/branches/py3k/Lib/multiprocessing/reduction.py Tue Aug 19 21:17:39 2008 @@ -82,9 +82,9 @@ try: if _listener is None: debug('starting listener and thread for sending handles') - _listener = Listener(authkey=current_process().get_authkey()) + _listener = Listener(authkey=current_process().authkey) t = threading.Thread(target=_serve) - t.set_daemon(True) + t.daemon = True t.start() finally: _lock.release() @@ -127,7 +127,7 @@ if inherited: return handle sub_debug('rebuilding handle %d', handle) - conn = Client(address, authkey=current_process().get_authkey()) + conn = Client(address, authkey=current_process().authkey) conn.send((handle, os.getpid())) new_handle = recv_handle(conn) conn.close() Modified: python/branches/py3k/Lib/multiprocessing/synchronize.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/synchronize.py (original) +++ python/branches/py3k/Lib/multiprocessing/synchronize.py Tue Aug 19 21:17:39 2008 @@ -108,9 +108,9 @@ def __repr__(self): try: if self._semlock._is_mine(): - name = current_process().get_name() - if threading.current_thread().get_name() != 'MainThread': - name += '|' + threading.current_thread().get_name() + name = current_process().name + if threading.current_thread().name != 'MainThread': + name += '|' + threading.current_thread().name elif self._semlock._get_value() == 1: name = 'None' elif self._semlock._count() > 0: @@ -133,9 +133,9 @@ def __repr__(self): try: if self._semlock._is_mine(): - name = current_process().get_name() - if threading.current_thread().get_name() != 'MainThread': - name += '|' + threading.current_thread().get_name() + name = current_process().name + if threading.current_thread().name != 'MainThread': + name += '|' + threading.current_thread().name count = self._semlock._count() elif self._semlock._get_value() == 1: name, count = 'None', 0 Modified: python/branches/py3k/Lib/multiprocessing/util.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/util.py (original) +++ python/branches/py3k/Lib/multiprocessing/util.py Tue Aug 19 21:17:39 2008 @@ -274,11 +274,11 @@ for p in active_children(): if p._daemonic: - info('calling terminate() for daemon %s', p.get_name()) + info('calling terminate() for daemon %s', p.name) p._popen.terminate() for p in active_children(): - info('calling join() for process %s', p.get_name()) + info('calling join() for process %s', p.name) p.join() debug('running the remaining "atexit" finalizers') Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Tue Aug 19 21:17:39 2008 @@ -120,22 +120,22 @@ return current = self.current_process() - authkey = current.get_authkey() + authkey = current.authkey self.assertTrue(current.is_alive()) - self.assertTrue(not current.is_daemon()) + self.assertTrue(not current.daemon) self.assertTrue(isinstance(authkey, bytes)) self.assertTrue(len(authkey) > 0) - self.assertEqual(current.get_ident(), os.getpid()) - self.assertEqual(current.get_exitcode(), None) + self.assertEqual(current.ident, os.getpid()) + self.assertEqual(current.exitcode, None) def _test(self, q, *args, **kwds): current = self.current_process() q.put(args) q.put(kwds) - q.put(current.get_name()) + q.put(current.name) if self.TYPE != 'threads': - q.put(bytes(current.get_authkey())) + q.put(bytes(current.authkey)) q.put(current.pid) def test_process(self): @@ -147,33 +147,33 @@ p = self.Process( target=self._test, args=args, kwargs=kwargs, name=name ) - p.set_daemon(True) + p.daemon = True current = self.current_process() if self.TYPE != 'threads': - self.assertEquals(p.get_authkey(), current.get_authkey()) + self.assertEquals(p.authkey, current.authkey) self.assertEquals(p.is_alive(), False) - self.assertEquals(p.is_daemon(), True) + self.assertEquals(p.daemon, True) self.assertTrue(p not in self.active_children()) self.assertTrue(type(self.active_children()) is list) - self.assertEqual(p.get_exitcode(), None) + self.assertEqual(p.exitcode, None) p.start() - self.assertEquals(p.get_exitcode(), None) + self.assertEquals(p.exitcode, None) self.assertEquals(p.is_alive(), True) self.assertTrue(p in self.active_children()) self.assertEquals(q.get(), args[1:]) self.assertEquals(q.get(), kwargs) - self.assertEquals(q.get(), p.get_name()) + self.assertEquals(q.get(), p.name) if self.TYPE != 'threads': - self.assertEquals(q.get(), current.get_authkey()) + self.assertEquals(q.get(), current.authkey) self.assertEquals(q.get(), p.pid) p.join() - self.assertEquals(p.get_exitcode(), 0) + self.assertEquals(p.exitcode, 0) self.assertEquals(p.is_alive(), False) self.assertTrue(p not in self.active_children()) @@ -185,12 +185,12 @@ return p = self.Process(target=self._test_terminate) - p.set_daemon(True) + p.daemon = True p.start() self.assertEqual(p.is_alive(), True) self.assertTrue(p in self.active_children()) - self.assertEqual(p.get_exitcode(), None) + self.assertEqual(p.exitcode, None) p.terminate() @@ -203,8 +203,8 @@ p.join() - # XXX sometimes get p.get_exitcode() == 0 on Windows ... - #self.assertEqual(p.get_exitcode(), -signal.SIGTERM) + # XXX sometimes get p.exitcode == 0 on Windows ... + #self.assertEqual(p.exitcode, -signal.SIGTERM) def test_cpu_count(self): try: @@ -331,7 +331,7 @@ target=self._test_put, args=(queue, child_can_start, parent_can_continue) ) - proc.set_daemon(True) + proc.daemon = True proc.start() self.assertEqual(queue_empty(queue), True) @@ -397,7 +397,7 @@ target=self._test_get, args=(queue, child_can_start, parent_can_continue) ) - proc.set_daemon(True) + proc.daemon = True proc.start() self.assertEqual(queue_empty(queue), True) @@ -620,17 +620,11 @@ woken = self.Semaphore(0) p = self.Process(target=self.f, args=(cond, sleeping, woken)) - try: - p.set_daemon(True) - except AttributeError: - p.daemon = True + p.daemon = True p.start() p = threading.Thread(target=self.f, args=(cond, sleeping, woken)) - try: - p.set_daemon(True) - except AttributeError: - p.daemon = True + p.daemon = True p.start() # wait for both children to start sleeping @@ -672,7 +666,7 @@ for i in range(3): p = self.Process(target=self.f, args=(cond, sleeping, woken, TIMEOUT1)) - p.set_daemon(True) + p.daemon = True p.start() t = threading.Thread(target=self.f, @@ -695,7 +689,7 @@ # start some more threads/processes for i in range(3): p = self.Process(target=self.f, args=(cond, sleeping, woken)) - p.set_daemon(True) + p.daemon = True p.start() t = threading.Thread(target=self.f, args=(cond, sleeping, woken)) @@ -1192,7 +1186,7 @@ conn, child_conn = self.Pipe() p = self.Process(target=self._echo, args=(child_conn,)) - p.set_daemon(True) + p.daemon = True p.start() seq = [1, 2.25, None] @@ -1341,7 +1335,7 @@ for family in self.connection.families: l = self.connection.Listener(family=family) p = self.Process(target=self._test, args=(l.address,)) - p.set_daemon(True) + p.daemon = True p.start() conn = l.accept() self.assertEqual(conn.recv(), 'hello') From python-3000-checkins at python.org Tue Aug 19 21:49:50 2008 From: python-3000-checkins at python.org (thomas.heller) Date: Tue, 19 Aug 2008 21:49:50 +0200 (CEST) Subject: [Python-3000-checkins] r65871 - in python/branches/py3k: Lib/ctypes/test/test_pointers.py Misc/NEWS Modules/_ctypes/_ctypes.c Message-ID: <20080819194950.33C921E4015@bag.python.org> Author: thomas.heller Date: Tue Aug 19 21:49:49 2008 New Revision: 65871 Log: Merged revisions 65868,65870 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65868 | thomas.heller | 2008-08-19 21:25:04 +0200 (Di, 19 Aug 2008) | 3 lines Fix a regression introduced by rev. 63792: ctypes function pointers that are COM methods must have a boolean True value. ........ r65870 | thomas.heller | 2008-08-19 21:40:23 +0200 (Di, 19 Aug 2008) | 1 line COM method code is windows specific ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/ctypes/test/test_pointers.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_ctypes/_ctypes.c Modified: python/branches/py3k/Lib/ctypes/test/test_pointers.py ============================================================================== --- python/branches/py3k/Lib/ctypes/test/test_pointers.py (original) +++ python/branches/py3k/Lib/ctypes/test/test_pointers.py Tue Aug 19 21:49:49 2008 @@ -1,4 +1,4 @@ -import unittest +import unittest, sys from ctypes import * import _ctypes_test @@ -183,5 +183,10 @@ self.failUnlessEqual(bool(CFUNCTYPE(None)(0)), False) self.failUnlessEqual(bool(CFUNCTYPE(None)(42)), True) + # COM methods are boolean True: + if sys.platform == "win32": + mth = WINFUNCTYPE(None)(42, "name", (), None) + self.failUnlessEqual(bool(mth), True) + if __name__ == '__main__': unittest.main() Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Aug 19 21:49:49 2008 @@ -18,6 +18,9 @@ without relying on a particular implementation; remove the ill-named PyMemoryView() function (PyMemoryView_GET_BUFFER() can be used instead). +- ctypes function pointers that are COM methods have a boolean True + value again. + - Issue #1819: function calls with several named parameters are now on average 35% faster (as measured by pybench). Modified: python/branches/py3k/Modules/_ctypes/_ctypes.c ============================================================================== --- python/branches/py3k/Modules/_ctypes/_ctypes.c (original) +++ python/branches/py3k/Modules/_ctypes/_ctypes.c Tue Aug 19 21:49:49 2008 @@ -3858,12 +3858,16 @@ } static int -Pointer_bool(CDataObject *self) +CFuncPtr_bool(CFuncPtrObject *self) { - return *(void **)self->b_ptr != NULL; + return ((*(void **)self->b_ptr != NULL) +#ifdef MS_WIN32 + || (self->index != 0) +#endif + ); } -static PyNumberMethods Pointer_as_number = { +static PyNumberMethods CFuncPtr_as_number = { 0, /* nb_add */ 0, /* nb_subtract */ 0, /* nb_multiply */ @@ -3873,7 +3877,7 @@ 0, /* nb_negative */ 0, /* nb_positive */ 0, /* nb_absolute */ - (inquiry)Pointer_bool, /* nb_bool */ + (inquiry)CFuncPtr_bool, /* nb_bool */ }; PyTypeObject CFuncPtr_Type = { @@ -3887,7 +3891,7 @@ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)CFuncPtr_repr, /* tp_repr */ - &Pointer_as_number, /* tp_as_number */ + &CFuncPtr_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ @@ -4960,6 +4964,25 @@ Pointer_subscript, }; +static int +Pointer_bool(CDataObject *self) +{ + return (*(void **)self->b_ptr != NULL); +} + +static PyNumberMethods Pointer_as_number = { + 0, /* nb_add */ + 0, /* nb_subtract */ + 0, /* nb_multiply */ + 0, /* nb_remainder */ + 0, /* nb_divmod */ + 0, /* nb_power */ + 0, /* nb_negative */ + 0, /* nb_positive */ + 0, /* nb_absolute */ + (inquiry)Pointer_bool, /* nb_bool */ +}; + PyTypeObject Pointer_Type = { PyVarObject_HEAD_INIT(NULL, 0) "_ctypes._Pointer", From python-3000-checkins at python.org Tue Aug 19 21:55:35 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 21:55:35 +0200 (CEST) Subject: [Python-3000-checkins] r65873 - python/branches/py3k Message-ID: <20080819195535.5E4C41E4012@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 21:55:35 2008 New Revision: 65873 Log: Blocked revisions 65872 via svnmerge ........ r65872 | benjamin.peterson | 2008-08-19 14:52:46 -0500 (Tue, 19 Aug 2008) | 1 line allow keyword args to be passed in after *args #3473 ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Tue Aug 19 22:15:03 2008 From: python-3000-checkins at python.org (guido.van.rossum) Date: Tue, 19 Aug 2008 22:15:03 +0200 (CEST) Subject: [Python-3000-checkins] r65875 - python/branches/py3k Message-ID: <20080819201503.DF8DD1E4006@bag.python.org> Author: guido.van.rossum Date: Tue Aug 19 22:15:03 2008 New Revision: 65875 Log: Blocked revisions 65874 via svnmerge ........ r65874 | guido.van.rossum | 2008-08-19 13:13:02 -0700 (Tue, 19 Aug 2008) | 3 lines Hopeful fix for issue 1878: remove Py_TPFLAGS_HAVE_VERSION_TAG from Py_TPFLAGS_DEFAULT when not building the core. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Tue Aug 19 22:57:11 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 22:57:11 +0200 (CEST) Subject: [Python-3000-checkins] r65877 - in python/branches/py3k: Doc/reference/expressions.rst Grammar/Grammar Lib/test/test_grammar.py Lib/test/test_keywordonlyarg.py Python/ast.c Python/graminit.c Message-ID: <20080819205711.3F76D1E4009@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 22:57:10 2008 New Revision: 65877 Log: allow keyword args after *args in a function call Modified: python/branches/py3k/Doc/reference/expressions.rst python/branches/py3k/Grammar/Grammar python/branches/py3k/Lib/test/test_grammar.py python/branches/py3k/Lib/test/test_keywordonlyarg.py python/branches/py3k/Python/ast.c python/branches/py3k/Python/graminit.c Modified: python/branches/py3k/Doc/reference/expressions.rst ============================================================================== --- python/branches/py3k/Doc/reference/expressions.rst (original) +++ python/branches/py3k/Doc/reference/expressions.rst Tue Aug 19 22:57:10 2008 @@ -612,11 +612,11 @@ call: `primary` "(" [`argument_list` [","] : | `expression` `genexpr_for`] ")" argument_list: `positional_arguments` ["," `keyword_arguments`] - : ["," "*" `expression`] - : ["," "**" `expression`] + : ["," "*" `expression`] ["," `keyword_arguments`] + : ["," "**" `expression`] : | `keyword_arguments` ["," "*" `expression`] - : ["," "**" `expression`] - : | "*" `expression` ["," "**" `expression`] + : ["," `keyword_arguments`] ["," "**" `expression`] + : | "*" `expression` ["," `keyword_arguments`] ["," "**" `expression`] : | "**" `expression` positional_arguments: `expression` ("," `expression`)* keyword_arguments: `keyword_item` ("," `keyword_item`)* @@ -674,12 +674,13 @@ If the syntax ``*expression`` appears in the function call, ``expression`` must evaluate to a sequence. Elements from this sequence are treated as if they were -additional positional arguments; if there are positional arguments *x1*,...,*xN* -, and ``expression`` evaluates to a sequence *y1*,...,*yM*, this is equivalent -to a call with M+N positional arguments *x1*,...,*xN*,*y1*,...,*yM*. +additional positional arguments; if there are positional arguments *x1*,..., +*xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*, this is +equivalent to a call with M+N positional arguments *x1*, ..., *xN*, *y1*, ..., +*yM*. -A consequence of this is that although the ``*expression`` syntax appears -*after* any keyword arguments, it is processed *before* the keyword arguments +A consequence of this is that although the ``*expression`` syntax may appear +*after* some keyword arguments, it is processed *before* the keyword arguments (and the ``**expression`` argument, if any -- see below). So:: >>> def f(a, b): Modified: python/branches/py3k/Grammar/Grammar ============================================================================== --- python/branches/py3k/Grammar/Grammar (original) +++ python/branches/py3k/Grammar/Grammar Tue Aug 19 22:57:10 2008 @@ -113,7 +113,9 @@ classdef: 'class' NAME ['(' [arglist] ')'] ':' suite -arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) +arglist: (argument ',')* (argument [','] + |'*' test (',' argument)* [',' '**' test] + |'**' test) argument: test [comp_for] | test '=' test # Really [keyword '='] test comp_iter: comp_for | comp_if Modified: python/branches/py3k/Lib/test/test_grammar.py ============================================================================== --- python/branches/py3k/Lib/test/test_grammar.py (original) +++ python/branches/py3k/Lib/test/test_grammar.py Tue Aug 19 22:57:10 2008 @@ -284,6 +284,14 @@ pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200) pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100) + # keyword arguments after *arglist + def f(*args, **kwargs): + return args, kwargs + self.assertEquals(f(1, x=2, *[3, 4], y=5), ((1, 3, 4), + {'x':2, 'y':5})) + self.assertRaises(SyntaxError, eval, "f(1, *(2,3), 4)") + self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)") + # argument annotation tests def f(x) -> list: pass self.assertEquals(f.__annotations__, {'return': list}) Modified: python/branches/py3k/Lib/test/test_keywordonlyarg.py ============================================================================== --- python/branches/py3k/Lib/test/test_keywordonlyarg.py (original) +++ python/branches/py3k/Lib/test/test_keywordonlyarg.py Tue Aug 19 22:57:10 2008 @@ -75,7 +75,7 @@ def testSyntaxErrorForFunctionCall(self): self.assertRaisesSyntaxError("f(p, k=1, p2)") - self.assertRaisesSyntaxError("f(p, *(1,2), k1=100)") + self.assertRaisesSyntaxError("f(p, k1=50, *(1,2), k1=100)") def testRaiseErrorFuncallWithUnexpectedKeywordArgument(self): self.assertRaises(TypeError, keywordonly_sum, ()) Modified: python/branches/py3k/Python/ast.c ============================================================================== --- python/branches/py3k/Python/ast.c (original) +++ python/branches/py3k/Python/ast.c Tue Aug 19 22:57:10 2008 @@ -1961,6 +1961,11 @@ "non-keyword arg after keyword arg"); return NULL; } + if (vararg) { + ast_error(CHILD(ch, 0), + "only named arguments may follow *expression"); + return NULL; + } e = ast_for_expr(c, CHILD(ch, 0)); if (!e) return NULL; Modified: python/branches/py3k/Python/graminit.c ============================================================================== --- python/branches/py3k/Python/graminit.c (original) +++ python/branches/py3k/Python/graminit.c Tue Aug 19 22:57:10 2008 @@ -1598,7 +1598,8 @@ static arc arcs_73_6[1] = { {0, 6}, }; -static arc arcs_73_7[1] = { +static arc arcs_73_7[2] = { + {161, 5}, {32, 3}, }; static state states_73[8] = { @@ -1609,7 +1610,7 @@ {4, arcs_73_4}, {2, arcs_73_5}, {1, arcs_73_6}, - {1, arcs_73_7}, + {2, arcs_73_7}, }; static arc arcs_74_0[1] = { {24, 1}, From python-3000-checkins at python.org Tue Aug 19 23:01:52 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Tue, 19 Aug 2008 23:01:52 +0200 (CEST) Subject: [Python-3000-checkins] r65879 - python/branches/py3k/Lib/bsddb/test/test_dbtables.py Message-ID: <20080819210152.A17571E400D@bag.python.org> Author: antoine.pitrou Date: Tue Aug 19 23:01:52 2008 New Revision: 65879 Log: Fix a failure in bsddb tests, following the changes in regular expression semantics Modified: python/branches/py3k/Lib/bsddb/test/test_dbtables.py Modified: python/branches/py3k/Lib/bsddb/test/test_dbtables.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_dbtables.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_dbtables.py Tue Aug 19 23:01:52 2008 @@ -173,8 +173,8 @@ # this should return two rows values = self.tdb.Select(tabname, ['b', 'a', 'd'], - conditions={'e': re.compile('wuzzy').search, - 'a': re.compile('^[0-9]+$').match}) + conditions={'e': re.compile(b'wuzzy').search, + 'a': re.compile(b'^[0-9]+$').match}) self.assertEquals(len(values), 2) # now lets delete one of them and try again From python-3000-checkins at python.org Tue Aug 19 23:04:41 2008 From: python-3000-checkins at python.org (guido.van.rossum) Date: Tue, 19 Aug 2008 23:04:41 +0200 (CEST) Subject: [Python-3000-checkins] r65881 - in python/branches/py3k/Lib/test: greyrgb.uue testimg.uue testimgr.uue testrgb.uue Message-ID: <20080819210441.A98651E4006@bag.python.org> Author: guido.van.rossum Date: Tue Aug 19 23:04:40 2008 New Revision: 65881 Log: Remove four uu-encoded image files that were once useful for testing imgfile, rgbimg and imageop. None of those modules exist any more... Removed: python/branches/py3k/Lib/test/greyrgb.uue python/branches/py3k/Lib/test/testimg.uue python/branches/py3k/Lib/test/testimgr.uue python/branches/py3k/Lib/test/testrgb.uue Deleted: python/branches/py3k/Lib/test/greyrgb.uue ============================================================================== --- python/branches/py3k/Lib/test/greyrgb.uue Tue Aug 19 23:04:40 2008 +++ (empty file) @@ -1,1547 +0,0 @@ -begin 644 greytest.rgb -M =H! 0 " 0 ! ! "0 )( ;F\@;F%M90 -M -M ! " #_ $ %- -M\ 0]<$ %%Z! !2>P -M -M -M -M -M -M -M -M H +!@ # L T1 .%@ #QH ! > -M 1(P $BD !,O 4- %3H !8_ 710 &$H !E0 :50 &UD -M !Q? =90 'FH !]P @=@ (7D ")^ CA )(D "6/ FE -M)YH "B> II *JH "NP LM0 +;D "Z_ OQ ,,@ #', R -MT ,]4 #39 UWP -N4 #?J X\ .?0 #KX [_ /0( #X' -M _"@ 0! $$5 !"&P 0R$ $0G !%+0 1C( $* "(D B98 (J< "+H@ C*@ (VN ". -ML@ C[8 )"Z "1OP DL0 )/* "4T E=8 );< "7X@ F.@ )GM -M ":\@ F_@ )S\ "> @ GP@ * . "A$P HA< *,< "D(0 I28 -M *8K "G, J#8 *D[ "J00 JT< *Q- "M4P KED *]> "P9 -ML6H +)P "S= M'H +6 "VA@ MXL +B/ "YDP NI< +N= "\ -MHP O:D +ZN "_M P+H ,' #"Q@ P\P ,31 #%UP QMT ,?C -M #(Z R>T ,KS #+]P S/P ,X" #/" T T -$2 #2& TQX -M -0D #5*@ UB\ -60 -MWU\ .!E #A:P XG .-T #D>0 Y7T .:# #GB0 Z(\ .F4 #J -MF0 ZY\ .RD #MJ [JX .^T #PN0 \;\ /+% #SR@ ]- /76 -M #VVP ]^ /CF #YZP ^O /OU #\^P _@$ /\' $ # ! 1( -M 0(6 $#&P !!"$ 04G $&+ !!S( 0 at X $)/ !"D( 0M' $,3 ! -M#5$ 0Y6 !!@ 04 $& !!0 00 $$ !!0 08 $& ! -M!0 08 $% !!@ 04 $& !!0 00 $& !!@ 04 $& -M !!@ 0, $% !!@ 04 $& !!0 08 $$ !!@ 08 -M $& !!0 00 $& !!0 00 $$ !! 04 $$ !!@ -M 08 $% !!@ 00 $$ !! 08 $% ! P 08 $% ! -M!@ 08 $& !!@ 04 $& !!@ 00 $& !!@ 00 $& -M !!@ 08 $& !!@ 04 $% !!@ 08 $& !!0 04 -M $% !!0 00 $$ !!0 04 $& !!@ 08 $& ! P -M 04 $% !!0 08 $& !!@ 08 $& !!0 00 $& ! -M!0 00 $& !!@ 04 $& !!@ 00 $& !!@ 04 $& -M !!@ 08 $$ !!@ 00 $% !!@ 08 $& !! 08 -M $% !!@ 08 $& !!@ 08 $& !! 00 $$ !!0 -M 04 $& !!@ 08 $& !!@ 08 $% !!0 08 $$ ! -M!@ 08 $& !!0 00 $% !!0 04 $% !!0 08 $% -M !!@ 08 $& !!@ 08 $% !!@ 08 $& !! 08 -M $& !!@ 04 $$ !! 00 $& !!@ 08 $% !!@ -M 08 $& !!@ 08 $% !!@ 08 $& !!0 04 $& ! -M! 04 $& !!@ 04 $% !!@ 08 $& !!@ 04 $& -M !!0 00 $% !!0 04 $& !!@ 08 $& !!@ 04 -M $$ !!0 00 $& !!@ 08 $% !!0 08 $% !! -M 08 $& !!0 08 $& !!0 08 $& !!0 04 $& ! -M!0 04 $% !!@ 08 $& !!0 08 $$ !!0 08 $& -M !!0 08 $& !! 08 $% !!0 04 $% !!OZ*@EA6 -M*3156$5:6TUFHII,#9$6%D#.?Y$ -M=W5H8%D_*1@@+3!07)U:EA%:5MK at 4\Y -M8H-V>VE8-CQ;@W V+4QO3#=64!U)1# 5&#M$8'!C$DV.TE@ 3D!1 #^<8)P-EAA8FI?+1LE<()F8V-?22DM -M.RU-:F)B3#8M3W!B;W)8.3DG&SE at 6%@I'6)[:F- at 36IR6T]R:EII/B=8U at V<&!:/QM)G)@ -M17=[8FIH23Y at 9T5%8FE-.3Q-7V)K5B=B@')Z:FE;;$UF at TLV:H-N?7-825IW -M>W!)24]K224V5D16:6$@&#(\16E-6SDM7VI:=WIZ:FM at -ALE+39F?'I836M: -M9GV"@FI%/X)%:P$V 5@ \')M>F-;6V)V=RT.)6.(8F-P7)K9DU%3&MJ8FA%9GI,+6]W:G)K6C]9 -M:$U5:G)H8$0Y25M<224E8&MR9EM;<'-Z=TE9>H)N?'9 at 7EEJH* :D5; -M23E):&\P)RE86%I at 8Q42,&A%<'IU>GIJ7"T@%25-:ER-339A:FIZ?()Z6UA@ -M6F)M>F]),$PM(@-)Z5A)6')R9FE- -M5G*#6DUB:FI$6E8M3'UZ24UN7EI--BU;?V)K6G)R:V))6#\R+39 at 6FAC9F9J -M7#8V/V)U=RT@&!56DPY(#9L7)@.RU?>@-R_G!F3&!N("5)8EI% -M/S9%:H!B3#Y)6$E;>GILG$_&S9Z8VMB=75R8D]/8VE63&);8V]FG)Q8:0M24DG16M<8VAB8WMR9S(8.UA$ -M-EA$871L/B4I,'6"8&-H168$:YMN@(9]9F-A/R5?7"4K("TY54UJ26QI+2U: -M6EX#>HU]:UI)26*#83(8(EQZ V:%:F!-:W(!>@%W /Y[AG=@6#E-6F)S:%A5 -M16EOV],67-5("U)8%@K%39@>G-R8#]8 -M36N";D1/GIB44UG:%EJ at G)B6FIJ:VZ >VYK -M:#LV7EEJ=V-$$B5J>G5N=TD@&RU?:@-:N45(>WMK+1A)&U:9FDV37-S;&E;=7A]=G)K6UA-7#9$/S0;/V!B16IH+45;6 at -CEFMK=6M: -M259B7C\M-F!L/TQK8UIB:FH!8@%$ /YG at GUS6#!$8&!:6#E$+6!K:VIR>G=D -M?7=M3R5823DR+5EB:$UB>G!)37IO/S(R.TLE&"UA:G)W33YM36J":S8V46YU -M>F],1%Q6,B4R7D0R-C!61%!@36IR:VEB8UMA259J64UB/S9K>FLE)5IK:V(Y -M/F)RH [&SQ83%IH8#8G:GI@&PXM8FIK>W=I8#\8%14M<5I,8W!)/FEZ -M'IL;G):6DE,65XE+55-=VIF>FI;:&!%/S\V/V ^)3Y,8VMB8E at R -M+3EK;VAH at G)Z 7G)Z64QB:EX_5F]J:V=>24EBFKS5$QB:V)<9EN"@G!:26]O3&A>259)6CY,>GII7UE%-CEC -M23YB>F<[.T1965I636)J:$DE& D;2UA,6ED^/RU%:UMR>G9U:DQNBG=C6TQH -M:U4[+5AN8&-J:&!6<(!Z=T]8:WIJ8#8[,BU)9U],3&)[<6)G:5 at M -M.SD@&!(_;VU)37)W at H)4(!@E25MF:F)9-CLP6$4Y15MVGIJ -M6$1B:%MC8%9<=7U]>W)S:F-I36A5.Q@;6FIU at H)J/BU>??YR658^+6I:7&Y; -M3W%W:$1C=6YL63]RVA64TMC9UI?9F(P26%- -M8UI:8&IR>FT\*Q at I5DU-25M%/DE83%9J>GIF/AU:DH)P84E:8DL^66EF?6XY -M8')K4'MR6#9::X!]8S8P8VMF84Q(:&!?3T6"6EP!:@%P /YH/TU[-"4=4SXP -M:#8V6FIJ8EM)+UN':G)R34V":F)@7#P at +6AW8DE:=WI;8&!8-D0_.S(I+6!J -M6%1::H)]=U4T*S98:VIC<$DP26%))S]-GMB,$E:/A at 2*6B":T4E"2U-641-8W6&?6YB.2E; -M;EI8/BD8#A@@1'IZ5B([7V)B3%QC:T\^27)ZFIK -M:U]):&L[&!@^W)O6C8R;V%%.SY66E9$6F)J;V!:6E9)238_F%0638K,#9(:'3UI;9WML:T1-9TQJ8UIJ -M8W!H36J":F)W:4E/=V]:2U4[(C]836ER=81UFM at 255@65EZ:FAC<(I at -C9)7V)J -M8FYT 7H!< #^6#Y)16=O3%EP83])-F)Z=V at P1$E)-C!Q at FIK:V-K@'=)("56 -M8EH_+2=CBFIJ6D0_36)/1#9-:&]%8&EJH*"8CLR25A@:FIH, at D@6&IJ:4PY37)R9U4 at +6!@9UI852D.#B R,#PM3'5J -M_DH)Z@@%U 7 -M_E8Y6556:$DP8G=I9S96 -M8TD^245-1#DV/UEB9EA;<'=B35Z"BGIK/DE::FM$8#8;-DUB9VUXA6M$0C]) -M8&=:;QL)"45536]O6$5KF)8/C8_4"T_E9::VM:36EL9BT;-G!R7%IF>G9K:VY+1"4 at -EA)36=6:4U6:&!/6F!) -M6$U$:$E/8VI at +3EK=H6"84E-:F]'-TDI&S9)1W-R?7)98$D^1$E89S05#BU) -M36MW;UIG66:"8S!@.69Z:D4P840M/#(V.S99F]8(AM)6$EUG)/:&I,1%I$6E at M6&IJ9&UUBEQC9G*"14A8 -M*2)8:F):8$DI*8(^:P%F 6H _EIH<& M(#]N23\^1&IR>FMR6D]9:F0I)5I: -M+5A%1%E?/S!(24DR.S8;.3X;/F)-G)P8'!C23Y@ -M8DU/=UDK*38[6W.$=WIZ:$187#YG8E]B:F)3>H9:/V)Z=58P/BD8275B7&9@ -M/TN"/D4!<@%B ,PV6%@;/C\_8%I823Y8:GIR<6(_.5MI/C996"U89EA-6$DI -M'39)6$DV+40[)2T_1&]V2S9:>HI>&!@PG\G87)F:#8[ S^+ -M,#];6U8O1&!Q:%8#2?Y-36!P8VA96F]M;6M,5F(_26 R'4]W7SY-;G%; -M+3ES<4LV-CYA:WQN&I9.3YA8TU-:F!)*24_ -M3%Z#>GJC at G)'5DDP8FUB65YK7&9UFE)3T1%.5B$>G);:H*"9G)J65MC6V\[&SYB5DE)6CEQGYW7BU)8FAA6TQ?G=-6G-H3SD5+5L_8F-;:W)B -M8$DV6FIJ6EAN=5I9:&))6X)R:FA/%1):32DV.3]9 at GIR 8 !50#^2T]K<%AG -M63X_6&)?23]-W)Z8#EJBG59( D@,#968DD=/F]R=6A-:W)N3S9- -M>GYH+TQZ at FI:=W),9FUI7C]@34UN238Y>GIF6T]I_G-]>V$8%3=R>G-C34]] -MAG9]<#PI.5]0)2]Z@&-C8FA@H):/U!T6W=[8"TP85LV16MN -M>G at _/TEI6DU).6)837:&;V-$4')U8VMR:T1L241U63Y$/CEC=WIR6&AJ8V9S -M>GIB35A-.6.'9EQ98#8 at .4U$2T5)3()C9@&& 7( _FE%:WI;:F,^.6-B7U]8 -M36IU<6!)26!@6FMK:'-O54EA8F-)8')@+6!G-C(G$AM:@FA%/S]9;VM84%!) -M6EQ?/C94:FYN>W)-1'UV3R 8#A at T8&]),#E,GUN -M46IR7&)M6T]:<%DY9E\M&VMK8VE%6^=R:7IJ*QTM:FYK22V-A<&YW?7(^+2DM6')ZF)B6EA$.TEB.3]9<$0^3 *# /YR.4UZ;VIG.2M;8%]BH=R/TMI8D4 at +45CA'!5-D4_2U4R-C!:GUF7&-R at GIP2S8\,DEK:SDM:XAO30-;ED]9854V+4UZ7DE)1#Q$5CXM -M/GQ?)24!<@&# /YK24UZ:G!,/CY at 85!:?V9J:W)O36)W:VEH9UH_66%:66)J -M:V]P8UAB65A-7UY$3')W238V.6MH24E:8%]<8F]B1$U-7GIB:EQF=8)Z6QL2 -M+6]$1&J(>F9?*0X;66 ;+6A%7V@^&T2"B')B2&V*6EQ)0D1B:EI).SY/8%I, -M+27^16-J:C<_9F-C:TL at +6MZ=G!W;%@I+V]P6FDV(F)Z;F];6"4K:(5W86!P -M:F=5*S8_:G)<14UO:ELR&Q at Y?(1W/S _6& _+2D^669Z,CEB<4E%=GUU8&AZ -M?()P1#Q926%R;%D^9WUZ;%I-23\_:68\&R)B;CM58&%I6DD\26M@@B4. 4P! -M=0#*3#E:>DUW8#Y(6G!B37%M=VIJ8CE%:T]6 -M3&-O;VAFUI@ -M:VMQ8#8E+4]K>V-(:ED8%4R"&$R&!4[8GB*:3]/:6-)-#Q866-K-BFS/F9:1&IZ;F)K&!/;G)U=GUR8%A$-G-X22DK24TP:6IJ>G(Y66-S:2T. 38!< #^)1U@>FER -M9EI-6&]W26)RBH%Z<$4V6G)B:G-K34M81#Y$9SD_13]-;$U61$E;=WMH7&)@ -M63Y::5I_;T0M-D1J>FE$(#EJ at GMF6F-,6G%W:F-I)39B>G)J3&)J4')[8&!V -M.5IH6#0K27)B241B at GI/26A68')8)25$G=)&V]W8#Y at 838E5F-;>H))/V)[=X)>( $; 3\ UQ at 5-EJ WIO3V%A16-W7F at V(" _ -M<6M6-$EI-C!9>G=%(!LV3UIRG=)+3E9GUH26)Z=VMK=V)% -M26MR,B K -M-FJ":4EK>G598'-L8VMI35!H3UES@&M$+4UR:VIR;W)Z>V)%6TDY26AO!#:K -M5DUB2W>";CP;-F!N at G9N;&9Z@': 8Q@;6&DV,%J ;UIH35I9;C0;)V:"?0%H -M 5D _H!B65Y88VY[>F))(!AJ<69N>F)K<%QJ:FE5.4U)6FIJFUK:"D5&" [6&AR1$%UBOZ 6S]: -M8G!%-CPT26)F'M[<$E- -MH6#V$8 -M%3=R>G-C34]]AG9]<#PI.5]0)2]Z@&-C6V)A?8!>-D6"=W4!; %K /Z"33E@ -M15A,<'MK5" 28WIK:W=B:FE,6')Z:#XM)24^8G)W:F%//D0[25IJF at _.24@(&AG1#]:>G(^.6-NF=%8EH^+1L@%39-+2=J -M at GQ--BT[.6MKFY0:G%;8GIB8V0T'39O339O@&YC:4E$/U!C@#^@TDG639).6EP8E4@ -M)5IZ>F)J:F)8+39B9'Y;-"D8($5C6EIH<4E%:7)N?7-%63E(?7-P83X@&TEZ at W);7T5; -M>& Y6&);=7A]=G)K6UA-7#8;)5IR9EHP6V-W=BTT15MJ:T08*6N"=7U[9F at V -M/FE)26E-1'6(:7=K,A at R86A5*45K?&LP.3FMM;S\@ -M17!R:W)<*2 T56$V$CEJ>GV&GIC8$5C at FM/8[MR9E-< -M at GAZ;&YR6EI)54E88F]I)45C:FHW/V9C8VM+("UK>G9P=VQ8*2]O<%II-B)B -MBGIK8&EK8#8.#@$P 6( _C9Z@&!9+2FHY+4UZ?7IZ/RU:>FM:8E at _241-/V)K -M?6-9*SYCBOZ-BGML36)816E;:X%/.6*#=GMI6#8\6X-P-A at 8-H)K/V%H6DQ? -M8VM8/VMJ9HJ/;GM:8&MK<6 V)2U/:WMC2&I9&!5, at G-9)1M6=79G,B4@)3Z" -M=U4"%0#^26I[@&YR:$5 at 1#LR+59BW!)*RE):VM;84U at 16)J:DDT8VA/>HUV -M:#E,1#!I8T0@(#]IG)P36)J524M6%]$ -M&QM9>GV%?&IK/Q at I<'IFG=)67J";GQV8%Y9:G)N4%@\26):6E at Y6&%B9G!+'4UH.6:1 at F M+55)86MF -M-B V8WF8^'5J2 at G!A5G!I245%36YQ22]%:EI;>WIO -M3V%A16-W7F at V(" _<6M6-$EI3S9K,$1:)39W at P$M 2< L4E-6FE$2'IR:TDM -M+4E>1&-W34E-6F)96W)P+5EW:U\V+4E?/SY)6%@R(E]C:WI;-DD#EDT/DU; -M:6]A23966FMK1"TE5I**@FA)7&-)/DE;7'5W6#E@,#YR;6UJ>FLY6G=C33\I -M*3YC6E0M.69A1&]%-CL;&TR" 6@!/@#^:$UC<$E%:W6'9R4I5%A%6G1$2&A; -M7F!%7GU)37]R:EE$5DU).SY)8#\E86QZ>F(V/UQ[EDI#@X^@GUZ=7V#=5M$871L/B4I,'6"8&-I168$:YEQFI;*4E:6&8I -M(%EJ?862>FEG9F)%6GMB7&MO35 at E+45%4&V ;SE-H-W24E at 7T5-:%E9:&AC8$E/G:#W=A6W5[8UHM36)621(837)F=9**V%%BH!;/UIB<$4V/#1)8F9R6&QN:V%@84MA24E4(!U%>&)B7UA)-BDI.0%H -M 5H W%8V+4DM+4ER at WI086%B8%E at 8&-R8FA at +2U;?W)H8$]88VIH6DE)6&]- -M+45BX*":V!)25IJ>E8V/TE%35IR>F ^5FIT -MG)OGUR:FZ%=S^ DGH)[6T0R-EAJ;W!R<&%$8W)83W*&@#\V27%A-A@;8&Q$ -M(#)I8#]:3411;H,Y8G)C,B Y37IF86EN9T=RBG)5;G2#8S\Y6$D\56!I:V$_ -M36MK3%QI+3!H<&!8-BM):VD^-C(M/FJ";S8"/P#^6%A)-D1-36ER=7IK-CY8 -M45@^:GIF330\-T5Z>FYC,AL at 8UM%8FIJ;FQC;VUN;%E);W)J;EI)/SY)6G*" -M at G5KWIR63E>56!SW1$*2U;:#\@,EIW6UM>-C!( -M9EA::FQ/-D1)GUU:FYK8EI@ -M8VIK:F)1>G0;27)R:G5%15IPH=P;&Q/:&QW?EMA.5MW:4MA<'=9*39%F)-24AZ>V!;)2!9:UA)/C\V R"(+5QR;FIJ;FH#8OYF>FUK8W)W -M+4M:3U%V<&%@3VIF/V%K14]I1#]BFI66T0E-F!I -M:5]B8G)R;UE-6W)F9F],8#P8#BE)6&)O6V!)/SY-G)B22TM1%E]@G)? -M6%9J>VM6.T19:%I-6%E)-CP\,CYB;UE<>FIK:V!-:DQ9>W=Z36!A345:;W)W -M86E:6F)B;&MH6%EP84]B>G6 VQ$&S!S<%E+,%MW:VEQ8$UF24UH/S9$)2U965 at _6W)K:&%J>G P.7-W -M<$LM.5A;9W)C3UMI/V)Z:VMJ7F9_6T0I)V*(@X* 3TAR<#(2'5EJ -M8UY$/F)B=V]625I8.4E at 83(@+5E8/S]88#9%9UIR<#PE1X-R<$LV6'!C8VM/6#(M W+384U-6#X_:&-B;6MU>F(R%2]WB'I/.5I,;VMA13YI8UAH>FM: -M2&IZ at W%%66MM5H=S(@-&!H8$E8/Q at E2UEP:U at E-G-S>W _5G)\:4U:344_:6 ^)14I -M25@^1&IZE!96UIN at G5B35@_27IZ at W!- -M85M%/V!8.6)F>XAC)0D26H-W8#D^.V):84U/3T4^6GML8V-H>HIL,$AZ=7)% -M/TEC8F-C:6$M1#8I-DUUBGI/4'-87EY5]"DM5#L8&RU9 FMH7CLV -M86!H230T/%A98VM)+39;(!(V:%I86EMN>W);35 at V6&YUB&(T8W!824\^)3 _ -M@)%P*0X827)F:V$^/VA98VQA2T0V-V=A8&MZ=8-C-D5[@G=@/SE)87)Z6FDV -M/SXM_C9-8G:"6TUL<%MA:5Q)83\R+39)6F-Z at G!826U-+3M$15IK>W=A6'*#=6$^/EA:;G=R:F I$C]/6#X_240G8VE86%!F>H)W30%: -M 7, _FM;8VIZ:U9B>FM:8W)V>&!-3%48#@XI27J2A'5R:EA)28B#DDT+5AK -M7G)S/DEP8F-K83]97CY915AB=UQZ<458 -M11U,:G)P1!LE8GIB45A8/AU8844_,&-0.2U) V"K6V)RW)B/UAA36IPFM88G)U>F]-8%@;"0X8-FN*BFU>338V1(J%@F]4+2U,;TPW5E =240P -M%1@[1&!P8W)R;VMK6"T;/WAP.6)U9')R3#()&%F"=UM>6$5),&!O.5AA:6EB -M6#!::#]A24U97$UR>%M98VQZ:D0I-C9C?7%;3V V/Z!Z;FAC624M25Z(;CLR -M6W5R:V-O-BU)6$54/E at V(!M%6P-8PDQ-6V-C:6-926!Q:WIR7G)K6TE/86=R -M=69A8#])=X-J9G!R6#8E/WN";G5R:F!>)4)@6$D_3'5N6F- at 1&MCFA at 230I6%IR;V!-:&EC:FQ$369J8P)[ /YF33M-=GU$35I,-&!J;7-U -M4&IP,A4.'3QO at HUZ12TI+4EZ>()UG=$.7!I-A(V8#9/15AI340;/UXG/T1,9T1) -M;')C22<_F8M("5:>WMH25IR:7> =V!%3UI) -M8FAF+0X8/TU%/DU)-C]88%I:6$E@>F)KG=Z6SXP8"DK/SX_-CEJFIB8E8^1$DY -M:6]$16)K6EQF8V%?@D11 7H!?0#^=7)816IZ:$E)+1@^54U[@%!,F$R(!LV:W9V:F9R>H* :D5;23E):&\P)RE86%I at 8VUJ6%M;1&YF)25B -MBG(_:H5Z<#8M67I[8"4P<&T;-FA at 839/*3YQ52DM27!;64]B:FD\,DQB -M239$2S9)8V-B<$D^]&E(&IP/S!S;24V640P8G%F;GIJ6TE':&%82TE/245$ -M&A1<'=R9U45)4U:.4E;6V)V=RT@ -M-EA at 6E@^&T1K37* :6%@15AP64UB8UL_9H-K8V)P7C(R=$Q$8GMZ@&-5-D5A -M85AA:7!5-EIK8UA%8W-O-A at E86]J8%I935]))6ES<6)89G%/-BD^9H):1 %J -M 7H _F1F;FUR6U at E%2T\/SXY<(:(:UI:9CY$;GIJ:7)A/RT_845I7&IK4&Z -MAGUF8V$_)5]<)2L at +3E536IR:UY)&RUC- at D.'6IZ8W!$68A+/%M:<()A.2 E -M/!@E6&85/G-'7UE)H->8FT^-D596VEK8$]C -M:F)I/TECF M+44@%2TV"25@ -M/C Y8&YZ6W!K530_6T]F at VM/>HA[;G)925E4)15-UQB=5Q:33EK at FI, 40!:P#^@W)'6G%C8F$R%1 at V -M/CYF?75K+2TV<&A-=UMI=V$_-DQB6E at P,G=R9E-<@GAZ;&YR6EI)3%E>)2U5 -M36!W6TP^8(" :R4)-GI]=G)B at UDP.6IZ?8IK/EEA-"DK%0X;8%@V+6!W=UIR -M:&!@86M;6FYI,&.*AGIJ8#Y%/A at .+5]0_E!J9GAR<7=S8%59:U\M/V-<;W!F -M?8)U>UEM>FU;1#8_:%@M+3E<@H-,16%%8VE85EE)8&IR -M=7)O8AL2.7IW;G)B3S])8X)B10$E 44 _GI[159C15IR;S\Y)2U$8W5HGIF8G=Q351L>W*">V-F:5Y)4$$@,EA at 1#9-9G)B35E96$UZG9P6V)J -M7E]Z:T]833E$8&!:6 ,_U&-RBGUR:5L_36-Z>EQ853(;)VMR7CE$8FMC2SY4 -M/RG5BG9U:DQNBG=C6TQH:U4[+5AA34DB/V]R9G=/-DM-;8-R -M9FUW33EIH*" -M:UX!1 %4 /Y]BGUL4&=RW)R338_+2]JG)[VI_=S9K?75Z9C8V6&IH6DE)6#9J -M;75[;T\V6&%P;'):/TEI:4L^6FM at 8%MA/VA4*2U@,B5M669Q26.#:UDV/%MZ -MVMK9R4V5#]6&Q at P7T(M6%IK:T0M -M)5:2BH)H6$D_+39P<#EHBF at 5/FI<;U@^52 @1%@Y6')Z>W)B;&)@7V-:-BU) -M83])- at X5,$5,4&1U=7FM>.R E_CPV6W$\)5A- -M:$E$/"5+ at W]/.4UB<& G24EF8UQ0:F<^)3Y/ -M;&QC238V379W34UJ6G!@8U5B5C8M340R:$M%>W%L at W):24D^6G5ZGIW:W)W;V)+/"U%25A5.3(V*2(^ -M1%IN at V$T("5821L817=N:EY/:&9U;VE4.S;^23YA>F@[-DEW8#L@%2UO>UD@ -M+6!S:#]H:V)J:V%J7U!G5C0E'5,^/DD^-F!H5C1-23 \1%ISG)]/RT_-RTY:W!5.T]F at GR# 5L!.0#^+5AN>FUK8D]M<#\M8H!P/CY) -M7UI9639-FQR>GIR:44E+41@<7!A/RTI-CD_67IR@%4R -M6&9;1%EZV at R%1 at M86\\#AL^:W)W>W)J -M8EYA:DDP:UA85#L[)2U$.S9-:U]%63\G,$E/;'- at -TE)2V.#@FIC86Y[6W)K -M6D0 at 23(V=6);:6!J>GUQ:44K)4UR>G)C;'-C6V)I;'9U;6,G1')?6F%6338E -M-S8K+4]Z=5HY8H)0>@%H 38 M1L_<&YF=7IB4& M%3!J@%])5$5%5CX^16)R -M8DLP8$1J -M=V!A1#8#/]588V=)2U0V-#9%6%!)&R4M/TQQ at FU<;&Y]FYK:6%$8&EJ;F->:$UN at FIB6" .*4EN9$UH138^)TE81%QR8C9)8EIH:W)F -M84DY8G)C,B Y37IF86ENWIR -M_FQ at 6&MP9C0I)2=8:4EC>FD@"1 at I/T1F?7I;34U at 3UA:245G;TQ9<%X_23]: -M:6!664D_7DE88%]$+3(I-C9$;FI:GEQ>,')J5C)!/"=JG5R:FV"<%XP6%A+:W)M??Z)WMF -M6!@8+4]A<'YP-BDM-EA at 8%!O:UA%6CE/;(-R6D5B:&MH64E,6EM)35HV+5IK -M<&)B6#!$6%Y56&)98(" 6VIR16]J64E95F!-1&)Z:4E/1$U$VIZ -MFI5)3(Y:G]B8GIF;T0I/VIB5C]K>F$M1%8V8'-Z;6)-:')8*2]8;CLP8()Z -M8$D\.7)C)0Y,=6M)37IZG-Z<&!8/DUF-A at V:WIR8U\^.6!X -M<'1 at -BUU@G-K<&)R=V):23E6<$DT:G)R:E at M)VJ)@F)654$V/CEC<$U(:UMF -M>FI6:&@[+4DE16%R>F at E#AUB;GLI at C!R 6,!/P#^*1L^;WR"@GIF:UMA64E% -M8G6&=4\G/FMS:W!RW)C7&YLWUM:&!$6EAC8FERAGU-("U; -M=6YZ at H)S:F R)6TY%2UA35""9R55=W!%65@\27![;UXR)3EB at G!J9F)07FM) -M6G5C8GIN8W(!L_)1U@>G=R -M:V]U=G5F-"LM3VE%1/YZBFDP17Q[=G)I3&)R26%/6UIN"5B .&UEZ;6IH47=A/D1):%A63%!B8VEJ3UA8:V$E,&-UUF"87(!:@%$ .X@/VA;@G5]9EQ;3#XV3VE99GUZ6B(5.6)?;H.&@FM- -M1#)H1!LM/D59>GEXI&Q45- at -:_F)K>G5ZWUS8S\8&"TP8G)%34U/ -M8W)Z>W=J:G=>,CQ+.45P:UM@:7)P63]/>'-R:F)-7V]J:FM09']ZF(_5FIB65],1W&">GIO:5MF:VA>/"U$.415 -M(C]P8E at V3WQZ<%A98EI@/S)8:W-5*2TY;8EL338;+69P=W0!<@%@ /XM)V)C -M6FMU?(-K/EA6'3E,F])+1L2/FZ"?U0=/$UB -M7G)K9GIZ14]>141$6VYZ@&(E3%I%27#^G=S<&I at 6%5;9GU[83X^4'I\<%0I&"5BA7UH+39,66-L=VQO<75Z -M8EAH9F-@/R!%:#E%6H*"1#X\& E$>GI]@WIA)1@^8W)P/C!$7CM):&]F:WIR2V!%+3YW_H%N8E%:=V-86GIZ-"!-;U42#A at M38(^)P%, 40 _BD^66MO8G)R>G)H5DU>7#!$@7UN -MH)Z8S(@)3!@:V8V-FAR9CE$>GV :4]:8G)Z at DTY -M8$DE&T5RG5P1"T_7#M4-BU-:&MA -M2UIC.2UB at GUK,ALE6()Z:%A;=W-B52 V8$DR+6%U53PM-UMQ7C98:F-),CD^ -M23X^238Y7UEJ;F]H8G)]@&<[-F!G/S9?;U0P:G5R6C ^6$1,7SEH36%%8FE+ -M<7M@*2DR25B"6& !:0%> /YH1R -M1!M862&8[.UGH9X)]FI816)P6FEF-EM6/" Y;UM%25AA<6@^-C!::&!4+39%.SE86&!B -M9FI at 7EEM>H)B84E65BTM6'9G/G&">F(#/HE)8V V5F-?:T<#8HEA6$]@35IB -M7VL!> & /YW6TDR$AM@>FQC8#8E6W)P246 :$U08" ;6H)K3U9,37!_<$U/ -M?W<^-FAB25A at 16-K8EI;6VYZV\M#@XP8GM))4E<,A4 at 6&ER=V-C:VE)3VGV -M:W5V?'!?52 .+6)H8W-Z>H)R8TD_3VIZ7VMH36%K82D at 6')R:UDR&S9J>FUA -M6&%;15ES65MH53L\340P+3YC<&M?/S9>8H!O,BDV/TE665IBSDV:H!K36!(8&1, -M8')<:FMC7F9Z+3!>1"DO15M;>G)C8DE%6FOM8F)F>WAK7B 5 -M(%EO8G)R:6!-8%M86FIR:G):/DE18$1):VYK<4]$*39K>G%B8VYA/UAF:5YK -M6DM88$DV(" _5F-R6V!H36IJ23(V24U624E-9W%Q(!@R/D5: -M6CXM6&-B:W*#>F%::%DI&#EO7%@[/TUK,#9B -M;G)H2UA9:&QH22TR.SQ)6UM,9G5O6$4^6'"\7T5@@()V9U at T,EER:W5K;&A@ -M6EA-3VAM8V-:-BTM-C)6@&)>=T0M("5@<&E64&T!<@%B *]Q8EIB.Q@[6#!$22TE7FE/3'N" -M>FI::W))("UO6C8^6&!03#LR)2]-6DUA8VE:3 1R_EQK36-K8%4R-EXM8%MB -M:FQ)& XB6DU;51T_>GQF6FU at 8%QB<'A[8U])86%B>W)FDV.6A: -M+39C=V8^,$D[ R74+6%J<'MI36)N>W)L6FIZ:V _/UE)8&-K:VI)& DR7BTM -M( D_F9>>FIN<#D.)6)O:%D_ -M:V P22T2 TG^66EK=G)[=V)A/QLV36!?67<\(!@B8F)R>FA>*0X at 26QC:GIO -M-B V:7N">FA:23\Y6V-A=W-5-#E8638V539+,A)%:V-%,!TE16MR8EA at 8F)R -M<6UW8S8V52T5("4P:GUZ=6YW/AM,BHI[<%I865INF _-DDT -M'0X;24Q:>H5:/UZ#>G)B:WIU:TQ%541836!R>FA>,C]H)0,)_B)B?V Y7V)H -M:$E89G)?,$EI8&-O4&]O/S1+6F^#:%MR:W)K.Q@@1&-I3UYC6# V(!@E&R(^ -M8VQH3W6)>UE$(!4M;FE;8EPG#@Y636=J4&M5&"!88%I-W!A -M84E%:G![B&]@6&!?-BU<6E at 8#B5 at 8FEA1#0G1(]J34U at 9FIR;VAN63D# -M&*(I1&)B7&MS5!4G9&UV>W)K;VMN=FIB6D5$38!K5#)$7R(M 6(!;0#):V-R -M7S]->GQS8EA$6#!$;"(P;8)Z8&-]9D5K>E at M($F"F9B;'IF>GI@,"=;4QU->F!R;H!H( ,5_B V:X!C8$5%;G!%8'%8,DEC -M6$QWB'IK1" M/V-[8#E::WIO/"D^6$589&-P6F!85#(T*2D2,&-,/DV"?VE5 -M( XE<(5P6V!>.Q at M66--,%A>&Q@\66)@=TLE(#MC8V)R>VM>EHV-DER;FYJ:50K"14G+15)6V: =85]<69F>W)9 -M:8)W/B!62"5):DAC6WIP,C \.RLE37MB63\^9F\^6'!H1%E at 8VAF@X):/CDE -M.UAF6"TM17)S52 Y;T4_:FYZ36-P3SX__C\[*RU).S(\;FUP62<8+6:#=UI; -M6&!!%3Y925EA:%4\1$UJ8F Y6#PT.45:7DQS8W-4&Q at M239-:FYN8F958VARF)<:W)R;VYR:V!83UMH -M8FIB<&IJ7&T_/U at R($V :DU:36MI.S]@=5 at V,$UP2')[-B(V)2U)8$DT+55L -M at 6]$27)9+4ELBD5%;5HV1?Y-3%Y$/TE$.6](:&!$1#YJ at X)L8F)R;#Q+6$1- -M6UIO:FE::&@V&TE>+2 V6')P6SEF at VM@7&A%/UAH65A",C]C=T at Y3W M8F-O -M51 at 2*5HM-F)Y;UYK3TU9:7-[6#0G-&%;.6J!;'-R9CP@%39RF9B/C]$8&!,16-R3"EZ83(W26-/2W!K -M8FIK:F]Z;6I/:$D8&" 8%2 V1!LM>WI96G!/9GQU63]B>UA-EIJ -M53Y:/!LPFI%24E9-C!<:F-R:UIJ>GIK -M8VU9/#)$1#0T25P2(&IW2&)]6F)Z@HER/B4\*25C10X.%4E-+41Z>FG: F):7V)LC'I:6%A)1$EC<&]K8G!P8%59 -M9D1@:G);3'J2BF\\1$0P6C0##OX5%0XV>GIB1#1$:%E88W%)/D]I5EIO6$5) -M1VYR6#]:>F\I%2U96#D_=E8^6"TV3VQJ>GIM/REB?TT_:3Y$F)%6DE%<@."GVMR;1L_3&)I.5 at Y -M3V!B=8-S7 at D816YW8V-H3WIS14P#6/Y at 67)R7UER'!%16A9:VEH:FUZ5"<@ -M+5I3/F)-154M%2U,6G)S;S8I8FDM,'%8+4D^-%]FFM@ -M8%]O<&!88UDV-C(V8&*R/D1$-C)J8U at R,BLI369N8UI8:G5F at G5<+1LP47IS33D!:P%R (1UW!F-C9;:T5H8EI@ -M-BLT+3Y68F \26!@)25B9BTG1$]F>H!R8$UBXIC16:">FMC8S PW=H9FI985 at M$B V26-$,&)M9EH_7V8^- at -:_DDI%24M27IR6$L_6')Z:F ^13X8 -M#BU?4%!J9GAR<7=O:%XV-CPI-EMU;F-D?8)R:VMI16MMG=886QJ/V)O4&-%25LV24DW/S8V -M3VE5-EA-+25):6YVB8)P3,M-8VA)/DUI:G=R8T]W:4]C:7IL11 at 5+6!B:')P -M<%8^3&I/568\+3\W+3EL=U4[3TU9>HIP35QVA7UZ;#PE;()U=7-O8DE):G!) -M/DT!7 %R /Y9=VIF>FI;:& M("D at -F ^)3Y,-D0\)4QJ1UIJ;6)>7V!-6SY/>GUR<%A;;'K^ -MU8^65A)56%B66I_8TUP:V)B:X*#21 at .+5MC6V%KA7Y]@V9-24PV -M)3WA:.2]B at WYU6EIJ<(9];6E)9W5M;7UZ63)I>FHV at C9? 6(!9P#^ -M17!<2')K<&MC5CY)-DEC6DD^+6-[;7!-*2!)9#X_7EIL3TE)8#\R4%Q;86)J -M=TURBF)'<&YC:%9)6$QO=V)824]R=FM;:6%)*0D.+44@&U9J/UJ!:6)R6#!; -M:#9$6D1$65L^-&MJ8&-[<6):;'!,6F- at 8%L[6'5[8')C15J!_G)13&U[:U@; -M-E4[-DEH:FMCE at E'3Q at 8%I96WN&AXIW8V!;2S9>7D0M.6Z# -M:B4;,GIR:V-H6UQ]?5QB6'=F:VY]>DPK8WEG+8(G60%J 5\ _DUN6-B8#E9>_YK.2E%GF)W6#!B -M:%E:6FYU9FMK;GIK7CL@)3PV6W$\)5A)6&%C24EKBGIK>G]N:TDE2&-:8G5I -M/SE,:FI6/RE$GAR5EA$@BUF 5@!'0#^+5IZ>C P4&I%6EQF)2TY>HIR63E08EE; -M34L_1&)P7&=13W)B3VYR23\^/UER;UM)35QJ8$E(:G)N@&$V25M-5EIN:EY/ -M:&9U;VE4.S9)/F%Z:#LV6V-:8&!8:HAS3&*"@GII.S!89W)U:4DV,&!H:%4M -M+V!;15MK:6);8W)Z_G)@/#Q/9W)J;FEIF at E#AUB;GMZ>V-)/#9).6EI;'HY+3(R25I)16:" -M at G=H-H(=6 %A 24 FEAK:FY at 2UAJ8V]J:#LI)5EU>G)85F)B6T5- V#^8F)K -M3UAJ7)))4UB7T])37*(<# Y <$D\/W)U=7)D23\_F,#6ZYI8FM836MA)3!C=7)I -M53Q-<'N%C7AC145>/%MJ2"T.#CX\/SDM,&*"A7%R8U4_ 3D!:P#^=8)W6F-6 -M-V)U;FYF;U]-8VQ/56IO6F-B-AM$:FUK669Q5E]P:VA/:G [#@XE245G=TQ) -M9H:(:%8Y:'IR>G(V/UYF=VE5-F-C2V-[>G)L8%AK<&8T1$U-26!@3&M9GII8TE$,"]65EQVBG)C:VMR;FI836EI-"E/8V-K:%E$8W:-DH!O -M33E-6&-0.3D=#CY@=38)%3E[A6YB38)).P$= 3\ BVIUFD^&T5K -M6W)M/C8_;8)P7C!86$MKF-K6C]R>FDV -M/TUR at V]A8%MA8V]@/" M,F)$.3PK+5MW+1 at P,$E:%>EHT)2U);G V1&UO8#E)5B]R:UDT&RU$8F]5)2TG8G)U -M?7I at 638@+3(V:XV#8F9NR5!21TY -M;6MH3T1/>GIY>FIF5FI[:3!;,CQB -M?8)P/CD@)4UW23!?8CX;.6D_6V _-"W5N"2UL?'!]@F,V17AR34AF("4I,G1>&S!9 -M;75W21LV 6 !1P#^1%I$6E at M36IJ9&AUBEQC9G*"14A8*2)8:FA8.4UZ?'5] -M at G);6X*(7UEC8F!68VXE/CP;.6I9/#(V9F))/DEB23]<;FQR82 5.6-K3VJ* -M at EA6:H.#82TG%2UM/C!).2<^;WIP25A::F$_*39F8FMK:4U;F Y66MP-#]B=6MA6$]C8%9A-#9-24UH6"T8:5]I:VIR at T0R&Q@^ -M:EA6:&([&S9P6%A>-BT\1%4^.6%$)41$8&IR;EIP6S8I&S9 at 7&Y,2&YN:W M -M.6)C6EXT($UO51()#B!,6T]4>G(Y+6M]6TUR1#8M-FAR62M86F9ZH9:/V)Z=58P/BD8275:/CE%>GM(4'MR8EIU at G)C -M3V%B6&IR-DA$.SY9:F0I-G=R6TD^6#D_:W)SHII,$5\>U@; -M*1 at E9#X^6#P8&V!Z>G!H6F)I2V9 at 7EIA8FEJV @%2!5:5I8.6)R5#9C?6Q%:V$Y*5A6@%H /)'5DD; -MOYM2TE)84D@#FF$@G))-VN*:#LM26!@9GIJ3%MP>FZ!84E:<&9Z?6@\-%B#>V-C -M7E%R9SE1GH!@@%R /YB8$DE6FIJ6EAKE\R&SEB/BU88&IM>G5F=7))16EP6S9$F-I:4 at _9FLV-E@V8&!)+45R>H)G26-J -M8SY$;TTM25XM+45N=6Y9;GB*:6E>-C]C8D0Y=7=)6%I)6%IF at GUN6S9/BGM1;&M16V)>25MR -M:U at _3$M97E8_.6N"6S]B at F-; 6L!<@#^V9B6UM9/!@. -M-GI]:FE83X)R138E.59J:U]6:FMC;UA9:$E$-EA at .RDR.TE?+39H;UMN:V!9 -M8VMR:5E)8$\;&V)R2$DW+3E%6FUP:U _17U[2&-R:V!<:&EHF)H8F)).S]-3VE) -M/CPI(#9O:$5R at H)U:$E):VIJ:39$H!J34T#28M8>GIR8S8I6&IR8P-8S40M+38V1&-C:EI: -M8W5R:&!825Y:8&)K23 ^.RU$:FE866)Z:UQ]>F- at 6$D_+2 5(FMZ;VM)*7* -M:E\_/DU:6EA at 8V-I-B56>EXV/SP[.S8V;G=C7FY5-DU@:G)< -M3%AS6"TW65MJ8!LM:FYB:E!)/T]K:V _/V!%VM:36IK4&E:8V):65A:8V-8_F)0 -M8()K1%!88SL at -C(Y8G!K65IF855+23\V/T0K&!M?<3])2%A0>FMC9F-8:&-A -M8%@_+5IR:W!J:5D_8%M:6EMC>FEA34Q;9FIR;FQ%46]H23M$8V-S:54M04E) -M1&EL:3\V36-P22=-/S!::VIK8TU::6$V16M8+6!]>GIP2X(V/ $K 3\ _G)L -M63YG?7IL6DE%-C]K:388(F)N.UE at 86%5)3YH141C;V=+36IZ8TU:>FDE+59A -M:5@@)6N#BG=8*2U9=W)@24EH)6=R')9 -M,BT\-C!R?6MJ9F-B6S\[/T]C1 X.-F-)/TM8369K:W)K8V-R:6-8,A at M3V-R -M:V-/26MN8UYC9FYN:U at V+4QB:F!I/SYH:5 at V/X"">WMI-CEI22=%:VE)/T^# -M=V%9:5D_36-G:T4G36Q[8V9J6UEL>GV"<$2"/%D!20%A /YX8$]N:VMA,"E?@HV -M51@@67)C:5E;:2!8:7)W8V-K:4E/:6MU=GQP7U5+/EIH/SE$25IC9F(I+38; -M/FM]EI,;7UZ:D<_52(;6G9R -MEL^2UM@:EDG#B!)23];:6%:9FYUF-/ -M6V)J;GIO/R4^6&)/144_86E%-D1ZAV]Z=ED^=W T/VE;15DY=7)86FMC:5 # -M8)([&"U(?8!S=GIG8UIR>F,_.6 !6@%I /YW86)R=FYR=7)Z=TD;;W=@/F!A -M-B568UMZ?W%C/QLE26MR9EMRAG V-EMR:UMJ6VUZ6UM)3#=$8VYN=75]BF]%26-K -M8UIN/!LR+3Q96VA@:7-F>H)K7&=R>VDY&!(\;&A86V%[@F,V5&%-8GM[8#)) -M65E$/$4_258I%2]Z?%MF<&-8>GMA66M/16M93TPY/F!:7U5-14EC*Q at E3WUM -M;8)N8&!99ED\@BU6 3\!6@#^8F9R=79C:6-:7'I4$EE]6T5;<5E):VA(W B#BUKH)-+41Z=UY: -M9S8 at 16-'65AK_G)V:45,9FM:83),6$L_6FQJ;G5V=8)Z8UE;8V-8>F\M*1 at E -M/SE-37!R6FMU=6MF:X!R+0X.+5I:16MK=7I:/EEA2TU]?5IIGI]>DQ(:V]B7&IS8S8P)WMU/!@M;'IU9DT[.6=Z1#9)8FMC:V]<545835MG -M>OYN:W!:24QW;&%+6&->*3E>:V-N=7)]@F]A/EI;8'*#63LE*2DM/DEJ:V-C -M9G)KH!V@&,8&UAI-C!:@&]::$U:=U&&BG@\+2T;)6."B%I'6V%% -M8&M),$5I83];>GYW7BU)8FAA6TQ?DP^54Q:;')F66$Y85I(:WING-C34]] -MAG9]<#PI.5]0)2]Z@&-C6V)H6'IZ=FA>-A at 8/WJ"6C]0=%MW>V M,&%;-D5K -M;GIX/S]):5I-23EB1&-I3UYC6# V+24I)24^8VQH3W5Z:U%B:%AI8CYA;VYF -M:DDE/VN*@F-B3%YZ:EA)25YJ;G)>12)>8$QJW<^ -M/EE%-CX_26YX84E0>GIF6T]IV$!& $5 ,LM:FYK22$DV-F%) -M.3L=-EA%6&1C<%I at 340$-OXE.6-,/FUU>DU%6T]A33E@H-[6"T_6$UR;EI9G5]>EI; -M85 at V86M@:V-%239%83\;3&IH-DQR>'5;4&MF/"U/=4\M&!@W9E5%1%!U=FMR -MV9H-CYI24EI341UB&D^ -M1VMN-!L^?V8_36IH/S8M/DAZAW(_2VEB12 M16.$<%4V13]57BTV,%9NF<_6GI9.2T_5%MB6#EZ12L5%1M$;5Q;>F)>=V V8F!C:V)) -M5#\[65D@(DEI239;G9P=VQ8*2]O<%II-B)BBGIN;UM8)2MHA7=A -M8'!J9U4K-C]JGIH27**=5I$)1LY9'6&>EIA845B -MAOYZ341J:54V2U1-8&D[;D\_6H)6%14M8%8P26%;8%QF;'M-.5!F9FQR:EQ::FMI8#9- -M=6--/SE%/DE@/TUN:$D[.T at P4'V#V$_6V _3"TE16.":FH!-P$_ -M /YK:W%@-B4M3VM[8TAJ61 at 53()S624;5G5V&$R&!4[8GB*:3]/;&E%-#Q68&-I6F)G:G)K3UA<8EMK6EA86TU8 -M-EAN=8AB-&-P6$E//B4P1'J :TE:@G5523Y86%%F;V=%37=6*WW^?')O6D5A -M84U:3'-R24QKG5C7UIC6TL_.75[:UI+6EE+ -M34],:6-I9BT@($5J=GMS8UI(>GUW36-R@FY[ 5H!8 #^:6-W<#XE -M-EA-F--8VMK8UYB:G)I8SD_6VAB8C8Y16:#8#!B -MW)C3T]J21M<_G5T>V)A:&,_64AN=U at G -M369 at 6&-;,#!C:G)Z=U8R16)W22U-:VYC;&L\#C9U:CE%6%\P.7)C66QJW183':"@&-RB'IB6&EI48)/8@%: 6H _EI;>WIO3V%A16-W7F at V -M(" _<6M6-$EI3S8G67UX12 ;-D]:6D]O6%9H6%YS65Y:;S\8-FA:;U!< -M=VYW:W4^-DUO3&YB141BF ^/W=O:VM8+1L_>' Y8G5DG!)1.I<=7A,35!P7UI;:W5:-D5 at 6%IJ8S8V -M3VMU?7=)-C];FLY6G=C33\I*3YC6E0M.69A -M1"DY:F9T-" E+39K>UM$:W)R3&)P86MQ<&)R9RT_=W)C-C1KG=$/UI/,$UI -M;&A::$PG'5J"U at M-EMR -M4%EC8V)C8408+5MZ=UE:6V-Q8V,_("=0?8-\8U9:.3]S:UI9, X;7'I]@&,_ -M.4AB>EI98&%)+3E1:G)L)QM$>H%J:VQJ=6 at _1%98,"TE16);9WMS9EYR?7)) -M6%M<=8)W6 $Y 6 _B4M1450;8!O.4UR;%M9/RTV1#\_+3YK=U at _27!B:UXR -M("LV:H)I26MZ=5E@VA18DLY8V%%3S<.#C9PBH9J6UXP57IK:&-P -M83LP24106AL.'6*#>FI<:G5<26%I:40#/Y$Y.7!R>EM(&)),')_:VE5*RU)8WIZ>'M[ -M<$E-H6#X!R -M8V9[UM/:&):8UI83S0@)R\Y=HEP<&D_3&M;:VM[@6D_24E+/A at . -M&S]NF)C9#0=-G=O339O@&YC:4E$/U!C -M=89Z:S]F6 X5*S]J6D1K:UQ(>H)R8&]P.3)KV-:>GIK85A8 -M7F(Y1&-J:F%6:VD^*418-DQK8VMO:6IA86Q16EIH<4E%:7)N?7-%63E(?7-P83X@&TEZ at W); -M7T5;>& Y6&);=7A]9G9]?75R9SY)-&-R8F%$%6]@2QL_:$0G'1MBBGU[85B" -M/S9A<'J#22HIN845<FMZ>TDY8UM)-BU)6$US?7UR:FIB7&E>?&Q9.45-67)6 -M.6)022U9:V9-3$5C8UXV:&M6159)+T5K:FM;655)3VMP.3\_2&ML6UD_+2(P -MH=@,&IR85I%6X%/.6MR#8E\W27!F<&$I#@XM8GIZ8V!%8X)K3V-R -M9E-<@EQB9GIU?'I90BU;GIJ;GM:67)C-BDP,D0_8W)]@G9S:UA at 47)R6#9$545R:$5-/CDM37)S -M8T5$6TTP-EQP;%H_.39%8EL^86QN?'<\("U:>GIF8G=Q351L85I-7&A>+5AR;FV"9&9Z -M8#EFX9RF);639)6VMA-TMAHUV:#E,1#!I8T0@(#]IH)N?'9 at 7EEJG)F:F)-8F)@6F)J21M)84QR8_UB6EEK8&-F -MFLM%25C>FI)17-R8V-J:EEH9FMK&!(M7&YZ;#]):FYI8$UF>@-] 7(!80"O3TQO>G]@+3M> -M at GUN:V);7EIJ;%M at 6D]86DE,8#X^6W)L9E45+5PY6H.*<"4;2W #=_YC/#=C -M>EDT/DU;:6]A23966FMK1"TY6H**@FA823\M-G!P.6B*:!4^:EQO6#Y5("!$ -M6#E8GIJ -M34]RG)P9F!-7UIK:4DM,CD_:6++8G)I6G)U:"TE16-F -M>V%)36--6'!M6UI$:GMP3TUB:UMB@%J )!;1&%T;#XE*3!U at F!C:45F!&N: -M<7)K7#D_6&X^+3]::TA5-#0_-D5F<'W=A6W5[8UHM36)621(837)F -M=9**9RD.#A50 at G)B=8!A8ULO3VIK8SE8;& \&S!S at VYV>FIK:V-J:V-8/UA8 -M53]5:$TOF%913E$;'IU8DD2+6:":C]BG)OW<^8F]6*14 at 1')96GI]=S0##OXV -MFMB>FMI23([.T1:6EA>6FI:,%@V*39%;U]$2TE- -M34E,34]Q2RTV84UK8V-P/U%P+0X.+6 V.4QB:6E-16MH16VN;6IZ:SE:=V-- -M/RDI/F-:5"TYF-N9BDV17)825MQ:$D^23XG7T0M -M+4E%8FQC6EAP<40@'31>8%M;8EII-BU68#9%4&V ;SE-/S9)8FIREQ>,')J -M5C)!/"=B:V!-8&]:16I:+2 V3W=[:&!:)S#^VYL:'%F1"DK6&-C<"4=1$E) -M8FA0;FQJ84D_65IB>&YZAW!L;$]H;'=^6V$Y6W=I2V%P=UDI-D5RFI5)3(Y:G]B8GIF;T0I/VIB5C]K>F$M1%8^6FEC -M35AZ8$UC32TI/TAQ at G=F8395_G)N/T1 at 6UA08F9R:&.#7BU)2UL_.7%R:UI9 -M6$U-.4V";EIF;EYC6$0G;F V,EAW:V)B6V!H3#YI83XT8FI:3TQJ345)/TU% -M36!S>H--4XJ"8F- at 23L_ -M26F#;$DE,&M[/((.#@%6 74 _GIK6$5B>%H[/UAC86M>54M at 8$AO6#]-<&$\ -M*6EF7EIF at WUN8W=J8EEK at F-F,C96:6F!G)R:C8; -M&S8V8HIZ7FEA8_Y_=T]@6F%835I>:G)DA75:6VEO1")$<7-:15E-839$>H)B -M4$U at 6TUN7EI--BU;?V);645%6EDP2VQ>-CE$86A-35A+6$E8-C!):GIR:DL_ -M6%A@:7)A35IR:T1<:2TP=WQ;6#8K52 @5GIZ14U]>G)R;6DM545K at VM)&SYX -M>DF"&!@!1 %J /Y[;$0;,'-P64LP6W=K:7%@369)36 at _-F%$)2U965 at _6W)K -M:&%J>G P.7-W<$LM.5A;9W)C3UMI/V)Z*R M.UIV at F9K -M;E[^8D at P8TUC8%M/6F)JFE++3Y86#Y$538P'-J8EDM)4R(844@*40I&#ERFM-7G-P&RTP8X)K1!A)@XIQ at EA% 4D! -M7P#^,A at M8%@^/UA at -D5G6G)P/"5' -M at W)P2S98<&-A84E09C]:8E8Y*2E/6TU;>GG)A.4EO63]:>H)M($AS9D5B -M<$4Y6%@[>XIZ:UY51$LM)2T2&V)@-AM$23]W8UE)/UMK at 5@^8H-V>VE8-CQA -M=VD\("E4,B4M3VIF at 8-P.3YR>BL8&UM_6T0I)V*(@X*"@ %/ 4@ DFIK+2W _5G)\ -M:4U:344_:6 ^)14I25@^1&IZ%IO>CXM8FI1=4PV6#8_8&YZ?6YXFMJ -MF)W<&)I1"D2(#Q9;U0;-FE;:VQC6#E-9H-+-FJ#;GUS64E8<'-K23(T854W -M/$U96GJ$52DM6#L##OYJ -MV);/RTP<'55 -M& X;1$DM&SYN at G]4'3Q-8EYR:V9Z>G)L2S9B;G),1#9I8$1H;H)Z4%E)+2=I -MB&YU at DD26G)>3"VUNF-+/V-U84$T/DU;:6]A23DG3W6*=EQVG=)67)];GQV8%Y9:FYK6E@\16-B66Y[<$DI -M.6A))PXV:6$M1#P5&T1]D@%[ 4\ _DUL<%MA:5Q)83\@'15C8F-Z at G!826U- -M/RT\1"U(:W-R63]86%YS>V,V55YZ at FM;<5M$GI]@S8E6WIR -M6"4 at 1%A6/CM:=5Q9?_Y+*45P+5E$( XV36IB+6=W -M>G5B1$UH:DU$86]R6E9P7SY-=7IJ6S8R/VI]?6MMG!)*R!Z?V P/UYU=6YK8EM>6FIL6V!:.6AN26)Z:V9Z>FA)/UE)*0XE6FDV -M-CX5&"6"67T!@@%; /YC>G=A3V-O8VE%+3(8/SY0H(V-FN">F,[%399<%I) -M87)C1'+>8S8^:#)[<"(.+6MR;F!H:UMC:VUI2#YC>G)@/B5B=7UR33)%<&L^ -M-F)Z>V!)>W=A6W5[8UHY9DE,;H)U:F)(:VY;65E;8%@V+3DP3&MR8UY5=&P^ -M)2U):G)J8VA%9 at 1KGG%R&T5H,#EZ=5QN?7)B24]))0X826$M(AL;.458;@&# -M 7, _G)Z at GAH8W-S?&A81"D@/DU-;7IR>GIR6#=)G!@255%3$U- -MW V+6)V at GM6.T1B;T0V3')R:%AB9F]C -M;GI[=R)86"U9=72!:UIK8C):8VIK6$E<6$M88$Q9<'AA2QL8*3]C:&)F;2U) -MF%9>&99:$E%:&))6&!%8VMB6EM;;GIR:DD^3&E@:7MH.R<^ -M+2UPBH))(DU9)2U)87)B/F-]>FYH*14T8F9K;G5U:%O^8%98:7-R;FDM)5AZ -M?5Q-:V: ?6I:239-:W)R251B:WV";VAK8VM-241K8EI)8#]:3411;H,[26$V -M2V]JD]-8E4R+55Q3S@%O 4@ F4MB34QR8DAGFM5/!L@(#]A -M2#E%D]$/TEC>WU9(!M:>G=-G)K&EL=FE815MG>F]%.T1I+6!;8FIL21 at .(EI-6U4=/WI\9EI at 6& Y+5IZF-I6CLE27=U;VXV+6]K;%M0;42S)T0P&VAQ -M9D0I*TEA8V!)/D5)26)C8F-$.UAC& D8+4UN?WIN8TE+9VI><%@\1$M5/"5% -M 7(!8@#!G=:3&AA338#+?YA:G![:4UB;GMR;%IJ>FM@ -M/S]926!C:VMJ21@),EXM+2 )/W)M6DU:6%@M&T5R9DUC.T5B>%H[/UA at 8V-> -M6$M at 8$AI6TU915EP.QT=(#),G)R>FE5/SYI:#Y8 5@!4 #C<$4P -M8X!B6GN*@UD^25AA15AA3&MI6%A$%0X;@8J"=V$_-BDV88B"=7)F:T\^83]- -M<$DM/VIO-AMP at WA-.6ER6#8@&RE)3%IZA5H_7H-ZG5K3$551%A-8')Z -M:%XR/V at E PG^(F)_8$5835 at R*41J2%A:8H)O6EH^-C])24U/22DR3VMO8$0R -M-$U-13P;&S]Z=7IR1!@@6V @17)@6F at Y16!V>V(E+6A96F)6.2DI3ULY6'"# -MA8);26!88&!>H:*@W=9*0X5.8*,A'UK8$M9639);&A987%O2R5O -M>G-96&-F8#8@&"!")TENA8IKF9Z>F P)UM3'4UZ8')N@&@@ Q7^ -M(#9K@&- at 25E)-DE?1$M,68-P;&M)56%C8TD_:5P\1&-ZH)Z8$$[4& V8'=C6F V)UIUG R,#P[*R5->V)86$E@ -M241-15E%18B*;F-(25MRX')@.5!I345HFI98#9,;FMI/UYH37!U51 at .&T1)/EEJ,#=O/B)CBGQU8&-K13M$>G(V -M27-K:UH_+2LE-C!%8$0E)39J=6-A8P-9G6AJ -M9G-@& D))7"*?'UZ245C9FIJ:38M7H*&:T5)/TMF>FM:6#P8)S @#BDV/DU; -MB'IB7&MRG)8.3]L]&UR;DE;645::FM[1!4Y>H""<6-8+14;36\^88*",B =2'*">G-F S:)1')[:V-B8VQ% -M 3P!3P#^:VI>03]97V. ?6YI85M84&II-DUI6DU$2UE925E:8G)N-C0@)6*# -M at G)W6#Y/345:<"T;67U];TTR)39J at W=),DD8&" 8%2 V1!LM>WI96G!/9GQU -M63]B>UA-EIJ53Y:/!LPV]$+5EA:%Q)83\I("E) -M6V-Z at G!826UP33ENAVUB/SP at +41NAH-W8&$^-EEB15IO8X)@-@%) 6D _DUB -M=W%)13YB>G5K540V8XB 83]9/#)$1#0T25P2(&IW2&)]6F)ZG5O1%9%6'!H4%R*BF9%,B4E6&=M9G=V6#9;6V,#:*E)-#(I/CY0EI8 -M7DE526-P;S8\7F$T&"4B2&I-:U!GG*"62 !+0$^ /Y$-TQR840@)TDY.5IR:FUV>W)> -M:VA5,BT_6FIA,B5-F))6&!@:7%I24M;2V-H,$ER63)R -M/UYM.QU@?7<_&S9B9C8V<&9B6' V -M(#E?9S9-W)F:W-[26)< -M8S8I-F!:8FAQ9FZ"<3LM at 8-R3T5,8&IZ=TU-;UMJ:4]:>F8M3&MC8G)R=6MA -M7C0T-D]O:EI,=TPM36)B6E%BV9MB%D at .S9-3$UK;G9P:W)R8V$[(CEB=8-R6%A[:6]R:G=J:W!; -M8()B8@%9 5H _G5Z:%QR7FA>,%N!>V$P6FYZ?6)/36N"=UMJ.41K -M>W=A17*#=6$^/EA:;G=-36);9UM)269Q7D5(8EIBH)R6$DM/TU8-D5;3%!9WIK53P;(" _84 at Y8UMW>F)A52DM-F*%@VEB>G5V:UIC9G-P6VR":$0!80%C -M /YB9FYRW)B/UAA36IP36!;8&E;8&%>:V-A16!).4]R8U8^6&!%+45J=7)G6S\R1&MF -M8F9N8E8^-D5]?79H14]C:WAR?7A)-FAP34E)1&EO.6IZ-QM)@EO^6D]-:DQ9 -M>S _:WQZ:S!>/B=:;7(M-FEM;VA)/$UZ@&D\/&%C24AK8UY$:6%)*V-G/D5O -M24EK9AL8/W5;36EP;TA%.4=ZA7IO/TE6/S(Y6EMI36ML34]K:VYI8&)F/# ; -M/W=-+3\V8W)-15E%*1 at P;H)L:WIN>G);6$QH:6%K at G V 3X!30"O6F-!8WQ- -M-BD8,'* 9FMK=7)B9V%)65E<U\G8')':F)%6#8^;CLP7(*";#!H -M1!@E38!),&IR8EQ at 33]B.5E;24G.:%IGF!B6"TI-EIF>F-Q:V%A>'%%14U/8TM;54UZ838M)4E; -M/S<_2S8.&$5B15MR9GIR:&);66%A8W)H 3X!- #^,#X8*W=C/" 8&U![8V)B -M=7IK;VM-/S]86SXP8"DK/SX_-CEJEE(8V]RF1N&A)-DM at 6EIR>FQR84U83&=937)RGIR:6):669Z>FI8 -M1"\V8W)@:&-1@%\ /YI/"LV86M95C(8)4]K:V%:8FY^@%I)2VY[>H!C539% -M86%886EP539::V-816-S;S88)6%O/!4I/SEF at H-]GIK85@; -M#B=<:W5H/EYB;W)K7F96&T1U=69/4%M%.4E-,$1J:4\Y22T5*1 at 5.75W-C\^ -M)T=01%;^34UC<%A)3SE88G);'6M];E at I("UGBG9L:38E-FA::')Z;V=86VUW -MW5R6$E)-EMI6%MC -M35F&CG),14M:=VE+14]I:VL[("5%6&)]62LE:7!+6#\V.6EH14Q%1$Q8 at FE; -M 6,!@@"]>F at R+4U:6T]5-#0^:6]B6DU9P-C UO^66!K?7UZHZ*=6MS<%M):'1,:&UCO7)[6REC at WIR63E>56!H6UM at 65ARBGI8/$E$ -M:X)C,$]Q8WII1"D;-FEW:3\E16!%:5D\-FAK5D5622]%:UH!1 %J /YJ;T5$ -M8%IB6&$\*R4V:&E;84]C:DD;$CER>HA!37IN+2TV16EI35AI:W-R251;7G-K -M5DAP<6!!-#])3V)Q;%YC85M;8%ERA(1UG-B6EH^4(6*:D5;:F9N -M=FZ#FYJ:SXMG9R -M:3\8*6%H7F=$/S\M85M$-EQP;%H_.39%@G* 3D!/P#^:6M96VAL<6EO62TE -M($5?8&-96F\V#@DE25Y[66UZ;5M$-C]H6"TM.5R"@TQ%845C:5A667=R6E19 -M65MR>GIP8V-;3UA/>HR$=6YC239@=7MZ6&-L:45J?6(Y3&IL9FMT:6"*>DLM -M-D1N>G9R8$UH52DV36QR:FAKG5K3&)M$OX2-E9(85MF=SXM*1 at M;FEV>WQWVM6.T19:%I-9F%+*30\,CYB;UE<>FIK:V!-:DQ9>W=Z36!A -M345:;W)W86E:6F)B;&MH6%EP84]B>G6 FYZ=6M88T5-:$U@:F(V54MI:E at B -M6H-L338E8H-O/" R539KB&]A25]H6DU%/TUJ;TEC:V T8W)S@&];6%ABF!)*3!;;FMJ8EM;8&-B84D; -M'6AF9T1J at QNN$D1-1&)K7&MC6%0T+6!?7W)\@&MNW)R=WIK:F-P:3]%6E at P/T199G%)8X-K638\6WIS -M9CQ)6#8_>FY;86AP;VA8.3]<FM at 6EA:6EQ]@VDY53\=+1MB -M8CE>8UA:6$Q6-CY-+TUN?8J&?'=8-"4_4')C UO(7G9]FYC24MJ22TK&%Q8.38P6G)]@VA%,"TM8W=I -M65M::GJ!>VM/6#(M W+#84U-6#X_:&-B;6MU>F(R%2]WB'I/.5I,;VMA13YI -M8UAH>FM:2&IZ at W%%66MMG):3'-Z8TM)6%E824M%>W%L at W):24D^6G5ZH-P36%;13]@6#EB9GN(8R4)$EJ#=V Y/CMB6F%-3T]%/EI[;&-C:'J* -M;#!(>G5R13])8V)C8WJ#G=,3'!@/SEO -MG)]F)18VDM'5AA13\P8U M-C]A -M=V9B6VE@:GI]<6E%*R5-=7US8VQS8UMB:6QV=6UC7RT;6H)H15],.3]%:6!C -M:6!R;V Y6H*$:T at I/W!$37)P.3(O.5A at 6F%I23YB8VM[=69B6V%H9U9)15MB -M:F-$4')U8VMR:UMC:GK^:U9B>FM:8W)V>&!-340@*38\6WIR3&ER:EA)5G)O -M33(M/FEO8FA4*1)8*0X2+4E67VAS>G)H8F(V.45F at V P8G)K;&A), at D;:HEZ -M230M6&M>/EE%6&)W7'IQ15AR>WIS1"U$67)]=69C:$5' -M=W):7D4=@DQJ 7(!< #^;CLR6W5R:V-O-BU)6$54/E at V+4188VYR#:F9P22T[16%;6VMO;FMO:5!R -M at VU8/SE:-CYKUY%14US=G)B8$E-V-06EY\_G='8GIK6&)R=7IO6F!4*2DM.6-[FM4+2U,;TPW -M5E =240P%1@[1&!P8W)R;VMK6"T;/WAP.6)U9')R3#()&%F"=UM>6$5),&!O -M.5AA:6EB6#!::#]A24U97$UR>%M98VQZ:D0I-C9C?7%;3V V/WIN:&-9)8(M -M20%> 8@ _GMH25IR:7> =V!%3UI)8FAF+2 V15IB9FYK<#XP8EIB8EDV6WIB -M:W)R;F))14E$26-B36-C6&*"D7)L at 6@_1$5A9CE%=TA(:WIC8GYM3$DP-B4^ -M7')C6#8M.58G.7IN138I45I>:F V+6EO1$E at 8V)<9F-A7T11>GUF33M-=OY] -M1$U:3#1@:FUS=5!B8SLR(!U(G=$.7!I-A(V8#9/15AI340; -M/UXG/T1,9T1);')C22<_+1M@:P-:_F)B33(Y8G%)179]=7)816IZ:$E)+1@^54U[ -M@%!,GM@)3!P;1LV:&!9/UAR8EXI/G%5*2U)<%M9 -M3V)J:3PR3&))-I)$2S9)8V-B<$D^:4AR at GA>,"4!8P%M /YK8SPY86%::WJ# -M>&A1<'=R9U50(!@V24]98F)-8VA923!9:%9 at -AM$:TUR@&EA8$58<%E-8F-; -M/V:#:V-;:W-P83XE+6-H;VMN6EIZBG)K;%A@:6)B66IJ3&9%(")9839W>V$Y -M/F!8/TEIF-:;HEZ7F-::')F8T]<:C!@8U at V.5@^7GIR6DE:/CE:8G)Z -M:D1F at F-A1#EO9$U/;V1F;FUR_EM8)14M/#\^.7"&B&M:6F8^1&YZ:FER83\M -M/V%%7&IK4&Z AGUF8V$_)5]<)2L at +3E536IR:UY)&RUC- at D.'6IZ8W!$68A+ -M/%M:<()A.2 E/!@E6'IZ231)<6$V&!M@;$0[%2MP;G6*;F-P:VQO:$U'64DV -M,&MW6DUJ;&-97H(P-@%' 68 _F)Z6R4_:VMI8W.*?6M:3%MP8VI65#D_64U: -M=W Y6G)A:7UP-C9O;3(E/UEC9G-<8V at Y1%AB;F at M3')W:E!R>F-/6&%527)J -M=75N6UZ&@V)08F9J9G)K8W!)25!;/QM%84ECF M -M+44@%2UU at T]97WMT1"DM6V at _530_6T]F at VM/>HA[;G)925E4)15-C9,8EHP,G=R9E-<@GAZ;&YR -M6EI)3%E>)2U536!W6TP^8(" :R4)-GI]=G)B at UDP.6IZ?8IK/EEA-"DK=WY; -M83E;=VE+87!W66!@86M;6FYI,&.*AGIJ8#Y%/A at .+5]04&IF>')Q at G=S 6 ! -M50#^8%I-66%C6V-L:WUR>G9P6V)J6F%L:455/T]B:S]/7$1:GI<6%4R&R=K&A+-RD;26]@/S [*S9$&Q4;6VYF;6I;26MP:CX;)WI[159C_D5:GIF8G=Q351L>W*">V-F:5Y)4&N"8V8R-E9I:8%R -M8FJ"F-J8U5;7FZ):%A; -M9BD;16)Q24E(:%0G.5MI/"LK)1TV;W5R8VMP:FMC26)U?6<#:H%N W+^:V@\ -M$EE[8E at M)SEH8$0R&TEP8W)F/TUZ at FM>1%2 BFIC65IIG9U:DQNBG=C6TQH:U4[+5AA34DB/V]R -M9G=/-DM-;8-R9FUW33EIW)R338_+2]J -MW)B -M;&)@7V-:-BU))39SFM>.R E -M/#9;<3PE at EA- 6@!20#^.R 5+6][62 M8'-H2VAK7&9K:UR&CG),14M:=VE+ -M/TMC8VAI5C1-23 \1%ISG)@3UA)+59$.6AN:VMF?(-; -M.45K>G5K_EM89()O)2UQ:3LE245K:FM@,E9N9F)J24EA5DD_/CDV'4E:6&8I -M(%EJ?862>DDV(!@EHIZ>G=KU!/ -M:FMQ9DE%;&AJ34Q@:&A)37*"?7IM8DU8.2U5/D5 at 9UIJ8E!Z:#8M6&YZ;6MB -M3VUP/RUB@' ^/DE?6EE9-DUS;UQB3&-T3$1B62T\+4UB5DD2&$UR9G62BFG)I124V55YZ at FM; -M<5M$G* 53)89EM$67IR:EDV6&]D9F]>7TM8.4UYX):1#8M/"4Y9T0P1&-K;TTY8W!K -M6$Q:8%@E17)@=8)F45A8/B=$,#Y@:$5$6DEB8RT;/W!N9J]U>F)08"T5,&J -M7TE41456/CY%8G)R6#!-GUW- ,.N39R<7)Z -M:V)S8SXY6H!H+4QW8D08%45SH!1EM-36!$86M%3VE$/V)RF9A:6YS9C .#BUK;76"FQ965MK9G9W21M-G)L8%AK<&:"-"D!)0$G /XM3V%P?G R%0XE66!@4&]K6$5: -M;&MH6%EP84]B>G5H64E$7UM)35HV+5IK<&)B6#!$6%Y56&)98(" 6VI]:CY, -M6EYK;&%:14UR>G!A16)O6DUC63]-8FM%-D5:>GUK1" 8(%A:2W!R1TE816 M -M*RTV3%MB2SY,@%LV/TM@;EO^3WUR46 \%2U69FI;;F [(!4W7S]);' _1$5C -M;VI08V!86FIL3S9$27-S8EIL>FIF*Q(M8GIM>7IK:F\_(F!Z7%XPDDR(#9I>WG!@6#Y-9C88-FMZ'!T8#8M=8)S:VIB6EE:8VM:6G!)/V-F -M8F-CFD_.3E-VIZF9O1"D_:F)6/VMZ82U$5C9@GIRE69M at G-K/R4M8'-K6WJ2=T]C>H)U -M;@%! 1@ _E]>24%<@#DV,CYR at W)96G)U:VIO:V%%/FEC6&-S:VMN?8)W:3\_ -M8EX;)6EK=7=L83]/:DU%)3(I375[;TU%6F-;:'IB6FYC54E%8V9::G)B/TUI -M8W**AH)K:4D_6V _,D1>8#XM8X%R:5I-8&E<8$1%6%I8/S]K:U8I&SYO?/Z" -M at GIF:UMA64E%8G6&=4\G/FMS:W!R26MR64]R>FM>)S V3WJ";F!%:GIH*25C>D]$/TEC -M=W!5/SE/*1 at V<$PY6GI[G)>:W)S>VYC8EIA34]/145:<&Q;:WN#?7!86&IF(!MI.5IX -M:6)-6FM@)1LV6%I<:FA)+3Y at 6VMZWUM:&!$6EAC -M8FERAGU-("U;=6YZ at H)S:E@[/U4M+6%-4()G)55W<$596#Q)<'MO7C(E.6*" -M<&IF8E!>:TE:=6-B>FYC=S8\,CF >F,V-EIF=U4E/X)N(!M)@G!825IR<%@@ -M&S\E'6!Z=W)K;W5V=68T*RU/:45$>HII,$5\@GMV 7(!:0#^)T5P5#=K/T]< -MGMW:FIW7C(K625%<&M;8&ER<%D_ -M3WAS=VIH538M1&EL;FIB:G)B.3YL>D0G/V--6&%@669R=&YZ9E@^-D5A6F9N -M9TD^7UEK;UM%8%!U:DQ%9F9K<'IR22 _:%N"Z'5]9EQ;3#XV3VE99GUZ6B(5 -M.6)?;H.&@FM-/SQ8&RT^15EZ=S8G8&,P2U]96G-U:EI%+24O9GUR;6M/8F)@ -M6FMP=W-<:W5$7D0RF]%6F90.6%SG)$23DV6&A:8W)R=VY9/RTM8VYN8F-;:%IC<&IJ=6M/6F@^ -M:7A:;WI6& X8/&-K;&!;:G=8-F!J-A(G8H:- at CP@'2DR/D0_/S1K WJ/6#!A -M64E):7)M>F-I:4AF 7,!60#^8FMW/B!P64TY:WUZGIR;$LV8FYR3$0V:6!$:&Z">E!922TG:8AN=8)I-!@; -M2VMN()%10%R 6L _GIR?TD217!)+4QR>G%P-FEO/C!8<&,@)6AZ?6L_-C):@F]$ -M-D]O8$E))U]L/"T[254M&!TY:W E+6J"=FMC8#9%H)O3&%) -M&W!Z at X-R:V!98FA(6V-KG=S<&I at 6%5;9GU[83X^4'QP5"D8)6*%?6 at M-DQ9 -M8VQW;&]Q=7IB6&AF8V _($5H.45:@H)$/CP8"41Z>GV#>F$E&#YC.TEH;V9K>G)+8$4M/G>!;F)16G>"8U@!6@%Z -M /Z#>H9P,#EO:#]%8WIF8C]H=V$\-EIC.2UB at GUK,ALE6()Z:%A;=W-B52 V -M8$DR+6%U53PM-UMQ7C98:VMF8W!I8FU\@W-R8"D@/W)Z:C8V+0Y:G)J -M66)R6TU;9G5F.38V,%9R=7QR47!B23XI6%A$8UI:8&E>*3Y9:V_^8G)R>G)H -M5DU>7#!$@7UNX9W8%IK at FA) 40!@ #^?VMN at V!; -MFI816)P6FEF-EM6/" Y;UM% -M25AA<6@^-C!::%E/;W=F>GIR6C\8#BE::FI5&Q4526)/8FIM;4=,;G)K6DE98VE+8F]" -M*3Y6-D1ZA')$&UA9)SE-9H)]02 ^6V M(D1)/R4V:VYR:SP;)V:#@TDG -M64DI#B5G"?7-C6H)@)0$; 6 [6)I7GII8H)R5FIZ>FM$ -M8W-K3&-W:V$I(%AR-D=K7'I\G)C6ED#8OYH9EQ/:6MB9G5W6TDR$AM@>FQC8#8E6W)P246 :$U08" ;6H)K -M3U9,37!W6%IK=SXV:&))6&!%8VMB6EM;;GIR:DD^3&E@:7MH.R<^+2UPBH)) -M(DU9)2U)87)UTDE25PR%2!8:7*0 -M=V-C:VE)3VEK=79\<%]5( $. 2T _EEO7G)B8WUS35QR:UI+6&!)-B @/U9CW5<:6,V+V-V at G5C/U5)6G5\9FMJ35MC24Q_ -M=VA%6&-J8F9[+3!>1"DO15M;>G)C8DE%6FMB -M8F9[>&N"7B !%0$@ +-9DD^37)J6FMJ1#LY8H-M8D])36IL=5Q?1$1 at 3#8G6EYP:590;7)B -MW!;14E% -M6G%(:GIO+1L^6$LM*2LG640B8HIR6$188%EJ:VMB at WUCTE$ -M:&9C:EQC14DB6'IF65E%3&IF:VM8+3EB240V+1U-?V)-9H)F<6):8CNI&#M8 -M,$1)+25>:4],>X)Z:EIK
+6!;8FIL21 at .(EI-6U4=/WI\9EIM8&!<8G!X>V-?26%A8GMR7#]) -M36-G:')C 44 _F$_&S98 -M8EA9=SL.#B)B8G> :5Y5*0X at 26EC:G9I-B V:7N">FA:23\Y6V-A=W-5-#E8 -M638V539+,A)$?W);:'-K6EI;8SYS>F-F>G5C6E9)+7F*:UIB7&MK6EM).QM8 -M=7)-13]8;FEFW:!:%!A1* V25 at Y.S(8($E:.2=P -MBGQB6')Z:38Y:%HM-F-P83Y).P,EU"UA:G![:4UB;GMR;%IJ>FM@/S]926!C -M:VMJ21@),EXM+2 )/W)M5CEB8V)<.6EW>FM956EP<&I<>FA$.TM:8WIF7GIJ -M;G Y#B5B;VA9/VM@,$DM$@-)AEEI:W9R>P%W 6( _EE$(!4M;FE;8EPG#@Y6 -M36=J4&MW51@@6&!:6G)C+255GMP86%)16IP>XAO8%A at 7S8M7%I8& XE -M8$E8:WI[:UI86$EC9VMN9D]G6F-)%5E\@G)<8V)J8F!)/C1);G9-)TEB:V=F -M>FIB6D5$38!K5#)$7R(M8FV"G5K3$551%A-8')Z:%XR/V at E -M PFZ(F)_8#E?8FAH25AF.Q at M66--,%AP7AL8 -M/%EB8'=+)2 [8V-BGQS8EA$6#!$;"(P;8)Z8&-]9D5K>E at M($EZF9Z>F P)UM3'4UZ8')N@&@@ Q6Z(#9K@&-@ -M145N<$5@<5 at R26-83'>(>FM$("T_8WM at .5IK>F\\*3Y815AD8W!:8%A4,C0I -M*1(P8TP^30&" 7\ _G!9)Q at M9H-W6EM88$$5/EE)66%A:%4\1$UJ8F Y6#PT -M.45:7CP_8W)ZEHV-DER;FII5"L)%2G R,#P[*R5->V)9/SYF;SY8<&A$ -M66!C:&:#@EH^.24[6&)8-BU%+2 V6')P6SEF -M at VM@7&A%/UAH65A",C]C=T at Y3W!>16-K;G!)6%A)6%A at 33!>1#])@D0Y 6\!2 #^3#Y$ -M:%A-;GIW:VIS=VA-6TE58$U%8WIZ9F9I-BE)6$0R.UAW8V%HEE:<$]F?'59/V)[ -M6$US6EIJ'IG+25)A5\Y8DDI25M'8F9568)93P%P 5@ _F!).6-W23(_:W)F -M7FYW2$U9/F%)26%N at G!:63]A?4E+7C]H=V)@9G*#>G: FI%24E9 -M-C!<:F-R:UIJ>FMC;5D\,D1$-#1)7!(@:G=(8GU:8GIR:#Y!9CY$?V at _35EM -M at H)O7$E812 I8%IF;V!I:%0P,EIB55AA8%Z"B7(^)3PI-EA$%0X524TM1'IZ -M9RT5)VIK6F]A)39 at 8%E:34F"34L!:@%W /YR6#]:>F\I%2U96#D_=E8^6"TV -M-D]L:GIZ;3\I8G]-/VD^1')B35MN at W)C>H!G340I3'-Z:V!A6VEC:&->/UAO -M:F-C65@^245837!P6UEH65 at E.6U]A' V2V-N at GIR3TQB6"=8EI87DE5 -M26-P;VMB<'!@55EF1&!JI**;SP_1#]).Q at .#A45#C9Z>F)$-$1H65AC -M<4D^3VE66F]8 at D5) 4GIK8&!?;W!?845:;FI at 6$D_35D_ -M2$E@>V=P;V9G13EH;7IR145-8G)U>G):;%@I16Z*@G5K:G5F at G5<+1LP47IS -M33EK,C)8HS=913E86V!R"1A%;G=C8VA/>G-%3%A)5F!9H)I37J2DGI;15A88#\T.2 ."0XV at H)J24MQ at UE88VIO;TAA.3EX -M<$5% 6@!60#].6>)BGU[<&8V-EMK16AB6F V*RLT+3Y68F \26!@)25B9BTG -M1$]F>H!R8$UBX)::FA)5G*)>'5NGQN=W!C52TE(#YO6F!F:W)H22T5(%F">GUR9'(E+3]8 -M8DD[)24[1%N";E\Y*2U$5F!B:V)W -M;HJ&=6!;6%AP6EIX52 5#BEP>F-%27*&:# R8&9Z:VG!S<6%IGMW:&:L:EEA6"T2(#9) -M8T0P8FUR>FYP8#05,DE834E9;G):6!4)"2=:669:/U]F/C8#6M$Y6G)J6"=9 -M86AK8VM-241K8EI)8#\_-DEK:#X_<&IB;VA>-C8\*39;=6YC9'V"FQK -MH5[5CY96$E586)9:G]C -M38%W36%C-A at G5DURG):8W-I -M84DV=UM8-CEK7QTE8FYJ9FMW7C9$/"5,:D=::FUB7G)R:$UK=7=C<'!87E]@ -M35L^3WI]VN"6!L!-@%5 /Y%238Y6UEC=V)BH!9-D1)/R4M8GV%:SE,:38;7GIR -M:TTM1#Y:8EIQ at H)R4#XMF9I7S0@,C))6D]-9H*"=V at V'59@,BU:G)@/#Q/9X)R:@%N 6D -M_F9W=VM$(!@I3U]$6']P53Y823!)2SEBTD;&UIMBGURG=;1" = -M+59::W]V:5MA13)%7C(V=W]9*2589DE86T5F1$EH35!L;VY at 1"U836I,67MW -M>E!W;FI$-F. 9FA863PP)6-]A8EJ2S8@(#9R:C!-53L[8%M92T51>E at 5%3EK -M>F9:3&)[:SX\/SDM,&*"A7%R8U4_/F>"?6I9:.U at 36IF=7IK8$E58%E9>FIH -M8W!@-BUB:$UP=7![6V)H1&)J:VEB:&!8/SE<>G)@2V!B>H-K/R4_=7)Y:#XM6#\M -M/UM) RV08H M)U]@34^ GIJ8308(#9-:X!R:6-L -M224M/S(P:HIO.R P6FE]:3EJ;VEP6$]:6H)K23Q615 at V/FYR:UIK>GII8W)[ -M:& ^.6AM2X"*A'QR8U9454MJ8S\^6D]$8&)R:UDO658R,"=J=5Q$+3!P8CY@ -M=38)%3E[A6YB34D['3]U at G=:8_Y6-V)U;FYF;U]-8VQ/56IO6F-B-AM$:FUK -M669Q5G!K:$]J<#L.#B5)16=W3$EFABT\8VMO1&J&;6IH8V)(;T58=&!R at 6]U -M:%IG+3E::W!$34U)8&!,:UER?&=-:VMD:5H_3&9U=6I86UA+66AA1"42.6H_ -M(#E$&R=OR5!21TY;6MH3T1/>GIY>FI6:GMI,%MR22TY23(@ -M23(;86]:5FIJ34E%)TQW?89[6UI8.SEJ=8-Z9EIK>F -M-BTT8W!824\^)41$:&-U=7=[:UIK>FIB8CDB+4E%-FA?6UI::TU;:D]J:TQJ -M?75L8F-:.5YT?75L8UMC6#8M-FAR62M86F9ZG!)6%IJ -M83\I-F9B:VMI35MR>FIJ:&-C6B(P1#!->GI at .5F":W !- $_ /YI?W)K:VEB -M14UR7BDY82TM.7J*4$TY*5A6GIH1%A<+W?^8E]B:V)3>H9:/V)Z=58P -M/BD8275:/CE%>GM(4'MB6G6"6F%@ -M:&AR>WIR2V@[ -M*259=7IR6%9B8EMKBF@[+4E at 8&9Z:DQ;<'IN at 7-)/S])8%@P23\M-EAI=X!- -M1%EB:5!R;P-)_BTE+4UK;UI-8V!-:G!C65E)(D>";6YU9FI$/E9:8G5]GJ"FYC:6%@-F!J8$Q)/DE9:@-ZD6UR -MA8)C,AT.&#]K8D0^.3E? 6(!6P#^9VMB3&:"@G5RF\Y,C9)7W=R8$QJGUV8EY8*59K6V9]?6YB3$M97E8_.6N" -M6S]B8UMKE\R&SEB/BU8:FUZ -M=69UFYL8F!-6DUC/R4Y84];:&MH -M13]F:S8V6#9 at 8TDM17)Z at F=)8VIC/D1O32U)7#8P16YU;EEN>(IS7"D8(%9W -M8FAB6X)96 %- 5L _FMR85E>;GUU;H5[9EYF;U]-8VE/5FIO8&- at 6X)R138E -M.59J:U]-:FMC;UA9:$E$-EA8-B ;&U9?)2UKG)8:/YJ8V9S>WI;35A-.6.'9EQ/;2T5.6)17"4R/B451&)1>GIB;&I,27!P -M:D0R8FYW7WV%.24B/CEB86-)2&MC7D1I84DK8V!526%;6V->:38I8H!H/C]) -M544^5&AR;7)6/&)R>F at Y8C\;+5A$-C!:<6),8&Z)@&U0-BD_:&-C:$V"5EH! -M-@%( (U$:FE866)Z:UQ]>F)J W+^1%MK8S8Y8TU:8BER@&I?.S!)6EI-:'!K -M;VM83'!I6&%L8#L@%2 V53Q$64U;=V9)65MC:UAF21 at .%4E987%X6CERGUA&QM,=75J63D[*2=,6D=R8CD;&TEA2 X218)]G)C -M-BE8;H6#6F!-/"TM-C9$8V-J6EIC>GQW:%Q)7EI at 8FM),#X!.P$M /X;/F=O -M6EMF;V)M;F)B?7UF86!K;S8_22DY6C!;!:DQB;8)I*R5-W9NF-JW)R<#X;&$EZ?VY?)1 at E1X*":FA% -M22TM-C]A=V9B6VE@:GI]H- at +41+/%!P3&)H*14O:5IB:VM$($1N.QMP -M;T0M/FEC3%]8238^8EA5-C9F+14^8AT.;V1;65%N339)41;_GUF7GIF66)F:VE86$4;27)R>H-R -M6DUN>G5<.5I94$DO9X!:.5AI87!K6"TM6G)J=75]=#(.&$EJ:G=H(!M):&)Q -M=6YB:FI%8&J"@F(^6%EKH)8&!4R7G=B13 .%2UQ=7IP36 _+3]8:75] -MFH_27IZ;V)A24MI -M.4EJ>FY@*1TT/#(I7V(M7VQ:8GIZ9FY>8V!816Y at -C)8=VMJ34UK;75K36!J -M7U at M27)?+4UP8V9X23(_8V-K:FIR;5\R(#9-8GQW)0X;-F)YE4R+6MU=7)-(A5-;F@^+VN"H9K23)% -M:5Y)8#DE;^%J65IZ at U!-8%M-;EY:338M6W]B:TQ8:V)C:F9K:VIC539,6#Y% -MU at _16E:36)J9F9J5C8V/V)R;S8@&!56G56,#XR*4EJ -M7TE%6&%A64E-:&X[&TEB W*<9EQG.R 5)3E%1%QJG)_>#P5-&%>-C)J at F))+4EI6&Z#>G!A/CM@ -M46-C36)K=VI66G!W:$0M+2 ^@GIP8V-S:UM)2S\^8FIW8E at Y-EA8+45J8EE+ -M;H-]?4PV56IQ>GIB,#E64%DV%3YZ at FHM("UA1#85,GIK.4DP,$1H:#8;.?Y: -M6$1:>F,Y26A%7GMZ<3\;-GIC;EI-3$U@:UQR/S]$6F-B7TUH9D0@(#9)3UEB8DUC:%E,6FIR6#!;33F"23X!+0%6 /Y9 -M6$5-8GI[=SX=27IF>H!$%1M$<#L2.7]W-A(G8F)L at WIR<%AA?6%6/RE/:WN( -M;4E;G9VH)M($AS9G9K238B.7!F>H-J;3XR,A4.$D1F14QR;T5);C\M/G)Z:V at V34DY.S\!50%/ /Y@:UDT1&]Z>DD[ -M-DQK;&M9,C)C>E4@)6)W/R!$2$UC>GIB8E at _:G)A52LE16:">W=?7&MC<&D_ -M+6)Z at GIF=HIW230M/V)B:V)J:F)Q:"(5,BT^:F)$8W-C/T1-FA66G-K6BWH-F!B1%M:/DUR8C\V:WIK)25: -M;W)R;UXM+4E';7AN?V P1$$8#BUH5DEMGIR6&AJ -M8V9S=G5F35A-.6.'9EQ07S8E/F1F:V)<2U8Y37ER22U$>V$V&Q at M8&@#294Y -M/UE-6G=P.5IR>W=H7G!@5EI5)S\!=0%; /Y/:FQ>26%<ED[,D]R;45H8$5/GU[ -M:30T16)G;VIB;F]U>E\[/"5%-B56FD at 86QI154_3V)K/T]<WMF6!@8+4]A<'YP,EMJ;TU)1$5?:F)@676%@F)0:F)B88(R)0%8 6@ -M_FM).6MG8(%N8FIR:U!K6#(M8VIC34UO;UMA:UI-/SE:8V)@/S8R$C)63W)R -M:FM9/V%K63E)-CLR-D5C8VIF9G5W:#8V3TE;;X)-/W)R9G(_7&9BGMW-#Y-6VEO84E)36MW;FUR -M6FMR?S]X8$]NDEL":%4!+0%- +IA6#!6,A at I23Y::W)Z;TDY3&E@ -M63\R)4M: V+^:FYR>F(^/U at V-DU[:DUJ;U!S8F)R:FJ#<$E51#Y812TE17)] -M:EE::TU).5E$)UEZ6C!-:F P1'J">FIK<&$Y6G)J6"=986AK8VM-241K8EI) -M8#]:6X)R=8AK15IRG=)&V]W8#Y at 838E5F)B:RT^8VM/:HJ"6%9J at X-U<$M?7DE!8F], -M:7IP8S\I,B5%<$DM3')Z<7 \)4QZ>G@!( $E /Y6.2T^:G5VG!$/F)C:4\R&S]@:G)K -M8FMN?W)A6EL_-C9J>F)N:C]J at FIZULG.4UMB'IR6F-S:6%)-G=;6SEK3V:% -MFYZ8" 2)UMR8GMW85MU>V-:&QM;@GUR7FMR>V]B -M:$DP3&)<8F1;:W5J3UQN:V-U_GUZ8$\Y6VYP=3E, at F%8.5ARF), -M6#\M38)Z>@(^ --F5"5):&!,35Q at +3!,,B4[26-8/UAB:U]86GI]8E at I+6!P -M65IF.3(@%2EB-CY?:'%O8FMI23 [*3!-6EMK?V]:3&)R:F)B53\V.TU$8G)R -M9FIZ;P-K_F)B7E\R.R )"2UFC9%;UI$+2=/8D5KH!V@&,8&UAI-C!:@&]::$U:,&%92:I) -M:7)M>F-I:4AFVA85EIJ65ER8$0T*TM@ -M-CY/87!P8G)_:#8E,#!I6SE:>G5J5EIB9G),6$DM)S8Y8&I:8EIRF9C:EIP:FI,)38V,&+^6SEDC7]W -M.41@@XEN-BUA8V)Z$5% -MH9[12UJ -M;FM))S!WBGU]>VE>-D58+2=J:V!P9U!+8$4M/G>!;F)16G=C6%IZ>G)_21(. -M&UII;G!?.QLB86YJ.T5U?7)).5AR at H)J3P%5 40 _FFEG*25)9EM;:DU::VIK5C8G8G)R:EIC8$EJ=V _1%]U>W!C -M8TA-F)%6VIK1!@I:X)U -M?7MF:#8^:4E):4U$=8AI:W!%&R5$>X9W8%IK:$E$@(-ZAG P#A5$6WJ0;RT; -M,DEW;S8P8%YB8$D^8(!J/P%; 7< _H!)*25)8DD_.4]Z@&9A14E?52 8(%9T -M>FM$)4QL8EQ08V-F>FA$3UE-:%@I%1L_>G)F1$TY138V.TE8,%AB/UIJ7S9: -M?7IF:G)F:VIM=T0Y:EH@*41% -M3'5C/REAAVUZ8"4 at 8_YL9EEUBEE@-DQN:VD_7FA-<'552QL)#B!)34P_7T19 -M7C8P6FTM8GIR6CY,6EHE%39J9QL88'I:6G)F8V-K2R M:WIV<'=L6"DO;W!: -M:38B8HIZ:WAF.SM99X)]C\I5$1:=SXM6#8P -M65 at V,'*"<#X!+P%J /Y_FI,+3LV8H!C2S V-D^&>F-U:59%6WI;36IP4 XM6&IJ7%I)6GIU -M:U at M/&/^:V]$:H9M:FAC8DAO15AT8'*!6&8M&!A$<&]?8&MK>GI:.T5H5EIB -M5CDI*4];.1LM6F at I(FN -B=Z:VMQ8#8E+4]K>V-(:ED8%4R" -M 14!.0#^6EIW>G]R:#8;-%AU:UIW7TMH6TDI$BU:8E]F25]8-BU886)R;S8; -M/VAP/S9>7D0Y6FMR=V!A6#PI(C8G*SPM-EA1:WIR<&E@,BE$8$PP#AMKC&UJ -M8EA5-F"":TU-7B4=>FUQ>FU6-DUZ6T1F:V@@&$EZ(!4 at 66]><'MW8F=98&AK7SE$4S9):&@R+8(V80(M /XM-FEN -M at GUO025$6$Q--G):/FAO669$/UMO:F-B8V \+5AC>X-Q5"LV8'$_.6)_:$59 -M469U>6M;8$M>6#\T*QLV6$QC>G5W8ED_/#=H1"TP(%B*;6)-8V=-8G)B/UI: -M.RER=&UZ<%A%2']B/VIJ;S8;-GIZ6"U86V)06V%:5FK^:DU)12=,=WV&>UM: -M6#LY:G6#>'5\8UE4/D5866I@:V=R8F)J;W!U51 at .&T1)8C\Y7S @&UIZ21M@ -M6EM[>F]/86%%8W=>:#8@(#]Q:U9-24AZ>V!;)2!9:UA)/D4[#A at 8-#)9GIK:$UA=7)R=%@M,%9R at F$_ at BM+ 4D!+0#^,BE):G6">E4M7FA$ -M33YB3S9:<$]B;TU-GM04&-H:VMJ:E\P8G=B<$0V25I6 -M+3])+25):V-R>F$=#A at M27)R:V$_-%AK:U at E1"4M1450;8!O.4UR;%M9/RTV -M1#\_65]U=G5J5CY)/FEG.0-CHVEJ<7=B83\;-EAB6$DV.7)Z8D4_)1M;?(:* -M:$1$16EC8$E6 5\!60#8:6!8:TUK<$D=16A966-W6B _8$587T]+6GUZ9TUK -M8V9$/UQU:CE%.5IK83\\37!P:%\_35M)869%7V!,6DT_-EAF3VEB;%!;6FJ -M>F=8,BU824U?-C]$9P-R_F-DH6"F)9FYL8F!-6DUC;T1-6UM-4'!B6F--5C8@($5H:%8T,C(;*U1,:GA] -M>EG.3'*"E!9 -M6UIN at H)_:54@#B5A<$E$25A$8&QI.RU6:&9]>V)).3E8:$U8 5D!=@#^BG=/ -M8R4V5E]%8&I,:U at V6$DY8&!8/T]R>GV":#\_8VI at 23];:F!6:&!8/S]K>G)K -M3TUR at GIJ:VL_6FMK:$D\*3];8')R:E!B24EU?7V*;D])35IB3&%)&U"*BF9( -M6GIW.2TV33ECAV9<3VTM%3Y?6%AB.2 8%3EP>F]F?84Y_B4B/CEB86-)2&MC -M7D1I84DK8V=B:FMC+2UB8D]C8U at W24U:;W)H7E561#9)+3YJ;G):4&YZ=7IK -M63\V56!IVYM<%DG -A B<$M)66 _,%I[<"TV6F)R at GIP5#!)6H)@6 %9 74 - -end Deleted: python/branches/py3k/Lib/test/testimg.uue ============================================================================== --- python/branches/py3k/Lib/test/testimg.uue Tue Aug 19 23:04:40 2008 +++ (empty file) @@ -1,1170 +0,0 @@ -begin 755 test.rawimg -M___Y^/\A$Q3_*1LC_QL4'/\;%AS_%Q(6_QP7&?\B&AW_'A<7_QT5&/\7$A3_ -M&108_Q84%O\7%1?_$Q 6_Q<3'/\:$Q__'1<;_R$:&O\5$Q7_'!D8_SHW-O\\ -M.CW_141*_TE)3/]/3U+_'1DA_R,<)O\B'"3_249,_T=$2O]$0D7_.38_]<7F/_%1$9 -M_QH6'O\B(2C_65A>_U587?]87%[_65M>_Q at 5&_\@'"3_%Q8<_U%34?]<6E7_ -M5U9/_U-14_\:%A__'AHB_TA&2/\]/CC_24I$_RDG*O\B'B;_)",I_UI;7/]; -M65;_7EA6_X%\?/^!?GW_7E]@_U!45O]45US_4U5:_U)46_].4%?_2TU4_T9( -M3_]#14S_1$E/_TA)4/](1T[_1D=._TI/5?])2E'_2$=._T-%3/])2U+_2$E0 -M_T9'3O]#1$O_0D1,_T!"2O]#14S_1DE._T5(3?]$1TS_0$-(_T1'3/]!0TC_ -M0T)(_S\^1/]#0DC_04-(_SD\0?\[0$7_0#]%_SY 1?\Z/$'_.CQ!_SH\0?\[ -M.S[_/SU _Q43%O\E(R;_%Q48_S0R-?\7%1C_)R4H_Q02%?\2$!/_%!(5_Q,1 -M%/\5$Q;_^>[U_SXT/O\F'"O_'QDA_QD4&/\6$17_%1 4_Q<2%O\:%1G_&!,7 -M_Q40%/\8$Q?_%Q03_Q<3%?\:%1O_'17YX_Y&1CO]O:FS_5U=:_U)45_]1 -M4U;_4%)7_TY/5O])4%;_2$]5_T1(4/]%1E'_1DA0_T=)4/]&2$__1$9-_T%# -M2O]$1DW_04-*_T!"2?] 0DG_04-*_T1&3?]!0TK_/D%&_T)%2O]!1$G_1$=, -M_T%#2O]!0TK_/3]&_T!"2?] 0D?_/D!%_S]!1O\^0$7_.3M _ST_1/\\/D/_ -M.CQ!_ST[/O\W-3?_,C R_S N,/\M*2O_)B(D_Q82%/\7$Q7_%1 4_Q(-$?\7 -M$A;_%1 4_Q81%?__]?K_+R4N_T<^2_\A'"+_&A49_Q81%?\5$!3_&!,7_Q81 -M%?\6$17_%1 4_Q at 3%_\7$1G_%Q(8_PT(#/]VGUW_V!C7?]765?_5E=8_TQ15O]+3U?_2E!:_T=*5O].4%C_2DQ3_T=)4/]' -M25#_14=._T9(3_]'25#_1$9-_SY 1_] 0DG_.SU$_T-%3/] 0TC_041)_TI- -M4O\^04;_/T%(_S]!2/\^0$?_0D1+_SY 1?\^0$7_/T%&_SY 1?\Z.CW_,C(U -M_RTM,/\G)RK_*RDK_R at F*/\J*"K_(R$C_R4A(_\I)2?_(AX at _RXJ+/\9%!C_ -M% \3_Q at 3%_\3#A+_&!,7__KQ\?\@%Q[_&Q0<_QL6&O\8$Q?_%1 4_Q40%/\5 -M$!3_%1 4_Q40%/\4#Q/_%Q(6_Q<3%?\7$A;_$PX2_Q at 3&?\<%1__&!,7_Q42 -M$?\4$!+_$0\2_Q(0$_\3$13_$Q$4_Q,1%/\4$A7_%A(:_QP8(?\;%AK_'!@: -M_Q\;'?\;%QG_%Q(6_Q40%/\5$!3_% \3_Q,/%_\7$QO_'AD?_Q\9'?\=&1O_ -M(R ?_R -M%R'_&Q@>_U964_]:6E?_7%E4_UE55_\8%!W_&AD at _V!?9?]=7E__86)C_ST\ -M0_\6%Q[_&QTB_V%B:?]B8FO_86%L_Q<7(/\B(RK_3E!5_U-56O]74EC_)Q\C -M_R4D(_];6UC_75Y8_VMJ:?^5DY7_A(""_UE65?]86%O_4U5:_U!26?].4%?_ -M2TU4_TE+4O]+353_1TE0_T)$2_]$1DW_1$9-_T-%3/]!0TK_04-*_SY!1O] -M0TC_0$-(_T%$2?\\/D7_/3]&_ST_1O\^0$?_/3]$_SP^0_\]/T3_.#H__S(P -M,_\J*"K_*RDK_R at F*/\H)BC_*2 -M(/\E(2/_)B$E_R,>(O\W,C;_)!\C_Q81%?_\\//_'A07_S$I+/\L)RG_'!<; -M_Q0/$_\5$!3_% \3_Q40%/\5$!3_% \3_Q<2%O\3#QC_%Q(8_Q at 3%_\8$1G_ -M$PP3_Q<1%?\5$!3_$1$4_Q(0$_\2$!/_$0\2_Q$/$O\0$!/_#0\2_Q43%O\@ -M&Q__%1,6_Q(0$_\1#Q+_$0\2_Q$/$O\0#A'_$0\2_Q .$?\1$A/_&!<>_Q at 4 -M'/\A'1__$0\1_TI&1/]54$K_(R(A_Q,1&O\5$QS_+2PR_U-45?]-4%7_5EE> -M_UY=8_\P+3/_'!@@_Q<8'_]>8VG_8F%H_V)A9_]C8FG_&!8?_Q<4(/]>7V;_ -M8&%H_V!A:/]45EO_&QHA_Q at 7'O]E9&K_961J_U]>9/\9%R#_'!HC_TU-4/\Q -M,S#_)R("7_'B C_R at L+O\;'R'_$1$4_Q$1%/\0$!/_$! 3_Q(0$_\3#A+_ -M&A08_W!H;/\7$A;_$A 3_Q$/$O\1#Q+_$0\2_Q .$?\1#Q+_$ X1_QD9'/]/ -M2U/_-S(X_R,@&_\].S/_5U!$_UI00?]>5TO_&A4;_Q at 4'/\X-CG_/#LZ_SY! -M0O]14UC_45)9_RPM-/\?&R/_%Q@?_V%F;/]H9V[_;6QR_V]N=?\6%!W_&Q at D -M_UU;9/]F9FG_9VAI_UM:8/\8%A__&AD at _V-C9O]H:FC_969G_Q85'/\4$QK_ -M5E=8_U]A7O]65EG_%A4<_QD8'O] /S[_)R4H_QH6'O\B'R7_9V-A_V%<8/\< -M&"#_(2 F_T=%1_\>'![_*"8H_UY<7O]Z=7#_J:&=_W=R=/];6%[_5%5<_TY. -M5_]$1D[_/4-+_S@[0/\Y/$'_+S(W_RDL,?\K*2S_+RHN_RTH+/\M*"S_*RDL -M_R at H*_\F)BG_)B8I_R8F*?\E)2C_*"@K_R_\6$17_&A49_QD4&/\8$Q?_&!,7_Q\:'O\F(27_2T5#_Y"+ -MA?^+B83_'Q\B_V)G;/]26%K_2DY0_S4D/_;%E'_W5 at 5/\I(27_,BTS_T1 0O]" -M0#W_55!*_U%,1O]'0D+_.C4Y_Q\;(_\7&!__4UA>_U-26?]/3E3_5U9=_Q at 6 -M'_\[.$3_,R\X_UM96_];7%;_6%99_QH7(_\9&!__6UQ=_U]C6_]@8F#_&!<= -M_QH9'_]?85__8&)?_UY>8?\8%Q[_%Q8<_T5$0_\V-#?_&!0<_QT:(/]K9F;_ -M;6AN_QD5'O\<&R+_;VQR_QT:(/\C(23_5U57_R8@)/\L)"C_4DU-_UM65O^ -M>WO_A8""_T1 0O\T,C3_)"0G_Q\>)/\;&B#_$A$7_R(B)?\H)BG_*RDL_S(P -M,_\R-#?_-SD\_SD[/O\Z/#__.3M _S at Z/_\V.#W_-3<\_S(T-_\L+C'_*"HM -M_R5TO_:V%6_UU/0/]\9%7_?F19_RT>(O\H(RG_ -M-S,U_SX[-O]E6D__85=)_U=,1?\\-C3_&A8>_Q<8'_\\/T3_/3Q"_QX;(?\< -M&R'_#PT6_R8B*_\M(B?_)2(=_UI<4_]3453_&Q at D_QD9(O]97%W_5UQ6_UI< -M6?\9&1S_&1@>_UYB8/]O<6__9&1G_Q at 7'O\<&R'_/T$__RDI+/\9%1W_'1DA -M_S\]/_\=&B#_&14>_Q<6'?\Q,#;_&Q@>_QP:'?]J:6C_(A\K_R =*?]02T__ -M3$9$_RHB'O\H(!S_3TI%_VAE8/^)A8?_6%99_TE'2O\5%!K_24Q1_T9)3O\\ -M/T3_0$-(_SY!1O]"14K_14A-_T!#2/]!1$G_/T!'_SH[0O\\/43_.3M _SL] -M0/\]/T+_+S$T_RLL+?\L*BS_*2'1S_ -M&A45_QD6'/\8%Q[_'QD=_T at N(?]*."K_4E-,_T9%2_\@&R?_%QDA_UYG;?]B -M9VS_:&=F_QT:(/\;&R;_0D1,_S at Z/?\M+#/_&!8?_Q85&_\\03W_#0\2_Q01 -M'?\8%A__$1D=_T5'3/\8%1O_%!8;_TQ.3/\:&!O_(R F_V9D9O\L*#'_'QLC -M_VAF:/]=6F#_(R F_T9$1_\A'R+_)"(E_U!*2/]%/SW_1D1'_Q45'O]B9&G_ -M4$]5_TQ+4?])2$[_24M0_T9(3?\_04;_0$)'_TU,4O\U-#K_,"\U_RTL,O\K -M*C#_*RHP_RHI+_\I*"[_)RDI/_ -M% \1_QD:&_\;%QG_&!,3_QD4%/\>&1G_%A$1_R4F(/\R-2__0$,]_T)%/_\R -M,B__+BXK_R$@'_\1#Q'_(!L;_T1"._]$03;_7%)$_WIK7O]31#?_0C,F_U-" -M-?]:2TO_'AD?_R,E*/]234?_;6)7_V582_]K7E'_95Q5_U)-4?].2TK_:FAC -M_Q41$_\6$A3_&A<=_Q83&?\J'A__6#TL_TTX)O]H7UC_;FIL_QX7(?\@'R;_ -M4UM?_V%E9_^)B(?_%!$7_Q<3'/^"@(/_?X%^_V-C9O\8%A__%!,9_TY,1_\6 -M$Q+_&14>_Q at 7'O\8("3_5%9;_Q,0%O\@(B?_65I;_Q,2&/\H)R[_9&1G_S0P -M.?\?&R/_9V5G_V%>9/\3$!;_5U58_QX<'_\C(23_96-F_QP;(?\6%A__1TI5 -M_R <'O]D7U__ at GU]_UU86/].3$__2DI-_T]/4O]&1DG_0$)'_T)$2?\^0$7_ -M/3]$_SY 1?\Y.T#_/D!%_ST_1/\]/4#_/S]"_SX^0?\_/T+_/CY!_SP\/_\S -M,S;_(" C_QH6&/_\^O?_*R at G_Q@6&/\;&1S_+2TP_Q at 8&_\6%AG_%!07_QX= -M)/\4%AO_%1 at 9_RDF(?\>'R#_CXZ-_YZ8D/_3SLG_T\O)_]7+Q__3RL3_R\6] -M_Z.7F/\8$A;_&1D<_Q at 3%_\<&!K_&A88_QP8&O\7$Q7_$1(3_QT>'_\;'1K_ -M)"&AC_24= _U932/]I7U'_>&9<_UA(/O]% -M."W_4D<\_V)34_\:$A;_&!H8_W)L9/]E6U'_;6!3_VI:2O]S9EO_55!+_VEG -M8/]:6%'_$PX0_Q40%/\5$AC_'QH<_T4V,?];/BS_2C =_Y:&??^&?W__)!TD -M_RDF+/]B:&K_?'^ _XF*B_\7%!K_&Q8<_WMW=?]O<6C_8F1A_QH9(/\7%AS_ -M14 [_T])1_\;%1W_%1<<_QHB)O\Y.T#_&18<_Q06&_]'24S_#Q 7_QP<)?]0 -M4E?_-C$]_Q\;(_]A7V'_6%5;_Q,0%O]85EG_'AP?_Q\=(/\[.D#_&!<=_Q01 -M%_\6$QG_&108_Q(,$/\J)"C_2D1(_U)04O]T(![_*"TG_SQ!._\K,"S_*S L_R\K*?]!/#;_5U%'_VA>4/]B4$;_ -M4$ V_T4Z+_]=4TC_7U)-_Q40$O\0$!/_;FEC_VQB6/][;F'_>6M<_X1W:O]C -M7%;_8%Q4_W%L9O\>%AG_%1 6_Q(0$_\@&1G_5$$Y_V%#+?]4-R7_D'UU_X^' -MA?\K)"O_8%]E_U!45O]04U3_3$U._P<&#/\C(23_14$__U)63?\F*"7_'ATC -M_Q at 7'?]-1D#_6%!._QL6'/\7%AS_*# T_U987?\;&![_%!8;_T1&2?\4%AO_ -M'1TH_T1&2_\M*S3_'QPB_TY,3O]/3%+_%!$7_UA66?\>'!__%A07_Q$,$/\: -M%AC_&!,5_R$:&O\;%AS_$P\7_QL7'_\=&2'_'!H=_R >(?\?'2#_4E!3_V]Q -M=/]565O_35%3_TI.4/]#2$W_/T1)_SY#2/\_1$G_0$%(_T-"2?]"04C_0D%( -M_ST_1/\]04/_.CY _S8Z//\5$Q7_^O+U_S0O-?\D(RG_;VIJ_Y:2D/\>&1W_ -M+2 at L_Z"5E/^+?WO_'1<;_QH9'_\=&QW_'1X?_Y60D/^>E8[_S\K%_];/S__8 -MS\__U,K&_]C,Q_^=E)3_&A47_QT9&_\5$Q7_%Q47_Q at 6&/\:&!K_$Q$3_Q,1 -M$_\;&1O_'!H<_QP:'/\G+";_.3X\_RHO+_\F+"C_-30M_R\J)/]+13W_6U-) -M_W]S:O]-03C_13LQ_TU%._]P8U;_(1D5_R\K+?]/1#W_&?\5$Q;_&AD?_Q\7&O\N+"[_C8B(_YZ5CO_/RL7_ -MTLO+_]?.SO_7%G_V9C6/]L:V#_-3,P_R >(?\B("+_*"0B_RT>&/]&*QK_ -M."$5_]3&P_^4C(K_'AH8_UU?7/]A;&?_6F!<_U]E8?]I;VO_76-?_SU#/_]* -M3T__$1,6_P\/$O\6%!?_-S0O_TQ'1_\@&B+_&!4;_S0Y/O]<7F/_659<_S R -M-_]045+_$@\5_R <)/\7%1C_%A07_QL9'/\6%!?_(!XA_Q42&/\D(2?_%!$7 -M_QX;(?\:%1G_&A49_Q81%?\4#Q/_%Q0:_Q83&?\8%1O_%1(8_Q83&?\4$1?_ -M%A,9_QD6'/\4$!C_(!PD_Q41&?\C'R?_-38W_U-54_]E9V7_2DQ*_TI,3_]$ -M1DG_04-&_SY 0_]"1$?_/T%$_SL]0/\^0$/_.3D\__OS]O\G(BC_(2 F_XZ) -MB?]U;VW_*B4I_Q at 6&?^]M[7_O;6Q_QP7&_\8%QW_&147_Q43%?^2C8W_GI6. -M_\K%P/_6S\__W=34_]S2SO_2QL'_H)>7_Q\:'/\7$Q7_%1,5_Q84%O\9%QG_ -M'!H<_Q,1$_\3$1/_&A@:_QL9&_\;&1O_)"DC_S4Z./\N,S/_)BPH_S0U+_\L -M*23_2T9 _TE#._]C657_65%-_TI%0/\Y-C'_,"PN_R0B)?\8%AG_&!89_QL7 -M&?\?&QG_+"4?_X!V;/]G6US_8EQ:_VEF8?] /3S_'AH<_QD7&?\T,B__)QP; -M_THS)_\Y)1W_RKV\_X-Y=?\@&1G_+"HL_S,Z.O](2TS_*2HK_V%B8_]]?G__ -M$1(3_[.UN/\;'2#_%A89_QP:'?\I)B'_O;BX_V!:8O\;&![_,C<\_S at Z/_\? -M'"+_*"HO_T!!0O\7%!K_)R,K_Q,1%/\,"@W_,C S_Q84%_\2$!/_'QPB_Q at 5 -M&_\3$!;_$0X4_Q at 3%_\9%!C_%A$5_Q40%/\2#Q7_&A<=_Q,0%O\2#Q7_&18< -M_Q$.%/\:%QW_$Q 6_Q82&O\7$QO_%1$9_Q82&O\?'2#_+"HM_RTK+O]24%/_ -M24I+_T5(2?]$1TC_0T9'_S]!1/\^0$/_04-&_T)$1_] 0D7___C[_R(?)?\5 -M%AW_'QP;_SPV-/\@&Q__(QTA_RX?'_\G%Q3_(AH>_Q,5&O\1%!7_0$%"_XB& -M at _^;E8W_Q\*]_];/S__=U-3_V]'-_]'%P?^>EY?_'!<9_Q82%/\4$A3_$ X0 -M_Q43%?\=&QW_$Q$3_Q<5%_\9%QG_,"XP_QH8&O\E*B;_,C8?]%.C__'QH:_RXJ+/\;%1G_%Q,5_R0C -M(O\?&AS_-"4?_R<9%O]74E3_>W-Q_R4=(/\E)"K_)BHL_R @(_\H)BG_&18< -M_VAG;?\@'R7_G)ZA_Q<9'/\:&AW_'1L>_R,>&?_$P<#_:&=M_R,@)O\7&A__ -M%QD>_Q(/%?\8%QW_*RPM_QT;'O\@'"3_$Q$4_Q84%_\U,S;_#0L._Q84%_\Q -M+C3_.#0\_QH6'O\;%Q__%Q(6_QH5&?\6$17_%1 4_Q83&?\7%!K_%!$7_Q83 -M&?\1#A3_$0X4_Q83&?\5$AC_%A,9_QL9'/\9%QK_&1<9_Q$-%?\3#Q?_.#0\ -M_RLH+O\G*2S__QP:'/\I -M)B7_CXZ'_Y65C/_$PKW_UL[,_]7*R?_:S\[_S<+!_Z&=F_\G)"/_%A(4_Q<2 -M%O\3$13_%Q47_Q84%O\5$Q7_%1,5_Q at 6&/\C(2/_&QD;_R0H)O\Y/CS_+S0R -M_R0I)_\[.SC_&R,M_S9&8/]#3VK_-3I3_S Z3O\]3UW_+#Q,_RF___Y^7E?]/34__24=$_Q\;'?\< -M&!K_(R4H_SY*4_\6+3+_3V)N_XZHM?\<)27_)2 @_SP_0/](34O_5E93_TU, -M2_],34[_LK2W_Q@;(/^TK[/_'AP>_Q\B(_\>&AS_(1\<_[FUL_]84U?_%A4< -M_Q(/%?\2$!/_$ X1_Q84%_\?'2#_%1,6_Q43%O\4$A7_$Q$4_Q$/$O\3$13_ -M$A 3_S(?\7 -M%1C_$ X1_QH8&_\4$A7_%!(5_Q02%?\3$AG_$Q(8_Q04%_\3%!7_%!4<_Q . -M%_]13U+_'QP;_VYO_Y>- at O]W:V+_.#(P_S] 0?](2$7_ -M:FYE_VIN9O]U at X;_.UUQ_WVOQ/^@Q^#_>**R_W6$A/^$>WO_0S]!_QLC(/\M -M,R__0TA&_W5Z>O^XP,+_%1\C_[V[OO\<&AS_&AT>_QX:'/\5&!+_MZFF_YN -MAO\4#Q7_$1$4_Q02%?\4$A7_$ X1_Q02%?\3$13_$Q$4_Q$/$O\2$!/_%1,6 -M_Q,1%/\4$A7_'ALA_Q,/%_\1#17_$ P4_Q$/$O\:&!O_&1<:_Q at 6&?\2$!/_ -M'1L>_Q02%?\:&!O_$@\5_Q(/%?\5$AC_%1(8_Q,2&/\1$QC_$Q4:_Q<9'O\1 -M$AG_$Q(8_S(P,O\?'1K_H9R<_X^$@_]H7%?_9EU=_V!<7O]>6ES_2D9(_U%- -M3_]24%/___3T_RPG*?\>("7_(1X=_RXF)/],1DK_(R F_R8>(?\J(B#_'1@< -M_Q@:'_\<&AS_=G-R_X.">_^8F(__O+JU_]C0SO_>T]+_V<[-_\6ZN?^JIJ3_ -M1T1#_Q82%/\7$A;_%Q48_QH8&O\7%1?_&!88_Q<5%_\7%1?_&QD;_QT;'?\? -M(R'_,38T_S,X-O\=(B#_.#8Q_R0B'_\?'"+_%A,?_Q01*/\P-U7_'S%5_R V -M7/\O5'?_.VJ-_RU:@O\>16__+%5Y_RY(;_]\@XG_GI"!_VQ at 5_]%03__+C$R -M_RHO*_]?8UK_ at 7]Z_UUF;?]9?)/_;YZV_Y_!V_^#I;G_H::K_S,L+/\T-3;_ -M55I8_WZ ??]L:VK_*2PM_Z"DIO]>8VC_PL##_Q,1$_\0$Q3_'AH<_R,A&O^X -MKZG_BWQ\_Q<1%?\6%!?_%!(5_Q02%?\3$13_$Q$4_Q,1%/\2$!/_$A 3_Q,1 -M%/\2$!/_$Q$4_QH8&_])1TK_%1,6_Q .$?\2$!/_$A 3_R >(?\B("/_(R$D -M_Q<5&/]$0D7_%!(5_Q .$?\4$!C_$@X6_QH6'O\G(RO_,2XT_S at S.?].2%#_ -M85ID_Q$.&_\4$1W_'!@@_T(]0?^MJ*K_LJJH_WMO:O]L967_BX*"_W!G9_]L -M967_7%=7_T,^0O__^?K_)R8M_RHO._\U-#K_*"(@_U=15?\>&R'_EI&3_[2L -MJO\^.3W_#A 5_QH8&O\>&QK_@'YW_Y63B_^\NK7_U]'/_]O0S__7S,O_PK>V -M_ZVII_\D(2#_&A88_Q40%/\3$13_&1<9_Q<5%_\8%AC_%Q47_Q<5%_\;&1O_ -M'QT?_Q\C(?\O-S3_.#T[_QPA'_\T.#K_'R$F_QH='O\1%AS_%QHL_Q8^7_Y:QO/]\F*#_7GB#_T-79?](97'_,D=D_WE[>?^6A';_<&5:_TM' -M1?]"14;_,38R_XZ/B/]Z=W;_'!DF_T%:H/^=EY7_2D="_U535?_6RLO_ -M6U-1_TI#0_\:%17_'!8:___X\_]!/4;_4UAJ_Q02%?\D)"'_;V1I_Q<4&O\3 -M%!7_*!T<_Q80%/\7%AS_&A88_X^*BO]_>'+_G9>/_ZVKIO_2T,W_V-#,_]?+ -MQ_^MJ*/_JZFF_QD6%?\;%QG_&A49_Q,1%/\7%1C_$0\2_Q02%?\5$AC_%A07 -M_Q84%O\Y.#?_)",B_RDX-/\U.3?_&1T;_R\T,/\E(BC_'1\<_Q0:(O\7&SO_ -M'!XA_UM95O^+F)W_B:.F_X69G?]E;6__6&)?_U=O;/\E0G+_>'U[_XMU<_]O -M95K_3TE'_R0E)O\C)2+_G92-_UUL_["PL_]"1$G_LK"S_QH: -M'?]S=7C_%1(8_QXB)/\E*2O_%!07_Q,.$O\6%!?_&A@;_Q<5&/\2$!/_%1,6 -M_Q,1%/\0#A'_$0\2_Q$/$?\1#Q'_#PT0_QL8'O\?)CS_%!8E_QT8&O\E("3_ -M$A 3_QD7&O\L*BW_'1L>_Q<5%_\5$Q7_34E+_RDD)O\:$A;_%A(4_Q(1$/\A -M'R+_$18<_Q@>(/\L*2C_'Q,6_V1:;?\;$BK_C("5_X%V??]%/#S_(1X=_SQ -M/O\P,C#_S\3#_S U,_]'2$G_(!L?_QH8&___\_+_*" C_R0A)_\A'!S_/T$^ -M_W1I;O\0#1/_)28G_S4J*?\G(27_%!,9_QL7&?];5E;_9V!:_Z":DO^EHY[_ -M@(6!_YR=E_^2D(O_=GES_WAX=?\7%!/_&!06_Q<2%O\1#Q+_%A07_Q02%?\7 -M%1C_%1(8_Q84%_\C(2/_&QH9_QP;&O\G-C+_.#PZ_Q@<&O\O.SC_)2(A_S8P -M)O\F+#S_'B=0_Q4;(_\B'AS_5%M;_U1G9_]TBHG_>XZ(_V!J8?]9<&O_+DM[ -M_W=\>O^9 at X'_=6M at _W9P;O\J*RS_,#(O_X^. at _]J8F#_#")CK_.3U%_R&_\F-#/_AIN=_W.)B_]A=W7_6V1=_UYU -M'Q^_YR'@O]G6DW_BH)^_Q\@(?\O,2__AXZ"_ZF5C?]06&+_9)2I -M_WFHP/^;S>C_6WR3_[RWO?^"=G?_'R A_SL^/__/R_WEW=/^FEYC_%1,5_RDM+_^[M;/_G)>9_Q at 3&?\=&Q[_%Q(2_T5) -M0?^HG9;_A8-^_V5O9O^%C8/_;'1J_V=O9?]I;67_%Q47_QH7'?\:&!O_&!88 -M_QL9&_\>'![_'!H<_Q at 6&/\:&!K_&A@:_Q at 6&/\7&!G_*"\O_S([._\4&1G_ -M-3 \_R(F'?\@%A__'2DP_R$V;/\6%"3_(A\>_R$M-/^*I*?_ at IVD_UUT>?]& -M4D__46IO_RU5?/]T>8O_D8!R_W- at 5O^>DHW_(2(C_Q\;'?^2BH;_IYV2_YFJ -MM_]VHKS_F,38_ZG-XO\J.TC_B(.#_YV8D_\>'B'_2TI0_\7 PO^NIJG_.C at Z -M_S@[//]+3D__/D-#_QH='O^"?H#_&!D:_QD9'/\<'!__$Q,6_Q04%_\6%AG_ -M%A89_QH:'?\]/4#_'Q\B_QD9'/\?'R+_#@X1_Q0.%O\4#Q/_$0\2_Q(0&?\8 -M(CW_(BI6_Q8<-O\8&"'_5$QG_T ^1_\K)R__&QHA_X.!?O]23T[_&A88_RE -M_RLH+O\?&R/_%!(4_V)C7?\;&QC_,S$L_QL8%_\5$Q;_*2TK_Q at 6&/__^/?_ -M0SL__Q\>)/\5%A?_)24B_[&EIO\;&1O_&1L>_QD3$?\6$1/_'!<=_QL9'/^2 -MC8W_14E!_Z*7D/]_?7C_7&5>_V9M9?]@9U__86A at _V1H8/\8%AC_&18<_Q84 -M%_\6%!;_&A@:_QT;'?\6%!;_%1,5_Q(0$O\9%QG_%Q47_Q<8&?\F+2W_-#T] -M_Q09&?\S,#S_(2@>_QH0&?\)$AG_&REA_QL7)_\G(1__&!H=_S1+2O^%H:3_ -M9'A\_TU65O]2:6C_,UAW_W%R??^7@&W_A7=N_ZB at GO\A'R+_'QT?_XV*A?^H -MH97_D:*O_R5/:?^SS^3_M'B'_'AXA_T-#1O\J*BW_(" C_RHJ+?\2$A7_% X6_Q0/$_\.# __ -M$Q$:_Q4A//\:)53_'"=*_S(U3O]B5'K_@'Z'_PT0%?\5$A[_$ T,_U!-3/\9 -M%1?_(!L?_T-"2/]65%;_8UQ<_Z:BJO]N;W;_%A07_QD2$O\Q)2'_'QH:_QL4 -M%/^IHZ'_%!$7_Q,/%_\/#0__8F-=_YN;F/\]/3K_'1L=_QL9'/\M+BC_&A88 -M___X]_],1$C_)20J_QX?(/\O-##_O[:V_QD7&?\D)"?_LZNI_[JUM_\;%AS_ -M$0\2_QX9&?\?(QO_H9:/_X!^>?\T/#C_.3\[_RTS+_\U.S?_76!:_Q at 6&/\4 -M$1?_%!(5_Q,1$_\5$Q7_%1,5_Q43%?\3$1/_%!(4_QD7&?\9%QG_%A<8_R$H -M*/\Q.CK_$A<7_RTM./\C*R'_(QDB_Q\E+?\?+67_-C5&_S'![_ -MC8Z(_YV8C/](66;_1VV(_Z_/Y?]TCJ/_1%1>_X2$@?^9FI3_)RTO_S U.O^P -MKK#_P[_!_V1I:?]<:&?_='M[_X2)B?^1CY'_J*"C_Q at 3%?\5$Q;_&AH=_Q 0 -M$_\7%QK_#@X1_Q86&?\='2#_'AXA_Q\?(O\9&1S_&1D<_P\/$O\3#17_$PX2 -M_Q .$?\4$AO_%1XV_QDC4/\;)4K_%!DW_V5/?/]^>87_$!@:_QH:)_\=&1O_ -M55)1_R at D)O\P*R__)R,E_R(8&_\R)2K_>7!W_T$V-?]@5EG_$0X4_Q00$O\6 -M$A3_&1(2_Y6/C?\5$AC_%! 8_Q<5%_]=7EC_GIZ;_S$R,_\<'!__'1L=_TM* -M0_^'A(/___7R_T Z/O\;'"/_&!D:_WAZ=_^\M;7_&A@:_Q43%O\F'Q__&A88 -M_Q83&?\='"+_BX:&_RHK)/^=E(W_ at X%\_R\W-/\H+2O_&1\;_RTS+_]365'_ -M&!88_Q01%_\4$A7_%1,5_Q02%/\3$1/_%!(4_Q43%?\4$A3_&1<9_QD7&?\7 -M&!G_(B&O\=%1G_&1\G_R0V;O\9'R__)BHB_RTP -M*O\V+2;_.S8V_VUP_[[#P_\^04+_S?]'1$/_&!06_RTH+/]'0DC_13M$_T,T/_^$?(;_85-4_Z&9G?\4$AO_ -M$Q48_Q,1$_\<%Q?_EY&/_PT+#O\5$AC_&!<6_V5F8/]K:6;_-38W_QH<(?\4 -M$A3_5%)*_[VZN?__]O#_54]3_S4Z1O\H)2O_)" >_[&NK?\9%1?_&A49_V%6 -M5?]C657_&Q<5_QT<&_\J'!W_*"DB_Y64B?^'B(+_)2PL_Q\F)O\>)B/_*C(N -M_TI63?\8&1K_%A$7_Q,1%/\6%!?_%A07_Q84%_\3$13_%!(4_Q02%/\6%!;_ -M&1<9_Q<5%_\?(B/_)S,R_PL2$O\M-3+_#Q$@_QL8$_\7(2S_&3!E_QXA,_\A -M'QC_+"HE_SPZ*_\G(AW_2D<\_X*(A/\C0F3_+%>%_QQ B_\M3I;_26=]_\"N -MLO\:'R3_(QD<_Y"0@?^>G)7_C(Z3_YFDJ_^7H[+_1UAE_SI&2O^.AH+_J*6D -M_]W5V/^3F)C_J:JK_\&_O/^ZN;C_V-/7_[JVM/_)PL+_ -M7O]K;6K_E9.._U%-2_\7$A;_+"@P_QX=(_\R*S+_.C$X_WYY?_]42TO_J:"@ -M_QP7&?\8%AG_$Q(8_QD4%O^EGYW_&!,7_Q43%O\:&1C_ at 8%X_YF6D?\\.#;_ -M)B(D_QD8%_]334/_P+V\___T\/]]=G;_&1HA_Q .$?^(A(+_JJ>F_QX:'/\= -M&!S_=&EH_VYF9/\:%17_'1L=_R\G*O\7(!G_-CTS_SI"/O\F+2W_(R8G_QD= -M&_\I+BK_1E!'_QL<'?\9%!K_%1,6_Q at 6&?\8%AG_&!89_Q02%?\6%!;_%1,5 -M_Q84%O\9%QG_%1,5_QXA(O\C+R[_$!<7_RLS,/\4%B7_&Q at 3_Q0>*?\9,6C_ -M+S-(_TA&0_\D)"'_+2LC_SHP,_\Y,RO_/STZ_R1 8O\L5X7_'D:1_RI+D_]$ -M7W?_MZ6I_Q,:&O\B%QS_C9!^_Z. at E/]X<&[_P;6X_]++U?\<'B;_.#L\_[6H -MH_^II*3_V<_2_WV"@O^;GI__RL7 _[JTLO_7G_B8:% -M_Q\>'?\7&1S_%1<:_Q$1%/\7%1C_%!46_PX/$/\_0$'_'A\@_R-_V-: -M6O^BF9G_'QH<_Q84%_\3$AC_'!<9_ZJDHO\T+S/_&A@;_R&1__%1(8_Q<9(/\4&B+_=W!W_QPD(/^*CXG_>7Y\_S5!0/\Y -M0D+_.4- _SM&0?]"3D7_$A,4_QD4&O\5$Q;_%1,6_Q84%_\7%1C_%!(5_Q84 -M%O\7%1?_%A06_QD7&?\8%AC_'2 A_R(N+?\@)R?_+#0Q_Q,5)/\<&13_"Q4@ -M_QHR:_\9'S7_0#\^_T!"0/\K,"K_'QPB_S8T+?\W.3;_'S99_RE7A/\:1I#_ -M*TJ2_SE2;_^QGZ'_%AX:_R8;(/^*BW[_I9^7_VA:6__JV=G_Z-C<_SDT-O]Y -M>7;_UGO_8S,__C9*2_WR#@__(QK__O;BS_^#7U__*P;O_O[>U_XJ% -MA?]Q;FW_+BTL_QH<'_\6&!O_%!07_Q at 6&?\/#0__$Q$3_Q,1$_\D(B3_'AP? -M_QP:'?\9%QK_%!(5_Q4/$_\4#Q/_$ X1_Q,3%O\8'RO_'R5%_Q$7,?\:%RW_ -M6$EB_V1I=?]D:6G_5EA5_X6#?O]134O_&A49_U).5O]_?H3_?WA__X!W?O^V -ML;?_A7Q\_Z:=G?\<%QG_'!H=_QP;(?\<%QG_K:>E_X:!A?\[.3S_+RXM_X:& -M??^=FI7_244]_QH8$_\:&!7_-"TG_[ZXO/__^OK_O+&P_R'B'_&AH=_Q04%_\1$13_% \3_Q0/$_\3$13_$A(5_Q<:&_\:'2[_#1$@ -M_Q at 1(O\E&BW_)RTU_S8[.?]45E/_55)-_U103O\9%!C_44Y4_RXK,?\B'2/_ -M+B4L_VYI;_]-1$3_KJ6E_Q at 3%?\5$Q;_#@T4_Q0/$_^LIZ?_?'AZ_S at V./\P -M,"W_EI:-_Z& -M_SH]/O\N/S__,4)"_S1&1/\Z3$C_2E-,_Q05%O\6$QG_'!8:_QD7&O\>'!__ -M%1,6_Q,1%/\6%!?_%!(5_QP:'?\:&!O_%148_QH>(/\B+S#_&B(D_R(J+O\3 -M'2?_(AX at _QH=*?\A.G7_)"9!_RHE(/]144;_.SLN_UA93/\Q-"C_'B =_Q at O -M3/\?2G3_"39]_RI+E/\B/V__Q*^K_Q08(/\F(1O_='1Q_ZBCG?])/SO_ZMO; -M__+5_];'Q_^YN;;_V\_0_YB9FO]67%[_S\C(_[JRL/_:TM#_ -MPKJX_[NSK_^EFZ3_4DU-_R(@'?\>'23_%!8;_Q<5&/\<&!K_$ T3_Q,0%O\3 -M$13_*RDK_RLK+O\9&R#_%!8;_Q$3&/\D)2;_-38W_SX_0/]+3$W_*"8I_Q88 -M&_\L,3'_9FAF_U!44O\\/CO_5U)-_VQ at 6_]__R(?*_\6#QG_ -M%10:_Q<8&?^BG9W_IIZ<_TI(0?]&1#W_3DE#_U),1/]_=W/___#L_[&EJ/\> -M&R'_&QL>_R4@(/]U<'#_&147_Q$/$O^JHZ/_LJNK_Q<3%?\3%1C_'AH<_R$I -M)O^QKJW_P;R\_W=\@?])457_0TM-_T)+2_]*3TG_%Q47_Q,0%O\2$!/_&A@; -M_Q02%?\5$Q;_$Q$4_Q04%_\2$A7_&1D<_QH:'?\8&!O_&Q\A_R M+O\B*BS_ -M(RDK_QHE+/\C)2/_)28Q_R9">_\?)#[_)R,A_S4V,/]'13W_5E9+_TU/1O\A -M(R'_%2Q)_R!+=?\)-GW_)D>0_QPY:?^QG)C_%1DA_R8A&_]34U#_G)>1_T V -M,O_NW]__[]G:_S N*__9T<__W]#0_WMY=O_;S<[_GYV?_T5)2__3T,__K:NH -M_]73T/^\NK?_HYZ9_ZF?J/\T+R__'!H7_S4X/?\>(R/_%AH8_S at Z-_\S+S'_ -M&A88_W!M;/]&1$'_*"'%[_WYW@?^NI['_J)^?_Z^FIO\:%1?_%Q48_Q<9(/\4%2#_(R(S -M_QH7+O\:%RW_$Q B_QD5)?\4#!K_$ P4_S0Q,/\_/C/_2T@\_S at V+___\^__ -MMZNN_Q42&/\7%QK_=7!P_STX./\6$A3_&!89_R8?'_\;%!3_&Q<9_Q47&O]* -M24C_-#PX_\.[N?_JV]O_X-'2_^+0U/_9R,C_T\/ _Y^:E/\?&QW_%1(8_Q,3 -M%O\8%AG_$Q$4_QD7&O\5$Q;_$! 3_Q 2%?\9&Q[_%QD<_Q45&/\9'1__("TN -M_R,K+?\H*RS_'2HO_R4K)_\L+C;_)$%W_R4K1?\C'R'_)"8D_S\]-O]144C_ -M75Y7_Q at 9&O\.)$3_&41N_P8S>O\H29+_'CMK_[NFHO\@)"S_)2 :_TM+2/^A -MG);_.C L_^76UO_PVMO_-C0Q_]C0SO_>S\__FI:4_][/T/^EH:/_2DQ/_]#) -MR?^LIJ3_U,[,_\"ZN/_$O+C_O;.\_S(M+?\R,"W_2$9(_YN;F/^8EI'_/3LT -M_ZFEH_\S+RW_KZRG_T ^-_^O_\JRJ?_)L:C_PZF at _[RAEO_5N*S_OZRB_T,W,_\> -M&1W_1T)(_Q<3%?\?&QW_)2$C_T(^0/\_-S7_HYJ:_QL6&/\7%1C_%!$7_Q<3 -M'/\-#!G_%!(E_QT9,_\<&#+_&Q at O_Q42*/\?&C3_)B,P_S0R+?\T,BO_4%53 -M___V\O_!M+/_'QXD_Q(4%_\=&1?_)!\?_R$='_\5$Q;_-"DH_T,X-_\?&AS_ -M&AH=_T1&1/\P.#3_P[FU__'1_R,@'_\6 -M&!W_%QL=_Q\B(_\='2#_(" C_R(B)?\E*2O_)2LM_R8L+O\J,#+_+# R_S(X -M.O\E,C/_)C$R_RHO+?\?*C'_)3 I_R4G+O\D/W7_*3%+_R0B)/\G*"G_1T=$ -M_U153_]254__)B at K_P\D0/\80V__!C)\_R9'C_\C/FW_N*>G_S O-?\K)B'_ -M,S$N_Z";E?\T+"C_Z]S=_^_9VO\L*2C_ULW-_]O,S/][DO_)KZ;_Q:J?_\JRJ?_*LJG_Q["D_\JSI_\[+RO_ -M/CH\_Q\=(/\M*BG_2$E#_TI+1?]24TW_4E--_TQ(1O]+1D;_&147_Q45&/\7 -M$A3_%@X8_Q80'O\7%1[_%A,J_Q41*_\7%2__&ALT_R$://\>&"S_'1P;_R4D -M(_^(@X?___+R_\V\MO\@'R;_%ALA_T-!/O\E)"/_%A06_QH8&_^,?W[_FHR- -M_R$7&O\@&R'_.C\__S4W-?^_NK7_\.'<_^W?W/_CU=+_VLK'_^'1SO^RJZ7_ -M/T$__R\Z._\N.CG_+3DX_RTY./\N.CG_+SLZ_RTX.?\N.3K_-#] _S(]/O\N -M.SS_+SP]_R8S-/\@+2[_'2XD_R$E-/\;*BG_,#@Z_R4]=/\H,TS_'R A_RDF -M)?\I*2;_2DU'_SH^-O\V-SC_%R$P_Q\[9_\0/(#_'D!__RH]9_^?FZ/_0S at W -M_RN_]2YLO^LEH[_OZ:?_^'(P__:P<#_T[V_ -M_QL4%/\?'!O_7UU:_R8D'_\[/SW_+"\P_SL^/_\W.CO_.3T[_UY at 7O]?8&'_ -M2TM._Q00&/\4#QO_#Q00_QD7*O\6$2W_%Q,M_Q44,?\3$C?_.35+_S,R.?]$ -M1D3_0T5#_]'(R/__\_?_SKRY_Q\<*?\<'RO_3$E(_QP;&O\9%QG_&1<:_QP6 -M'O\@&B+_'!<=_Q at 6&?]'3$S_/3\]_[^ZM?_LW=C_\-W7_]"]M__HU]'_X-'+ -M_ZNJH_\Y0$#_+SL__R at P,O\L-37_*34T_R at T,_\G,S+_)"\P_R,N+_\C+B__ -M(BTN_R8Q,O\K-C?_*C4V_R)_\?(23_+4A^_RHT3_\C -M(R;_+"@J_R\M)O]85TS_8V)7_UQ85O\-%B?_#"91_Q$Z?/\>1(+_)SE?_[*M -ML_\K)BC_'ATC_R0?&?^\L/]=6%+_I9Z8_YB/B?]Y -M;6C_1$0[_U)52?]*34'_14@\_V%A5O_&N*__[]/,_^#'P/_ERK__\-?0_]+# -MP_\@%A__%1 6_Q at 4%O\E(B'_+RTJ_Q83$O\U,3/_0S]!_QH6&/\F(2'_6%-3 -M_W5POK?_>T,W_,R at G_Z&/_\I)D/_8F-N -M_SH[//\F)BG_)",J_RPL+__2RLC___+M_X1R:/\6%!?_%!8;_UY=5O])1T3_ -M'!@:_QP7&_\B%13_'1$,_QL6%O\4%!?_$Q at 8_RDM*_^KIJ;_W]#+_[*KJ_\P -M-#;_*C(T_RLX.?\J-C/_+SP]_RHV._\K,S?_*3(R_RDU-/\D,"__)# O_RHR -M-/\J,C3_("@J_Q at C)/\:(B3_("8H_R at N,/\F+"[_+"PC_QP[7?\'$R[_'148 -M_QTWXL_^NI*#_QKZ\_UY96?_,PK[_D(J(_T=(2?_'Q<#_,BHH_\S$ -MR/\D)"?_N+"L_]C*Q__.P<#_A'UW_R(D&__*QK[_2#PU_ZRLH_^LK*/_,"\H -M_ZNLI?\W.S/_D)*)_S\_-/]$13C_<7%D_V9G6O^1BX/_V,6__]["O_^ID8[_ -M)Q at 8_RD=(/\2#0__$0\,_RLK'/\R-1__,30=_R\S'?\N,"W_,C,T_S$R,_\Q -M,C/_*BDH_Q43%?\8%AC_3DQ/_Q48._^AG+;_9F%<_Z>BNO\<&S__(R(__UM; -M;O\S.#+_.3TU_R ?)?\K*#3_961J_\C"P/_TZO3_5T9&_R4A*?\;'27_'1P; -M_QD7&O\;&![_&Q<@_QP8(?\;%Q__&18<_QD7&O\@'B'_&QH9_QH8%?\R*"O_ -MVL[*_TE24O\U/4'_-3T__S$\/?\O-SG_*C(T_R(?\7'1__&2$C_QHE)O\>*2K_(2PM_R$L+?\N-2G_-TEE_Q$9 -M*?\:&1C_(BQ._RLT1?\@(B#_'AHC_Q\A)O\B)2;_(R8G_R at M+?\P-3/_,C4V -M_S0S.?\\.$'_/C8Y_UA33O^&?GK_M*BK_\&\OO^FFY3_1T1*_^3=W?_RV];_ -M>71T_]K2U?_9R,C_T+NY_X)Z=O_$N+G_)B$C_\+!P/]03E'_-#8[_[^]O_]? -M75__O+&X_RLG*?^[LJS_WL[+_V%95_\V-2[_R<6]_V=F7_\_.C3_P[JT_SDW -M,/^NHIW_;&9>_SHZ+_]T=&?_:6=8_X![:?]W;UO_='!A_RXI)/\@&QO_$PX2 -M_Q$0%O\3%!7_&!4;_Q at 2%O\7$@S_-S$A_SLW(?\T-"'_-C0L_Q<6%?\D(B3_ -M)"(D_R$?(?\7%1C_$A 3_Q,3%O\?(23_!@HP_S6K_?WEI_WQV9O\\.C/_-#DU_P\5 -M$?\@)"+_&QP=_R(@(O\H)BC_)R8E_R at F(?\W-3#_'1H5_R0@'O]*1T;_$A 3 -M_Q(0$_\7%1C_$A 3_Q84%_\5$Q;_$1$4_Q@:'?\]0C[_(R<_^=D8S_ -M;&-=_TI%1?^1E)7_,SP\_T9+2?^1D9K_'APL_R at I,/^0CXC__^_B_[R2:O^Y -MCV'_K8E<_ZZ#5?^WBU__M(E9_[2+5_^WBUG_O(Y;_[>*5/^WBU/_O8E7_ZF -M5O^1>5[_V,J[_^31R_\L+2[_$Q4:_Q(6&/\6&AS_$Q48_R at J+?\0$A7_)RDL -M_QD;'O\F*"O_%!89_R4G*O\1$Q;_&R$C_QHB)/\?)2?_(2/_*PL7_V6__=W)F_WYZ:_][=&;_;&9<_Q\='_]0 -M3$K_4TM'_R$;&?\@&QO_+BDM_SP\.?]04TW_-#7E'_@'IR_R(@&_^QJJ3_X,[+_X1Y>/^HHYW_M;&I -M_S(P*/\V-2[_O;RU_Z2?FO\C)!W_F96-_W%E7/]U;F+_:V9:_WET:/\@'1C_ -M'1\B_QD7%/\^/3;_,#,M_TU33_]G96?_8F)?_T9+1?\I+B[_(BDI_RHM,O\8 -M%Q[_&QD;_YJ2E?^@F)O_HYN>_ZZFJ?^SJJK_N[*R_[RUM?_$O[__Q,Z]_UM@ -M6O]866#_J[.O_RLM,/^6DIK_,2PP_S8R-/]W=7?_B8F4_R0B,O\='B7_+3,U -M___T[O_4FV'_S)YQ_[Z%0__"DUW_OY!6_\256__ D5?_OY%7_[^,5__!D5+_ -MDFQ%_RT;#?]<4U/_8&!7_]+'P/_=SL__*S$S_RTR./\^0$7_)2DK_R8H*_\M -M,S7_(BHL_R0L+O\6'![_+# R_Q06&?\I*S#_%!,9_S0S.?\A'R+_&!X at _R,K -M+?\F+C+_*S V_S at T-O_4R<[_X,_7_^G7U/_MV='_\=K5__'9UO_SVMG_^-S9 -M__/7T__AR<;_^./?_Z.9E?\V,T#_)52._QXS@?\K4XK_P<+-_U=05_\G&"/_ -M='AZ_Y^7C?^'@GW_W=/6_][)SO\9'1__F9>9_\[ P?_8Q\?_9EE4_\_)P?\H -M)R;_14(]_X)[=?\^/#7_6UI3_T$\-_\3$0S_# H'_ZJBH/_.P\+_Q+RX_U!. -M1_] 1#O_6E1,_[:JI?]*0SW_+"TF_[>PI/^">&K_E8N _Y2)?O]A64__+RTJ -M_S@[0/]A8V;_8F5?_U-43?\R,2K_3$I#_RXL*?\R-#+_(RHJ_QD='_\;'2#_ -M%QD<_Q\A)/\M+S+_EXV)_Z&4C_^CEI'_FXZ)_Y6,AO^1B(+_C(-]_XR#??^$ -M?7?_*B8H_V%A:O^VLKO_,BXV_XZ+D?\6%!?_$ X0_X5_ at _]Z=8'_*BDZ_RDI -M,O],45;___'K_\6,4O_ DF7_SY94_\*37?_)F6+_R)AA_\657O_*EU;_R)EI -M_V!%(/\F&A7_(AP at _R$?*/]/3TS_S\.\_^?6UO\O,S7_%QD at _QT<(O\C)RG_ -M&QT at _R,I*_\P.#K_*"\O_Q@='?\K+B__&!D:_SL\-O]&24/_*3 P_QDC)_\< -M(R__(R8Q_S8S.?_1R,C_Z-;2_^W:U/_VW]K_^-_:__+_QX;(?\G(B;_)" B_QP:'/\9&AO_(!TC_Q at 8&_\7%1C_<6=J_XN#AO^> -MF9G_='!N_ZNHH__.O+C_+B@@_R\R)?_'O:[_GX]\_YN.??^1B('_75Q;_TY1 -M5O\Y04O_-3]*_SD^1/\I,2[_+S8/]46ES_ -M4%98_U%24_]/3E7_9F9U_Z^IM_]X='W_B(6+_X:$A_^IIZG_BH2(_W]ZAO\E -M)#7_.#A!_VQN'B'_(2,F_RDM+_\H*C'_3E%6_Q46%_^1B8?_ -MT\# _]"]O?^DF)3_3$,]_T-$/?]35T[_BH1\_YR+A?]I8V'_6EI=_SQ$3O\W -M1%7_-T=;_S%"6?\Z25S_,SQ#_RHP,O\A)RG_-CH\_Q88&_\G)RK_,C at Z_S,_ -M0_\K,CC_+CH^_RPW./\9(2/_*"PN_]K2U?_;TM+_X=C8_][5U?_HV=K_Y]77 -M_^C6V/_GU=?_]./C_]3)SO]X_S%"6?\T/$;_%A@;_Q06'?\Z-SW_&18<_Q<9'O\O -M-SO_'2DM_R$J,?\C,33_(S Q_S R-?\K)2G_Y]//__+;UO_OVM7_]^+=__?B -MWO_ZY>'_]>#;__?BW?_]XMO_S[FZ_VAB:O^IJ[#_D8V5_WY[@?^XM;O_IZ6H -M_VUG:_]Z=X/_(R0U_R at I,/\I)RG___7K_]FE;/_-IGS_VJ1A_\JA8/_%E5[_ -MO91C_Q\- /\@&#K_,"I&_RHI,/\\/#G_3TI%_SDT+O\]-3'_U,3!_^W9U?\V -M.SG_(R at M_R0D)_\M,C+_%AH8_S$S,?\_/CW_+3(R_R(F*/\G*2S_'1@>_VQF -M9/_$M[+_[M;3__'7U/_VW=C_\][9__'>V/_XW]K_[MO3__G%@O_)O[O_ULC%_[ROM/]J -M8&/_T<7!_\R]N/]M9V7_)B at K_R(G+?\V.3[_)BHL_TI.4/\[/T'_1TQ,_SL^ -M/_\@(2+_'QT?_];*S?_&O+__&A88_QX:'/\Q-CO_*B0H_Q8>(O\N/TW_,3]8 -M_SE#3?\]4&+_,$1 at _R8S1O\1%Q__.D=8_RXY1/\=&AG_*S \_RPL+_]A863_ -M+#0^_S=!1?\@+"O_+#4[_R0Q-O\K-SO_)BPN_RTK+?_GV-/_[]K5__+=V?_U -MW]W_^.'B__;@WO_VX=W_^.'<___GX/_FU=7_U?_TWM7_\N+8__7BV/_AS\O_V,7+_SQ$ -M5/\M057_.T5:_R=!;/\7("[_GY.$_R Q5?];763_%QXD_QLS6O\C,$G_$BQ- -M_R=6C?\L69G_,4V&_[Z^S?^NL*W_0#@[_QD4&/^!A'C_@'Y[_\:\N/_5QL'_ -MNJZQ_X%Y??_&O;W_R;V^_T1 0O\/%1?_&!HA_R,G*?\3%QG_%!@:_Q@<'O\1 -M%!7_'A\@_S$O,?\Y-3?_-C$W_S at Y0/\W.4#_'!LB_R8O+_\B(2?_'2HW_RT^ -M5O\Q/E'_)2HO_QXH-_]%3V3_EI6;_ZZII/]W?HK_,#I(_[*MK?\Y/TG_04)# -M_]'-S_\P-#S_-3U!_QLD)/\L,SG_("TR_S$]0?\8'B#_%187_]_0R__RW=C_ -M]=O8__G__#9VO_OVMC_[]G7_YJ.D?^$AHW_J*NP_Z";G_]F -M867_K*>K_Z:AI?]S;G#_$1(=_R F-O\N+C?_H9V?__SPZ__=IVW_RJ!R_\:7 -M7?^ND'K_.2(S_QX7-?\K)$+_*"$S_QP7'?\?&AK_(!D9_QH3&O\=&!S_*24C -M_\["O?_SW-?_/STZ_SDW.?]A6EK_-C at U_QP<&?\G)2+_+RHJ_YB,A?^FEHW_ -MT[VT_^_3R__ES\;_\-C/_^W1R?_LULW_\M;3_^+)R/^RH)W_N*:C_T8Z-O_6 -MSMC_-$=9_S1.7/\[/DG_.%:"_Q\?(O^QFGW_)3MB_T-%3/\Z/S__'#%4_Q8@ -M-/\@,D[_%SAM_R=,C?\L0'K_N[G)_X**AO\D("+_&!,7_W=Z;O]V=''_M:NG -M_]?'OO^^L;#_8%M?_U)-3_^PJJ[_B(J/_R$F*_\<'R3_&1T?_RTQ,_\R-CC_ -M)RLM_R4F)_\>'![_'QL=_YF4EO\X-SW_1DM1_R\T.O\7$QO_("0B_R$>)/\A -M+CO_,$!0_SD[0_^IHJ+_H**Q_TU79O][>W[_YN#>_Y*9I_\V/TW_P[BW_S@] -M0_\Y/CS_S,C&_S_QD1)?\T+D+_$ T9_Q84%_\8$QG_% T5_Q(/ -M%?\K*"?_Q;NW__#6S?^KHIO_:V5C_R,9%?\E("3_&10:_Q,.$/\<%Q?_$@T- -M_R(='_\?&!__(QPD_RH?'O\T)"'_.",A_RX<&?\G&1K_(AT?_QTB(/]U>7?_ -M0T5#_];1T_]::WO_&B8J_Q89)/\F3H;_&A\K_W)B4O\=-%[___CSLG_D7UU_SXU+_]&1#__\N'4_Y^'>/^LFHS_ at W=N_]_0U/]!0$?_769M -M_T!#2/^;F9O_&147_YJ6F/^GHZ7_<&MO_R(B,?\E*#K_+R\X_ZZFJO__[M;_ -MQYMS_SX>!/\<%17_&108_Q40%/\7$A;_%A$5_Q,1%/\6%!?_%1,6_Q43%O\4 -M$A3_%!,9_QD4&/^^LJ[_Z-7-_VI=6/\E'!S_2D \_TI%1?\9%1?_%A(4_QH6 -M&/]12T__-2\S_R8@)/\Y,S?_%A$5_Q<2%O\9%!C_&A49_QL9'/\5&1O_.D1! -M_U%64/\R-T/_[-O._S5#6/\G(R'_$!8F_S1:C?\;&RK_4T X_QTI1O\9'"[_ -M&AH=_Q4=,?\;)3#_'2 Y_Q <.?\C-V3_(#UW_ZVQQO^2C8__+2\T_Q89&O]P -M&R'_)R(D_TA#/?\9&A3_$1$4_RDG*O^&?GS_+RTP_Q,6&_\0$Q3_*BXL -M_V=F9?\P,3+_'2 E_SD^1/\U,S;_+2PK_T!#5?\Q04K_ at I"/_]W9V_\P-$G_ -M-D!/_[^WL_\U.D#_/$$__\W)Q_\O,3C_-C<^_SX^1_\G*C7_)24R_QDB*/^' -M at H3_M:ZU_][3R/^&<67_4U)'_RTL)?_?T,O_CGEM_ZF8B/]H9%S_TL+&_S]! -M2/\V.D+_0T)(_YB6F/\B'B#_E9&3_Y>3E?]J:&O_)24P_R$C,O\T-#?_K:BN -M___MX/\L'P[_'QPB_QT:(/\A'AW_'AD=_QD4&/\9%!C_%A07_R >(?\O+3#_ -M-S4X_SD[0/\_0$?_5E%7_\:YM/_NV]/_BGQY_T4V.O\I%QG_%@\/_Q,/$?\8 -M%!;_7%A:_VME:?]=5UO_2$)&_UM56?]54%3_%1 4_QX9'?\2#1'_C8>%_ZVE -MH_^]N+/_N+"L_Z6DJ__"L:3_4F)\_R,@'_\3&2/_1EN+_QD;(_]>4TC_$Q at Q -M_QH<*_\2$A7_%ATK_RHS.O\5%RS_#A4I_Q ;/?\C07G_HZF__XJ"AO\I(2O_ -M%1,6_V9E9/\B(A__,S0N_XZ%?_^BG)K_%Q47_RHG(O^(@'S_C(6%_Q\:'/\9 -M%QK_%A06_Q04%_\8%13_,28?_V5=6?]84U?_-#(U_XB ?O]544__@()__X:( -MA?\W/#C_&!L at _V-C9O]N:6G_L*RN_[VZN?]W=V[_.SY#_SA#1/]\B(7_W-C: -M_SD]4O\Q.TK_OK:R_S,X/O\^0T'_S\O)_S(T._]"0TK_-S= _RTP._\E*#/_ -M(RTQ_[RSL_^VJ[#_X-/&_XAN8/]223O_8EA-__'F[_G(]^_VEC6__4 -MQ,C_.#I!_S@\1/\^/4/_D(Z0_R <'O]>6ES_-# R_VUK;O\F)C'_(2,R_S,S -M-O^OJK#_^-?H_Q@:&/\6$AO_& X7_Q02%/\5$!3_$PX2_Q at 3%_\Y-SK_/SU -M_TI(2_]%0T;_0$))_T-%3?]'0DC_T+^Y_^W7S_^$=7;_(!@<_QP7&?\7$Q7_ -M&!06_R\K+?],2$K_6U59_TQ&2O\4#A+_(QTA_S$L,/] .S__&A49_Q0/$_^Z -MKZC_Q;&I_Z")A/^ ;&C_:V-F_[BFF/\S1F3_&!D:_Q(7'/\C)E#_%1@=_UQ8 -M2?\:&"O_'1TH_QH8&O\6&"#_(RPR_Q86)?\4%A[_&!PQ_R(Z:_^4EZC_I)N; -M_T,^0O\<%AK_03Q _QH8&O\;'1K_2DA _Z&>F?\:%AC_+"LJ_T! /?\R+R[_ -M$P\1_QH5&?\>&QK_*"PJ_VEI9O]B4DG_MZJE_\*ZOO\E("3_9U]=_Y^7D__B -MWMS_<7-Q_TM/4?\V.#W_7UI5_V)64?]/35#_6%)6_TU-0O]+2DG_&1P=_W5^ -M?O_=V=O_/$!5_RHT0_^_M[/_1$E/_S@].__/R\G_*2LR_ST^1?] 0$G_*RXY -M_R8L-/\9)"7_P;:U_\*RMO_CU,[_=5U4_U!&._];44/_Z]3/_W]L8/^+ at G'_ -M9F!8_]3"QO]!0TK_.CY&_T5$2O]^?'[_(Q\A_Q\;'?\B'B#_:6=J_Q at 8(_\5 -M%R;_3$Q/_[*ML?_YV/?_%A$5_R$1%?\=#QC_%!(5_Q40%/\8$Q?_%Q(8_PX) -M#?\U,#3_1D1'_U!-4_]&1U+_5EED_TQ'3?_&M:__Y]+._XQ_?O\;&1O_%1 at 9 -M_Q43%?\8%!;_&A88_Q82%/\1"P__#@@,_R :'O\;%1G_% \3_R ;'_\4#Q/_ -M'AD=_S\^,_^]M*;_P+*I_[RVKO_'O[O_JIN._TA;>?]34%;_&A\?_RLF2O\< -M'B'_6%9'_QX8)O\?'2;_&1<:_Q04'?\E+#+_$Q8B_PP-%/\:&B?_#!I!_T9& -M4?_ N;/_)B at F_QX9'?\6$17_%A89_Q(5%O\E)A__5E-._R,?(?\A(R'_)"DE -M_S]$0O\?(R'_4U%3_VYL:?^*B8C_'1\=_XMX;O_(M+#_UL?+_R,=(?]:5%+_ -MP[V[_^+:W?^!?H3_*"HQ_R ;(?]Q96'_?G-L_SH\0?\7$AC_6%9._S0Q,/\Z -M.#O_;7%S_]G6U?\Z/U'_,3M)_\*ZMO] 14O_.3X\_\C#P_\G*RW_/D!#_T9' -M3O\H*S;_,C8^_Q&!S_+RHD_ZF?E?^/@7C_:V-9_W%@6O^2C8C_0%-E_R$9)_\9&1S_ -M(R$T_R A*/]F85O_%A(:_Q\?*O\6%B'_'AXI_R$@_\6&!W_&1@>_R_QX='/\M+"O_-#,R_T)! -M0/\N+2S_*RTJ_WA]=_^@GI?_CHB&_^#5VO\;'!W_;5Q/_]W(P__MU=K_,2DM -M_T$\//^UM[7_XMC;_X:$A_\R.C[_'1LD_VID:/]H96#_4590_VEG8O]$03S_ -M8U]=_R4B(?^)B8S_X]W;_SQ 3_\\1E3_M[*M_T%&3/\]0$'_H)ZA_S Z-_] -M1D+_24A._S8Y1/\I*C7_(BHL_\2YN/_$M;G_V -M_V]J;O]Q;7W_*"E"_RPN-O]I;&W_XMCA_R at C)_\>(![_,S$L_S&_\_ -M/SS_0T- _R0B)/\?(1__/T1 _V=D7__-R,/_ZMO at _R:_TM56?\6&!__)R at I_VUL9?]+3T?_8F-< -M_RHK)?]?9&#_45E6_XJ.D/_AV]G_/T-2_SQ&5/^ZM;#_049,_T!#1/_+RD9#_,R0D_R09&/\G&1K_3D=!_SA# -M3O\:$R3_%!46_Q<4)_\I+#?_,3,V_R0D+_\='2C_(2$L_QP<)_\4%A[_$! 9 -M_Q,1&O\3#QC_%A, at _Q<:)?\H+3/_/#H]_S\].O\].S;_/3LV_S\]./\Q+S'_ -M'AP?_QH8&_\<&AW_'!H=_Q<7&O\8&QS_BX>%_]#(Q/_IU]O_*28L_S4S+O_4 -MQ\+_[]?<_RXF*O\Q+"S_MK&Q_^G9W?^8F)O_6&9I_YRDKO\3%AO_3DY+_WM] -M>O]76%G_*RTP_RDS-_\X1TS_ at XB-_]O5T_] 1%/_.4-1_XN&@?\^0TG_1DE* -M_\O)S/\Q.#[_0D5*_SX]1/\I+#?_-3<__R at P,O_!MK7_OJ^S_]/1SO]#0T#_ -M04=#_UI:5__,RL?_3U%._UA=6?];75K_T+_%_TI-4O^TM[S_:F5K_YR6GO\F -M(27_IJ.B_YV8GO]J96G_=7&!_RDJ0_\R-#S_B82(_]C0WO\3%B?_.4=<_Q$> -M._]!3&7_*"]%_QL=+/\<'"?_(1HB_RTF+?\P*S'_,S$T_S0O,_\_04;_-CA -M_SHX.__8RG[_,"HN_Q80%/\W,37_&1<9_QP8&O\B'1__'QT?_Q00$O\N -M*2/_/45/_Q0*&?\3$13_$Q B_R$D+_\@(2C_'!PE_Q<7(/\<'"7_&AHC_R(B -M*_\;&R3_%A0=_Q<3'/\5$A[_%!0A_Q49(?](24K_24M)_RHM+O\<'R#_&AT> -M_Q@:'_\8%Q[_&A8>_QX?)O\F)2O_.#H]_QPA(?\Z.SS_O+FT_^?5V?\F("C_ -M+C(P_\*VL?_UW>#_*B(F_R\J*O^SK*S_V,O*_Z*=H?]7:V__FZ*N_Y>9H?\G -M)BS_'ATC_R(F+O]E9FW_L;;"_T9=:?^"BY'_V]73_T-&4O\Z1%+_LZZI_T-% -M3/\[/C__OKR__S$V//\[/47_0#Y'_RS_R,E -M*/\F*"O_("@J_RHN,/\M+3#_*R\Q_RDJ*_\O+S+_'B(D_T-(3?]%2DC_T+_% -M_R\F+?\H*2K_KJ*=__7=X/\I(27_+"\ -MP?^GDXO_O:.6_["6B/_!J)?_R+&?_\VRH?_!I9?_R;*F_]O'P_]:7%__KK"X -M_UA56_]U<7G_)R(F_YN9EO^/BXW_75A:_VMK>O\I+$7_-#0]_VA=8O_MV>/_ -M(A at A_QT<(_\='"/_*2,K_Q at 2&O\8$Q?_'QT?_R0@(O\>&AS_'!@:_QH6&/\> -M%Q?_)2 F_ST\0_\F("3_HYF<_[2NK/^)AH'_+"DH_QX8'/\4#A+_KZFM_QL5 -M&?]P:F[_*"(F_UM56?\W,37_F8Z3_V1<8/^"?(#_$PX2_Q40$O\F(2/_)R(D -M_Q\:'/\.#A'_%A(4_Q(>,_\H-5+_$A$>_Q(/&_\4$1W_%Q0 at _QL8)/\>&R?_ -M'QPH_QH7(_\@'B?_'QTF_QH8(?\2$!G_$1 7_Q(1&/\3$AC_%!,9_R$C)O\> -M("/_.CP__SH\/_\4&AS_-SD\_U!+3_^4B8[_:V1K_X)]@_]"0$/_8V%C_Z6C -MH/_IVMO_*R4I_RXN*__-P;S_\MK=_R8>(O\I)";_L*"H_\# O?^ZJ;G_,TQ= -M_V9U>_]OA)#_;H:9_UEXBO]RD*;_;Y"<_V*-G_\H/$K_ at H2'_]C0S/].35K_ -M.41/_UQ>5?\Z.T+_,S_V9B:O\E("3_E9.0_XR(BO]E8&+_=76$_RTP2?\P,#G_KZBH -M_^G(O]",CK_,2 F_R$5%O\F&R#_'!,:_QT7&_]- -M1TO_&A08_Q<1%?\<%AK_*B0H_QP6&O\>$QC_% P0_QP6&O\7$A;_%A$3_QT8 -M&O\G(B3_'QH<_QL9'/\>&AC_$AHJ_Q8=,?\7%R+_&QLF_QL;)O\;&R;_'!HC -M_QT;)/\>'"7_*27K_WM;2 -M_TE(5?\M.$/_+#0J_TU.5?\[/4#_+S(S_R(/\C'B#_'1@:_R,<%O\<'B/_*",I_QX:(O\='2;_'1TF_QP= -M*/\L*S+_,C$W_R ?)?\8%QW_&A<=_QH7'?\9%AS_%Q0:_Q<7&O\='"+_)B4L -M_QT:)O\7%AS_7EYA_S P,_],3$__+BHL_QT@(?\Z0D3_&1L>_Q47'_\<'"7_ -M$Q87_V-?7?_$O;?_ZMK7_RHF*/\G(1__LJ:?_^/+SO\P*"S_,"PN_\.WL_]N -M=W#_N[6Y_S]27/^0D9+_PL3)_S<]3?\Y057_>H&'_]3,RO]H:'?_/$95_SQ" -M1/]T;&C_3$M8_RXY1/\1&Q+_(B0I_S at Z/?\5&AK_)BLP_SD\0?])2$__,C8^ -M_S0U0/\@)2K_JZ*B_\:WO/^LFY7_JI2+_ZB3A_^?BWW_EXA[_Y>%>_][:&#_ -MBGQS_^?2S?]C8V#_JZNN_TI%1?](14O_(!L?_X)_?O]I96?_9%]C_UU=;/\C -M)SW_/#U$_Y60EO_DT>?_*28L_S V0/\V,S__(R,L_Q,4'_\3%!__.SQ'_RLD -M+/\N+"[_/S0S_UI25O]965S_-#)_\L -M*2__(" I_QX;)_\6$1W_%Q(>_Q<2'O\6%!W_&1<@_QT;)/\?'2;_&AHC_Q<7 -M(/\<'"7_,S,\_U=46O\J*"O_$ X1_QH8&_]@8%W_>'IW_SP_0/\5%QK_'B E -M_T- 1O\9)B?_65M>_\6RLO_RU='_-RY_S4J+_\Q+S'_ -MSL*Y_V]UA?_,P<#_.TA9_Y".D?_*Q<7_-#Y-_R\[2O]Y?G[_V];1_VUO?O\R -M0E7_+3LZ_U122_]245[_,CQ*_QD='_\5&1O_,C8X_SH^0/\Z/T7_/3]"_TQ. -M4?\P-#S_)2LU_R$D*?]K:&?_N["U_]/(Q__-P[__U,K&_]S2SO_EV=7_Z-K7 -M_^77U/_JW-G_]N+>_UQ>7/]L;G'_)"$@_SLY._\?'2#_1D1'_QH8&_];6F'_ -M'A\P_R0G./\T.#K_ at H""_^'3[_\K+37_2%%?_RXP/_\:'2C_)BHY_QTA,/\0 -M%"/_5U!:_VEK;O^^L+'_Q+G _V5E;O].4%C_1DE._RHE)_\E'A[_(1H:_R,< -M'/\C'!S_*"$A_R$:&O\I(B+_+B:_\W(R/] 2EG_.454_VIS<_]S<&O_ -M?7^._S% 4_\T0#__1T4^_U958O\B+#K_/D)$_SD]/_\_0T7_/4%#_SQ!1_\W -M.3S_/D!#_S T//\G+3?_(20I_R4G)?^BG*#_YM'/__OBW?_XW]K_^N'<__WF -MX?_ZX][_^.'<__GBW?_TV-K_;6MM_R8F*?\X-3#_DY*1_R4C)?\B("+_(1\A -M_U-26?\N+T#_)"_RTH*/\U,##_'AD9_RTH*/\D'Q__)"(D_XM^>?]%-SC_)C15 -M_Q(>._\8&2K_%A,?_Q85(O\>'2K_&AHE_QX>*?\8&"/_%!,:_S(Q./\?'B7_ -M(!\F_QX<'_\>'!__'!H=_R_R at I.O\D)SC_-#@Z_TA&2/_AS^/_,2PP_R(C*O\R+C;_)2 B -M_Q0/$_\>&1W_,2PP_T,_1_\H*B__S+_$_]G(TO]85FG_1DE;_T-#3O\I(27_ -M*A\>_S0I*/\N(R+_*R ?_S H)/\L)R+_-"\J_R at C'O\R*B;_,B*/\>&B/_&ADF_QD:)?\8&"'_*2DR_S$Q.O\K+"W_(R(A -M_R$?(?\?'1__'QT at _QP:'?\7%1C_-30Z_Q<4&O\5%1C_'R A_R\I+?\C)"7_ -M4TI$_X5V_QD5%_^EGI[_VL_6_T-#3O\\/$O_0#I( -M_S$J,?\G("#_(QP<_RLD)/\F'Q__+",C_S4L+/\X+R__,"(2S_,S(X_R4C)O\@'B'_'AP?_R,@ -M'_\A'AW_(1P at _R$<(O\F'R;_'AD=_QP;(O\O,SO_FI&8_YRAH?\V3T[_15]H -M_SHW1/^3 at XO_N:JN_V%:8?_DW>?_?H&2_T%)7?\N*C+_FY::_\_ NO\W+#'_ -M*R at N_[:II/^]KJ__?7)Y_R at C(__%N;#_FY&-_\C'SO],3E7_%A06_W^!B/]# -M35O_.D95_QTL*/],3E/_CXJ<_R at R1O\?(R7_2DM,_QX@*/\H*SS_.SU$_S0X -M.O]"2$K_.T%#_RXQ-O\N,3;_*2PQ_RHM,O\F*S'_*"LP_S0V.?\D)2;_PKBM -M_[>CF__ at R<3_BWEO_Z"-A?^[JZC_8UM9_U-+0?_FU-#_XLW+_Y:+BO\U.CK_ -M,S@]_R$>'?^0BH+_>WEQ_R8F*?\E*#3_*RX__U-26/^%A8+_V,O=_RXF,/\Q -M+##_'QLC_QL7'_\B'R7_'1H at _S M,_\Q,3K_%Q0:_S&R'_'!D?_QT:(/\H(RG_*R8J_RLC)O\M)"3_ -M)",B_V=E8/]F85O_*!T<_[*GKO]S;77_)B7%[_ -M-#8]_SQ'4O\\2U'_'RD?_T5(0O^5E)O_*2\Y_UQ?9/\;("7_+C9 _Q at B,/\] -M1DS_-#H\_T!"1?\9%QK_%QD>_RTP-?\I+#'_+C$V_R$F+/\B)2K_+C S_SDZ -M._^^M*G_K9F1_^++QO^,>G#_F(A^_\"TK?]_)?\='"/_(!\F_QX>*_\G*"__95Y>_]_0T?\W -M-3[_,# __T0^3/]".T+_+28F_R4>'O\E'A[_(AL;_S J+O\9%!C_%1 4_Q<2 -M%O\:$A7_(AL;_RLD)/\K)"3_-C$Q_R4=(/]^)/]L:VK_,"LF_YN.C?\I(R?_N*VF_R@>&O]I:&__1$9- -M_QL?)_\W0$[_1D]@_S]"3O\0#1K_"0 2_R(7+O\.!QG_*20P_QL;)/\Q-$#_ -M*"\]_R0F+?\9&1S_24E,_Q04%_\;'2+_*2PQ_R\R-_\N,3;_)"DO_R,F*_\F -M*"O_/3X__[ZTJ?^SGY?_YL_*_Y.!=_^.>W/_P;*M_VE?6_]>4DG_[M_:_^33 -MT__7R,G_14!$_SDZ._\C(1[_85]:_RLP+O\I+2O_1TE1_S0T1_\T+SO_TL;/ -M_]3$V/]%/D;_(R F_R$?*/\W-T+_.3I%_U-47_\F)B__*"@S_Q\?*/](0$/_ -MWL_/_T,_2/]#0U+_/#E&_T [0?\D'!__*2 @_S(I*?\S*BK_&1,7_QH5&_\> -M&1__'1@<_QL3%O\@&1G_)1X>_R at A(?\P*"3_D8B"_]?(P_]J7EK_)R(D_R$; -M'_\H("/_,2 at H_R0B'_]>8V/_8F9H_XJ%A?]02$;_(!T<_Q\='_\C'!S_)1TA -M_R$;'_\F("3_*B(E_T])1_^1CHG_G)>1_[2PJ/\V,3'_,"LO_W]^A?\T.$#_ -M9&9D_[NVNO_(O^EF93_ at GEY_R\Q -M.?\R-#S_+35%_SI%5O\(#R/_)1TX_VIDGO]13I#_.#AQ_Q@;2O\:$BW_+RD_ -M_Q01)/\7%R+_&!,7_QL8'O\A(23_J*BK_RLN,_\L+C/_-CD^_RPN-?\C*"[_ -M'B$F_R4G*O\S,3/_P+:L_[*?E__>QL/_DX%W_X5T;O^MFY__;&IL_X)[=?_D -MU];_X\[,_["?G_^[LK+_)R4H_R\J+O\T,3#_("8H_U]F9O\L-#[_,C=)_S P -M.__3R]7_U'RK_&ALF_R0=)_\8$1C_&1,; -M_RXG+__DU=G_1T!*_ST]3/\V-D/_3TI0_RH>)_\I'"'_+2,?_R\C)/\:%!C_ -M(AP at _R(='_\J(B7_)R @_RDB(O\K)"3_*2(B_S0J)O]E9F#_X-/2_X%O$!G_'Q8=_QL9 -M,_]75X#_4E)Y_P\/'O\E("#_+C0\_T-!0__;TM+_*BDP_RXM-/\V.$#_*RXY -M_R8J,O\A)"G_*RDL_SHU-_^_L*K_UL.]_^W8UO^>BX/_A8!T_]C S_] 3E?_ -M+ATC_W9VA?_6Q\?_.# S_V]L_R <'O\@'2/_ -M>G)P_SP^1?]'5V?_.T53_SE"0O\;%C+_:5:$_Q4,'?\3%!O_$@X6_Q80&/\4 -M$1[_%Q8=_PH&%O\Q*T'_&14>_R4<'/\_0TO_24=)_];1T?\@'R7_+BTS_S$S -M.O\N,CK_,#4[_R4H+?\P+C'_(1P>_XM[_]Q;67_R[;, -M_Q_O?\M*"K_1#]%_RTI,?\X,3'_GY6+_X6$??^-BHG_ -M9F9O_RHM/O]%04G_Q+W'_]K#X/\E'"/_&!$8_R$0&O\A&B'_&QLD_R(H,/\M -M,#O_)20J_RXM-/]545G_ULS/_T([1?\[.TK_4U- at _U-.5/\P*";_(148_RP@ -M(?].13__O[.L_]S/RO]&/CS_*"(F_R,;'O\I(B+_)1X>_RDB(O\S*27_B8J$ -M_][1T/^@CI#_*" C_RG/^FG)C_P[>P_YZ6E/\H(R7_*B(E_U=(2/^4DH__WM+5_^+3V/\O -M+BW_)" B_R(>)O\W.D7_/4!!_[RTLO_:R\O_XM[<_U5:5/\U,S7_8%E at _Z.8 -MG?_MU]C_SL7,_SQ!3?\<&R+_8EI8_U5/3?\:%17_(Q\A_R$?(?\<&AS_'QT? -M_Q\='_]834S_2$E0_T939/]!2%;_)QTP_STK+?^KDH'_=EI7_UH]//^8=6[_ -MA6%7_X1B7_\K&!+_EH%__Z>1D_\4!@/_-RDF_T)$3/])2DO_U=+1_QP>(?\L -M+2[_/T)'_S U._\L,3?_)"_RPH*O\\-SW_+R at R_T X-O^@E(7_ at GES -M_XE]?O]?6V/_)BDU_SLZ0/^\M[W_S+S8_RDJ,?\4'R;_&QTD_R(B+?\E*C;_ -M/$1._Q,:(/\E)"K_*RHP_SDV//\?&!C_/3E"_SL[2O]*2EG_4U!6_RLC(?\X -M+"W_*AXA_RLD'O^7BX+_V,S%_UE.3?\J)BC_(!L=_RHC(_\J(R/_*"$A_S F -M(O^)BH3_WM'0_Z22E/\H("/_)Q\B_RHC(_\K)2/_+RDG_VUN;_]@96K_)B$C -M_Z21A?_ K:7_Q[NT_\6YL/_(N[;_JJ.C_R at E*_\E(R;_1C at U_[>PJO_?T-#_ -MZMO<_S0Q,/\D("+_'AHB_S7O_>GU^_W5[??]H -M96O_KJ.H__/AWO_8S=3_24Y:_QD:(?\H(B#_)A\?_R8A(?\A'1__'!P?_R > -M(?\A'R'_'AL:_T8W-_]!.T/_1T]?_U9;9_],3E7_#0,,_RL4'_\R(2?_%0H7 -M_R$4'_\G%Q__&0T6_R$:(O\8"QC_)A at G_R :(O^6BHO_1$)+_T=(2?_1T,__ -M+"XQ_TQ.3/\9'!W_("4J_SQ!1_\I+C/_2$-'_][6V?^)>&O_P:NB_^G3R_^8 -MA';_?W1I_]>[S_\<+CC_+"4L_R8Q//^1D(__*28E_S8P-/\I(RO_1S\[_YN+ -M>_^1AG__D8.$_TE$2O\B)3#_(R,F_ZZLKO_=SN;_)RLS_SM)6/\G*S/_-C8S -M_T) /?\_.SG_&Q,1_RPM)_\M,R__66%=_]72T?\X.4#_+3 \_SHW1/]I9&C_ -M+"(E_RXD)_\F'Q__)B(@_ST\-?_7R\?_;%M;_R8?'_\A'AW_)R @_R\F)O\M -M(2+_-2 at G_XZ.B__>T=#_LZ*B_RDD)/\D'Q__*",C_RHE)?\X,"[_96=E_V)I -M:?\B'2'_F8R!_\.RLO^#?';_:6=B_^76VO^MH:+_*28E_R4@(/\X,RW_O;2N -M_]3(Q/_DW-K_.#4T_R0@(O\@'"3_,C5 _SY%1?_"L[/_S+^^_^_DX_]Q:G;_ -M1U-<_UY=8_^YJZS_Z=K4_^70U?]%15+_&!HA_R0?(?\F(B3_(Q\A_R <'O\@ -M'![_(1T?_R(>(/\>&AS_-2EHO]955[_0D5& -M_];3TO\K+3#_.#HX_S4W-/\R-3K_,#$\_R at P-/_&NKO_Y]C=_Y5_=O_)L*O_ -MY'!G_(QL?_Q<; -M&?\?)1?_/D,W_SE"-?\M.BW_(RX;_R)"+?]ICX#_QL7$_TE$2O] /D?_-2\W -M_T Y.?\N(B/_)1L>_RLD)/\E(1__("0<_\C#OO^#<'#_,B0E_R0='?\G("#_ -M,RHJ_RTA(O\P(R+_AX>$_]K-S/^_KJ[_*20D_R0?'_\M*"C_,"LK_S8N+/]E -M9V7_7V9F_R,>(O]V;&'_:EU<_XR*@_^,CXG_Y]C<_["DI?\O+"O_)B$A_RLJ -M(_^MIJ#_R+JW_^O at W_\Q+BW_(Q\A_QL7'_\P,S[_/$-#_[^NKO^_L+#_\N7D -M_VYH=O])5F'_5E=>_[*FJ?_AU<[_Y]+7_S\_3/\@(BG_)2 B_R,?(?\C'R'_ -M(!P>_R <'O\A'1__(AX at _QX:'/\K(R'_24M._T926_]:96S_1$]:_SE#3O\J -M,3__,C%._S G8_\T*F__/S9\_UM1FO\8%4G_95^+_T$]7?\Y04O_E923_UA4 -M7?],3U#_V=;5_S R-_\P,3+_24M)_S R.?\Q,CW_)R\S_\.WN/_DU=K_?G%L -M_\"KJ?_WC_U\K)_\BWM_\H(R/_)2 @_R_WMP9?]H65G_LJNE_YN9E/_DU=G_MZNL_S,P+_\G -M(B+_(2(;_ZZIH_^MGYS_Y=C7_S,N+O\E(2/_)" H_SD\1_\Y/C[_P*VM_Z>6 -MEO_NW]__8UUK_SA)5O]#1T__JZ"E_^'4S__FT=;_/3U*_R B*?\H(R7_)B(D -M_R4A(_\B'B#_(AX at _R(>(/\B'B#_(AX at _R,;%_]14$__/$5,_XB*D?^+B8O_ -M24]1_SM'3/] 2%+_>'I__T9'3O\H+CC_'"4S_TQ55?]Y>GO_Q\')_SD^2O^+ -MB8O_3TM4_T)%1O_)QL7_+S W_RDI+/^8F9K_/#Y&_ST,W_J9B8_R8C -M(O\A'AW_)R @_RXE)?\N(B/_,20C_T1%/__7R,C_S+N[_R at C(_\E("#_)!\? -M_R8A(?\N)R?_*RDK_SH_/_\?&A[_;U]6_W]O;/^1B(+_I)^:_^C9VO^ZKJ__ -M+2HI_R,>'O\D)1[_KZFA_Y.'@__BU=3_/CDY_R,?(?\C(";_1$=2_T1(2O^\ -MK*G_DX*"_^?8V/^#?8O_-TA6_U]B;?^O_\RPK/^9C8;_V<37_R,Q0/\E(2G_)BLQ_WAX -M=?^=F)+_D(N+_X![>_^(@7O_9V!:_UQ=9/^5D)3_*"HM_S=#1_\[1$3_9FMK -M_][;S_\M*BG_,"XW_S@^.O]_?HO_9D.*_Z-[K_]%+$O_JHJ]_WM8F/_3PLS_ -M[-K0_TI&3_\^/DO_4U)?_ST\0_\K(R'_+R,D_S D)?\^-##_ _]W+R/_2P<'_)B$A_R0? -M'_\H(R/_*R8F_R at C)_\I)"C_)B$E_Q\:'O]S8V#_C(![_WIWWO\Z-37_)R,E_R0B)?]256#_ -M1$=3_[JKI?]U9V3_Z=O<_Y6)DO] 2EC_7%]J_Z.;GO^?F)C_Z-O6_T-#3O\N -M,3S_*B8H_R8B)/\C'R'_)" B_R(>(/\B'B#_(!P>_R(>(/\7$!C_*2XT_\K% -MR_^\M+C_W-/3_U%59/\A*3/_0$=3_VQN=?^7CH[_W,W2_TY17?]L;G7_=VUP -M_]W.T_]$1U+_AHN+_V%?:/\^04+_QL'!_RO_4R-?_+BY!_R$C*_\Y -M-3?_C7QV_]K#M_]!-3;_)R,E_V!>6?^$A7__B(B+_Y2/D_]P<7+_2E-3_U5: -M6O^'B8S_Z+O?_XA.H/^F9-'_QYS2_UQ(4?\U&3/_1S [_S4N*/^)?7G_FHF4 -M_]3(Q/_MVM3_4T]7_S'O\J)27_)R(F_QH5&?\A'"#_'!<;_U1$0?^6BH7_8V!;_ZFC -MH?_;S5E+_Y-O;_SPW-_\G(R7_'1L> -M_T!#3O\[/DK_L*&;_U]13O_DUM?_K:&J_T)-6/]35U__7E=7_X%Z>O_DU]+_ -M3T]:_RTP._\D("+_)2$C_R,?(?\D("+_(AX at _R,?(?\F(B3_(1T?_RLC(?\S -M,2S_74Y._ZB>FO_7S\W_3U-B_RLS/?] 1U/_7%YE_X^&AO_FU]S_24Q8_U)4 -M6_]C65S_VLO0_SH]2/]^@X/_85]H_TE,3?_>V=G_+RXU_R\N-?^4DIO_/#U( -M_SU 1?\N-#[_MJFH_\"LKO^JD8K_HHA]_ZJ4C/^YGY3_CG]R_\K#S_\P,S[_ -M(R8G_XU_@/^3 at 7W_WLO%_TH\/?\<%A[_(1\B_UQ>6_]K;VW_='%P_W]^??]W -M?'K_9VMI_UU at 8?_FQ=;_;DAI_]RUV/_[XMW_54A-_RDB+/\I)C+_-35 _WIS -M9_^5C7W_R[^Z_^30S/]'1$K_,S- _S at W1/]655S_*2$?_S(F)_\S)RC_-"HF -M_Y&%?O_9RL7_Q;:V_RLC)O\B'1__)1T at _RXE)?\K(!__-BHE_X* >?_2P+W_ -MTL'!_RDD)/\E("#_)B$A_R(='?\<%QO_%A$5_Q<2%O\;%AK_134R_Z>;EO]. -M2T;_IJ">_]W/S/_7S,O_,"TL_R8A(_\R+BS_Q+:G_U5-2?_BV=G_.C4U_R8B -M)/\:&!O_(R8Q_T)%4?^FEY'_4D1!_^'3U/^WK+/_/$A1_U9;8?^9DY'_D(F) -M_^GAWO_<&-8_]K2T/]35V;_+34__T5,6/]:7&/_?71T_^G:W_]% -M2%3_3U%8_V!66?_>S]3_1$=2_XZ3D_]T_][:&#_R[_( -M_T$_0?\X,R[_9EM:_SX\.?\J+"K_-C0V_R =(_\V-SC_='AV_VIM4E/_-#$E_RPH)O]$ -M.T+_>FYE_XZ%=__)O+O_W(/\F'B'_+20D_RXF)/\V+2?_;FEC -M_]K(Q?_/OK[_*R8F_R4@(/\D'Q__*",C_Q0/$_\4$!+_%A$5_Q at 3%_\P)B+_ -MLJ6 at _T-!.O^ZL*S_T\?#_]S1T/\T+R__)R(D_S at T,O^_LZ3_23\[_^79VO]" -M/3__)B(D_R ;'_\C)C'_0D-._ZB_T-&4O]46V'_1CY!_]O/TO] 1E#_<'-T_VEH;_]'2DO_GIJ<_S0V._\M -M+#+_IJ*K_S8Y1/\O,C?_+C0^_Y^2D?^QGZ'_:U]:_UQ74?]H:6/_;FIB_WUK -M9__#LKC_ULS(_]&_O/]V85__JJ&A_R0C*?\_-SO_)B0A_XN.B/]G;&K_455= -M_W%P;_]^?'?_5UE6_U!12_]344G_X]/*_V=84__ATM+_Y=#+_VQ at 8?\Q*C'_ -M.3,[_SPX0?^+ at GO_?G5N_[ZRK?_ at S,3_349-_SL]3/])2UK_.C8__S H*_\L -M)27_+RHE_R\J)/^/BX/_S<&Z_]+ O?\N)27_)!\?_RDB(O\J(R/_*"$A_RWMP_\"KI__&P;S_V]/1_S0M+?\D'R'_/34S_ZJDE/]5247_ -MY]C9_TI$2/\I(R?_(AP at _R >)_\M+S3_B(6$_T Z,O_BU-'_R;C _TM48O]$ -M257_E8^-_Z.T]C_0$-/_S]+5/\T,C3_S<;&_SQ!3?]*1T;_8&%B_T-(3?]02T__ -M+3$S_RTM,/^JI*S_045-_SM 1?\I,3O_6E)0_]#$Q?^*C8[_?W^"_Y^=IO]6 -M76/_+C<^_SL]0O\N)R?_,2 at H_[2GHO\J)2?_(" I_TQ'2?^'A'G_I:29_V=L -M:/]L='C_8W9^_X:(C?^"@G__1T5"_UI54/_8R+[_<6)<_]W/S/_FTLK_=VII -M_S4M,?\_.#__0SU%_V=@6O]N9V'_K**>_][+Q?]M9F[_0T15_U97:/]'0D[_ -M+24H_RTF)O\K)B'_-C$K_VQH8/_)O;;_U,*__RLB(O\D'Q__)A\?_RTF)O\J -M(R/_+2(/\_-S7_E8]_ -M_W!D8/_:R\S_95]C_RDC)_\C'2'_(!XG_ST_1/]%0D'_M:^G_]C*Q__1P,C_ -M04I8_U199?^0BHC_H)F9_^/1S?]W<'S_1D=2_R at C)?\J)2?_K*6E_Y2,BO^+ -M?GW_G)&6_R4@)O\J(B7_?W1S_UI<6O_$O;W_MK.R_[RNMO]-55__0DQ:_TE. -M8/]'3E3_<6QL_^+7W/],3UO_.45._X2"A/_:T]/_.3Y*_ST^/_]765S_/3]& -M_R at G+?\4&!K_)"0G_[NUO?]"1D[_049+_S$Y0_^1B8?_W]/4_U=I=_\W36/_ -M)SQ5_S!%7?](7'#_%R$O_QT?(O\F)23_4$5*_S G+O\?&A[_I9^7_["EGO^. -MAX'_;6]M_VYV>O]6:(S_2%%B_U!:2_],3$G_4TY._]?(N_]Z;&/_V'O\G("#_*"$A_R@='/\B -M(1K_%A8C_RDE+?\<'1?_RJVI_W-P9?_,L*W_L*BD_]_7U?\V+R__)!\A_S H -M)O]XM_UAA9_]+ -M5V#_/T94_T=/4_]234W_W-'6_U-68O]#3UC_A(*$_]3-S?\]0D[_'2,E_R\Q -M-O]/3UC_)B'O_6R<3_AH."_UI@ -M8O^/EYO_8F-D_RLF)O\N)R?_+24A_RLF(?]A757_HY>0_]3"O_\I("#_(AT= -M_R0='?\K)"3_+R at H_RXE)?\B'AS_3TU(_\O O_\M)"3_(QP<_RLD)/\M)B;_ -M(14>_U588_\@)%'_-S!?_QX<'__'JZ?_MJO^4CXK_W-'0_S at O+_\D -M'R'_*B(@_UU62/]V:F7_V\S-_X5]@/\H(B;_(!H>_QD9(O\^/T;_.3 at W_[6O -MI__3QL'_V,?-_T--6/]%2U7_?G9T_UE45/_(N;3_B8.+_T]27?\E(R7_+"W5S_]K. -MS_\C)2K_'"$G_U-68O\I)##_(ATA_R(@'?\D(AW_(B_UM94O]".3/_T,*__S H -M)O\B&QO_)1X>_S I*?\H(2'_*B,C_R\I(?^0B7O_R;VX_RLD)/\B'1W_*",C -M_RDD)/\K(BG_6&)?_R I6/\\/&?_'!X<_[VHH_]B4DG_MZJE_W1Q;/_=S,S_ -M/C4U_R,A(_\H("/_/C at V_SLT+O]G6US_E(N+_RLD)/\>&1__&AHC_SQ 2/\\ -M.CS_IYN6_\>YL/_;RW__0D)/_QT; -M'O\G'2#_IIB5_]'%OO^JFI?_MJ>G_S$H*/\G(R7_-CP^_TQ04O]85%;_IIZ< -M_S4Z-O\B*RO_2%%8_T9/7?]045S_AXF,_^/4V/]24&#_-T%+_U]@8?^^N[K_ -M-CE%_R at K-_\_04G_1DA/_T5(3?](3E#_*2DL_ZVIL?])25+_,3@^_S$U-_]+ -M24;_R\+"_R4@(O\B&AW_N:VP_R at C)?\@'2/_'!LA_Q86&?\E*"G_LZRF_]C+ -MQO_BUM+_N[>U_T)'1_]P=G+_4EA4_SD^0__CU]/_[]S4_^S9T?_SX-C_^^?? -M_\2[M?]%.S?_>FQI_]2^M?^:BH?_+28F_S\]0/\V+S;_'!T>_SP[.O^4D([_ -ML:6 at _W!H;/\G)S3_0DA8_V9D=/\E'2#_+B,B_RTB(?\E(1__)2,>_R 8%/_/ -MPL'_+28F_Q\8&/\B&QO_*2(B_R\H*/\M)B;_,"HB_Y.,?O_,P+O_*R0D_R(= -M'?\E("#_+2 at H_RLB(O]?9%[_7F5S_UI:9?\;&13_PJVH_T'B?_ -M04=1_T='2O^;D8W_M:FB_]K(RO]26F3_1$Q at _Q\>*_\6&R#_4TQ&_V5?9_\I -M)##_*B(F_S at I+?^LEY7_V%@O]Y:FK_*R(B_RRK?_XW=;_^=[7__[C -MW/_]Y-W_P+*S_RLC)O\A&QG_K9J0_Z>8D_\P*BC_04 __S8Q,_]%2TW_1$A& -M_Y&(@O^:C(G_CH.(_RPJ.O]$15S_<6U]_RLC)O\M(B'_,"4D_QX:&/\>'!?_ -M&A02_\B_O_\G(B3_(AT=_R$:&O\G("#_*R0D_RXG)_\M)Q__AX!R_\_#OO\H -M(2'_(!L;_R8A(?\F(2'_)B0A_UQ at 7O]G;&K_9&-B_R(>'/^]J*/_-RTC_YV8 -MDO\].S;_WLW-_V%86/\C(2/_*",E_S8S+O^ >W7_3$1 _ZJBH/\J(R/_(!LA -M_QD9(O\]1%#_/3Y%_X^'A?]934G_X,[2_T1,5O] 2%C_+BDO_TI&2/^!>'+_ -M(2$L_S4R/O\H(R7_,2("7_0$-(_TQ06/\[04O_3E!8_VIL;__4Q9?]+3E/_-#H\_QP<'_^>FJ+_1D9/ -M_RPO._\N,#?_,30U_TM*4/^KI*3_V\[-_^G8V/_KWMW_XM31_[^MJ?^5A'[_ -M=V1<_^?2S?_MV]?_T\O'_];+RO_3S\W_/T)#_V]Q;__JV];_^=[7___DW?__ -MY=[__^7>___GX/^BD9?_(QL?_QD4%/^,>V[_I)2+_R4@(/\^.SK_1#\__S=! -M1?]$247_CH-\_X^!?O^IH*#_/SQ(_SY 5?]84F#_+B_RXI*?\H*"7_8&)E_V5K9_]D9&?_(AT=_\*NIO\_ -M-"W_ at X)[_QL<%O_:R\S_'_ -M_^;?___GX/__YM___>3=_YR$C?\J&B+_03LY_WUL7O][:V'_)!\C_T$Y-_]" -M.CC_+S@^_S(U-O^+ at GO_>6QG_[ZTL/\V-3S_3U)D_TQ(6/\K(R;_*R$D_R\C -M)/\L(1K_*B0<_WAP9O_2Q\#_,B at K_R :'O\A&1S_+R8F_RXC(O\N)27_)R,A -M_VMJ7_^XKZG_*"$A_R$<'O\C'A[_+"@F_RPC(_]B8V3_8FMK_V%D9?\@'AO_ -MNJF;_R4=&_]W>'G_&!<6_\2]O?^4AH?_*" >_R8>&O];44?_95Q._V)>5O^Y -MK*O_*RHI_R8?)O\9%1[_.$%(_R_R$9'/\P)R?_+R0C_R\F -M)O\A'1O_7UY3_XZ%?_\G("#_(QX at _Q\:&O\J)B3_+20D_UE:6_]:8V/_:6QM -M_QX=(_^QI9[_'Q<:_S_["DG_^7G_\>#:__OB -MU?__Y-G__^7A___CW___Y=[__^7<__WDW?^FD8W_+B(>_S\X,O]D447_=F9< -M_QH5&?] .#;_,"@F_RDE+?\E(R7_:&A?_UM23/^XJJ?_,"HR_TY18_]&2%?_ -M,"LM_RLA)/\T*"G_,"4>_R at B&O^-A7O_QKNT_RXD)_\?&1W_'Q<:_RPC(_\M -M(B'_+",C_R8B(/\Z.2[_7U90_R8?'_\?&AS_*",C_R <&O\M)"3_4U15_UYG -M9_]B96;_(!TC_ZJ9D_\X*RK_6E12_W%K8_^TJJ;_IYN<_R8@)/\F(R+_65), -M_T,],_]V=&__R[Z]_RDH)_\A&B'_(!PE_SD^2O] 0D7_ at H!X_YB.BO\@'2/_ -M6EQD_TA/6_]-5V7_045-_T-&4O],5F3_355?_R A(O\O*2?_J9V6_Z*, at _^L -MEH[_HY.0_RD>(_\D'B+_*BPQ_TE05O]+5%O_2U5?_U!17/]<96O_M[.[_T$_ -M3_\I+SG_EY.;_R(?)?\K-4#_)BX^_QH>+?\A(";_A8" _TY24/\U.CC_&1L> -M_SDX/O]!1$G_'ATC_S4R./\A(RC_*"PT_R4G+O\\/D/_/CY!_YF/>__!II__ -MY,NZ_YF&;O_3P[K_EHB)_S,M,?\G(B3_Y]+&_\:]M_]/5UO_86=I_^',T?_V -MWMO__N?;___HW__[WMW_PZ6G__S at W/__Y][__^;?_[.DGO\F'AK_.30N_U=* -M/?]Q8UK_&!(6_S(I*?\F'1W_*"$I_QT9&_]+3$7_44A!_\BVL_\H'B?_861U -M_T5(5/\X,S/_)QT at _S,G*O\S*"'_*R4=_VYE7O^_M*W_,BDI_R$<'O\?%QK_ -M*R(B_S$F)?\J(2'_)R$?_RHH(/\_.#+_(!@;_R ;'?\G(B+_)2$?_RHC(_]/ -M4%'_769F_V%D9?\C'B+_IY2*_VY=5_]<4$?_<&9;_ZJ>F?^SI:;_)R(F_R0@ -M(O])1#__,BTG_W-Q;O_+P+__+"DH_R,=(?\A'27_(R\V_SH\.O]J75C_(QX@ -M_T1)5?]#2E;_04E3_T--6/]/4EW_2U!<_TM59/],5V+_(20E_RTH(_^GEX[_ -MNJ69_Z6/A_]$-C/_)QT at _R8@)/\N+C'_/$-)_T=05_]C9V__HJ*K_U1=9/\N -M*S'_-31!_S4Z1O\:&"C_.3='_RHR0O\<("C_(" C_XR(AO]G6U;_BHZ&_X:+ -MA_]\?'__-SD^_TY15O\;'2+_*B(?^@C8'_8%!&_SDM)O]?54O_D(1__[6HI_\F -M'B'_)AP?_S4P,O\N+"[_85U?_\>^OO\N)27_(QX at _R$?(O\;'2+_-C<^_TU1 -M6?\^1$[_+C(Z_TE/6?]"257_14Y<_T!*5?]&4%O_/DA3_TE37O\A(RC_*2$= -M_ZB8CO^XI9O_:EI7_X5X=_\B&QO_)"(D_R at C(_\T.3__0DA2_["GI_^EH*#_ -M24Y:_TU+3?\X.D+_(2LZ_SA#5/\H,4+_'1TH_RDD*/^AG9O_6%-'_Z>'__^C;___FV_^CE)7_ -M(QD<_R\H*/] -S#_8%92_QH1$?\F'B'_(!H>_R0>(O\>&AS_+2LH_R,;%__" -MLZW_.34S_T)'3/]L<'+_-BXL_RXB(_\Q)2C_,RHD_R0=%_\Q*"'_DXB!_SDP -M,/\A'![_'Q<:_RHA(?\P)23_+R8F_R4>'O\8%!+_'!H7_Q40%/\;%AK_)AXA -M_R@?'_\J)B3_14=%_V-L;/]@9&;_(!\E_XIX;O]00CG_*Q\;_T4[,?]U:63_ -MNJVL_RDA)/\F&R+_+R at O_QP>(?\/$A/_44M)_RD@(/\A'![_(!XA_QL=(O\I -M*C'_/$!(_T9,5O\M,3G_6F!J_S]&4O])4F#_35=B_T--6/]"3%?_45MF_R$C -M*/\J(B#_I):-_TH\,_^)?GW_& \/_R0?(?\A'"#_4$='_T)$2?]%2U/_9U]= -M_W)M;?\]0D[_+RTO_S]!2?]%4F7_+#9%_R at H,?]12$C_M+"N_V1;5/^]K)__ -MHX^'_U=84?]H;6G_O[W _S(T.?]/45;_(2,H_S R-_\K+3+_(2,K_RTO-O\Z -M/$'_-C8Y_V1;5/^##__^7> -M_Z"1E?\B&A[_*20F_S(K)?]734G_'!,3_R4=(/\>&!S_'A8:_QL7&?\D)2;_ -M'AD;_[VPJ_\Q+RS_66%E_X*'C/\X,#/_-"@I_R\D(_\Q*"+_'A82_T(Y,O]3 -M2$'_*R(B_R(='_\>%AG_*B$A_RH?'O\K(R'_)1X>_Q0/$?\7$A;_%1 6_Q0/ -M$_\E'2#_*R(B_RLG)?\J+"K_9W!P_VEM;_\?'B7_?&QC_UI.1_\Q)B7_1#LT -M_UQ02__"M;3_+"0G_R8=)/\C'2'_*2("C_ -M("$H_SLZ0/\D(B7_'AH8_T(Z-O]0143_(1T?_R4A(_\B'B#_(Q\A_R8B)/_I -MU-#_HYV;_VQT=O]234__]=_=__KAX/_[XN'__N7D___IXO__Z>+__^KB___K -MYO__Z^;_E8B-_R$8'_\A'"#_*B4 at _TI"0/\5#@[_)!P?_QT7&_\@&!O_'AL: -M_R at D)O]33$S_M*>F_S(P,O]A:&[_2D]5_R\G*_\S*"?_+B0 at _R\E(?\;%1/_ -M+B@@_S\W+?\;$Q'_*20F_QX9&_\K(B+_,28E_RD@(/\H("/_%A 4_QP6'O\3 -M#A3_% \3_R$<'O\E'A[_*B4E_S at Z./]IYMO\Q*2S_)2 B_SLV,?^+ at GO_:5E/_QT1#?\I("#_*B4G -M_S0R-?\7&1[_)"4L_TE-5?]67&;_1$I4_T]48/\Z04W_0DM9_U-:9O]#35C_ -M1E%<_TY79?\B'B?_+"(E_W5K9_\;%A'_)B(D_R >(?\A'"#_'18=_YJ-C/_@ -MV-O_/D%&_V!;5O^8E)+_-3M#_S P,_]+3U?_&A\E_XN)AO^QIZ/_8UI:_ZJD -MG/^:BW[_IYB+_V5E7/\\2DG_*S/8___HW?__Z^#_^^3?___KY___ -MZN;__^WG__WJY/^-?(;_(!<>_QT;'O\?&AS_.30V_Q<3%?\<&!K_'AH<_R,? -M'?]S;FG_M*NE_U!#/O]22DC_*2R_R\G*O\C(!__?75S_R,6%?\E'1O_(ATA_R0< -M'_\H(2'_(1TE_Q at 8(?\A(2K_1TA3_TY17?]-4V/_1DY>_T5-7?\Z0E+_6U]N -M_T]99_]'5F/_3UAF_R1C_\Y.3S_;W!W_U!06?]E:&G_?W]\_X!X=/^\ -MJZ7_GY2-_Y>,A?]D7%C_1TU)_S="0_\J-3;_-#L[_X.)A?])3U'_)20J_S(O -M-?\A(RC_)RTO_R,D+_\Z/#G_Y.'@_RLH+O\A'![_IIN:_R$9'/\?'"+_+BLJ -M_Z.AF?^___HW___ZN+_ -M_^OC__[JXO__Z^/__NOC_WUL=O\>%1S_&!89_Q at 3%?\M*"K_&!06_QH6&/\< -M&!K_65!*_S at O*?\T+BS_03P^_T5 0O\B("/_04E-_U9;8?\H(R7_*R0D_R8? -M'_\L)27_%A 4_QH7%O\<&A7_%1$3_Q82%/\;%QG_)A\?_RXF)/\F'Q__)2 B -M_Q81$_\;%AC_)2 @_RDD)/\F(2'_)B$A_R&R'_ -M3D<[_V]A7O\;%AK_0$5%_QL:&?]G8ES_)B0?_QX?(/\7$A;_(AH>_R$?(O\A -M'B3_(1D<_R(;&_\;%Q__("(J_SD[0_\_14__2E%=_T)+6?\Z0U'_1D]=_U9? -M;?\_3%G_2%5B_TE47_]-5V'_-S8\_R at C)_\@&Q__(!L?_X%Y?/\I(23_'!<9 -M_QL7&?^>F);_KI^D_T-%2O]74DW_D8J*_TA"1O_CU=W_Y=KA_Y&/F/]<5%?_ -MO*RC_[RIG?]]>W3_24Q&_S]$0O\Y1T;_+C(!W_9VID_WEV%AG_'AH<_]S4TO_PW^7_0T5*_V5C7O^"@(+_8%I>_^C6VO_IW=[_V-+: -M_^[@X?^]KJ'_BH)X_TU/3?\X04'_.$='_R\Y/?]%2DK_B9&._S Y.?]!3$W_ -M/T=+_R,B*/^?G*+_,S4Z_RPT-O\Q,CW_75E7_^;8V?]*04C_F)*0_YF4C_^/ -MCHW_C8N(_V1I9_]=9&3_9F5>_^W=T__VW-'__]_5__[CV/__YMW__^;=___E -MW/__Z-___^OC__SHX/_ZYM[__NKB___JXO]:25/_(1@?_QL9'/\=&!K_&!,5 -M_Q41$_\6$A3_%A(4_QT6'?\E'R/_/#_TU36_](2U;_ -M/SD]_R<@(/\B&QO_*"$A_Q42$?\3$13_&!89_Q(0$O\3#Q'_'1D;_R4>'O\R -M*BC_*2$?_S H)O\J(B#_+"0B_R@@'/\O)R/_+B8B_RHB'O\J(R/_(R$C_UIC -M8_]C:FK_)2(H_S I'?^8BH?_-3 T_W5P:O]%0C?_(QL7_QP-$O\B&AW_(1L9 -M_R<<&_\A'1O_'QH>_R,;'O\E'A[_)2$I_S0V/O\T.D+_0TM5_SU'4O\U/TG_ -M0$I4_T]98_\X0DS_,3M)_SX^3?^KH:O_I)ZB_SLV.O\F(27_(1P at _QP7&_]2 -M0T?_,B,G_R(8&_\/#0__J9Z=_^/2V/];76+_7%I5_W%V=O]A7&#_Y-+4_^/9 -MU?_HX.3_NJVH_XA^YMW__N3;___GWO__ZN+_^^??__[JXO_]Z>'__^CA - -end Deleted: python/branches/py3k/Lib/test/testimgr.uue ============================================================================== --- python/branches/py3k/Lib/test/testimgr.uue Tue Aug 19 23:04:40 2008 +++ (empty file) @@ -1,1170 +0,0 @@ -begin 755 test.rawimg.rev -M_UI)4_\A&!__&QD<_QT8&O\8$Q7_%1$3_Q82%/\6$A3_'18=_R4?(_\\-S?_ -M14(]_QP4&/\:%A[_35-;_TA+5O\_.3W_)R @_R(;&_\H(2'_%1(1_Q,1%/\8 -M%AG_$A 2_Q,/$?\=&1O_)1X>_S(J*/\I(1__,"@F_RHB(/\L)"+_*" <_R\G -M(_\N)B+_*B(>_RHC(_\C(2/_6F-C_V-J:O\E(BC_,"D=_YB*A_\U,#3_=7!J -M_T5"-_\C&Q?_' T2_R(:'?\A&QG_)QP;_R$=&_\?&A[_(QL>_R4>'O\E(2G_ -M-#8^_S0Z0O]#2U7_/4=2_S4_2?] 2E3_3UEC_SA"3/\Q.TG_/CY-_ZNAJ_^D -MGJ+_.S8Z_R8A)?\A'"#_'!<;_U)#1_\R(R?_(A@;_P\-#_^IGIW_X]+8_UM= -M8O]<6E7_<79V_V%<8/_DTM3_X]G5_^C at Y/^ZK:C_B'YP_TQ12_\Z/S__/T=) -M_R$O,O]15ES_B(R*_S8\./]#2TW_.D9*_SI"1O\?'B3_V-7;_S8X/?\N-CC_ -M+S [_UU95__IU]G_74M-_^#1R_^>E(G_7V!9_UU<5?]875W_5F)A_V]N9__L -MW]3_]]_6__W=U?_[W]?__.+9___FW?_^Y-O__^?>___JXO_[Y]___NKB__WI -MX?__Z.'_;EUG_R$8'_\3$13_&106_R ;'?\5$1/_&A88_QH6&/\D'!K_*!\? -M_T,^/O\]/#O_0SU!_QX;(?])4%;_3E):_S8P-/\I(B+_*R0D_RHC(_\6$A3_ -M%1,5_Q,1$_\4$A3_$@X0_R <'O\C'!S_-"PJ_R8?'_\I(B+_)!T=_R at A(?\I -M(R'_*2,A_RDC(?\L)B3_*B(E_RXL+O]B:VO_96QL_R =(_\[-"C_AGAU_Q at 3 -M%_\7%Q3_7UU8_UI84?\C'!S_&A@;_R(=(?\C&Q__(!L?_R(=(_\@&!O_*2(B -M_R4A*?\D)B[_+C0\_SM#3?\\1E'_0DQ7_TI47_]$3EG_1U%<_SY(5O]!2%3_ -M7EYG_Y&3F/]!/T+_(ATA_RDD*/\E("3_3T-&_R at 9'?\>%AG_'AH<_]S4TO_P -MW^7_0T5*_V5C7O^"@(+_8%I>_^C6VO_IW=[_V-+:_^[@X?^]KJ'_BH)X_TU/ -M3?\X04'_.$='_R\Y/?]%2DK_B9&._S Y.?]!3$W_/T=+_R,B*/^?G*+_,S4Z -M_RPT-O\Q,CW_75E7_^;8V?]*04C_F)*0_YF4C_^/CHW_C8N(_V1I9_]=9&3_ -M9F5>_^W=T__VW-'__]_5__[CV/__YMW__^;=___EW/__Z-___^OC__SHX/_Z -MYM[__NKB___JXO]];';_'A4<_Q at 6&?\8$Q7_+2 at J_Q@4%O\:%AC_'!@:_UE0 -M2O\X+RG_-"XL_T$\/O]%0$+_(B C_T%)3?]66V'_*",E_RLD)/\F'Q__+"4E -M_Q80%/\:%Q;_'!H5_Q41$_\6$A3_&Q<9_R8?'_\N)B3_)A\?_R4@(O\6$1/_ -M&Q88_R4@(/\I)"3_)B$A_R8A(?\G'R+_)B0F_V=P'R#_%Q(6_R(:'O\A'R+_(1XD_R$9 -M'/\B&QO_&Q7S_*2$D_QP7&?\;%QG_ -MGIB6_ZZ?I/]#14K_5U)-_Y&*BO](0D;_X]7=_^7:X?^1CYC_7%17_[RLH_^\ -MJ9W_?7MT_TE,1O\_1$+_.4=&_RXW-_\Y0D+_CI65_RXU-?\W/3__.3@^_Q at 5 -M&_\Q,SC_-3L]_RHK-O]03DO_W-75_R4F+?\6%QC_-S P_R___HW___ZN+_ -M_^OC__[JXO_^ZN+__^OC_XU\AO\@%Q[_'1L>_Q\:'/\Y-#;_%Q,5_QP8&O\> -M&AS_(Q\=_W-N:?^TJZ7_4$,^_U)*2/\I)RG_1$Q._T-(3?\P*RW_*B,C_R8? -M'_\I(B+_&!(6_R,@&_\E)1C_%A(0_R,>(O\>&AS_*R0D_RPD(O\G(B3_)R(F -M_Q81%?\5$!3_%! 2_QP8&O\D("+_)" B_RHB)?\M*RW_:'%Q_UUD9/\>&R'_ -M5D]#_W)D8?\B'2'_.#XZ_R,>&/_$M[+_+R&AS_&Q<9 -M_Q<2%/^ZMK3_WM'6_T5$2O]:4D[_EY&/_SDY//]O<'?_4%!9_V5H:?]_?WS_ -M@'AT_[RKI?^?E(W_EXR%_V1<6/]'34G_-T)#_RHU-O\T.SO_ at XF%_TE/4?\E -M)"K_,B\U_R$C*/\G+2__(R0O_SH\.?_DX>#_*R at N_R$<'O^FFYK_(1D<_Q\< -M(O\N*RK_HZ&9_YR9E/_6RF_S(P,O]A:&[_2D]5_R\G*_\S -M*"?_+B0 at _R\E(?\;%1/_+B@@_S\W+?\;$Q'_*20F_QX9&_\K(B+_,28E_RD@ -M(/\H("/_%A 4_QP6'O\3#A3_% \3_R$<'O\E'A[_*B4E_S at Z./]IYMO\Q*2S_)2 B_SLV,?^+ at GO_ -M:5E/_QT1#?\I("#_*B4G_S0R-?\7&1[_)"4L_TE-5?]67&;_1$I4_T]48/\Z -M04W_0DM9_U-:9O]#35C_1E%<_TY79?\B'B?_+"(E_W5K9_\;%A'_)B(D_R > -M(?\A'"#_'18=_YJ-C/_ at V-O_/D%&_V!;5O^8E)+_-3M#_S P,_]+3U?_&A\E -M_XN)AO^QIZ/_8UI:_ZJDG/^:BW[_IYB+_V5E7/\\2DG_*S/8___H -MW?__Z^#_^^3?___KY___ZN;__^WG__WJY/^@D97_(AH>_RDD)O\R*R7_5TU) -M_QP3$_\E'2#_'A@<_QX6&O\;%QG_)"4F_QX9&_^]L*O_,2\L_UEA9?^"AXS_ -M.# S_S0H*?\O)"/_,2 at B_QX6$O]".3+_4TA!_RLB(O\B'1__'A89_RHA(?\J -M'Q[_*R,A_R4>'O\4#Q'_%Q(6_Q40%O\4#Q/_)1T at _RLB(O\K)R7_*BPJ_V=P -M(_\6%Q[_0$1,_U%78?\B)B[_ -M3%)<_S]&4O]'4%[_/4=2_T5/6O]$3EG_25->_R -M&1G_)R,E_R,>(O\A'"+_<&%A_XZ)C?]!1DS_75A3_Z.?G?\\04W_+RTO_SH\ -M1/]%3ES_*BLR_V!:6/^HG9S_6U90_\"SJ/^EDH;_CX-Z_T)*1O]36U?_<')P -M_S8W/O].3U;_*"HO_SH\0?\L+C/_'B H_R A*/\[.D#_)"(E_QX:&/]".C;_ -M4$5$_R$='_\E(2/_(AX at _R,?(?\F(B3_Z=30_Z.=F_]L=';_4DU/__7?W?_Z -MX>#_^^+A__[EY/__Z>+__^GB___JXO__Z^;__^OF_Z.4E?\C&1S_+R at H_T W -M,/]@5E+_&A$1_R8>(?\@&A[_)!XB_QX:'/\M*RC_(QL7_\*SK?\Y-3/_0D=, -M_VQP_Q at 4$O\<&A?_%1 4_QL6&O\F'B'_*!\?_RHF)/]% -M1T7_8VQL_V!D9O\@'R7_BGAN_U!".?\K'QO_13LQ_W5I9/^ZK:S_*2$D_R8; -M(O\O*"__'!XA_P\2$_]12TG_*2 @_R$<'O\@'B'_&QTB_RDJ,?\\0$C_1DQ6 -M_RTQ.?]:8&K_/T92_TE28/]-5V+_0TU8_T),5_]16V;_(2,H_RHB(/^DEHW_ -M2CPS_XE^??\8#P__)!\A_R$<(/]01T?_0D1)_T5+4_]G7UW_(?^@C8'_8%!&_SDM)O]?54O_D(1__[6HI_\F -M'B'_)AP?_S4P,O\N+"[_85U?_\>^OO\N)27_(QX at _R$?(O\;'2+_-C<^_TU1 -M6?\^1$[_+C(Z_TE/6?]"257_14Y<_T!*5?]&4%O_/DA3_TE37O\A(RC_*2$= -M_ZB8CO^XI9O_:EI7_X5X=_\B&QO_)"(D_R at C(_\T.3__0DA2_["GI_^EH*#_ -M24Y:_TU+3?\X.D+_(2LZ_SA#5/\H,4+_'1TH_RDD*/^AG9O_6%-'_Z>'__^C;___FV_^SI)[_ -M)AX:_SDT+O]72CW_<6-:_Q at 2%O\R*2G_)AT=_R at A*?\=&1O_2TQ%_U%(0?_( -MMK/_*!XG_V%D=?]%2%3_.#,S_R<=(/\S)RK_,R at A_RLE'?]N95[_O[2M_S(I -M*?\A'![_'Q<:_RLB(O\Q)B7_*B$A_R4BO]N75?_7%!'_W!F6_^JGIG_ -MLZ6F_R(/]$257_0TI6_T%)4_]#35C_3U)=_TM07/]+563_3%=B_R$D -M)?\M*"/_IY>._[JEF?^ECX?_1#8S_R<=(/\F("3_+BXQ_SQ#2?]'4%?_8V=O -M_Z*BJ_]4763_+BLQ_S4T0?\U.D;_&A at H_SDW1_\J,D+_'" H_R @(_^,B(;_ -M9UM6_XJ.AO^&BX?_?'Q__SZ -MQ_\T.5+_/S]4_U!$7?]94V?_8%QL_VMG=_][9G+_CG9[__SBW___Z-W__^KA -M_Z:1C?\N(A[_/S at R_V111?]V9ES_&A49_T X-O\P*";_*24M_R4C)?]H:%__ -M6U),_[BJI_\P*C+_3E%C_T9(5_\P*RW_*R$D_S0H*?\P)1[_*"(:_XV%>__& -MN[3_+B0G_Q\9'?\?%QK_+",C_RTB(?\L(R/_)B(@_SHY+O]?5E#_)A\?_Q\: -M'/\H(R/_(!P:_RTD)/]35%7_7F=G_V)E9O\@'2/_JIF3_S at K*O]:5%+_<6MC -M_[2JIO^GFYS_)B D_R8C(O]94DS_0STS_W9T;__+OKW_*2 at G_R$:(?\@'"7_ -M.3Y*_T!"1?^"@'C_F(Z*_R =(_]:7&3_2$];_TU79?]!14W_0T92_TQ69/]- -M55__("$B_R\I)_^IG9;_HHR#_ZR6CO^CDY#_*1XC_R0>(O\J+#'_25!6_TM4 -M6_]+55__4%%<_UQE:_^WL[O_03]/_RDO.?^7DYO_(A\E_RLU0/\F+C[_&AXM -M_R$@)O^%@(#_3E)0_S4Z./\9&Q[_.3@^_T%$2?\>'2/_-3(X_R$C*/\H+#3_ -M)2V__^Y]O__^C?__O>W?_#I:?__.#<___G -MWO__YM__MYV at _S$?(?])/3G_=F%5_W]M8_\B'2'_-BXL_S\W-?\D)BW_)"(D -M_WUY_R$9'/\P)R?_+R0C_R\F)O\A'1O_7UY3_XZ%?_\G -M("#_(QX at _Q\:&O\J)B3_+20D_UE:6_]:8V/_:6QM_QX=(_^QI9[_'Q<:_S_["DG_^7G_\>#:__OBU?__Y-G__^7A___CW___ -MY=[__^7<__WDW?^VMA_R0?(_]!.3?_0CHX_R\X -M/O\R-3;_BX)[_WEL9_^^M+#_-C4\_T]29/],2%C_*R,F_RLA)/\O(R3_+"$: -M_RHD'/]X<&;_TL? _S(H*_\@&A[_(1D<_R\F)O\N(R+_+B4E_R_RPH)O\L(R/_8F-D_V)K:_]A9&7_(!X;_[JIF_\E -M'1O_=WAY_Q at 7%O_$O;W_E(:'_R@@'O\F'AK_6U%'_V5<3O]B7E;_N:RK_RLJ -M*?\F'R;_&14>_SA!2/\G)BW_,"HN_R8H)O][C_ZB=EO^XI)S_MZ>D_RTB)_\E'R/_ -M,"\U_TY/5O\D)B[_;&]Z_UU>:?]67V7_55%9_SG%C_UI/2/^O -MI*/_,2PL_QP7'?\L*C/_.4--_RDJ,?]_=G;_)B >_];)SO]*35C_14A3_X=\ -M>_]>6%;_*" >_TQ/6O\Z/$3_'AH<_RLF*/^=DI'_LJ>@_[RJIO^]KJ[_+",C -M_R8B)/\U-CW_5EA at _R B*?\<'B/_C(V4_TI,4_] 04C_9F=R_T9)5/]N<'/_ -MKZ.D_T5#4_\H,#K_:&IM_SHX._\E*#3_)BDU_T!"2O]66%__0T5*_S<]/_\M -M+3#_:65M_S] 1_\P,3S_-3<^_T9*3/\O,3;_?G)N_Z"+B?_1N;;_=6)<_]C* -MTO]83EC_*"$K_R ;(?_IU-+_X<_+_T4^./].1D+_34U*_WU\>__8D_\P*BC_ -M04 __S8Q,_]%2TW_1$A&_Y&(@O^:C(G_CH.(_RPJ.O]$15S_<6U]_RLC)O\M -M(B'_,"4D_QX:&/\>'!?_&A02_\B_O_\G(B3_(AT=_R$:&O\G("#_*R0D_RXG -M)_\M)Q__AX!R_\_#OO\H(2'_(!L;_R8A(?\F(2'_)B0A_UQ at 7O]G;&K_9&-B -M_R(>'/^]J*/_-RTC_YV8DO\].S;_WLW-_V%86/\C(2/_*",E_S8S+O^ >W7_ -M3$1 _ZJBH/\J(R/_(!LA_QD9(O\]1%#_/3Y%_X^'A?]934G_X,[2_T1,5O] -M2%C_+BDO_TI&2/^!>'+_(2$L_S4R/O\H(R7_,2("7_0$-(_TQ06/\[04O_3E!8 -M_VIL;__4Q9?]+3E/_ -M-#H\_QP<'_^>FJ+_1D9/_RPO._\N,#?_,30U_TM*4/^KI*3_V\[-_^G8V/_K -MWMW_XM31_[^MJ?^5A'[_=V1<_^?2S?_MV]?_T\O'_];+RO_3S\W_/T)#_V]Q -M;__JV];_^=[7___DW?__Y=[__^7>___GX/_$N[7_13LW_WIL:?_4OK7_FHJ' -M_RTF)O\_/4#_-B\V_QP='O\\.SK_E)"._[&EH/]P:&S_)R_UYE -M<_]:6F7_&QD4_\*MJ/]'.3#_IIV7_V%?6O_>S&1W_+BLJ -M_S(N+/]W;W+_HIF9_RTF)O\A'"+_'AXG_T%'4?]'1TK_FY&-_[6IHO_:R,K_ -M4EID_T1,8/\?'BO_%AL at _U-,1O]E7V?_*20P_RHB)O\X*2W_K)>5_]G(PO^7 -MA8+_>6IJ_RLB(O\G(R7_+S(W_TY15O\W-SK_AH&#_QP?(/\/%1?_2U%9_T!' -M4_]'2%/_B8N._]O,T/]%0U/_-T%+_R(C)/\X-33_+"\[_SU 3/]"1$S_3$Y5 -M_TM.4_]"2$K_)24H_[&MM?]!04K_+S,[_S8Y/O])2TG_D(N-_R$='_\O*"C_ -M."\O_T(]/?](1DC_:F5E_Y&)A_^IG9G_Z]S6_]7(P_]:4$S_U__^X]S__>3=_\S'N_]<44K_II*._^') -MP/^9B(C_,2DL_S at U._]$/47_)B$A_R ?'O\N+"[_O[:P_XB#@_\\0D3_9G)V -M_V]Q>/\O*BK_,28E_RL@'_\D(![_6UE2_T(Y,__0PK__,"@F_R(;&_\E'A[_ -M,"DI_R at A(?\J(R/_+RDA_Y")>__)O;C_*R0D_R(='?\H(R/_*20D_RLB*?]8 -M8E__("E8_SP\9_\<'AS_O:BC_V)22?^WJJ7_='%L_]W,S/\^-37_(R$C_R@@ -M(_\^.#;_.S0N_V=;7/^4BXO_*R0D_QX9'_\:&B/_/$!(_SPZ//^GFY;_Q[FP -M_]O)S?](4%K_25!>_T]'2_\B(2?_4$4^_X%[?_]"0D__'1L>_R<=(/^FF)7_ -MT<6^_ZJ:E_^VIZ?_,2 at H_R0_]3"O_\I("#_(AT= -M_R0='?\K)"3_+R at H_RXE)?\B'AS_3TU(_\O O_\M)"3_(QP<_RLD)/\M)B;_ -M(14>_U588_\@)%'_-S!?_QX<'__'JZ?_MJO^4CXK_W-'0_S at O+_\D -M'R'_*B(@_UU62/]V:F7_V\S-_X5]@/\H(B;_(!H>_QD9(O\^/T;_.3 at W_[6O -MI__3QL'_V,?-_T--6/]%2U7_?G9T_UE45/_(N;3_B8.+_T]27?\E(R7_+"W5S_]K. -MS_\C)2K_'"$G_U-68O\I)##_(ATA_R(@'?\D(AW_(BFQC_]G-QO_ETLC_@')O_RHA(?]!.3W_24))_VIC7?]G8EW_3T=%_]/$O_]A -M7&#_.3Q'_V-F')B_X1X=/_>S]#_;&9J_R at B)O\F("3_'1LD_SY 1?\\ -M.3C_M:^G_^'3T/_5Q,S_3%5C_T1)5?^$?GS_BH.#_];$P/^*@X__1TA3_RPH -M*O\O*"C_KZ2C_ZN=FO^'=W3_HI:7_R\I+?\K(R'_JI*5_U%)3/_+O\#_O["P -M_[BGK?]886?_2U=@_S]&5/]'3U/_4DU-_]S1UO]35F+_0T]8_X2"A/_4S0_XJ(@_]/4U'_/4)"_W-[??\Z2UG_86!F_UE<4/]03D?_8UM1 -M_]C(OO]Q8ES_W<_,_^;2RO]W:FG_-2TQ_S\X/_]#/47_9V!:_VYG8?^LHI[_ -MWLO%_VUF;O]#1%7_5E=H_T="3O\M)2C_+28F_RLF(?\V,2O_;&A at _\F]MO_4 -MPK__*R(B_R0?'_\F'Q__+28F_RHC(_\M)R7_2D(^_RH@'/_+O[O_*R(B_R0= -M'?\B&QO_*R0D_R47'_\C&Q?_(ALB_RXF*?\@(1K_SK*N_W-R9__#J:;_N+.N -M_]W5T_\V+R__(QX at _S\W-?^5CW__<&1 at _]K+S/]E7V/_*2,G_R,=(?\@'B?_ -M/3]$_T5"0?^UKZ?_V,K'_]' R/]!2EC_5%EE_Y"*B/^@F9G_X]'-_W=P?/]& -M1U+_*",E_RHE)_^LI:7_E(R*_XM^??^_XZ'@?]M;VW_;G9Z_U9HC/](46+_4%I+_TQ, -M2?]33D[_X]/*_V=84__ATM+_Y=#+_VQ at 8?\Q*C'_.3,[_SPX0?^+ at GO_?G5N -M_[ZRK?_ at S,3_349-_SL]3/])2UK_.C8__S H*_\L)27_+RHE_R\J)/^/BX/_ -MS<&Z_]+ O?\N)27_)!\?_RDB(O\J(R/_*"$A_RWMP_\"K -MI__&P;S_V]/1_S0M+?\D'R'_/34S_ZJDE/]5247_Y]C9_TI$2/\I(R?_(AP@ -M_R >)_\M+S3_B(6$_T Z,O_BU-'_R;C _TM48O]$257_E8^-_Z.T]C_0$-/_S]+ -M5/\T,C3_S<;&_SQ!3?]*1T;_8&%B_T-(3?]02T__+3$S_RTM,/^JI*S_045- -M_SM 1?\I,3O_6E)0_]#$Q?^*C8[_?W^"_Y^=IO]676/_+C<^_SL]0O\N)R?_ -M,2 at H_[2GHO\J)2?_(" I_TQ'2?^'A'G_I:29_V=L:/]L='C_8W9^_X:(C?^" -M at G__1T5"_UI54/_HV];_6U%'_^37TO_BSM?_7E)3_S0Q)?\L*";_1#M"_WIN -M9?^.A7?_R;R[_]W)Q?]!/T'_,3$^_T1$4?](1T[_,"HH_RH>'_\S)RC_-RXH -M_YB-AO_8R<3_T\+"_RHB)?\C'B#_)AXA_RTD)/\N)B3_-BTG_VYI8__:R,7_ -MS[Z^_RLF)O\E("#_)!\?_R at C(_\4#Q/_%! 2_Q81%?\8$Q?_,"8B_[*EH/]# -M03K_NK"L_]/'P__V?]04%O_/4!+_R8A(_\G(R7_*24G_U925/]G8F3_4T]1_R,>(O\K)RG_ -M*B8D_T='1/]G6%S_A(&'_]C0T_]88&K_359=_TA/6_]56F#_=&MK_^;9WO]# -M1E+_5%MA_T8^0?_;S]+_0$90_W!S=/]I:&__1TI+_YZ:G/\T-CO_+2PR_Z:B -MJ_\V.43_+S(W_RXT/O^?DI'_L9^A_VM?6O]<5U'_:&EC_VYJ8O]]:V?_P[*X -M_];,R/_1O[S_=F%?_ZJAH?\D(RG_/S<[_R8D(?^+CHC_9VQJ_U%57?]Q<&__ -M?GQW_U=95O]044O_4U%)_^;%UO]N2&G_W+78__OBW?]52$W_*2(L_RDF,O\U -M-4#_>G-G_Y6-??_+O[K_Y-#,_T=$2O\S,T#_.#=$_U957/\I(1__,B8G_S,G -M*/\T*B;_D85^_]G*Q?_%MK;_*R,F_R(='_\E'2#_+B4E_RL@'_\V*B7_ at H!Y -M_]+ O?_2P<'_*20D_R4@(/\F(2'_(AT=_QP7&_\6$17_%Q(6_QL6&O]%-3+_ -MIYN6_TY+1O^FH)[_W<_,_]?,R_\P+2S_)B$C_S(N+/_$MJ?_54U)_^+9V?\Z -M-37_)B(D_QH8&_\C)C'_0D51_Z:7D?]21$'_X=/4_[>LL_\\2%'_5EMA_YF3 -MD?^0B8G_Z=S7_T9&4?\X.T;_)R,E_R_]P8UC_VM+0_U-79O\M-3__14Q8_UI<8_]]='3_ -MZ=K?_T5(5/]/45C_8%99_][/U/]$1U+_CI.3_W1R>_]%2$G_R<3$_S0S.O\L -M*S+_FIBA_S,T/_\X.T#_)"HT_ZN>G?^NFIS_CGUW_W!D7?]".S7_DH1[_WMH -M8/_+O\C_03]!_S at S+O]F6UK_/CPY_RHL*O\V-#;_(!TC_S8W./]T>';_:FUR -M_YF6E?]H9F/_<'5Q_U164_]454__Z+O?_XA.H/^F9-'_QYS2_UQ(4?\U&3/_ -M1S [_S4N*/^)?7G_FHF4_]3(Q/_MVM3_4T]7_S'O\J)27_)R(F_QH5&?\A'"#_'!<; -M_U1$0?^6BH7_8V!;_ZFCH?_;S5E+_ -MY-O;_SPW-_\G(R7_'1L>_T!#3O\[/DK_L*&;_U]13O_DUM?_K:&J_T)-6/]3 -M5U__7E=7_X%Z>O_DU]+_3T]:_RTP._\D("+_)2$C_R,?(?\D("+_(AX at _R,? -M(?\F(B3_(1T?_RLC(?\S,2S_74Y._ZB>FO_7S\W_3U-B_RLS/?] 1U/_7%YE -M_X^&AO_FU]S_24Q8_U)46_]C65S_VLO0_SH]2/]^@X/_85]H_TE,3?_>V=G_ -M+RXU_R\N-?^4DIO_/#U(_SU 1?\N-#[_MJFH_\"LKO^JD8K_HHA]_ZJ4C/^Y -MGY3_CG]R_\K#S_\P,S[_(R8G_XU_@/^3 at 7W_WLO%_TH\/?\<%A[_(1\B_UQ> -M6_]K;VW_='%P_W]^??]W?'K_9VMI_UU at 8?_>V\__+2HI_S N-_\X/CK_?WZ+ -M_V9#BO^C>Z__12Q+_ZJ*O?][6)C_T\+,_^S:T/]*1D__/CY+_U-27_\]/$/_ -M*R,A_R\C)/\P)"7_/C0P_W)F7__7R,/_K)V=_RLC)O\@&QW_)Q\B_S,J*O\O -M)"/_,24 at _XF'@/_=R\C_TL'!_R8A(?\D'Q__*",C_RLF)O\H(R?_*20H_R8A -M)?\?&A[__]Z=W+_IZ&?_^'3T/_*O[[_+RPK_R4@(O\L*";_Q+:G -M_W5M:?_GWM[_.C4U_RBEO_$J)K_ -MNYZ2_\&EE_^;BGK_U,C7_RXN0?\A(RO_.34W_XU\=O_:P[?_034V_RO\H/RS_("PK_S$Z,_\W1#G_*#0]_S]"5/_*PL7_Y]C2_SL[1/\\0$__2TE9 -M_T9"2O\N)"?_+2,F_R<>'O\P*BC_8UQ6_][0S?^IF)C_)B,B_R$>'?\G("#_ -M+B4E_RXB(_\Q)"/_1$4__]?(R/_,N[O_*",C_R4@(/\D'Q__)B$A_RXG)_\K -M*2O_.C\__Q\:'O]O7U;_?V]L_Y&(@O^DGYK_Z-G:_[JNK_\M*BG_(QX>_R0E -M'O^OJ:'_DX>#_^+5U/\^.3G_(Q\A_R,@)O]$1U+_1$A*_[RLJ?^3 at H+_Y]C8 -M_X-]B_\W2%;_7V)M_YR4F/_:SLG_YM36_S8W0O\N,#?_*"0F_R(/\B'B#_(1T?_R,?(?\H'1S_1T-%_U%05O_ N<#_ZMGC_UU69_\] -M0E3_0DE;_WUV@/^UJ;+_Y]WL_U129?]A87#_C(*+_^#3V/\\/T3_CI"._U!. -M5_]"14;_SLO*_R at I,/\K*C#_B8B._S,T/_\N,#C_+C8Z_\2XN?_FUMK_T<&X -M_].YK/_7MZ__S+"L_YF-AO_9Q-?_(S% _R4A*?\F*S'_>'AU_YV8DO^0BXO_ -M@'M[_XB!>_]G8%K_7%UD_Y60E/\H*BW_-T-'_SM$1/]F:VO_O\3*_SY(-_\V -M0C/_+T P_TQC4/\Y5$/_#"D7_SY?3?\S3CW_/%I*_YBMH?_9TWC_U\K)_\BWM_\H(R/_)2 @_R_WMP9?]H65G_LJNE_YN9E/_DU=G_MZNL_S,P+_\G -M(B+_(2(;_ZZIH_^MGYS_Y=C7_S,N+O\E(2/_)" H_SD\1_\Y/C[_P*VM_Z>6 -MEO_NW]__8UUK_SA)5O]#1T__JZ"E_^'4S__FT=;_/3U*_R B*?\H(R7_)B(D -M_R4A(_\B'B#_(AX at _R(>(/\B'B#_(AX at _R,;%_]14$__/$5,_XB*D?^+B8O_ -M24]1_SM'3/] 2%+_>'I__T9'3O\H+CC_'"4S_TQ55?]Y>GO_Q\')_SD^2O^+ -MB8O_3TM4_T)%1O_)QL7_+S W_RDI+/^8F9K_/#Y&_S'A/_:S(/\>&AS_*R,A_TE+3O]&4EO_6F5L -M_T1/6O\Y0T[_*C$__S(Q3O\P)V/_-"IO_S\V?/];49K_&!5)_V5?B_]!/5W_ -M.4%+_Y64D_]85%W_3$]0_]G6U?\P,C?_,#$R_TE+2?\P,CG_,3(]_R&IA_W9K9/^2 at 8'_1CU$_R,D*_\^/#__MJNJ -M_]W.YO\G*S/_.TE8_R'?\G("#_+R8F_RTA(O\U*"?_CHZ+_][1T/^SHJ+_*20D_R0? -M'_\H(R/_*B4E_S at P+O]E9V7_8FEI_R(=(?^9C('_P[*R_X-\=O]I9V+_Y=;: -M_ZVAHO\I)B7_)2 @_S at S+?^]M*[_U,C$_^3_R <'O\A'1__(AX at _QX:'/\U)RC_2T9,_U5@ -M:_]16V7_1TU=_R at H-_]@76__6S_B'UV_Y&"@_]+1$O_(R4L_S4U -M./^AG)S_S+S8_RDJ,?\4'R;_&QTD_R(B+?\E*C;_/$1._Q,:(/\E)"K_*RHP -M_SDV//\?&!C_/3E"_SL[2O]*2EG_4U!6_RLC(?\X+"W_*AXA_RLD'O^7BX+_ -MV,S%_UE.3?\J)BC_(!L=_RHC(_\J(R/_*"$A_S F(O^)BH3_WM'0_Z22E/\H -M("/_)Q\B_RHC(_\K)2/_+RDG_VUN;_]@96K_)B$C_Z21A?_ K:7_Q[NT_\6Y -ML/_(N[;_JJ.C_R at E*_\E(R;_1C at U_[>PJO_?T-#_ZMO<_S0Q,/\D("+_'AHB -M_S7O_>GU^_W5[??]H96O_KJ.H__/AWO_8S=3_ -M24Y:_QD:(?\H(B#_)A\?_R8A(?\A'1__'!P?_R >(?\A'R'_'AL:_T8W-_]! -M.T/_1T]?_U9;9_],3E7_#0,,_RL4'_\R(2?_%0H7_R$4'_\G%Q__&0T6_R$: -M(O\8"QC_)A at G_R :(O^6BHO_1$)+_T=(2?_1T,__+"XQ_TQ.3/\9'!W_("4J -M_SQ!1_\I+C/_2$-'_][6V?^)>&O_P:NB_^G3R_^8A';_?W1I_]>[S_\<+CC_ -M+"4L_R8Q//^1D(__*28E_S8P-/\I(RO_1S\[_YN+>_^1AG__D8.$_TE$2O\B -M)3#_(R,F_ZZLKO_:P^#_)1PC_Q at 1&/\A$!K_(1HA_QL;)/\B*##_+3 [_R4D -M*O\N+33_55%9_];,S_]".T7_.SM*_U-38/]33E3_,"@F_R$5&/\L("'_3D4_ -M_[^SK/_'O\I(B+_,RDE_XF*A/_>T=#_ -MH(Z0_R@@(_\G'R+_*"$A_RPF)/\P+"K_7U]B_UUB9_\E("+_L**9_V584_^F -MGIS_IIR8_\.WL/^>EI3_*",E_RHB)?]72$C_E)*/_][2U?_BT]C_+RXM_R0@ -M(O\B'B;_-SI%_SU 0?^\M++_VLO+_^+>W/]56E3_-3,U_V!98/^CF)W_[=?8 -M_\[%S/\\04W_'!LB_V):6/]53TW_&A45_R,?(?\A'R'_'!H<_Q\='_\?'1__ -M6$U,_TA)4/]&4V3_04A6_R<=,/\]*RW_JY*!_W9:5_]:/3S_F'5N_X5A5_^$ -M8E__*Q at 2_Y:!?_^GD9/_% 8#_S]_\;!V?\R-3K_'" H_Q,2'_\;%QG_$Q,6_Q87'O\< -M%R/_'!<=_Q(.%O\J)"S_T,3'_U-,5O] 0$__04%._U!+4?\L(B7_*Q\B_TQ! -M0/\W+"O_6$U,_Y>/C?\T+2W_)!\A_R8?'_\K)"3_*R0D_R at A(?\R*"3_B8J$ -M_^'4T_^+>7O_(QL>_R4=(/\K)"3_+2 -M_R =(_]Z*/\?)37_Q[^]_RTH*O]$/T7_+2DQ_S at Q,?^?E8O_A81] -M_XV*B?]F9F__*BT^_T5!2?_$O'RK_ -M&ALF_R0=)_\8$1C_&1,;_RXG+__DU=G_1T!*_ST]3/\V-D/_3TI0_RH>)_\I -M'"'_+2,?_R\C)/\:%!C_(AP at _R(='_\J(B7_)R @_RDB(O\K)"3_*2(B_S0J -M)O]E9F#_X-/2_X%O$!G_'Q8=_QL9,_]75X#_4E)Y_P\/'O\E("#_+C0\_T-!0__;TM+_ -M*BDP_RXM-/\V.$#_*RXY_R8J,O\A)"G_*RDL_SHU-_^_L*K_UL.]_^W8UO^> -MBX/_A8!T_]C S_] 3E?_+ATC_W9VA?_6Q\?_.# S_V]L'O\H -M(2'_,"@D_Y&(@O_7R,/_:EY:_R_]34T?^]P[__ -MJ[&S_]31U__LV]O_\MS4_[FUM_\_4%;_%20D_W=X>?^ZK:C_75-6_QX<'_\= -M'!O_D(J(_T4Y-?\C'B+_I9F4_X)Y>?\O,3G_,C0\_RTU1?\Z15;_" \C_R4= -M./]J9)[_44Z0_S at XW7_Y-?6_^/.S/^PGY__N[*R_R_R4>'O\B&QO_,"HN_QD4&/\5$!3_%Q(6_QH2%?\B&QO_ -M*R0D_RLD)/\V,3'_)1T at _WYR=?]A65S_)!\C_R$<(/\K(R;_+R8F_R_R(<(/\?&1W_(QTA_Q at 3 -M%_\<%QO_'1H9_U123_^/BHS_3TI._Q\>)?\]04G_5UQ8_\#"Q?_3T>'_O+?) -M_R,<+?])0U'_U<[8_^K=W/_JUMC_IYRI_TI"5O\\(S3_=VYU_\.TKO]+0$7_ -M(1XD_VQK:O\P*R;_FXZ-_RDC)_^XK:;_*!X:_VEH;_]$1DW_&Q\G_S= 3O]& -M3V#_/T)._Q -&O\) !+_(A&R'_'!D?_QT:(/\H(RG_*R8J_RLC)O\M)"3_ -M)",B_V=E8/]F85O_*!T<_[*GKO]S;77_)B7%[_ -M-#8]_SQ'4O\\2U'_'RD?_T5(0O^5E)O_*2\Y_UQ?9/\;("7_+C9 _Q at B,/\] -M1DS_-#H\_T!"1?\9%QK_%QD>_RTP-?\I+#'_+C$V_R$F+/\B)2K_+C S_SDZ -M._^^M*G_K9F1_^++QO^,>G#_F(A^_\"TK?]_T>/_ -M*" J_R ;'_\A'27_(ATC_QL6&O\?&A[_*",G_QL8'O\9%1?_I9Z>_]K/UO]# -M0T[_/#Q+_T Z2/\Q*C'_)R @_R,<'/\K)"3_)A\?_RPC(_\U+"S_."\O_S G -M)_\R*RO_*R0D_R<@(/\K)"3_*R,G_Q40%/\5%1C_&Q49_QP5'/\<%QO_(!@; -M_RLB(O\C(2/_?\H(R/_Q;FP_YN1C?_(Q\[_3$Y5 -M_Q84%O]_ at 8C_0TU;_SI&5?\=+"C_3$Y3_X^*G/\H,D;_'R,E_TI+3/\>("C_ -M*"L\_SL]1/\T.#K_0DA*_SM!0_\N,3;_+C$V_RDL,?\J+3+_)BLQ_R at K,/\T -M-CG_)"4F_\*XK?^WHYO_X,G$_XMY;_^@C87_NZNH_V-;6?]32T'_YM30_^+- -MR_^6BXK_-3HZ_S,X/?\A'AW_D(J"_WMY_S(J)O\R)R;_+R0C_RXC(O\I(B+_*B4E_QP7%_\7$A+_'1@:_QT8 -M&O\=&!C_*R8F_QT6'?^%>G/_=FE<_TO]7D:?_2(BG_S!PC_\Z -M9HC_*C!&_W!:6_\W(B?_)"$G_[:OJ?_0N;K_8519_R\M+__-P;C_:FMV_]K1 -MT?]!2UK_4$Y1_\"^P/]&4%__/DI9_Q_RTH*/\U -M,##_'AD9_RTH*/\D'Q__)"(D_XM^>?]%-SC_)C15_Q(>._\8&2K_%A,?_Q85 -M(O\>'2K_&AHE_QX>*?\8&"/_%!,:_S(Q./\?'B7_(!\F_QX<'_\>'!__'!H= -M_R_R at I.O\D -M)SC_-#@Z_TA&2/_AT^__*RTU_TA17_\N,#__&ATH_R8J.?\=(3#_$!0C_U=0 -M6O]I:V[_OK"Q_\2YP/]E96[_3E!8_T9)3O\J)2?_)1X>_R$:&O\C'!S_(QP< -M_R at A(?\A&AK_*2(B_RXG)_\Q*BK_)A\?_RHC(_\M)B;_*B4E_R_Q at 5(?\3$!S_&!4A_QT:)O\:%R3_'QPI_QD6(_\@'2K_-#([_RDH -M+_](1T[_'QXE_QX<'_\3$13_#PT0_PL)#/\7$AC_0C@[_QX4$/\8&A?_%A<0 -M_S8U+O\A.#/_35]C_S]!2/_7R,/_,B -M__CAW/_YXMW_]-C:_VUK;?\F)BG_.#4P_Y.2D?\E(R7_(B B_R$?(?]34EG_ -M+B] _R0G./\V.CS_3TU/_^31Y_\I)BS_,#9 _S8S/_\C(RS_$Q0?_Q,4'_\[ -M/$?_*R0L_RXL+O\_-#/_6E)6_UE97/\T-SC_+3(R_R8E)/\B'1__)2 B_R(= -M'_\E("+_+"0G_R0<'_\I(23_*R,F_RDD)O\C'B#_*",E_R8A(_\F(2'_(1P< -M_R0?'_\D'Q__&A45_R(='?\G(B+_)!\?_R(:'O\C'!S_(1\B_Q at A,O\0%RG_ -M'AXG_RPI+_\@("G_'ALG_Q81'?\7$A[_%Q(>_Q84'?\9%R#_'1LD_Q\=)O\: -M&B/_%Q<@_QP<)?\S,SS_5U1:_RHH*_\0#A'_&A@;_V!@7?]X>G?_/#] _Q47 -M&O\>("7_0T!&_QDF)_]96U[_Q;*R__+5T?\W)R__(R,F_XF+ at O_+M[G_-2HO -M_S$O,?_.PKG_;W6%_\S!P/\[2%G_D(Z1_\K%Q?\T/DW_+SM*_WE^?O_;UM'_ -M;6]^_S)"5?\M.SK_5%)+_U)17O\R/$K_&1T?_Q49&_\R-CC_.CY _SH_1?\] -M/T+_3$Y1_S T//\E*S7_(20I_VMH9_^[L+7_T\C'_\W#O__4RL;_W-+._^79 -MU?_HVM?_Y=?4_^K'S#_)"(/\C'B#_'1@:_R,<%O\<'B/_*",I -M_QX:(O\='2;_'1TF_QP=*/\L*S+_,C$W_R ?)?\8%QW_&A<=_QH7'?\9%AS_ -M%Q0:_Q<7&O\='"+_)B4L_QT:)O\7%AS_7EYA_S P,_],3$__+BHL_QT@(?\Z -M0D3_&1L>_Q47'_\<'"7_$Q87_V-?7?_$O;?_ZMK7_RHF*/\G(1__LJ:?_^/+ -MSO\P*"S_,"PN_\.WL_]N=W#_N[6Y_S]27/^0D9+_PL3)_S<]3?\Y057_>H&' -M_]3,RO]H:'?_/$95_SQ"1/]T;&C_3$M8_RXY1/\1&Q+_(B0I_S at Z/?\5&AK_ -M)BLP_SD\0?])2$__,C8^_S0U0/\@)2K_JZ*B_\:WO/^LFY7_JI2+_ZB3A_^? -MBWW_EXA[_Y>%>_][:&#_BGQS_^?2S?]C8V#_JZNN_TI%1?](14O_(!L?_X)_ -M?O]I96?_9%]C_UU=;/\C)SW_/#U$_Y60EO_IW.?_&Q$:_R8?)O\@&Q__(ATC -M_R0?)?\G)"K_+2HP_Q at 3%_\=&1O_%Q,5_Q41$_\7$!#_'!<=_ST\0_\D'B+_ -M0C(Z_S$@)O\A%1;_)AL at _QP3&O\=%QO_34=+_QH4&/\7$17_'!8:_RHD*/\< -M%AK_'A,8_Q0,$/\<%AK_%Q(6_Q81$_\=&!K_)R(D_Q\:'/\;&1S_'AH8_Q(: -M*O\6'3'_%QO^[L;O_0%1B_Y.(C_^^O -M)_\?'2;_&A at A_Q(0&?\1$!?_$A$8_Q,2&/\4$QG_(2,F_QX@(_\Z/#__.CP_ -M_Q0:'/\W.3S_4$M/_Y2)CO]K9&O_ at GV#_T) 0_]C86/_I:. at _^G:V_\K)2G_ -M+BXK_\W!O/_RVMW_)AXB_RDD)O^PH*C_P,"]_[JIN?\S3%W_9G5[_V^$D/]N -MAIG_67B*_W*0IO]OD)S_8HV?_R@\2O^"A(?_V-#,_TY-6O\Y1$__7%Y5_SH[ -M0O\S-SG_=D/^SF8O_PZJ9_\2JE?_-KYK_PZ22_\FPG__ at R<3_='5V_ZFJL?]?6E[_ -M9F)J_R4@)/^5DY#_C(B*_V5 at 8O]U=83_+3!)_S P.?^OJ*C_Y]3D_R,=*_\P -M.DC_&R R_R$F./\8&RS_%14 at _QL6'/\9%1?_'!@:_R_R,E -M*/\F*"O_("@J_RHN,/\M+3#_*R\Q_RDJ*_\O+S+_'B(D_T-(3?]%2DC_T+_% -M_R\F+?\H*2K_KJ*=__7=X/\I(27_+"\ -MP?^GDXO_O:.6_["6B/_!J)?_R+&?_\VRH?_!I9?_R;*F_]O'P_]:7%__KK"X -M_UA56_]U<7G_)R(F_YN9EO^/BXW_75A:_VMK>O\I+$7_-#0]_VA=8O_8T-[_ -M$Q8G_SE'7/\1'CO_04QE_R at O1?\;'2S_'!PG_R$:(O\M)BW_,"LQ_S,Q-/\T -M+S/_/T%&_S8X0/\Z.#O_V,G)_\R]M_]Y;F/_>6UH_QH5%_]@6U__44Q0_Q<2 -M%O\B'"#_)1\C_TY(3/]:5%C_@'I^_S J+O\6$!3_-S$U_QD7&?\<&!K_(AT? -M_Q\='_\4$!+_+BDC_SU%3_\4"AG_$Q$4_Q,0(O\A)"__("$H_QP<)?\7%R#_ -M'!PE_QH:(_\B(BO_&QLD_Q84'?\7$QS_%1(>_Q04(?\5&2'_2$E*_TE+2?\J -M+2[_'!\@_QH='O\8&A__&!<>_QH6'O\>'R;_)B4K_S at Z/?\<(2'_.CL\_[RY -MM/_GU=G_)B H_RXR,/_"MK'_]=W at _RHB)O\O*BK_LZRL_]C+RO^BG:'_5VMO -M_YNBKO^7F:'_)R8L_QX=(_\B)B[_969M_[&VPO]&76G_ at HN1_]O5T_]#1E+_ -M.D12_[.NJ?]#14S_.SX__[Z\O_\Q-CS_.SU%_T ^1_\G*S/_+C X_R4M+_^! -M>7?_NZ^R_]S*QO_>R\7_WLW'_]W)P?_BR<+_T+NV_]C$P/_1NK7_W\G+_U-6 -M6_^EJ*W_5U)8_XJ&CO\E("3_HI^>_YN6FO]E8&3_<&Y^_R&!S_)R$E_R8@)/\B'"#_%0X._YZ1 -MD/\S)"3_)!D8_R<9&O].1T'_.$-._QH3)/\4%1;_%Q0G_RDL-_\Q,S;_)"0O -M_QT=*/\A(2S_'!PG_Q06'O\0$!G_$Q$:_Q,/&/\6$R#_%QHE_R at M,_\\.CW_ -M/STZ_ST[-O\].S;_/STX_S$O,?\>'!__&A@;_QP:'?\<&AW_%Q<:_Q@;'/^+ -MAX7_T,C$_^G7V_\I)BS_-3,N_]3'PO_OU]S_+B8J_S$L+/^VL;'_Z=G=_YB8 -MF_]89FG_G*2N_Q,6&_].3DO_>WUZ_U=86?\K+3#_*3,W_SA'3/^#B(W_V]73 -M_T!$4_\Y0U'_BX:!_SY#2?]&24K_R\G,_S$X/O]"14K_/CU$_RDL-_\U-S__ -M*# R_\&VM?^^K[/_T]'._T-#0/]!1T/_6EI7_\S*Q_]/44[_6%U9_UM=6O_0 -MO\7_2DU2_[2WO/]J96O_G):>_R8A)?^FHZ+_G9B>_VIE:?]U<8'_*2I#_S(T -M//^)A(C_XMCA_R at C)_\>(![_,S$L_S&_\_/SS_0T- _R0B)/\?(1__ -M/T1 _V=D7__-R,/_ZMO at _R:_TM56?\6&!__)R at I_VUL9?]+3T?_8F-<_RHK)?]?9&#_45E6_XJ. -MD/_AV]G_/T-2_SQ&5/^ZM;#_049,_T!#1/_+RG[_ -M'A@<_R\J)/^IGY7_CX%X_VMC6?]Q8%K_DHV(_T!39?\A&2?_&1D<_R,A-/\@ -M(2C_9F%;_Q82&O\?'RK_%A8A_QX>*?\G*C;_+3 \_Q04(?\4$R#_%QDN_Q\A -M*?^'A(/_%A@=_QD8'O\G)2C_,"XQ_QT;'O\>'1S_+2PK_S0S,O]"04#_+BTL -M_RLM*O]X?7?_H)Z7_XZ(AO_ at U=K_&QP=_VU<3__=R,/_[=7:_S$I+?]!/#S_ -MM;>U_^+8V_^&A(?_,CH^_QT;)/]J9&C_:&5 at _U%64/]I9V+_1$$\_V-?7?\E -M(B'_B8F,_^/=V_\\0$__/$94_[>RK?]!1DS_/4!!_Z">H?\P.C?_0$9"_TE( -M3O\V.43_*2HU_R(J+/_$N;C_Q+6Y_]G-R/]-1#W_03LS_U)'0/_DT]/_7%)( -M_V=D4_]72D7_U<#&_T1'3/^!A(G_=G%W_UA26O]54%3_'1H9_QT8'O]O:F[_ -M<6U]_R at I0O\L+C;_:6QM__G8]_\6$17_(1$5_QT/&/\4$A7_%1 4_Q at 3%_\7 -M$AC_#@D-_S4P-/]&1$?_4$U3_T9'4O]6663_3$=-_\:UK__GTL[_C']^_QL9 -M&_\5&!G_%1,5_Q at 4%O\:%AC_%A(4_Q$+#_\." S_(!H>_QL5&?\4#Q/_(!L? -M_Q0/$_\>&1W_/SXS_[VTIO_ LJG_O+:N_\>_N_^JFX[_2%MY_U-05O\:'Q__ -M*R9*_QP>(?]85D?_'A at F_Q\=)O\9%QK_%!0=_R4L,O\3%B+_# T4_QH:)_\, -M&D'_1D91_\"YL_\F*";_'AD=_Q81%?\6%AG_$A46_R4F'_]64T[_(Q\A_R$C -M(?\D*27_/T1"_Q\C(?]345/_;FQI_XJ)B/\='QW_BWAN_\BTL/_6Q\O_(QTA -M_UI44O_#O;O_XMK=_X%^A/\H*C'_(!LA_W%E8?]^&AS_(!P> -M_W5S=O^ ?XS_+"T^_S$S./^PJZ__^-?H_Q@:&/\6$AO_& X7_Q02%/\5$!3_ -M$PX2_Q at 3%_\Y-SK_/SU _TI(2_]%0T;_0$))_T-%3?]'0DC_T+^Y_^W7S_^$ -M=7;_(!@<_QP7&?\7$Q7_&!06_R\K+?],2$K_6U59_TQ&2O\4#A+_(QTA_S$L -M,/] .S__&A49_Q0/$_^ZKZC_Q;&I_Z")A/^ ;&C_:V-F_[BFF/\S1F3_&!D: -M_Q(7'/\C)E#_%1@=_UQ82?\:&"O_'1TH_QH8&O\6&"#_(RPR_Q86)?\4%A[_ -M&!PQ_R(Z:_^4EZC_I)N;_T,^0O\<%AK_03Q _QH8&O\;'1K_2DA _Z&>F?\: -M%AC_+"LJ_T! /?\R+R[_$P\1_QH5&?\>&QK_*"PJ_VEI9O]B4DG_MZJE_\*Z -MOO\E("3_9U]=_Y^7D__BWMS_<7-Q_TM/4?\V.#W_7UI5_V)64?]/35#_6%)6 -M_TU-0O]+2DG_&1P=_W5^?O_=V=O_/$!5_RHT0_^_M[/_1$E/_S@].__/R\G_ -M*2LR_ST^1?] 0$G_*RXY_R8L-/\9)"7_P;:U_\*RMO_CU,[_=5U4_U!&._]; -M44/_Z]3/_W]L8/^+ at G'_9F!8_]3"QO]!0TK_.CY&_T5$2O]^?'[_(Q\A_Q\; -M'?\B'B#_:6=J_Q at 8(_\5%R;_3$Q/_[*ML?__[>#_+!\._Q\<(O\=&B#_(1X= -M_QX9'?\9%!C_&108_Q84%_\@'B'_+RTP_S?]%-CK_*1<9_Q8/#_\3#Q'_&!06_UQ86O]K96G_75=;_TA"1O]; -M55G_55!4_Q40%/\>&1W_$@T1_XV'A?^MI:/_O;BS_[BPK/^EI*O_PK&D_U)B -M?/\C(!__$QDC_T9;B_\9&R/_7E-(_Q,8,?\:'"O_$A(5_Q8=*_\J,SK_%1S_S4Z -M0/\\03__S"A/^UKK7_WM/( -M_X9Q9?]34D?_+2PE_]_0R_^.>6W_J9B(_VAD7/_2PL;_/T%(_S8Z0O]#0DC_ -MF):8_R(>(/^5D9/_EY.5_VIH:_\E)3#_(2,R_S0T-_^MJ*[___+I_]FC:O_ -MEVW_?5PX_QT;%O\1#AO_%!$>_QD1)?\T+D+_$ T9_Q84%_\8$QG_% T5_Q(/ -M%?\K*"?_Q;NW__#6S?^KHIO_:V5C_R,9%?\E("3_&10:_Q,.$/\<%Q?_$@T- -M_R(='_\?&!__(QPD_RH?'O\T)"'_.",A_RX<&?\G&1K_(AT?_QTB(/]U>7?_ -M0T5#_];1T_]::WO_&B8J_Q89)/\F3H;_&A\K_W)B4O\=-%[___CSLG_D7UU_SXU+_]&1#__\N'4_Y^'>/^LFHS_ at W=N_]_0U/]!0$?_769M -M_T!#2/^;F9O_&147_YJ6F/^GHZ7_<&MO_R(B,?\E*#K_+R\X_ZZFJO_\\.O_ -MW:=M_\J@%S7_*R1"_R at A,_\<%QW_'QH:_R 9&?\: -M$QK_'1@<_RDE(__.PKW_\]S7_S\].O\Y-SG_85I:_S8X-?\<'!G_)R4B_R\J -M*O^8C(7_II:-_].]M/_OT\O_Y<_&__#8S__MTF[_=G1Q_[6KI__7Q[[_OK&P_V!;7_]234__L*JN_XB*C_\A)BO_'!\D_QD= -M'_\M,3/_,C8X_R_Q\;'?^9E);_.#<]_T9+4?\O-#K_%Q,; -M_R D(O\A'B3_(2X[_S! 4/\Y.T/_J:*B_Z"BL?]-5V;_>WM^_^;@WO^2F:?_ -M-C]-_\.XM_\X/4/_.3X\_\S(QO\W.4'_.C]$_QHA(?\P-3O_$QH at _QXC*/\L -M*BW_*2$D_^?3S__MV-/_Z]G5__+DX?_ZY-S_]MW6__'S,C_Z=?9_TE# -M2_]\A8S_F)N at _Z6CI?]*1DC_I*"B_Z*>H/]Y -MU?_RXMC_]>+8_^'/R__8Q/^ ?GO_QKRX_]7&P?^ZKK'_ at 7E]_\:]O?_)O;[_1$!"_P\5%_\8 -M&B'_(R_Q$4%?\>'R#_,2\Q_SDU-_\V,3?_.#E _S(/\5%A?_W]#+__+=V/_UV]C_^=S;__?;W?_VW=[_\-G:_^_:V/_O -MV=?_FHZ1_X2&C?^HJ[#_H)N?_V9A9?^LIZO_IJ&E_W-N_VQF9/_$M[+_[M;3__'7U/_V -MW=C_\][9__'>V/_XW]K_[MO3__G%@O_)O[O_ULC%_[ROM/]J8&/_T<7!_\R]N/]M9V7_ -M)B at K_R(G+?\V.3[_)BHL_TI.4/\[/T'_1TQ,_SL^/_\@(2+_'QT?_];*S?_& -MO+__&A88_QX:'/\Q-CO_*B0H_Q8>(O\N/TW_,3]8_SE#3?\]4&+_,$1 at _R8S -M1O\1%Q__.D=8_RXY1/\=&AG_*S \_RPL+_]A863_+#0^_S=!1?\@+"O_+#4[ -M_R0Q-O\K-SO_)BPN_RTK+?_GV-/_[]K5__+=V?_UW]W_^.'B__;@WO_VX=W_ -M^.'<___GX/_FU=7_W/_YW]S_^-S8___ at W/_XW-C_^-[5__??UO_QV-G_\=?4_VY:5O\Q -M*"+_+2X1W_X^-B/\N(!W_'!02_PT<'/\O0$[_-455_S=+8?\R -M1V/_+D-?_S%&7O\Q0EG_-#Q&_Q88&_\4%AW_.C<]_QD6'/\7&1[_+S<[_QTI -M+?\A*C'_(S$T_R,P,?\P,C7_*R4I_^?3S__RV];_[]K5__?BW?_WXM[_^N7A -M__7 at V__WXMW__>+;_\^YNO]H8FK_J:NP_Y&-E?]^>X'_N+6[_Z>EJ/]M9VO_ -M>G>#_R,D-?\H*3#_*2_V _/_\=$"/_'R$?_U902/]J9&C_/T Y_]/'P/_GT]7_.#H]_QT< -M(_\9%AS_+3$S_S8X._\G+2__*3$S_RTR,O\4&!;_-37%T_S,N-/\M+S?_;G1^_VUO("__&$R%_R$\B?\D -M3(K_OK_*_WQW=_\C$R'_$!,8_YJ2B/^'@GW_T,;)_]_)R_^;G9O_R<7#_]3$ -MP?_9RL7_.S,V_Q47'O\8&!O_)2,F_QX>(?\A(R;_*2TO_R at J,?].45;_%187 -M_Y&)A__3P,#_T+V]_Z28E/],0SW_0T0]_U-73O^*A'S_G(N%_VEC8?]:6EW_ -M/$1._S=$5?\W1UO_,4)9_SI)7/\S/$/_*C R_R$G*?\V.CS_%A@;_RG9^_X!]@_^SL;3_K:NM -M_X)\@/^$?XO_)R8W_R4E+O]L:FS___'K_\6,4O_ DF7_SY94_\*37?_)F6+_ -MR)AA_\657O_*EU;_R)EI_V!%(/\F&A7_(AP at _R$?*/]/3TS_S\.\_^?6UO\O -M,S7_%QD at _QT<(O\C)RG_&QT at _R,I*_\P.#K_*"\O_Q@='?\K+B__&!D:_SL\ -M-O]&24/_*3 P_QDC)_\<(R__(R8Q_S8S.?_1R,C_Z-;2_^W:U/_VW]K_^-_: -M__+_QX;(?\G(B;_)" B_QP:'/\9&AO_(!TC_Q at 8 -M&_\7%1C_<6=J_XN#AO^>F9G_='!N_ZNHH__.O+C_+B@@_R\R)?_'O:[_GX]\ -M_YN.??^1B('_75Q;_TY15O\Y04O_-3]*_SD^1/\I,2[_+S8/]46ES_4%98_U%24_]/3E7_9F9U_Z^IM_]X='W_B(6+_X:$ -MA_^IIZG_BH2(_W]ZAO\E)#7_.#A!_VQN_RPP,O\4 -M%AG_*2LP_Q03&?\T,SG_(1\B_Q@>(/\C*RW_)BXR_RLP-O\X-#;_U,G._^#/ -MU__IU]3_[=G1__':U?_QV=;_\]K9__C,X'_*U.*_\'"S?]74%?_)Q at C_W1X>O^?EXW_AX)]_]W3UO_>R<[_ -M&1T?_YF7F?_.P,'_V,?'_V995/_/R<'_*"W7_/CPU_UM:4_]! -M/#?_$Q$,_PP*!_^JHJ#_SL/"_\2\N/]03D?_0$0[_UI43/^VJJ7_2D,]_RPM -M)O^WL*3_ at GAJ_Y6+@/^4B7[_85E/_R\M*O\X.T#_86-F_V)E7_]35$W_,C$J -M_TQ*0_\N+"G_,C0R_R,J*O\9'1__&QT at _Q<9'/\?(23_+2\R_Y>-B?^AE(__ -MHY:1_YN.B?^5C(;_D8B"_XR#??^, at WW_A'UW_RHF*/]A86K_MK*[_S(N-O^. -MBY'_%A07_Q .$/^%?X/_>G6!_RHI.O\I*3+_3%%6___PX__,G6W_RIIG_\N< -M9?_#E%K_QI1;_\*05__!CUC_P)-7_\"/7/_!C%;_OI!3_ZE]2_]&+QC_86-A -M_\S%Q?_=T(B3_(R at H_RPQ,?\R.#K_*S U_SU#2_^A -MHJW_*#U:_UUFC__9S-__\-G:__75R__PV=K_\-K8__'9UO_NW-C_[^#;_^WA -MV/_CV-?_766%_SY1E_\M3'S_O4?^ >G+_(B ;_[&JI/_ at SLO_A'EX_ZBCG?^UL:G_,C H_S8U+O^] -MO+7_I)^:_R,D'?^9E8W_<65<_W5N8O]K9EK_>71H_R =&/\='R+_&1<4_SX] -M-O\P,RW_35-/_V=E9_]B8E__1DM%_RDN+O\B*2G_*BTR_Q at 7'O\;&1O_FI*5 -M_Z"8F_^CFY[_KJ:I_[.JJO^[LK+_O+6U_\2_O__$SKW_6V!:_UA98/^KLZ__ -M*RTP_Y:2FO\Q+##_-C(T_W=U=_^)B93_)"(R_QT>)?\M,S7__^_B_[R2:O^Y -MCV'_K8E<_ZZ#5?^WBU__M(E9_[2+5_^WBUG_O(Y;_[>*5/^WBU/_O8E7_ZF -M5O^1>5[_V,J[_^31R_\L+2[_$Q4:_Q(6&/\6&AS_$Q48_R at J+?\0$A7_)RDL -M_QD;'O\F*"O_%!89_R4G*O\1$Q;_&R$C_QHB)/\?)2?_(2/_*PL7_V6__=W)F_WYZ:_][=&;_;&9<_Q\='_]0 -M3$K_4TM'_R$;&?\@&QO_+BDM_SP\.?]04TW_-#G5U_]')S/_8Q\?_V<;&_R,@'_^_NKS_3DY1_X.! -M?/^:EI3_FYF;_\O'Q?]V=W'_P;BX_RHF*/^ZL:O_X-#-_["HIO_!P+G_:&1< -M_SPW,?^JJ*'_4TY(_S8T+?_ N[7_,BXF_\&^L_]Z=VO_>WEJ_W]Y:?]\=F;_ -M/#HS_S0Y-?\/%1'_("0B_QL<'?\B("+_*"8H_R(?\;&AG_&A at 5_S(H*__:SLK_25)2_S4]0?\U/3__,3P]_R\W.?\J -M,C3_)R\Q_Q\G*?\;(R7_&2$C_QDA(_\@)";_'!XA_Q<='_\9(2/_&B4F_QXI -M*O\A+"W_(2PM_RXU*?\W267_$1DI_QH9&/\B+$[_*S1%_R B(/\>&B/_'R$F -M_R(E)O\C)B?_*"TM_S U,_\R-3;_-#,Y_SPX0?\^-CG_6%-._X9^>O^TJ*O_ -MP;R^_Z:;E/]'1$K_Y-W=__+;UO]Y='3_VM+5_]G(R/_0N[G_ at GIV_\2XN?\F -M(2/_PL' _U!.4?\T-CO_O[V__U]=7_^\L;C_*RSLO_85E7_S8U -M+O_)Q;W_9V9?_S\Z-/_#NK3_.3_RTQ+_^=G:;_>WF)_RHK -M,O_$O[K___+M_X1R:/\6%!?_%!8;_UY=5O])1T3_'!@:_QP7&_\B%13_'1$, -M_QL6%O\4%!?_$Q at 8_RDM*_^KIJ;_W]#+_[*KJ_\P-#;_*C(T_RLX.?\J-C/_ -M+SP]_RHV._\K,S?_*3(R_RDU-/\D,"__)# O_RHR-/\J,C3_("@J_Q at C)/\: -M(B3_("8H_R at N,/\F+"[_+"PC_QP[7?\'$R[_'148_QTWXL_^NI*#_ -MQKZ\_UY96?_,PK[_D(J(_T=(2?_'Q<#_,BHH_\S$R/\D)"?_N+"L_]C*Q__. -MP<#_A'UW_R(D&__*QK[_2#PU_ZRLH_^LK*/_,"\H_ZNLI?\W.S/_D)*)_S\_ -M-/]$13C_<7%D_V9G6O^1BX/_V,6__]["O_^ID8[_)Q at 8_RD=(/\2#0__$0\, -M_RLK'/\R-1__,30=_R\S'?\N,"W_,C,T_S$R,_\Q,C/_*BDH_Q43%?\8%AC_ -M3DQ/_Q48._^AG+;_9F%<_Z>BNO\<&S__(R(__UM;;O\S.#+_.3TU_R ?)?\K -M*#3_961J_\C"P/_^[_#_QK2P_SX\1?\D*##_&!83_Q at 7%O\5$Q7_%1,6_Z*= -MG_^OIZK_&108_Q86&?\E*BK_-3(/\;(R7_'24G_R H*O\O,2C_)$!;_PP7+_\A'1__(#MQ_R0M2_\: -M&1__(QXB_Q\;&?\Y-S#_2DA _TQ'1_\5&2[_'"U1_QTW8_\I0&K_'RE$_UI4 -M6/\H)2O_'R G_QX:'/\D(B3_*"8C_^;MJ?_$OKS_44Y-_]/*Q/^]LZ__J*6D_\K%O_^QI:'_Q+S _RTM,/^WKZW_ -MWM#-_S,H)_^AG);_5%1+_VIJ7__ MJS_-CLO_YVBEO]!/SC_N[JS_T$_./^N -MJ:/_5%1+_SL^,O]664W_4E5)_TY-0O_7Q[[_]-7/_^K/R/_6O[K_J9>3_T at _ -M/_\3$!;_%1(8_QD4&/\7$Q7_,"TL_Q83$O\=&1O_)R,E_Q at 4%O\<&1C_+2 at H -M_TY)2_^;E9G_#PL__Z>BS/^VL[__KJ/8_Q01//\@'C__*29#_V)C;O\Z.SS_ -M)B8I_R0C*O\L+"__TLK(___S]__.O+G_'QPI_QP?*_],24C_'!L:_QD7&?\9 -M%QK_'!8>_R :(O\<%QW_&!89_T=,3/\]/SW_O[JU_^S=V/_PW=?_T+VW_^C7 -MT?_ at T'2/_)!\9_YRS_\"ZN/]23T[_VM'+_[RTL/^ZL[/_S,.]_];(Q?_.QLK_)24H -M_\S$PO_:S,G_6U-1_SDX,?_!O;7_(B<;_X!]N_]2YLO^LEH[_ -MOZ:?_^'(P__:P<#_T[V__QL4%/\?'!O_7UU:_R8D'_\[/SW_+"\P_SL^/_\W -M.CO_.3T[_UY at 7O]?8&'_2TM._Q00&/\4#QO_#Q00_QD7*O\6$2W_%Q,M_Q44 -M,?\3$C?_.35+_S,R.?]$1D3_0T5#_]'(R/__]O+_P;2S_Q\>)/\2%!?_'1D7 -M_R0?'_\A'1__%1,6_S0I*/]#.#?_'QH<_QH:'?]$1D3_,#@T_\.YM?_QW-K_ -MY]O7_^'5T?_=T,O_V_Q83*O\5 -M$2O_%Q4O_QH;-/\A&CS_'A at L_QT<&_\E)"/_B(.'___S[_^WJZ[_%1(8_Q<7 -M&O]U<'#_/3 at X_Q82%/\8%AG_)A\?_QL4%/\;%QG_%1<:_TI)2/\T/#C_P[NY -M_^K;V__ at T=+_XM#4_]G(R/_3P\#_GYJ4_Q\;'?\5$AC_$Q,6_Q at 6&?\3$13_ -M&1<:_Q43%O\0$!/_$!(5_QD;'O\7&1S_%148_QD='_\@+2[_(RLM_R at K+/\= -M*B__)2LG_RPN-O\D07?_)2M%_R,?(?\D)B3_/STV_U%12/]=7E?_&!D:_PXD -M1/\91&[_!C-Z_RA)DO\>.VO_NZ:B_R D+/\E(!K_2TM(_Z& -M&R'_&QL>_R4@(/]U<'#_&147_Q$/$O^JHZ/_LJNK_Q<3%?\3%1C_'AH<_R$I -M)O^QKJW_P;R\_W=\@?])457_0TM-_T)+2_]*3TG_%Q47_Q,0%O\2$!/_&A@; -M_Q02%?\5$Q;_$Q$4_Q04%_\2$A7_&1D<_QH:'?\8&!O_&Q\A_R M+O\B*BS_ -M(RDK_QHE+/\C)2/_)28Q_R9">_\?)#[_)R,A_S4V,/]'13W_5E9+_TU/1O\A -M(R'_%2Q)_R!+=?\)-GW_)D>0_QPY:?^QG)C_%1DA_R8A&_]34U#_G)>1_T V -M,O_NW]__[]G:_S N*__9T<__W]#0_WMY=O_;S<[_GYV?_T5)2__3T,__K:NH -M_]73T/^\NK?_HYZ9_ZF?J/\T+R__'!H7_S4X/?\>(R/_%AH8_S at Z-_\S+S'_ -M&A88_W!M;/]&1$'_*"'%[_WYW@?^NI['_J)^?_Z^FIO\:%1?_%Q48_Q<9(/\4%2#_(R(S -M_QH7+O\:%RW_$Q B_QD5)?\4#!K_$ P4_S0Q,/\_/C/_2T@\_S at V+___\>W_ -MJIZA_R$>)/\:&AW_A8" _[:QL?\2#A#_&!89_QT6%O\K)"3_&147_Q47&O]H -M8F;_%1P<_YJ=GO\Z/3[_+C\__S%"0O\T1D3_.DQ(_TI33/\4%1;_%A,9_QP6 -M&O\9%QK_'AP?_Q43%O\3$13_%A07_Q02%?\<&AW_&A@;_Q45&/\:'B#_(B\P -M_QHB)/\B*B[_$QTG_R(>(/\:'2G_(3IU_R0F0?\J)2#_45%&_SL[+O]864S_ -M,30H_QX@'?\8+TS_'TIT_PDV??\J2Y3_(C]O_\2OJ_\4&"#_)B$;_W1T_\_( -MR/^ZLK#_VM+0_\*ZN/^[LZ__I9ND_U)-3?\B(!W_'ATD_Q06&_\7%1C_'!@: -M_Q -$_\3$!;_$Q$4_RLI*_\K*R[_&1L at _Q06&_\1$QC_)"4F_S4V-_\^/T#_ -M2TQ-_R at F*?\6&!O_+#$Q_V9H9O]05%+_/#X[_U=23?]L8%O_?W-L_W)J:/\> -M&1W_4$I._R$<(O\0"A+_+"8N_VQF;O]<4U/_K:2D_QH5%_\7%1C_#P\:_Q(1 -M'O\B'RO_%@\9_Q44&O\7&!G_HIV=_Z:>G/]*2$'_1D0]_TY)0_]23$3_?W=S -M___Z^O^\L;#_)R(B_R0@(O\D'Q__C8J)_P\+#?\5$!3_LJBD_[>KI_\?%Q7_ -M'!D8_Q\5&/\@)"+_EI:3_U]B8_\T0D'_.$9%_SI)1?\^34C_0T]&_Q$4%?\; -M%AS_$Q$4_Q at 6&?\9%QK_%Q48_Q02%?\9%QG_%A06_QP:'/\5$Q7_&!88_QPA -M(?\F,C'_(BDI_R4L+/\9'2S_'QL9_PX5(?\A.W3_&A\X_R%!?_ -M?'MT_Z*:EO]@5%?_Y=?8_^O(?\:&AW_%!07_Q$1%/\4#Q/_% \3 -M_Q,1%/\2$A7_%QH;_QH=+O\-$2#_&!$B_R4:+?\G+37_-CLY_U164_]54DW_ -M5%!._QD4&/]13E3_+BLQ_R(=(_\N)2S_;FEO_TU$1/^NI:7_&!,5_Q43%O\. -M#13_% \3_ZRGI_]\>'K_.#8X_S P+?^6EHW_H9R6_TQ*0_\>'AO_(R$C_R at C -M(_^WM;C___3Q_Z&6E?\:%Q;_'AH<_S&1__%1(8 -M_Q<9(/\4&B+_=W!W_QPD(/^*CXG_>7Y\_S5!0/\Y0D+_.4- _SM&0?]"3D7_ -M$A,4_QD4&O\5$Q;_%1,6_Q84%_\7%1C_%!(5_Q84%O\7%1?_%A06_QD7&?\8 -M%AC_'2 A_R(N+?\@)R?_+#0Q_Q,5)/\<&13_"Q4 at _QHR:_\9'S7_0#\^_T!" -M0/\K,"K_'QPB_S8T+?\W.3;_'S99_RE7A/\:1I#_*TJ2_SE2;_^QGZ'_%AX: -M_R8;(/^*BW[_I9^7_VA:6__JV=G_Z-C<_SDT-O]Y>7;_UGO_8S,__ -MC9*2_WR#@__(QK__O;BS_^#7U__*P;O_O[>U_XJ%A?]Q;FW_+BTL_QH<'_\6 -M&!O_%!07_Q at 6&?\/#0__$Q$3_Q,1$_\D(B3_'AP?_QP:'?\9%QK_%!(5_Q4/ -M$_\4#Q/_$ X1_Q,3%O\8'RO_'R5%_Q$7,?\:%RW_6$EB_V1I=?]D:6G_5EA5 -M_X6#?O]134O_&A49_U).5O]_?H3_?WA__X!W?O^VL;?_A7Q\_Z:=G?\<%QG_ -M'!H=_QP;(?\<%QG_K:>E_X:!A?\[.3S_+RXM_X:&??^=FI7_244]_QH8$_\: -M&!7_-"TG_[ZXO/__]/#_?79V_QD:(?\0#A'_B(2"_ZJGIO\>&AS_'1@<_W1I -M:/]N9F3_&A45_QT;'?\O)RK_%R 9_S8],_\Z0C[_)BTM_R,F)_\9'1O_*2XJ -M_T901_\;'!W_&10:_Q43%O\8%AG_&!89_Q at 6&?\4$A7_%A06_Q43%?\6%!;_ -M&1<9_Q43%?\>(2+_(R\N_Q 7%_\K,S#_%!8E_QL8$_\4'BG_&3%H_R\S2/]( -M1D/_)"0A_RTK(_\Z,#/_.3,K_S\].O\D0&+_+%>%_QY&D?\J2Y/_1%]W_[>E -MJ?\3&AK_(A<<_XV0?O^CH)3_>'!N_\&UN/_2R]7_'!XF_S@[//^UJ*/_J:2D -M_]G/TO]]@H+_FYZ?_\K%P/^ZM++_W-+5_\B^NO_.QL3_?GEY_XF&A?\?'AW_ -M%QD<_Q47&O\1$13_%Q48_Q05%O\.#Q#_/T!!_QX?(/\G)2C_)2,F_R >(?\4 -M$A7_%A 4_Q0/$_\/#1#_#P\2_QPE/?\;(5'_$QY _Q8;-/\O(#G_:6YZ_V1I -M:?]H:F?_B8>"_U).3/\D'R/_/#A _T9%2_\1"A'_.C$X_XR'C?]C6EK_HIF9 -M_Q\:'/\6%!?_$Q(8_QP7&?^JI*+_-"\S_QH8&_\G)B7_?W]V_WUZ=?\_-C#_ -M*R8A_Q\:%/]63$'_R\'$___V\/]53U/_-3I&_R at E*_\D(![_L:ZM_QD5%_\: -M%1G_8595_V-95?\;%Q7_'1P;_RH<'?\H*2+_E92)_X>(@O\E+"S_'R8F_QXF -M(_\J,B[_2E9-_Q at 9&O\6$1?_$Q$4_Q84%_\6%!?_%A07_Q,1%/\4$A3_%!(4 -M_Q84%O\9%QG_%Q47_Q\B(_\G,S+_"Q(2_RTU,O\/$2#_&Q at 3_QCLO]'6&7_.D9*_XZ& -M at O^HI:3_W=78_Y.8F/^IJJO_P;^\_[JYN/_8T]?_NK:T_\G"PO]S;F[_A8*! -M_R\N+?\8&AW_&AP?_Q(2%?\8%AG_#0X/_UA;7/]15%7_(B4F_R >(?\D(B7_ -M'1L>_Q,1%/\6$!3_% \3_Q$/$O\4%!?_'28^_QPC4?\4'4+_'" \_RX>.O]A -M9G+_65Y>_VMM:O^5DX[_44U+_Q<2%O\L*##_'ATC_S(K,O\Z,3C_?GE__U1+ -M2_^IH*#_'!<9_Q at 6&?\3$AC_&106_Z6?G?\8$Q?_%1,6_QH9&/^!@7C_F9:1 -M_SPX-O\F(B3_&1 at 7_U--0__ O;S___7R_T Z/O\;'"/_&!D:_WAZ=_^\M;7_ -M&A@:_Q43%O\F'Q__&A88_Q83&?\='"+_BX:&_RHK)/^=E(W_ at X%\_R\W-/\H -M+2O_&1\;_RTS+_]365'_&!88_Q01%_\4$A7_%1,5_Q02%/\3$1/_%!(4_Q43 -M%?\4$A3_&1<9_QD7&?\7&!G_(B&O\=%1G_&1\G -M_R0V;O\9'R__)BHB_RTP*O\V+2;_.S8V_VUP_[[#P_\^04+_S?]'1$/_&!06_RTH+/]'0DC_13M$_T,T/_^$ -M?(;_85-4_Z&9G?\4$AO_$Q48_Q,1$_\<%Q?_EY&/_PT+#O\5$AC_&!<6_V5F -M8/]K:6;_-38W_QH<(?\4$A3_5%)*_[VZN?__^/?_3$1(_R4D*O\>'R#_+S0P -M_[^VMO\9%QG_)"0G_[.KJ?^ZM;?_&Q8<_Q$/$O\>&1G_'R,;_Z&6C_^ ?GG_ -M-#PX_SD_._\M,R__-3LW_UU at 6O\8%AC_%!$7_Q02%?\3$1/_%1,5_Q43%?\5 -M$Q7_$Q$3_Q02%/\9%QG_&1<9_Q87&/\A*"C_,3HZ_Q(7%_\M+3C_(RLA_R,9 -M(O\?)2W_'RUE_S8U1O\W.#+_/T$^_S,X,O^9I:3_F:6I_VYU=?]/96/_,UEY -M_W1\D/^(@'[_AH&!_ZRFJO\;%AS_'AP>_XV.B/^=F(S_2%EF_T=MB/^OS^7_ -M=(ZC_T147O^$A('_F9J4_R_^$ -MB8G_D8^1_ZB at H_\8$Q7_%1,6_QH:'?\0$!/_%Q<:_PX.$?\6%AG_'1T at _QX> -M(?\?'R+_&1D<_QD9'/\/#Q+_$PT5_Q,.$O\0#A'_%!(;_Q4>-O\9(U#_&R5* -M_Q09-_]E3WS_?GF%_Q 8&O\:&B?_'1D;_U524?\H)";_,"LO_RF_\Q,C/_'!P?_QT;'?]+2D/_AX2#___X]_]#.S__'QXD_Q46 -M%_\E)2+_L:6F_QL9&_\9&Q[_&1,1_Q81$_\<%QW_&QD<_Y*-C?]%24'_HI>0 -M_W]]>/]<95[_9FUE_V!G7_]A:&#_9&A at _Q@6&/\9%AS_%A07_Q84%O\:&!K_ -M'1L=_Q84%O\5$Q7_$A 2_QD7&?\7%1?_%Q at 9_R8M+?\T/3W_%!D9_S,P//\A -M*![_&A 9_PD2&?\;*6'_&Q'S_3596_U)I -M:/\S6'?_<7)]_Y> ;?^%=V[_J*">_R$?(O\?'1__C8J%_ZBAE?^1HJ__)4]I -M_[//Y/^URMS_$QTG_XJ%?_^#@'O_'B(D_UE;8/^_N[W_O;F[_RPQ,?\T0#__ -M-#T]_TQ85_\D)RC_E(R/_QD1%/\6%!?_&AH=_Q 0$_\8&!O_%148_QX>(?\> -M'B'_0T-&_RHJ+?\@("/_*BHM_Q(2%?\4#A;_% \3_PX,#_\3$1K_%2$\_QHE -M5/\<)TK_,C5._V)4>O^ ?H?_#1 5_Q42'O\0#0S_4$U,_QD5%_\@&Q__0T)( -M_U945O]C7%S_IJ*J_VYO=O\6%!?_&1(2_S$E(?\?&AK_&Q04_ZFCH?\4$1?_ -M$P\7_P\-#_]B8UW_FYN8_ST].O\=&QW_&QD<_RTN*/\:%AC___KY_RLC)_\2 -M$1?_'!T>_WEW=/^FEYC_%1,5_RDM+_^[M;/_G)>9_Q at 3&?\=&Q[_%Q(2_T5) -M0?^HG9;_A8-^_V5O9O^%C8/_;'1J_V=O9?]I;67_%Q47_QH7'?\:&!O_&!88 -M_QL9&_\>'![_'!H<_Q at 6&/\:&!K_&A@:_Q at 6&/\7&!G_*"\O_S([._\4&1G_ -M-3 \_R(F'?\@%A__'2DP_R$V;/\6%"3_(A\>_R$M-/^*I*?_ at IVD_UUT>?]& -M4D__46IO_RU5?/]T>8O_D8!R_W- at 5O^>DHW_(2(C_Q\;'?^2BH;_IYV2_YFJ -MM_]VHKS_F,38_ZG-XO\J.TC_B(.#_YV8D_\>'B'_2TI0_\7 PO^NIJG_.C at Z -M_S@[//]+3D__/D-#_QH='O^"?H#_&!D:_QD9'/\<'!__$Q,6_Q04%_\6%AG_ -M%A89_QH:'?\]/4#_'Q\B_QD9'/\?'R+_#@X1_Q0.%O\4#Q/_$0\2_Q(0&?\8 -M(CW_(BI6_Q8<-O\8&"'_5$QG_T ^1_\K)R__&QHA_X.!?O]23T[_&A88_RE -M_RLH+O\?&R/_%!(4_V)C7?\;&QC_,S$L_QL8%_\5$Q;_*2TK_Q at 6&/_Y[>[_ -M)Q\B_Q81%?\>&QK_'1T:_YJ.D?\H)2O_*"DJ_S$I)_\J)2?_%1(8_R(@(O]^ -M>7G_6U90_Z.:D_^4DHW_;G5N_Y&6D/]Z?7?_;G5N_W)S;?\4$1#_&108_QD4 -M&/\6%!?_&!89_Q at 6&?\9%QK_&1<:_Q84%_\@'B#_%Q85_QL:&?\G,S#_-#DW -M_Q8:&/\X/D#_(1\<_QX7$?]&3E[_)"U<_QH;)O\@'AO_)C0S_X:;G?]SB8O_ -M87=U_UMD7?]>=7#_+D]Z_WA\?O^. at O^I -ME8W_4%AB_V24J?]YJ,#_F\WH_UM\D_^\M[W_ at G9W_Q\@(?\[/C__S\G'_ZBA -MH?\Q+S'_+R\R_RHI+_]<6%;_'1H9_T-"2/\)"!7_'18B_R :(O\9%AS_$!,4 -M_Q45&/\4$A7_$0\2_Q84%_\?'2#_%A07_Q$/$O\1#Q+_$A 3_Q(0$O\2$!/_ -M%1(8_QTC0_\1%C#_$0\2_Q<1%?\I)2[_)R0J_S M,_\N+"__,2\Q_R8D)O\> -M&AS_0CT__R(E/O]*46?_%!XL_R,S3?]*5G7_"PP=_R$9%?]A7$K_0SXY_Q at 3 -M%?^BG9__*B0L_QH5&_\5%Q7_24Q&_U!/2/^LHI[_&1T;_Q at 9&O\H)BG_,"XP -M___S\O\H("/_)"$G_R$<'/\_03[_=&EN_Q -$_\E)B?_-2HI_R7/_>'AU_Q<4$_\8 -M%!;_%Q(6_Q$/$O\6%!?_%!(5_Q<5&/\5$AC_%A07_R,A(_\;&AG_'!L:_R)U#_%1LC_R(>'/]46UO_5&=G -M_W2*B?][CHC_8&IA_UEP:_\N2WO_=WQZ_YF#@?]U:V#_=G!N_RHK+/\P,B__ -MCXZ#_VIB8/\,)S+_<:C _X.QS?]BEK?_>:+ _[.SO/]N8F/_)"(D_RXR,/_/ -MR(?\=&QW_ -M(B B_VIF:/\F(2/_$P\?_Q at 8(_\5&!W_&B4P_QXF.O\Y/47_)R(=_S4O)_]L -M:VK_# T._Z2BG_\U,"O_(1P<_Q88%O\^0S__3$I%_\6YM?]'3$K_+B\P_QD4 -M&/\8%AG___3Q_SDT.O\7%R3_)B$E_RDK*/]]_["PL_]"1$G_LK"S_QH:'?]S=7C_%1(8_QXB)/\E -M*2O_%!07_Q,.$O\6%!?_&A@;_Q<5&/\2$!/_%1,6_Q,1%/\0#A'_$0\2_Q$/ -M$?\1#Q'_#PT0_QL8'O\?)CS_%!8E_QT8&O\E("3_$A 3_QD7&O\L*BW_'1L> -M_Q<5%_\5$Q7_34E+_RDD)O\:$A;_%A(4_Q(1$/\A'R+_$18<_Q@>(/\L*2C_ -M'Q,6_V1:;?\;$BK_C("5_X%V??]%/#S_(1X=_SQ /O\P,C#_S\3#_S U,_]' -M2$G_(!L?_QH8&___^//_03U&_U-8:O\4$A7_)"0A_V]D:?\7%!K_$Q05_R@= -M'/\6$!3_%Q8<_QH6&/^/BHK_?WAR_YV7C_^MJZ;_TM#-_]C0S/_7R\?_K:BC -M_ZNIIO\9%A7_&Q<9_QH5&?\3$13_%Q48_Q$/$O\4$A7_%1(8_Q84%_\6%!;_ -M.3 at W_R0C(O\I.#3_-3DW_QD=&_\O-##_)2(H_QT?'/\4&B+_%QL[_QP>(?]; -M65;_BYB=_XFCIO^%F9W_96UO_UAB7_]7;VS_)4)R_WA]>_^+=7/_;V5:_T]) -M1_\D)2;_(R4B_YV4C?]=;''_'RY%_Q K0_]]I;K_F\OG_Z',Y/^\P,+_4$=' -M_RDG*?]@9&+_SLC&_YF4E/\;&1O_N[N^_TI,4?^XM[[_&1L>_V!C9/\8%!+_ -M(1T;_R8A(?\9%!;_% \5_Q at 6&?\B("/_'1L>_Q(0$_\1#Q+_$A 3_Q84%_\3 -M$13_$0\1_Q$/$?\-"P[_'!D?_S,[2_\2$A__%0\3_Q(3%/\0$!/_&!89_R0B -M)?\7%1C_&!88_Q<5%_\8%!;_&A47_QP7'?\-#Q;_!PP2_P@'#O\3#A+_'!H7 -M_Q\;$_]^:6?_?6)R_T at N2?]3/5?_0C8__XV"@?]645'_.3L^_RTO-/_.PL/_ -M+C,Q_TQ-3O\=&!S_%Q0:___Y^O\G)BW_*B\[_S4T.O\H(B#_5U%5_QX;(?^6 -MD9/_M*RJ_SXY/?\.$!7_&A@:_QX;&O^ ?G?_E9.+_[RZM?_7T<__V]#/_]?, -MR__"M[;_K:FG_R0A(/\:%AC_%1 4_Q,1%/\9%QG_%Q47_Q at 6&/\7%1?_%Q47 -M_QL9&_\?'1__'R,A_R\W-/\X/3O_'"$?_S0X.O\?(2;_&AT>_Q$6'/\7&BS_ -M%R(C_T-84O]YCY?_EK&\_WR8H/]>>(/_0U=E_TAE7MY_Y:$=O]P -M95K_2T=%_T)%1O\Q-C+_CH^(_WIW=O\<&2;_05IQ_X&PPO^9Q=G_C+?)_ZJY -MN?\X-33_.3X^_V1I9__-R_]O:&__HYZ at _YV7E?]*1T+_55-5 -M_];*R_];4U'_2D-#_QH5%?\<%AK___3T_RPG*?\>("7_(1X=_RXF)/],1DK_ -M(R F_R8>(?\J(B#_'1@<_Q@:'_\<&AS_=G-R_X.">_^8F(__O+JU_]C0SO_> -MT]+_V<[-_\6ZN?^JIJ3_1T1#_Q82%/\7$A;_%Q48_QH8&O\7%1?_&!88_Q<5 -M%_\7%1?_&QD;_QT;'?\?(R'_,38T_S,X-O\=(B#_.#8Q_R0B'_\?'"+_%A,? -M_Q01*/\P-U7_'S%5_R V7/\O5'?_.VJ-_RU:@O\>16__+%5Y_RY(;_]\@XG_ -MGI"!_VQ at 5_]%03__+C$R_RHO*_]?8UK_ at 7]Z_UUF;?]9?)/_;YZV_Y_!V_^# -MI;G_H::K_S,L+/\T-3;_55I8_WZ ??]L:VK_*2PM_Z"DIO]>8VC_PL##_Q,1 -M$_\0$Q3_'AH<_R,A&O^XKZG_BWQ\_Q<1%?\6%!?_%!(5_Q02%?\3$13_$Q$4 -M_Q,1%/\2$!/_$A 3_Q,1%/\2$!/_$Q$4_QH8&_])1TK_%1,6_Q .$?\2$!/_ -M$A 3_R >(?\B("/_(R$D_Q<5&/]$0D7_%!(5_Q .$?\4$!C_$@X6_QH6'O\G -M(RO_,2XT_S at S.?].2%#_85ID_Q$.&_\4$1W_'!@@_T(]0?^MJ*K_LJJH_WMO -M:O]L967_BX*"_W!G9_]L967_7%=7_T,^0O__\.S_.S0T_RDJ*_]-1T7_-2TK -M_S8P-/\:%QW_65%4_V-;6?\G(B;_&QTB_R8D)O\V,S+_CXZ'_YB8C__$PKW_ -MV='/_]?,R__:S\[_Q;JY_ZJFI/]/3$O_%1$3_Q81%?\3$13_%Q47_Q84%O\5 -M$Q7_%1,5_Q84%O\>'![_&A@:_R(F)/\X/3O_,#4S_R,H)O\U.3?_%Q\I_PL7 -M,O\,$S?_"!,R_RL\:O\>.7;_*4M]_R=0@?\^;)[_+%J,_S);C/]%:)#_3F:- -M_TQ47O^7C8+_=VMB_S at R,/\_0$'_2$A%_VIN9?]J;F;_=8.&_SM=GK_N,#"_Q4?(_^] -MN[[_'!H<_QH='O\>&AS_%1 at 2_[>IIO^;@(;_% \5_Q$1%/\4$A7_%!(5_Q . -M$?\4$A7_$Q$4_Q,1%/\1#Q+_$A 3_Q43%O\3$13_%!(5_QX;(?\3#Q?_$0T5 -M_Q ,%/\1#Q+_&A@;_QD7&O\8%AG_$A 3_QT;'O\4$A7_&A@;_Q(/%?\2#Q7_ -M%1(8_Q42&/\3$AC_$1,8_Q,5&O\7&1[_$1(9_Q,2&/\R,#+_'QT:_Z&5_T]-3_])1T3_'QL=_QP8&O\C)2C_/DI3 -M_Q8M,O]/8F[_CJBU_QPE)?\E("#_/#] _TA-2_]65E/_34Q+_TQ-3O^RM+?_ -M&!L at _[2OL_\>'![_'R(C_QX:'/\A'QS_N;6S_UA35_\6%1S_$@\5_Q(0$_\0 -M#A'_%A07_Q\=(/\5$Q;_%1,6_Q02%?\3$13_$0\2_Q,1%/\2$!/_-S,[_S(N -M-_\=&2+_&A8?_Q(/%?\7%1C_%Q48_Q<5&/\/#1#_(!XA_Q<5&/\0#A'_&A@; -M_Q02%?\4$A7_%!(5_Q,2&?\3$AC_%!07_Q,4%?\4%1S_$ X7_U%/4O\?'!O_ -M;F]P_V9D8?^%@'K_5%-2_TQ04O]%24O_2$A+_TI(2_]'14C___C[_R(?)?\5 -M%AW_'QP;_SPV-/\@&Q__(QTA_RX?'_\G%Q3_(AH>_Q,5&O\1%!7_0$%"_XB& -M at _^;E8W_Q\*]_];/S__=U-3_V]'-_]'%P?^>EY?_'!<9_Q82%/\4$A3_$ X0 -M_Q43%?\=&QW_$Q$3_Q<5%_\9%QG_,"XP_QH8&O\E*B;_,C8?]%.C__'QH:_RXJ+/\;%1G_%Q,5_R0C -M(O\?&AS_-"4?_R<9%O]74E3_>W-Q_R4=(/\E)"K_)BHL_R @(_\H)BG_&18< -M_VAG;?\@'R7_G)ZA_Q<9'/\:&AW_'1L>_R,>&?_$P<#_:&=M_R,@)O\7&A__ -M%QD>_Q(/%?\8%QW_*RPM_QT;'O\@'"3_$Q$4_Q84%_\U,S;_#0L._Q84%_\Q -M+C3_.#0\_QH6'O\;%Q__%Q(6_QH5&?\6$17_%1 4_Q83&?\7%!K_%!$7_Q83 -M&?\1#A3_$0X4_Q83&?\5$AC_%A,9_QL9'/\9%QK_&1<9_Q$-%?\3#Q?_.#0\ -M_RLH+O\G*2S_U_[VUL?\<%QO_&!<=_QD5%_\5 -M$Q7_DHV-_YZ5CO_*Q<#_UL_/_]W4U/_77_(!D9_RPJ+/\S.CK_2$M,_RDJ -M*_]A8F/_?7Y__Q$2$_^SM;C_&QT at _Q86&?\<&AW_*28A_[VXN/]@6F+_&Q@> -M_S(W//\X.C__'QPB_R at J+_] 04+_%Q0:_R7_R0?(?\= -M&1O_%A06_Q<5%_\9%QG_&A@:_Q,1$_\2$!+_&A@:_QP:'/\:&!K_)RPF_S<\ -M.O\J+R__)2LG_R\Q+O\H)B/_/#DT_T0_.?]'/SW_&Q(2_R,<'/\>&1G_,RHD -M_T0\./]234W_:%]9_V9:4?]Q9EO_>FU at _X5W:/]Y<6?_9F-8_VQK8/\U,S#_ -M(!XA_R(@(O\H)"+_+1X8_T8K&O\X(17_U,;#_Y2,BO\>&AC_75]<_V%L9_]: -M8%S_7V5A_VEO:_]=8U__/4,__TI/3_\1$Q;_#P\2_Q84%_\W-"__3$='_R : -M(O\8%1O_-#D^_UQ>8_]95ES_,#(W_U!14O\2#Q7_(!PD_Q<5&/\6%!?_&QD< -M_Q84%_\@'B'_%1(8_R0A)_\4$1?_'ALA_QH5&?\:%1G_%A$5_Q0/$_\7%!K_ -M%A,9_Q at 5&_\5$AC_%A,9_Q01%_\6$QG_&18<_Q00&/\@'"3_%1$9_R,?)_\U -M-C?_4U53_V5G9?]*3$K_2DQ/_T1&2?]!0T;_/D!#_T)$1_\_043_.SU _SY -M0_\Y.3S_^O+U_S0O-?\D(RG_;VIJ_Y:2D/\>&1W_+2 at L_Z"5E/^+?WO_'1<; -M_QH9'_\=&QW_'1X?_Y60D/^>E8[_S\K%_];/S__8S\__U,K&_]C,Q_^=E)3_ -M&A47_QT9&_\5$Q7_%Q47_Q at 6&/\:&!K_$Q$3_Q,1$_\;&1O_'!H<_QP:'/\G -M+";_.3X\_RHO+_\F+"C_-30M_R\J)/]+13W_6U-)_W]S:O]-03C_13LQ_TU% -M._]P8U;_(1D5_R\K+?]/1#W_%Q[_&Q@>_Q42&/\5%A?_$Q05_Q87&/\0$1+_#@T3_QP;(?\8&1K_ -M'B >_R at M)_\\03O_*S L_RLP+/\O*RG_03PV_U=11_]H7E#_8E!&_U! -O]% -M.B__75-(_U]23?\5$!+_$! 3_VYI8_]L8EC_>VYA_WEK7/^$=VK_8UQ6_V!< -M5/]Q;&;_'A89_Q40%O\2$!/_(!D9_U1!.?]A0RW_5#_Q06&_]$1DG_%!8;_QT=*/]$ -M1DO_+2LT_Q\<(O].3$[_3TQ2_Q01%_]85EG_'AP?_Q84%_\1#!#_&A88_Q at 3 -M%?\A&AK_&Q8<_Q,/%_\;%Q__'1DA_QP:'?\@'B'_'QT at _U)04_]O<73_55E; -M_TU14_]*3E#_0TA-_S]$2?\^0TC_/T1)_T!!2/]#0DG_0D%(_T)!2/\]/T3_ -M/4%#_SH^0/\V.CS_%1,5__SZ]_\K*"?_&!88_QL9'/\M+3#_&!@;_Q86&?\4 -M%!?_'ATD_Q06&_\5&!G_*28A_QX?(/^/CHW_GIB0_]/.R?_3R\G_U8_Q at 2%O\9&1S_&!,7_QP8&O\:%AC_'!@:_Q<3%?\1$A/_'1X? -M_QL=&O\D)R'_'" 8_T!#/?\E)R3_%1<5_QX:&/])1T#_5E-(_VE?4?]X9ES_ -M6$@^_T4X+?]21SS_8E-3_QH2%O\8&AC_W=U_V]Q:/]B9&'_&AD@ -M_Q<6'/]%0#O_3TE'_QL5'?\5%QS_&B(F_SD[0/\9%AS_%!8;_T=)3/\/$!?_ -M'!PE_U!25_\V,3W_'QLC_V%?8?]855O_$Q 6_UA66?\>'!__'QT at _SLZ0/\8 -M%QW_%!$7_Q83&?\9%!C_$@P0_RHD*/]*1$C_4E!2_W1R=/]<6ES_6%98_TM- -M4O]'2D__1DE._T)%2O\_0D?_.SY#_S@[0/\S-CO_+C U_RXM,_\N+3/_+BTS -M_RLM,/\K+3#_+C S_RLM,/\@'B#_\_7R_SP^//\A'R'_CXJ._T]-4/\6%!?_ -M%Q48_Q43%O\C&Q__&108_QT@(?\6&!;_&Q\=_Y"1B_^BFY7_U<_-_];+RO_5 -MR<7_T\K$_\W'O_^>DI/_% \1_QD:&_\;%QG_&!,3_QD4%/\>&1G_%A$1_R4F -M(/\R-2__0$,]_T)%/_\R,B__+BXK_R$@'_\1#Q'_(!L;_T1"._]$03;_7%)$ -M_WIK7O]31#?_0C,F_U-"-?]:2TO_'AD?_R,E*/]234?_;6)7_V582_]K7E'_ -M95Q5_U)-4?].2TK_:FAC_Q41$_\6$A3_&A<=_Q83&?\J'A__6#TL_TTX)O]H -M7UC_;FIL_QX7(?\@'R;_4UM?_V%E9_^)B(?_%!$7_Q<3'/^"@(/_?X%^_V-C -M9O\8%A__%!,9_TY,1_\6$Q+_&14>_Q at 7'O\8("3_5%9;_Q,0%O\@(B?_65I; -M_Q,2&/\H)R[_9&1G_S0P.?\?&R/_9V5G_V%>9/\3$!;_5U58_QX<'_\C(23_ -M96-F_QP;(?\6%A__1TI5_R <'O]D7U__ at GU]_UU86/].3$__2DI-_T]/4O]& -M1DG_0$)'_T)$2?\^0$7_/3]$_SY 1?\Y.T#_/D!%_ST_1/\]/4#_/S]"_SX^ -M0?\_/T+_/CY!_SP\/_\S,S;_(" C_QH6&/_V\O#_/SHZ_RTK+?\G)RK_FIB; -M_Q at 3%_\8$Q?_&108_QP8&O\5$Q7_&AT>_Q at 6&?\?&QG_FI6/_YF4CO_6V=K_ -MS]/5_]#0T__-R,K_R[_ _V)65_]'0D+_?X%__V)?7O]34U#_0D(__S,S,/\N -M+BO_.#LU_S0V,_\K+2O_(R,F_QP9&/\6$Q+_$0P0_Q40%O\@&1G_14,\_U93 -M2/]M8U7_@')C_W-E5O]N7$[_;UM-_UU.3_];5U__*"LP_T5"/?]G6U+_9EE, -M_UM01?]*1D3_(Q\G_QH8&_]555+_'AT<_QH5%?\9%AS_&!<>_Q\9'?](+B'_ -M2C at J_U)33/]&14O_(!LG_Q<9(?]>9VW_8F=L_VAG9O\=&B#_&QLF_T)$3/\X -M.CW_+2PS_Q at 6'_\6%1O_/$$]_PT/$O\4$1W_&!8?_Q$9'?]%1TS_&!4;_Q06 -M&_],3DS_&A@;_R,@)O]F9&;_+"@Q_Q\;(_]H9FC_75I at _R,@)O]&1$?_(1\B -M_R0B)?]02DC_13\]_T9$1_\5%1[_8F1I_U!/5?],2U'_24A._TE+4/]&2$W_ -M/T%&_T!"1_]-3%+_-30Z_S O-?\M+#+_*RHP_RLJ,/\J*2__*2 at N_R_Q at 3%_\8$Q?_%Q(6_Q02%?\5$Q;_&108_T0\./^7D8?_F9B1 -M_\'$Q?^TN;[_K[.U_[:TM__!N;W_96-E_V=J:_]=8&'_,S8W_R0I*?\A)B;_ -M(",D_R,D)?\B("+_'1L>_Q at 6&?\6%!?_$ X1_Q,.$O\3#A+_$@T1_R(=(?\_ -M.3W_+"8D_UY72_]K85;_74] _WQD5?]^9%G_+1XB_R at C*?\W,S7_/CLV_V5: -M3_]A5TG_5TQ%_SPV-/\:%A[_%Q@?_SP_1/\]/$+_'ALA_QP;(?\/#1;_)B(K -M_RTB)_\E(AW_6EQ3_U-15/\;&"3_&1DB_UE<7?]77%;_6EQ9_QD9'/\9&![_ -M7F)@_V]Q;_]D9&?_&!<>_QP;(?\_03__*2DL_QD5'?\=&2'_/ST__QT:(/\9 -M%1[_%Q8=_S$P-O\;&![_'!H=_VII:/\B'RO_(!TI_U!+3_],1D3_*B(>_R@@ -M'/]/2D7_:&5 at _XF%A_]85EG_24=*_Q44&O])3%'_1DE._SP_1/] 0TC_/D%& -M_T)%2O]%2$W_0$-(_T%$2?\_0$?_.CM"_SP]1/\Y.T#_.SU _ST_0O\O,33_ -M*RPM_RPJ+/\I)RG_*2_\6$17_&A49_QD4&/\8$Q?_&!,7_Q\:'O\F(27_2T5#_Y"+ -MA?^+B83_'Q\B_V)G;/]26%K_2DY0_S4D/_;%E'_W5 at 5/\I(27_,BTS_T1 0O]" -M0#W_55!*_U%,1O]'0D+_.C4Y_Q\;(_\7&!__4UA>_U-26?]/3E3_5U9=_Q at 6 -M'_\[.$3_,R\X_UM96_];7%;_6%99_QH7(_\9&!__6UQ=_U]C6_]@8F#_&!<= -M_QH9'_]?85__8&)?_UY>8?\8%Q[_%Q8<_T5$0_\V-#?_&!0<_QT:(/]K9F;_ -M;6AN_QD5'O\<&R+_;VQR_QT:(/\C(23_5U57_R8@)/\L)"C_4DU-_UM65O^ -M>WO_A8""_T1 0O\T,C3_)"0G_Q\>)/\;&B#_$A$7_R(B)?\H)BG_*RDL_S(P -M,_\R-#?_-SD\_SD[/O\Z/#__.3M _S at Z/_\V.#W_-3<\_S(T-_\L+C'_*"HM -M_R_R at F*/]>7%[_>G5P_ZFAG?]W_U157/].3E?_1$9._SU#2_\X.T#_.3Q!_R\R-_\I+#'_*RDL_R\J+O\M -M*"S_+2 at L_RLI+/\H*"O_)B8I_R8F*?\F)BG_)24H_R at H*_\G)RK_)R%!?_,2DL_RPG*?\<%QO_% \3_Q40%/\4#Q/_%1 4_Q40%/\4#Q/_ -M%Q(6_Q,/&/\7$AC_&!,7_Q at 1&?\3#!/_%Q$5_Q40%/\1$13_$A 3_Q(0$_\1 -M#Q+_$0\2_Q 0$_\-#Q+_%1,6_R ;'_\5$Q;_$A 3_Q$/$O\1#Q+_$0\2_Q . -M$?\1#Q+_$ X1_Q$2$_\8%Q[_&!0<_R$='_\1#Q'_2D9$_U502O\C(B'_$Q$: -M_Q43'/\M+#+_4U15_TU05?]665[_7EUC_S M,_\<&"#_%Q@?_UYC:?]B86C_ -M8F%G_V-B:?\8%A__%Q0 at _UY?9O]@86C_8&%H_U166_\;&B'_&!<>_V5D:O]E -M9&K_7UYD_QD7(/\<&B/_34U0_S$S,/\G)RK_&QHA_QD8'O]!0#__+2LN_R < -M)/\G)"K_0#TX_T(^0/\A'B3_'Q\B_V1E7_^"@WW_EI64_V=E:/]565O_55A= -M_TY05_]*2E/_2$=._T9'3O]%1T[_049,_SY#2/] 14K_/D-(_SU"1_\^0$/_ -M/CY!_S0T-_\O+S+_+"HM_RLI+/\J*"O_*B at K_RLI*_\H)BC_*2(/\E(2/_)B$E_R,>(O\W -M,C;_)!\C_Q81%?_Z\?'_(!<>_QL4'/\;%AK_&!,7_Q40%/\5$!3_%1 4_Q40 -M%/\5$!3_% \3_Q<2%O\7$Q7_%Q(6_Q,.$O\8$QG_'!4?_Q at 3%_\5$A'_%! 2 -M_Q$/$O\2$!/_$Q$4_Q,1%/\3$13_%!(5_Q82&O\<&"'_&Q8:_QP8&O\?&QW_ -M&Q<9_Q<2%O\5$!3_%1 4_Q0/$_\3#Q?_%Q,;_QX9'_\?&1W_'1D;_R,@'_\G -M)"/_(1X=_Q82&O\8%!S_(!XA_TM+2/]-3TS_3E)*_TY/2/\<&!K_'A -M_QL=(O]A8FG_8F)K_V%A;/\7%R#_(B,J_TY05?]355K_5U)8_R6/]K:FG_E9.5_X2 @O]95E7_6%A;_U-56O]04EG_3E!7_TM-5/]) -M2U+_2TU4_T=)4/]"1$O_1$9-_T1&3?]#14S_04-*_T%#2O\^04;_0$-(_T!# -M2/]!1$G_/#Y%_ST_1O\]/T;_/D!'_ST_1/\\/D/_/3]$_S at Z/_\R,#/_*B at J -M_RLI*_\H)BC_*"8H_RDG*?\G)2?_)"(D_R[U_SXT/O\F'"O_'QDA_QD4&/\6$17_ -M%1 4_Q<2%O\:%1G_&!,7_Q40%/\8$Q?_%Q03_Q<3%?\:%1O_'17YX_Y&1 -MCO]O:FS_5U=:_U)45_]14U;_4%)7_TY/5O])4%;_2$]5_T1(4/]%1E'_1DA0 -M_T=)4/]&2$__1$9-_T%#2O]$1DW_04-*_T!"2?] 0DG_04-*_T1&3?]!0TK_ -M/D%&_T)%2O]!1$G_1$=,_T%#2O]!0TK_/3]&_T!"2?] 0D?_/D!%_S]!1O\^ -M0$7_.3M _ST_1/\\/D/_.CQ!_ST[/O\W-3?_,C R_S N,/\M*2O_)B(D_Q82 -M%/\7$Q7_%1 4_Q(-$?\7$A;_%1 4_Q81%?__^?C_(1,4_RD;(_\;%!S_&Q8< -M_Q<2%O\<%QG_(AH=_QX7%_\=%1C_%Q(4_QD4&/\6%!;_%Q47_Q,0%O\7$QS_ -M&A,?_QT7&_\A&AK_%1,5_QP9&/\Z-S;_/#H]_T5$2O])24S_3T]2_QT9(?\C -M'";_(APD_TE&3/]'1$K_1$)%_SDW.O]$0D7_3DQ/_U%/4O\9$AS_&Q0>_RDE -M+?]45EO_55=<_U577/]<7F/_7%YC_Q41&?\:%A[_(B$H_UE87O]56%W_6%Q> -M_UE;7O\8%1O_(!PD_Q<6'/]14U'_7%I5_U=63_]345/_&A8?_QX:(O](1DC_ -M/3XX_TE*1/\I)RK_(AXF_R0C*?]:6US_6UE6_UY85O^!?'S_ at 7Y]_UY?8/]0 -M5%;_5%=<_U-56O]25%O_3E!7_TM-5/]&2$__0T5,_T1)3_](25#_2$=._T9' -M3O]*3U7_24I1_TA'3O]#14S_24M2_TA)4/]&1T[_0T1+_T)$3/] 0DK_0T5, -M_T9)3O]%2$W_1$=,_T!#2/]$1TS_04-(_T-"2/\_/D3_0T)(_T%#2/\Y/$'_ -M.T!%_T _1?\^0$7_.CQ!_SH\0?\Z/$'_.SL^_S\]0/\5$Q;_)2,F_Q<5&/\T ->,C7_%Q48_R\ "MR L]0 +G@ "_Z Q?0 ,P #2# V!@ -M-XD #D+ ZC@ /! #V3 _%@ 0)D $(< !#GP 12( $:E !( -M* 2:L $LN !,L0 3C, $^V !1.0 4KP %0_ !5P@ 5T4 %C( -M !:2P 6\X %U1 !>U 8%< &': !C70 9. &9C !GY@ :6D -M &KL !L;P ;?( &]U !P^ XT 'T0 !^DP @!8 (&9 "#' A)D (8< "'GP B2( (JC ", -M) C:< (\J "0K0 DC ).S "5-@ EK4 )@U "9LP FS( )RS -M ">- G[, *$N "BIP I"@ *6E "G)@ J*( Q8 -VP #UX -M !#? 27 $]@ !56 6UP &%D !G: ;70 '. !Y@ ?XP -M(68 "+H D:P )>H "=J H[0 *G "OS M=@ +O@ #![ Q -M_@ ,X$ #4$ VAP . D #F, [#P /)$ #X4 _EP 01H $*= -M !$( 1:, $H &MM !L\ ;G, &_V !Q>0 LP H#0 *&L "C* I*< *8F "GI -MJ2$ S9 .7 #]\ !%> 2VP %%< !76 76 &-D !I; ; -MW@ '5\ ![A @9 (>< "-I D[ )FD "?K I;@ *O$ "QT -M M]P +WD ##\ R?P - ( #6% W" .(H #H- [D /1( -M #Z5 ! & 09L $,> !$H0 1B0 $>G !)*@ 2JT $PP !-L@ -M3S4 %"X !2.P 4[X %5! !6Q 6$< %G* !;30 7- %Y3 !? -MU@ 85D &+< !D7P 9>( &=E !HZ :FL &ON !M<0 ;O0 '!W -M !Q^@ 8 'F) ![# ?(\ 'X2 !_E0 @1@ -M (*; "$&@ A9L (<> "(H0 BB0 (NC "-)@ CJD ) L "1KP -MDS( )2U "6. E[< )DW ":M0 G#0 )VU "?- H+4 *(K "C -MJ0 I28 *:G "H(P J:( " @0 ($ !_ ?P 'X " -M @0 ( "! @0 ($ "! @0 ($ " @0 '\ -M " @0 ($ "! @0 ( "! @0 ($ "! @0 -M ( "! @0 ($ "! @0 ($ "! @0 ($ "! -M at 0 ($ "! @ ($ "! @0 ($ "! @0 ($ "! -M @0 ($ "! @0 ($ "! @0 ($ "! @0 ($ -M "! @0 ($ "! @0 ($ "! @0 ($ "! @0 -M ($ "! @0 ($ "! ?P ($ "! @0 ($ "! -M at 0 ($ "! @0 ($ "! @0 ($ "! @0 ($ "! -M ?P ($ !^ @0 '\ "! ?@ '\ "! @0 ($ -M !_ ?P '\ " @0 ( "! @0 '\ "! @0 -M ($ "! @0 '\ "! @0 ($ "! @0 ($ "! -M at 0 ($ "! @0 ($ "! @0 ($ "! @0 ($ "! -M @0 ($ "! @0 ($ "! @0 ($ "! @0 ($ -M "! @0 ($ "! @0 ($ "! @0 ($ "! @0 -M ($ "! @0 ($ "! @0 ($ "! @0 ($ "! -M at 0 ($ "! @0 ($ "! @0 ($ "! ?P ($ "! -M @0 ($ !_ @0 ($ "! @0 ($ "! @0 ($ -M "! @0 ($ "! @0 ($ !_ @0 '\ "! ?P -M ($ "! @0 ($ !_ ?P '\ " @0 ( "! -M at 0 ( "! @0 ($ "! ?P ($ "! @0 ($ "! -M @0 ($ "! @0 ($ "! @0 ($ "! @ ($ -M "! @0 ($ "! @0 ($ "! @0 ($ "! @0 -M ($ "! @0 ($ "! @0 ($ "! @0 ($ "! -M at 0 ($ "! @0 ($ "! @0 ($ "! @0 ($ "! -M @0 ($ "! @0 ($ "! @0 ($ "! @0 ($ -M "! ?P ($ "! @0 '\ "! @0 ($ "! @0 -M ($ "! ?0 'X !\ ?0 '\ !_ ?P 'D !\ -M?P '\ !_ ?P ('J^!0C'!P6&1T7&!08%A<6'!\;&A48-CU*3%(A -M)B1,2D4Z14]2'!XM6UQ<8V,9'BA>75Y>&R0<455/4Q\B2#A$*B8I7%96?'U@ -M5EQ:6U=43TQ/4$Y.55%.3%)03DM,2DQ.34Q(3$A(1$A(00-% T&+/D 6)A at U -M&"@5$Q4!% $6 .WY$QL4%A(7&A<5$A04%1 3$Q<:$QDW.D1)3QD<'$9$0C=" -M3$\2%"565U=>7A$6(5A87%L5'!936E91%AI&/DHG'B-;65A\?E]45U544$U( -M14E)1T=/2D=%2TE'1$1"14E(1T-'0T(^0D,\0#] SR+.ST3(Q4R%242$!(! -M$0$3 .W_(2D;&Q<<(AX=%QD6%Q,7&ATA%1PZ/$5)3QTC(DE'1#E$3E$9&RE4 -M555<7!4:(EE56%D8(!=17%=3&AY(/4DI(B1:6UZ!@5Y05%-23DM&0T1(2$9* -M24A#24A&0T) 0T9%1$!$04,_0T$Y.T ^ SJ+.S\5)1'1Q!21H>'1@<'R B)"@9&!U+35!15!<9+VE545$<(QA86%M4 -M&QM86ULE(1Q?1RTB*%)YD6]74E%03DE(1$5&1T9$041!0$!!1$$^0D%$04$] -M0$ ^/SXY/3PZ/3(3$_3!L=)DY13$\<)AU64DY6(!]65%(E -M(2!A8F8<)UE-3U10=UU76%976E984U!03D]034=)1$Q(25)&2$A'2T5%1D4] -M-3 J*R at J(R,G("P8$QF!75DQ+2D=.2D='149'1#Y .T- 04H^/S\^0CX^/SXZ,BTG*R at J(R4I(BX9 -M%!@!$P$8 (7Q'AP:%P44C!,6%182&1\7$1(2$P,4XA4:(1H:'1D6%!03%QL? -M'1L?(QT:'"%(3$I(&B$>4U=45QT at 95]C0QXB:6ML("I56E at C(UA8:96"55M: -M65=44E102TU-3$I*1DA(245&1D=$0T0_,RHK*"@I)R0E)B$A0> -M2T]23Q at 7&%9:6544&5]>8CP7'6)B81(2$>,@$? 1$ A?LF&Q<8!16!% ,7[148-!H5%!$2$0\-$!\;%A43%!(3 -M$A,1%Q at 9&2U%/188*5)-45(G(!U;8UUG&1I:8FA%%1I?9&(2&V%>81\ -M*%I@=F165UI13$I%2$5%0T5"/#U!/3X\/#@Z+"DN*BHG*24H)28G(B4F(S/RXD*CA )")? -M?91H6UU74P-.BTQ(2DA'0T$W,BTL RN%*"DH*B<#)@4D at 2(!)@$0 )[P%"DG -M%P\0#Q 0#Q(/$A,1#!$0$1 0#P\0#Q,;$Q ##[L.#PX2%Q0=#T90(A$3+%10 -M65TM&!AC86%B%A1?86%6&A=D9%X7&DTS)QH80"L<)#T^'A]E at Y5E65A02@-' -MED9#14-"0#XT+RHI*"@I)B_!XQ+!P4%105%107 -M$Q<8&!,7%1$2$A$1$ T5(!42 Q'4$!$0$1 at 8(1%*52,3%2U3359>,!P77F)B -M8Q at 77F!@5!L8965?&1Q-,2<;&4$M("= 0B$?9(*69U553DI(1D5!/D ^/3X^ -M-"\L*RHJ*R at I*"DF)24F!22!(@$F 1( EOD;&Q<8%AL8%144%Q4;$QHE(RXA -M%!0#$X42&&P6$P,2Q1$2$1Q3.!LS1$%+&QPY.D)8630C'VQN*%YPG71>7%=.2T!!-S$L+@,L at 2L#*8DH -M*RHJ)R>JEW6U1.1#TX.2\I*R\M+2LH R:))2 at G)R0D)2 at G!"6!* $B -M 2T ]?,F&QM[%1D8%Q<>)4.%A")L6E Z,"TI'Q at 7&!$3%!(2$1(2$11 &QLY -M0T=4)3-"/4I&0CDC'UY95%T?1#A;5EDC'UU;8!T?7U]A'AQ#-QP at 9FX>(G(@ -M)%X)"-"%Q9$-!0:9F at 5&VP:(54@)$U6 -M>X! ,B0>&A$B)BDP-#D[/#LZ.#&!=%-A@=:VT9'&\=(U]96MA-RDF)"4B'AD7$1(2$2$])$M60%59(BDU-D])130>'T1"(2$6 -M*R<=4U0D(EU661P>8&]G'B$_+!TA/R >'38>'6 at K*4]$'AQ%8(=92AI13D1( -M1DI-2$E'0D1 0$(T+2PI*0,H 1T!% "@]"(7%Y :$Q,2$A,4/)&8Q+FSM+EC -M:F V*28C)" ;%A0##I at -'3DF5V%/9&0>(S,[6E=,-A88/SP;&PT#(H1<41 at 9 -M URS&1AB<607&T$I%1D]&A46,!@::1\=2T8B($IEA59'%$Q)/T-!14A#1$ [ -M/3L]/S$L*B:UU\?BTH-SYE85<\&A<\/1X<#R8M)5I3&QE95UH9&5YO -M9!@&1F/CMK5T\K 5T)_7E _,"LU,RLF&!(0 -M%AD\2%5C5DY-3U\P/5),140G&U(<%1P>'2$J3$LG(6UL9B F3#TS'QL]$AT? -M'4P;&TP;)F8Q(VA@)D8$Q,4&!,=%AN5E-G3T,B_5D*!7U-",RX[-BTC&1,,$!E#4V-R -M95Q;3E:&!@9'!4:&!^:F=;/T,W+8D=_8E-",RXX-"LC'!81%2!%5FV &AD8'TA*4D8@%UYB:!T;0C at M&!8\#108$448%$P:(V8L'VA= -M(T8A)%!%1A5B4$Q)248_0$TU,"TK*RHI)P,I at RLI*@$; 1D ^_(\(8Y0%Q at 6 -M'Q at A%AV+E-R8U2Q\H1U=+4551 -M2F,3%!T9'RPF6&PA)E]GAQ<<@WYF'QE'$AX>)%L6)UL8+F7WU83TU224=)141%0$5$0$)!0D$_-@$C 1@ ^_4^'XI-%!43&Q0@&!^1 -MF\_+R$%4<(6,;%DH<7WU8 -M3$I/1D)$0#] .T _/3\^/SX\,P$@ 18 ^_,\(8]/%A<5(QD=%AN0HM76U=/- -MGA09&Q at 9'A8E,D!",BXA$2!$1%QZ4T)36AXC4FUE:V523FH5%AH6*EA-:&X> -M(%-AB107 at G]C&!1.%AD8&%03(%D3*&0T'V=A$U<>(V4<%D<@9()=3DI/1D!" -M/CT^.3X]/3\^/SX\,P$@ 1H ]? /3\*Q@;+1 at 6%!X4%2D>CY[3T]73RZ,8&1@<&AP7$1T;)!Q )14>259I -M>%A%4F(:&')E;6IS56E:$Q45'T5;2I:&)"EB?(D7&WMO8AH714\;%1HY&11' -M#QQ0-A]A6!-8'A\[&!06&1(J2E)T7%A+1T9"/SLX,P0N at RLK+@$K 2 ^_4J -M''^5&B!G&!<5&!(3(1H>)SLL+"DV1U!&-B](31(3 -M8UAA7&I65&89%A,9.2TE=84K95943 at PD/TTE(QU 3AP<-%T>&TD;*$LT(DY2 -M%UD?%Q 8%1H<%Q\A'2$@4W1;4U!-24A)2$E(2$1#0 $\ 14 ^_0G&7Z4%QUE -M;!4G%"B+E,W1S-# FA<8$A84%Q$-&QD at +4$P,"L\45Y00#I34A 0:6)N:W=< -M7&P6$! 904,W?8*#PK*R]!5VAB4$5=7Q40;FQ[>81C8'$>%1(@ -M5&%4D(\K8%!03 %A$:&"$;$QL= -M'" ?4F]534I#/SX_0$-"0CT].@$V 14 ^_4U*6J0'2R4>QL?'1^0CL7/S\;' -ME!<;%1<8&A,3&QP<)CPO*"TD/4EJ.#$[5A4M/5AC9W!>5V at T'QLB'BP>JE\O -M:6UA7#]#-%46$"$TB",F.V49($PC("'B4E -M1W5B55%*2$5#0C8V.0$T 1H ^_(O(VJ2&2B5?Q<9&QZ0E&A0;&R4E1W5?3DI#03X\.S$Q -M- $O 1D ^_-(,!IE(R4=&18?&BZ(CL7+SL[%ER$;%A<9&A,2&AP:)CHO)RXC -M-#D]$AP9)#A-65%;8&AG6& P(2(B&!H5PXH87&=<86M?/T\6$A$B$1&Q45$0\4$Q42$Q$3%A <$1\V56=,3$9#0$1!/0% 3D ^_A'*Q]O -M)" @(14:'RZ-GL_2U]S6H"0=%A<9&A,2&AP:)S,T12:&9Q -M>H5Y9FPU("(H+48XU)0>76%:7VE=/4H1#Q8W3" 8-%Q9,% 2(!<6&Q8@%204 -M'AH:%A07%A at 5%A06&10@%2,U4V5*2D1!/D(_.P$^ 3D KO8H)HEM*1FUL1L= -M%Q6-CL#/U,[!EQP5%189'!,3&AL;(S at S*"\D0#M534 Q+B4$&U%Q<5$XV5Q<_4 -MTL:7&A,3%!<:$1$8&1DI.C,L-2E&0UE1138L(A86%QLE=EM<9CT:%S(<,R6] -M>1DJ.DLJ8GX2M1T6&B:X6A at W.APJ010C$0HP%! <%1 .$Q01$ \7$ \6#A<0 -M$A,1$ATJ*U!*2$=&04!# 40!0@#[^RRM;=W-*@'Q<5 -M%AD<$Q,:&QLD-2XF-"Q+26-92CDP)!@8&Q\L@&=B:4 >&30G2CG*@R L,T at I -M87T1LQL6'"F]8!LR.!\H0!'!84$!4=$Q<9,!HE,C,D/"AO8G]L -M;7!UR4E)B H&6@@G!<:'2/$:",7%Q(8*QT@ -M$Q8U#18Q.!H;%QH6%187%!81$185%AL9&1$3."LG'"6'C+W,R<[!FR,4%A07%A45&",;)CPR)S at M8&I33EU,/D!/:F9O -ME4]$'1HH4S)NM24 at 0$M32TZW(+,>(QP:&Z A'.?3TD?'",^%D^.'"4\ -M2%9-3+(8M!X?'B&Y6!82$A 6'Q45%!,1$Q(W,AT:$@,7A0\@%Q : Q2/$Q,4 -M$Q0041]N9H543$5( 4H!1P#J[#0K12LT'519)B(F,H>/O<_+SKFD2Q,5%!<6 -M%146'AHD.S,F-RDR-S)J=GV!GHR,D(U>@F(P045E9H9QQ."RA'M!("]&>L(C -MOAP>'!*FAA44%141%104$A,6%!4A%Q44$AL:&1,>%1L5%008C1H>&1 at R&IR# -M5UU>7$@!3P%3 );P-"I'+3 745LB'20SCIC"TS\C,TAZP!^[&AT:&*F -M#Q$2$@X2$1$/$!,1$AL/#0P/&!<6$!L2& \/ Q*.$Q49$A(P'9R$7%U<6D8! -M30%0 /O_.RE--38:66,G&R8VCYC$V=?:Q:I/%183%Q85%18>&B(X,",U%PL, -M""L>*2<^+#)%3DR7=S at _2&IJ=3M]H'AUA$,;+4-UN!6]'!H>%;>;%!$4%! 4 -M$Q,1$A43%!X3$1 1&AD8$AT4&A(2%143$1,7$1,R'Z&/:&9 at 7DH!40%2 -/T -M*24=)$HF(2 <'QQR>X^USM+-N:1#%!88&A<8%Q<;'2$T-B Q'R(?*%557'>- -M at F]Y;XF!5S\R*UIZ;9.VV[FK+#98?6HMIFC#$Q0<&JE\%1<5%0,4I1,3%!,4 -M&TH6$1,3(2,D&$45$1 at 6'BLT.5!D&QT at 0:JH:F6"9V4!5P%" -/T)R >)D8@ -M'B(8&AIS at IBZT-/.NJ9$$A(5&!46%149&R,V."(V(AP3$3P:6F+#5:@&LLI&/ $1,:(:]\$102$@,1I1 0$1 1&$<3#A 0 -M'B A%4(2#A .%B,N,TA:#A$8/:BJ;V6"9V4!5P$^ -/_+!XA+DPC)BH=&!QV -M at YB\V-[9Q:I'%A<7&A<8%Q<;'1\Q,QTX)!\6%# ?("\[+1XL+GR>;$4N*E^! -M75EOGX.A,S15?FPIH%["$Q >([B+%Q84% ,3I1(2$Q(3&DD5$!(2("(C%T04 -M$!02&BVR+<&P!7 %# -/Z+3LZ(%4ADZH]%1H:=XNUS\_+ -MMJ<@&!04&1<8%Q<;'R$T.Q\Z)AX<+"-2E[R@@V5Q9'EV6D5&,HAV)G'"V%@,3I1(2$Q,.'%5-%1,0$1L8$@D3&4I&11 at P -M.H-1;&M[;Z"50E7+44,!%0$: -/Y)B\T(E$;D:PY$!@;?I.ZT=#,MZDA%A 1 -M%Q46%149'2,W/2$X(1T6&B)8C[&8>%=E1WN$94=%-H]W&5JPQ;>Y-3YIR8H8 -MCF.D$S,BAE\=%Q0;$P,0I0\/$! +&4]'$A -#A at 5#P80%4(].@\I-7Y'75IN -M:)Z71U/*4T,!%0$6 -/_)RHU*%<>EK0^#AH>@)6\U]O7PJTD&A43&1<8%Q<; -M'Q\O.!PT'QH1%Q=#>99\7D-(,GF6<$M",8YZ'$&!F8RJ.#EDS8\)>KT-#+J*D6%Q41%0\2$A04.",X.1TT(A\:&QY9 -MF*.9;6)O0GUU94DE)91L+BNER\S 1R=DR)09NTRW&V,4'2$4#Q8@&Q /$!01 -M#P\+&3L2#Q,0%B(5%A44%1LTFS'7 at 8)"L7$A<;&!,6%!$2$1$0'CPE&B03&BT> -M%Q5+)A84$"(<("@6;2J5?3P=/C##,TD!'P$; -?T-!&!XY.QPV(B8I)AL[B:R6AFUT07Y_;4(J)9 C7XV3 -MD7VP52H8RIL0#+$-4@!&P$8 )O_.1!>&5=)'F5=T at I(Y\9-EME75"J7RP4 -MT* >L$*R&G,5'B44$Q8:%Q(5$Q #$:$/&Q\4'242&2P=%Q5-*1H6$B$1&"P? -M9!N, at 44A/##/,$@9>+)B&%K>WJ!8&XL+X-@,L#-M\"\8R0PQYHLJ3&K -M%VHQ12D9%!07$Q0;& 02H1$?01\+)1L:)2$=(F at C'R,=,#I%'2=J#I\K'!8_ -M1;5*, $8 1D ^_,@(1Q!:0TF*B$3%U9 at FJ.%G9!Y>!04$@\4$A42%"$:&S8\ -M'#LB,"PG&QY;9XJ.:G!+?(-K<"LRCF(GJ+&6HK-B(C+)FBJF+*T88R0Y(A,1 -M$100$1 at 5#P\0$ X9(PT+(Q47(AX;(&8A#Q at 8)28](B]K#:(P'!A#2KE,+P$4 -M 18 ^_\H)"$_=! E-2<4&UMGH*6 G))V>!<8%Q$6%!<5%B,;'" -M%2)45'1[8%DN=YEU=BHPCVH,<8-B>;-N)"[/GRRF*K$;8B<\(101$Q82$QH7 -M$1$2$A <' H0*!@9)" =(FHF$Q at 5&AXY)S5L#*0U(18^3,5'+@$9 1@ ^^XB -M%1H:D2LJ)R<8(GE0DXUND'=N;1 8&!<9&1H:%R 5&3 W&$ <$5Y<)ALSG8MU -M77!Z?H)-?B$O at HUBJ<#HD[UW(3_'H3$R+U892!4B(AP4&!42%R 7$A(3$A,8 -M0S 2%2XJ,R\Q)AP_/F,U8,&5P^$YTD%1=,3Z(=&0$F 2X V/DG%AX=FB at H,2H5(GY; -MHY1ND7IN)QGBA\OAZE0 -M9'F;6[R"'SO/J#$O*EP=0PD=(!D0%101%A\6$1$#$J 5'1$1%RDG,"XQ)AY" -M(DH4(TH+(6%#&*(J&A5)4*P9& $H 3 ^_DG%QYTF!4OLYD9'A)!EGYF at VIE -M91<=&Q@;'AP8&AH8&2\[&3P='S!L)!XTIZ1Y3V]\BW)6C2,=AI*WO-CB2(.3 -M(5#"J3H\3T,>@!H<'Q87&1D=0"(<(A$6$Q(9/58V(6='+R%^3A at F)#% @Z V -M%B8=%J4N(Q1=&"P7%@$K 1@ ^_HC$1UWEQ,MM9<3&Q))G8-OC71O;147&!89 -M'!H6&!@6&"\[&3 F%BDV%!\MI)UT4FI5>8!@DB(;BIVJHL3-.X.8'DK IC@[ -M3D,=?AD9'!,4%A8:/1\9'PX.#P\0(BH<&$P^)QJ!3Q8B$B,U;8$D%BT?%J9=IBI*HB='DO%KCHX2SX:@A at 9 -M'!,4%A8:/1\9'PX4%!$2&"(6&%1 *QN#4AHG#1PR9W8?'3 at C':TK'Q1B&S,; -M%0$I 1@ ^_<_)!$1,='(U!D'A>95]@8!@<%Q8:'185$AD7&2T]&3P> -M&1EA)Q\=2J1\5FAW?6UNGB(?A96O:>3<)W][)&"]NS$_/50RH@*A(. -M#PP1(24G-51^$!(-314;0E1%J"$?C:B1);.U$XJ#'EF_O2PT-$PDE!D6&A 8%1X>0RH@*A(4% X3%1H< -M,F* #1404!D at 0U9CIFX6&3$?&ZD4$P]BFST=&P$M 1H F?=(*B PMADGJ;<< -M$AD;CWDX.R\W6A at 7%1,#%=\3%!D9&"@Z%S at A(BUE1C(^,J2I=6-YD'Z!JAP> -MB(QFB.6C7H&4+SJPP6EG>XF1HQ46'1,:$1D@(2(<'!(5$A$;-E!*-WR%&B<; -M428O)1LJ=S59%!(4$HT8&!=8FS,?'0%# 8, F?A$)!\TMAXF/H!,3&A 7#A8='A\9&0\-#@X2'B,E&4]Y&!H94B0K(Q at E -M<#96#A 2$H\2$!5>GC(<&P%* 80 F?],)1XOOQDDL[H;$1X?H8 T.2TU71 at 4 -M%!,#%=\3%!D9%B$Q$BTC(Q\?-C<_,YF9;D\S=(B&K!L>C9U(1Z]T1(29)S"P -MPV1<=(21J!@5&A 7#A8='A\9&0\3$Q 4%1D;%&5^$!H=52 at P)R(R>4%@$106 -M&945%!==GC$<'0%+ 8< GO(^(QIWM1H6'Q at 9(H8DC7PT*QLO41 at 7%144$Q05 -M% ,9VBAI1K at X!80BF>QX[%NU[#0LM< -MDADH'!8:$R$F*QP>&!,4$A,A,$M!.WE]-BMY0Q8L2$0_AE2=&Q at 3%X\.&!9@ -M9C%1\V'RHP+39P3U%0.T]HLATK1<95545&QTBB8(L)B,N31H7% ,7 Q3=%AD7(S(2,B 3+&4S&"4K'3R$ -M9(6+EGVR)!R!E9.KLF5*@J38F*N\N->TPFZ!+1T?%1D/7%4F(24>%!03$A<^ -M44(\.G)>:HY+%C C,CA_2Z 9&1 at 6G1<6&'B1-B07 4,!O "8]D\Z)2"N%156 -M61<<'"F4B"PF)C)6&1$1 Q3@$1(2%!<5(C,2-1$8(3 A'RHZ(D>(0E= 3F>N -M'QF0G(ZDHUA&AJ75F*J_N=.VPFZ"+AH<$A8.6U0E'B(;$1 /#Q0F(QT@'F9> -M;9--$B@=*S%Y2Z 7%A(4GQ,3&8&6."(8 4T!O0"8_U4U*"2Q&1IA8QL=*BB5 -MAR4?'BI*&!83 Q;@$Q04%AD7'R<++0\;%QD>(2P\)TJ"(RP<+4G &B.0GHR9 -MET -M,CI^5*D<&!,9I1 at 5&H&9/"89 5,!P "8\'8A$8*F'!QH9!4=*ADS/BTG&RI' -M'1H6 QG@%185%AD5(BX7,"43*6A(0R$C,RLZ8H61DW>I&AQ^E&ZXU28\HZ32 -M at I_ LM6ZQ'F%'1P:%!@6$$$@*"8A%103$!(]44 T.7II9X),(T!+$3B-6ID< -M%Q at 9HC,;)79U,"$4 4$!Q "8]'8:#H2G&AAI9A4;)R ]0BTF'2Y0'!03 Q;@ -M$A03%!<3(2\7,Q88'C$S1B0K,#,]0%=&2U^E&A>0H'"URQX[J*3/@I[%M-*^ -MQGF&'AD7$145#T ?)2,>$A /#0\E(1X;(&YI:H=.'SA%"C&'6ID:%!(7I"\8 -M)G]Z-B8: 4P!P0"8_WT9$(BJ'AUT;AH=+Q*D2W$R*-HWC!TAPXM:G9?9O*NMS(SGZ)'Q<5 -M$1<4#C\>)R4@%!84#P\<&Q,6+VED:(E2)#Q&$3J,8Z(?%A,[M85M+!\;%QD/$Q,D -M'QT:%1,3$18K13$M8G5I57Y+&5:$?WZW?)T9'2$9I84\+7V5/1,5 2'>Q?)T7&AL7IX$Y+H::11 at 8 2T!N #N_Z$:'C>V -M%A\>%1<4=QR*>34Y.3M"$AD5%187%!87%AD8'2(@+!,<"QH90$ K'S8W'RD: -M*SFQ%B:*I6CJZ#EYU:78C7S(O>#*OXIQ+AH6%!@/$Q,D'AP9%!44$!,8'Q$: -M6&1D5H51&E)_?X"VA:8$'(FMACLOAIU)&AH!- &^ /OZL"(B'XD-%*2G%1 at 8 -M(I-C045%2$85'!09&A at 5&18<%1 at A,2DL+!DA=#@E*C0Y*S!3A(Z5=)@?%W26 -M5]C=*+NCH=&+:LVUU[ZRBEPQ'QT7&1,3%"8A'1<4$Q,4%1LN("(M-3E334X8 -M5#$C+&]$I146%!.G>C at MC99#&R,!(P&X /OZL2(@'XH+$*BK%QD5))9B0D9) -M34\4%A$6%Q42%Q0:$Q8A,BDL'1L5.Q\F+3LX,S8Q5D1-49 at B%'N:5-?<*L&I -MH&A01#P\1$AH=$1$:+3M64E 43BL=)6E$ -MI1,3#0^G>#8PEIQ*'B$!(P&U /O_O"&A01%!03$A<:#1 at E)S94550942XB+FY-KA at 5#A2L -M?#@PEJ%,'B,!* &W /OMH20=@+$0&18D%QIF')X^/T)$2$P6&1H:'Q84%Q4= -M&Q@@,"0N)R I=4$@1BY,*!U,='V4;ZL@&W&=.]O='97'MM":7LBPT+BOI$T= -M)!L8&A,6%"LN(!L8)C= 32D;,692.TU;;&@=3B(2+FY3I!<8&AXK&1H9G9Q! -M/4,!1 %S /OQGAX:@+$.%A8D%1=B')T]/T)&3%,5$Q87'!,1%!(:&!4>+R(J -M'1X=.B8E43M9-" O2C9+/Z\8(72C/]O<()?'N<^97,BRTKJSFTT@'185& T0 -M$2DK&Q83)38_3"88,6A4/E)@KR(I_6N=N85L^ZVL*[I5(B'A07'! 3$RLK&101 -M)#4^2R at 6+&90/%=L?W(>4"$0+&Q -M(' 7$J.K%1@<)JV\@55-2TD7%A,;%184%Q4<'1LA+BPK+",Q>SXA,#U+1B%) -M=7V0:9 at A&U"1,M_:*\_0=LZ?2\^HT+>9J"\7/2,8-S$8;$$F-*(C7DE /EA+ -M5XBAL+.NISTA5WI[@;&?IA<8(" S+BTB)1H4,#,!/ $O /OPI1L;(' 5#Z.K -M$Q4:*:Z\?%%+2T\5$! 8$A,1%!(9&A@?+2HI)24F0B0C-D563R,L2S9'.9P9 -M(5.7-M_9+M'0>GR\:.",:.B\6;40G-J0E84Q#05M.7(VEM+BU -MM$,:3W)Q=Z>?IA45&14B%Q<0%0P,,3X!2 $V /O_L1X;)749$:JR%Q,>(;'! -M=TE#0DH7$Q(:%!43%!(9&A@;("(C&B,E)A\G-4=632$5( DF'+$5)E.<0.[O -M,-G?>]N?1=.MU;RCJ30<-1X6.#,:<$8H-*(C7TI!/UE.89FWR-'1S50C57AX -M?JZHKQH7%Q0C&AH3&100-#\!2P$X /OOKA@:<#@4&1\4&1I(.+G;TM3(P)0= -M&!89%!H6$Q4>'!@?+BTL+R5-' B03) /D1(KZFHH):LHC,=2!4=(T UFA at 8 -M%QP9)3,R+R at T,"T!*P%3 /OSJQ(7<#@2%A\4%Q=)/+O;T=#(PYH;$A,6$1<3 -M$!(;&14=+2LK*BLN02L?)CU17ADD1#-).Z8D($N<,-;:--#/EL^A3,FFSKJ\ -MLRTP1IN6.Z4OK#Z:.G8H23I(1DQ0M[*QJ:&XK#<90A,;(3XWFA85$1,,$AD8 -M&!(:(S(!,@%5 /O_MQ47=3T6&"8;&Q5*-,/JX.+9TY\?%1,8$QD5$! 9%Q49 -M(",H'24L)"4C)#]171 at .&08H'KL@)4NA.N7P-MC>FMZE2M"LU,#$O3(R2)N8 -M/:DSKT"<.74G139$0D94RLK)P[S5OT,>1QXR"JZD58?C:9 -M**(D5SL^/%.2II^IJ:2G*SP@*4-%34U&1A<8%!@>'BHK+S0\+!L!(P&' /OV -MM!X4&1\=$RDX&AI&.+GAD&@+ZDK8$1' -M15^>KZJRLK"S+SH=*DE+4U-(1A45$@X0%1,1%1L:&!P!) &# /O_P1\2'20A -M%31#'QI$,,/QY^'=V9XC%A]>P2MNZRL7&R2S >K$]BDYEC$2A+JHL7D!#05BER<7* -MRL?*.SX?+4A*4E),2QD5%Q86%Q85%QHA'AT!)0&( /ORMB8A/B,6&WZ-&B$_ -M-;76Z<[7TQC6$RWN9:FR,&]%!Q=)#\O/CH] -M8&!+$ \4%Q$3%!(U,D8!10'( /O_S2 60R46&HR:(2 Z-;_P[>/:X;(_+RXM -M+2XO+2XT,BXO)B =(1LP)2@?*2E*.C87'Q >*I]#)RN?,^OO*\_DO,FW3MNT -MR=;0S2C)T\$YH2NT0XZ at 7:Q"7TE at 54G#U*R_X=K3&Q]?)CLL.SZ3]&TL\/(QB7$S%,XO2=] -M/+Q8GH]M1%5-2&&XT\?*U\,6$!0B+1,Q/Q8A4W"%'10?&AD0%B4P)2)[(K'B2<,>[Q.62U^L+Y8XLSBC2S)-24*^ -MS\BZDS\6&!@5+!(;)188*$N9/\R_V#P_0VX\*2H!+P'( /OOM#PH%A<3$YVG -M%!8J-[#-T89E7$\V.C8S-C(N,2TM+AXC)2 at Q0!<=.RT9'ALW2$<9+3= *50E -M(!HB)MS<0V;)LJV^3LJSI<6EO"VOT"B<5&JV.Z(_NC^I5#Y954W'U<^_ES\0 -M$A03+1,9(Q09*$F5"Z*SHQ$>)F,[)B,!+ '* /O^QCXD&!@5%:*O&18E-;7< -MX(]J74DK+BXJ*B8B)B(B(Q8;'2 O) PA("0:(Q\Y2DP5'!TI'UHH'QXD*.;O -M0VO8O[?$4=.]J,JQQ"VWWC.A5&K -IU!NT&N5#M64D[7].K6J4 at 3%1D7,!8= -M)Q@<+4Z;#Z>VKA0@*6(Z)B0!+ '2 /OM:!<;5D0:&Q0,%A<8*Z;+JS8T.3,] -M.SLQ\!W&[XUHZ,HI3.)-#AD6H._OXX8( \,'!\='2TT,S,H%1A/ -M.[90/T1Q9I'8WJDG*1(1*S(Q+RXR,3$J%1A.%:%FIQPC6S,Y("L! -M90'( .3T1BDE&QH>("$?'!HA&14KRE)!/STY-#$I)2,C)B$?(R8J+2TI92D8 -M3D4@(R8F)RTS-CE!.4YZJ[Z42MW6=-7(N7:Y(\!1.[]?N"FLRU(2$N-Q$:(BL@'A\B(R at P,C0\ -M/EB&M,&F1^3R>=K9T(+$)L)0-+]?O"N[WF$VR6<_PSFN;#IT:8!W="X@$Q$3 -M&!@7-SLT-AT15$S,M04HR/CUJG+W)T<_2ULR_(S"0 -M5=O1= -M1A,3&!,7%A0=/C9SC%U%E3Q)FBP!, &( .'F+BLK+38K.#U"2%M<9VY\S\8Y -M*2LR+2LH("D5)1$A(2,G*BT];R,F*3,A.#]LGK[*U]?3V-;))"N74]O4=H3C2[+KYW>7EV.CD5)!P@ R:7-1H at 1Q 0%1 4 -M$Q$:0B=>D6-%E#Q+D1P!*0&/ /OP0CG9)RB at 6.3L>M'8V2._3H.: -MF\MVP2JZX+#!:#RJ4S; ,L%Z>W]\/#0/(!LB*",7(QG_#*OV^W(+'.=TXVNGLP -MKDQV>7)Z=&8=3$L;&RD\4SBL]WRGZ.R&^_([O>?T\ZP7TQLTUX at 7=^ -M>VP?4%,A("X\4#0?&Q(<&QD:%A at 8%AA016"Y+IZ?(RB))P$G 30 ^^-M9V5: -M6U=85UQ64TL88<7-)QHD(ATL&BT?+AHO&24D*#$Z-4NM6H_?VLO:V-;8V]C7 -MA9=\TT=5+X]OW-)./\G,A+)VI*"ZUFAV-7&)::!@B%#8M -M3V=?12XI,AX;E9N>J:JRM;^]6F"O,)HP-'>4,@$E 34 ^_"=FIR4E)"/DX^, -MD'TO8\71)Q4?(!HI&"L=*Q:.Q,#6\GR2596YF=!T?%STS4V5B2RXI -M+1<9DIB;IJJRM;_.8%FS+9(L,G6)(@$> 3, ^__,RLO#QL+!P,#!OJE&8Q2 -M0MCFFLLJOXYWQEZ (K'@A*BU,C:]I".9<75K>2 =&3XP36=B1BDB*A@;FJ"C -MKK.[O,3$6UBK*Y8Q-G>)) $= 2T A^YA<4-=5EL#5_%210U35\#/,SA%*RLU -M+"X>,ADP&3DB("TR-C;.U]31U=;9V=/&WY5 CH&*S5HU]ULX?F<''5,$F -M/74U4S<,!Z#"N$<[3*4])J1J@'Y/*D!F7TTJ0RDR*A\@'"0RB8^1B8:"?7UW -M*&J[-I$7$(.!.@$R 58 ^_2;GH63D)61D8R1;!M38,?.,3) *2 at S*BP<,!8K -M$S,?'BLN,#3)S]?9VMG:W-?)XYDS5#-3PE 8>)>"T\D=E\#'6"E91A+SAA8E,R3"XR(QD;%Q\MEZ&CFY61C(R$*F&V,HX6$(5Z*@$I -M 4P ^^M2951=8F%>5FD@%2 H3+S6-2 B*2 K.B\=+QHV0S G+S$YR-+4VMK4 -MU]C7T:\<,6\ID8B(S%]G)Y"&ULU!P#F7"HO"@RO8^.B%Q103\^ -M,3=#/B(S+RXA)R6E923F:I=(6$IX1Z) $X 6X ^__%P,_"RCM]OCR\_?V[,8E+V80(20C -MO5]H'Z*0W=DZQ=[).AP>)R0<&2 8%W&+GG2KSBXOQY^;D5U..34Y*2\^/",N -M)RD=(1\K8G)M:&!85%!13V:O>(B&J8I_)0$X 6P ^^YDH)V=F9N$BV-:1$1'0DD\,"H"SK8*$)P$E 6P ^^EN;69I:%MI-T$4'8!\0,3<."4=,AHG(S%#+Q4N'VS2 -MW-S8W-C5UMG45B(?*AX:*QHH at I"(R(T@'W]_PL6UP+^_2RXG(QLD-AT;%RR\ -MM3)WB!T2'$Y586-?7EE&&QT]'!X[+3$T,34IS];5W=[AV]W;NFJPE8&[J&N# -M-0$P 2D ^_*HF::;FI"2'R(4&XF!2\G;-Q\7,!4E(S5),A at G%V7.WM_ -MW]C76B at G*"0A,"(=3$9-PI09&HF$PL2UPL3$3"PG(AHD-A at 9&3+!N3N$C2 4 -M'$!%2T=#1D(\&!8W%ADW*2HQ,#(ET]O:XN+EX.+BN6*KC7NUI6=W) $I 2< -M^__?Q-W'SL._0#$-'9F-3M;Q-" :+!,A'#!$,AHH&V[=]/GX__CX]_'Q;C$M -M+"TJ-2@<'2 at FO98D&(^'R]V\R-'962 at B'Q+>W=S at U7BTFG*QJ7]D- $X 8T ^_6EIJ2AE90-&"HI -M/$HT-<39.R at D,AHS/C(F*1AFM];7W=[>W]O/S]#4$0S%T'GU7&OE&RKHWU<)@$Q 8P ^__9S=K*Q;T?(# J/$\Y/=3M -M-B,D+18Q/RTB)QULQ.[Q]O/Q^.[YXE(=+!QK("DG,R<8/3,MQ)X=&8*'R=:\ -M:M',;28B-B9*.T<[(!_6QAH>,2H6+C$Y/3 F$3HN'2LL82PW("PD*R8MY^_R -M]?CV]OC_YG*MF7&PJ():'P$P 8L ^^MQVMC7 -MD8VPGV6KI7 =-@$W 9\ ^_"KHZ.GA1L3"1,S-"D7*[W;/B$?-TLT&24@?\/8 -MW=_=WM[BXL_%1$%%02"3,5T>,S L5EE-OK X%(1^O,:N>;V]0!4:)Q<8'!0? -M+S4Q.3D;+R$J/CXJ*$^5J7XZK3]"S30])#,M/1X6T-W;W-O=V=K9CH:KFV&G -MH6X2)@$N 9T ^_WASMW:K2 at 8$!@V.3$;,,OM.1P@,4'8/"T[)Q>?(%L7&R,2)RPQOJY &8& QM6Z@<;)1 \8(Q,4&!$>,3DV.#<< -M)B(=+3$E'D66KG'98]43H;(B0[4$.B -ML69^WJ=-MT,\QD%$(3L@*"TDS]/5X=S6U\C92XR at I4BBH'0(AQ6TVJBB8?'3$V*R8<&Y0W2S03)!XN0#NBHE=[X)D_ -MN#T^R#D_(34:(RHAT]C9Y.3=W,S70X6;HT:@GG,G* $L :4 ^_S=RL:N.1XK -M*!P?(!H=*<[S/SEA-APG+YBFT^_E\.WL\N*RN$;6-#0[.!^Q)4,Z'!8@%R^8%*PB"$<&2TR)R4>'YDX1B\7("$A,#FIH$U[YI(VPS at YS#(2$9&A\@=T/3>RHDABM27GQ.1VQ&3'MTQU\Y%6U- -M6[RN2H2'438U*RXF%QL?'80V.3$7#Q\P,[O:CE9^WDU+MTP[T#HZ,30S(KA[ -MR74O/]1XC&[41VU(FQ>8I6\Q.@$X :H ^_*CEUP;#A$1+ at T4$PT/*+O6HF49 -M(!0.%PT=&!P?)",<&1TB>471:R893A]B-'-5,&(P'SPZM6,X$G907\*O2(6# -M3#$P*2LC%AT=&X0S-"\3$ALF++?;?4QXVCT]NT8_TC,U+RTJ';1XSGTU1.&' -MFG?00&9#F166HVLB* $O :8 ^__9P'T=$109-! 6&!02*\7PJVLC)1D3'!(B -M'R,J-#@N)R(==4/66AH6)AIR'7-6(EPI"R(HN%TW%'129]&Z2HB(2BPM)2DA -M$QL?'XLS,2L8%" <(+WH?#QQWSUWH93+=^.J6C2/S9#F"*5EVHE(0$T :T ^^ .(B = -M'1 at 8%R$P.$!'5[33>3H9#Q$66FE;1EE4%!T1A:.SK*ND?!\CBR-(,2L5*SHL -M*3UYOX8K%F0?+G^:%R)\A1P:%A<4'UE7-7Y/?X4X(&9IKKEN0T2%VE)*LCY! -MR3M*0#LS,;.PQF [3==N?EO(041#D!Y<,FXQ,@$V ; ANT?'!H>&0,4\AXM -M-3M 4;G;?#87#P\46&570E50$!D-AZ6XL*2Q8B 96QM3&!P2'3,7%1M!J8(A -M$V4B-(6<%2> A1H7%!05)EU3,H!1 at H@\&V-IK+IW/D.(V#T[MCA#RS1#-S H -M+;.KTVY)6-QZCV/$.CP]CAQ:,&LF(P$S :H ^_\L'QTA'AD9%B O-SD_5L;N -MBD4I%A,87&M=2%M5%1X2C:V]N*7"4B,31AE>$QH2%BH5#A CHXHI%68B,XZB -M%RJ(C!\9%A08,658-(A5@(8W&&-NL+UW.SA\W#DQOC,^SS)"-RTE([RVX(A2 -M8O&/G&G4.#@^D"!>-&TF(0$S :\ ^^@8&Q<4%!(7.D!+1DE-2+G/=AP9%18M -M2EE*$B$P/QD3J*F$:&:89!H<4!U)*R@:(#(E'C%KJ)M"&D :&D"9&"H]+A$9 -M&BIF2:6^)%V3W'%1/5514%9"21U^VU5#LT\[R3)%23DT);6VSE0[0\]@<5C& -M2D9*?B$=(&HC)@%/ ;$ ^]<:$@X2$ X3-SU(0T)%0K_7=1 at 7$Q0K2%5&#ATL -M.Q4/K[&);&.F1AD7)AA8&!T8&"P6%APZEYL^%CP8'4B>%BM +P\5&RQI4JJZ -M(%^7WG-/.%I635)-2AQ^V4 TMTD]RRL^0"XL)+:RU%U&4=1L at F#"0SY$?!\; -M'F<8%P%, :T ^_ at 8%A at 4%1,8.3]*14!#1]#MA" <%Q at O3%M,%",Q0!H4NL6@ -M@&NX,Q at 2(Q5<&AT:%B,6%!@BE*1#'$$:&TJA&BQ ,A,:'BAI8K?")6>?XG%+ -M-E]B3UA-2QEUW3PJOT0XSRD]0"LF&<'"XW506^M_BV;403I%?B,?(FD8%0%, -M ;( ^_<5%1 at 5%!<8#31'4U)D3:_.?AL9%188% \,'AD3'Q,=,Z:IKKN.>58? -M2B%')B8:'3(B%"=!4;,F'149%A].(2$E0B%3:8@=;K#+(5*[W80Q(6%L01A. -M,#MSU5%)MDL\PRU#3C8^([6VR#TV/M%475/'344Y<",<'G:,/@$X :\ ^]@1 -M$0\2$!,2"3!$34=91[72?QD8$Q06$@L(&A4/&P\9/K2RMK^;6U ?)AY6&!T7 -M%"P6#1H:1KDH&1$6%293'R,I1"-1;(D?>+3''52]VGXJ&V5S/!)6,3AQUC\[ -MND4^PRM 1RLV(KFTSD,^2-1A/[W O,>J2%,:*QQ8'A\9%"43#!H, -M1L F'A86$B56(R$D/Q]3;HH=B\C6(UK#XH$H('%^.A=8-#IMV3HQPD YR"<^ -M1B at R%\/&UU)"4.QP=F'513DV;R4>('6 + $Q ; @NDB Q?V%A(6&"Q)/U16 -M/JM>/V19%D2B&"-'@FUE97X<))5X65J(92<<-"A;&BHA*38\(2 N*8,='B at Q -M'APK,D L*G>7AMH=3\/:+3RUVX<^)&A at 4&(\72&,VT]4K4Q!H3="3D0U++BY -MR#TS0--(4T7&3(EW6E09'FY]0@$V 6T ^]L8$!(5%! 4&BY%-TA)-:Q=0VI; -M$D">%!]#?FEA87H8*I^!8V"-4QD9(2%A$A\6'BHP%!,9(808&"4N&QTL,T$M -M+7V>B-4<7,C5*3RWV(0Z&V1E5F=!7R*)W4!&LD9 GCI&2#DJ*KFUS40[1]-2 -M9$K 1X1Q4E :&&IM*0$N 6P ^^TB#Q :&149(#)*.TM).;EK2V]?%T6C&25) -MA&]G9X >+ZF/:W&20"$9(R!F%A\6'B,2(@-#@V,"PR'QPH*& H'RX^.CD;/$ D'T!?P^ J*\#@(R^T -MV)I9'REE1UPE8%:0V5)4L$Q$S$%&4#\R+K>SQCTV1M-$347*6;YJIB5FHG"# -M1@$X 5\ ^]@C(#$S/4I003Y$.BDS-BO(GW!D&!L-:Q<[%5,0'V,7'F.)FGN< -M4!,;'ADC*RTK)2$G%! 7'5TB(C-#/SP>/T,B(41DR-LG-<;;'R^UU9=5&"AL -M3V,K9%F.VT-&M49#R4%&230J++BOQC\Y2-!'4T;"5+EDGB%GG&QS+0$P 6 -M^^(H'C,W04]51D%&/"HR.#+5J'9I'2 2/T,D'S]GS>HG/=?S)S2XX9=+%B=M2V(J7U&* -MX3\\ND% RSA!2C$H),.^ST,[3MA'4$G34;9II"9JH7%W+ $N 6$ ^]DV-#E' -M+" A*S(Y.38V02M<2&1Y&Q<<'!E:'!@<)20@#I D&!I!3B06)SEDP-TR-TU-1 at 4E* -MS#Y*1#<_,K6SSD!#5\=.65K%4KQKGB6BGFF!0P$\ 8@ ^]HX-3<_(1H?*S W -M.C,M.2A=3VY_&1,8&!56&!08(2 <#I$D&1E'0Q,5%"PS)!TA'!80$0\3&BTZ -M/3L[/2\<&!H:%QN'R-(U41#AD-)R3A%/2PW -M,+:OT4-'6LI175V_3;=EEB&CF&5Q*@$T 80 ^^<^-CD]'ALC,C4[.S,M-RIJ -M6G:&'A@='1M<'AH>)R8B%9XS)"=..!H4%RDQ)!TA'!00$Q,6%R@\/ST]/S$> -M&AP<%QB+T.DI-=3O+C&VZ9A8G!-.>U(2%*22X@'A\>'B8K/2$\ -MM-DH,+'@)BJLRJ%OKJ$L(RYMPFF1TU)2J4P_OSQ%1S,X+W>RQL7'P<*VP+7+ -M6ZU8CB2>FF1^00$] 7D ^] 61QY,+QT<&B8K,2]!.#C)O6YM%5M,$AP?2%1Z -M*A Q%Q@='1 I10H1$"0A'!<<&B(;%!,2%!E)2RT?'1H7%A\E.B$[N=4@,K;= -M(BJLRYUKHIDF'29FMEV+U49$KD4^O#8]/BLP+7FORLO-RW>+0V-'?4Z57BB6BFV5P)P$S -M 6X H>0K2#(X+" <%QHE,SPW-RQ;8SY&'Q<5$A8A%Q09$Q49$P,AC!(2'2(7 -M'QTC(QT<'P,FR" 9&ALN,QXH*RHP,#$K,B1-2,4M*IW@)2FSRJURBF2%7VQ1 -MI7:"SW1&ED9#O#1"4CDS,WS!BY:(EY^AEZ;#7[A;>2:6C5IZ10$] 6( H=0= -M.B F&Q46%1 at C,3PQ,"A=:4E+'1,1#A(=$Q 4#Q$5$0,?UQ 7$1,.$Q$7&A85 -M&!T;&Q40$14M,!LE*"@N+2\J+R)(2K\F*:+=(2>PT:)GAEQW4EQ*DFB TV<[ -MGC]!NB\[22XH+WR\DZ.6J+&RI;+'7+!5<2*9BUAK+ $T 5T H>$YZVV at PH$ [OBPY -M2RLE(X''I[VPP;CUUK*0$T 6@ ^^,A(R,K&A&QT@)"Y"9BJ::B20BF*$20$Y :@ ^]D8'!PC$A,=(!H8%A<@/""9KH8I -M& ZI%6HB53&.7'P.$"$B&@X2'C41#Q$4&!L<%QX=&! 0$1(3(R \/!HY2XED -M?4!AH]HE+L':'B2 at P*E,=82&>)"0C3R$T$U$7CLW99((3%28G'PX6$B at 2$A07&QX?&B ?&A(1$A,4(1XZ.A0W4)1K at D)CI>DK -M+LWR)BFPP+HS9F]N67)O8BB"V$XY7#HSSP\3-P\G@=*E? -M9B65C&5U+0$P :\ J><:)A\C)2HP%QL5$Q =0R(Z)A8@&AM+&!4:*!H8$!H6 -M$QHD'!P8*C$B R;/(R0E,#$S&A86%1L;*4,O+S%92!,;.C!&G- at H);;6*2^I -M>KMBC\IIA(?&;$]ZTE5#*E5 ,S%"44 W)Y'"IY>5E9N8EJ#!;[9.6R6+AF-U -M1P$[ :, J=P1'QL='R0J$QD3$1 7/!XR(!4;$Q='%!$6)!83#!82$1 at B&AD: -M&AT7 QO/&AL<)RLM%! 3$A02)$ L+"Y610\3,RQ&HM at F*KW3)2VD at K%4B+U7 -MD;)B B)"%!P7%ATG'QL>$A87 QO/ -M'!T>*2XP%Q,3$A44(CXJ*BY40Q<7-#%+J>LJ+T8"YN -MWDDM+$T[+R'A@<'B,: QV#*S$? Q?)%A07'"4: -M%EXP3"H at 0AL7'!9?O=HF(:;+*"RW=[52D<0]08',:$9";$LY&R0Z&BL\2#8U -M):*WFY23BXB%:'S28ZM%11M_95]=)P$] 9 G>4T+1XJ(R$N'QX8&B8E02<8 -M%Q84$!H9&1(:$QL; Q';%APC(QTC'"@>'1T<+#(@&!H:&1<7'28=%UXP3"X= -M.AD5'!-CQ.HJ)[+C,###;KL_D,(W.7K4:#P\=$PN$2(X%28Y23(T(*O&K*JH -MGY>7>XKG8ZM*2""":61=(P$\ 94 ^^'AT@)"8C("4\6BL1&UUW0!HE1B=> -MLM$O)H*Y+S&YAUQ[_&SM77U-G> -M7'$@.R!'&V$P. $Z 8( ^]$F-C,C%!0\)"PT4EDW,B4=(!T@)!PA(R0>(R$A -M'!\?%1TB'QH<'R$7'BD@&Q$2$A07&QT:%QPS5"@.&&!Z/Q<@0"9;LM4G(XNW -M*B_"=<%(CL4^.W[6;T([4E$\'1DV/C\_3C0K)&BPR,/*TMG:U]SB7FXA.1U$ -M&%H?)P$X 8 ^^0I,#8C$Q,[*RX_6EDT+28B)2(E+"0I*RDC*"8F(20D&B(G -M)"(C(1 at 0'BP@'A87%Q89'1\:%QPS5RH0&F!X/!4>0QE9Q?(W(XG+-3'.;\P[ -MD,HT+WG;;3(M5%(R&14R.CH]3# E(6N[T\W4W.7HY>KV7&PD.Q]&&EL>) $T -M 8( ^^\U7S\H.3 C6FZQP&Y83B<>&AP<(1HB)RH?(R8E(B at F+R0@'!\^/XR- -M*" >(1PA)B0I(RH[+TXE'Q00#!@[$!<0+C-C2,,N)#A:,S:U.\-4FLA95'-K -MCE,_/F(Z1#]%0T<\0SPW*26 at S]W:W.'>W-W:;2DPD24B(5E . $\ 4\ ^],M -M43 =*B$44&NPN650224>&AP<(1HB)RH?(R8E(B at F+R0@'"$_-6=L%!05%1 5 -M&A<<%ATR*$<>'!$-"1(X%!H7-3A?0<@G'T)9+S2^*\1#E\A*17-P?T! 154L -M0CU#04$Y0#0M)">+?X>;CX>+8:R8UDB,@'U(O)P$Z 4T ^^$K2"X:)AT0 -M5VF^Q&5.1BHE(2,C*"$I+C$F*BTJ)RTK-"DE(1],/$-4#1<7&!,8'1H?&2 T -M*4@?'A,/"Q="'A at 6-B%-/]&1,5'1H>&!,Q'A\<'!HE)Q$?)!M6LFDY -M)$>%?:XQ*+JZ/">^2LI%B<-,0S9*A2XR/TXE-"XS*RXQ+3$P)"@UNK2OJY^5 -ME8UX131.;ADE85&!0R'R >'APG*1,A)AQBPV,>"AYD6J,V -M+;;,1RG*1-4XB\A"-RI, at R0F04\;,"HO)RDO*RTJ(20UR,;!O:VAH9F32C93 -M;AHF8E at H) $T 4@ ^^,P*C8B$QTP1R_$TFE;3B4>*"(?)"(J'B8F(R(B)1<2 -M&AH8)AUS7$,Z*",F)2$R.BTA(1\@'1 at Z&A at A+25$<'JGIX^(1ELG)ZFZ62^X -M=M%:4!:T8I&@$Q 44 ^^,J'R4C -M&AXG'A>>UDY+2#$@'"0?(RPO)RLD("0G%!@9'!L;(B-G+Y#09R4L."8A'Q\= -M("(F'2([F*%.:$2+KF'GDETRFKHQ+J2O>2.PC -MST,\.BH@'"0?(RPO)RLD("0C$ ,5VA<8(B%M/9/%6QHA,B,>'" >'!P?&1LS -MD:%/7S>#JEK=@4DJEL L**FN8VK6TO4S8LZ.!Z*>28H+@%2 84 L=XH("$B&Q\H&QFEVD,\0#$G -M(RLF+#4X,#(K)RLK%14;'!P@*R-R1Z'28AD>,R4@'B,#(<R8E*P%3 84 ^]TP,",?)2 S.AHPV41.1C,?("8?,2TQ -M'1HBT(2,B'QHE(28KHJ=\7$!IKVCT3X_3$(F'AX;+A at 4%A4;)"0Q('5<(R F)B5??I,H -M'1L<'B =(1<;&4^,3B5)6,7AR2U1V-S8J58T=:Y%)&HFC2>F&F]-)TY at 3AH2 -M+ADP)$ ]+1Q,%R(Q-S8O*RL_J9?*=W.M6TG:T\E$.QY:+BM11P$[ <\ JM0J -M(!(8'AP?'BA>T#4P/CLF'AX;*A00$A(;)"0Q'7)9'QPC)B9A@),E&P,:SAP9 -M'1,7&E**2AY!7,+1MQQ#SMW6G$(C;K1 'FLKCB.M'FA&'T!/0 at T %PKJITH\=\-+(6PPFRFX*&E$&S=&/Q )(@XI&S$H)!E)%!LI -M+RXD(R8]OK/FDX[!:5[NY-=%.2-A*RE'- $T =( ^]A&)BA"15\O,RA#STA2 -M1D$?("DJ%QL?'!89'B$D at L-:)!\C*!]C:(5&'!\<(1\D)4>)D:@Q+X5 9+K> -MT;^SU]O4MU8D>:A6'QN(-2*4>3D\158C.)Z0<4HM/R0B%QXDJS,S/C4N)BHS -MK)?#=VZ?;'76S)^R*"XP*&8^20$[ =4 ^\0^(!\W.E0F*!] SS]#.3L<("DJ -M$Q49&!,9'B$HB,A>(AL@*")C9H5('1T<'1L@(DF.E[ Q*WXX9K;6U,.QT=O< -MM5 D>*U3'!R*.1Z9>3$T-44/'61..!L2*1$7$Q at AJ"XN.2XH(2'1L@ -M)2 at PD==J)R$H,21>8HI0(!\C)2$F*D^1G+0V,'\T9+ODX6M;(+DX["[ -M)R\T(%\L,@$P =, ^^)-/"T]*B8G&!LOV4I,0U G(1\D&" ?)2 B)"(F8-)Q -M(" E(B5B8QFX'B8@#AAG&IJWLZ\S(1]%2L?BV%589BP>&1TS@'D>(#Q#TC T0#DR*2PWJKW6 at W3/5R.%QS-R.S*OD$5H -M2@$T :D ^\E+,QXP'QL=$1,GU4 ]-DH>'",C%!P=(B B)"(J9M-O'1TE)"=? -M7A>\'B <#A1C'J"_N+(T'Q"!)24L*BM?61S()2,B -M%1EH**_!Q, U(QLW3'B-P16=30C*$'1L6&!X=%D$>'$M) -MT24S.CH[+3$>V7,-R at UO2I%,3&+?8EO/@%) << AL$U(!(7$P,7\@XD -MQ$Q 04LB'T$L38\M'Q\D)"$HBM1Y&QTD)RE at 6"*1'1<>C)M0(+*#I<\P(1LY -M/[_3UD\XP=C?PST:*C$]%1H>'!UR/E=%0A96#!0.$!$6!BL5'$-'T1\M,S(U -M*"X<>ZW4A6VV*1XEOR at _*3&5A(IF+0%! ;T ^\8R'!,;$Q8<'!(JT%- 05 L -M*TPW6)&+(R4K+2U at 4R>;)!HCF*97++Z!K]HR)1\V/LGBXU$\ -MS.?US#@;,C="&2$E("!Z/$<[.1MI%1,2%A07"C$9)3])UB N,2XP)3 AB\'I -MF''+%R8?QRU$+3B?A8UF*@%% <0 ^^ C&!HA)# [*C19ST5*8%0F&"$_K,H\ -M)AXB'B(EA-"0(R(A)"IB9R*94YR8L)0E)4B/U=@M(B9%0;++W%0U8)W8S$TB -M6$T5(2$<'Q],4&16,"V!5SQN5U\2?Y,#)DQ+T2$N1SLW+!T9;*+,=&72."\] -MGBH],C:%7U;*0$Z ;< ^]HE&"$A&R(M)2Y5UD([4U,P(2Q.O]Q&*",I)2DSB=Z@*"4WN(O)"(W/;S:XE4U8*/MSCP<8E4:(R$<'Q]82$9! -M)SVK=EJ8A80KEJ<4-T))U1PL/S L)!P@L5-*!TC(R$BA-"4(R(C(R=O:B.% -MI;2PMJ,K)C6JT-PP(B)%4F'*>WY]:ZC>U%HA(!\A'Q\A(1HW0U]G50P?)Q7U[9:/AS4X:(A\A'1P>'QLW.T];3@,4(0H4%PT:"Q@: -MBD)(T"Y.'"5!+D/6>*O3A'2[+B4QD"8P(S^+AH-$)0$C :P ^\PI%!LB)3P3 -M)2LY'ST[2E,K."HKE]A9*B J*B at PB=ZD*"WIU:*[SV$D9*"8F(1P@(1Y&04=63 TK,A4A)QDA&"8 at ED1'T2Q, -M&2 \*4C>B<'IF'_7'"PFD2DV*4>;D9%)(@$C :X ^^8S6#,S/3D1)R]=T4 \ -M1&@E)Q\@-<=;'QT@)B(GB]"B)!\C)2YE:2&!LG9BVJ(E("VNQ-HT(B1 1;.^ -MXW9<8ZS4U5(A(20A'AX?(!PH3&ME73=OE#D?&A8Z458HHEY&TC X-#H\-+O= -M=JO+=V?3/R,_:"4N)T1L=H-++ $X 9P ^\XK22LV0#L3+3-ATCDP-V0B)!\B -M/,M;'QX@)B$HCM&B)!\C)3!G:1V,LGQGUJ$F(#.TR-PU(!PU1;._Y&I37:O: -MT$4:'R(?'!P='AHG1F!;32A=;B(0#0D9)S0AI55%TRTZ-S4Q,+K8?[#,AG' -M,QLU9B,FW(R B)"0]9!YE6:64V:PO(ANC -MG-@U-$](B,B(04>KQM018J)3T=(>D<-28Z -M+FA"-5*U79 Z(0%# :D ^\\R5WHL*S,Y/53%TD1/64HG)AXH5LV8(AT@)2,C -M/\B[(R ?(2WM: -M9)0M1P%$ 6L ^\A%;X\_+#I$-$+"V#M 24(D(QXJ7-"8(QX@)2(D1'QX>'1\=0U"Y -MV59"27:IW5)A at M,_D$Y%RRDJB#0P-KC6P;FWL(W$,2$K>)B+>X%@79 J0P%$ -M 6L ^\8N3'4H(#$W*#_*YSL\2T8N+2)V0@(AG7)4H-P$[ 68 ^\\I -M-SJ+BJ]+O9C,T$]+7T,A)"4P7\.=)ATB*B,@@,C!(1\C)BW*?T+XK -M(B:G:=XU)25 at 4Z5DW))8:IZ8UDX\*"0A(B @'B 8-,NXTV0S4W6.TEUU<--2 -MBVA"P2TQFD,_-JJ[EIJ2EWK702LW=KAT[\L("BV;=XU -M(R)51ZMGVXE*7YN8VT,Q)B(?(!X>'!X0+L6TTU4I1VZ.S5%N;I8K(+B,U?,,U(UZ%B(]Q4P%: 8D ^]XM,#A_9J-%JGO3[$H^ -M4STK+S ^L*R G,R\QB=W2)B0H*R at I)A]SC'JGX93$U%=$8&$@("0O -M<,"U)ATD*R4K@)289(!M!A5NARLDM)2>H4MLW)1Y.2IM.UZI87U=Z -MTEH[(B,A(B A)!\A+$Z:S6(]4V6&W%A;7-!(@VA-V34UFTA%/JBNBGV,E'+/ -M/B> ?<4]'B);;7!]>@%I 6$ ^[M.9)Q(&3 N?8G(VD\W4UHB'R,S=\6U(QLA -M*R8PB,K#*2$>)2(5'!=$BF"CSSU,S1UZ&UTQ46;W%^? %K 6 ^^B(IL=<-4;W!)" A'1L5 -M%AHRED:>S,LL(RRG2=DU)!LQ49%!U+-189&)UU%&)24C)"NL(295:WM8T&8_ -M6&-TWU186=12DWM)Q#HRH3] -)V<=UTU>V#(02Y:.2HV(SAV)((B8UX=CTEI7+Y$(Z)AHC0J92X;<\5IF0Z48X)R'B0F+6G(OB8@'R,/$!$3)J5!L,?1+R(TLS_9/2(;)D.<*-&Y2%V0 -ME-Y00"$C)5)B3QXG)D=8@=!@5D]::]E&6S[/1G-H2IHV+*(Y,C22GU]7:6IK -MLLR_8:$C-R2.;%5P?%D"40#[Z%ODXEXT+$1ZCLG=03%$2# J,S>8V-,J(R8M -M+C9NVL\K)20H%!06&#"R0[K3W#0G.+])Y4(F("-"J#3>QCQ6E9OK4#TF)RE6 -M9U,C*RI'9X386$U(573F0U1&VT!P:4>>-"VF-B\NG[%K7&AN?\T2TA,Y1%V4 at G("ZO!TRT?-:1)V$0C'!XOA3K4N%1)CYS453LG*J4V>Y(='!TM+AO%85=0 -M6VC30TLRQD%'84A+,2VD14 Q4L2-?YU=-STG**$I&QT=HB" 44!50#[ -MXV?AY6PQ.3R+?K[@33M).C L+R^/S=(N)"DJ*"=DPLPM)B0J(R,@*!^]>\#& -MVS0D/:I5YTHI(B MB$#BR4M$E:/F7#HM,*H[AYLA(B,K-R#05TM)4VW>0#\T -MS3Q*8$-0+2VJ03LI6M"*?Y]6+CLN,;0J($R'I6=L8X:" 4]3DM#A]1W8U5=<"\B)$HN'I>>@6UZC&)+ 4D!3@#[R&+/TFHM.#U at 9Z++ -M9D170B4F)C%HO<(B'Q\F(R="(+\B'1LD%QL;)B&R-X]DRU\C'1X_ -M0J_*P$I9BIG1<$;4-61RTM -M*S9LR=0K)"8M*BU**LLK)"(K)2,B+B#.<\.XW38C/Y5PVF4I(R ]1;78T4%4 -MD*#C=T8H*JR4BYPE*G]:Q+:\34))1W'B3#F$VCD]5STH%"2[0D$QD=]7-R

I9:VDU2\A)F)TT&HF)"1%.*?0S&-5?(/ CU,J -M**.:=)(4T)[ -M2V!< 4X!6P#[UWK9Y8 J04EJ9T_383EC0RXK+BASO=8K(2,J*S,A),PM)2*Q[$@F*;9"8G(2%5D+\@'1TD*"4<2+\D'"0F'F-17Q^G -M8*J*T"\A($AES8 F'B)&-Z?!S5A5=%2TBUTE)YF?AIX?)BM)H*985U946#[< -M559KPTDW&5%222VY2#8^<\\J)V(P(1T=)5ACS*13/9!F;'Z! 6P!DP#[QEW( -MSW3< D'"0F%5 at D,!RK:JV/T2\? -M(E9JS'TB&AD_.*_&QTU+=E2Y at U(C)YVDBYT<)B9)HJM:6%%(5#_924QIPSTQ -M$DA+1RJQ0#$V=(B& 7,!H@#[TFG7XH4L,T5H -M,276AEJ/8BLN+2MAH]0I(B0K+RXB3\LM(RLM(54 at -Q['4W#@D*EUVVX4H -M(!D^.;73V$-%?EG(B4\E+*FSFJLD+3%"GJUB3$5!3$+E1D)KRC at J$4A)02JW -M/"PP>]HC'%,I(B(D(EIMW;),,HE><9*2 7X!K@#[NTJ.P(@L.T4A'BZP at T1V -M>"HE'QY2,[\F&QXI(2,A>[@D'2,D*5]89QRC2:5LS#4C(S8N7(LD'R-(/):P -MS5I>2R<^?T\>()6^EZT(;'9C%FJ.HZ@;#18=" B(1\>%,$F&!LB*"8B?KLD -M'2 H(EYS912H,)=:S3LB'2HL >,!Y #[ -MQ$5ZU)HM/S86AO"1Z9A -MWD0B'BXR=Z(M(1Y!1YNUVE)$'Q9392DJ.*S9EWDK)R].-X8<#TM 1XG;13O56G-H3SY.Q_CY ?X!_0"BLR89D),H -M/S--1H*)B#I =X!X #[LB,;FI at J0#%+2(B, -M at RI%;2,B)1H<%+\B'1H@)"U*V$9-+;R\O/0G';WN3E >4!YP"BP"LAK:&L at G(B$G*RXMA\\H( ,FU%QG9"*]-YT]WF$C*#: 3*HJ(!D]/8]9X$1 -M+DJ!(34H,:' J+4L)C=.&$X>0$P[3FK4.RE';R4S/EQ+-!R>1BPN,4NKV^GK -MXK^5=^?MT];3/V_J^03_ /N7'Q1NBR Z/T5%?'Z at 2%5@)R(A(!5=P"<>&" K -M)2!PMB(<'BDE96=G':8M>Q;,9RJKB,B-E at B -M'HU,06=)<*-#,&HX*"E"6$4]+65 ,3=*,7*+N6+*3B$;U,\^1DU\S]GIYN%%3DU]W/@$_P'] /N-(CE> -M82,W.#XV>V>P/&18)B0D&AQFP"L>'"8B)2%?J2$>'B8C9&ME&YL;>1:]AQX: -M1TY6JRDF'D at M+B9Q1$M<5%-<0!PFHY:FEE6459/"9+/T1"+2A. -M0SA$*BU&0#\_*8>JPW_(/RW-T!W0'A /N$&CML:Q\Y.C at U -M at FRT-5)((R$C(21PQR@:&28C)2-JKR$<'B at C8VMD'JD=>!>]AB >45Q>K"H? -M%4$F*BAS.SM544M2.1 at CIYVDIR(?+T\F;UY?435*/"M +S8V'AU&/C4_)"=! -M.#@Z)I:MT)/'-Q\BT\,_:EVQX>7GY>8!Y 'H /B<*D%]>R1!0B\RBWF^-D], -M*RLO+"IXTC(@(2\N+B=KN"@A(RPL8F)A(+HE=QC$E"@F6V5BN2LF&3 at G,"9[ -M/S543T5,.AXKL:BXMRTE,$XD;%U653= -RT_)R\Q'!I$/#4\)2H_-#8X)J#% -MYZ/3/B4IZ]5#:%.U^/P%_P#[H"$Y56,A+#4M)'%&CH[LY at E(44[9+ at L("Y<-QDY7#E>7$Q244P='I^# -MF* C(CM>.7!K;%T]3#NC,3U!+B =P!W0#[G1\]86T=+C)"@H9;XI&ADG)"8=7H4@ -M'AHF)%IC;!VE%S= M9'C57 -M,69 at 9E4M0CVI*R at M(B(V/!L:.BD?/"\T,3>3K="3OS0?(=#!7#UYX.+DY>/E -M >4!Y #WMS%)=G\B-C\D)'UMK#)623$H,#,N;(HC9%ME35)D7R(GEH..D",B,59;7UQKNT\YFR5 /BTF@% X -M'CY)(S at H-"Y#07N?NFZZB3$DQK=;:=';V]_=I]P!W@'? /N1(CA19A4X*"4C -M:%*J*E%(*R$H)2*%NR09%R,B(R(Y5A\:(QPD5&=E'9DK5&NJFR C4CUTOB@: -M'#Y"@(X=7$]7149652$IG8R6DQX>+%!455%ELS\ODQ\U+AX@@%(Z&SA$'3(C -M+"<^/H^FRX;#B"TBTKU79\S>Y^C>I> !YP'F /NF+C]D=AI ,"DE:%NX,$Y& -M,"LT,"B-QBX?'RPM+"8Z7R8?*" M4UYB(*HX6G&TIR8F64-VRRDA(#E @I@@ -M6DA-04-,32 OJ:*LHRDD*DE+2U!'V_O_[P_P"_P#[GAHN/5H6*1TI&T5!LR=U5#,@*B$=7JTI -M'AHB)2$?(#(;'2(?(U%F92**5T=;F:8F(C\G;K\H(24V.E@@55936%U<9&(E -M(XZ9AS,@)#%)5V^K9#%!1BA'0B at CAE:&AW\^5B(M/2LX.D)GF*I8I(TJ(\_' -M4E1=9VQW24I)35)055ECS8= -M("Y#4&>B72LT.A at W,B @B%N.BWPY41TG.",R-3]ZH[MPK9(J(\VZ.3]$4UQG -M9G;B >@!Z@#[LR8Y5W$8,B8H'4M1R"AA13 at G,S,K;K\R(1\K,2HG*C\@("ZI40G)BX\1V.B -M5"XU-1HY*AP at C&>*AGPW3ALJ-A\M,S^'OM:#Q:$Q*NG'-#]066!K>X[\ O\ -M^Y(=+C15$B8A*2 V,+,J67 E)"0<&%RA+1P7)"$D'ADC%!TD'2(_:6DA at 48F -M2W^G(1\R+E^^)2 B(CY93CI955Q56U->*!V.FU=W&R0C/U*GH%I-0CI40B at H -MFT>1?EC905,H-#0V-D!$4(:31)TF(B/3LWE/X.'BWN34X0+; /N2'# ^6A(C -M'24>.S>U)DYD*2,<(AYCJ"T:%"0B)!X>*A(9(1TD06EG'HU0+56$J!X<,"Q= -MOB4>'QTW440R3TE.2E!(4R,AF*5:>!LB(SE(IZ!.2SHK0S$=))U3G(E;T3Q. -M(R\O+C [05^8HE*<(R$AT*YR2-C9VM;9S.4!Z 'F )JC*#A(9ALK(RLB/D/* -M+DUG,2\J*R5LLS8?' ,MWB4A*Q8>*28H/V!C(*!@.5^0M28F-2YAQRXC(1LV -M33XN24)%0$8^22$IJ+AJA2(D*#1"L*5)33 at A."@=*:%8IXE=USE+(2TM*BLX -M/VNMNF.S+R F[+MG1^;IZN;FW/H"_P#[E1PH,%(1(1XB'"@7K3-,$A<4&B$?)$5L9B5N.1LQ9*PD(B\A$TD@'B$B,4A6.6I28&)8 -M5V8H((TS?0\A($=)4UUM3B])944Q2*Y4GX=1:< Y5B at W,BLV03E4:65J(2 C -M)=.W7RW9V]O !W@#[E!DH-U81'AH>&BL;LS5'<"XB)2H=*(@P'!%!H0%AX?)D=L9!]X0A\[::TA&R@>$DL@'!X=*D!,,6!&4E=-3%LC(I8\ -M?@\?'$=$2U]M0BU!4C8H2+!;K(]8;;TT42,R+2,O/#9;'BYN;J >D!Y0#UHR,O0& :)B D'BTCPCE";#8N,3,D,9,Y(1\J,"\E&!P5 -M&R8H*D5C8""*4"M%=;HI)B\<#U$I(2 ;*3Q&+5H_24U#0E$A*J1*B1 at D(5!" -M16=R/2\_12PH4;1DO:-7:+\R3R$P*R$M.C9D at WY\+B4C*/#%5S+Y"/\ ^)4> -M)B5)$R <&ADF&ZLL98PS*2,B$C)!(A\9(1XA'A$6%A,@(B4J<&\E8T+AY%=1DE(B)AC4Q3G4TO1%PR6)Q0J(9Z -M1E=P/E8O03,H*$ E $'R,@(230FW9/W>#AY /B N8 ^Y$:)"M-$QT8%A;$XF.U"U)!T=)W5D&!@6 -M'A=$5R921E!'3TY3)1U,>QDC'AQAB498GT$M/$XK6IU6LY*#2EMR-T\J/"X@ -M(3HB&CI%'2$>'R+4G71-W^'BY>GIZ at +K /B@(BDR5QPE'AX;)!Z],5F".#0O -M,1Y"4RLB'BHJ*R44%Q44)2LK*F=I'WQ:,41)R,A<(Y!7:,\+SI%*F"H6\"ECT)3<#9.*#HL'B [)!Y"4"$E -M(B,FZ:-L4O7Z^_X%_P#[C1\@($ .'QL;&B9,IC)N52LG("$3("T1)ALB)2 C -M%!X4$QX>)3AR:2%94"+%5F5&!-66987&4G)6<1)"$@ -M'8S;1E:20S-7)8:C6IQ^BUQ)-%!'6B(_,2LP1"DC,KPK(1\C)*MO:2W8V-W@ -MW^?F > -M)3IR9QIB52(FL6(AX<%HW805N4 -M.S!/'XFG6J2+F&5*-U1"51TY+"0G02T! -MZ@#YE2$A*DH5)!T@'BA3M#)A2B\S+B\;+C\;*1XK,2DH%AP3%"$E*CAI8QMN -M83 [-\'APV -M%1H<'6FE/D at I3DTM(Q\B%AL8$"(<)"(D)A44$AHB(B4M<60A0V$A.ABR*A]S -M%1LA'R$E(2I376->75)N9V-F+2,?(R8<&12TUDI.CSQW66E\=*6-A5A)0S8[ -MA5$J-2 at O+SG@+AZ:'"(JF93(J=/CV][>W^+CX at +C /M\%QL:-!,8&A]NJT-* -M)TQ(*R,?(A(@)1(>&B0D(B(1$! 8(" B*W%D&T]D'3X>MR<@=18='1PA'1 at A -M2%%33DU"7UE66"8?&Q\D&A<2MM%$4I$Y<%!H?WBKE(Q<34(U.XE/)"\C+20\ -MX2@15J7.6]097^ O)^79$ -MW^+CX@'B >, ^VP5%A,H%!884"\N/$ @25LC)!\E$!<:$1(7'R8?(!$6("0A -M(1\D<&H;1V$611IB)!\2&A\>&1L7(CM%44M#3U],5517-B,;&WDA%Q>8GT52 -MBD+5VH]4K*E[3$1'-T*5-3TX%3,[*T[5)AXN;GZ.KKZ@'J -M >L LWT>&!@M&!H<63 at T044B058H*R8L%AH<%18;)BXF)18;)2DF)B -M3F\;0!MG)AX7(@,AOR(;(#D_2D(Z1E8_2$E--R@@(($I'!N>KD-7D4CCY9%< -MO+Q]23\Y+CF.+C9WG at SOSX_ 7_@?X!_@'_ )]G'Q06 -M'1,8&!H?/CM!(59:-"(D(Q05$Q00'APJ'R(=!"'8)"4N:VPC*'47%%A1'!LA -M'Q\C&R(I+CQ-45=?65Q65&>80B$H)$8=&1S2Y4I>@E[:WMKAH7A-04<]2HXY -M34LHHCHV/5?92)"/C8AG9%[3T=78W=WDS\=)"!#&18:U-]%8X!:UMW2X*Z"3T%'.4J1.4Q'(IPU-#)9 -MV$&2E(Z+:61EW=S?X^;FY>CKZ.8"Z@"@;B$3&2 5&AHD*$,]0QY)3C8I*RH6 -M%1,4$B C-"8I)"@#*=$L*BYB92 [AA at 77UHC&B(C("(@*24D+CL\0DI$1SY! -M7I%!(BDE3R@>'MSP0V6"8.CIV.Z]BDTX."]%B3!!/R.?,RPQ7>9*F)F/C61= -M9NWV__X%_X+\^@'^ ?\ M%,?'!H5$Q04'2,W/1@>6U8](!LA$109$A$;'B@? -M)B B'",B'B,C8VHH'82H<$L_23)(38Z2T<_2EE".SZAGC8A'!=#(Q at -GM)=6G9< -MTMG at K7Y1/T-;7'%AY./HNHA, -H.C\A48 at V0SHZ']@V+B]=Z5W at GE]=6%9O[/?]^_S__O__^_X!_0'_ - -end From python-3000-checkins at python.org Tue Aug 19 23:30:55 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Tue, 19 Aug 2008 23:30:55 +0200 (CEST) Subject: [Python-3000-checkins] r65883 - in python/branches/py3k/Lib/multiprocessing: forking.py managers.py reduction.py sharedctypes.py util.py Message-ID: <20080819213055.B267E1E4009@bag.python.org> Author: amaury.forgeotdarc Date: Tue Aug 19 23:30:55 2008 New Revision: 65883 Log: Issue #3125: Remove copy_reg in multiprocessing and replace it with ForkingPickler.register() to resolve conflict with ctypes. Modified: python/branches/py3k/Lib/multiprocessing/forking.py python/branches/py3k/Lib/multiprocessing/managers.py python/branches/py3k/Lib/multiprocessing/reduction.py python/branches/py3k/Lib/multiprocessing/sharedctypes.py python/branches/py3k/Lib/multiprocessing/util.py Modified: python/branches/py3k/Lib/multiprocessing/forking.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/forking.py (original) +++ python/branches/py3k/Lib/multiprocessing/forking.py Tue Aug 19 23:30:55 2008 @@ -12,7 +12,7 @@ from multiprocessing import util, process -__all__ = ['Popen', 'assert_spawning', 'exit', 'duplicate', 'close'] +__all__ = ['Popen', 'assert_spawning', 'exit', 'duplicate', 'close', 'ForkingPickler'] # # Check that the current thread is spawning a child process @@ -26,6 +26,50 @@ ) # +# Try making some callable types picklable +# + +from pickle import _Pickler as Pickler +class ForkingPickler(Pickler): + dispatch = Pickler.dispatch.copy() + @classmethod + def register(cls, type, reduce): + def dispatcher(self, obj): + rv = reduce(obj) + if isinstance(rv, str): + self.save_global(obj, rv) + else: + self.save_reduce(obj=obj, *rv) + cls.dispatch[type] = dispatcher + +def _reduce_method(m): + if m.__self__ is None: + return getattr, (m.__class__, m.__func__.__name__) + else: + return getattr, (m.__self__, m.__func__.__name__) +class _C: + def f(self): + pass +ForkingPickler.register(type(_C().f), _reduce_method) + + +def _reduce_method_descriptor(m): + return getattr, (m.__objclass__, m.__name__) +ForkingPickler.register(type(list.append), _reduce_method_descriptor) +ForkingPickler.register(type(int.__add__), _reduce_method_descriptor) + +try: + from functools import partial +except ImportError: + pass +else: + def _reduce_partial(p): + return _rebuild_partial, (p.func, p.args, p.keywords or {}) + def _rebuild_partial(func, args, keywords): + return partial(func, *args, **keywords) + ForkingPickler.register(partial, _reduce_partial) + +# # Unix # @@ -105,16 +149,18 @@ import _thread import msvcrt import _subprocess - import copyreg import time from ._multiprocessing import win32, Connection, PipeConnection from .util import Finalize - try: - from cPickle import dump, load, HIGHEST_PROTOCOL - except ImportError: - from pickle import dump, load, HIGHEST_PROTOCOL + #try: + # from cPickle import dump, load, HIGHEST_PROTOCOL + #except ImportError: + from pickle import load, HIGHEST_PROTOCOL + + def dump(obj, file, protocol=None): + ForkingPickler(file, protocol).dump(obj) # # @@ -346,9 +392,8 @@ return type(conn), (Popen.duplicate_for_child(conn.fileno()), conn.readable, conn.writable) - copyreg.pickle(Connection, reduce_connection) - copyreg.pickle(PipeConnection, reduce_connection) - + ForkingPickler.register(Connection, reduce_connection) + ForkingPickler.register(PipeConnection, reduce_connection) # # Prepare current process Modified: python/branches/py3k/Lib/multiprocessing/managers.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/managers.py (original) +++ python/branches/py3k/Lib/multiprocessing/managers.py Tue Aug 19 23:30:55 2008 @@ -18,13 +18,12 @@ import weakref import threading import array -import copyreg import queue from traceback import format_exc from multiprocessing import Process, current_process, active_children, Pool, util, connection from multiprocessing.process import AuthenticationString -from multiprocessing.forking import exit, Popen, assert_spawning +from multiprocessing.forking import exit, Popen, assert_spawning, ForkingPickler from multiprocessing.util import Finalize, info try: @@ -38,14 +37,14 @@ def reduce_array(a): return array.array, (a.typecode, a.tostring()) -copyreg.pickle(array.array, reduce_array) +ForkingPickler.register(array.array, reduce_array) view_types = [type(getattr({}, name)()) for name in ('items','keys','values')] if view_types[0] is not list: # only needed in Py3.0 def rebuild_as_list(obj): return list, (list(obj),) for view_type in view_types: - copyreg.pickle(view_type, rebuild_as_list) + ForkingPickler.register(view_type, rebuild_as_list) # # Type for identifying shared objects Modified: python/branches/py3k/Lib/multiprocessing/reduction.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/reduction.py (original) +++ python/branches/py3k/Lib/multiprocessing/reduction.py Tue Aug 19 23:30:55 2008 @@ -13,11 +13,10 @@ import sys import socket import threading -import copyreg import _multiprocessing from multiprocessing import current_process -from multiprocessing.forking import Popen, duplicate, close +from multiprocessing.forking import Popen, duplicate, close, ForkingPickler from multiprocessing.util import register_after_fork, debug, sub_debug from multiprocessing.connection import Client, Listener @@ -134,7 +133,7 @@ return new_handle # -# Register `_multiprocessing.Connection` with `copy_reg` +# Register `_multiprocessing.Connection` with `ForkingPickler` # def reduce_connection(conn): @@ -147,10 +146,10 @@ handle, readable=readable, writable=writable ) -copyreg.pickle(_multiprocessing.Connection, reduce_connection) +ForkingPickler.register(_multiprocessing.Connection, reduce_connection) # -# Register `socket.socket` with `copy_reg` +# Register `socket.socket` with `ForkingPickler` # def fromfd(fd, family, type_, proto=0): @@ -169,10 +168,10 @@ close(fd) return _sock -copyreg.pickle(socket.socket, reduce_socket) +ForkingPickler.register(socket.socket, reduce_socket) # -# Register `_multiprocessing.PipeConnection` with `copy_reg` +# Register `_multiprocessing.PipeConnection` with `ForkingPickler` # if sys.platform == 'win32': @@ -187,4 +186,4 @@ handle, readable=readable, writable=writable ) - copyreg.pickle(_multiprocessing.PipeConnection, reduce_pipe_connection) + ForkingPickler.register(_multiprocessing.PipeConnection, reduce_pipe_connection) Modified: python/branches/py3k/Lib/multiprocessing/sharedctypes.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/sharedctypes.py (original) +++ python/branches/py3k/Lib/multiprocessing/sharedctypes.py Tue Aug 19 23:30:55 2008 @@ -9,10 +9,9 @@ import sys import ctypes import weakref -import copyreg from multiprocessing import heap, RLock -from multiprocessing.forking import assert_spawning +from multiprocessing.forking import assert_spawning, ForkingPickler __all__ = ['RawValue', 'RawArray', 'Value', 'Array', 'copy', 'synchronized'] @@ -124,8 +123,7 @@ def rebuild_ctype(type_, wrapper, length): if length is not None: type_ = type_ * length - if sys.platform == 'win32' and type_ not in copyreg.dispatch_table: - copyreg.pickle(type_, reduce_ctype) + ForkingPickler.register(type_, reduce_ctype) obj = type_.from_address(wrapper.get_address()) obj._wrapper = wrapper return obj Modified: python/branches/py3k/Lib/multiprocessing/util.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/util.py (original) +++ python/branches/py3k/Lib/multiprocessing/util.py Tue Aug 19 23:30:55 2008 @@ -8,7 +8,6 @@ import itertools import weakref -import copyreg import atexit import threading # we want threading to install it's # cleanup function before multiprocessing does @@ -302,35 +301,3 @@ register_after_fork(self, lambda obj : obj.__dict__.clear()) def __reduce__(self): return type(self), () - -# -# Try making some callable types picklable -# - -def _reduce_method(m): - if m.__self__ is None: - return getattr, (m.__self__.__class__, m.__func__.__name__) - else: - return getattr, (m.__self__, m.__func__.__name__) -copyreg.pickle(type(Finalize.__init__), _reduce_method) - -def _reduce_method_descriptor(m): - return getattr, (m.__objclass__, m.__name__) -copyreg.pickle(type(list.append), _reduce_method_descriptor) -copyreg.pickle(type(int.__add__), _reduce_method_descriptor) - -def _reduce_builtin_function_or_method(m): - return getattr, (m.__self__, m.__name__) -copyreg.pickle(type(list().append), _reduce_builtin_function_or_method) -copyreg.pickle(type(int().__add__), _reduce_builtin_function_or_method) - -try: - from functools import partial -except ImportError: - pass -else: - def _reduce_partial(p): - return _rebuild_partial, (p.func, p.args, p.keywords or {}) - def _rebuild_partial(func, args, keywords): - return partial(func, *args, **keywords) - copyreg.pickle(partial, _reduce_partial) From python-3000-checkins at python.org Tue Aug 19 23:42:14 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 19 Aug 2008 23:42:14 +0200 (CEST) Subject: [Python-3000-checkins] r65884 - in python/branches/py3k: Doc/library/ssl.rst Include/pymath.h Lib/lib2to3 Lib/lib2to3/refactor.py Message-ID: <20080819214214.18AB11E400D@bag.python.org> Author: benjamin.peterson Date: Tue Aug 19 23:42:13 2008 New Revision: 65884 Log: Merged revisions 65658,65869,65882 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ................ r65658 | bill.janssen | 2008-08-12 12:09:57 -0500 (Tue, 12 Aug 2008) | 1 line update ssl documentation ................ r65869 | benjamin.peterson | 2008-08-19 14:27:53 -0500 (Tue, 19 Aug 2008) | 1 line fix a little typo ................ r65882 | benjamin.peterson | 2008-08-19 16:07:15 -0500 (Tue, 19 Aug 2008) | 9 lines Merged revisions 65876 via svnmerge from svn+ssh://pythondev at svn.python.org/sandbox/trunk/2to3/lib2to3 ........ r65876 | benjamin.peterson | 2008-08-19 15:54:52 -0500 (Tue, 19 Aug 2008) | 1 line apply a fix I think will help Windows ........ ................ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/library/ssl.rst python/branches/py3k/Include/pymath.h python/branches/py3k/Lib/lib2to3/ (props changed) python/branches/py3k/Lib/lib2to3/refactor.py Modified: python/branches/py3k/Doc/library/ssl.rst ============================================================================== --- python/branches/py3k/Doc/library/ssl.rst (original) +++ python/branches/py3k/Doc/library/ssl.rst Tue Aug 19 23:42:13 2008 @@ -335,6 +335,15 @@ established, returns ``None``. +.. method:: SSLSocket.unwrap() + + Performs the SSL shutdown handshake, which removes the TLS layer + from the underlying socket, and returns the underlying socket + object. This can be used to go from encrypted operation over a + connection to unencrypted. The returned socket should always be + used for further communication with the other side of the + connection, rather than the original socket + .. index:: single: certificates .. index:: single: X509 certificate Modified: python/branches/py3k/Include/pymath.h ============================================================================== --- python/branches/py3k/Include/pymath.h (original) +++ python/branches/py3k/Include/pymath.h Tue Aug 19 23:42:13 2008 @@ -19,7 +19,7 @@ *Note: PC/pyconfig.h defines copysign as _copysign */ #ifndef HAVE_COPYSIGN -extern double copysign(doube, double); +extern double copysign(double, double); #endif #ifndef HAVE_ACOSH Modified: python/branches/py3k/Lib/lib2to3/refactor.py ============================================================================== --- python/branches/py3k/Lib/lib2to3/refactor.py (original) +++ python/branches/py3k/Lib/lib2to3/refactor.py Tue Aug 19 23:42:13 2008 @@ -177,6 +177,8 @@ else: fixer_pkg = self.fixer_dir fixer_pkg = fixer_pkg.replace(os.path.sep, ".") + if os.path.altsep: + fixer_pkg = self.fixer_dir.replace(os.path.altsep, ".") pre_order_fixers = [] post_order_fixers = [] fix_names = self.options.fix From python-3000-checkins at python.org Wed Aug 20 00:09:34 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Wed, 20 Aug 2008 00:09:34 +0200 (CEST) Subject: [Python-3000-checkins] r65886 - in python/branches/py3k: Lib/test/test_codecs.py Lib/test/test_memoryview.py Misc/NEWS Objects/memoryobject.c Message-ID: <20080819220934.CD8F21E4006@bag.python.org> Author: antoine.pitrou Date: Wed Aug 20 00:09:34 2008 New Revision: 65886 Log: Issue #2394: implement more of the memoryview API. Modified: python/branches/py3k/Lib/test/test_codecs.py python/branches/py3k/Lib/test/test_memoryview.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/memoryobject.c Modified: python/branches/py3k/Lib/test/test_codecs.py ============================================================================== --- python/branches/py3k/Lib/test/test_codecs.py (original) +++ python/branches/py3k/Lib/test/test_codecs.py Wed Aug 20 00:09:34 2008 @@ -621,7 +621,7 @@ def test_bug1601501(self): # SF bug #1601501: check that the codec works with a buffer - str(b"\xef\xbb\xbf", "utf-8-sig") + self.assertEquals(str(b"\xef\xbb\xbf", "utf-8-sig"), "") def test_bom(self): d = codecs.getincrementaldecoder("utf-8-sig")() Modified: python/branches/py3k/Lib/test/test_memoryview.py ============================================================================== --- python/branches/py3k/Lib/test/test_memoryview.py (original) +++ python/branches/py3k/Lib/test/test_memoryview.py Wed Aug 20 00:09:34 2008 @@ -5,8 +5,166 @@ import unittest import test.support +import sys -class MemoryviewTest(unittest.TestCase): + +class CommonMemoryTests: + # + # Tests common to direct memoryviews and sliced memoryviews + # + + base_object = b"abcdef" + + def check_getitem_with_type(self, tp): + b = tp(self.base_object) + oldrefcount = sys.getrefcount(b) + m = self._view(b) + self.assertEquals(m[0], b"a") + self.assert_(isinstance(m[0], bytes), type(m[0])) + self.assertEquals(m[5], b"f") + self.assertEquals(m[-1], b"f") + self.assertEquals(m[-6], b"a") + # Bounds checking + self.assertRaises(IndexError, lambda: m[6]) + self.assertRaises(IndexError, lambda: m[-7]) + self.assertRaises(IndexError, lambda: m[sys.maxsize]) + self.assertRaises(IndexError, lambda: m[-sys.maxsize]) + # Type checking + self.assertRaises(TypeError, lambda: m[None]) + self.assertRaises(TypeError, lambda: m[0.0]) + self.assertRaises(TypeError, lambda: m["a"]) + m = None + self.assertEquals(sys.getrefcount(b), oldrefcount) + + def test_getitem_readonly(self): + self.check_getitem_with_type(bytes) + + def test_getitem_writable(self): + self.check_getitem_with_type(bytearray) + + def test_setitem_readonly(self): + b = self.base_object + oldrefcount = sys.getrefcount(b) + m = self._view(b) + def setitem(value): + m[0] = value + self.assertRaises(TypeError, setitem, b"a") + self.assertRaises(TypeError, setitem, 65) + self.assertRaises(TypeError, setitem, memoryview(b"a")) + m = None + self.assertEquals(sys.getrefcount(b), oldrefcount) + + def test_setitem_writable(self): + b = bytearray(self.base_object) + oldrefcount = sys.getrefcount(b) + m = self._view(b) + m[0] = b"0" + self._check_contents(b, b"0bcdef") + m[1:3] = b"12" + self._check_contents(b, b"012def") + m[1:1] = b"" + self._check_contents(b, b"012def") + m[:] = b"abcdef" + self._check_contents(b, b"abcdef") + + # Overlapping copies of a view into itself + m[0:3] = m[2:5] + self._check_contents(b, b"cdedef") + m[:] = b"abcdef" + m[2:5] = m[0:3] + self._check_contents(b, b"ababcf") + + def setitem(key, value): + m[key] = value + # Bounds checking + self.assertRaises(IndexError, setitem, 6, b"a") + self.assertRaises(IndexError, setitem, -7, b"a") + self.assertRaises(IndexError, setitem, sys.maxsize, b"a") + self.assertRaises(IndexError, setitem, -sys.maxsize, b"a") + # Wrong index/slice types + self.assertRaises(TypeError, setitem, 0.0, b"a") + self.assertRaises(TypeError, setitem, (0,), b"a") + self.assertRaises(TypeError, setitem, "a", b"a") + # Trying to resize the memory object + self.assertRaises(ValueError, setitem, 0, b"") + self.assertRaises(ValueError, setitem, 0, b"ab") + self.assertRaises(ValueError, setitem, slice(1,1), b"a") + self.assertRaises(ValueError, setitem, slice(0,2), b"a") + + m = None + self.assertEquals(sys.getrefcount(b), oldrefcount) + + def test_len(self): + self.assertEquals(len(self._view(self.base_object)), 6) + + def test_tobytes(self): + m = self._view(self.base_object) + b = m.tobytes() + self.assertEquals(b, b"abcdef") + self.assert_(isinstance(b, bytes), type(b)) + + def test_tolist(self): + m = self._view(self.base_object) + l = m.tolist() + self.assertEquals(l, list(b"abcdef")) + + def test_compare(self): + # memoryviews can compare for equality with other objects + # having the buffer interface. + m = self._view(self.base_object) + for tp in (bytes, bytearray): + self.assertTrue(m == tp(b"abcdef")) + self.assertFalse(m != tp(b"abcdef")) + self.assertFalse(m == tp(b"abcde")) + self.assertTrue(m != tp(b"abcde")) + self.assertFalse(m == tp(b"abcde1")) + self.assertTrue(m != tp(b"abcde1")) + self.assertTrue(m == m) + self.assertTrue(m == m[:]) + self.assertTrue(m[0:6] == m[:]) + self.assertFalse(m[0:5] == m) + + # Comparison with objects which don't support the buffer API + self.assertFalse(m == "abc") + self.assertTrue(m != "abc") + self.assertFalse("abc" == m) + self.assertTrue("abc" != m) + + # Unordered comparisons + for c in (m, b"abcdef"): + self.assertRaises(TypeError, lambda: m < c) + self.assertRaises(TypeError, lambda: c <= m) + self.assertRaises(TypeError, lambda: m >= c) + self.assertRaises(TypeError, lambda: c > m) + + def check_attributes_with_type(self, tp): + b = tp(self.base_object) + m = self._view(b) + self.assertEquals(m.format, 'B') + self.assertEquals(m.itemsize, 1) + self.assertEquals(m.ndim, 1) + self.assertEquals(m.shape, (6,)) + self.assertEquals(m.size, 6) + self.assertEquals(m.strides, (1,)) + self.assertEquals(m.suboffsets, None) + return m + + def test_attributes_readonly(self): + m = self.check_attributes_with_type(bytes) + self.assertEquals(m.readonly, True) + + def test_attributes_writable(self): + m = self.check_attributes_with_type(bytearray) + self.assertEquals(m.readonly, False) + + +class MemoryviewTest(unittest.TestCase, CommonMemoryTests): + + def _view(self, obj): + return memoryview(obj) + + def _check_contents(self, obj, contents): + self.assertEquals(obj, contents) def test_constructor(self): ob = b'test' @@ -17,8 +175,38 @@ self.assertRaises(TypeError, memoryview, argument=ob) self.assertRaises(TypeError, memoryview, ob, argument=True) + +class MemorySliceTest(unittest.TestCase, CommonMemoryTests): + base_object = b"XabcdefY" + + def _view(self, obj): + m = memoryview(obj) + return m[1:7] + + def _check_contents(self, obj, contents): + self.assertEquals(obj[1:7], contents) + + def test_refs(self): + m = memoryview(b"ab") + oldrefcount = sys.getrefcount(m) + m[1:2] + self.assertEquals(sys.getrefcount(m), oldrefcount) + + +class MemorySliceSliceTest(unittest.TestCase, CommonMemoryTests): + base_object = b"XabcdefY" + + def _view(self, obj): + m = memoryview(obj) + return m[:7][1:] + + def _check_contents(self, obj, contents): + self.assertEquals(obj[1:7], contents) + + def test_main(): - test.support.run_unittest(MemoryviewTest) + test.support.run_unittest( + MemoryviewTest, MemorySliceTest, MemorySliceSliceTest) if __name__ == "__main__": Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Aug 20 00:09:34 2008 @@ -12,6 +12,13 @@ Core and Builtins ----------------- +- Issue #2394: implement more of the memoryview API, with the caveat that + only one-dimensional contiguous buffers are supported and exercised right + now. Slicing, slice assignment and comparison (equality and inequality) + have been added. Also, the tolist() method has been implemented, but only + for byte buffers. Endly, the API has been updated to return bytes objects + wherever it used to return bytearrays. + - Issue #3560: clean up the new C PyMemoryView API so that naming is internally consistent; add macros PyMemoryView_GET_BASE() and PyMemoryView_GET_BUFFER() to access useful properties of a memory views Modified: python/branches/py3k/Objects/memoryobject.c ============================================================================== --- python/branches/py3k/Objects/memoryobject.c (original) +++ python/branches/py3k/Objects/memoryobject.c Wed Aug 20 00:09:34 2008 @@ -13,8 +13,8 @@ } if (self->view.obj == NULL) return 0; - return self->view.obj->ob_type->tp_as_buffer->bf_getbuffer(self->base, NULL, - PyBUF_FULL); + return self->view.obj->ob_type->tp_as_buffer->bf_getbuffer( + self->view.obj, NULL, PyBUF_FULL); } static void @@ -37,9 +37,14 @@ &PyMemoryView_Type); if (mview == NULL) return NULL; mview->base = NULL; + /* XXX there should be an API to duplicate a buffer object */ mview->view = *info; - if (info->obj) - Py_INCREF(mview->view.obj); + if (info->shape == &(info->len)) + mview->view.shape = &(mview->view.len); + if (info->strides == &(info->itemsize)) + mview->view.strides = &(mview->view.itemsize); + /* NOTE: mview->view.obj should already have been incref'ed as + part of PyBuffer_FillInfo(). */ return (PyObject *)mview; } @@ -258,12 +263,12 @@ "for a non-contiguousobject."); return NULL; } - bytes = PyByteArray_FromStringAndSize(NULL, view->len); + bytes = PyBytes_FromStringAndSize(NULL, view->len); if (bytes == NULL) { PyBuffer_Release(view); return NULL; } - dest = PyByteArray_AS_STRING(bytes); + dest = PyBytes_AS_STRING(bytes); /* different copying strategy depending on whether or not any pointer de-referencing is needed */ @@ -386,17 +391,45 @@ static PyObject * memory_tobytes(PyMemoryViewObject *mem, PyObject *noargs) { - return PyByteArray_FromObject((PyObject *)mem); + return PyObject_CallFunctionObjArgs( + (PyObject *) &PyBytes_Type, mem, NULL); } +/* TODO: rewrite this function using the struct module to unpack + each buffer item */ + static PyObject * memory_tolist(PyMemoryViewObject *mem, PyObject *noargs) { - /* This should construct a (nested) list of unpacked objects - possibly using the struct module. - */ - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + Py_buffer *view = &(mem->view); + Py_ssize_t i; + PyObject *res, *item; + char *buf; + + if (strcmp(view->format, "B") || view->itemsize != 1) { + PyErr_SetString(PyExc_NotImplementedError, + "tolist() only supports byte views"); + return NULL; + } + if (view->ndim != 1) { + PyErr_SetString(PyExc_NotImplementedError, + "tolist() only supports one-dimensional objects"); + return NULL; + } + res = PyList_New(view->len); + if (res == NULL) + return NULL; + buf = view->buf; + for (i = 0; i < view->len; i++) { + item = PyLong_FromUnsignedLong((unsigned char) *buf); + if (item == NULL) { + Py_DECREF(res); + return NULL; + } + PyList_SET_ITEM(res, i, item); + buf++; + } + return res; } @@ -412,7 +445,7 @@ memory_dealloc(PyMemoryViewObject *self) { if (self->view.obj != NULL) { - if (PyTuple_Check(self->base)) { + if (self->base && PyTuple_Check(self->base)) { /* Special case when first element is generic object with buffer interface and the second element is a contiguous "shadow" that must be copied back into @@ -454,8 +487,8 @@ if (PyObject_GetBuffer((PyObject *)self, &view, PyBUF_FULL) < 0) return NULL; - res = PyByteArray_FromStringAndSize(NULL, view.len); - PyBuffer_ToContiguous(PyByteArray_AS_STRING(res), &view, view.len, 'C'); + res = PyBytes_FromStringAndSize(NULL, view.len); + PyBuffer_ToContiguous(PyBytes_AS_STRING(res), &view, view.len, 'C'); PyBuffer_Release(&view); return res; } @@ -511,7 +544,7 @@ if (result < 0) { result += view->shape[0]; } - if ((result < 0) || (result > view->shape[0])) { + if ((result < 0) || (result >= view->shape[0])) { PyErr_SetString(PyExc_IndexError, "index out of bounds"); return NULL; @@ -525,7 +558,7 @@ { ptr = *((char **)ptr) + view->suboffsets[0]; } - return PyByteArray_FromStringAndSize(ptr, view->itemsize); + return PyBytes_FromStringAndSize(ptr, view->itemsize); } else { /* Return a new memory-view object */ @@ -537,10 +570,46 @@ return PyMemoryView_FromBuffer(&newview); } } + else if (PySlice_Check(key)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx((PySliceObject*)key, view->len, + &start, &stop, &step, &slicelength) < 0) { + return NULL; + } - /* Need to support getting a sliced view */ - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; + if (step == 1 && view->ndim == 1) { + Py_buffer newview; + void *newbuf = (char *) view->buf + + start * view->itemsize; + int newflags = view->readonly + ? PyBUF_CONTIG_RO : PyBUF_CONTIG; + + /* XXX There should be an API to create a subbuffer */ + if (view->obj != NULL) { + if (PyObject_GetBuffer(view->obj, + &newview, newflags) == -1) + return NULL; + } + else { + newview = *view; + } + newview.buf = newbuf; + newview.len = slicelength; + newview.format = view->format; + if (view->shape == &(view->len)) + newview.shape = &(newview.len); + if (view->strides == &(view->itemsize)) + newview.strides = &(newview.itemsize); + return PyMemoryView_FromBuffer(&newview); + } + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; + } + PyErr_Format(PyExc_TypeError, + "cannot index memory using \"%.200s\"", + key->ob_type->tp_name); + return NULL; } @@ -548,9 +617,138 @@ static int memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value) { - return 0; + Py_ssize_t start, len, bytelen, i; + Py_buffer srcview; + Py_buffer *view = &(self->view); + char *srcbuf, *destbuf; + + if (view->readonly) { + PyErr_SetString(PyExc_TypeError, + "cannot modify read-only memory"); + return -1; + } + if (view->ndim != 1) { + PyErr_SetNone(PyExc_NotImplementedError); + return -1; + } + if (PyIndex_Check(key)) { + start = PyNumber_AsSsize_t(key, NULL); + if (start == -1 && PyErr_Occurred()) + return -1; + if (start < 0) { + start += view->shape[0]; + } + if ((start < 0) || (start >= view->shape[0])) { + PyErr_SetString(PyExc_IndexError, + "index out of bounds"); + return -1; + } + len = 1; + } + else if (PySlice_Check(key)) { + Py_ssize_t stop, step; + + if (PySlice_GetIndicesEx((PySliceObject*)key, view->len, + &start, &stop, &step, &len) < 0) { + return -1; + } + if (step != 1) { + PyErr_SetNone(PyExc_NotImplementedError); + return -1; + } + } + else { + PyErr_Format(PyExc_TypeError, + "cannot index memory using \"%.200s\"", + key->ob_type->tp_name); + return -1; + } + if (PyObject_GetBuffer(value, &srcview, PyBUF_CONTIG_RO) == -1) { + return -1; + } + /* XXX should we allow assignment of different item sizes + as long as the byte length is the same? + (e.g. assign 2 shorts to a 4-byte slice) */ + if (srcview.itemsize != view->itemsize) { + PyErr_Format(PyExc_TypeError, + "mismatching item sizes for \"%.200s\" and \"%.200s\"", + view->obj->ob_type->tp_name, srcview.obj->ob_type->tp_name); + goto _error; + } + if (srcview.len != len) { + PyErr_SetString(PyExc_ValueError, + "cannot modify size of memoryview object"); + goto _error; + } + /* Do the actual copy */ + destbuf = (char *) view->buf + start * view->itemsize; + srcbuf = (char *) srcview.buf; + bytelen = len * view->itemsize; + if (destbuf + bytelen < srcbuf || srcbuf + bytelen < destbuf) + /* No overlapping */ + memcpy(destbuf, srcbuf, bytelen); + else if (destbuf < srcbuf) { + /* Copy in ascending order */ + for (i = 0; i < bytelen; i++) + destbuf[i] = srcbuf[i]; + } + else { + /* Copy in descencing order */ + for (i = bytelen - 1; i >= 0; i--) + destbuf[i] = srcbuf[i]; + } + + PyBuffer_Release(&srcview); + return 0; + +_error: + PyBuffer_Release(&srcview); + return -1; +} + +static PyObject * +memory_richcompare(PyObject *v, PyObject *w, int op) +{ + Py_buffer vv, ww; + int equal = 0; + PyObject *res; + + vv.obj = NULL; + ww.obj = NULL; + if (op != Py_EQ && op != Py_NE) + goto _notimpl; + if (PyObject_GetBuffer(v, &vv, PyBUF_CONTIG_RO) == -1) { + PyErr_Clear(); + goto _notimpl; + } + if (PyObject_GetBuffer(w, &ww, PyBUF_CONTIG_RO) == -1) { + PyErr_Clear(); + goto _notimpl; + } + + if (vv.itemsize != ww.itemsize || vv.len != ww.len) + goto _end; + + equal = !memcmp(vv.buf, ww.buf, vv.len * vv.itemsize); + +_end: + PyBuffer_Release(&vv); + PyBuffer_Release(&ww); + if ((equal && op == Py_EQ) || (!equal && op == Py_NE)) + res = Py_True; + else + res = Py_False; + Py_INCREF(res); + return res; + +_notimpl: + PyBuffer_Release(&vv); + PyBuffer_Release(&ww); + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } + /* As mapping */ static PyMappingMethods memory_as_mapping = { (lenfunc)memory_length, /*mp_length*/ @@ -591,7 +789,7 @@ memory_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - 0, /* tp_richcompare */ + memory_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ From python-3000-checkins at python.org Wed Aug 20 01:02:39 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Wed, 20 Aug 2008 01:02:39 +0200 (CEST) Subject: [Python-3000-checkins] r65888 - in python/branches/py3k/Lib/test: regrtest.py test_nis.py Message-ID: <20080819230239.3AAE51E4009@bag.python.org> Author: benjamin.peterson Date: Wed Aug 20 01:02:38 2008 New Revision: 65888 Log: disable test_nis; it hangs Modified: python/branches/py3k/Lib/test/regrtest.py python/branches/py3k/Lib/test/test_nis.py Modified: python/branches/py3k/Lib/test/regrtest.py ============================================================================== --- python/branches/py3k/Lib/test/regrtest.py (original) +++ python/branches/py3k/Lib/test/regrtest.py Wed Aug 20 01:02:38 2008 @@ -1135,6 +1135,7 @@ # These are broken tests, for now skipped on every platform. # XXX Fix these! self.expected.add('test_cProfile') + self.expected.add('test_nis') # expected to be skipped on every platform, even Linux if not os.path.supports_unicode_filenames: Modified: python/branches/py3k/Lib/test/test_nis.py ============================================================================== --- python/branches/py3k/Lib/test/test_nis.py (original) +++ python/branches/py3k/Lib/test/test_nis.py Wed Aug 20 01:02:38 2008 @@ -2,6 +2,8 @@ import unittest import nis +raise support.TestSkipped("test_nis hangs on Solaris") + class NisTests(unittest.TestCase): def test_maps(self): try: From python-3000-checkins at python.org Wed Aug 20 01:30:42 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Wed, 20 Aug 2008 01:30:42 +0200 (CEST) Subject: [Python-3000-checkins] r65890 - python/branches/py3k Message-ID: <20080819233042.8003C1E4006@bag.python.org> Author: amaury.forgeotdarc Date: Wed Aug 20 01:30:42 2008 New Revision: 65890 Log: Blocked revisions 65016 via svnmerge ........ r65016 | jesse.noller | 2008-07-16 16:32:36 +0200 (mer., 16 juil. 2008) | 2 lines Apply Amaury's patch to multiprocessing for issue 3125, removes the copy_reg and replaces it with ForkingPickler.register(), which should resolve the conflict with the global registry/ctypes ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Wed Aug 20 03:51:11 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Wed, 20 Aug 2008 03:51:11 +0200 (CEST) Subject: [Python-3000-checkins] r65895 - python/branches/py3k Message-ID: <20080820015111.161A71E4006@bag.python.org> Author: benjamin.peterson Date: Wed Aug 20 03:51:10 2008 New Revision: 65895 Log: Blocked revisions 65806,65880,65891,65893 via svnmerge ........ r65806 | marc-andre.lemburg | 2008-08-18 06:13:45 -0500 (Mon, 18 Aug 2008) | 3 lines Restore Python 2.3 compatibility and remove "with" usage. ........ r65880 | guido.van.rossum | 2008-08-19 16:02:04 -0500 (Tue, 19 Aug 2008) | 2 lines Issue 1179: [CVE-2007-4965] Integer overflow in imageop module. ........ r65891 | amaury.forgeotdarc | 2008-08-19 19:08:47 -0500 (Tue, 19 Aug 2008) | 2 lines follow-up of issue3473: update the compiler package to recognize the new syntax. ........ r65893 | benjamin.peterson | 2008-08-19 20:42:01 -0500 (Tue, 19 Aug 2008) | 1 line deprecate some useless, noop methods in symtable ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Wed Aug 20 04:00:15 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Wed, 20 Aug 2008 04:00:15 +0200 (CEST) Subject: [Python-3000-checkins] r65896 - in python/branches/py3k: Doc/library/symtable.rst Lib/symtable.py Misc/NEWS Message-ID: <20080820020015.477CC1E4006@bag.python.org> Author: benjamin.peterson Date: Wed Aug 20 04:00:14 2008 New Revision: 65896 Log: kill the obsolete symtable.Symbol methods Modified: python/branches/py3k/Doc/library/symtable.rst python/branches/py3k/Lib/symtable.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/symtable.rst ============================================================================== --- python/branches/py3k/Doc/library/symtable.rst (original) +++ python/branches/py3k/Doc/library/symtable.rst Wed Aug 20 04:00:14 2008 @@ -144,15 +144,6 @@ Return ``True`` if the symbol is global. - .. method:: is_vararg() - - Return ``True`` if the symbol is a star arg (receives varargs). - - .. method:: is_kewordarg() - - Return ``True`` if the symbol is a two-star arg (receives keyword - arguments). - .. method:: is_local() Return ``True`` if the symbol is local to its block. Modified: python/branches/py3k/Lib/symtable.py ============================================================================== --- python/branches/py3k/Lib/symtable.py (original) +++ python/branches/py3k/Lib/symtable.py Wed Aug 20 04:00:14 2008 @@ -2,7 +2,6 @@ import _symtable from _symtable import (USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM, - DEF_STAR, DEF_DOUBLESTAR, DEF_INTUPLE, DEF_FREE, DEF_FREE_GLOBAL, DEF_FREE_CLASS, DEF_IMPORT, DEF_BOUND, OPT_IMPORT_STAR, SCOPE_OFF, SCOPE_MASK, FREE, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT) @@ -193,12 +192,6 @@ def is_global(self): return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)) - def is_vararg(self): - return bool(self.__flags & DEF_STAR) - - def is_keywordarg(self): - return bool(self.__flags & DEF_DOUBLESTAR) - def is_local(self): return bool(self.__flags & DEF_BOUND) @@ -211,9 +204,6 @@ def is_assigned(self): return bool(self.__flags & DEF_LOCAL) - def is_in_tuple(self): - return bool(self.__flags & DEF_INTUPLE) - def is_namespace(self): """Returns true if name binding introduces new namespace. Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Aug 20 04:00:14 2008 @@ -249,6 +249,9 @@ Library ------- +- The methods ``is_in_tuple()``, ``is_vararg()``, and ``is_keywordarg()`` of + symtable.Symbol have been removed. + - Patch #3133: http.server.CGIHTTPRequestHandler did not work on windows. - a new ``urllib`` package was created. It consists of code from From python-3000-checkins at python.org Wed Aug 20 04:06:00 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Wed, 20 Aug 2008 04:06:00 +0200 (CEST) Subject: [Python-3000-checkins] r65897 - in python/branches/py3k: Doc/library/symtable.rst Lib/symtable.py Lib/test/test_symtable.py Misc/NEWS Message-ID: <20080820020600.8D77B1E4006@bag.python.org> Author: benjamin.peterson Date: Wed Aug 20 04:06:00 2008 New Revision: 65897 Log: return sets instead of tuples from some symtable methods Modified: python/branches/py3k/Doc/library/symtable.rst python/branches/py3k/Lib/symtable.py python/branches/py3k/Lib/test/test_symtable.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/symtable.rst ============================================================================== --- python/branches/py3k/Doc/library/symtable.rst (original) +++ python/branches/py3k/Doc/library/symtable.rst Wed Aug 20 04:06:00 2008 @@ -95,19 +95,19 @@ .. method:: get_parameters() - Return a tuple containing names of parameters to this function. + Return a set containing names of parameters to this function. .. method:: get_locals() - Return a tuple containing names of locals in this function. + Return a set containing names of locals in this function. .. method:: get_globals() - Return a tuple containing names of globals in this function. + Return a set containing names of globals in this function. .. method:: get_frees() - Return a tuple containing names of free variables in this function. + Return a set containing names of free variables in this function. .. class:: Class @@ -116,7 +116,7 @@ .. method:: get_methods() - Return a tuple containing the names of methods declared in the class. + Return a set containing the names of methods declared in the class. .. class:: Symbol Modified: python/branches/py3k/Lib/symtable.py ============================================================================== --- python/branches/py3k/Lib/symtable.py (original) +++ python/branches/py3k/Lib/symtable.py Wed Aug 20 04:06:00 2008 @@ -129,8 +129,8 @@ __globals = None def __idents_matching(self, test_func): - return tuple([ident for ident in self.get_identifiers() - if test_func(self._table.symbols[ident])]) + return frozenset(ident for ident in self.get_identifiers() + if test_func(self._table.symbols[ident])) def get_parameters(self): if self.__params is None: @@ -165,7 +165,7 @@ d = {} for st in self._table.children: d[st.name] = 1 - self.__methods = tuple(d) + self.__methods = frozenset(d) return self.__methods Modified: python/branches/py3k/Lib/test/test_symtable.py ============================================================================== --- python/branches/py3k/Lib/test/test_symtable.py (original) +++ python/branches/py3k/Lib/test/test_symtable.py Wed Aug 20 04:06:00 2008 @@ -80,11 +80,11 @@ def test_function_info(self): func = self.spam - self.assertEqual(func.get_parameters(), ("a", "b", "kw", "var")) + self.assertEqual(func.get_parameters(), {"a", "b", "kw", "var"}) self.assertEqual(func.get_locals(), - ("a", "b", "bar", "glob", "internal", "kw", "var", "x")) - self.assertEqual(func.get_globals(), ("bar", "glob")) - self.assertEqual(self.internal.get_frees(), ("x",)) + {"a", "b", "bar", "glob", "internal", "kw", "var", "x"}) + self.assertEqual(func.get_globals(), {"bar", "glob"}) + self.assertEqual(self.internal.get_frees(), {"x"}) def test_globals(self): self.assertTrue(self.spam.lookup("glob").is_global()) @@ -142,7 +142,7 @@ self.assertEqual(self.Mine.get_name(), "Mine") def test_class_info(self): - self.assertEqual(self.Mine.get_methods(), ('a_method',)) + self.assertEqual(self.Mine.get_methods(), {'a_method'}) def test_filename_correct(self): ### Bug tickler: SyntaxError file name correct whether error raised Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Aug 20 04:06:00 2008 @@ -249,6 +249,9 @@ Library ------- +- symtable.Function's ``get_locals()``, ``get_globals()``, ``get_parameters()``, + and ``get_frees()`` and symtable.Class's ``get_methods()`` now return sets. + - The methods ``is_in_tuple()``, ``is_vararg()``, and ``is_keywordarg()`` of symtable.Symbol have been removed. From python-3000-checkins at python.org Wed Aug 20 04:33:00 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Wed, 20 Aug 2008 04:33:00 +0200 (CEST) Subject: [Python-3000-checkins] r65899 - in python/branches/py3k: Lib/symtable.py Lib/test/test_parser.py Message-ID: <20080820023300.65FD41E4006@bag.python.org> Author: benjamin.peterson Date: Wed Aug 20 04:33:00 2008 New Revision: 65899 Log: Merged revisions 65885,65892,65894,65898 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65885 | benjamin.peterson | 2008-08-19 17:06:11 -0500 (Tue, 19 Aug 2008) | 1 line check that the parser module can handle the new keyword syntax ........ r65892 | benjamin.peterson | 2008-08-19 20:27:30 -0500 (Tue, 19 Aug 2008) | 1 line add a NEWS note for new args syntax ........ r65894 | benjamin.peterson | 2008-08-19 20:44:45 -0500 (Tue, 19 Aug 2008) | 2 lines newSymbolTable is not public API ........ r65898 | benjamin.peterson | 2008-08-19 21:15:42 -0500 (Tue, 19 Aug 2008) | 1 line fix silly errors of mine ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/symtable.py python/branches/py3k/Lib/test/test_parser.py Modified: python/branches/py3k/Lib/symtable.py ============================================================================== --- python/branches/py3k/Lib/symtable.py (original) +++ python/branches/py3k/Lib/symtable.py Wed Aug 20 04:33:00 2008 @@ -8,15 +8,14 @@ import weakref -__all__ = ["symtable", "SymbolTable", "newSymbolTable", "Class", - "Function", "Symbol"] +__all__ = ["symtable", "SymbolTable", "Class", "Function", "Symbol"] def symtable(code, filename, compile_type): raw = _symtable.symtable(code, filename, compile_type) for top in raw.values(): if top.name == 'top': break - return newSymbolTable(top, filename) + return _newSymbolTable(top, filename) class SymbolTableFactory: def __init__(self): @@ -36,7 +35,7 @@ obj = self.__memo[key] = self.new(table, filename) return obj -newSymbolTable = SymbolTableFactory() +_newSymbolTable = SymbolTableFactory() class SymbolTable(object): @@ -111,12 +110,12 @@ return [self.lookup(ident) for ident in self.get_identifiers()] def __check_children(self, name): - return [newSymbolTable(st, self._filename) + return [_newSymbolTable(st, self._filename) for st in self._table.children if st.name == name] def get_children(self): - return [newSymbolTable(st, self._filename) + return [_newSymbolTable(st, self._filename) for st in self._table.children] Modified: python/branches/py3k/Lib/test/test_parser.py ============================================================================== --- python/branches/py3k/Lib/test/test_parser.py (original) +++ python/branches/py3k/Lib/test/test_parser.py Wed Aug 20 04:33:00 2008 @@ -66,6 +66,7 @@ self.check_expr("foo(a, b, c, *args)") self.check_expr("foo(a, b, c, *args, **kw)") self.check_expr("foo(a, b, c, **kw)") + self.check_expr("foo(a, *args, keyword=23)") self.check_expr("foo + bar") self.check_expr("foo - bar") self.check_expr("foo * bar") From python-3000-checkins at python.org Wed Aug 20 06:17:25 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Wed, 20 Aug 2008 06:17:25 +0200 (CEST) Subject: [Python-3000-checkins] r65901 - in python/branches/py3k: Lib/test/test_os.py Message-ID: <20080820041725.099261E4006@bag.python.org> Author: hirokazu.yamamoto Date: Wed Aug 20 06:17:24 2008 New Revision: 65901 Log: Merged revisions 65900 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65900 | hirokazu.yamamoto | 2008-08-20 13:13:28 +0900 | 1 line fixed get_file_system in test_os.py ('path' is unicode on py3k and ansi on trunk) ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_os.py Modified: python/branches/py3k/Lib/test/test_os.py ============================================================================== --- python/branches/py3k/Lib/test/test_os.py (original) +++ python/branches/py3k/Lib/test/test_os.py Wed Aug 20 06:17:24 2008 @@ -299,12 +299,15 @@ # systems support centiseconds if sys.platform == 'win32': def get_file_system(path): - import os - root = os.path.splitdrive(os.path.realpath("."))[0] + '\\' + root = os.path.splitdrive(os.path.abspath(path))[0] + '\\' import ctypes - kernel32 = ctypes.windll.kernel32 - buf = ctypes.create_string_buffer("", 100) - if kernel32.GetVolumeInformationA(root, None, 0, None, None, None, buf, len(buf)): + from ctypes.wintypes import LPCWSTR, LPWSTR, DWORD + LPDWORD = ctypes.POINTER(DWORD) + f = ctypes.windll.kernel32.GetVolumeInformationW + f.argtypes = (LPCWSTR, LPWSTR, DWORD, + LPDWORD, LPDWORD, LPDWORD, LPWSTR, DWORD) + buf = ctypes.create_unicode_buffer("", 100) + if f(root, None, 0, None, None, None, buf, len(buf)): return buf.value if get_file_system(support.TESTFN) == "NTFS": From python-3000-checkins at python.org Wed Aug 20 09:34:41 2008 From: python-3000-checkins at python.org (mark.summerfield) Date: Wed, 20 Aug 2008 09:34:41 +0200 (CEST) Subject: [Python-3000-checkins] r65903 - python/branches/py3k/Doc/library/re.rst Message-ID: <20080820073441.9D87F1E4006@bag.python.org> Author: mark.summerfield Date: Wed Aug 20 09:34:41 2008 New Revision: 65903 Log: Revised all texts concerning the ASCII flag: (1) put Unicode case first (since that's the default), (2) made all descriptions consistent, (3) dropped mention of re.LOCALE in most places since it is not recommended. Modified: python/branches/py3k/Doc/library/re.rst Modified: python/branches/py3k/Doc/library/re.rst ============================================================================== --- python/branches/py3k/Doc/library/re.rst (original) +++ python/branches/py3k/Doc/library/re.rst Wed Aug 20 09:34:41 2008 @@ -323,67 +323,78 @@ Matches only at the start of the string. ``\b`` - Matches the empty string, but only at the beginning or end of a word. A word is - defined as a sequence of alphanumeric or underscore characters, so the end of a - word is indicated by whitespace or a non-alphanumeric, non-underscore character. - Note that ``\b`` is defined as the boundary between ``\w`` and ``\ W``, so the - precise set of characters deemed to be alphanumeric depends on the values of the - ``ASCII`` and ``LOCALE`` flags. Inside a character range, ``\b`` represents - the backspace character, for compatibility with Python's string literals. + Matches the empty string, but only at the beginning or end of a word. + A word is defined as a sequence of Unicode alphanumeric or underscore + characters, so the end of a word is indicated by whitespace or a + non-alphanumeric, non-underscore Unicode character. Note that + formally, ``\b`` is defined as the boundary between a ``\w`` and a + ``\W`` character (or vice versa). By default Unicode alphanumerics + are the ones used, but this can be changed by using the :const:`ASCII` + flag. Inside a character range, ``\b`` represents the backspace + character, for compatibility with Python's string literals. ``\B`` Matches the empty string, but only when it is *not* at the beginning or end of a - word. This is just the opposite of ``\b``, so is also subject to the settings - of ``ASCII`` and ``LOCALE`` . + word. This is just the opposite of ``\b``, so word characters are + Unicode alphanumerics or the underscore, although this can be changed + by using the :const:`ASCII` flag. ``\d`` For Unicode (str) patterns: - When the :const:`ASCII` flag is specified, matches any decimal digit; this - is equivalent to the set ``[0-9]``. Otherwise, it will match whatever - is classified as a digit in the Unicode character properties database - (but this does include the standard ASCII digits and is thus a superset - of [0-9]). + Matches any Unicode digit (which includes ``[0-9]``, and also many + other digit characters). If the :const:`ASCII` flag is used only + ``[0-9]`` is matched (but the flag affects the entire regular + expression, so in such cases using an explicit ``[0-9]`` may be a + better choice). For 8-bit (bytes) patterns: - Matches any decimal digit; this is equivalent to the set ``[0-9]``. + Matches any decimal digit; this is equivalent to ``[0-9]``. ``\D`` - Matches any character which is not a decimal digit. This is the - opposite of ``\d`` and is therefore similarly subject to the settings of - ``ASCII`` and ``LOCALE``. + Matches any character which is not a Unicode decimal digit. This is + the opposite of ``\d``. If the :const:`ASCII` flag is used this + becomes the equivalent of ``[^0-9]`` (but the flag affects the entire + regular expression, so in such cases using an explicit ``[^0-9]`` may + be a better choice). ``\s`` For Unicode (str) patterns: - When the :const:`ASCII` flag is specified, matches only ASCII whitespace - characters; this is equivalent to the set ``[ \t\n\r\f\v]``. Otherwise, - it will match this set whatever is classified as space in the Unicode - character properties database (including for example the non-breaking - spaces mandated by typography rules in many languages). + Matches Unicode whitespace characters (which includes + ``[ \t\n\r\f\v]``, and also many other characters, for example the + non-breaking spaces mandated by typography rules in many + languages). If the :const:`ASCII` flag is used, only + ``[ \t\n\r\f\v]`` is matched (but the flag affects the entire + regular expression, so in such cases using an explicit + ``[ \t\n\r\f\v]`` may be a better choice). + For 8-bit (bytes) patterns: Matches characters considered whitespace in the ASCII character set; - this is equivalent to the set ``[ \t\n\r\f\v]``. + this is equivalent to ``[ \t\n\r\f\v]``. ``\S`` - Matches any character which is not a whitespace character. This is the - opposite of ``\s`` and is therefore similarly subject to the settings of - ``ASCII`` and ``LOCALE``. + Matches any character which is not a Unicode whitespace character. This is + the opposite of ``\s``. If the :const:`ASCII` flag is used this + becomes the equivalent of ``[^ \t\n\r\f\v]`` (but the flag affects the entire + regular expression, so in such cases using an explicit ``[^ \t\n\r\f\v]`` may + be a better choice). ``\w`` For Unicode (str) patterns: - When the :const:`ASCII` flag is specified, this is equivalent to the set - ``[a-zA-Z0-9_]``. Otherwise, it will match whatever is classified as - alphanumeric in the Unicode character properties database (it will - include most characters that can be part of a word in whatever language, - as well as numbers and the underscore sign). + Matches Unicode word characters; this includes most characters + that can be part of a word in any language, as well as numbers and + the underscore. If the :const:`ASCII` flag is used, only + ``[a-zA-Z0-9_]`` is matched (but the flag affects the entire + regular expression, so in such cases using an explicit + ``[a-zA-Z0-9_]`` may be a better choice). For 8-bit (bytes) patterns: Matches characters considered alphanumeric in the ASCII character set; - this is equivalent to the set ``[a-zA-Z0-9_]``. With :const:`LOCALE`, - it will additionally match whatever characters are defined as - alphanumeric for the current locale. + this is equivalent to ``[a-zA-Z0-9_]``. ``\W`` - Matches any character which is not an alphanumeric character. This is the - opposite of ``\w`` and is therefore similarly subject to the settings of - ``ASCII`` and ``LOCALE``. + Matches any character which is not a Unicode word character. This is + the opposite of ``\w``. If the :const:`ASCII` flag is used this + becomes the equivalent of ``[^a-zA-Z0-9_]`` (but the flag affects the + entire regular expression, so in such cases using an explicit + ``[^a-zA-Z0-9_]`` may be a better choice). ``\Z`` Matches only at the end of the string. @@ -471,17 +482,12 @@ matching instead of full Unicode matching. This is only meaningful for Unicode patterns, and is ignored for byte patterns. - Note that the :const:`re.U` flag still exists (as well as its synonym - :const:`re.UNICODE` and its embedded counterpart ``(?u)``), but it has - become useless in Python 3.0. - In previous Python versions, it was used to specify that - matching had to be Unicode dependent (the default was ASCII matching in - all circumstances). Starting from Python 3.0, the default is Unicode - matching for Unicode strings (which can be changed by specifying the - ``'a'`` flag), and ASCII matching for 8-bit strings. Further, Unicode - dependent matching for 8-bit strings isn't allowed anymore and results - in a ValueError. - + Note that for backward compatibility, the :const:`re.U` flag still + exists (as well as its synonym :const:`re.UNICODE` and its embedded + counterpart ``(?u)``), but these are redundant in Python 3.0 since + matches are Unicode by default for strings (and Unicode matching + isn't allowed for bytes). + .. data:: I IGNORECASE From python-3000-checkins at python.org Wed Aug 20 09:40:18 2008 From: python-3000-checkins at python.org (mark.summerfield) Date: Wed, 20 Aug 2008 09:40:18 +0200 (CEST) Subject: [Python-3000-checkins] r65904 - python/branches/py3k/Doc/library/re.rst Message-ID: <20080820074018.8D7E01E400D@bag.python.org> Author: mark.summerfield Date: Wed Aug 20 09:40:18 2008 New Revision: 65904 Log: Tiny fix of IGNORECASE plus removal of a UNICODE reference. Modified: python/branches/py3k/Doc/library/re.rst Modified: python/branches/py3k/Doc/library/re.rst ============================================================================== --- python/branches/py3k/Doc/library/re.rst (original) +++ python/branches/py3k/Doc/library/re.rst Wed Aug 20 09:40:18 2008 @@ -173,11 +173,11 @@ ``'m'``, or ``'$'``; ``[a-z]`` will match any lowercase letter, and ``[a-zA-Z0-9]`` matches any letter or digit. Character classes such as ``\w`` or ``\S`` (defined below) are also acceptable inside a - range, although the characters they match depends on whether :const:`LOCALE` - or :const:`UNICODE` mode is in force. If you want to include a - ``']'`` or a ``'-'`` inside a set, precede it with a backslash, or - place it as the first character. The pattern ``[]]`` will match - ``']'``, for example. + range, although the characters they match depends on whether + :const:`ASCII` or :const:`LOCALE` mode is in force. If you want to + include a ``']'`` or a ``'-'`` inside a set, precede it with a + backslash, or place it as the first character. The pattern ``[]]`` + will match ``']'``, for example. You can match the characters not within a range by :dfn:`complementing` the set. This is indicated by including a ``'^'`` as the first character of the set; @@ -493,7 +493,8 @@ IGNORECASE Perform case-insensitive matching; expressions like ``[A-Z]`` will match - lowercase letters, too. This is not affected by the current locale. + lowercase letters, too. This is not affected by the current locale + and works for Unicode characters as expected. .. data:: L From python-3000-checkins at python.org Wed Aug 20 10:58:41 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Wed, 20 Aug 2008 10:58:41 +0200 (CEST) Subject: [Python-3000-checkins] r65905 - python/branches/py3k/Lib/multiprocessing/managers.py Message-ID: <20080820085841.0D43B1E4006@bag.python.org> Author: amaury.forgeotdarc Date: Wed Aug 20 10:58:40 2008 New Revision: 65905 Log: Partially revert r65883 to let the tests pass. I am working on the proper fix, which is to use the custom pickler in connection.send(), instead of the standard pickle.dumps(). Modified: python/branches/py3k/Lib/multiprocessing/managers.py Modified: python/branches/py3k/Lib/multiprocessing/managers.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/managers.py (original) +++ python/branches/py3k/Lib/multiprocessing/managers.py Wed Aug 20 10:58:40 2008 @@ -45,6 +45,8 @@ return list, (list(obj),) for view_type in view_types: ForkingPickler.register(view_type, rebuild_as_list) + import copyreg + copyreg.pickle(view_type, rebuild_as_list) # # Type for identifying shared objects From python-3000-checkins at python.org Wed Aug 20 11:04:46 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Wed, 20 Aug 2008 11:04:46 +0200 (CEST) Subject: [Python-3000-checkins] r65906 - python/branches/py3k/Lib/multiprocessing/process.py Message-ID: <20080820090446.8234A1E4006@bag.python.org> Author: amaury.forgeotdarc Date: Wed Aug 20 11:04:46 2008 New Revision: 65906 Log: For some reason sys.stdin may be None on Windows, and makes test_multiprocessing fail. Since we are closing the fileno anyway, the best is to skip this part. Now test_multiprocessing should pass on Windows. Modified: python/branches/py3k/Lib/multiprocessing/process.py Modified: python/branches/py3k/Lib/multiprocessing/process.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/process.py (original) +++ python/branches/py3k/Lib/multiprocessing/process.py Wed Aug 20 11:04:46 2008 @@ -219,10 +219,11 @@ try: self._children = set() self._counter = itertools.count(1) - try: - os.close(sys.stdin.fileno()) - except (OSError, ValueError): - pass + if sys.stdin is not None: + try: + os.close(sys.stdin.fileno()) + except (OSError, ValueError): + pass _current_process = self util._finalizer_registry.clear() util._run_after_forkers() From ncoghlan at gmail.com Wed Aug 20 11:24:39 2008 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 20 Aug 2008 19:24:39 +1000 Subject: [Python-3000-checkins] r65852 - python/branches/py3k/Lib/test/test_threading.py In-Reply-To: <1afaf6160808191147j23bd200fm7196f8dc57d33fdf@mail.gmail.com> References: <20080819143256.E7EC61E4006@bag.python.org> <1afaf6160808191147j23bd200fm7196f8dc57d33fdf@mail.gmail.com> Message-ID: <48ABE2D7.9060500@gmail.com> Benjamin Peterson wrote: > On Tue, Aug 19, 2008 at 1:38 PM, Brett Cannon wrote: >> Isn't testing warnings fun? =) > > Infuriatingly so... Something I found interesting - the "multiple warnings" feature I initially added to catch_warning() solely in response to an external request, actually turned out to be necessary to test the Py3k warnings for the __hash__ changes (since a single class definition can emit multiple warnings). Just think how hard this would all be if Brett hadn't added the original version of that context manager :) Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org From ncoghlan at gmail.com Wed Aug 20 11:29:50 2008 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 20 Aug 2008 19:29:50 +1000 Subject: [Python-3000-checkins] r65862 - in python/branches/py3k: Include/memoryobject.h Misc/NEWS Modules/_json.c Objects/memoryobject.c Objects/unicodeobject.c In-Reply-To: <20080819182214.8BB641E4006@bag.python.org> References: <20080819182214.8BB641E4006@bag.python.org> Message-ID: <48ABE40E.2060001@gmail.com> antoine.pitrou wrote: > +/* The struct is declared here so that macros can work, but it shouldn't > + be considered public. Don't access those fields directly, use the macros > + and functions instead! */ > +typedef struct { > + PyObject_HEAD > + PyObject *base; > + Py_buffer view; > +} PyMemoryViewObject; If we don't want people to use this struct directly, we should start the name with an underscore. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org From ncoghlan at gmail.com Wed Aug 20 11:36:25 2008 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 20 Aug 2008 19:36:25 +1000 Subject: [Python-3000-checkins] r65897 - in python/branches/py3k: Doc/library/symtable.rst Lib/symtable.py Lib/test/test_symtable.py Misc/NEWS In-Reply-To: <20080820020600.8D77B1E4006@bag.python.org> References: <20080820020600.8D77B1E4006@bag.python.org> Message-ID: <48ABE599.3080709@gmail.com> benjamin.peterson wrote: > Author: benjamin.peterson > Date: Wed Aug 20 04:06:00 2008 > New Revision: 65897 > > Log: > return sets instead of tuples from some symtable methods What are you gaining by throwing away the ordering information? That can matter, especially for the parameters. If the symtable module itself has already thrown away the ordering information by this point, then that in itself is probably a bug to be fixed. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org From solipsis at pitrou.net Wed Aug 20 12:27:42 2008 From: solipsis at pitrou.net (Antoine Pitrou) Date: Wed, 20 Aug 2008 10:27:42 +0000 (UTC) Subject: [Python-3000-checkins] =?utf-8?q?r65862_-_in_python/branches/py3k?= =?utf-8?q?=3A=09Include/memoryobject=2Eh_Misc/NEWS_Modules/=5Fjson?= =?utf-8?q?=2Ec=09Objects/memoryobject=2Ec_Objects/unicodeobject=2E?= =?utf-8?q?c?= References: <20080819182214.8BB641E4006@bag.python.org> <48ABE40E.2060001@gmail.com> Message-ID: Nick Coghlan gmail.com> writes: > > antoine.pitrou wrote: > > +/* The struct is declared here so that macros can work, but it shouldn't > > + be considered public. Don't access those fields directly, use the macros > > + and functions instead! */ > > +typedef struct { > > + PyObject_HEAD > > + PyObject *base; > > + Py_buffer view; > > +} PyMemoryViewObject; > > If we don't want people to use this struct directly, we should start the > name with an underscore. Well, they can use it as an opaque pointer (PyMemoryViewObject *), just not access the fields directly. I don't know what the convention should be in that case, but feel free to make the necessary changes. cheers Antoine. From ncoghlan at gmail.com Wed Aug 20 12:38:17 2008 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 20 Aug 2008 20:38:17 +1000 Subject: [Python-3000-checkins] r65862 - in python/branches/py3k: Include/memoryobject.h Misc/NEWS Modules/_json.c Objects/memoryobject.c Objects/unicodeobject.c In-Reply-To: References: <20080819182214.8BB641E4006@bag.python.org> <48ABE40E.2060001@gmail.com> Message-ID: <48ABF419.50406@gmail.com> Antoine Pitrou wrote: > Nick Coghlan gmail.com> writes: >> antoine.pitrou wrote: >>> +/* The struct is declared here so that macros can work, but it shouldn't >>> + be considered public. Don't access those fields directly, use the macros >>> + and functions instead! */ >>> +typedef struct { >>> + PyObject_HEAD >>> + PyObject *base; >>> + Py_buffer view; >>> +} PyMemoryViewObject; >> If we don't want people to use this struct directly, we should start the >> name with an underscore. > > Well, they can use it as an opaque pointer (PyMemoryViewObject *), just not > access the fields directly. I don't know what the convention should be in that > case, but feel free to make the necessary changes. Ah, good point. What has been implemented seems fine then. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org From musiccomposition at gmail.com Wed Aug 20 14:44:01 2008 From: musiccomposition at gmail.com (Benjamin Peterson) Date: Wed, 20 Aug 2008 07:44:01 -0500 Subject: [Python-3000-checkins] r65897 - in python/branches/py3k: Doc/library/symtable.rst Lib/symtable.py Lib/test/test_symtable.py Misc/NEWS In-Reply-To: <48ABE599.3080709@gmail.com> References: <20080820020600.8D77B1E4006@bag.python.org> <48ABE599.3080709@gmail.com> Message-ID: <1afaf6160808200544i60198a9bg3c273c32fe527fb3@mail.gmail.com> On Wed, Aug 20, 2008 at 4:36 AM, Nick Coghlan wrote: > benjamin.peterson wrote: >> Author: benjamin.peterson >> Date: Wed Aug 20 04:06:00 2008 >> New Revision: 65897 >> >> Log: >> return sets instead of tuples from some symtable methods > > What are you gaining by throwing away the ordering information? That can > matter, especially for the parameters. If the symtable module itself has > already thrown away the ordering information by this point, then that in > itself is probably a bug to be fixed.' That's a good point. Consider it reverted. > > Cheers, > Nick. > > -- > Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia > --------------------------------------------------------------- > http://www.boredomandlaziness.org > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > -- Cheers, Benjamin Peterson "There's no place like 127.0.0.1." From python-3000-checkins at python.org Wed Aug 20 14:55:31 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Wed, 20 Aug 2008 14:55:31 +0200 (CEST) Subject: [Python-3000-checkins] r65907 - in python/branches/py3k: Doc/library/symtable.rst Lib/symtable.py Lib/test/test_symtable.py Misc/NEWS Message-ID: <20080820125531.E28F41E4006@bag.python.org> Author: benjamin.peterson Date: Wed Aug 20 14:55:31 2008 New Revision: 65907 Log: revert 65897 Modified: python/branches/py3k/Doc/library/symtable.rst python/branches/py3k/Lib/symtable.py python/branches/py3k/Lib/test/test_symtable.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Doc/library/symtable.rst ============================================================================== --- python/branches/py3k/Doc/library/symtable.rst (original) +++ python/branches/py3k/Doc/library/symtable.rst Wed Aug 20 14:55:31 2008 @@ -95,19 +95,19 @@ .. method:: get_parameters() - Return a set containing names of parameters to this function. + Return a tuple containing names of parameters to this function. .. method:: get_locals() - Return a set containing names of locals in this function. + Return a tuple containing names of locals in this function. .. method:: get_globals() - Return a set containing names of globals in this function. + Return a tuple containing names of globals in this function. .. method:: get_frees() - Return a set containing names of free variables in this function. + Return a tuple containing names of free variables in this function. .. class:: Class @@ -116,7 +116,7 @@ .. method:: get_methods() - Return a set containing the names of methods declared in the class. + Return a tuple containing the names of methods declared in the class. .. class:: Symbol Modified: python/branches/py3k/Lib/symtable.py ============================================================================== --- python/branches/py3k/Lib/symtable.py (original) +++ python/branches/py3k/Lib/symtable.py Wed Aug 20 14:55:31 2008 @@ -128,8 +128,8 @@ __globals = None def __idents_matching(self, test_func): - return frozenset(ident for ident in self.get_identifiers() - if test_func(self._table.symbols[ident])) + return tuple([ident for ident in self.get_identifiers() + if test_func(self._table.symbols[ident])]) def get_parameters(self): if self.__params is None: @@ -164,7 +164,7 @@ d = {} for st in self._table.children: d[st.name] = 1 - self.__methods = frozenset(d) + self.__methods = tuple(d) return self.__methods Modified: python/branches/py3k/Lib/test/test_symtable.py ============================================================================== --- python/branches/py3k/Lib/test/test_symtable.py (original) +++ python/branches/py3k/Lib/test/test_symtable.py Wed Aug 20 14:55:31 2008 @@ -80,11 +80,11 @@ def test_function_info(self): func = self.spam - self.assertEqual(func.get_parameters(), {"a", "b", "kw", "var"}) + self.assertEqual(func.get_parameters(), ("a", "b", "kw", "var")) self.assertEqual(func.get_locals(), - {"a", "b", "bar", "glob", "internal", "kw", "var", "x"}) - self.assertEqual(func.get_globals(), {"bar", "glob"}) - self.assertEqual(self.internal.get_frees(), {"x"}) + ("a", "b", "bar", "glob", "internal", "kw", "var", "x")) + self.assertEqual(func.get_globals(), ("bar", "glob")) + self.assertEqual(self.internal.get_frees(), ("x",)) def test_globals(self): self.assertTrue(self.spam.lookup("glob").is_global()) @@ -142,7 +142,7 @@ self.assertEqual(self.Mine.get_name(), "Mine") def test_class_info(self): - self.assertEqual(self.Mine.get_methods(), {'a_method'}) + self.assertEqual(self.Mine.get_methods(), ('a_method',)) def test_filename_correct(self): ### Bug tickler: SyntaxError file name correct whether error raised Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Aug 20 14:55:31 2008 @@ -249,9 +249,6 @@ Library ------- -- symtable.Function's ``get_locals()``, ``get_globals()``, ``get_parameters()``, - and ``get_frees()`` and symtable.Class's ``get_methods()`` now return sets. - - The methods ``is_in_tuple()``, ``is_vararg()``, and ``is_keywordarg()`` of symtable.Symbol have been removed. From python-3000-checkins at python.org Wed Aug 20 15:42:16 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Wed, 20 Aug 2008 15:42:16 +0200 (CEST) Subject: [Python-3000-checkins] r65909 - in python/branches/py3k: Lib/ctypes/wintypes.py Message-ID: <20080820134216.7048B1E4006@bag.python.org> Author: hirokazu.yamamoto Date: Wed Aug 20 15:42:16 2008 New Revision: 65909 Log: Merged revisions 65908 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65908 | hirokazu.yamamoto | 2008-08-20 22:14:07 +0900 | 1 line Issue #3612: Added some missing basic types in ctypes.wintypes. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/ctypes/wintypes.py Modified: python/branches/py3k/Lib/ctypes/wintypes.py ============================================================================== --- python/branches/py3k/Lib/ctypes/wintypes.py (original) +++ python/branches/py3k/Lib/ctypes/wintypes.py Wed Aug 20 15:42:16 2008 @@ -7,8 +7,10 @@ WCHAR = c_wchar UINT = c_uint +INT = c_int DOUBLE = c_double +FLOAT = c_float BOOLEAN = BYTE BOOL = c_long @@ -22,6 +24,9 @@ ULONG = c_ulong LONG = c_long +USHORT = c_ushort +SHORT = c_short + # in the windows header files, these are structures. _LARGE_INTEGER = LARGE_INTEGER = c_longlong _ULARGE_INTEGER = ULARGE_INTEGER = c_ulonglong @@ -29,6 +34,7 @@ LPCOLESTR = LPOLESTR = OLESTR = c_wchar_p LPCWSTR = LPWSTR = c_wchar_p LPCSTR = LPSTR = c_char_p +LPCVOID = LPVOID = c_void_p # WPARAM is defined as UINT_PTR (unsigned type) # LPARAM is defined as LONG_PTR (signed type) @@ -157,18 +163,19 @@ ("cFileName", c_wchar * MAX_PATH), ("cAlternateFileName", c_wchar * 14)] -__all__ = ['ATOM', 'BOOL', 'BOOLEAN', 'BYTE', 'COLORREF', 'DOUBLE', - 'DWORD', 'FILETIME', 'HACCEL', 'HANDLE', 'HBITMAP', 'HBRUSH', +__all__ = ['ATOM', 'BOOL', 'BOOLEAN', 'BYTE', 'COLORREF', 'DOUBLE', 'DWORD', + 'FILETIME', 'FLOAT', 'HACCEL', 'HANDLE', 'HBITMAP', 'HBRUSH', 'HCOLORSPACE', 'HDC', 'HDESK', 'HDWP', 'HENHMETAFILE', 'HFONT', 'HGDIOBJ', 'HGLOBAL', 'HHOOK', 'HICON', 'HINSTANCE', 'HKEY', 'HKL', 'HLOCAL', 'HMENU', 'HMETAFILE', 'HMODULE', 'HMONITOR', 'HPALETTE', 'HPEN', 'HRGN', 'HRSRC', 'HSTR', 'HTASK', 'HWINSTA', - 'HWND', 'LANGID', 'LARGE_INTEGER', 'LCID', 'LCTYPE', 'LGRPID', - 'LONG', 'LPARAM', 'LPCOLESTR', 'LPCSTR', 'LPCWSTR', 'LPOLESTR', - 'LPSTR', 'LPWSTR', 'MAX_PATH', 'MSG', 'OLESTR', 'POINT', - 'POINTL', 'RECT', 'RECTL', 'RGB', 'SC_HANDLE', - 'SERVICE_STATUS_HANDLE', 'SIZE', 'SIZEL', 'SMALL_RECT', 'UINT', - 'ULARGE_INTEGER', 'ULONG', 'VARIANT_BOOL', 'WCHAR', - 'WIN32_FIND_DATAA', 'WIN32_FIND_DATAW', 'WORD', 'WPARAM', '_COORD', - '_FILETIME', '_LARGE_INTEGER', '_POINTL', '_RECTL', '_SMALL_RECT', - '_ULARGE_INTEGER', 'tagMSG', 'tagPOINT', 'tagRECT', 'tagSIZE'] + 'HWND', 'INT', 'LANGID', 'LARGE_INTEGER', 'LCID', 'LCTYPE', + 'LGRPID', 'LONG', 'LPARAM', 'LPCOLESTR', 'LPCSTR', 'LPCVOID', + 'LPCWSTR', 'LPOLESTR', 'LPSTR', 'LPVOID', 'LPWSTR', 'MAX_PATH', + 'MSG', 'OLESTR', 'POINT', 'POINTL', 'RECT', 'RECTL', 'RGB', + 'SC_HANDLE', 'SERVICE_STATUS_HANDLE', 'SHORT', 'SIZE', 'SIZEL', + 'SMALL_RECT', 'UINT', 'ULARGE_INTEGER', 'ULONG', 'USHORT', + 'VARIANT_BOOL', 'WCHAR', 'WIN32_FIND_DATAA', 'WIN32_FIND_DATAW', + 'WORD', 'WPARAM', '_COORD', '_FILETIME', '_LARGE_INTEGER', + '_POINTL', '_RECTL', '_SMALL_RECT', '_ULARGE_INTEGER', 'tagMSG', + 'tagPOINT', 'tagRECT', 'tagSIZE'] From python-3000-checkins at python.org Wed Aug 20 16:59:21 2008 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 20 Aug 2008 16:59:21 +0200 (CEST) Subject: [Python-3000-checkins] r65913 - python/branches/py3k Message-ID: <20080820145921.177171E4006@bag.python.org> Author: guido.van.rossum Date: Wed Aug 20 16:59:20 2008 New Revision: 65913 Log: Blocked revisions 65912 via svnmerge ........ r65912 | guido.van.rossum | 2008-08-20 07:57:20 -0700 (Wed, 20 Aug 2008) | 2 lines News for the imageop fix. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Wed Aug 20 17:02:34 2008 From: python-3000-checkins at python.org (guido.van.rossum) Date: Wed, 20 Aug 2008 17:02:34 +0200 (CEST) Subject: [Python-3000-checkins] r65915 - python/branches/py3k Message-ID: <20080820150234.AC99F1E4012@bag.python.org> Author: guido.van.rossum Date: Wed Aug 20 17:02:34 2008 New Revision: 65915 Log: Blocked revisions 65914 via svnmerge ........ r65914 | guido.van.rossum | 2008-08-20 08:01:50 -0700 (Wed, 20 Aug 2008) | 2 lines News for the tp_flags change. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Wed Aug 20 18:18:19 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Wed, 20 Aug 2008 18:18:19 +0200 (CEST) Subject: [Python-3000-checkins] r65918 - python/branches/py3k/Lib/test/test_os.py Message-ID: <20080820161819.8FBE31E4006@bag.python.org> Author: hirokazu.yamamoto Date: Wed Aug 20 18:18:19 2008 New Revision: 65918 Log: Reverted r65901 and uses GetVolumeInformationW because string in py3k is unicode. See http://mail.python.org/pipermail/python-checkins/2008-August/073116.html Modified: python/branches/py3k/Lib/test/test_os.py Modified: python/branches/py3k/Lib/test/test_os.py ============================================================================== --- python/branches/py3k/Lib/test/test_os.py (original) +++ python/branches/py3k/Lib/test/test_os.py Wed Aug 20 18:18:19 2008 @@ -301,13 +301,9 @@ def get_file_system(path): root = os.path.splitdrive(os.path.abspath(path))[0] + '\\' import ctypes - from ctypes.wintypes import LPCWSTR, LPWSTR, DWORD - LPDWORD = ctypes.POINTER(DWORD) - f = ctypes.windll.kernel32.GetVolumeInformationW - f.argtypes = (LPCWSTR, LPWSTR, DWORD, - LPDWORD, LPDWORD, LPDWORD, LPWSTR, DWORD) + kernel32 = ctypes.windll.kernel32 buf = ctypes.create_unicode_buffer("", 100) - if f(root, None, 0, None, None, None, buf, len(buf)): + if kernel32.GetVolumeInformationW(root, None, 0, None, None, None, buf, len(buf)): return buf.value if get_file_system(support.TESTFN) == "NTFS": From python-3000-checkins at python.org Wed Aug 20 18:20:46 2008 From: python-3000-checkins at python.org (hirokazu.yamamoto) Date: Wed, 20 Aug 2008 18:20:46 +0200 (CEST) Subject: [Python-3000-checkins] r65919 - python/branches/py3k Message-ID: <20080820162046.AC4261E4006@bag.python.org> Author: hirokazu.yamamoto Date: Wed Aug 20 18:20:46 2008 New Revision: 65919 Log: Blocked revisions 65917 via svnmerge ........ r65917 | hirokazu.yamamoto | 2008-08-21 01:15:28 +0900 | 1 line Reverted r65900. See http://mail.python.org/pipermail/python-checkins/2008-August/073116.html ........ Modified: python/branches/py3k/ (props changed) From g.brandl at gmx.net Wed Aug 20 23:00:03 2008 From: g.brandl at gmx.net (Georg Brandl) Date: Wed, 20 Aug 2008 23:00:03 +0200 Subject: [Python-3000-checkins] r65862 - in python/branches/py3k: Include/memoryobject.h Misc/NEWS Modules/_json.c Objects/memoryobject.c Objects/unicodeobject.c In-Reply-To: References: <20080819182214.8BB641E4006@bag.python.org> <48ABE40E.2060001@gmail.com> Message-ID: Antoine Pitrou schrieb: > Nick Coghlan gmail.com> writes: >> >> antoine.pitrou wrote: >> > +/* The struct is declared here so that macros can work, but it shouldn't >> > + be considered public. Don't access those fields directly, use the macros >> > + and functions instead! */ >> > +typedef struct { >> > + PyObject_HEAD >> > + PyObject *base; >> > + Py_buffer view; >> > +} PyMemoryViewObject; >> >> If we don't want people to use this struct directly, we should start the >> name with an underscore. > > Well, they can use it as an opaque pointer (PyMemoryViewObject *), just not > access the fields directly. I don't know what the convention should be in that > case, but feel free to make the necessary changes. Well, logically it would be field names starting with underscores. Just kidding, Georg From python-3000-checkins at python.org Wed Aug 20 23:35:51 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Wed, 20 Aug 2008 23:35:51 +0200 (CEST) Subject: [Python-3000-checkins] r65920 - in python/branches/py3k: Lib/xmlrpc/client.py Misc/NEWS Message-ID: <20080820213551.2DA521E4006@bag.python.org> Author: amaury.forgeotdarc Date: Wed Aug 20 23:35:50 2008 New Revision: 65920 Log: #3614: Correct a typo in xmlrpc.client. Modified: python/branches/py3k/Lib/xmlrpc/client.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/xmlrpc/client.py ============================================================================== --- python/branches/py3k/Lib/xmlrpc/client.py (original) +++ python/branches/py3k/Lib/xmlrpc/client.py Wed Aug 20 23:35:50 2008 @@ -1203,7 +1203,7 @@ headers = {} if extra_headers: for key, val in extra_headers: - header[key] = val + headers[key] = val headers["Content-Type"] = "text/xml" headers["User-Agent"] = self.user_agent connection.request("POST", handler, request_body, headers) @@ -1271,7 +1271,7 @@ headers = {} if extra_headers: for key, val in extra_headers: - header[key] = val + headers[key] = val headers["Content-Type"] = "text/xml" headers["User-Agent"] = self.user_agent connection.request("POST", handler, request_body, headers) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Aug 20 23:35:50 2008 @@ -46,6 +46,9 @@ Library ------- +- Issue #3614: Corrected a typo in xmlrpc.client, leading to a NameError + "global name 'header' is not defined". + - Issue #2834: update the regular expression library to match the unicode standards of py3k. In other words, mixing bytes and unicode strings (be it as pattern, search string or replacement string) raises a TypeError. From python-3000-checkins at python.org Thu Aug 21 01:23:35 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Thu, 21 Aug 2008 01:23:35 +0200 (CEST) Subject: [Python-3000-checkins] r65921 - in python/branches/py3k: Lib/test/test_exceptions.py Python/ceval.c Message-ID: <20080820232335.6BF4E1E400A@bag.python.org> Author: benjamin.peterson Date: Thu Aug 21 01:23:34 2008 New Revision: 65921 Log: apply a fix for #3611 where the current exception context was deleted with a generator causing a segfault Modified: python/branches/py3k/Lib/test/test_exceptions.py python/branches/py3k/Python/ceval.c Modified: python/branches/py3k/Lib/test/test_exceptions.py ============================================================================== --- python/branches/py3k/Lib/test/test_exceptions.py (original) +++ python/branches/py3k/Lib/test/test_exceptions.py Thu Aug 21 01:23:34 2008 @@ -564,6 +564,28 @@ pass self.assertEquals(e, (None, None, None)) + def test_3118(self): + def gen(): + try: + yield 1 + finally: + pass + + def f(): + g = gen() + next(g) + try: + try: + raise ValueError + except: + del g + raise KeyError + except Exception as e: + self.assert_(isinstance(e.__context__, ValueError)) + + f() + + def test_badisinstance(self): # Bug #2542: if issubclass(e, MyException) raises an exception, # it should be ignored Modified: python/branches/py3k/Python/ceval.c ============================================================================== --- python/branches/py3k/Python/ceval.c (original) +++ python/branches/py3k/Python/ceval.c Thu Aug 21 01:23:34 2008 @@ -2453,7 +2453,7 @@ if (b->b_type == EXCEPT_HANDLER) { UNWIND_EXCEPT_HANDLER(b); - if (why == WHY_EXCEPTION) { + if (why == WHY_EXCEPTION && !throwflag) { Py_CLEAR(tstate->exc_type); Py_CLEAR(tstate->exc_value); Py_CLEAR(tstate->exc_traceback); From python-3000-checkins at python.org Thu Aug 21 03:28:07 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Thu, 21 Aug 2008 03:28:07 +0200 (CEST) Subject: [Python-3000-checkins] r65924 - python/branches/py3k-grandrenaming Message-ID: <20080821012807.875AE1E4006@bag.python.org> Author: benjamin.peterson Date: Thu Aug 21 03:28:07 2008 New Revision: 65924 Log: kill an old branch Removed: python/branches/py3k-grandrenaming/ From python-3000-checkins at python.org Thu Aug 21 04:39:52 2008 From: python-3000-checkins at python.org (barry.warsaw) Date: Thu, 21 Aug 2008 04:39:52 +0200 (CEST) Subject: [Python-3000-checkins] r65927 - in python/branches/py3k: Include/patchlevel.h Lib/distutils/__init__.py Lib/idlelib/idlever.py Misc/NEWS Misc/RPM/python-3.0.spec README RELNOTES Message-ID: <20080821023952.32F401E401A@bag.python.org> Author: barry.warsaw Date: Thu Aug 21 04:39:51 2008 New Revision: 65927 Log: Bumping to 3.0b3 Modified: python/branches/py3k/Include/patchlevel.h python/branches/py3k/Lib/distutils/__init__.py python/branches/py3k/Lib/idlelib/idlever.py python/branches/py3k/Misc/NEWS python/branches/py3k/Misc/RPM/python-3.0.spec python/branches/py3k/README python/branches/py3k/RELNOTES Modified: python/branches/py3k/Include/patchlevel.h ============================================================================== --- python/branches/py3k/Include/patchlevel.h (original) +++ python/branches/py3k/Include/patchlevel.h Thu Aug 21 04:39:51 2008 @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 0 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 2 +#define PY_RELEASE_SERIAL 3 /* Version as a string */ -#define PY_VERSION "3.0b2+" +#define PY_VERSION "3.0b3" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ Modified: python/branches/py3k/Lib/distutils/__init__.py ============================================================================== --- python/branches/py3k/Lib/distutils/__init__.py (original) +++ python/branches/py3k/Lib/distutils/__init__.py Thu Aug 21 04:39:51 2008 @@ -20,5 +20,5 @@ # #--start constants-- -__version__ = "3.0b2" +__version__ = "3.0b3" #--end constants-- Modified: python/branches/py3k/Lib/idlelib/idlever.py ============================================================================== --- python/branches/py3k/Lib/idlelib/idlever.py (original) +++ python/branches/py3k/Lib/idlelib/idlever.py Thu Aug 21 04:39:51 2008 @@ -1 +1 @@ -IDLE_VERSION = "3.0b2" +IDLE_VERSION = "3.0b3" Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Aug 21 04:39:51 2008 @@ -7,7 +7,7 @@ What's new in Python 3.0b3? =========================== -*Release date: XX-XXX-2008* +*Release date: 20-Aug-2008* Core and Builtins ----------------- Modified: python/branches/py3k/Misc/RPM/python-3.0.spec ============================================================================== --- python/branches/py3k/Misc/RPM/python-3.0.spec (original) +++ python/branches/py3k/Misc/RPM/python-3.0.spec Thu Aug 21 04:39:51 2008 @@ -34,7 +34,7 @@ %define name python #--start constants-- -%define version 3.0b2 +%define version 3.0b3 %define libver 3.0 #--end constants-- %define release 1pydotorg Modified: python/branches/py3k/README ============================================================================== --- python/branches/py3k/README (original) +++ python/branches/py3k/README Thu Aug 21 04:39:51 2008 @@ -1,4 +1,4 @@ -This is Python version 3.0 beta 2 +This is Python version 3.0 beta 3 ================================= For notes specific to this release, see RELNOTES in this directory. Modified: python/branches/py3k/RELNOTES ============================================================================== --- python/branches/py3k/RELNOTES (original) +++ python/branches/py3k/RELNOTES Thu Aug 21 04:39:51 2008 @@ -6,6 +6,12 @@ Please report bugs to http://bugs.python.org/. +Version 3.0b3 - Release Date 20-Aug-2008 +---------------------------------------- + +Please search the bug tracker for critical issues in Python 3.0. + + Version 3.0b2 - Release Date 17-Jul-2008 ---------------------------------------- From python-3000-checkins at python.org Thu Aug 21 05:02:47 2008 From: python-3000-checkins at python.org (barry.warsaw) Date: Thu, 21 Aug 2008 05:02:47 +0200 (CEST) Subject: [Python-3000-checkins] r65929 - in python/branches/py3k: Include/patchlevel.h Misc/NEWS Message-ID: <20080821030247.7B6231E4006@bag.python.org> Author: barry.warsaw Date: Thu Aug 21 05:02:47 2008 New Revision: 65929 Log: done with 3.0 Modified: python/branches/py3k/Include/patchlevel.h python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Include/patchlevel.h ============================================================================== --- python/branches/py3k/Include/patchlevel.h (original) +++ python/branches/py3k/Include/patchlevel.h Thu Aug 21 05:02:47 2008 @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 3 /* Version as a string */ -#define PY_VERSION "3.0b3" +#define PY_VERSION "3.0b3+" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository) */ Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Thu Aug 21 05:02:47 2008 @@ -4,6 +4,18 @@ (editors: check NEWS.help for information about editing NEWS using ReST.) +What's New in Python 3.0 release candidate 1 +============================================ + +*Release date: XX-XXXX-2008* + +Core and Builtins +----------------- + +Library +------- + + What's new in Python 3.0b3? =========================== From ncoghlan at gmail.com Thu Aug 21 12:28:19 2008 From: ncoghlan at gmail.com (Nick Coghlan) Date: Thu, 21 Aug 2008 20:28:19 +1000 Subject: [Python-3000-checkins] r65862 - in python/branches/py3k: Include/memoryobject.h Misc/NEWS Modules/_json.c Objects/memoryobject.c Objects/unicodeobject.c In-Reply-To: References: <20080819182214.8BB641E4006@bag.python.org> <48ABE40E.2060001@gmail.com> Message-ID: <48AD4343.7010202@gmail.com> Georg Brandl wrote: > Antoine Pitrou schrieb: >> Well, they can use it as an opaque pointer (PyMemoryViewObject *), just not >> access the fields directly. I don't know what the convention should be in that >> case, but feel free to make the necessary changes. > > Well, logically it would be field names starting with underscores. > > Just kidding, Heh, I almost wrote the same thing, but I stopped myself. That way lies madness :) Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org From python-3000-checkins at python.org Thu Aug 21 18:51:16 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Thu, 21 Aug 2008 18:51:16 +0200 (CEST) Subject: [Python-3000-checkins] r65932 - python/branches/py3k/Doc/c-api/object.rst Message-ID: <20080821165116.3CE7D1E4008@bag.python.org> Author: benjamin.peterson Date: Thu Aug 21 18:51:15 2008 New Revision: 65932 Log: PyObject_Unicode doesn't exist anymore Modified: python/branches/py3k/Doc/c-api/object.rst Modified: python/branches/py3k/Doc/c-api/object.rst ============================================================================== --- python/branches/py3k/Doc/c-api/object.rst (original) +++ python/branches/py3k/Doc/c-api/object.rst Thu Aug 21 18:51:15 2008 @@ -140,16 +140,6 @@ and, therefore, by the :func:`print` function. -.. cfunction:: PyObject* PyObject_Unicode(PyObject *o) - - .. index:: builtin: unicode - - Compute a Unicode string representation of object *o*. Returns the Unicode - string representation on success, *NULL* on failure. This is the equivalent of - the Python expression ``unicode(o)``. Called by the :func:`unicode` built-in - function. - - .. cfunction:: int PyObject_IsInstance(PyObject *inst, PyObject *cls) Returns ``1`` if *inst* is an instance of the class *cls* or a subclass of From python-3000-checkins at python.org Thu Aug 21 19:00:40 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Thu, 21 Aug 2008 19:00:40 +0200 (CEST) Subject: [Python-3000-checkins] r65933 - in python/branches/py3k/Lib/test: test_exceptions.py test_raise.py Message-ID: <20080821170040.AF26A1E4007@bag.python.org> Author: benjamin.peterson Date: Thu Aug 21 19:00:40 2008 New Revision: 65933 Log: move test to a better location Modified: python/branches/py3k/Lib/test/test_exceptions.py python/branches/py3k/Lib/test/test_raise.py Modified: python/branches/py3k/Lib/test/test_exceptions.py ============================================================================== --- python/branches/py3k/Lib/test/test_exceptions.py (original) +++ python/branches/py3k/Lib/test/test_exceptions.py Thu Aug 21 19:00:40 2008 @@ -564,27 +564,6 @@ pass self.assertEquals(e, (None, None, None)) - def test_3118(self): - def gen(): - try: - yield 1 - finally: - pass - - def f(): - g = gen() - next(g) - try: - try: - raise ValueError - except: - del g - raise KeyError - except Exception as e: - self.assert_(isinstance(e.__context__, ValueError)) - - f() - def test_badisinstance(self): # Bug #2542: if issubclass(e, MyException) raises an exception, Modified: python/branches/py3k/Lib/test/test_raise.py ============================================================================== --- python/branches/py3k/Lib/test/test_raise.py (original) +++ python/branches/py3k/Lib/test/test_raise.py Thu Aug 21 19:00:40 2008 @@ -302,6 +302,28 @@ except NameError as e: self.failUnless(e.__context__.__context__ is None) + def test_3118(self): + # deleting the generator caused the __context__ to be cleared + def gen(): + try: + yield 1 + finally: + pass + + def f(): + g = gen() + next(g) + try: + try: + raise ValueError + except: + del g + raise KeyError + except Exception as e: + self.assert_(isinstance(e.__context__, ValueError)) + + f() + class TestRemovedFunctionality(unittest.TestCase): def test_tuples(self): From python-3000-checkins at python.org Thu Aug 21 22:05:57 2008 From: python-3000-checkins at python.org (mark.dickinson) Date: Thu, 21 Aug 2008 22:05:57 +0200 (CEST) Subject: [Python-3000-checkins] r65959 - in python/branches/py3k: Lib/test/test_float.py Message-ID: <20080821200557.09B6E1E4007@bag.python.org> Author: mark.dickinson Date: Thu Aug 21 22:05:56 2008 New Revision: 65959 Log: Merged revisions 65958 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65958 | mark.dickinson | 2008-08-21 21:02:24 +0100 (Thu, 21 Aug 2008) | 5 lines Fix float.fromhex test to give additional information on failure. This change is aimed at diagnosing issue 3633 (test_float fails on Solaris). Reviewed by Benjamin Peterson ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_float.py Modified: python/branches/py3k/Lib/test/test_float.py ============================================================================== --- python/branches/py3k/Lib/test/test_float.py (original) +++ python/branches/py3k/Lib/test/test_float.py Thu Aug 21 22:05:56 2008 @@ -448,7 +448,13 @@ '0x1p0\0 0x1p0', # embedded null byte is not end of string ] for x in invalid_inputs: - self.assertRaises(ValueError, fromHex, x) + try: + result = fromHex(x) + except ValueError: + pass + else: + self.fail('Expected float.fromhex(%r) to raise ValueError; ' + 'got %r instead' % (x, result)) def test_from_hex(self): From python-3000-checkins at python.org Thu Aug 21 23:40:15 2008 From: python-3000-checkins at python.org (mark.dickinson) Date: Thu, 21 Aug 2008 23:40:15 +0200 (CEST) Subject: [Python-3000-checkins] r65965 - in python/branches/py3k: Objects/floatobject.c Message-ID: <20080821214015.9C1181E4007@bag.python.org> Author: mark.dickinson Date: Thu Aug 21 23:40:15 2008 New Revision: 65965 Log: Merged revisions 65964 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65964 | mark.dickinson | 2008-08-21 22:38:38 +0100 (Thu, 21 Aug 2008) | 7 lines issue 3633: Solaris allows fullwidth Unicode digits in isxdigit, so rewrite float.fromhex to only allow ASCII hex digits on all platforms. (Tests for this are already present, but the test_float failures on Solaris hadn't been noticed before.) Reviewed by Antoine Pitrou. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Objects/floatobject.c Modified: python/branches/py3k/Objects/floatobject.c ============================================================================== --- python/branches/py3k/Objects/floatobject.c (original) +++ python/branches/py3k/Objects/floatobject.c Thu Aug 21 23:40:15 2008 @@ -1041,7 +1041,6 @@ static int hex_from_char(char c) { int x; - assert(isxdigit(c)); switch(c) { case '0': x = 0; @@ -1271,12 +1270,12 @@ /* coefficient: [. ] */ coeff_start = s; - while (isxdigit(*s)) + while (hex_from_char(*s) >= 0) s++; s_store = s; if (*s == '.') { s++; - while (isxdigit(*s)) + while (hex_from_char(*s) >= 0) s++; coeff_end = s-1; } @@ -1298,10 +1297,10 @@ exp_start = s; if (*s == '-' || *s == '+') s++; - if (!isdigit(*s)) + if (!('0' <= *s && *s <= '9')) goto parse_error; s++; - while (isdigit(*s)) + while ('0' <= *s && *s <= '9') s++; exp = strtol(exp_start, NULL, 10); } From python-3000-checkins at python.org Fri Aug 22 02:57:25 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Fri, 22 Aug 2008 02:57:25 +0200 (CEST) Subject: [Python-3000-checkins] r65969 - python/branches/py3k Message-ID: <20080822005725.371961E4007@bag.python.org> Author: benjamin.peterson Date: Fri Aug 22 02:57:24 2008 New Revision: 65969 Log: Blocked revisions 65922,65926 via svnmerge ........ r65922 | barry.warsaw | 2008-08-20 20:15:08 -0500 (Wed, 20 Aug 2008) | 2 lines Bump to 2.6b3. ........ r65926 | barry.warsaw | 2008-08-20 21:12:56 -0500 (Wed, 20 Aug 2008) | 1 line done with the release ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Fri Aug 22 10:27:53 2008 From: python-3000-checkins at python.org (robert.schuppenies) Date: Fri, 22 Aug 2008 10:27:53 +0200 (CEST) Subject: [Python-3000-checkins] r65973 - in python/branches/py3k: Lib/tkinter/__init__.py Message-ID: <20080822082753.B5A471E4007@bag.python.org> Author: robert.schuppenies Date: Fri Aug 22 10:27:53 2008 New Revision: 65973 Log: Merged revisions 65971 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65971 | robert.schuppenies | 2008-08-22 10:03:43 +0200 (Fri, 22 Aug 2008) | 2 lines Issue #1342811: Fixed broken patch. Reviewed by benjamin.peterson. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/tkinter/__init__.py Modified: python/branches/py3k/Lib/tkinter/__init__.py ============================================================================== --- python/branches/py3k/Lib/tkinter/__init__.py (original) +++ python/branches/py3k/Lib/tkinter/__init__.py Fri Aug 22 10:27:53 2008 @@ -2654,11 +2654,13 @@ if index2 is None: index2 = index1 cmds = [] - for i in range(self.index(index1), self.index(index2)+1): - if 'command' in self.entryconfig(i): - c = str(self.entrycget(i, 'command')) - if c in self._tclCommands: - cmds.append(c) + (num_index1, num_index2) = (self.index(index1), self.index(index2)) + if (num_index1 is not None) and (num_index2 is not None): + for i in range(num_index1, num_index2 + 1): + if 'command' in self.entryconfig(i): + c = str(self.entrycget(i, 'command')) + if c in self._tclCommands: + cmds.append(c) self.tk.call(self._w, 'delete', index1, index2) for c in cmds: self.deletecommand(c) From python-3000-checkins at python.org Fri Aug 22 21:38:46 2008 From: python-3000-checkins at python.org (christian.heimes) Date: Fri, 22 Aug 2008 21:38:46 +0200 (CEST) Subject: [Python-3000-checkins] r65976 - in python/branches/py3k: Objects/obmalloc.c Message-ID: <20080822193846.0B9CE1E4002@bag.python.org> Author: christian.heimes Date: Fri Aug 22 21:38:45 2008 New Revision: 65976 Log: Merged revisions 65975 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65975 | christian.heimes | 2008-08-22 21:34:15 +0200 (Fri, 22 Aug 2008) | 1 line Changed type of numarenas from uint to size_t to silence a GCC warning on 64bit OSes. Reviewed by Benjamin Peterson. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Objects/obmalloc.c Modified: python/branches/py3k/Objects/obmalloc.c ============================================================================== --- python/branches/py3k/Objects/obmalloc.c (original) +++ python/branches/py3k/Objects/obmalloc.c Fri Aug 22 21:38:45 2008 @@ -517,7 +517,7 @@ #endif if (unused_arena_objects == NULL) { uint i; - uint numarenas; + size_t numarenas; size_t nbytes; /* Double the number of arena objects on each allocation. From python-3000-checkins at python.org Fri Aug 22 21:56:47 2008 From: python-3000-checkins at python.org (christian.heimes) Date: Fri, 22 Aug 2008 21:56:47 +0200 (CEST) Subject: [Python-3000-checkins] r65979 - in python/branches/py3k: Modules/_sqlite/row.c Message-ID: <20080822195647.A0F761E4012@bag.python.org> Author: christian.heimes Date: Fri Aug 22 21:56:47 2008 New Revision: 65979 Log: Merged revisions 65978 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65978 | christian.heimes | 2008-08-22 21:55:54 +0200 (Fri, 22 Aug 2008) | 3 lines Silenced a compiler warning in the sqlite module Modules/_sqlite/row.c:187: warning: suggest parentheses around && within || Reviewed by Benjamin Peterson ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Modules/_sqlite/row.c Modified: python/branches/py3k/Modules/_sqlite/row.c ============================================================================== --- python/branches/py3k/Modules/_sqlite/row.c (original) +++ python/branches/py3k/Modules/_sqlite/row.c Fri Aug 22 21:56:47 2008 @@ -178,8 +178,8 @@ if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) { pysqlite_Row *other = (pysqlite_Row *)_other; PyObject *res = PyObject_RichCompare(self->description, other->description, opid); - if (opid == Py_EQ && res == Py_True - || opid == Py_NE && res == Py_False) { + if ((opid == Py_EQ && res == Py_True) + || (opid == Py_NE && res == Py_False)) { Py_DECREF(res); return PyObject_RichCompare(self->data, other->data, opid); } From python-3000-checkins at python.org Fri Aug 22 22:50:59 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Fri, 22 Aug 2008 22:50:59 +0200 (CEST) Subject: [Python-3000-checkins] r65983 - python/branches/py3k Message-ID: <20080822205059.4AFFA1E4002@bag.python.org> Author: benjamin.peterson Date: Fri Aug 22 22:50:59 2008 New Revision: 65983 Log: Merged revisions 65982 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65982 | benjamin.peterson | 2008-08-22 15:43:48 -0500 (Fri, 22 Aug 2008) | 4 lines fix a few get_name() calls and turn then to .name Reviewer: Christian Heimes ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 23 00:05:21 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Sat, 23 Aug 2008 00:05:21 +0200 (CEST) Subject: [Python-3000-checkins] r65985 - in python/branches/py3k: Misc/NEWS Objects/bytesobject.c Message-ID: <20080822220521.52DE41E4002@bag.python.org> Author: amaury.forgeotdarc Date: Sat Aug 23 00:05:20 2008 New Revision: 65985 Log: #3650: fix a reference leak in bytes.split('x') Actually the same as r65785, but trunk only has bytearray. Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/bytesobject.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Aug 23 00:05:20 2008 @@ -12,6 +12,8 @@ Core and Builtins ----------------- +- Issue #3650: Fixed a reference leak in bytes.split('x'). + Library ------- Modified: python/branches/py3k/Objects/bytesobject.c ============================================================================== --- python/branches/py3k/Objects/bytesobject.c (original) +++ python/branches/py3k/Objects/bytesobject.c Sat Aug 23 00:05:20 2008 @@ -1163,8 +1163,11 @@ PyBuffer_Release(&vsub); return NULL; } - else if (n == 1) - return split_char(self, len, sub[0], maxsplit); + else if (n == 1) { + list = split_char(self, len, sub[0], maxsplit); + PyBuffer_Release(&vsub); + return list; + } list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) { @@ -1379,8 +1382,11 @@ PyBuffer_Release(&vsub); return NULL; } - else if (n == 1) - return rsplit_char(self, len, sub[0], maxsplit); + else if (n == 1) { + list = rsplit_char(self, len, sub[0], maxsplit); + PyBuffer_Release(&vsub); + return list; + } list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) { From python-3000-checkins at python.org Sat Aug 23 10:03:04 2008 From: python-3000-checkins at python.org (hyeshik.chang) Date: Sat, 23 Aug 2008 10:03:04 +0200 (CEST) Subject: [Python-3000-checkins] r65988 - in python/branches/py3k: Lib/encodings/aliases.py Misc/NEWS Message-ID: <20080823080304.35D311E4009@bag.python.org> Author: hyeshik.chang Date: Sat Aug 23 10:03:03 2008 New Revision: 65988 Log: #1276: Add temporary encoding aliases for non-supported Mac CJK encodings that are detected as system defaults in MacOS with CJK locales. Will be replaced by properly-implemented codecs in 3.1. Modified: python/branches/py3k/Lib/encodings/aliases.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/encodings/aliases.py ============================================================================== --- python/branches/py3k/Lib/encodings/aliases.py (original) +++ python/branches/py3k/Lib/encodings/aliases.py Sat Aug 23 10:03:03 2008 @@ -519,4 +519,9 @@ #'zip' : 'zlib_codec', #'zlib' : 'zlib_codec', + # temporary mac CJK aliases, will be replaced by proper codecs in 3.1 + 'x_mac_japanese' : 'shift_jis', + 'x_mac_korean' : 'euc_kr', + 'x_mac_simp_chinese' : 'gb2312', + 'x_mac_trad_chinese' : 'big5', } Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Aug 23 10:03:03 2008 @@ -60,6 +60,12 @@ Library ------- +- Issue #1276: Added temporary aliases for CJK Mac encodings to resolve + a build problem on MacOS with CJK locales. It adds four temporary + mappings to existing legacy codecs that are virtually compatible + with Mac encodings. They will be replaced by codecs correctly + implemented in 3.1. + - Issue #3614: Corrected a typo in xmlrpc.client, leading to a NameError "global name 'header' is not defined". From python-3000-checkins at python.org Sat Aug 23 17:14:57 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sat, 23 Aug 2008 17:14:57 +0200 (CEST) Subject: [Python-3000-checkins] r65994 - python/branches/py3k/Doc/library/types.rst Message-ID: <20080823151457.9A4AA1E400A@bag.python.org> Author: georg.brandl Date: Sat Aug 23 17:14:57 2008 New Revision: 65994 Log: Remove outdated example from types module doc. Since the types left in the modules are obscure, I didn't add a substitute example. Modified: python/branches/py3k/Doc/library/types.rst Modified: python/branches/py3k/Doc/library/types.rst ============================================================================== --- python/branches/py3k/Doc/library/types.rst (original) +++ python/branches/py3k/Doc/library/types.rst Sat Aug 23 17:14:57 2008 @@ -1,4 +1,3 @@ - :mod:`types` --- Names for built-in types ========================================= @@ -7,41 +6,19 @@ This module defines names for some object types that are used by the standard -Python interpreter, but not for the types defined by various extension modules. -Also, it does not include some of the types that arise during processing such as -the ``listiterator`` type. New names exported by future versions of this module -will all end in ``Type``. - -Typical use is for functions that do different things depending on their -argument types, like the following:: - - from types import IntType - def delete(mylist, item): - if type(item) is IntType: - del mylist[item] - else: - mylist.remove(item) - -Starting in Python 2.2, built-in factory functions such as :func:`int` and -:func:`str` are also names for the corresponding types. This is now the -preferred way to access the type instead of using the :mod:`types` module. -Accordingly, the example above should be written as follows:: - - def delete(mylist, item): - if isinstance(item, int): - del mylist[item] - else: - mylist.remove(item) +Python interpreter, but not exposed as builtins like :class:`int` or +:class:`str` are. Also, it does not include some of the types that arise +transparently during processing such as the ``listiterator`` type. -Starting in Python 3.0 all types that are also available as builtins are no -longer exposed through the types module. +Typical use is for :func:`isinstance` or :func:`issubclass` checks. The module defines the following names: .. data:: FunctionType LambdaType - The type of user-defined functions and lambdas. + The type of user-defined functions and functions created by :keyword:`lambda` + expressions. .. data:: GeneratorType @@ -65,7 +42,9 @@ .. data:: BuiltinFunctionType BuiltinMethodType - The type of built-in functions like :func:`len` or :func:`sys.exit`. + The type of built-in functions like :func:`len` or :func:`sys.exit`, and + methods of built-in classes. (Here, the term "built-in" means "written in + C".) .. data:: ModuleType From python-3000-checkins at python.org Sat Aug 23 17:21:08 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sat, 23 Aug 2008 17:21:08 +0200 (CEST) Subject: [Python-3000-checkins] r65996 - python/branches/py3k Message-ID: <20080823152108.5B0CD1E400A@bag.python.org> Author: georg.brandl Date: Sat Aug 23 17:21:08 2008 New Revision: 65996 Log: Blocked revisions 65995 via svnmerge ........ r65995 | georg.brandl | 2008-08-23 17:15:31 +0200 (Sat, 23 Aug 2008) | 2 lines Small updates to types member docs, backport from r65994. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 23 22:08:07 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 23 Aug 2008 22:08:07 +0200 (CEST) Subject: [Python-3000-checkins] r65998 - python/branches/py3k/Python/pythonrun.c Message-ID: <20080823200807.A3D2B1E4003@bag.python.org> Author: benjamin.peterson Date: Sat Aug 23 22:08:07 2008 New Revision: 65998 Log: fix #3653 Python could segfault if invalid values were passed to sys.excepthook Author: Daniel Diniz Reviewer: Georg Brandl Modified: python/branches/py3k/Python/pythonrun.c Modified: python/branches/py3k/Python/pythonrun.c ============================================================================== --- python/branches/py3k/Python/pythonrun.c (original) +++ python/branches/py3k/Python/pythonrun.c Sat Aug 23 22:08:07 2008 @@ -1300,6 +1300,13 @@ int err = 0; PyObject *type, *tb; + if (!PyExceptionInstance_Check(value)) { + PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); + PyFile_WriteString(Py_TYPE(value)->tp_name, f); + PyFile_WriteString(" found\n", f); + return; + } + Py_INCREF(value); fflush(stdout); type = (PyObject *) Py_TYPE(value); From brett at python.org Sat Aug 23 22:07:58 2008 From: brett at python.org (Brett Cannon) Date: Sat, 23 Aug 2008 13:07:58 -0700 Subject: [Python-3000-checkins] r65988 - in python/branches/py3k: Lib/encodings/aliases.py Misc/NEWS In-Reply-To: <20080823080304.35D311E4009@bag.python.org> References: <20080823080304.35D311E4009@bag.python.org> Message-ID: On Sat, Aug 23, 2008 at 1:03 AM, hyeshik.chang wrote: > Author: hyeshik.chang > Date: Sat Aug 23 10:03:03 2008 > New Revision: 65988 > > Log: > #1276: Add temporary encoding aliases for non-supported Mac CJK > encodings that are detected as system defaults in MacOS with CJK > locales. Will be replaced by properly-implemented codecs in 3.1. > Did anybody review this? -Brett From nnorwitz at gmail.com Sat Aug 23 22:12:00 2008 From: nnorwitz at gmail.com (Neal Norwitz) Date: Sat, 23 Aug 2008 13:12:00 -0700 Subject: [Python-3000-checkins] r65998 - python/branches/py3k/Python/pythonrun.c In-Reply-To: <20080823200807.A3D2B1E4003@bag.python.org> References: <20080823200807.A3D2B1E4003@bag.python.org> Message-ID: How about a test and NEWS entry for this? On Sat, Aug 23, 2008 at 1:08 PM, benjamin.peterson wrote: > Author: benjamin.peterson > Date: Sat Aug 23 22:08:07 2008 > New Revision: 65998 > > Log: > fix #3653 Python could segfault if invalid values were passed to sys.excepthook > > Author: Daniel Diniz > Reviewer: Georg Brandl > > > Modified: > python/branches/py3k/Python/pythonrun.c > > Modified: python/branches/py3k/Python/pythonrun.c > ============================================================================== > --- python/branches/py3k/Python/pythonrun.c (original) > +++ python/branches/py3k/Python/pythonrun.c Sat Aug 23 22:08:07 2008 > @@ -1300,6 +1300,13 @@ > int err = 0; > PyObject *type, *tb; > > + if (!PyExceptionInstance_Check(value)) { > + PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); > + PyFile_WriteString(Py_TYPE(value)->tp_name, f); > + PyFile_WriteString(" found\n", f); > + return; > + } > + > Py_INCREF(value); > fflush(stdout); > type = (PyObject *) Py_TYPE(value); > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > From python-3000-checkins at python.org Sat Aug 23 22:19:17 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 23 Aug 2008 22:19:17 +0200 (CEST) Subject: [Python-3000-checkins] r65999 - in python/branches/py3k: Lib/test/test_sys.py Misc/NEWS Message-ID: <20080823201917.EC4691E4003@bag.python.org> Author: benjamin.peterson Date: Sat Aug 23 22:19:17 2008 New Revision: 65999 Log: add NEWS note and test for last commit Modified: python/branches/py3k/Lib/test/test_sys.py python/branches/py3k/Misc/NEWS Modified: python/branches/py3k/Lib/test/test_sys.py ============================================================================== --- python/branches/py3k/Lib/test/test_sys.py (original) +++ python/branches/py3k/Lib/test/test_sys.py Sat Aug 23 22:19:17 2008 @@ -62,6 +62,12 @@ self.assert_(err.getvalue().endswith("ValueError: 42\n")) + def test_excepthook(self): + with test.support.captured_output("stderr") as stderr: + sys.excepthook(1, '1', 1) + self.assert_("TypeError: print_exception(): Exception expected for " \ + "value, str found" in stderr.getvalue()) + # FIXME: testing the code for a lost or replaced excepthook in # Python/pythonrun.c::PyErr_PrintEx() is tricky. Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Aug 23 22:19:17 2008 @@ -26,6 +26,9 @@ Core and Builtins ----------------- +- Issue #3653: Fix a segfault when sys.excepthook was called with invalid + arguments. + - Issue #2394: implement more of the memoryview API, with the caveat that only one-dimensional contiguous buffers are supported and exercised right now. Slicing, slice assignment and comparison (equality and inequality) From python-3000-checkins at python.org Sat Aug 23 22:32:28 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 23 Aug 2008 22:32:28 +0200 (CEST) Subject: [Python-3000-checkins] r66001 - in python/branches/py3k: Misc/NEWS Modules/_testcapimodule.c Message-ID: <20080823203228.048451E4003@bag.python.org> Author: benjamin.peterson Date: Sat Aug 23 22:32:27 2008 New Revision: 66001 Log: #3643 add more checks to _testcapi to prevent segfaults Author: Victor Stinne Reviewer: Benjamin Peterson Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_testcapimodule.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sat Aug 23 22:32:27 2008 @@ -17,6 +17,12 @@ Library ------- +Extension Modules +----------------- + +- Issue #3643: Added a few more checks to _testcapi to prevent segfaults by + exploitation of poor argument checking. + What's new in Python 3.0b3? =========================== Modified: python/branches/py3k/Modules/_testcapimodule.c ============================================================================== --- python/branches/py3k/Modules/_testcapimodule.c (original) +++ python/branches/py3k/Modules/_testcapimodule.c Sat Aug 23 22:32:27 2008 @@ -961,6 +961,10 @@ if (!PyArg_ParseTuple(args, "O:exception_print", &value)) return NULL; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, "an exception instance is required"); + return NULL; + } tb = PyException_GetTraceback(value); PyErr_Display((PyObject *) Py_TYPE(value), value, tb); From python-3000-checkins at python.org Sat Aug 23 23:04:47 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 23 Aug 2008 23:04:47 +0200 (CEST) Subject: [Python-3000-checkins] r66002 - python/branches/py3k/Doc/c-api/file.rst Message-ID: <20080823210447.640011E4003@bag.python.org> Author: benjamin.peterson Date: Sat Aug 23 23:04:47 2008 New Revision: 66002 Log: bring the PyFile docs into sync with reality Modified: python/branches/py3k/Doc/c-api/file.rst Modified: python/branches/py3k/Doc/c-api/file.rst ============================================================================== --- python/branches/py3k/Doc/c-api/file.rst (original) +++ python/branches/py3k/Doc/c-api/file.rst Sat Aug 23 23:04:47 2008 @@ -9,32 +9,8 @@ Python's built-in file objects are implemented entirely on the :ctype:`FILE\*` support from the C standard library. This is an implementation detail and may -change in future releases of Python. - - -.. ctype:: PyFileObject - - This subtype of :ctype:`PyObject` represents a Python file object. - - -.. cvar:: PyTypeObject PyFile_Type - - .. index:: single: FileType (in module types) - - This instance of :ctype:`PyTypeObject` represents the Python file type. This is - exposed to Python programs as ``file`` and ``types.FileType``. - - -.. cfunction:: int PyFile_Check(PyObject *p) - - Return true if its argument is a :ctype:`PyFileObject` or a subtype of - :ctype:`PyFileObject`. - - -.. cfunction:: int PyFile_CheckExact(PyObject *p) - - Return true if its argument is a :ctype:`PyFileObject`, but not a subtype of - :ctype:`PyFileObject`. +change in future releases of Python. The ``PyFile_`` APIs are a wrapper over +the :mod:`io` module. .. cfunction:: PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding, char *newline, int closefd) @@ -74,39 +50,6 @@ raised if the end of the file is reached immediately. -.. cfunction:: PyObject* PyFile_Name(PyObject *p) - - Return the name of the file specified by *p* as a string object. - - -.. cfunction:: void PyFile_SetBufSize(PyFileObject *p, int n) - - .. index:: single: setvbuf() - - Available on systems with :cfunc:`setvbuf` only. This should only be called - immediately after file object creation. - - -.. cfunction:: int PyFile_SetEncoding(PyFileObject *p, const char *enc) - - Set the file's encoding for Unicode output to *enc*. Return 1 on success and 0 - on failure. - - -.. cfunction:: int PyFile_SoftSpace(PyObject *p, int newflag) - - .. index:: single: softspace (file attribute) - - This function exists for internal use by the interpreter. Set the - :attr:`softspace` attribute of *p* to *newflag* and return the previous value. - *p* does not have to be a file object for this function to work properly; any - object is supported (thought its only interesting if the :attr:`softspace` - attribute can be set). This function clears any errors, and will return ``0`` - as the previous value if the attribute either does not exist or if there were - errors in retrieving it. There is no way to detect errors from this function, - but doing so should not be needed. - - .. cfunction:: int PyFile_WriteObject(PyObject *obj, PyObject *p, int flags) .. index:: single: Py_PRINT_RAW From python-3000-checkins at python.org Sat Aug 23 23:48:02 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sat, 23 Aug 2008 23:48:02 +0200 (CEST) Subject: [Python-3000-checkins] r66005 - python/branches/py3k Message-ID: <20080823214802.466A41E4003@bag.python.org> Author: benjamin.peterson Date: Sat Aug 23 23:48:02 2008 New Revision: 66005 Log: Blocked revisions 66004 via svnmerge ........ r66004 | benjamin.peterson | 2008-08-23 16:40:15 -0500 (Sat, 23 Aug 2008) | 1 line fix warning ........ Modified: python/branches/py3k/ (props changed) From ncoghlan at gmail.com Sun Aug 24 05:19:28 2008 From: ncoghlan at gmail.com (Nick Coghlan) Date: Sun, 24 Aug 2008 13:19:28 +1000 Subject: [Python-3000-checkins] r65988 - in python/branches/py3k: Lib/encodings/aliases.py Misc/NEWS In-Reply-To: References: <20080823080304.35D311E4009@bag.python.org> Message-ID: <48B0D340.9020509@gmail.com> Brett Cannon wrote: > On Sat, Aug 23, 2008 at 1:03 AM, hyeshik.chang > wrote: >> Author: hyeshik.chang >> Date: Sat Aug 23 10:03:03 2008 >> New Revision: 65988 >> >> Log: >> #1276: Add temporary encoding aliases for non-supported Mac CJK >> encodings that are detected as system defaults in MacOS with CJK >> locales. Will be replaced by properly-implemented codecs in 3.1. >> > > Did anybody review this? Given the nature of the change, I think the mailing list discussion on the topic qualifies as reviewing it. Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org From python-3000-checkins at python.org Sun Aug 24 07:48:10 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Sun, 24 Aug 2008 07:48:10 +0200 (CEST) Subject: [Python-3000-checkins] r66007 - in python/branches/py3k: Lib/decimal.py Misc/NEWS Misc/valgrind-python.supp Modules/_ctypes/stgdict.c Modules/_fileio.c Modules/signalmodule.c Objects/stringlib/formatter.h Objects/structseq.c Python/getargs.c Message-ID: <20080824054810.E18311E401A@bag.python.org> Author: neal.norwitz Date: Sun Aug 24 07:48:10 2008 New Revision: 66007 Log: Merged revisions 66006 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk TESTED=./python -E -tt ./Lib/test/regrtest.py -uall (both debug and opt modes) ........ r66006 | neal.norwitz | 2008-08-23 22:04:52 -0700 (Sat, 23 Aug 2008) | 25 lines Fix: * crashes on memory allocation failure found with failmalloc * memory leaks found with valgrind * compiler warnings in opt mode which would lead to invalid memory reads * problem using wrong name in decimal module reported by pychecker Update the valgrind suppressions file with new leaks that are small/one-time leaks we don't care about (ie, they are too hard to fix). TBR=barry TESTED=./python -E -tt ./Lib/test/regrtest.py -uall (both debug and opt modes) in opt mode: valgrind -q --leak-check=yes --suppressions=Misc/valgrind-python.supp \ ./python -E -tt ./Lib/test/regrtest.py -uall,-bsddb,-compiler \ -x test_logging test_ssl test_multiprocessing valgrind -q --leak-check=yes --suppressions=Misc/valgrind-python.supp \ ./python -E -tt ./Lib/test/regrtest.py test_multiprocessing for i in `seq 1 4000` ; do LD_PRELOAD=~/local/lib/libfailmalloc.so FAILMALLOC_INTERVAL=$i \ ./python -c pass done At least some of these fixes should probably be backported to 2.5. ........ Modified: python/branches/py3k/Lib/decimal.py python/branches/py3k/Misc/NEWS python/branches/py3k/Misc/valgrind-python.supp python/branches/py3k/Modules/_ctypes/stgdict.c python/branches/py3k/Modules/_fileio.c python/branches/py3k/Modules/signalmodule.c python/branches/py3k/Objects/stringlib/formatter.h python/branches/py3k/Objects/structseq.c python/branches/py3k/Python/getargs.c Modified: python/branches/py3k/Lib/decimal.py ============================================================================== --- python/branches/py3k/Lib/decimal.py (original) +++ python/branches/py3k/Lib/decimal.py Sun Aug 24 07:48:10 2008 @@ -5147,7 +5147,7 @@ log_tenpower = f*M # exact else: log_d = 0 # error < 2.31 - log_tenpower = div_nearest(f, 10**-p) # error < 0.5 + log_tenpower = _div_nearest(f, 10**-p) # error < 0.5 return _div_nearest(log_tenpower+log_d, 100) Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 24 07:48:10 2008 @@ -12,6 +12,14 @@ Core and Builtins ----------------- +- Fix crashes on memory allocation failure found with failmalloc. + +- Fix memory leaks found with valgrind and update suppressions file. + +- Fix compiler warnings in opt mode which would lead to invalid memory reads. + +- Fix problem using wrong name in decimal module reported by pychecker. + - Issue #3650: Fixed a reference leak in bytes.split('x'). Library Modified: python/branches/py3k/Misc/valgrind-python.supp ============================================================================== --- python/branches/py3k/Misc/valgrind-python.supp (original) +++ python/branches/py3k/Misc/valgrind-python.supp Sun Aug 24 07:48:10 2008 @@ -47,6 +47,39 @@ # { + Suppress leaking the GIL. Happens once per process, see comment in ceval.c. + Memcheck:Leak + fun:malloc + fun:PyThread_allocate_lock + fun:PyEval_InitThreads +} + +{ + Suppress leaking the GIL after a fork. + Memcheck:Leak + fun:malloc + fun:PyThread_allocate_lock + fun:PyEval_ReInitThreads +} + +{ + Suppress leaking the autoTLSkey. This looks like it shouldn't leak though. + Memcheck:Leak + fun:malloc + fun:PyThread_create_key + fun:_PyGILState_Init + fun:Py_InitializeEx + fun:Py_Main +} + +{ + Hmmm, is this a real leak or like the GIL? + Memcheck:Leak + fun:malloc + fun:PyThread_ReInitTLS +} + +{ Handle PyMalloc confusing valgrind (possibly leaked) Memcheck:Leak fun:realloc Modified: python/branches/py3k/Modules/_ctypes/stgdict.c ============================================================================== --- python/branches/py3k/Modules/_ctypes/stgdict.c (original) +++ python/branches/py3k/Modules/_ctypes/stgdict.c Sun Aug 24 07:48:10 2008 @@ -408,6 +408,7 @@ ffi_ofs = 0; } + assert(stgdict->format == NULL); if (isStruct && !isPacked) { stgdict->format = alloc_format_string(NULL, "T{"); } else { @@ -527,7 +528,9 @@ #undef realdict if (isStruct && !isPacked) { + char *ptr = stgdict->format; stgdict->format = alloc_format_string(stgdict->format, "}"); + PyMem_Free(ptr); if (stgdict->format == NULL) return -1; } Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Sun Aug 24 07:48:10 2008 @@ -278,6 +278,7 @@ ret = -1; done: + PyMem_Free(name); return ret; } Modified: python/branches/py3k/Modules/signalmodule.c ============================================================================== --- python/branches/py3k/Modules/signalmodule.c (original) +++ python/branches/py3k/Modules/signalmodule.c Sun Aug 24 07:48:10 2008 @@ -796,7 +796,8 @@ #if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER) ItimerError = PyErr_NewException("signal.ItimerError", PyExc_IOError, NULL); - PyDict_SetItemString(d, "ItimerError", ItimerError); + if (ItimerError != NULL) + PyDict_SetItemString(d, "ItimerError", ItimerError); #endif if (PyErr_Occurred()) { Modified: python/branches/py3k/Objects/stringlib/formatter.h ============================================================================== --- python/branches/py3k/Objects/stringlib/formatter.h (original) +++ python/branches/py3k/Objects/stringlib/formatter.h Sun Aug 24 07:48:10 2008 @@ -641,7 +641,10 @@ /* We know this can't fail, since we've already reserved enough space. */ STRINGLIB_CHAR *pstart = p + n_leading_chars; - int r = STRINGLIB_GROUPING(pstart, n_digits, n_digits, +#ifndef NDEBUG + int r = +#endif + STRINGLIB_GROUPING(pstart, n_digits, n_digits, spec.n_total+n_grouping_chars-n_leading_chars, NULL, 0); assert(r); Modified: python/branches/py3k/Objects/structseq.c ============================================================================== --- python/branches/py3k/Objects/structseq.c (original) +++ python/branches/py3k/Objects/structseq.c Sun Aug 24 07:48:10 2008 @@ -32,6 +32,8 @@ PyStructSequence *obj; obj = PyObject_New(PyStructSequence, type); + if (obj == NULL) + return NULL; Py_SIZE(obj) = VISIBLE_SIZE_TP(type); return (PyObject*) obj; @@ -522,10 +524,16 @@ Py_INCREF(type); dict = type->tp_dict; - PyDict_SetItemString(dict, visible_length_key, - PyLong_FromLong((long) desc->n_in_sequence)); - PyDict_SetItemString(dict, real_length_key, - PyLong_FromLong((long) n_members)); - PyDict_SetItemString(dict, unnamed_fields_key, - PyLong_FromLong((long) n_unnamed_members)); +#define SET_DICT_FROM_INT(key, value) \ + do { \ + PyObject *v = PyLong_FromLong((long) value); \ + if (v != NULL) { \ + PyDict_SetItemString(dict, key, v); \ + Py_DECREF(v); \ + } \ + } while (0) + + SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence); + SET_DICT_FROM_INT(real_length_key, n_members); + SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members); } Modified: python/branches/py3k/Python/getargs.c ============================================================================== --- python/branches/py3k/Python/getargs.c (original) +++ python/branches/py3k/Python/getargs.c Sun Aug 24 07:48:10 2008 @@ -1354,7 +1354,7 @@ /* XXX for 3.x, getbuffer and convertbuffer can probably be merged again. */ static int -getbuffer(PyObject *arg, Py_buffer *view, char**errmsg) +getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { void *buf; Py_ssize_t count; @@ -1364,8 +1364,10 @@ return -1; } if (pb->bf_getbuffer) { - if (pb->bf_getbuffer(arg, view, 0) < 0) + if (pb->bf_getbuffer(arg, view, 0) < 0) { + *errmsg = "convertible to a buffer"; return -1; + } if (!PyBuffer_IsContiguous(view, 'C')) { *errmsg = "contiguous buffer"; return -1; @@ -1374,8 +1376,10 @@ } count = convertbuffer(arg, &buf, errmsg); - if (count < 0) + if (count < 0) { + *errmsg = "convertible to a buffer"; return count; + } PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); return 0; } From python-3000-checkins at python.org Sun Aug 24 07:54:11 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Sun, 24 Aug 2008 07:54:11 +0200 (CEST) Subject: [Python-3000-checkins] r66008 - python/branches/py3k Message-ID: <20080824055411.72C7A1E400A@bag.python.org> Author: neal.norwitz Date: Sun Aug 24 07:54:11 2008 New Revision: 66008 Log: Update props for r66007. Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 24 09:08:56 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Sun, 24 Aug 2008 09:08:56 +0200 (CEST) Subject: [Python-3000-checkins] r66009 - in python/branches/py3k: Lib/test/seq_tests.py Lib/test/support.py Lib/test/test_bigmem.py Misc/NEWS Modules/gcmodule.c Modules/mmapmodule.c Objects/bytearrayobject.c Objects/bytesobject.c Objects/longobject.c Objects/tupleobject.c Objects/unicodeobject.c Message-ID: <20080824070856.2D08C1E400A@bag.python.org> Author: neal.norwitz Date: Sun Aug 24 09:08:55 2008 New Revision: 66009 Log: Closes release blocker #3627. Merged revisions 65335 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk TESTED=./python -E -tt ./Lib/test/regrtest.py -uall (both debug and opt) ........ r65335 | neal.norwitz | 2008-07-31 10:17:14 -0700 (Thu, 31 Jul 2008) | 1 line Security patches from Apple: prevent int overflow when allocating memory ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/seq_tests.py python/branches/py3k/Lib/test/support.py python/branches/py3k/Lib/test/test_bigmem.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/gcmodule.c python/branches/py3k/Modules/mmapmodule.c python/branches/py3k/Objects/bytearrayobject.c python/branches/py3k/Objects/bytesobject.c python/branches/py3k/Objects/longobject.c python/branches/py3k/Objects/tupleobject.c python/branches/py3k/Objects/unicodeobject.c Modified: python/branches/py3k/Lib/test/seq_tests.py ============================================================================== --- python/branches/py3k/Lib/test/seq_tests.py (original) +++ python/branches/py3k/Lib/test/seq_tests.py Sun Aug 24 09:08:55 2008 @@ -304,11 +304,13 @@ self.assertEqual(id(s), id(s*1)) def test_bigrepeat(self): - x = self.type2test([0]) - x *= 2**16 - self.assertRaises(MemoryError, x.__mul__, 2**16) - if hasattr(x, '__imul__'): - self.assertRaises(MemoryError, x.__imul__, 2**16) + import sys + if sys.maxsize <= 2147483647: + x = self.type2test([0]) + x *= 2**16 + self.assertRaises(MemoryError, x.__mul__, 2**16) + if hasattr(x, '__imul__'): + self.assertRaises(MemoryError, x.__imul__, 2**16) def test_subscript(self): a = self.type2test([10, 11]) Modified: python/branches/py3k/Lib/test/support.py ============================================================================== --- python/branches/py3k/Lib/test/support.py (original) +++ python/branches/py3k/Lib/test/support.py Sun Aug 24 09:08:55 2008 @@ -68,6 +68,7 @@ use_resources = None # Flag set to [] by regrtest.py max_memuse = 0 # Disable bigmem tests (they will still be run with # small sizes, to make sure they work.) +real_max_memuse = 0 # _original_stdout is meant to hold stdout at the time regrtest began. # This may be "the real" stdout, or IDLE's emulation of stdout, or whatever. @@ -599,12 +600,14 @@ _1M = 1024*1024 _1G = 1024 * _1M _2G = 2 * _1G +_4G = 4 * _1G MAX_Py_ssize_t = sys.maxsize def set_memlimit(limit): import re global max_memuse + global real_max_memuse sizes = { 'k': 1024, 'm': _1M, @@ -616,6 +619,7 @@ if m is None: raise ValueError('Invalid memory limit %r' % (limit,)) memlimit = int(float(m.group(1)) * sizes[m.group(3).lower()]) + real_max_memuse = memlimit if memlimit > MAX_Py_ssize_t: memlimit = MAX_Py_ssize_t if memlimit < _2G - 1: @@ -661,6 +665,27 @@ return wrapper return decorator +def precisionbigmemtest(size, memuse, overhead=5*_1M): + def decorator(f): + def wrapper(self): + if not real_max_memuse: + maxsize = 5147 + else: + maxsize = size + + if real_max_memuse and real_max_memuse < maxsize * memuse: + if verbose: + sys.stderr.write("Skipping %s because of memory " + "constraint\n" % (f.__name__,)) + return + + return f(self, maxsize) + wrapper.size = size + wrapper.memuse = memuse + wrapper.overhead = overhead + return wrapper + return decorator + def bigaddrspacetest(f): """Decorator for tests that fill the address space.""" def wrapper(self): Modified: python/branches/py3k/Lib/test/test_bigmem.py ============================================================================== --- python/branches/py3k/Lib/test/test_bigmem.py (original) +++ python/branches/py3k/Lib/test/test_bigmem.py Sun Aug 24 09:08:55 2008 @@ -1,5 +1,5 @@ from test import support -from test.support import bigmemtest, _1G, _2G +from test.support import bigmemtest, _1G, _2G, _4G, precisionbigmemtest import unittest import operator @@ -53,6 +53,22 @@ self.assertEquals(s[lpadsize:-rpadsize], SUBSTR) self.assertEquals(s.strip(), SUBSTR.strip()) + @precisionbigmemtest(size=_2G - 1, memuse=1) + def test_center_unicode(self, size): + SUBSTR = ' abc def ghi' + try: + s = SUBSTR.center(size) + except OverflowError: + pass # acceptable on 32-bit + else: + self.assertEquals(len(s), size) + lpadsize = rpadsize = (len(s) - len(SUBSTR)) // 2 + if len(s) % 2: + lpadsize += 1 + self.assertEquals(s[lpadsize:-rpadsize], SUBSTR) + self.assertEquals(s.strip(), SUBSTR.strip()) + del s + @bigmemtest(minsize=_2G, memuse=2) def test_count(self, size): SUBSTR = ' abc def ghi' @@ -69,10 +85,51 @@ s = b'.' * size self.assertEquals(len(s.decode('utf-8')), size) + def basic_encode_test(self, size, enc, c='.', expectedsize=None): + if expectedsize is None: + expectedsize = size + + s = c * size + self.assertEquals(len(s.encode(enc)), expectedsize) + @bigmemtest(minsize=_2G + 2, memuse=3) def test_encode(self, size): - s = '.' * size - self.assertEquals(len(s.encode('utf-8')), size) + return self.basic_encode_test(size, 'utf-8') + + @precisionbigmemtest(size=_4G / 6 + 2, memuse=2) + def test_encode_raw_unicode_escape(self, size): + try: + return self.basic_encode_test(size, 'raw_unicode_escape') + except MemoryError: + pass # acceptable on 32-bit + + @precisionbigmemtest(size=_4G / 5 + 70, memuse=3) + def test_encode_utf7(self, size): + try: + return self.basic_encode_test(size, 'utf7') + except MemoryError: + pass # acceptable on 32-bit + + @precisionbigmemtest(size=_4G / 4 + 5, memuse=6) + def test_encode_utf32(self, size): + try: + return self.basic_encode_test(size, 'utf32', expectedsize=4*size+4) + except MemoryError: + pass # acceptable on 32-bit + + @precisionbigmemtest(size=_2G-1, memuse=2) + def test_decodeascii(self, size): + return self.basic_encode_test(size, 'ascii', c='A') + + @precisionbigmemtest(size=_4G / 5, memuse=6+2) + def test_unicode_repr_oflw(self, size): + try: + s = "\uAAAA"*size + r = repr(s) + except MemoryError: + pass # acceptable on 32-bit + else: + self.failUnless(s == eval(r)) @bigmemtest(minsize=_2G, memuse=2) def test_endswith(self, size): @@ -458,6 +515,11 @@ self.assertEquals(s.count('\\'), size) self.assertEquals(s.count('0'), size * 2) + @bigmemtest(minsize=2**32 / 5, memuse=6+2) + def test_unicode_repr(self, size): + s = "\uAAAA" * size + self.failUnless(len(repr(s)) > size) + # This test is meaningful even with size < 2G, as long as the # doubled string is > 2G (but it tests more if both are > 2G :) @bigmemtest(minsize=_1G + 2, memuse=3) @@ -641,6 +703,35 @@ def test_repeat_large(self, size): return self.basic_test_repeat(size) + @bigmemtest(minsize=_1G - 1, memuse=12) + def test_repeat_large_2(self, size): + return self.basic_test_repeat(size) + + @precisionbigmemtest(size=_1G - 1, memuse=9) + def test_from_2G_generator(self, size): + try: + t = tuple(range(size)) + except MemoryError: + pass # acceptable on 32-bit + else: + count = 0 + for item in t: + self.assertEquals(item, count) + count += 1 + self.assertEquals(count, size) + + @precisionbigmemtest(size=_1G - 25, memuse=9) + def test_from_almost_2G_generator(self, size): + try: + t = tuple(range(size)) + count = 0 + for item in t: + self.assertEquals(item, count) + count += 1 + self.assertEquals(count, size) + except MemoryError: + pass # acceptable, expected on 32-bit + # Like test_concat, split in two. def basic_test_repr(self, size): t = (0,) * size Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 24 09:08:55 2008 @@ -12,6 +12,8 @@ Core and Builtins ----------------- +- Apply security patches from Apple. + - Fix crashes on memory allocation failure found with failmalloc. - Fix memory leaks found with valgrind and update suppressions file. Modified: python/branches/py3k/Modules/gcmodule.c ============================================================================== --- python/branches/py3k/Modules/gcmodule.c (original) +++ python/branches/py3k/Modules/gcmodule.c Sun Aug 24 09:08:55 2008 @@ -1318,7 +1318,10 @@ _PyObject_GC_Malloc(size_t basicsize) { PyObject *op; - PyGC_Head *g = (PyGC_Head *)PyObject_MALLOC( + PyGC_Head *g; + if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) + return PyErr_NoMemory(); + g = (PyGC_Head *)PyObject_MALLOC( sizeof(PyGC_Head) + basicsize); if (g == NULL) return PyErr_NoMemory(); @@ -1361,6 +1364,8 @@ { const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); PyGC_Head *g = AS_GC(op); + if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) + return (PyVarObject *)PyErr_NoMemory(); g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); if (g == NULL) return (PyVarObject *)PyErr_NoMemory(); Modified: python/branches/py3k/Modules/mmapmodule.c ============================================================================== --- python/branches/py3k/Modules/mmapmodule.c (original) +++ python/branches/py3k/Modules/mmapmodule.c Sun Aug 24 09:08:55 2008 @@ -245,7 +245,7 @@ return(NULL); /* silently 'adjust' out-of-range requests */ - if ((self->pos + num_bytes) > self->size) { + if (num_bytes > self->size - self->pos) { num_bytes -= (self->pos+num_bytes) - self->size; } result = PyByteArray_FromStringAndSize(self->data+self->pos, num_bytes); Modified: python/branches/py3k/Objects/bytearrayobject.c ============================================================================== --- python/branches/py3k/Objects/bytearrayobject.c (original) +++ python/branches/py3k/Objects/bytearrayobject.c Sun Aug 24 09:08:55 2008 @@ -121,6 +121,11 @@ return NULL; } + /* Prevent buffer overflow when setting alloc to size+1. */ + if (size == PY_SSIZE_T_MAX) { + return PyErr_NoMemory(); + } + new = PyObject_New(PyByteArrayObject, &PyByteArray_Type); if (new == NULL) return NULL; Modified: python/branches/py3k/Objects/bytesobject.c ============================================================================== --- python/branches/py3k/Objects/bytesobject.c (original) +++ python/branches/py3k/Objects/bytesobject.c Sun Aug 24 09:08:55 2008 @@ -83,6 +83,12 @@ return (PyObject *)op; } + if (size > PY_SSIZE_T_MAX - sizeof(PyBytesObject)) { + PyErr_SetString(PyExc_OverflowError, + "byte string is too large"); + return NULL; + } + /* Inline PyObject_NewVar */ op = (PyBytesObject *)PyObject_MALLOC(sizeof(PyBytesObject) + size); if (op == NULL) @@ -111,7 +117,7 @@ assert(str != NULL); size = strlen(str); - if (size > PY_SSIZE_T_MAX) { + if (size > PY_SSIZE_T_MAX - sizeof(PyBytesObject)) { PyErr_SetString(PyExc_OverflowError, "byte string is too long"); return NULL; Modified: python/branches/py3k/Objects/longobject.c ============================================================================== --- python/branches/py3k/Objects/longobject.c (original) +++ python/branches/py3k/Objects/longobject.c Sun Aug 24 09:08:55 2008 @@ -139,6 +139,8 @@ PyErr_NoMemory(); return NULL; } + /* XXX(nnorwitz): This can overflow -- + PyObject_NEW_VAR / _PyObject_VAR_SIZE need to detect overflow */ return (PyLongObject*)PyObject_INIT_VAR(result, &PyLong_Type, size); } Modified: python/branches/py3k/Objects/tupleobject.c ============================================================================== --- python/branches/py3k/Objects/tupleobject.c (original) +++ python/branches/py3k/Objects/tupleobject.c Sun Aug 24 09:08:55 2008 @@ -60,11 +60,12 @@ Py_ssize_t nbytes = size * sizeof(PyObject *); /* Check for overflow */ if (nbytes / sizeof(PyObject *) != (size_t)size || - (nbytes += sizeof(PyTupleObject) - sizeof(PyObject *)) - <= 0) + (nbytes > PY_SSIZE_T_MAX - sizeof(PyTupleObject) - sizeof(PyObject *))) { return PyErr_NoMemory(); } + nbytes += sizeof(PyTupleObject) - sizeof(PyObject *); + op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size); if (op == NULL) return NULL; Modified: python/branches/py3k/Objects/unicodeobject.c ============================================================================== --- python/branches/py3k/Objects/unicodeobject.c (original) +++ python/branches/py3k/Objects/unicodeobject.c Sun Aug 24 09:08:55 2008 @@ -311,6 +311,11 @@ return unicode_empty; } + /* Ensure we won't overflow the size. */ + if (length > ((PY_SSIZE_T_MAX / sizeof(Py_UNICODE)) - 1)) { + return (PyUnicodeObject *)PyErr_NoMemory(); + } + /* Unicode freelist & memory allocation */ if (free_list) { unicode = free_list; @@ -1860,6 +1865,9 @@ if (size == 0) return PyBytes_FromStringAndSize(NULL, 0); + if (cbAllocated / 5 != size) + return PyErr_NoMemory(); + v = PyByteArray_FromStringAndSize(NULL, cbAllocated); if (v == NULL) return NULL; @@ -2452,8 +2460,9 @@ { PyObject *v, *result; unsigned char *p; + Py_ssize_t nsize, bytesize; #ifndef Py_UNICODE_WIDE - int i, pairs; + Py_ssize_t i, pairs; #else const int pairs = 0; #endif @@ -2481,8 +2490,11 @@ 0xDC00 <= s[i+1] && s[i+1] <= 0xDFFF) pairs++; #endif - v = PyByteArray_FromStringAndSize(NULL, - 4 * (size - pairs + (byteorder == 0))); + nsize = (size - pairs + (byteorder == 0)); + bytesize = nsize * 4; + if (bytesize / 4 != nsize) + return PyErr_NoMemory(); + v = PyByteArray_FromStringAndSize(NULL, bytesize); if (v == NULL) return NULL; @@ -2726,8 +2738,9 @@ { PyObject *v, *result; unsigned char *p; + Py_ssize_t nsize, bytesize; #ifdef Py_UNICODE_WIDE - int i, pairs; + Py_ssize_t i, pairs; #else const int pairs = 0; #endif @@ -2750,8 +2763,15 @@ if (s[i] >= 0x10000) pairs++; #endif - v = PyByteArray_FromStringAndSize(NULL, - 2 * (size + pairs + (byteorder == 0))); + /* 2 * (size + pairs + (byteorder == 0)) */ + if (size > PY_SSIZE_T_MAX || + size > PY_SSIZE_T_MAX - pairs - (byteorder == 0)) + return PyErr_NoMemory(); + nsize = size + pairs + (byteorder == 0); + bytesize = nsize * 2; + if (bytesize / 2 != nsize) + return PyErr_NoMemory(); + v = PyByteArray_FromStringAndSize(NULL, bytesize); if (v == NULL) return NULL; @@ -3082,6 +3102,12 @@ PyObject *repr, *result; char *p; +#ifdef Py_UNICODE_WIDE + const Py_ssize_t expandsize = 10; +#else + const Py_ssize_t expandsize = 6; +#endif + /* XXX(nnorwitz): rather than over-allocating, it would be better to choose a different scheme. Perhaps scan the first N-chars of the string and allocate based on that size. @@ -3100,12 +3126,12 @@ escape. */ + if (size > (PY_SSIZE_T_MAX - 2 - 1) / expandsize) + return PyErr_NoMemory(); + repr = PyByteArray_FromStringAndSize(NULL, -#ifdef Py_UNICODE_WIDE - + 10*size -#else - + 6*size -#endif + 2 + + expandsize*size + 1); if (repr == NULL) return NULL; @@ -3353,10 +3379,15 @@ char *q; #ifdef Py_UNICODE_WIDE - repr = PyByteArray_FromStringAndSize(NULL, 10 * size); + const Py_ssize_t expandsize = 10; #else - repr = PyByteArray_FromStringAndSize(NULL, 6 * size); + const Py_ssize_t expandsize = 6; #endif + + if (size > PY_SSIZE_T_MAX / expandsize) + return PyErr_NoMemory(); + + repr = PyByteArray_FromStringAndSize(NULL, expandsize * size); if (repr == NULL) return NULL; if (size == 0) @@ -5747,6 +5778,11 @@ return self; } + if (left > PY_SSIZE_T_MAX - self->length || + right > PY_SSIZE_T_MAX - (left + self->length)) { + PyErr_SetString(PyExc_OverflowError, "padded string is too long"); + return NULL; + } u = _PyUnicode_New(left + self->length + right); if (u) { if (left) From python-3000-checkins at python.org Sun Aug 24 18:15:19 2008 From: python-3000-checkins at python.org (christian.heimes) Date: Sun, 24 Aug 2008 18:15:19 +0200 (CEST) Subject: [Python-3000-checkins] r66010 - python/branches/py3k/Objects/bytesobject.c Message-ID: <20080824161520.028BC1E4005@bag.python.org> Author: christian.heimes Date: Sun Aug 24 18:15:19 2008 New Revision: 66010 Log: Fixed yet another compiler warning of 64bit builds. Reviewed by Georg Brandl. Modified: python/branches/py3k/Objects/bytesobject.c Modified: python/branches/py3k/Objects/bytesobject.c ============================================================================== --- python/branches/py3k/Objects/bytesobject.c (original) +++ python/branches/py3k/Objects/bytesobject.c Sun Aug 24 18:15:19 2008 @@ -3212,7 +3212,7 @@ int numnondigits = 0; /* Avoid exceeding SSIZE_T_MAX */ - if (prec > PY_SSIZE_T_MAX-3) { + if (prec > INT_MAX-3) { PyErr_SetString(PyExc_OverflowError, "precision too large"); return NULL; From python-3000-checkins at python.org Sun Aug 24 20:12:21 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Sun, 24 Aug 2008 20:12:21 +0200 (CEST) Subject: [Python-3000-checkins] r66015 - python/branches/py3k Message-ID: <20080824181221.87BE71E4003@bag.python.org> Author: benjamin.peterson Date: Sun Aug 24 20:12:21 2008 New Revision: 66015 Log: Blocked revisions 66013 via svnmerge ........ r66013 | benjamin.peterson | 2008-08-24 13:10:20 -0500 (Sun, 24 Aug 2008) | 4 lines generate py3k warnings on __getslice__, __delslice__, and __setslice__ Reviewer: Brett Cannon ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sun Aug 24 22:59:23 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Sun, 24 Aug 2008 22:59:23 +0200 (CEST) Subject: [Python-3000-checkins] r66016 - in python/branches/py3k/Misc: NEWS gdbinit Message-ID: <20080824205923.7328C1E4003@bag.python.org> Author: neal.norwitz Date: Sun Aug 24 22:59:23 2008 New Revision: 66016 Log: Fix gdbinit to handle new types/APIs. Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Misc/gdbinit Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 24 22:59:23 2008 @@ -33,6 +33,11 @@ - Issue #3643: Added a few more checks to _testcapi to prevent segfaults by exploitation of poor argument checking. +Tools/Demos +----------- + +- Fix Misc/gdbinit so it works. + What's new in Python 3.0b3? =========================== Modified: python/branches/py3k/Misc/gdbinit ============================================================================== --- python/branches/py3k/Misc/gdbinit (original) +++ python/branches/py3k/Misc/gdbinit Sun Aug 24 22:59:23 2008 @@ -32,7 +32,7 @@ while $_i < f->f_nlocals if f->f_localsplus + $_i != 0 set $_names = co->co_varnames - set $_name = PyUnicode_AsString(PyTuple_GetItem($_names, $_i)) + set $_name = _PyUnicode_AsString(PyTuple_GetItem($_names, $_i)) printf "%s:\n", $_name # side effect of calling _PyObject_Dump is to dump the object's # info - assigning just prevents gdb from printing the @@ -50,7 +50,7 @@ set $__co = f->f_code set $__lasti = f->f_lasti set $__sz = ((PyVarObject *)$__co->co_lnotab)->ob_size/2 - set $__p = (unsigned char *)((PyStringObject *)$__co->co_lnotab)->ob_sval + set $__p = (unsigned char *)((PyBytesObject *)$__co->co_lnotab)->ob_sval set $__li = $__co->co_firstlineno set $__ad = 0 while ($__sz-1 >= 0 && $__continue) @@ -73,8 +73,8 @@ end define pyframe - set $__fn = (char *)((PyStringObject *)co->co_filename)->ob_sval - set $__n = PyUnicode_AsString(co->co_name) + set $__fn = _PyUnicode_AsString(co->co_filename) + set $__n = _PyUnicode_AsString(co->co_name) printf "%s (", $__fn lineno printf "): %s\n", $__n From python-3000-checkins at python.org Mon Aug 25 00:07:29 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Mon, 25 Aug 2008 00:07:29 +0200 (CEST) Subject: [Python-3000-checkins] r66019 - in python/branches/py3k: Lib/test/test_fileio.py Modules/_fileio.c Message-ID: <20080824220729.49BC01E4003@bag.python.org> Author: neal.norwitz Date: Mon Aug 25 00:07:28 2008 New Revision: 66019 Log: Merged revisions 66018 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r66018 | neal.norwitz | 2008-08-24 15:03:05 -0700 (Sun, 24 Aug 2008) | 6 lines #3662: Fix segfault introduced when fixing memory leaks. TESTED=./python -E -tt ./Lib/test/regrtest.py test_fileio R (approach from bug)=Amaury and Benjamin ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_fileio.py python/branches/py3k/Modules/_fileio.c Modified: python/branches/py3k/Lib/test/test_fileio.py ============================================================================== --- python/branches/py3k/Lib/test/test_fileio.py (original) +++ python/branches/py3k/Lib/test/test_fileio.py Mon Aug 25 00:07:28 2008 @@ -226,6 +226,10 @@ except: pass + def testInvalidInit(self): + self.assertRaises(TypeError, _fileio._FileIO, "1", 0, 0) + + def test_main(): # Historically, these tests have been sloppy about removing TESTFN. # So get rid of it no matter what. Modified: python/branches/py3k/Modules/_fileio.c ============================================================================== --- python/branches/py3k/Modules/_fileio.c (original) +++ python/branches/py3k/Modules/_fileio.c Mon Aug 25 00:07:28 2008 @@ -175,7 +175,7 @@ kwlist, Py_FileSystemDefaultEncoding, &name, &mode, &closefd)) - goto error; + return -1; } } From python-3000-checkins at python.org Mon Aug 25 01:50:09 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Mon, 25 Aug 2008 01:50:09 +0200 (CEST) Subject: [Python-3000-checkins] r66021 - in python/branches/py3k: Misc/NEWS Modules/_pickle.c Message-ID: <20080824235009.3CF6A1E4003@bag.python.org> Author: neal.norwitz Date: Mon Aug 25 01:50:08 2008 New Revision: 66021 Log: Issue #3657: Fix uninitialized memory read when pickling longs. The conversion to the unicode API was incorrect, it should use bytes. repr is a bad variable name. The use is overloaded, but I'll leave that to fix later. R=Brett TESTED=./python -E -tt ./Lib/test/regrtest.py -uall valgrind -q --leak-check=yes --suppressions=Misc/valgrind-python.supp \ ./python -E -tt ./Lib/test/regrtest.py test_pickletools Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_pickle.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Mon Aug 25 01:50:08 2008 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #3657: Fix uninitialized memory read when pickling longs. + Found by valgrind. + - Apply security patches from Apple. - Fix crashes on memory allocation failure found with failmalloc. Modified: python/branches/py3k/Modules/_pickle.c ============================================================================== --- python/branches/py3k/Modules/_pickle.c (original) +++ python/branches/py3k/Modules/_pickle.c Mon Aug 25 01:50:08 2008 @@ -924,10 +924,10 @@ "long too large to pickle"); goto error; } - repr = PyUnicode_FromStringAndSize(NULL, (int)nbytes); + repr = PyBytes_FromStringAndSize(NULL, (Py_ssize_t)nbytes); if (repr == NULL) goto error; - pdata = (unsigned char *)_PyUnicode_AsString(repr); + pdata = (unsigned char *)PyBytes_AS_STRING(repr); i = _PyLong_AsByteArray((PyLongObject *)obj, pdata, nbytes, 1 /* little endian */ , 1 /* signed */ ); From python-3000-checkins at python.org Mon Aug 25 03:04:16 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Mon, 25 Aug 2008 03:04:16 +0200 (CEST) Subject: [Python-3000-checkins] r66022 - python/branches/py3k/Lib/test/test_posix.py Message-ID: <20080825010416.C1AA91E4003@bag.python.org> Author: neal.norwitz Date: Mon Aug 25 03:04:16 2008 New Revision: 66022 Log: Try to fix the sporadic problems on the Solaris buildbot with removing the directories/files. R=Brett TESTED=./python -E -tt ./Lib/test/regrtest.py test_posix Modified: python/branches/py3k/Lib/test/test_posix.py Modified: python/branches/py3k/Lib/test/test_posix.py ============================================================================== --- python/branches/py3k/Lib/test/test_posix.py (original) +++ python/branches/py3k/Lib/test/test_posix.py Mon Aug 25 03:04:16 2008 @@ -24,7 +24,7 @@ fp.close() def tearDown(self): - os.unlink(support.TESTFN) + support.unlink(support.TESTFN) def testNoArgFunctions(self): # test posix functions which take no arguments and have @@ -249,7 +249,7 @@ _create_and_do_getcwd(dirname) finally: - shutil.rmtree(base_path) + support.rmtree(base_path) os.chdir(curdir) From python-3000-checkins at python.org Mon Aug 25 03:53:32 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Mon, 25 Aug 2008 03:53:32 +0200 (CEST) Subject: [Python-3000-checkins] r66024 - in python/branches/py3k: Lib/multiprocessing/connection.py Lib/test/test_multiprocessing.py Message-ID: <20080825015332.D75EF1E4003@bag.python.org> Author: neal.norwitz Date: Mon Aug 25 03:53:32 2008 New Revision: 66024 Log: Merged revisions 66023 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r66023 | neal.norwitz | 2008-08-24 18:50:24 -0700 (Sun, 24 Aug 2008) | 6 lines Fix problem reported by pychecker where AuthenticationError wasn't imported. Add some test coverage to this code. More tests should be added (TODO added). R=Brett TESTED=./python -E -tt ./Lib/test/regrtest.py test_multiprocessing ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/multiprocessing/connection.py python/branches/py3k/Lib/test/test_multiprocessing.py Modified: python/branches/py3k/Lib/multiprocessing/connection.py ============================================================================== --- python/branches/py3k/Lib/multiprocessing/connection.py (original) +++ python/branches/py3k/Lib/multiprocessing/connection.py Mon Aug 25 03:53:32 2008 @@ -17,7 +17,7 @@ import itertools import _multiprocessing -from multiprocessing import current_process +from multiprocessing import current_process, AuthenticationError from multiprocessing.util import get_temp_dir, Finalize, sub_debug, debug from multiprocessing.forking import duplicate, close Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Mon Aug 25 03:53:32 2008 @@ -1737,6 +1737,37 @@ testcases_threads = create_test_cases(ThreadsMixin, type='threads') globals().update(testcases_threads) +class OtherTest(unittest.TestCase): + # TODO: add more tests for deliver/answer challenge. + def test_deliver_challenge_auth_failure(self): + class _FakeConnection(object): + def recv_bytes(self, size): + return 'something bogus' + def send_bytes(self, data): + pass + self.assertRaises(multiprocessing.AuthenticationError, + multiprocessing.connection.deliver_challenge, + _FakeConnection(), b'abc') + + def test_answer_challenge_auth_failure(self): + class _FakeConnection(object): + def __init__(self): + self.count = 0 + def recv_bytes(self, size): + self.count += 1 + if self.count == 1: + return multiprocessing.connection.CHALLENGE + elif self.count == 2: + return 'something bogus' + return '' + def send_bytes(self, data): + pass + self.assertRaises(multiprocessing.AuthenticationError, + multiprocessing.connection.answer_challenge, + _FakeConnection(), b'abc') + +testcases_other = [OtherTest] + # # # @@ -1765,7 +1796,8 @@ testcases = ( sorted(testcases_processes.values(), key=lambda tc:tc.__name__) + sorted(testcases_threads.values(), key=lambda tc:tc.__name__) + - sorted(testcases_manager.values(), key=lambda tc:tc.__name__) + sorted(testcases_manager.values(), key=lambda tc:tc.__name__) + + testcases_other ) loadTestsFromTestCase = unittest.defaultTestLoader.loadTestsFromTestCase From python-3000-checkins at python.org Mon Aug 25 05:05:55 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Mon, 25 Aug 2008 05:05:55 +0200 (CEST) Subject: [Python-3000-checkins] r66027 - in python/branches/py3k: Lib/test/test_multiprocessing.py Message-ID: <20080825030555.3C9A91E4003@bag.python.org> Author: neal.norwitz Date: Mon Aug 25 05:05:54 2008 New Revision: 66027 Log: Merged revisions 66026 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r66026 | neal.norwitz | 2008-08-24 20:03:25 -0700 (Sun, 24 Aug 2008) | 6 lines Use bytes as return type from recv_bytes() methods. Not sure why this only affects some buildbots. R=Brett TESTED=./python -E -tt ./Lib/test/regrtest.py test_multiprocessing ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_multiprocessing.py Modified: python/branches/py3k/Lib/test/test_multiprocessing.py ============================================================================== --- python/branches/py3k/Lib/test/test_multiprocessing.py (original) +++ python/branches/py3k/Lib/test/test_multiprocessing.py Mon Aug 25 05:05:54 2008 @@ -1742,7 +1742,7 @@ def test_deliver_challenge_auth_failure(self): class _FakeConnection(object): def recv_bytes(self, size): - return 'something bogus' + return b'something bogus' def send_bytes(self, data): pass self.assertRaises(multiprocessing.AuthenticationError, @@ -1758,8 +1758,8 @@ if self.count == 1: return multiprocessing.connection.CHALLENGE elif self.count == 2: - return 'something bogus' - return '' + return b'something bogus' + return b'' def send_bytes(self, data): pass self.assertRaises(multiprocessing.AuthenticationError, From python-3000-checkins at python.org Mon Aug 25 05:55:03 2008 From: python-3000-checkins at python.org (neal.norwitz) Date: Mon, 25 Aug 2008 05:55:03 +0200 (CEST) Subject: [Python-3000-checkins] r66029 - in python/branches/py3k: Lib/test/test_smtplib.py Message-ID: <20080825035503.BD3621E4013@bag.python.org> Author: neal.norwitz Date: Mon Aug 25 05:55:03 2008 New Revision: 66029 Log: Merged revisions 66028 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r66028 | neal.norwitz | 2008-08-24 20:52:40 -0700 (Sun, 24 Aug 2008) | 1 line Try to reduce the flakiness of this test ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/test/test_smtplib.py Modified: python/branches/py3k/Lib/test/test_smtplib.py ============================================================================== --- python/branches/py3k/Lib/test/test_smtplib.py (original) +++ python/branches/py3k/Lib/test/test_smtplib.py Mon Aug 25 05:55:03 2008 @@ -220,6 +220,10 @@ m = 'A test message' smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) smtp.sendmail('John', 'Sally', m) + # XXX(nnorwitz): this test is flaky and dies with a bad file descriptor + # in asyncore. This sleep might help, but should really be fixed + # properly by using an Event variable. + time.sleep(0.01) smtp.quit() self.client_evt.set() From python-3000-checkins at python.org Mon Aug 25 23:05:22 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Mon, 25 Aug 2008 23:05:22 +0200 (CEST) Subject: [Python-3000-checkins] r66034 - in python/branches/py3k: Doc/bugs.rst Doc/library/multiprocessing.rst Lib/test/test_list.py Lib/test/test_re.py Misc/build.sh Modules/_collectionsmodule.c Modules/_testcapimodule.c Objects/bytearrayobject.c Objects/stringlib/find.h Message-ID: <20080825210522.179E41E4019@bag.python.org> Author: benjamin.peterson Date: Mon Aug 25 23:05:21 2008 New Revision: 66034 Log: Merged revisions 65910,65977,65980,65984,65986,66000,66011-66012,66014,66017,66020 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65910 | benjamin.peterson | 2008-08-20 09:07:59 -0500 (Wed, 20 Aug 2008) | 1 line fix up the multiprocessing docs a little ........ r65977 | christian.heimes | 2008-08-22 14:47:25 -0500 (Fri, 22 Aug 2008) | 3 lines Silenced compiler warning Objects/stringlib/find.h:97: warning: 'stringlib_contains_obj' defined but not used Reviewed by Benjamin Peterson ........ r65980 | christian.heimes | 2008-08-22 15:10:27 -0500 (Fri, 22 Aug 2008) | 3 lines Fixed two format strings in the _collections module. For example Modules/_collectionsmodule.c:674: warning: format '%i' expects type 'int', but argument 2 has type 'Py_ssize_t' Reviewed by Benjamin Peterson ........ r65984 | christian.heimes | 2008-08-22 16:23:47 -0500 (Fri, 22 Aug 2008) | 1 line d is the correct format string ........ r65986 | mark.hammond | 2008-08-22 19:59:14 -0500 (Fri, 22 Aug 2008) | 2 lines Fix bug 3625: test issues on 64bit windows. r=pitrou ........ r66000 | benjamin.peterson | 2008-08-23 15:27:43 -0500 (Sat, 23 Aug 2008) | 5 lines #3643 add a few more checks to _testcapi to prevent segfaults Author: Victor Stinner Reviewer: Benjamin Peterson ........ r66011 | neal.norwitz | 2008-08-24 12:27:43 -0500 (Sun, 24 Aug 2008) | 1 line Ignore a couple more tests that report leaks inconsistently. ........ r66012 | neal.norwitz | 2008-08-24 12:29:53 -0500 (Sun, 24 Aug 2008) | 1 line Use the actual blacklist of leaky tests ........ r66014 | georg.brandl | 2008-08-24 13:11:07 -0500 (Sun, 24 Aug 2008) | 2 lines #3654: fix duplicate test method name. Review by Benjamin P. ........ r66017 | benjamin.peterson | 2008-08-24 16:55:03 -0500 (Sun, 24 Aug 2008) | 1 line remove note about unimplemented feature ........ r66020 | brett.cannon | 2008-08-24 18:15:19 -0500 (Sun, 24 Aug 2008) | 1 line Clarify that some attributes/methods are listed somewhat separately because they are not part of the threading API. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/bugs.rst python/branches/py3k/Doc/library/multiprocessing.rst python/branches/py3k/Lib/test/test_list.py python/branches/py3k/Lib/test/test_re.py python/branches/py3k/Misc/build.sh python/branches/py3k/Modules/_collectionsmodule.c python/branches/py3k/Modules/_testcapimodule.c python/branches/py3k/Objects/bytearrayobject.c python/branches/py3k/Objects/stringlib/find.h Modified: python/branches/py3k/Doc/bugs.rst ============================================================================== --- python/branches/py3k/Doc/bugs.rst (original) +++ python/branches/py3k/Doc/bugs.rst Mon Aug 25 23:05:21 2008 @@ -8,11 +8,7 @@ stability. In order to maintain this reputation, the developers would like to know of any deficiencies you find in Python. -If you find errors in the documentation, please use either the "Add a comment" -or the "Suggest a change" features of the relevant page in the most recent -online documentation at http://docs.python.org/. - -All other bug reports should be submitted via the Python Bug Tracker +Bug reports should be submitted via the Python Bug Tracker (http://bugs.python.org/). The bug tracker offers a Web form which allows pertinent information to be entered and submitted to the developers. Modified: python/branches/py3k/Doc/library/multiprocessing.rst ============================================================================== --- python/branches/py3k/Doc/library/multiprocessing.rst (original) +++ python/branches/py3k/Doc/library/multiprocessing.rst Mon Aug 25 23:05:21 2008 @@ -248,7 +248,7 @@ The constructor should always be called with keyword arguments. *group* should always be ``None``; it exists solely for compatibility with - :class:`~threading.Thread`. *target* is the callable object to be invoked by + :class:`threading.Thread`. *target* is the callable object to be invoked by the :meth:`run()` method. It defaults to ``None``, meaning nothing is called. *name* is the process name. By default, a unique name is constructed of the form 'Process-N\ :sub:`1`:N\ :sub:`2`:...:N\ :sub:`k`' where N\ @@ -290,13 +290,9 @@ A process cannot join itself because this would cause a deadlock. It is an error to attempt to join a process before it has been started. - .. attribute:: Process.name + .. attribute:: name - Return the process's name. - - .. attribute:: Process.name = name - - Set the process's name. + The process's name. The name is a string used for identification purposes only. It has no semantics. Multiple processes may be given the same name. The initial @@ -309,14 +305,10 @@ Roughly, a process object is alive from the moment the :meth:`start` method returns until the child process terminates. - .. attribute:: Process.daemon - - Return the process's daemon flag., this is a boolean. + .. attribute:: daemon - .. attribute:: Process.daemon = daemonic - - Set the process's daemon flag to the Boolean value *daemonic*. This must - be called before :meth:`start` is called. + The process's daemon flag, a Boolean value. This must be called before + :meth:`start` is called. The initial value is inherited from the creating process. @@ -327,36 +319,33 @@ Otherwise a daemonic process would leave its children orphaned if it gets terminated when its parent process exits. - In addition process objects also support the following methods: + In addition to the :class:`Threading.Thread` API, :class:`Process` objects + also support the following attributes and methods: - .. attribute:: Process.pid + .. attribute:: pid Return the process ID. Before the process is spawned, this will be ``None``. - .. attribute:: Process.exitcode + .. attribute:: exitcode - Return the child's exit code. This will be ``None`` if the process has - not yet terminated. A negative value *-N* indicates that the child was - terminated by signal *N*. + The child's exit code. This will be ``None`` if the process has not yet + terminated. A negative value *-N* indicates that the child was terminated + by signal *N*. - .. attribute:: Process.authkey + .. attribute:: authkey - Return the process's authentication key (a byte string). + The process's authentication key (a byte string). When :mod:`multiprocessing` is initialized the main process is assigned a random string using :func:`os.random`. When a :class:`Process` object is created, it will inherit the - authentication key of its parent process, although this may be changed - using :attr:`Process.authkey` below. + authentication key of its parent process, although this may be changed by + setting :attr:`authkey` to another byte string. See :ref:`multiprocessing-auth-keys`. - .. attribute:: Process.authkey = authkey - - Set the process's authentication key which must be a byte string. - .. method:: terminate() Terminate the process. On Unix this is done using the ``SIGTERM`` signal; @@ -375,8 +364,8 @@ cause other processes to deadlock. Note that the :meth:`start`, :meth:`join`, :meth:`is_alive` and - :meth:`get_exit_code` methods should only be called by the process that - created the process object. + :attr:`exit_code` methods should only be called by the process that created + the process object. Example usage of some of the methods of :class:`Process`:: @@ -390,7 +379,7 @@ >>> p.terminate() >>> print p, p.is_alive() False - >>> p.get_exit_code() == -signal.SIGTERM + >>> p.exitcode == -signal.SIGTERM True @@ -1075,7 +1064,7 @@ *authkey* is the authentication key which will be used to check the validity of incoming connections to the server process. If *authkey* is ``None`` then - ``current_process().get_auth_key()``. Otherwise *authkey* is used and it + ``current_process().authkey``. Otherwise *authkey* is used and it must be a string. .. method:: start() @@ -1599,7 +1588,7 @@ If *authentication* is ``True`` or *authkey* is a string then digest authentication is used. The key used for authentication will be either - *authkey* or ``current_process().get_auth_key()`` if *authkey* is ``None``. + *authkey* or ``current_process().authkey)`` if *authkey* is ``None``. If authentication fails then :exc:`AuthenticationError` is raised. See :ref:`multiprocessing-auth-keys`. @@ -1632,7 +1621,7 @@ otherwise it must be *None*. If *authkey* is ``None`` and *authenticate* is ``True`` then - ``current_process().get_auth_key()`` is used as the authentication key. If + ``current_process().authkey`` is used as the authentication key. If *authkey* is ``None`` and *authentication* is ``False`` then no authentication is done. If authentication fails then :exc:`AuthenticationError` is raised. See :ref:`multiprocessing-auth-keys`. @@ -1748,7 +1737,7 @@ **not** involve sending the key over the connection.) If authentication is requested but do authentication key is specified then the -return value of ``current_process().get_auth_key`` is used (see +return value of ``current_process().authkey`` is used (see :class:`~multiprocessing.Process`). This value will automatically inherited by any :class:`~multiprocessing.Process` object that the current process creates. This means that (by default) all processes of a multi-process program will share Modified: python/branches/py3k/Lib/test/test_list.py ============================================================================== --- python/branches/py3k/Lib/test/test_list.py (original) +++ python/branches/py3k/Lib/test/test_list.py Mon Aug 25 23:05:21 2008 @@ -15,6 +15,23 @@ self.assertEqual(list(''), []) self.assertEqual(list('spam'), ['s', 'p', 'a', 'm']) + if sys.maxsize == 0x7fffffff: + # This test can currently only work on 32-bit machines. + # XXX If/when PySequence_Length() returns a ssize_t, it should be + # XXX re-enabled. + # Verify clearing of bug #556025. + # This assumes that the max data size (sys.maxint) == max + # address size this also assumes that the address size is at + # least 4 bytes with 8 byte addresses, the bug is not well + # tested + # + # Note: This test is expected to SEGV under Cygwin 1.3.12 or + # earlier due to a newlib bug. See the following mailing list + # thread for the details: + + # http://sources.redhat.com/ml/newlib/2002/msg00369.html + self.assertRaises(MemoryError, list, range(sys.maxsize // 2)) + # This code used to segfault in Py2.4a3 x = [] x.extend(-y for y in x) Modified: python/branches/py3k/Lib/test/test_re.py ============================================================================== --- python/branches/py3k/Lib/test/test_re.py (original) +++ python/branches/py3k/Lib/test/test_re.py Mon Aug 25 23:05:21 2008 @@ -352,10 +352,6 @@ self.assertEqual(re.search(r"\d\D\w\W\s\S", "1aa! a", re.UNICODE).group(0), "1aa! a") - def test_ignore_case(self): - self.assertEqual(re.match("abc", "ABC", re.I).group(0), "ABC") - self.assertEqual(re.match("abc", "ABC", re.I).group(0), "ABC") - def test_bigcharset(self): self.assertEqual(re.match("([\u2222\u2223])", "\u2222").group(1), "\u2222") @@ -383,6 +379,8 @@ self.assertEqual(re.match(r"(a)(?!\s(abc|a))", "a b").group(1), "a") def test_ignore_case(self): + self.assertEqual(re.match("abc", "ABC", re.I).group(0), "ABC") + self.assertEqual(re.match("abc", "ABC", re.I).group(0), "ABC") self.assertEqual(re.match(r"(a\s[^a])", "a b", re.I).group(1), "a b") self.assertEqual(re.match(r"(a\s[^a]*)", "a bb", re.I).group(1), "a bb") self.assertEqual(re.match(r"(a\s[abc])", "a b", re.I).group(1), "a b") Modified: python/branches/py3k/Misc/build.sh ============================================================================== --- python/branches/py3k/Misc/build.sh (original) +++ python/branches/py3k/Misc/build.sh Mon Aug 25 23:05:21 2008 @@ -67,7 +67,7 @@ # Note: test_XXX (none currently) really leak, but are disabled # so we don't send spam. Any test which really leaks should only # be listed here if there are also test cases under Lib/test/leakers. -LEAKY_TESTS="test_(asynchat|cmd_line|popen2|socket|smtplib|sys|threadsignals|urllib2_localnet|httpservers)" +LEAKY_TESTS="test_(asynchat|cmd_line|docxmlrpc|dumbdbm|file|ftplib|httpservers|imaplib|popen2|socket|smtplib|sys|telnetlib|threadedtempfile|threading|threadsignals|urllib2_localnet|xmlrpc)" # These tests always fail, so skip them so we don't get false positives. _ALWAYS_SKIP="" Modified: python/branches/py3k/Modules/_collectionsmodule.c ============================================================================== --- python/branches/py3k/Modules/_collectionsmodule.c (original) +++ python/branches/py3k/Modules/_collectionsmodule.c Mon Aug 25 23:05:21 2008 @@ -670,8 +670,9 @@ return NULL; } if (((dequeobject *)deque)->maxlen != -1) - result = PyUnicode_FromFormat("deque(%R, maxlen=%i)", aslist, - ((dequeobject *)deque)->maxlen); + + result = PyUnicode_FromFormat("deque(%R, maxlen=%" PY_FORMAT_SIZE_T "d)", + aslist, ((dequeobject *)deque)->maxlen); else result = PyUnicode_FromFormat("deque(%R)", aslist); Py_DECREF(aslist); Modified: python/branches/py3k/Modules/_testcapimodule.c ============================================================================== --- python/branches/py3k/Modules/_testcapimodule.c (original) +++ python/branches/py3k/Modules/_testcapimodule.c Mon Aug 25 23:05:21 2008 @@ -714,14 +714,17 @@ */ static PyThread_type_lock thread_done = NULL; -static void +static int _make_call(void *callable) { PyObject *rc; + int success; PyGILState_STATE s = PyGILState_Ensure(); rc = PyObject_CallFunction((PyObject *)callable, ""); + success = (rc != NULL); Py_XDECREF(rc); PyGILState_Release(s); + return success; } /* Same thing, but releases `thread_done` when it returns. This variant @@ -738,10 +741,17 @@ test_thread_state(PyObject *self, PyObject *args) { PyObject *fn; + int success = 1; if (!PyArg_ParseTuple(args, "O:test_thread_state", &fn)) return NULL; + if (!PyCallable_Check(fn)) { + PyErr_Format(PyExc_TypeError, "'%s' object is not callable", + fn->ob_type->tp_name); + return NULL; + } + /* Ensure Python is set up for threading */ PyEval_InitThreads(); thread_done = PyThread_allocate_lock(); @@ -752,10 +762,10 @@ /* Start a new thread with our callback. */ PyThread_start_new_thread(_make_call_from_thread, fn); /* Make the callback with the thread lock held by this thread */ - _make_call(fn); + success &= _make_call(fn); /* Do it all again, but this time with the thread-lock released */ Py_BEGIN_ALLOW_THREADS - _make_call(fn); + success &= _make_call(fn); PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */ Py_END_ALLOW_THREADS @@ -765,7 +775,7 @@ */ Py_BEGIN_ALLOW_THREADS PyThread_start_new_thread(_make_call_from_thread, fn); - _make_call(fn); + success &= _make_call(fn); PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */ Py_END_ALLOW_THREADS @@ -773,6 +783,8 @@ PyThread_release_lock(thread_done); PyThread_free_lock(thread_done); + if (!success) + return NULL; Py_RETURN_NONE; } #endif Modified: python/branches/py3k/Objects/bytearrayobject.c ============================================================================== --- python/branches/py3k/Objects/bytearrayobject.c (original) +++ python/branches/py3k/Objects/bytearrayobject.c Mon Aug 25 23:05:21 2008 @@ -1026,6 +1026,7 @@ #define STRINGLIB_EMPTY nullbytes #define STRINGLIB_CHECK_EXACT PyByteArray_CheckExact #define STRINGLIB_MUTABLE 1 +#define FROM_BYTEARRAY 1 #include "stringlib/fastsearch.h" #include "stringlib/count.h" Modified: python/branches/py3k/Objects/stringlib/find.h ============================================================================== --- python/branches/py3k/Objects/stringlib/find.h (original) +++ python/branches/py3k/Objects/stringlib/find.h Mon Aug 25 23:05:21 2008 @@ -90,7 +90,7 @@ return stringlib_rfind(str + start, end - start, sub, sub_len, start); } -#ifdef STRINGLIB_WANT_CONTAINS_OBJ +#ifdef STRINGLIB_WANT_CONTAINS_OBJ && !defined(FROM_BYTEARRAY) Py_LOCAL_INLINE(int) stringlib_contains_obj(PyObject* str, PyObject* sub) From python-3000-checkins at python.org Tue Aug 26 18:46:48 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 26 Aug 2008 18:46:48 +0200 (CEST) Subject: [Python-3000-checkins] r66038 - in python/branches/py3k: Doc/c-api/bytes.rst Doc/c-api/object.rst Include/bytesobject.h Include/object.h Lib/test/test_bytes.py Misc/NEWS Objects/bytesobject.c Objects/object.c Message-ID: <20080826164648.431B61E4004@bag.python.org> Author: benjamin.peterson Date: Tue Aug 26 18:46:47 2008 New Revision: 66038 Log: make bytes(o) respect __bytes__ #2415 This adds two new C-API functions: PyObject_Bytes and PyBytes_FromObject. Reviewer: Barry Modified: python/branches/py3k/Doc/c-api/bytes.rst python/branches/py3k/Doc/c-api/object.rst python/branches/py3k/Include/bytesobject.h python/branches/py3k/Include/object.h python/branches/py3k/Lib/test/test_bytes.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/bytesobject.c python/branches/py3k/Objects/object.c Modified: python/branches/py3k/Doc/c-api/bytes.rst ============================================================================== --- python/branches/py3k/Doc/c-api/bytes.rst (original) +++ python/branches/py3k/Doc/c-api/bytes.rst Tue Aug 26 18:46:47 2008 @@ -118,6 +118,12 @@ arguments. +.. cfunction:: PyObject* PyBytes_FromObject(PyObject *o) + + Return the bytes representation of object *o* that implements the buffer + protocol. + + .. cfunction:: Py_ssize_t PyBytes_Size(PyObject *o) Return the length of the bytes in bytes object *o*. Modified: python/branches/py3k/Doc/c-api/object.rst ============================================================================== --- python/branches/py3k/Doc/c-api/object.rst (original) +++ python/branches/py3k/Doc/c-api/object.rst Tue Aug 26 18:46:47 2008 @@ -139,6 +139,14 @@ Python expression ``str(o)``. Called by the :func:`str` built-in function and, therefore, by the :func:`print` function. +.. cfunction:: PyObject* PyObject_Bytes(PyObject *o) + + .. index:: builtin: bytes + + Compute a bytes representation of object *o*. *NULL* is returned on failure + and a bytes object on success. This is equivalent to the Python expression + ``bytes(o)``. + .. cfunction:: int PyObject_IsInstance(PyObject *inst, PyObject *cls) Modified: python/branches/py3k/Include/bytesobject.h ============================================================================== --- python/branches/py3k/Include/bytesobject.h (original) +++ python/branches/py3k/Include/bytesobject.h Tue Aug 26 18:46:47 2008 @@ -48,6 +48,7 @@ PyAPI_FUNC(PyObject *) PyBytes_FromStringAndSize(const char *, Py_ssize_t); PyAPI_FUNC(PyObject *) PyBytes_FromString(const char *); +PyAPI_FUNC(PyObject *) PyBytes_FromObject(PyObject *); PyAPI_FUNC(PyObject *) PyBytes_FromFormatV(const char*, va_list) Py_GCC_ATTRIBUTE((format(printf, 1, 0))); PyAPI_FUNC(PyObject *) PyBytes_FromFormat(const char*, ...) Modified: python/branches/py3k/Include/object.h ============================================================================== --- python/branches/py3k/Include/object.h (original) +++ python/branches/py3k/Include/object.h Tue Aug 26 18:46:47 2008 @@ -423,6 +423,7 @@ PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *); PyAPI_FUNC(PyObject *) PyObject_Str(PyObject *); PyAPI_FUNC(PyObject *) PyObject_ASCII(PyObject *); +PyAPI_FUNC(PyObject *) PyObject_Bytes(PyObject *); PyAPI_FUNC(int) PyObject_Compare(PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyObject_RichCompare(PyObject *, PyObject *, int); PyAPI_FUNC(int) PyObject_RichCompareBool(PyObject *, PyObject *, int); Modified: python/branches/py3k/Lib/test/test_bytes.py ============================================================================== --- python/branches/py3k/Lib/test/test_bytes.py (original) +++ python/branches/py3k/Lib/test/test_bytes.py Tue Aug 26 18:46:47 2008 @@ -458,6 +458,18 @@ with open(fd, "rb", buffering=0) as f: self.assertRaises(TypeError, f.readinto, b"") + def test_custom(self): + class A: + def __bytes__(self): + return b'abc' + self.assertEqual(bytes(A()), b'abc') + class A: pass + self.assertRaises(TypeError, bytes, A()) + class A: + def __bytes__(self): + return None + self.assertRaises(TypeError, bytes, A()) + class ByteArrayTest(BaseBytesTest): type2test = bytearray Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Tue Aug 26 18:46:47 2008 @@ -27,6 +27,13 @@ - Issue #3650: Fixed a reference leak in bytes.split('x'). +- bytes(o) now tries to use o.__bytes__() before using fallbacks. + +C API +----- + +- PyObject_Bytes and PyBytes_FromObject were added. + Library ------- Modified: python/branches/py3k/Objects/bytesobject.c ============================================================================== --- python/branches/py3k/Objects/bytesobject.c (original) +++ python/branches/py3k/Objects/bytesobject.c Tue Aug 26 18:46:47 2008 @@ -2882,11 +2882,10 @@ static PyObject * string_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *x = NULL, *it; + PyObject *x = NULL; const char *encoding = NULL; const char *errors = NULL; PyObject *new = NULL; - Py_ssize_t i, size; static char *kwlist[] = {"source", "encoding", "errors", 0}; if (type != &PyBytes_Type) @@ -2924,6 +2923,14 @@ "encoding or errors without a string argument"); return NULL; } + return PyObject_Bytes(x); +} + +PyObject * +PyBytes_FromObject(PyObject *x) +{ + PyObject *new, *it; + Py_ssize_t i, size; /* Is it an int? */ size = PyNumber_AsSsize_t(x, PyExc_ValueError); Modified: python/branches/py3k/Objects/object.c ============================================================================== --- python/branches/py3k/Objects/object.c (original) +++ python/branches/py3k/Objects/object.c Tue Aug 26 18:46:47 2008 @@ -453,6 +453,45 @@ return res; } +PyObject * +PyObject_Bytes(PyObject *v) +{ + PyObject *bytesmeth, *result, *func; + static PyObject *bytesstring = NULL; + + if (bytesstring == NULL) { + bytesstring = PyUnicode_InternFromString("__bytes__"); + if (bytesstring == NULL) + return NULL; + } + + if (v == NULL) + return PyBytes_FromString(""); + + if (PyBytes_CheckExact(v)) { + Py_INCREF(v); + return v; + } + + /* Doesn't create a reference */ + func = _PyType_Lookup(Py_TYPE(v), bytesstring); + if (func != NULL) { + result = PyObject_CallFunctionObjArgs(func, v, NULL); + if (result == NULL) + return NULL; + if (!PyBytes_Check(result)) { + PyErr_Format(PyExc_TypeError, + "__bytes__ returned non-bytes (type %.200s)", + Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; + } + return result; + } + PyErr_Clear(); + return PyBytes_FromObject(v); +} + /* The new comparison philosophy is: we completely separate three-way comparison from rich comparison. That is, PyObject_Compare() and PyObject_Cmp() *just* use the tp_compare slot. And PyObject_RichCompare() From python-3000-checkins at python.org Tue Aug 26 19:14:31 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Tue, 26 Aug 2008 19:14:31 +0200 (CEST) Subject: [Python-3000-checkins] r66040 - python/branches/py3k Message-ID: <20080826171431.5965D1E401A@bag.python.org> Author: benjamin.peterson Date: Tue Aug 26 19:14:31 2008 New Revision: 66040 Log: Blocked revisions 66039 via svnmerge ........ r66039 | benjamin.peterson | 2008-08-26 12:08:40 -0500 (Tue, 26 Aug 2008) | 1 line sort of backport 66038 by aliasing PyObject_Bytes to PyObject_Str ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Wed Aug 27 00:02:58 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Wed, 27 Aug 2008 00:02:58 +0200 (CEST) Subject: [Python-3000-checkins] r66041 - in python/branches/py3k: Misc/NEWS Python/pythonrun.c Message-ID: <20080826220258.DBF3E1E4004@bag.python.org> Author: antoine.pitrou Date: Wed Aug 27 00:02:58 2008 New Revision: 66041 Log: #3663: extra DECREF on syntax errors. Patch by Amaury Forgeot d'Arc, reviewed by Benjamin Peterson. Modified: python/branches/py3k/Misc/NEWS python/branches/py3k/Python/pythonrun.c Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Aug 27 00:02:58 2008 @@ -12,6 +12,8 @@ Core and Builtins ----------------- +- Issue #3663: Py_None was decref'd when printing SyntaxErrors. + - Issue #3657: Fix uninitialized memory read when pickling longs. Found by valgrind. Modified: python/branches/py3k/Python/pythonrun.c ============================================================================== --- python/branches/py3k/Python/pythonrun.c (original) +++ python/branches/py3k/Python/pythonrun.c Wed Aug 27 00:02:58 2008 @@ -1242,7 +1242,10 @@ if (exception == NULL) return; PyErr_NormalizeException(&exception, &v, &tb); - tb = tb ? tb : Py_None; + if (tb == NULL) { + tb = Py_None; + Py_INCREF(tb); + } PyException_SetTraceback(v, tb); if (exception == NULL) return; From python-3000-checkins at python.org Wed Aug 27 00:40:49 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Wed, 27 Aug 2008 00:40:49 +0200 (CEST) Subject: [Python-3000-checkins] r66042 - in python/branches/py3k: Include/abstract.h Lib/test/test_abc.py Lib/test/test_exceptions.py Lib/test/test_typechecks.py Misc/NEWS Objects/abstract.c Objects/typeobject.c Python/errors.c Message-ID: <20080826224049.174771E4004@bag.python.org> Author: antoine.pitrou Date: Wed Aug 27 00:40:48 2008 New Revision: 66042 Log: Issue #2534: speed up isinstance() and issubclass() by 50-70%, so as to match Python 2.5 speed despite the __instancecheck__ / __subclasscheck__ mechanism. In the process, fix a bug where isinstance() and issubclass(), when given a tuple of classes as second argument, were looking up __instancecheck__ / __subclasscheck__ on the tuple rather than on each type object. Reviewed by Benjamin Peterson and Raymond Hettinger. Modified: python/branches/py3k/Include/abstract.h python/branches/py3k/Lib/test/test_abc.py python/branches/py3k/Lib/test/test_exceptions.py python/branches/py3k/Lib/test/test_typechecks.py python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/abstract.c python/branches/py3k/Objects/typeobject.c python/branches/py3k/Python/errors.c Modified: python/branches/py3k/Include/abstract.h ============================================================================== --- python/branches/py3k/Include/abstract.h (original) +++ python/branches/py3k/Include/abstract.h Wed Aug 27 00:40:48 2008 @@ -1273,6 +1273,11 @@ /* issubclass(object, typeorclass) */ +PyAPI_FUNC(int) _PyObject_RealIsInstance(PyObject *inst, PyObject *cls); + +PyAPI_FUNC(int) _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls); + + #ifdef __cplusplus } #endif Modified: python/branches/py3k/Lib/test/test_abc.py ============================================================================== --- python/branches/py3k/Lib/test/test_abc.py (original) +++ python/branches/py3k/Lib/test/test_abc.py Wed Aug 27 00:40:48 2008 @@ -75,15 +75,21 @@ pass b = B() self.assertEqual(issubclass(B, A), False) + self.assertEqual(issubclass(B, (A,)), False) self.assertEqual(isinstance(b, A), False) + self.assertEqual(isinstance(b, (A,)), False) A.register(B) self.assertEqual(issubclass(B, A), True) + self.assertEqual(issubclass(B, (A,)), True) self.assertEqual(isinstance(b, A), True) + self.assertEqual(isinstance(b, (A,)), True) class C(B): pass c = C() self.assertEqual(issubclass(C, A), True) + self.assertEqual(issubclass(C, (A,)), True) self.assertEqual(isinstance(c, A), True) + self.assertEqual(isinstance(c, (A,)), True) def test_isinstance_invalidation(self): class A(metaclass=abc.ABCMeta): @@ -92,22 +98,29 @@ pass b = B() self.assertEqual(isinstance(b, A), False) + self.assertEqual(isinstance(b, (A,)), False) A.register(B) self.assertEqual(isinstance(b, A), True) + self.assertEqual(isinstance(b, (A,)), True) def test_registration_builtins(self): class A(metaclass=abc.ABCMeta): pass A.register(int) self.assertEqual(isinstance(42, A), True) + self.assertEqual(isinstance(42, (A,)), True) self.assertEqual(issubclass(int, A), True) + self.assertEqual(issubclass(int, (A,)), True) class B(A): pass B.register(str) class C(str): pass self.assertEqual(isinstance("", A), True) + self.assertEqual(isinstance("", (A,)), True) self.assertEqual(issubclass(str, A), True) + self.assertEqual(issubclass(str, (A,)), True) self.assertEqual(issubclass(C, A), True) + self.assertEqual(issubclass(C, (A,)), True) def test_registration_edge_cases(self): class A(metaclass=abc.ABCMeta): @@ -130,29 +143,40 @@ class A(metaclass=abc.ABCMeta): pass self.failUnless(issubclass(A, A)) + self.failUnless(issubclass(A, (A,))) class B(metaclass=abc.ABCMeta): pass self.failIf(issubclass(A, B)) + self.failIf(issubclass(A, (B,))) self.failIf(issubclass(B, A)) + self.failIf(issubclass(B, (A,))) class C(metaclass=abc.ABCMeta): pass A.register(B) class B1(B): pass self.failUnless(issubclass(B1, A)) + self.failUnless(issubclass(B1, (A,))) class C1(C): pass B1.register(C1) self.failIf(issubclass(C, B)) + self.failIf(issubclass(C, (B,))) self.failIf(issubclass(C, B1)) + self.failIf(issubclass(C, (B1,))) self.failUnless(issubclass(C1, A)) + self.failUnless(issubclass(C1, (A,))) self.failUnless(issubclass(C1, B)) + self.failUnless(issubclass(C1, (B,))) self.failUnless(issubclass(C1, B1)) + self.failUnless(issubclass(C1, (B1,))) C1.register(int) class MyInt(int): pass self.failUnless(issubclass(MyInt, A)) + self.failUnless(issubclass(MyInt, (A,))) self.failUnless(isinstance(42, A)) + self.failUnless(isinstance(42, (A,))) def test_all_new_methods_are_called(self): class A(metaclass=abc.ABCMeta): Modified: python/branches/py3k/Lib/test/test_exceptions.py ============================================================================== --- python/branches/py3k/Lib/test/test_exceptions.py (original) +++ python/branches/py3k/Lib/test/test_exceptions.py Wed Aug 27 00:40:48 2008 @@ -582,12 +582,18 @@ except KeyError: pass except: - self.fail("Should have raised TypeError") + self.fail("Should have raised KeyError") else: - self.fail("Should have raised TypeError") - self.assertEqual(stderr.getvalue(), - "Exception ValueError: ValueError() " - "in ignored\n") + self.fail("Should have raised KeyError") + + def g(): + try: + return g() + except RuntimeError: + return sys.exc_info() + e, v, tb = g() + self.assert_(isinstance(v, RuntimeError), type(v)) + self.assert_("maximum recursion depth exceeded" in str(v), str(v)) def test_MemoryError(self): Modified: python/branches/py3k/Lib/test/test_typechecks.py ============================================================================== --- python/branches/py3k/Lib/test/test_typechecks.py (original) +++ python/branches/py3k/Lib/test/test_typechecks.py Wed Aug 27 00:40:48 2008 @@ -33,26 +33,39 @@ def testIsSubclassBuiltin(self): self.assertEqual(issubclass(int, Integer), True) + self.assertEqual(issubclass(int, (Integer,)), True) self.assertEqual(issubclass(float, Integer), False) + self.assertEqual(issubclass(float, (Integer,)), False) def testIsInstanceBuiltin(self): self.assertEqual(isinstance(42, Integer), True) + self.assertEqual(isinstance(42, (Integer,)), True) self.assertEqual(isinstance(3.14, Integer), False) + self.assertEqual(isinstance(3.14, (Integer,)), False) def testIsInstanceActual(self): self.assertEqual(isinstance(Integer(), Integer), True) + self.assertEqual(isinstance(Integer(), (Integer,)), True) def testIsSubclassActual(self): self.assertEqual(issubclass(Integer, Integer), True) + self.assertEqual(issubclass(Integer, (Integer,)), True) def testSubclassBehavior(self): self.assertEqual(issubclass(SubInt, Integer), True) + self.assertEqual(issubclass(SubInt, (Integer,)), True) self.assertEqual(issubclass(SubInt, SubInt), True) + self.assertEqual(issubclass(SubInt, (SubInt,)), True) self.assertEqual(issubclass(Integer, SubInt), False) + self.assertEqual(issubclass(Integer, (SubInt,)), False) self.assertEqual(issubclass(int, SubInt), False) + self.assertEqual(issubclass(int, (SubInt,)), False) self.assertEqual(isinstance(SubInt(), Integer), True) + self.assertEqual(isinstance(SubInt(), (Integer,)), True) self.assertEqual(isinstance(SubInt(), SubInt), True) + self.assertEqual(isinstance(SubInt(), (SubInt,)), True) self.assertEqual(isinstance(42, SubInt), False) + self.assertEqual(isinstance(42, (SubInt,)), False) def test_main(): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Aug 27 00:40:48 2008 @@ -12,6 +12,13 @@ Core and Builtins ----------------- +- Issue #2534: speed up isinstance() and issubclass() by 50-70%, so as to + match Python 2.5 speed despite the __instancecheck__ / __subclasscheck__ + mechanism. In the process, fix a bug where isinstance() and issubclass(), + when given a tuple of classes as second argument, were looking up + __instancecheck__ / __subclasscheck__ on the tuple rather than on each + type object. + - Issue #3663: Py_None was decref'd when printing SyntaxErrors. - Issue #3657: Fix uninitialized memory read when pickling longs. Modified: python/branches/py3k/Objects/abstract.c ============================================================================== --- python/branches/py3k/Objects/abstract.c (original) +++ python/branches/py3k/Objects/abstract.c Wed Aug 27 00:40:48 2008 @@ -2474,39 +2474,38 @@ static int abstract_issubclass(PyObject *derived, PyObject *cls) { - PyObject *bases; + PyObject *bases = NULL; Py_ssize_t i, n; int r = 0; - - if (derived == cls) - return 1; - - if (PyTuple_Check(cls)) { - /* Not a general sequence -- that opens up the road to - recursion and stack overflow. */ - n = PyTuple_GET_SIZE(cls); + while (1) { + if (derived == cls) + return 1; + bases = abstract_get_bases(derived); + if (bases == NULL) { + if (PyErr_Occurred()) + return -1; + return 0; + } + n = PyTuple_GET_SIZE(bases); + if (n == 0) { + Py_DECREF(bases); + return 0; + } + /* Avoid recursivity in the single inheritance case */ + if (n == 1) { + derived = PyTuple_GET_ITEM(bases, 0); + Py_DECREF(bases); + continue; + } for (i = 0; i < n; i++) { - if (derived == PyTuple_GET_ITEM(cls, i)) - return 1; + r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls); + if (r != 0) + break; } + Py_DECREF(bases); + return r; } - bases = abstract_get_bases(derived); - if (bases == NULL) { - if (PyErr_Occurred()) - return -1; - return 0; - } - n = PyTuple_GET_SIZE(bases); - for (i = 0; i < n; i++) { - r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls); - if (r != 0) - break; - } - - Py_DECREF(bases); - - return r; } static int @@ -2524,7 +2523,7 @@ } static int -recursive_isinstance(PyObject *inst, PyObject *cls, int recursion_depth) +recursive_isinstance(PyObject *inst, PyObject *cls) { PyObject *icls; static PyObject *__class__ = NULL; @@ -2553,25 +2552,6 @@ } } } - else if (PyTuple_Check(cls)) { - Py_ssize_t i, n; - - if (!recursion_depth) { - PyErr_SetString(PyExc_RuntimeError, - "nest level of tuple too deep"); - return -1; - } - - n = PyTuple_GET_SIZE(cls); - for (i = 0; i < n; i++) { - retval = recursive_isinstance( - inst, - PyTuple_GET_ITEM(cls, i), - recursion_depth-1); - if (retval != 0) - break; - } - } else { if (!check_class(cls, "isinstance() arg 2 must be a class, type," @@ -2601,6 +2581,24 @@ if (Py_TYPE(inst) == (PyTypeObject *)cls) return 1; + if (PyTuple_Check(cls)) { + Py_ssize_t i; + Py_ssize_t n; + int r = 0; + + if (Py_EnterRecursiveCall(" in __instancecheck__")) + return -1; + n = PyTuple_GET_SIZE(cls); + for (i = 0; i < n; ++i) { + PyObject *item = PyTuple_GET_ITEM(cls, i); + r = PyObject_IsInstance(inst, item); + if (r != 0) + /* either found it, or got an error */ + break; + } + Py_LeaveRecursiveCall(); + return r; + } if (name == NULL) { name = PyUnicode_InternFromString("__instancecheck__"); if (name == NULL) @@ -2625,51 +2623,25 @@ } return ok; } - return recursive_isinstance(inst, cls, Py_GetRecursionLimit()); + return recursive_isinstance(inst, cls); } static int -recursive_issubclass(PyObject *derived, PyObject *cls, int recursion_depth) +recursive_issubclass(PyObject *derived, PyObject *cls) { - int retval; + if (PyType_Check(cls) && PyType_Check(derived)) { + /* Fast path (non-recursive) */ + return PyType_IsSubtype((PyTypeObject *)derived, (PyTypeObject *)cls); + } + if (!check_class(derived, + "issubclass() arg 1 must be a class")) + return -1; + if (!check_class(cls, + "issubclass() arg 2 must be a class" + " or tuple of classes")) + return -1; - { - if (!check_class(derived, - "issubclass() arg 1 must be a class")) - return -1; - - if (PyTuple_Check(cls)) { - Py_ssize_t i; - Py_ssize_t n = PyTuple_GET_SIZE(cls); - - if (!recursion_depth) { - PyErr_SetString(PyExc_RuntimeError, - "nest level of tuple too deep"); - return -1; - } - for (i = 0; i < n; ++i) { - retval = recursive_issubclass( - derived, - PyTuple_GET_ITEM(cls, i), - recursion_depth-1); - if (retval != 0) { - /* either found it, or got an error */ - return retval; - } - } - return 0; - } - else { - if (!check_class(cls, - "issubclass() arg 2 must be a class" - " or tuple of classes")) - return -1; - } - - retval = abstract_issubclass(derived, cls); - } - - return retval; + return abstract_issubclass(derived, cls); } int @@ -2678,20 +2650,40 @@ static PyObject *name = NULL; PyObject *t, *v, *tb; PyObject *checker; - PyErr_Fetch(&t, &v, &tb); + if (PyTuple_Check(cls)) { + Py_ssize_t i; + Py_ssize_t n; + int r = 0; + + if (Py_EnterRecursiveCall(" in __subclasscheck__")) + return -1; + n = PyTuple_GET_SIZE(cls); + for (i = 0; i < n; ++i) { + PyObject *item = PyTuple_GET_ITEM(cls, i); + r = PyObject_IsSubclass(derived, item); + if (r != 0) + /* either found it, or got an error */ + break; + } + Py_LeaveRecursiveCall(); + return r; + } if (name == NULL) { name = PyUnicode_InternFromString("__subclasscheck__"); if (name == NULL) return -1; } + PyErr_Fetch(&t, &v, &tb); checker = PyObject_GetAttr(cls, name); PyErr_Restore(t, v, tb); if (checker != NULL) { PyObject *res; int ok = -1; - if (Py_EnterRecursiveCall(" in __subclasscheck__")) + if (Py_EnterRecursiveCall(" in __subclasscheck__")) { + Py_DECREF(checker); return ok; + } res = PyObject_CallFunctionObjArgs(checker, derived, NULL); Py_LeaveRecursiveCall(); Py_DECREF(checker); @@ -2701,7 +2693,19 @@ } return ok; } - return recursive_issubclass(derived, cls, Py_GetRecursionLimit()); + return recursive_issubclass(derived, cls); +} + +int +_PyObject_RealIsInstance(PyObject *inst, PyObject *cls) +{ + return recursive_isinstance(inst, cls); +} + +int +_PyObject_RealIsSubclass(PyObject *derived, PyObject *cls) +{ + return recursive_issubclass(derived, cls); } Modified: python/branches/py3k/Objects/typeobject.c ============================================================================== --- python/branches/py3k/Objects/typeobject.c (original) +++ python/branches/py3k/Objects/typeobject.c Wed Aug 27 00:40:48 2008 @@ -584,6 +584,49 @@ return result; } +static PyObject * +type___instancecheck__(PyObject *type, PyObject *inst) +{ + switch (_PyObject_RealIsInstance(inst, type)) { + case -1: + return NULL; + case 0: + Py_RETURN_FALSE; + default: + Py_RETURN_TRUE; + } +} + + +static PyObject * +type_get_instancecheck(PyObject *type, void *context) +{ + static PyMethodDef ml = {"__instancecheck__", + type___instancecheck__, METH_O }; + return PyCFunction_New(&ml, type); +} + +static PyObject * +type___subclasscheck__(PyObject *type, PyObject *inst) +{ + switch (_PyObject_RealIsSubclass(inst, type)) { + case -1: + return NULL; + case 0: + Py_RETURN_FALSE; + default: + Py_RETURN_TRUE; + } +} + +static PyObject * +type_get_subclasscheck(PyObject *type, void *context) +{ + static PyMethodDef ml = {"__subclasscheck__", + type___subclasscheck__, METH_O }; + return PyCFunction_New(&ml, type); +} + static PyGetSetDef type_getsets[] = { {"__name__", (getter)type_name, (setter)type_set_name, NULL}, {"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL}, @@ -592,6 +635,8 @@ (setter)type_set_abstractmethods, NULL}, {"__dict__", (getter)type_dict, NULL, NULL}, {"__doc__", (getter)type_get_doc, NULL, NULL}, + {"__instancecheck__", (getter)type_get_instancecheck, NULL, NULL}, + {"__subclasscheck__", (getter)type_get_subclasscheck, NULL, NULL}, {0} }; Modified: python/branches/py3k/Python/errors.c ============================================================================== --- python/branches/py3k/Python/errors.c (original) +++ python/branches/py3k/Python/errors.c Wed Aug 27 00:40:48 2008 @@ -160,11 +160,12 @@ int res = 0; PyObject *exception, *value, *tb; PyErr_Fetch(&exception, &value, &tb); - res = PyObject_IsSubclass(err, exc); + /* PyObject_IsSubclass() can recurse and therefore is + not safe (see test_bad_getattr in test.pickletester). */ + res = PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc); /* This function must not fail, so print the error here */ if (res == -1) { PyErr_WriteUnraisable(err); - /* issubclass did not succeed */ res = 0; } PyErr_Restore(exception, value, tb); From python-3000-checkins at python.org Wed Aug 27 00:44:20 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Wed, 27 Aug 2008 00:44:20 +0200 (CEST) Subject: [Python-3000-checkins] r66044 - python/branches/py3k Message-ID: <20080826224420.4A1D61E4004@bag.python.org> Author: antoine.pitrou Date: Wed Aug 27 00:44:20 2008 New Revision: 66044 Log: Blocked revisions 66043 via svnmerge ........ r66043 | antoine.pitrou | 2008-08-27 00:42:08 +0200 (mer., 27 ao?t 2008) | 11 lines Issue #2534: speed up isinstance() and issubclass() by 50-70%, so as to match Python 2.5 speed despite the __instancecheck__ / __subclasscheck__ mechanism. In the process, fix a bug where isinstance() and issubclass(), when given a tuple of classes as second argument, were looking up __instancecheck__ / __subclasscheck__ on the tuple rather than on each type object. Reviewed by Benjamin Peterson and Raymond Hettinger. ........ Modified: python/branches/py3k/ (props changed) From nnorwitz at gmail.com Wed Aug 27 01:53:52 2008 From: nnorwitz at gmail.com (Neal Norwitz) Date: Tue, 26 Aug 2008 16:53:52 -0700 Subject: [Python-3000-checkins] r66038 - in python/branches/py3k: Doc/c-api/bytes.rst Doc/c-api/object.rst Include/bytesobject.h Include/object.h Lib/test/test_bytes.py Misc/NEWS Objects/bytesobject.c Objects/object.c In-Reply-To: <20080826164648.431B61E4004@bag.python.org> References: <20080826164648.431B61E4004@bag.python.org> Message-ID: On Tue, Aug 26, 2008 at 9:46 AM, benjamin.peterson wrote: > Modified: python/branches/py3k/Objects/bytesobject.c > ============================================================================== > --- python/branches/py3k/Objects/bytesobject.c (original) > +++ python/branches/py3k/Objects/bytesobject.c Tue Aug 26 18:46:47 2008 > @@ -2924,6 +2923,14 @@ > "encoding or errors without a string argument"); > return NULL; > } > + return PyObject_Bytes(x); > +} > + > +PyObject * > +PyBytes_FromObject(PyObject *x) > +{ > + PyObject *new, *it; > + Py_ssize_t i, size; > > /* Is it an int? */ > size = PyNumber_AsSsize_t(x, PyExc_ValueError); What happens if x (the object passed in) is NULL? n From musiccomposition at gmail.com Wed Aug 27 02:02:21 2008 From: musiccomposition at gmail.com (Benjamin Peterson) Date: Tue, 26 Aug 2008 19:02:21 -0500 Subject: [Python-3000-checkins] r66038 - in python/branches/py3k: Doc/c-api/bytes.rst Doc/c-api/object.rst Include/bytesobject.h Include/object.h Lib/test/test_bytes.py Misc/NEWS Objects/bytesobject.c Objects/object.c In-Reply-To: References: <20080826164648.431B61E4004@bag.python.org> Message-ID: <1afaf6160808261702u36065e19k362108d42e78abad@mail.gmail.com> On Tue, Aug 26, 2008 at 6:53 PM, Neal Norwitz wrote: > On Tue, Aug 26, 2008 at 9:46 AM, benjamin.peterson > wrote: >> Modified: python/branches/py3k/Objects/bytesobject.c >> ============================================================================== >> --- python/branches/py3k/Objects/bytesobject.c (original) >> +++ python/branches/py3k/Objects/bytesobject.c Tue Aug 26 18:46:47 2008 >> @@ -2924,6 +2923,14 @@ >> "encoding or errors without a string argument"); >> return NULL; >> } >> + return PyObject_Bytes(x); >> +} >> + >> +PyObject * >> +PyBytes_FromObject(PyObject *x) >> +{ >> + PyObject *new, *it; >> + Py_ssize_t i, size; >> >> /* Is it an int? */ >> size = PyNumber_AsSsize_t(x, PyExc_ValueError); > > What happens if x (the object passed in) is NULL? It segfaults, but this is ok because PyObject_Bytes checks for NULL. > > n > _______________________________________________ > Python-3000-checkins mailing list > Python-3000-checkins at python.org > http://mail.python.org/mailman/listinfo/python-3000-checkins > -- Cheers, Benjamin Peterson "There's no place like 127.0.0.1." From nnorwitz at gmail.com Wed Aug 27 02:04:36 2008 From: nnorwitz at gmail.com (Neal Norwitz) Date: Tue, 26 Aug 2008 17:04:36 -0700 Subject: [Python-3000-checkins] r66038 - in python/branches/py3k: Doc/c-api/bytes.rst Doc/c-api/object.rst Include/bytesobject.h Include/object.h Lib/test/test_bytes.py Misc/NEWS Objects/bytesobject.c Objects/object.c In-Reply-To: <1afaf6160808261702u36065e19k362108d42e78abad@mail.gmail.com> References: <20080826164648.431B61E4004@bag.python.org> <1afaf6160808261702u36065e19k362108d42e78abad@mail.gmail.com> Message-ID: On Tue, Aug 26, 2008 at 5:02 PM, Benjamin Peterson wrote: > On Tue, Aug 26, 2008 at 6:53 PM, Neal Norwitz wrote: >> On Tue, Aug 26, 2008 at 9:46 AM, benjamin.peterson >> wrote: >>> Modified: python/branches/py3k/Objects/bytesobject.c >>> ============================================================================== >>> --- python/branches/py3k/Objects/bytesobject.c (original) >>> +++ python/branches/py3k/Objects/bytesobject.c Tue Aug 26 18:46:47 2008 >>> @@ -2924,6 +2923,14 @@ >>> "encoding or errors without a string argument"); >>> return NULL; >>> } >>> + return PyObject_Bytes(x); >>> +} >>> + >>> +PyObject * >>> +PyBytes_FromObject(PyObject *x) >>> +{ >>> + PyObject *new, *it; >>> + Py_ssize_t i, size; >>> >>> /* Is it an int? */ >>> size = PyNumber_AsSsize_t(x, PyExc_ValueError); >> >> What happens if x (the object passed in) is NULL? > > It segfaults, but this is ok because PyObject_Bytes checks for NULL. Since this is now a public API, anyone can pass NULL here. In general we check for NULLs from most public APIs (I think). Though IIRC we are pretty inconsistent. n From musiccomposition at gmail.com Wed Aug 27 02:13:03 2008 From: musiccomposition at gmail.com (Benjamin Peterson) Date: Tue, 26 Aug 2008 19:13:03 -0500 Subject: [Python-3000-checkins] r66038 - in python/branches/py3k: Doc/c-api/bytes.rst Doc/c-api/object.rst Include/bytesobject.h Include/object.h Lib/test/test_bytes.py Misc/NEWS Objects/bytesobject.c Objects/object.c In-Reply-To: References: <20080826164648.431B61E4004@bag.python.org> <1afaf6160808261702u36065e19k362108d42e78abad@mail.gmail.com> Message-ID: <1afaf6160808261713s72a43b02w5b0617b1ae21b69f@mail.gmail.com> On Tue, Aug 26, 2008 at 7:04 PM, Neal Norwitz wrote: > On Tue, Aug 26, 2008 at 5:02 PM, Benjamin Peterson > wrote: >> On Tue, Aug 26, 2008 at 6:53 PM, Neal Norwitz wrote: >>> On Tue, Aug 26, 2008 at 9:46 AM, benjamin.peterson >>> wrote: >>>> Modified: python/branches/py3k/Objects/bytesobject.c >>>> ============================================================================== >>>> --- python/branches/py3k/Objects/bytesobject.c (original) >>>> +++ python/branches/py3k/Objects/bytesobject.c Tue Aug 26 18:46:47 2008 >>>> @@ -2924,6 +2923,14 @@ >>>> "encoding or errors without a string argument"); >>>> return NULL; >>>> } >>>> + return PyObject_Bytes(x); >>>> +} >>>> + >>>> +PyObject * >>>> +PyBytes_FromObject(PyObject *x) >>>> +{ >>>> + PyObject *new, *it; >>>> + Py_ssize_t i, size; >>>> >>>> /* Is it an int? */ >>>> size = PyNumber_AsSsize_t(x, PyExc_ValueError); >>> >>> What happens if x (the object passed in) is NULL? >> >> It segfaults, but this is ok because PyObject_Bytes checks for NULL. > > Since this is now a public API, anyone can pass NULL here. In general > we check for NULLs from most public APIs (I think). Though IIRC we > are pretty inconsistent. I wasn't under that impression. For example, a quick glance shows that none of the PyList API functions check for NULL. Anyway, what should PyBytes_FromObject return for NULL anyway? Probably just another NULL. > > n > -- Cheers, Benjamin Peterson "There's no place like 127.0.0.1." From nnorwitz at gmail.com Wed Aug 27 02:25:12 2008 From: nnorwitz at gmail.com (Neal Norwitz) Date: Tue, 26 Aug 2008 17:25:12 -0700 Subject: [Python-3000-checkins] r66038 - in python/branches/py3k: Doc/c-api/bytes.rst Doc/c-api/object.rst Include/bytesobject.h Include/object.h Lib/test/test_bytes.py Misc/NEWS Objects/bytesobject.c Objects/object.c In-Reply-To: <1afaf6160808261713s72a43b02w5b0617b1ae21b69f@mail.gmail.com> References: <20080826164648.431B61E4004@bag.python.org> <1afaf6160808261702u36065e19k362108d42e78abad@mail.gmail.com> <1afaf6160808261713s72a43b02w5b0617b1ae21b69f@mail.gmail.com> Message-ID: On Tue, Aug 26, 2008 at 5:13 PM, Benjamin Peterson wrote: > On Tue, Aug 26, 2008 at 7:04 PM, Neal Norwitz wrote: >> On Tue, Aug 26, 2008 at 5:02 PM, Benjamin Peterson >> wrote: >>> On Tue, Aug 26, 2008 at 6:53 PM, Neal Norwitz wrote: >>>> On Tue, Aug 26, 2008 at 9:46 AM, benjamin.peterson >>>> wrote: >>>>> Modified: python/branches/py3k/Objects/bytesobject.c >>>>> ============================================================================== >>>>> --- python/branches/py3k/Objects/bytesobject.c (original) >>>>> +++ python/branches/py3k/Objects/bytesobject.c Tue Aug 26 18:46:47 2008 >>>>> @@ -2924,6 +2923,14 @@ >>>>> "encoding or errors without a string argument"); >>>>> return NULL; >>>>> } >>>>> + return PyObject_Bytes(x); >>>>> +} >>>>> + >>>>> +PyObject * >>>>> +PyBytes_FromObject(PyObject *x) >>>>> +{ >>>>> + PyObject *new, *it; >>>>> + Py_ssize_t i, size; >>>>> >>>>> /* Is it an int? */ >>>>> size = PyNumber_AsSsize_t(x, PyExc_ValueError); >>>> >>>> What happens if x (the object passed in) is NULL? >>> >>> It segfaults, but this is ok because PyObject_Bytes checks for NULL. >> >> Since this is now a public API, anyone can pass NULL here. In general >> we check for NULLs from most public APIs (I think). Though IIRC we >> are pretty inconsistent. > > I wasn't under that impression. For example, a quick glance shows that > none of the PyList API functions check for NULL. Like I said, we're inconsistent. :-) We discussed this on python-dev a while ago, but there wasn't really any resolution IIRC. I generally prefer to be safe which is why I prefer to have checks unless there's a good reason not to. > Anyway, what should PyBytes_FromObject return for NULL anyway? > Probably just another NULL. Objects/dictobject.c has good examples. Something like: if (x == NULL) { PyErr_BadInternalCall(); return NULL; } n From python-3000-checkins at python.org Wed Aug 27 02:28:35 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Wed, 27 Aug 2008 02:28:35 +0200 (CEST) Subject: [Python-3000-checkins] r66046 - python/branches/py3k/Objects/bytesobject.c Message-ID: <20080827002835.263AE1E4006@bag.python.org> Author: benjamin.peterson Date: Wed Aug 27 02:28:34 2008 New Revision: 66046 Log: add NULL checking for PyBytes_FromObject; R=Neal Modified: python/branches/py3k/Objects/bytesobject.c Modified: python/branches/py3k/Objects/bytesobject.c ============================================================================== --- python/branches/py3k/Objects/bytesobject.c (original) +++ python/branches/py3k/Objects/bytesobject.c Wed Aug 27 02:28:34 2008 @@ -2932,6 +2932,11 @@ PyObject *new, *it; Py_ssize_t i, size; + if (x == NULL) { + PyErr_BadInternalCall(); + return NULL; + } + /* Is it an int? */ size = PyNumber_AsSsize_t(x, PyExc_ValueError); if (size == -1 && PyErr_Occurred()) { From musiccomposition at gmail.com Wed Aug 27 02:28:53 2008 From: musiccomposition at gmail.com (Benjamin Peterson) Date: Tue, 26 Aug 2008 19:28:53 -0500 Subject: [Python-3000-checkins] r66038 - in python/branches/py3k: Doc/c-api/bytes.rst Doc/c-api/object.rst Include/bytesobject.h Include/object.h Lib/test/test_bytes.py Misc/NEWS Objects/bytesobject.c Objects/object.c In-Reply-To: References: <20080826164648.431B61E4004@bag.python.org> <1afaf6160808261702u36065e19k362108d42e78abad@mail.gmail.com> <1afaf6160808261713s72a43b02w5b0617b1ae21b69f@mail.gmail.com> Message-ID: <1afaf6160808261728g252754afx6096cb48196b3dbb@mail.gmail.com> On Tue, Aug 26, 2008 at 7:25 PM, Neal Norwitz wrote: > On Tue, Aug 26, 2008 at 5:13 PM, Benjamin Peterson > wrote: >> On Tue, Aug 26, 2008 at 7:04 PM, Neal Norwitz wrote: >>> On Tue, Aug 26, 2008 at 5:02 PM, Benjamin Peterson >>> wrote: >>>> On Tue, Aug 26, 2008 at 6:53 PM, Neal Norwitz wrote: >>>>> On Tue, Aug 26, 2008 at 9:46 AM, benjamin.peterson >>>>> wrote: >>>>>> Modified: python/branches/py3k/Objects/bytesobject.c >>>>>> ============================================================================== >>>>>> --- python/branches/py3k/Objects/bytesobject.c (original) >>>>>> +++ python/branches/py3k/Objects/bytesobject.c Tue Aug 26 18:46:47 2008 >>>>>> @@ -2924,6 +2923,14 @@ >>>>>> "encoding or errors without a string argument"); >>>>>> return NULL; >>>>>> } >>>>>> + return PyObject_Bytes(x); >>>>>> +} >>>>>> + >>>>>> +PyObject * >>>>>> +PyBytes_FromObject(PyObject *x) >>>>>> +{ >>>>>> + PyObject *new, *it; >>>>>> + Py_ssize_t i, size; >>>>>> >>>>>> /* Is it an int? */ >>>>>> size = PyNumber_AsSsize_t(x, PyExc_ValueError); >>>>> >>>>> What happens if x (the object passed in) is NULL? >>>> >>>> It segfaults, but this is ok because PyObject_Bytes checks for NULL. >>> >>> Since this is now a public API, anyone can pass NULL here. In general >>> we check for NULLs from most public APIs (I think). Though IIRC we >>> are pretty inconsistent. >> >> I wasn't under that impression. For example, a quick glance shows that >> none of the PyList API functions check for NULL. > > Like I said, we're inconsistent. :-) We discussed this on python-dev > a while ago, but there wasn't really any resolution IIRC. > > I generally prefer to be safe which is why I prefer to have checks > unless there's a good reason not to. > >> Anyway, what should PyBytes_FromObject return for NULL anyway? >> Probably just another NULL. > > Objects/dictobject.c has good examples. Something like: > > if (x == NULL) { > PyErr_BadInternalCall(); > return NULL; > } Well, I suppose it can't hurt. :) > > n > -- Cheers, Benjamin Peterson "There's no place like 127.0.0.1." From python-3000-checkins at python.org Wed Aug 27 02:31:37 2008 From: python-3000-checkins at python.org (benjamin.peterson) Date: Wed, 27 Aug 2008 02:31:37 +0200 (CEST) Subject: [Python-3000-checkins] r66047 - in python/branches/py3k: Include/object.h Misc/NEWS Modules/binascii.c Objects/abstract.c Python/getargs.c Message-ID: <20080827003137.A9B771E4004@bag.python.org> Author: benjamin.peterson Date: Wed Aug 27 02:31:37 2008 New Revision: 66047 Log: Fix #3651 various memory leaks when using the buffer interface by Amaury Forgeot d'Arc Reviewer: Antoine Pitrou Modified: python/branches/py3k/Include/object.h python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/binascii.c python/branches/py3k/Objects/abstract.c python/branches/py3k/Python/getargs.c Modified: python/branches/py3k/Include/object.h ============================================================================== --- python/branches/py3k/Include/object.h (original) +++ python/branches/py3k/Include/object.h Wed Aug 27 02:31:37 2008 @@ -143,7 +143,7 @@ /* buffer interface */ typedef struct bufferinfo { void *buf; - PyObject *obj; /* borrowed reference */ + PyObject *obj; /* owned reference */ Py_ssize_t len; Py_ssize_t itemsize; /* This is Py_ssize_t so it can be pointed to by strides in simple case.*/ Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Wed Aug 27 02:31:37 2008 @@ -21,6 +21,10 @@ - Issue #3663: Py_None was decref'd when printing SyntaxErrors. +- Issue #3651: Fix various memory leaks when using the buffer + interface, or when the "s#" code of PyArg_ParseTuple is given a + bytes object. + - Issue #3657: Fix uninitialized memory read when pickling longs. Found by valgrind. Modified: python/branches/py3k/Modules/binascii.c ============================================================================== --- python/branches/py3k/Modules/binascii.c (original) +++ python/branches/py3k/Modules/binascii.c Wed Aug 27 02:31:37 2008 @@ -231,6 +231,7 @@ */ if ( this_ch < ' ' || this_ch > (' ' + 64)) { PyErr_SetString(Error, "Illegal char"); + PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; } @@ -259,6 +260,7 @@ if ( this_ch != ' ' && this_ch != ' '+64 && this_ch != '\n' && this_ch != '\r' ) { PyErr_SetString(Error, "Trailing garbage"); + PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; } @@ -805,6 +807,7 @@ ** of the string only). This is a programmer error. */ PyErr_SetString(Error, "Orphaned RLE code at start"); + PyBuffer_Release(&pin); Py_DECREF(rv); return NULL; } Modified: python/branches/py3k/Objects/abstract.c ============================================================================== --- python/branches/py3k/Objects/abstract.c (original) +++ python/branches/py3k/Objects/abstract.c Wed Aug 27 02:31:37 2008 @@ -260,6 +260,7 @@ *buffer_len = view.len; if (pb->bf_releasebuffer != NULL) (*pb->bf_releasebuffer)(obj, &view); + Py_XDECREF(view.obj); return 0; } @@ -305,6 +306,7 @@ *buffer_len = view.len; if (pb->bf_releasebuffer != NULL) (*pb->bf_releasebuffer)(obj, &view); + Py_XDECREF(view.obj); return 0; } @@ -332,6 +334,7 @@ *buffer_len = view.len; if (pb->bf_releasebuffer != NULL) (*pb->bf_releasebuffer)(obj, &view); + Py_XDECREF(view.obj); return 0; } Modified: python/branches/py3k/Python/getargs.c ============================================================================== --- python/branches/py3k/Python/getargs.c (original) +++ python/branches/py3k/Python/getargs.c Wed Aug 27 02:31:37 2008 @@ -1245,7 +1245,7 @@ /* Caller is interested in Py_buffer, and the object supports it directly. */ format++; - if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { PyErr_Clear(); return converterr("read-write buffer", arg, msgbuf, bufsize); } @@ -1257,11 +1257,11 @@ /* Here we have processed w*, only w and w# remain. */ if (pb == NULL || pb->bf_getbuffer == NULL || - ((temp = (*pb->bf_getbuffer)(arg, &view, - PyBUF_SIMPLE)) != 0) || + ((temp = PyObject_GetBuffer(arg, &view, + PyBUF_SIMPLE)) != 0) || view.readonly == 1) { - if (temp==0 && pb->bf_releasebuffer != NULL) { - (*pb->bf_releasebuffer)(arg, &view); + if (temp==0) { + PyBuffer_Release(&view); } return converterr("single-segment read-write buffer", arg, msgbuf, bufsize); @@ -1295,7 +1295,7 @@ "bytes or read-only character buffer", arg, msgbuf, bufsize); - if ((*pb->bf_getbuffer)(arg, &view, PyBUF_SIMPLE) != 0) + if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) return converterr("string or single-segment read-only buffer", arg, msgbuf, bufsize); @@ -1306,6 +1306,8 @@ "string or pinned buffer", arg, msgbuf, bufsize); + PyBuffer_Release(&view); + if (count < 0) return converterr("(unspecified)", arg, msgbuf, bufsize); { @@ -1340,14 +1342,13 @@ return -1; } - if ((*pb->bf_getbuffer)(arg, &view, PyBUF_SIMPLE) != 0) { + if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) { *errmsg = "bytes or single-segment read-only buffer"; return -1; } count = view.len; *p = view.buf; - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(arg, &view); + PyBuffer_Release(&view); return count; } @@ -1364,7 +1365,7 @@ return -1; } if (pb->bf_getbuffer) { - if (pb->bf_getbuffer(arg, view, 0) < 0) { + if (PyObject_GetBuffer(arg, view, 0) < 0) { *errmsg = "convertible to a buffer"; return -1; } From python-3000-checkins at python.org Thu Aug 28 09:57:16 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Thu, 28 Aug 2008 09:57:16 +0200 (CEST) Subject: [Python-3000-checkins] r66051 - python/branches/py3k/Python/bltinmodule.c Message-ID: <20080828075716.B8C271E4002@bag.python.org> Author: georg.brandl Date: Thu Aug 28 09:57:16 2008 New Revision: 66051 Log: #3706: fix error message for wrong exec() argument type. R=Guido. Modified: python/branches/py3k/Python/bltinmodule.c Modified: python/branches/py3k/Python/bltinmodule.c ============================================================================== --- python/branches/py3k/Python/bltinmodule.c (original) +++ python/branches/py3k/Python/bltinmodule.c Thu Aug 28 09:57:16 2008 @@ -495,7 +495,7 @@ static char * -source_as_string(PyObject *cmd) +source_as_string(PyObject *cmd, char *funcname, char *what) { char *str; Py_ssize_t size; @@ -506,8 +506,9 @@ return NULL; } else if (!PyObject_CheckReadBuffer(cmd)) { - PyErr_SetString(PyExc_TypeError, - "eval()/exec() arg 1 must be a string, bytes or code object"); + PyErr_Format(PyExc_TypeError, + "%s() arg 1 must be a %s object", + funcname, what); return NULL; } if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) { @@ -591,7 +592,7 @@ return result; } - str = source_as_string(cmd); + str = source_as_string(cmd, "compile", "string, bytes, AST or code"); if (str == NULL) return NULL; @@ -703,7 +704,7 @@ return PyEval_EvalCode((PyCodeObject *) cmd, globals, locals); } - str = source_as_string(cmd); + str = source_as_string(cmd, "eval", "string, bytes or code"); if (str == NULL) return NULL; @@ -751,13 +752,7 @@ } else if (locals == Py_None) locals = globals; - if (!PyUnicode_Check(prog) && - !PyCode_Check(prog)) { - PyErr_Format(PyExc_TypeError, - "exec() arg 1 must be a string, file, or code " - "object, not %.100s", prog->ob_type->tp_name); - return NULL; - } + if (!PyDict_Check(globals)) { PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not %.100s", globals->ob_type->tp_name); @@ -785,7 +780,8 @@ v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); } else { - char *str = source_as_string(prog); + char *str = source_as_string(prog, "exec", + "string, bytes or code"); PyCompilerFlags cf; if (str == NULL) return NULL; From python-3000-checkins at python.org Thu Aug 28 13:28:26 2008 From: python-3000-checkins at python.org (christian.heimes) Date: Thu, 28 Aug 2008 13:28:26 +0200 (CEST) Subject: [Python-3000-checkins] r66054 - python/branches/py3k/Objects/object.c Message-ID: <20080828112826.8F2751E4002@bag.python.org> Author: christian.heimes Date: Thu Aug 28 13:28:26 2008 New Revision: 66054 Log: Removed bytesmeth declaration in OyObject_Bytes. It's not used any more and causes a compiler warning. Modified: python/branches/py3k/Objects/object.c Modified: python/branches/py3k/Objects/object.c ============================================================================== --- python/branches/py3k/Objects/object.c (original) +++ python/branches/py3k/Objects/object.c Thu Aug 28 13:28:26 2008 @@ -456,7 +456,7 @@ PyObject * PyObject_Bytes(PyObject *v) { - PyObject *bytesmeth, *result, *func; + PyObject *result, *func; static PyObject *bytesstring = NULL; if (bytesstring == NULL) { From python-3000-checkins at python.org Thu Aug 28 16:55:11 2008 From: python-3000-checkins at python.org (christian.heimes) Date: Thu, 28 Aug 2008 16:55:11 +0200 (CEST) Subject: [Python-3000-checkins] r66055 - python/branches/py3k/Objects/stringlib/find.h Message-ID: <20080828145511.523F41E4011@bag.python.org> Author: christian.heimes Date: Thu Aug 28 16:55:10 2008 New Revision: 66055 Log: Removed merge glitch from stringlib/find.h as explained on the python committers list. The FROM_BYTEARRAY isn't required here. This also fixes bug #3713 Modified: python/branches/py3k/Objects/stringlib/find.h Modified: python/branches/py3k/Objects/stringlib/find.h ============================================================================== --- python/branches/py3k/Objects/stringlib/find.h (original) +++ python/branches/py3k/Objects/stringlib/find.h Thu Aug 28 16:55:10 2008 @@ -90,7 +90,7 @@ return stringlib_rfind(str + start, end - start, sub, sub_len, start); } -#ifdef STRINGLIB_WANT_CONTAINS_OBJ && !defined(FROM_BYTEARRAY) +#ifdef STRINGLIB_WANT_CONTAINS_OBJ Py_LOCAL_INLINE(int) stringlib_contains_obj(PyObject* str, PyObject* sub) From python-3000-checkins at python.org Fri Aug 29 09:13:33 2008 From: python-3000-checkins at python.org (amaury.forgeotdarc) Date: Fri, 29 Aug 2008 09:13:33 +0200 (CEST) Subject: [Python-3000-checkins] r66056 - in python/branches/py3k: Lib/test/test_raise.py Misc/NEWS Python/ceval.c Python/errors.c Message-ID: <20080829071333.021451E4002@bag.python.org> Author: amaury.forgeotdarc Date: Fri Aug 29 09:13:32 2008 New Revision: 66056 Log: Issue 3611: in some cases (a __del__ re-raising an exception, when called from inside an 'except' clause), the exception __context__ would be reset to None. This crases the interpreter if this precisely happens inside PyErr_SetObject. - now the __context__ is properly preserved - in any case, PyErr_SetObject now saves the current exc_value in a local variable, to avoid such crashes in the future. Reviewer: Antoine Pitrou. Modified: python/branches/py3k/Lib/test/test_raise.py python/branches/py3k/Misc/NEWS python/branches/py3k/Python/ceval.c python/branches/py3k/Python/errors.c Modified: python/branches/py3k/Lib/test/test_raise.py ============================================================================== --- python/branches/py3k/Lib/test/test_raise.py (original) +++ python/branches/py3k/Lib/test/test_raise.py Fri Aug 29 09:13:32 2008 @@ -324,6 +324,30 @@ f() + def test_3611(self): + # A re-raised exception in a __del__ caused the __context__ + # to be cleared + class C: + def __del__(self): + try: + 1/0 + except: + raise + + def f(): + x = C() + try: + try: + x.x + except AttributeError: + del x + raise TypeError + except Exception as e: + self.assertNotEqual(e.__context__, None) + self.assert_(isinstance(e.__context__, AttributeError)) + + with support.captured_output("stderr"): + f() class TestRemovedFunctionality(unittest.TestCase): def test_tuples(self): Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Aug 29 09:13:32 2008 @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #3611: An exception __context__ could be cleared in a complex pattern + involving a __del__ method re-raising an exception. + - Issue #2534: speed up isinstance() and issubclass() by 50-70%, so as to match Python 2.5 speed despite the __instancecheck__ / __subclasscheck__ mechanism. In the process, fix a bug where isinstance() and issubclass(), Modified: python/branches/py3k/Python/ceval.c ============================================================================== --- python/branches/py3k/Python/ceval.c (original) +++ python/branches/py3k/Python/ceval.c Fri Aug 29 09:13:32 2008 @@ -2453,11 +2453,6 @@ if (b->b_type == EXCEPT_HANDLER) { UNWIND_EXCEPT_HANDLER(b); - if (why == WHY_EXCEPTION && !throwflag) { - Py_CLEAR(tstate->exc_type); - Py_CLEAR(tstate->exc_value); - Py_CLEAR(tstate->exc_traceback); - } continue; } UNWIND_BLOCK(b); Modified: python/branches/py3k/Python/errors.c ============================================================================== --- python/branches/py3k/Python/errors.c (original) +++ python/branches/py3k/Python/errors.c Fri Aug 29 09:13:32 2008 @@ -53,6 +53,7 @@ PyErr_SetObject(PyObject *exception, PyObject *value) { PyThreadState *tstate = PyThreadState_GET(); + PyObject *exc_value; PyObject *tb = NULL; if (exception != NULL && @@ -63,8 +64,10 @@ return; } Py_XINCREF(value); - if (tstate->exc_value != NULL && tstate->exc_value != Py_None) { + exc_value = tstate->exc_value; + if (exc_value != NULL && exc_value != Py_None) { /* Implicit exception chaining */ + Py_INCREF(exc_value); if (value == NULL || !PyExceptionInstance_Check(value)) { /* We must normalize the value right now */ PyObject *args, *fixed_value; @@ -88,8 +91,8 @@ This is O(chain length) but context chains are usually very short. Sensitive readers may try to inline the call to PyException_GetContext. */ - if (tstate->exc_value != value) { - PyObject *o = tstate->exc_value, *context; + if (exc_value != value) { + PyObject *o = exc_value, *context; while ((context = PyException_GetContext(o))) { Py_DECREF(context); if (context == value) { @@ -98,8 +101,9 @@ } o = context; } - Py_INCREF(tstate->exc_value); - PyException_SetContext(value, tstate->exc_value); + PyException_SetContext(value, exc_value); + } else { + Py_DECREF(exc_value); } } if (value != NULL && PyExceptionInstance_Check(value)) From python-3000-checkins at python.org Fri Aug 29 20:37:06 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Fri, 29 Aug 2008 20:37:06 +0200 (CEST) Subject: [Python-3000-checkins] r66057 - in python/branches/py3k: Include/cobject.h Misc/NEWS Objects/cobject.c Python/getargs.c Message-ID: <20080829183706.5567B1E4007@bag.python.org> Author: antoine.pitrou Date: Fri Aug 29 20:37:05 2008 New Revision: 66057 Log: #3668: When PyArg_ParseTuple correctly parses a s* format, but raises an exception afterwards (for a subsequent parameter), the user code will not call PyBuffer_Release() and memory will leak. Reviewed by Amaury Forgeot d'Arc. Modified: python/branches/py3k/Include/cobject.h python/branches/py3k/Misc/NEWS python/branches/py3k/Objects/cobject.c python/branches/py3k/Python/getargs.c Modified: python/branches/py3k/Include/cobject.h ============================================================================== --- python/branches/py3k/Include/cobject.h (original) +++ python/branches/py3k/Include/cobject.h Fri Aug 29 20:37:05 2008 @@ -48,6 +48,15 @@ /* Modify a C object. Fails (==0) if object has a destructor. */ PyAPI_FUNC(int) PyCObject_SetVoidPtr(PyObject *self, void *cobj); + +typedef struct { + PyObject_HEAD + void *cobject; + void *desc; + void (*destructor)(void *); +} PyCObject; + + #ifdef __cplusplus } #endif Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Fri Aug 29 20:37:05 2008 @@ -12,6 +12,10 @@ Core and Builtins ----------------- +- Issue #3668: Fix a memory leak with the "s*" argument parser in + PyArg_ParseTuple and friends, which occurred when the argument for "s*" + was correctly parsed but parsing of subsequent arguments failed. + - Issue #3611: An exception __context__ could be cleared in a complex pattern involving a __del__ method re-raising an exception. Modified: python/branches/py3k/Objects/cobject.c ============================================================================== --- python/branches/py3k/Objects/cobject.c (original) +++ python/branches/py3k/Objects/cobject.c Fri Aug 29 20:37:05 2008 @@ -9,13 +9,6 @@ typedef void (*destructor1)(void *); typedef void (*destructor2)(void *, void*); -typedef struct { - PyObject_HEAD - void *cobject; - void *desc; - void (*destructor)(void *); -} PyCObject; - PyObject * PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *)) { Modified: python/branches/py3k/Python/getargs.c ============================================================================== --- python/branches/py3k/Python/getargs.c (original) +++ python/branches/py3k/Python/getargs.c Fri Aug 29 20:37:05 2008 @@ -139,24 +139,35 @@ /* Handle cleanup of allocated memory in case of exception */ +static void +cleanup_ptr(void *ptr) +{ + PyMem_FREE(ptr); +} + +static void +cleanup_buffer(void *ptr) +{ + PyBuffer_Release((Py_buffer *) ptr); +} + static int -addcleanup(void *ptr, PyObject **freelist) +addcleanup(void *ptr, PyObject **freelist, void (*destr)(void *)) { PyObject *cobj; if (!*freelist) { *freelist = PyList_New(0); if (!*freelist) { - PyMem_FREE(ptr); + destr(ptr); return -1; } } - cobj = PyCObject_FromVoidPtr(ptr, NULL); + cobj = PyCObject_FromVoidPtr(ptr, destr); if (!cobj) { - PyMem_FREE(ptr); + destr(ptr); return -1; } if (PyList_Append(*freelist, cobj)) { - PyMem_FREE(ptr); Py_DECREF(cobj); return -1; } @@ -167,15 +178,15 @@ static int cleanreturn(int retval, PyObject *freelist) { - if (freelist) { - if (retval == 0) { - Py_ssize_t len = PyList_GET_SIZE(freelist), i; - for (i = 0; i < len; i++) - PyMem_FREE(PyCObject_AsVoidPtr( - PyList_GET_ITEM(freelist, i))); - } - Py_DECREF(freelist); + if (freelist && retval != 0) { + /* We were successful, reset the destructors so that they + don't get called. */ + Py_ssize_t len = PyList_GET_SIZE(freelist), i; + for (i = 0; i < len; i++) + ((PyCObject *) PyList_GET_ITEM(freelist, i)) + ->destructor = NULL; } + Py_XDECREF(freelist); return retval; } @@ -807,6 +818,11 @@ if (getbuffer(arg, p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } format++; } else if (*format == '#') { void **p = (void **)va_arg(*p_va, char **); @@ -856,6 +872,11 @@ if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); format++; + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } break; } count = convertbuffer(arg, p, &buf); @@ -889,6 +910,11 @@ if (getbuffer(arg, p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } format++; } else if (*format == '#') { /* any buffer-like object */ void **p = (void **)va_arg(*p_va, char **); @@ -1094,7 +1120,7 @@ "(memory error)", arg, msgbuf, bufsize); } - if (addcleanup(*buffer, freelist)) { + if (addcleanup(*buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr( "(cleanup problem)", @@ -1136,7 +1162,7 @@ return converterr("(memory error)", arg, msgbuf, bufsize); } - if (addcleanup(*buffer, freelist)) { + if (addcleanup(*buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr("(cleanup problem)", arg, msgbuf, bufsize); @@ -1249,6 +1275,11 @@ PyErr_Clear(); return converterr("read-write buffer", arg, msgbuf, bufsize); } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) return converterr("contiguous buffer", arg, msgbuf, bufsize); break; From python-3000-checkins at python.org Fri Aug 29 20:45:22 2008 From: python-3000-checkins at python.org (antoine.pitrou) Date: Fri, 29 Aug 2008 20:45:22 +0200 (CEST) Subject: [Python-3000-checkins] r66059 - python/branches/py3k Message-ID: <20080829184522.827021E4008@bag.python.org> Author: antoine.pitrou Date: Fri Aug 29 20:45:22 2008 New Revision: 66059 Log: Blocked revisions 66058 via svnmerge ........ r66058 | antoine.pitrou | 2008-08-29 20:39:48 +0200 (ven., 29 ao?t 2008) | 7 lines #3668: When PyArg_ParseTuple correctly parses a s* format, but raises an exception afterwards (for a subsequent parameter), the user code will not call PyBuffer_Release() and memory will leak. Reviewed by Amaury Forgeot d'Arc. ........ Modified: python/branches/py3k/ (props changed) From python-3000-checkins at python.org Sat Aug 30 11:58:31 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sat, 30 Aug 2008 11:58:31 +0200 (CEST) Subject: [Python-3000-checkins] r66064 - python/branches/py3k/Doc/tutorial/interpreter.rst Message-ID: <20080830095831.338381E4002@bag.python.org> Author: georg.brandl Date: Sat Aug 30 11:58:30 2008 New Revision: 66064 Log: #3577: 3.0 is not installed as "python" on Unix. Modified: python/branches/py3k/Doc/tutorial/interpreter.rst Modified: python/branches/py3k/Doc/tutorial/interpreter.rst ============================================================================== --- python/branches/py3k/Doc/tutorial/interpreter.rst (original) +++ python/branches/py3k/Doc/tutorial/interpreter.rst Sat Aug 30 11:58:30 2008 @@ -10,16 +10,16 @@ Invoking the Interpreter ======================== -The Python interpreter is usually installed as :file:`/usr/local/bin/python` on -those machines where it is available; putting :file:`/usr/local/bin` in your +The Python interpreter is usually installed as :file:`/usr/local/bin/python3.0` +on those machines where it is available; putting :file:`/usr/local/bin` in your Unix shell's search path makes it possible to start it by typing the command :: - python + python3.0 -to the shell. Since the choice of the directory where the interpreter lives is -an installation option, other places are possible; check with your local Python -guru or system administrator. (E.g., :file:`/usr/local/python` is a popular -alternative location.) +to the shell. [#]_ Since the choice of the directory where the interpreter lives +is an installation option, other places are possible; check with your local +Python guru or system administrator. (E.g., :file:`/usr/local/python` is a +popular alternative location.) On Windows machines, the Python installation is usually placed in :file:`C:\Python30`, though you can change this when you're running the @@ -58,8 +58,8 @@ ``python -m module [arg] ...``, which executes the source file for *module* as if you had spelled out its full name on the command line. -Note that there is a difference between ``python file`` and ``python Author: georg.brandl Date: Sat Aug 30 21:21:01 2008 New Revision: 66077 Log: Remove outdated comment. Reviewed by Antoine. Modified: python/branches/py3k/Objects/boolobject.c Modified: python/branches/py3k/Objects/boolobject.c ============================================================================== --- python/branches/py3k/Objects/boolobject.c (original) +++ python/branches/py3k/Objects/boolobject.c Sat Aug 30 21:21:01 2008 @@ -173,7 +173,6 @@ /* The objects representing bool values False and True */ -/* Named Zero for link-level compatibility */ struct _longobject _Py_FalseStruct = { PyVarObject_HEAD_INIT(&PyBool_Type, 0) { 0 } From python-3000-checkins at python.org Sat Aug 30 21:53:05 2008 From: python-3000-checkins at python.org (georg.brandl) Date: Sat, 30 Aug 2008 21:53:05 +0200 (CEST) Subject: [Python-3000-checkins] r66078 - in python/branches/py3k: Lib/pydoc.py Message-ID: <20080830195305.9146E1E4004@bag.python.org> Author: georg.brandl Date: Sat Aug 30 21:53:05 2008 New Revision: 66078 Log: Merged revisions 66076 via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r66076 | georg.brandl | 2008-08-30 21:03:43 +0200 (Sat, 30 Aug 2008) | 2 lines #3707: fix inf. recursion in pydoc topic search. Rev'd by Antoine. ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Lib/pydoc.py Modified: python/branches/py3k/Lib/pydoc.py ============================================================================== --- python/branches/py3k/Lib/pydoc.py (original) +++ python/branches/py3k/Lib/pydoc.py Sat Aug 30 21:53:05 2008 @@ -1548,10 +1548,10 @@ 'del': ('del', 'BASICMETHODS'), 'elif': 'if', 'else': ('else', 'while for'), - 'except': 'except', - 'finally': 'finally', + 'except': 'try', + 'finally': 'try', 'for': ('for', 'break continue while'), - 'from': 'from', + 'from': 'import', 'global': ('global', 'NAMESPACES'), 'if': ('if', 'TRUTHVALUE'), 'import': ('import', 'MODULES'), From python-3000-checkins at python.org Sun Aug 31 14:40:14 2008 From: python-3000-checkins at python.org (nick.coghlan) Date: Sun, 31 Aug 2008 14:40:14 +0200 (CEST) Subject: [Python-3000-checkins] r66084 - in python/branches/py3k: Doc/reference/datamodel.rst Message-ID: <20080831124014.DA7701E4005@bag.python.org> Author: nick.coghlan Date: Sun Aug 31 14:40:14 2008 New Revision: 66084 Log: Merged revisions 65487 (with heavy modifications for Py3k as well as some cleanups of the type heirarchy) via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r65487 | nick.coghlan | 2008-08-04 22:40:59 +1000 (Mon, 04 Aug 2008) | 1 line Issue 643841: better documentation of the special method lookup process, especially for new-style classes. Also removes the warnings about not being authoritative for new-style classes - the language reference actually covers those fairly well now (albeit in a fashion that isn't always particularly easy to follow). ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/reference/datamodel.rst Modified: python/branches/py3k/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k/Doc/reference/datamodel.rst (original) +++ python/branches/py3k/Doc/reference/datamodel.rst Sun Aug 31 14:40:14 2008 @@ -36,7 +36,7 @@ changes once it has been created; you may think of it as the object's address in memory. The ':keyword:`is`' operator compares the identity of two objects; the :func:`id` function returns an integer representing its identity (currently -implemented as its address). An object's :dfn:`type` is also unchangeable. +implemented as its address). An object's :dfn:`type` is also unchangeable. [#]_ An object's type determines the operations that the object supports (e.g., "does it have a length?") and also defines the possible values for objects of that type. The :func:`type` function returns an object's type (which is an object @@ -77,7 +77,7 @@ such objects also provide an explicit way to release the external resource, usually a :meth:`close` method. Programs are strongly recommended to explicitly close such objects. The ':keyword:`try`...\ :keyword:`finally`' statement -provides a convenient way to do this. +and the ':keyword:`with`' statement provide convenient ways to do this. .. index:: single: container @@ -116,7 +116,8 @@ Below is a list of the types that are built into Python. Extension modules (written in C, Java, or other languages, depending on the implementation) can define additional types. Future versions of Python may add types to the type -hierarchy (e.g., rational numbers, efficiently stored arrays of integers, etc.). +hierarchy (e.g., rational numbers, efficiently stored arrays of integers, etc.), +although such additions will often be provided via the standard library instead. .. index:: single: attribute @@ -172,7 +173,7 @@ There are two types of integers: - Integers + Integers (:class:`int`) These represent numbers in an unlimited range, subject to available (virtual) memory only. For the purpose of shift and mask operations, a binary @@ -180,7 +181,7 @@ 2's complement which gives the illusion of an infinite string of sign bits extending to the left. - Booleans + Booleans (:class:`bool`) .. index:: object: Boolean single: False @@ -212,7 +213,7 @@ overhead of using objects in Python, so there is no reason to complicate the language with two kinds of floating point numbers. - :class:`numbers.Complex` + :class:`numbers.Complex` (:class:`complex`) .. index:: object: complex pair: complex; number @@ -293,6 +294,15 @@ parentheses must be usable for grouping of expressions). An empty tuple can be formed by an empty pair of parentheses. + Bytes + .. index:: bytes, byte + + A bytes object is an immutable array. The items are 8-bit bytes, + represented by integers in the range 0 <= x < 256. Bytes literals + (like ``b'abc'`` and the built-in function :func:`bytes` can be used to + construct bytes objects. Also, bytes objects can be decoded to strings + via the :meth:`decode` method. + Mutable sequences .. index:: object: mutable sequence @@ -316,19 +326,18 @@ placing a comma-separated list of expressions in square brackets. (Note that there are no special cases needed to form lists of length 0 or 1.) - Bytes - .. index:: bytes, byte + Byte Arrays + .. index:: bytearray - A bytes object is a mutable array. The items are 8-bit bytes, - represented by integers in the range 0 <= x < 256. Bytes literals - (like ``b'abc'`` and the built-in function :func:`bytes` can be used to - construct bytes objects. Also, bytes objects can be decoded to strings - via the :meth:`decode` method. + A bytearray object is a mutable array. They are created by the built-in + :func:`bytearray` constructor. Aside from being mutable (and hence + unhashable), byte arrays otherwise provide the same interface and + functionality as immutable bytes objects. .. index:: module: array The extension module :mod:`array` provides an additional example of a - mutable sequence type. + mutable sequence type, as does the :mod:`collections` module. Set types .. index:: @@ -399,7 +408,8 @@ module: bsddb The extension modules :mod:`dbm.ndbm`, :mod:`dbm.gnu`, and :mod:`bsddb` - provide additional examples of mapping types. + provide additional examples of mapping types, as does the :mod:`collections` + module. Callable types .. index:: @@ -524,7 +534,7 @@ User-defined method objects may be created when getting an attribute of a class (perhaps via an instance of that class), if that attribute is a user-defined function object or a class method object. - + When an instance method object is created by retrieving a user-defined function object from a class via one of its instances, its :attr:`__self__` attribute is the instance, and the method object is said @@ -571,11 +581,11 @@ single: generator; iterator A function or method which uses the :keyword:`yield` statement (see section - :ref:`yield`) is called a :dfn:`generator - function`. Such a function, when called, always returns an iterator object - which can be used to execute the body of the function: calling the iterator's - :meth:`__next__` method will cause the function to execute until it provides a - value using the :keyword:`yield` statement. When the function executes a + :ref:`yield`) is called a :dfn:`generator function`. Such a function, when + called, always returns an iterator object which can be used to execute the + body of the function: calling the iterator's :meth:`__next__` method will + cause the function to execute until it provides a value using the + :keyword:`yield` statement. When the function executes a :keyword:`return` statement or falls off the end, a :exc:`StopIteration` exception is raised and the iterator will have reached the end of the set of values to be returned. @@ -655,18 +665,21 @@ extension modules loaded dynamically from a shared library, it is the pathname of the shared library file. -.. XXX "Classes" and "Instances" is outdated! - see http://www.python.org/doc/newstyle.html for newstyle information - Custom classes - Class objects are created by class definitions (see section :ref:`class`). A - class has a namespace implemented by a dictionary object. Class attribute - references are translated to lookups in this dictionary, e.g., ``C.x`` is - translated to ``C.__dict__["x"]``. When the attribute name is not found - there, the attribute search continues in the base classes. The search is - depth-first, left-to-right in the order of occurrence in the base class list. + Custon class types are typically created by class definitions (see section + :ref:`class`). A class has a namespace implemented by a dictionary object. + Class attribute references are translated to lookups in this dictionary, e.g., + ``C.x`` is translated to ``C.__dict__["x"]`` (although there are a number of + hooks which allow for other means of locating attributes). When the attribute + name is not found there, the attribute search continues in the base classes. + This search of the base classes uses the C3 method resolution order which + behaves correctly even in the presence of 'diamond' inheritance structures + where there are multiple inheritance paths leading back to a common ancestor. + Additional details on the C3 MRO used by Python can be found in the + documentation accompanying the 2.3 release at + http://www.python.org/download/releases/2.3/mro/. - .. XXX document descriptors and new MRO + .. XXX: Could we add that MRO doc as an appendix to the language ref? .. index:: object: class @@ -980,25 +993,10 @@ with special names. This is Python's approach to :dfn:`operator overloading`, allowing classes to define their own behavior with respect to language operators. For instance, if a class defines a method named :meth:`__getitem__`, -and ``x`` is an instance of this class, then ``x[i]`` is equivalent to -``x.__getitem__(i)``. Except where mentioned, attempts to execute an operation -raise an exception when no appropriate method is defined. - -.. XXX above translation is not correct for new-style classes! - -Special methods are only guaranteed to work if defined in an object's class, not -in the object's instance dictionary. That explains why this won't work:: - - >>> class C: - ... pass - ... - >>> c = C() - >>> c.__len__ = lambda: 5 - >>> len(c) - Traceback (most recent call last): - File "", line 1, in - TypeError: object of type 'C' has no len() - +and ``x`` is an instance of this class, then ``x[i]`` is roughly equivalent +to ``type(x).__getitem__(x, i)``. Except where mentioned, attempts to execute an +operation raise an exception when no appropriate method is defined (typically +:exc:`AttributeError` or :exc:`TypeError`). When implementing a class that emulates any built-in type, it is important that the emulation only be implemented to the degree that it makes sense for the @@ -1277,7 +1275,7 @@ Note that if the attribute is found through the normal mechanism, :meth:`__getattr__` is not called. (This is an intentional asymmetry between :meth:`__getattr__` and :meth:`__setattr__`.) This is done both for efficiency - reasons and because otherwise :meth:`__setattr__` would have no way to access + reasons and because otherwise :meth:`__getattr__` would have no way to access other attributes of the instance. Note that at least for instance variables, you can fake total control by not inserting any values in the instance attribute dictionary (but instead inserting them in another object). See the @@ -1296,6 +1294,12 @@ method with the same name to access any attributes it needs, for example, ``object.__getattribute__(self, name)``. + .. note:: + + This method may still be bypassed when looking up special methods as the + result of implicit invocation via language syntax or builtin functions. + See :ref:`special-lookup`. + .. method:: object.__setattr__(self, name, value) @@ -1881,8 +1885,89 @@ The specification, background, and examples for the Python :keyword:`with` statement. + +.. _special-lookup: + +Special method lookup +--------------------- + +For custom classes, implicit invocations of special methods are only guaranteed +to work correctly if defined on an object's type, not in the object's instance +dictionary. That behaviour is the reason why the following code raises an +exception:: + + >>> class C(object): + ... pass + ... + >>> c = C() + >>> c.__len__ = lambda: 5 + >>> len(c) + Traceback (most recent call last): + File "", line 1, in + TypeError: object of type 'C' has no len() + +The rationale behind this behaviour lies with a number of special methods such +as :meth:`__hash__` and :meth:`__repr__` that are implemented by all objects, +including type objects. If the implicit lookup of these methods used the +conventional lookup process, they would fail when invoked on the type object +itself:: + + >>> 1 .__hash__() == hash(1) + True + >>> int.__hash__() == hash(int) + Traceback (most recent call last): + File "", line 1, in + TypeError: descriptor '__hash__' of 'int' object needs an argument + +Incorrectly attempting to invoke an unbound method of a class in this way is +sometimes referred to as 'metaclass confusion', and is avoided by bypassing +the instance when looking up special methods:: + + >>> type(1).__hash__(1) == hash(1) + True + >>> type(int).__hash__(int) == hash(int) + True + +In addition to bypassing any instance attributes in the interest of +correctness, implicit special method lookup may also bypass the +:meth:`__getattribute__` method even of the object's metaclass:: + + >>> class Meta(type): + ... def __getattribute__(*args): + ... print "Metaclass getattribute invoked" + ... return type.__getattribute__(*args) + ... + >>> class C(object): + ... __metaclass__ = Meta + ... def __len__(self): + ... return 10 + ... def __getattribute__(*args): + ... print "Class getattribute invoked" + ... return object.__getattribute__(*args) + ... + >>> c = C() + >>> c.__len__() # Explicit lookup via instance + Class getattribute invoked + 10 + >>> type(c).__len__(c) # Explicit lookup via type + Metaclass getattribute invoked + 10 + >>> len(c) # Implicit lookup + 10 + +Bypassing the :meth:`__getattribute__` machinery in this fashion +provides significant scope for speed optimisations within the +interpreter, at the cost of some flexibility in the handling of +special methods (the special method *must* be set on the class +object itself in order to be consistently invoked by the interpreter). + + .. rubric:: Footnotes +.. [#] It *is* possible in some cases to change an object's type, under certain + controlled conditions. It generally isn't a good idea though, since it can + lead to some very strange behaviour if it is handled incorrectly. + .. [#] A descriptor can define any combination of :meth:`__get__`, :meth:`__set__` and :meth:`__delete__`. If it does not define :meth:`__get__`, then accessing the attribute even on an instance will return the descriptor From python-3000-checkins at python.org Sun Aug 31 15:21:24 2008 From: python-3000-checkins at python.org (nick.coghlan) Date: Sun, 31 Aug 2008 15:21:24 +0200 (CEST) Subject: [Python-3000-checkins] r66086 - in python/branches/py3k: Doc/reference/datamodel.rst Message-ID: <20080831132124.91C731E400F@bag.python.org> Author: nick.coghlan Date: Sun Aug 31 15:21:24 2008 New Revision: 66086 Log: Merged revisions 66085 (with modifications) via svnmerge from svn+ssh://pythondev at svn.python.org/python/trunk ........ r66085 | nick.coghlan | 2008-08-31 23:10:50 +1000 (Sun, 31 Aug 2008) | 1 line Issue 2235: document the ability to block inheritance of __hash__ in the language reference ........ Modified: python/branches/py3k/ (props changed) python/branches/py3k/Doc/reference/datamodel.rst Modified: python/branches/py3k/Doc/reference/datamodel.rst ============================================================================== --- python/branches/py3k/Doc/reference/datamodel.rst (original) +++ python/branches/py3k/Doc/reference/datamodel.rst Sun Aug 31 15:21:24 2008 @@ -1239,12 +1239,29 @@ be in the wrong hash bucket). User-defined classes have :meth:`__cmp__` and :meth:`__hash__` methods - by default; with them, all objects compare unequal and ``x.__hash__()`` - returns ``id(x)``. + by default; with them, all objects compare unequal (except with themselves) + and ``x.__hash__()`` returns ``id(x)``. + Classes which inherit a :meth:`__hash__` method from a parent class but + change the meaning of :meth:`__cmp__` or :meth:`__eq__` such that the hash + value returned is no longer appropriate (e.g. by switching to a value-based + concept of equality instead of the default identity based equality) can + explicitly flag themselves as being unhashable by setting + ``__hash__ = None`` in the class definition. Doing so means that not only + will instances of the class raise an appropriate :exc:`TypeError` when + a program attempts to retrieve their hash value, but they will also be + correctly identified as unhashable when checking + ``isinstance(obj, collections.Hashable)`` (unlike classes which define + their own :meth:`__hash__` to explicitly raise :exc:`TypeError`). + + If a class that overrrides :meth:`__cmp__` or :meth:`__eq__` needs to + retain the implementation of :meth:`__hash__` from a parent class, + the interpreter must be told this explicitly by setting + ``__hash__ = .__hash__``. Otherwise the inheritance of + :meth:`__hash__` will be blocked, just as if :attr:`__hash__` had been + explicitly set to :const:`None`. .. method:: object.__bool__(self) - .. index:: single: __len__() (mapping object method) Called to implement truth value testing, and the built-in operation ``bool()``; From python-3000-checkins at python.org Sun Aug 31 16:12:13 2008 From: python-3000-checkins at python.org (jesus.cea) Date: Sun, 31 Aug 2008 16:12:13 +0200 (CEST) Subject: [Python-3000-checkins] r66089 - in python/branches/py3k: Lib/bsddb/__init__.py Lib/bsddb/db.py Lib/bsddb/dbobj.py Lib/bsddb/dbrecio.py Lib/bsddb/dbshelve.py Lib/bsddb/dbtables.py Lib/bsddb/dbutils.py Lib/bsddb/test/test_1413192.py Lib/bsddb/test/test_all.py Lib/bsddb/test/test_associate.py Lib/bsddb/test/test_basics.py Lib/bsddb/test/test_compare.py Lib/bsddb/test/test_compat.py Lib/bsddb/test/test_cursor_pget_bug.py Lib/bsddb/test/test_dbobj.py Lib/bsddb/test/test_dbshelve.py Lib/bsddb/test/test_dbtables.py Lib/bsddb/test/test_distributed_transactions.py Lib/bsddb/test/test_early_close.py Lib/bsddb/test/test_get_none.py Lib/bsddb/test/test_join.py Lib/bsddb/test/test_lock.py Lib/bsddb/test/test_misc.py Lib/bsddb/test/test_pickle.py Lib/bsddb/test/test_queue.py Lib/bsddb/test/test_recno.py Lib/bsddb/test/test_replication.py Lib/bsddb/test/test_sequence.py Lib/bsddb/test/test_thread.py Misc/NEWS Modules/_bsddb.c Modules/bsddb.h setup.py Message-ID: <20080831141213.E8D221E4005@bag.python.org> Author: jesus.cea Date: Sun Aug 31 16:12:11 2008 New Revision: 66089 Log: bsddb code updated to version 4.7.3pre2. This code is the same than Python 2.6 one, since the intention is to keep an unified 2.x/3.x codebase. The Python code is automatically translated using "2to3". Please, do not update this code in Python 3.0 by hand. Update the 2.6 one and then do "2to3". Added: python/branches/py3k/Lib/bsddb/test/test_distributed_transactions.py python/branches/py3k/Lib/bsddb/test/test_early_close.py python/branches/py3k/Lib/bsddb/test/test_replication.py Removed: python/branches/py3k/Lib/bsddb/test/test_1413192.py Modified: python/branches/py3k/Lib/bsddb/__init__.py python/branches/py3k/Lib/bsddb/db.py python/branches/py3k/Lib/bsddb/dbobj.py python/branches/py3k/Lib/bsddb/dbrecio.py python/branches/py3k/Lib/bsddb/dbshelve.py python/branches/py3k/Lib/bsddb/dbtables.py python/branches/py3k/Lib/bsddb/dbutils.py python/branches/py3k/Lib/bsddb/test/test_all.py python/branches/py3k/Lib/bsddb/test/test_associate.py python/branches/py3k/Lib/bsddb/test/test_basics.py python/branches/py3k/Lib/bsddb/test/test_compare.py python/branches/py3k/Lib/bsddb/test/test_compat.py python/branches/py3k/Lib/bsddb/test/test_cursor_pget_bug.py python/branches/py3k/Lib/bsddb/test/test_dbobj.py python/branches/py3k/Lib/bsddb/test/test_dbshelve.py python/branches/py3k/Lib/bsddb/test/test_dbtables.py python/branches/py3k/Lib/bsddb/test/test_get_none.py python/branches/py3k/Lib/bsddb/test/test_join.py python/branches/py3k/Lib/bsddb/test/test_lock.py python/branches/py3k/Lib/bsddb/test/test_misc.py python/branches/py3k/Lib/bsddb/test/test_pickle.py python/branches/py3k/Lib/bsddb/test/test_queue.py python/branches/py3k/Lib/bsddb/test/test_recno.py python/branches/py3k/Lib/bsddb/test/test_sequence.py python/branches/py3k/Lib/bsddb/test/test_thread.py python/branches/py3k/Misc/NEWS python/branches/py3k/Modules/_bsddb.c python/branches/py3k/Modules/bsddb.h python/branches/py3k/setup.py Modified: python/branches/py3k/Lib/bsddb/__init__.py ============================================================================== --- python/branches/py3k/Lib/bsddb/__init__.py (original) +++ python/branches/py3k/Lib/bsddb/__init__.py Sun Aug 31 16:12:11 2008 @@ -33,18 +33,25 @@ #---------------------------------------------------------------------- -"""Support for BerkeleyDB 3.3 through 4.4 with a simple interface. +"""Support for Berkeley DB 4.0 through 4.7 with a simple interface. For the full featured object oriented interface use the bsddb.db module -instead. It mirrors the Sleepycat BerkeleyDB C API. +instead. It mirrors the Oracle Berkeley DB C API. """ +import sys +absolute_import = (sys.version_info[0] >= 3) + try: if __name__ == 'bsddb3': # import _pybsddb binary as it should be the more recent version from # a standalone pybsddb addon package than the version included with # python as bsddb._bsddb. - import _pybsddb + if absolute_import : + # Because this syntaxis is not valid before Python 2.5 + exec("from . import _pybsddb") + else : + import _pybsddb _bsddb = _pybsddb from bsddb3.dbutils import DeadlockWrap as _DeadlockWrap else: @@ -64,10 +71,18 @@ #---------------------------------------------------------------------- -import sys, os, collections +import sys, os + from weakref import ref -class _iter_mixin(collections.MutableMapping): +if sys.version_info[0:2] <= (2, 5) : + import UserDict + MutableMapping = UserDict.DictMixin +else : + import collections + MutableMapping = collections.MutableMapping + +class _iter_mixin(MutableMapping): def _make_iter_cursor(self): cur = _DeadlockWrap(self.db.cursor) key = id(cur) @@ -81,64 +96,89 @@ return lambda ref: self._cursor_refs.pop(key, None) def __iter__(self): + self._kill_iteration = False + self._in_iter += 1 try: - cur = self._make_iter_cursor() + try: + cur = self._make_iter_cursor() - # FIXME-20031102-greg: race condition. cursor could - # be closed by another thread before this call. + # FIXME-20031102-greg: race condition. cursor could + # be closed by another thread before this call. - # since we're only returning keys, we call the cursor - # methods with flags=0, dlen=0, dofs=0 - key = _DeadlockWrap(cur.first, 0,0,0)[0] - yield key + # since we're only returning keys, we call the cursor + # methods with flags=0, dlen=0, dofs=0 + key = _DeadlockWrap(cur.first, 0,0,0)[0] + yield key + + next = cur.__next__ + while 1: + try: + key = _DeadlockWrap(next, 0,0,0)[0] + yield key + except _bsddb.DBCursorClosedError: + if self._kill_iteration: + raise RuntimeError('Database changed size ' + 'during iteration.') + cur = self._make_iter_cursor() + # FIXME-20031101-greg: race condition. cursor could + # be closed by another thread before this call. + _DeadlockWrap(cur.set, key,0,0,0) + next = cur.__next__ + except _bsddb.DBNotFoundError: + pass + except _bsddb.DBCursorClosedError: + # the database was modified during iteration. abort. + pass +# When Python 2.3 not supported in bsddb3, we can change this to "finally" + except : + self._in_iter -= 1 + raise - next = cur.next - while 1: - try: - key = _DeadlockWrap(next, 0,0,0)[0] - yield key - except _bsddb.DBCursorClosedError: - cur = self._make_iter_cursor() - # FIXME-20031101-greg: race condition. cursor could - # be closed by another thread before this call. - _DeadlockWrap(cur.set, key,0,0,0) - next = cur.next - except _bsddb.DBNotFoundError: - return - except _bsddb.DBCursorClosedError: - # the database was modified during iteration. abort. - return + self._in_iter -= 1 def iteritems(self): if not self.db: return + self._kill_iteration = False + self._in_iter += 1 try: - cur = self._make_iter_cursor() + try: + cur = self._make_iter_cursor() - # FIXME-20031102-greg: race condition. cursor could - # be closed by another thread before this call. + # FIXME-20031102-greg: race condition. cursor could + # be closed by another thread before this call. - kv = _DeadlockWrap(cur.first) - key = kv[0] - yield kv + kv = _DeadlockWrap(cur.first) + key = kv[0] + yield kv + + next = cur.__next__ + while 1: + try: + kv = _DeadlockWrap(next) + key = kv[0] + yield kv + except _bsddb.DBCursorClosedError: + if self._kill_iteration: + raise RuntimeError('Database changed size ' + 'during iteration.') + cur = self._make_iter_cursor() + # FIXME-20031101-greg: race condition. cursor could + # be closed by another thread before this call. + _DeadlockWrap(cur.set, key,0,0,0) + next = cur.__next__ + except _bsddb.DBNotFoundError: + pass + except _bsddb.DBCursorClosedError: + # the database was modified during iteration. abort. + pass +# When Python 2.3 not supported in bsddb3, we can change this to "finally" + except : + self._in_iter -= 1 + raise + + self._in_iter -= 1 - next = cur.next - while 1: - try: - kv = _DeadlockWrap(next) - key = kv[0] - yield kv - except _bsddb.DBCursorClosedError: - cur = self._make_iter_cursor() - # FIXME-20031101-greg: race condition. cursor could - # be closed by another thread before this call. - _DeadlockWrap(cur.set, key,0,0,0) - next = cur.next - except _bsddb.DBNotFoundError: - return - except _bsddb.DBCursorClosedError: - # the database was modified during iteration. abort. - return class _DBWithCursor(_iter_mixin): """ @@ -166,13 +206,12 @@ # a collection of all DBCursor objects currently allocated # by the _iter_mixin interface. self._cursor_refs = {} + self._in_iter = 0 + self._kill_iteration = False def __del__(self): self.close() - def __repr__(self): - return repr(dict(self.iteritems())) - def _checkCursor(self): if self.dbc is None: self.dbc = _DeadlockWrap(self.db.cursor) @@ -181,7 +220,7 @@ self.saved_dbc_key = None # This method is needed for all non-cursor DB calls to avoid - # BerkeleyDB deadlocks (due to being opened with DB_INIT_LOCK + # Berkeley DB deadlocks (due to being opened with DB_INIT_LOCK # and DB_THREAD to be thread safe) when intermixing database # operations that use the cursor internally with those that don't. def _closeCursors(self, save=1): @@ -195,7 +234,7 @@ pass _DeadlockWrap(c.close) del c - for cref in self._cursor_refs.values(): + for cref in list(self._cursor_refs.values()): c = cref() if c is not None: _DeadlockWrap(c.close) @@ -211,6 +250,12 @@ self._checkOpen() return _DeadlockWrap(lambda: len(self.db)) # len(self.db) + if sys.version_info[0:2] >= (2, 6) : + def __repr__(self) : + if self.isOpen() : + return repr(dict(_DeadlockWrap(self.db.items))) + return repr(dict()) + def __getitem__(self, key): self._checkOpen() return _DeadlockWrap(lambda: self.db[key]) # self.db[key] @@ -218,6 +263,8 @@ def __setitem__(self, key, value): self._checkOpen() self._closeCursors() + if self._in_iter and key not in self: + self._kill_iteration = True def wrapF(): self.db[key] = value _DeadlockWrap(wrapF) # self.db[key] = value @@ -225,6 +272,8 @@ def __delitem__(self, key): self._checkOpen() self._closeCursors() + if self._in_iter and key in self: + self._kill_iteration = True def wrapF(): del self.db[key] _DeadlockWrap(wrapF) # del self.db[key] @@ -248,17 +297,15 @@ self._checkOpen() return _DeadlockWrap(self.db.has_key, key) - __contains__ = has_key - def set_location(self, key): self._checkOpen() self._checkCursor() return _DeadlockWrap(self.dbc.set_range, key) - def next(self): + def __next__(self): self._checkOpen() self._checkCursor() - rv = _DeadlockWrap(self.dbc.next) + rv = _DeadlockWrap(self.dbc.__next__) return rv def previous(self): @@ -287,146 +334,6 @@ self._checkOpen() return _DeadlockWrap(self.db.sync) -class _ExposedProperties: - @property - def _cursor_refs(self): - return self.db._cursor_refs - -class StringKeys(collections.MutableMapping, _ExposedProperties): - """Wrapper around DB object that automatically encodes - all keys as UTF-8; the keys must be strings.""" - - def __init__(self, db): - self.db = db - - def __len__(self): - return len(self.db) - - def __getitem__(self, key): - return self.db[key.encode("utf-8")] - - def __setitem__(self, key, value): - self.db[key.encode("utf-8")] = value - - def __delitem__(self, key): - del self.db[key.encode("utf-8")] - - def __iter__(self): - for k in self.db: - yield k.decode("utf-8") - - def close(self): - self.db.close() - - def keys(self): - for k in self.db.keys(): - yield k.decode("utf-8") - - def has_key(self, key): - return self.db.has_key(key.encode("utf-8")) - - __contains__ = has_key - - def values(self): - return self.db.values() - - def items(self): - for k,v in self.db.items(): - yield k.decode("utf-8"), v - - def set_location(self, key): - return self.db.set_location(key.encode("utf-8")) - - def next(self): - key, value = self.db.next() - return key.decode("utf-8"), value - - def previous(self): - key, value = self.db.previous() - return key.decode("utf-8"), value - - def first(self): - key, value = self.db.first() - return key.decode("utf-8"), value - - def last(self): - key, value = self.db.last() - return key.decode("utf-8"), value - - def set_location(self, key): - key, value = self.db.set_location(key.encode("utf-8")) - return key.decode("utf-8"), value - - def sync(self): - return self.db.sync() - -class StringValues(collections.MutableMapping, _ExposedProperties): - """Wrapper around DB object that automatically encodes - and decodes all values as UTF-8; input values must be strings.""" - - def __init__(self, db): - self.db = db - - def __len__(self): - return len(self.db) - - def __getitem__(self, key): - return self.db[key].decode("utf-8") - - def __setitem__(self, key, value): - self.db[key] = value.encode("utf-8") - - def __delitem__(self, key): - del self.db[key] - - def __iter__(self): - return iter(self.db) - - def close(self): - self.db.close() - - def keys(self): - return self.db.keys() - - def has_key(self, key): - return self.db.has_key(key) - - __contains__ = has_key - - def values(self): - for v in self.db.values(): - yield v.decode("utf-8") - - def items(self): - for k,v in self.db.items(): - yield k, v.decode("utf-8") - - def set_location(self, key): - return self.db.set_location(key) - - def next(self): - key, value = self.db.next() - return key, value.decode("utf-8") - - def previous(self): - key, value = self.db.previous() - return key, value.decode("utf-8") - - def first(self): - key, value = self.db.first() - return key, value.decode("utf-8") - - def last(self): - key, value = self.db.last() - return key, value.decode("utf-8") - - def set_location(self, key): - key, value = self.db.set_location(key) - return key, value.decode("utf-8") - - def sync(self): - return self.db.sync() - #---------------------------------------------------------------------- # Compatibility object factory functions @@ -507,12 +414,12 @@ elif flag == 'n': flags = db.DB_CREATE #flags = db.DB_CREATE | db.DB_TRUNCATE - # we used db.DB_TRUNCATE flag for this before but BerkeleyDB + # we used db.DB_TRUNCATE flag for this before but Berkeley DB # 4.2.52 changed to disallowed truncate with txn environments. if file is not None and os.path.isfile(file): os.unlink(file) else: - raise error("flags should be one of 'r', 'w', 'c' or 'n', not "+repr(flag)) + raise error("flags should be one of 'r', 'w', 'c' or 'n'") return flags | db.DB_THREAD #---------------------------------------------------------------------- @@ -520,16 +427,14 @@ # This is a silly little hack that allows apps to continue to use the # DB_THREAD flag even on systems without threads without freaking out -# BerkeleyDB. +# Berkeley DB. # # This assumes that if Python was built with thread support then -# BerkeleyDB was too. +# Berkeley DB was too. try: import _thread del _thread - if db.version() < (3, 3, 0): - db.DB_THREAD = 0 except ImportError: db.DB_THREAD = 0 Modified: python/branches/py3k/Lib/bsddb/db.py ============================================================================== --- python/branches/py3k/Lib/bsddb/db.py (original) +++ python/branches/py3k/Lib/bsddb/db.py Sun Aug 31 16:12:11 2008 @@ -37,15 +37,24 @@ # case we ever want to augment the stuff in _db in any way. For now # it just simply imports everything from _db. -if __name__.startswith('bsddb3.'): - # import _pybsddb binary as it should be the more recent version from - # a standalone pybsddb addon package than the version included with - # python as bsddb._bsddb. - from _pybsddb import * - from _pybsddb import __version__ -else: - from _bsddb import * - from _bsddb import __version__ +import sys +absolute_import = (sys.version_info[0] >= 3) -if version() < (3, 2, 0): - raise ImportError("correct BerkeleyDB symbols not found. Perhaps python was statically linked with an older version?") +if not absolute_import : + if __name__.startswith('bsddb3.') : + # import _pybsddb binary as it should be the more recent version from + # a standalone pybsddb addon package than the version included with + # python as bsddb._bsddb. + from _pybsddb import * + from _pybsddb import __version__ + else: + from _bsddb import * + from _bsddb import __version__ +else : + # Because this syntaxis is not valid before Python 2.5 + if __name__.startswith('bsddb3.') : + exec("from ._pybsddb import *") + exec("from ._pybsddb import __version__") + else : + exec("from ._bsddb import *") + exec("from ._bsddb import __version__") Modified: python/branches/py3k/Lib/bsddb/dbobj.py ============================================================================== --- python/branches/py3k/Lib/bsddb/dbobj.py (original) +++ python/branches/py3k/Lib/bsddb/dbobj.py Sun Aug 31 16:12:11 2008 @@ -21,12 +21,24 @@ # added to _bsddb.c. # -from . import db - -try: - from collections import MutableMapping -except ImportError: - class MutableMapping: pass +import sys +absolute_import = (sys.version_info[0] >= 3) +if absolute_import : + # Because this syntaxis is not valid before Python 2.5 + exec("from . import db") +else : + from . import db + +if sys.version_info[0:2] <= (2, 5) : + try: + from UserDict import DictMixin + except ImportError: + # DictMixin is new in Python 2.3 + class DictMixin: pass + MutableMapping = DictMixin +else : + import collections + MutableMapping = collections.MutableMapping class DBEnv: def __init__(self, *args, **kwargs): @@ -95,9 +107,8 @@ def set_get_returns_none(self, *args, **kwargs): return self._cobj.set_get_returns_none(*args, **kwargs) - if db.version() >= (4,0): - def log_stat(self, *args, **kwargs): - return self._cobj.log_stat(*args, **kwargs) + def log_stat(self, *args, **kwargs): + return self._cobj.log_stat(*args, **kwargs) if db.version() >= (4,1): def dbremove(self, *args, **kwargs): @@ -115,7 +126,7 @@ class DB(MutableMapping): def __init__(self, dbenv, *args, **kwargs): # give it the proper DBEnv C object that its expecting - self._cobj = db.DB(dbenv._cobj, *args, **kwargs) + self._cobj = db.DB(*(dbenv._cobj,) + args, **kwargs) # TODO are there other dict methods that need to be overridden? def __len__(self): @@ -126,8 +137,10 @@ self._cobj[key] = value def __delitem__(self, arg): del self._cobj[arg] - def __iter__(self): - return iter(self.keys()) + + if sys.version_info[0:2] >= (2, 6) : + def __iter__(self) : + return self._cobj.__iter__() def append(self, *args, **kwargs): return self._cobj.append(*args, **kwargs) @@ -163,8 +176,6 @@ return self._cobj.key_range(*args, **kwargs) def has_key(self, *args, **kwargs): return self._cobj.has_key(*args, **kwargs) - def __contains__(self, key): - return self._cobj.has_key(key) def items(self, *args, **kwargs): return self._cobj.items(*args, **kwargs) def keys(self, *args, **kwargs): Modified: python/branches/py3k/Lib/bsddb/dbrecio.py ============================================================================== --- python/branches/py3k/Lib/bsddb/dbrecio.py (original) +++ python/branches/py3k/Lib/bsddb/dbrecio.py Sun Aug 31 16:12:11 2008 @@ -29,6 +29,7 @@ """ import errno +import string class DBRecIO: def __init__(self, db, key, txn=None): @@ -38,6 +39,7 @@ self.len = None self.pos = 0 self.closed = 0 + self.softspace = 0 def close(self): if not self.closed: @@ -82,9 +84,9 @@ if self.closed: raise ValueError, "I/O operation on closed file" if self.buflist: - self.buf = self.buf + ''.join(self.buflist) + self.buf = self.buf + string.joinfields(self.buflist, '') self.buflist = [] - i = self.buf.find('\n', self.pos) + i = string.find(self.buf, '\n', self.pos) if i < 0: newpos = self.len else: @@ -133,7 +135,7 @@ self.pos = newpos def writelines(self, list): - self.write(''.join(list)) + self.write(string.joinfields(list, '')) def flush(self): if self.closed: @@ -158,14 +160,14 @@ if f.getvalue() != text: raise RuntimeError, 'write failed' length = f.tell() - print('File length =', length) + print 'File length =', length f.seek(len(lines[0])) f.write(lines[1]) f.seek(0) - print('First line =', repr(f.readline())) + print 'First line =', repr(f.readline()) here = f.tell() line = f.readline() - print('Second line =', repr(line)) + print 'Second line =', repr(line) f.seek(-len(line), 1) line2 = f.read(len(line)) if line != line2: @@ -177,8 +179,8 @@ line2 = f.read() if line != line2: raise RuntimeError, 'bad result after seek back from EOF' - print('Read', len(list), 'more lines') - print('File length =', f.tell()) + print 'Read', len(list), 'more lines' + print 'File length =', f.tell() if f.tell() != length: raise RuntimeError, 'bad length' f.close() Modified: python/branches/py3k/Lib/bsddb/dbshelve.py ============================================================================== --- python/branches/py3k/Lib/bsddb/dbshelve.py (original) +++ python/branches/py3k/Lib/bsddb/dbshelve.py Sun Aug 31 16:12:11 2008 @@ -32,21 +32,43 @@ import pickle import sys +import sys +absolute_import = (sys.version_info[0] >= 3) +if absolute_import : + # Because this syntaxis is not valid before Python 2.5 + exec("from . import db") +else : + from . import db + #At version 2.3 cPickle switched to using protocol instead of bin if sys.version_info[:3] >= (2, 3, 0): HIGHEST_PROTOCOL = pickle.HIGHEST_PROTOCOL - def _dumps(object, protocol): - return pickle.dumps(object, protocol=protocol) - from collections import MutableMapping +# In python 2.3.*, "cPickle.dumps" accepts no +# named parameters. "pickle.dumps" accepts them, +# so this seems a bug. + if sys.version_info[:3] < (2, 4, 0): + def _dumps(object, protocol): + return pickle.dumps(object, protocol) + else : + def _dumps(object, protocol): + return pickle.dumps(object, protocol=protocol) + else: HIGHEST_PROTOCOL = None def _dumps(object, protocol): return pickle.dumps(object, bin=protocol) - class MutableMapping: pass -from . import db -_unspecified = object() +if sys.version_info[0:2] <= (2, 5) : + try: + from UserDict import DictMixin + except ImportError: + # DictMixin is new in Python 2.3 + class DictMixin: pass + MutableMapping = DictMixin +else : + import collections + MutableMapping = collections.MutableMapping #------------------------------------------------------------------------ @@ -135,13 +157,15 @@ def keys(self, txn=None): - if txn is not None: + if txn != None: return self.db.keys(txn) else: - return self.db.keys() + return list(self.db.keys()) + + if sys.version_info[0:2] >= (2, 6) : + def __iter__(self) : + return self.db.__iter__() - def __iter__(self): - return iter(self.keys()) def open(self, *args, **kwargs): self.db.open(*args, **kwargs) @@ -157,14 +181,14 @@ if self._closed: return '' % (id(self)) else: - return repr(dict(self.iteritems())) + return repr(dict(iter(self.items()))) def items(self, txn=None): - if txn is not None: + if txn != None: items = self.db.items(txn) else: - items = self.db.items() + items = list(self.db.items()) newitems = [] for k, v in items: @@ -172,12 +196,12 @@ return newitems def values(self, txn=None): - if txn is not None: + if txn != None: values = self.db.values(txn) else: - values = self.db.values() + values = list(self.db.values()) - return map(pickle.loads, values) + return list(map(pickle.loads, values)) #----------------------------------- # Other methods @@ -194,24 +218,28 @@ def associate(self, secondaryDB, callback, flags=0): def _shelf_callback(priKey, priData, realCallback=callback): - data = pickle.loads(priData) + # Safe in Python 2.x because expresion short circuit + if sys.version_info[0] < 3 or isinstance(priData, bytes) : + data = pickle.loads(priData) + else : + data = pickle.loads(bytes(priData, "iso8859-1")) # 8 bits return realCallback(priKey, data) + return self.db.associate(secondaryDB, _shelf_callback, flags) - def get(self, key, default=_unspecified, txn=None, flags=0): - # If no default is given, we must not pass one to the - # extension module, so that an exception can be raised if - # set_get_returns_none is turned off. - if default is _unspecified: - data = self.db.get(key, txn=txn, flags=flags) - # if this returns, the default value would be None - default = None - else: - data = self.db.get(key, default, txn=txn, flags=flags) - if data is default: - return data - return pickle.loads(data) + #def get(self, key, default=None, txn=None, flags=0): + def get(self, *args, **kw): + # We do it with *args and **kw so if the default value wasn't + # given nothing is passed to the extension module. That way + # an exception can be raised if set_get_returns_none is turned + # off. + data = self.db.get(*args, **kw) + try: + return pickle.loads(data) + except (EOFError, TypeError, pickle.UnpicklingError): + return data # we may be getting the default value, or None, + # so it doesn't need unpickled. def get_both(self, key, value, txn=None, flags=0): data = _dumps(value, self.protocol) @@ -234,10 +262,6 @@ raise NotImplementedError - def __contains__(self, key): - return self.db.has_key(key) - - #---------------------------------------------- # Methods allowed to pass-through to self.db # @@ -331,7 +355,11 @@ return None else: key, data = rec - return key, pickle.loads(data) + # Safe in Python 2.x because expresion short circuit + if sys.version_info[0] < 3 or isinstance(data, bytes) : + return key, pickle.loads(data) + else : + return key, pickle.loads(bytes(data, "iso8859-1")) # 8 bits #---------------------------------------------- # Methods allowed to pass-through to self.dbc Modified: python/branches/py3k/Lib/bsddb/dbtables.py ============================================================================== --- python/branches/py3k/Lib/bsddb/dbtables.py (original) +++ python/branches/py3k/Lib/bsddb/dbtables.py Sun Aug 31 16:12:11 2008 @@ -13,30 +13,29 @@ # -- Gregory P. Smith # This provides a simple database table interface built on top of -# the Python BerkeleyDB 3 interface. +# the Python Berkeley DB 3 interface. # _cvsid = '$Id$' import re import sys import copy -import struct import random -import pickle - -from bsddb.db import * +import struct +import pickle as pickle -# All table names, row names etc. must be ASCII strings -# However, rowids, when represented as strings, are latin-1 encoded -def _E(s): - return s.encode("ascii") +try: + # For Pythons w/distutils pybsddb + from bsddb3 import db +except ImportError: + # For Python 2.3 + from bsddb import db # XXX(nnorwitz): is this correct? DBIncompleteError is conditional in _bsddb.c -try: - DBIncompleteError -except NameError: +if not hasattr(db,"DBIncompleteError") : class DBIncompleteError(Exception): pass + db.DBIncompleteError = DBIncompleteError class TableDBError(Exception): pass @@ -51,22 +50,22 @@ class ExactCond(Cond): """Acts as an exact match condition function""" - def __init__(self, strtomatch, encoding="utf-8"): - self.strtomatch = strtomatch.encode(encoding) + def __init__(self, strtomatch): + self.strtomatch = strtomatch def __call__(self, s): return s == self.strtomatch class PrefixCond(Cond): """Acts as a condition function for matching a string prefix""" - def __init__(self, prefix, encoding="utf-8"): - self.prefix = prefix.encode(encoding) + def __init__(self, prefix): + self.prefix = prefix def __call__(self, s): return s[:len(self.prefix)] == self.prefix class PostfixCond(Cond): """Acts as a condition function for matching a string postfix""" - def __init__(self, postfix, encoding="utf-8"): - self.postfix = postfix.encode(encoding) + def __init__(self, postfix): + self.postfix = postfix def __call__(self, s): return s[-len(self.postfix):] == self.postfix @@ -76,7 +75,7 @@ string. Case insensitive and % signs are wild cards. This isn't perfect but it should work for the simple common cases. """ - def __init__(self, likestr, re_flags=re.IGNORECASE, encoding="utf-8"): + def __init__(self, likestr, re_flags=re.IGNORECASE): # escape python re characters chars_to_escape = '.*+()[]?' for char in chars_to_escape : @@ -84,18 +83,8 @@ # convert %s to wildcards self.likestr = likestr.replace('%', '.*') self.re = re.compile('^'+self.likestr+'$', re_flags) - self.encoding = encoding def __call__(self, s): - return self.re.match(s.decode(self.encoding)) - -def CmpToKey(mycmp): - 'Convert a cmp= function into a key= function' - class K(object): - def __init__(self, obj, *args): - self.obj = obj - def __lt__(self, other): - return mycmp(self.obj, other.obj) == -1 - return K + return self.re.match(s) # # keys used to store database metadata @@ -104,7 +93,7 @@ _columns = '._COLUMNS__' # table_name+this key contains a list of columns def _columns_key(table): - return _E(table + _columns) + return table + _columns # # these keys are found within table sub databases @@ -114,20 +103,21 @@ # row in the table. (no data is stored) _rowid_str_len = 8 # length in bytes of the unique rowid strings + def _data_key(table, col, rowid): - return _E(table + _data + col + _data) + rowid + return table + _data + col + _data + rowid def _search_col_data_key(table, col): - return _E(table + _data + col + _data) + return table + _data + col + _data def _search_all_data_key(table): - return _E(table + _data) + return table + _data def _rowid_key(table, rowid): - return _E(table + _rowid) + rowid + _E(_rowid) + return table + _rowid + rowid + _rowid def _search_rowid_key(table): - return _E(table + _rowid) + return table + _rowid def contains_metastrings(s) : """Verify that the given string does not contain any @@ -146,43 +136,110 @@ class bsdTableDB : def __init__(self, filename, dbhome, create=0, truncate=0, mode=0o600, recover=0, dbflags=0): - """bsdTableDB(filename, dbhome, create=0, truncate=0, mode=0o600) + """bsdTableDB(filename, dbhome, create=0, truncate=0, mode=0600) - Open database name in the dbhome BerkeleyDB directory. + Open database name in the dbhome Berkeley DB directory. Use keyword arguments when calling this constructor. """ self.db = None - myflags = DB_THREAD + myflags = db.DB_THREAD if create: - myflags |= DB_CREATE - flagsforenv = (DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | - DB_INIT_TXN | dbflags) + myflags |= db.DB_CREATE + flagsforenv = (db.DB_INIT_MPOOL | db.DB_INIT_LOCK | db.DB_INIT_LOG | + db.DB_INIT_TXN | dbflags) # DB_AUTO_COMMIT isn't a valid flag for env.open() try: - dbflags |= DB_AUTO_COMMIT + dbflags |= db.DB_AUTO_COMMIT except AttributeError: pass if recover: - flagsforenv = flagsforenv | DB_RECOVER - self.env = DBEnv() + flagsforenv = flagsforenv | db.DB_RECOVER + self.env = db.DBEnv() # enable auto deadlock avoidance - self.env.set_lk_detect(DB_LOCK_DEFAULT) + self.env.set_lk_detect(db.DB_LOCK_DEFAULT) self.env.open(dbhome, myflags | flagsforenv) if truncate: - myflags |= DB_TRUNCATE - self.db = DB(self.env) + myflags |= db.DB_TRUNCATE + self.db = db.DB(self.env) # this code relies on DBCursor.set* methods to raise exceptions # rather than returning None self.db.set_get_returns_none(1) # allow duplicate entries [warning: be careful w/ metadata] - self.db.set_flags(DB_DUP) - self.db.open(filename, DB_BTREE, dbflags | myflags, mode) + self.db.set_flags(db.DB_DUP) + self.db.open(filename, db.DB_BTREE, dbflags | myflags, mode) self.dbfilename = filename + + if sys.version_info[0] >= 3 : + class cursor_py3k(object) : + def __init__(self, dbcursor) : + self._dbcursor = dbcursor + + def close(self) : + return self._dbcursor.close() + + def set_range(self, search) : + v = self._dbcursor.set_range(bytes(search, "iso8859-1")) + if v != None : + v = (v[0].decode("iso8859-1"), + v[1].decode("iso8859-1")) + return v + + def __next__(self) : + v = getattr(self._dbcursor, "next")() + if v != None : + v = (v[0].decode("iso8859-1"), + v[1].decode("iso8859-1")) + return v + + class db_py3k(object) : + def __init__(self, db) : + self._db = db + + def cursor(self, txn=None) : + return cursor_py3k(self._db.cursor(txn=txn)) + + def has_key(self, key, txn=None) : + return getattr(self._db,"has_key")(bytes(key, "iso8859-1"), + txn=txn) + + def put(self, key, value, flags=0, txn=None) : + key = bytes(key, "iso8859-1") + if value != None : + value = bytes(value, "iso8859-1") + return self._db.put(key, value, flags=flags, txn=txn) + + def put_bytes(self, key, value, txn=None) : + key = bytes(key, "iso8859-1") + return self._db.put(key, value, txn=txn) + + def get(self, key, txn=None, flags=0) : + key = bytes(key, "iso8859-1") + v = self._db.get(key, txn=txn, flags=flags) + if v != None : + v = v.decode("iso8859-1") + return v + + def get_bytes(self, key, txn=None, flags=0) : + key = bytes(key, "iso8859-1") + return self._db.get(key, txn=txn, flags=flags) + + def delete(self, key, txn=None) : + key = bytes(key, "iso8859-1") + return self._db.delete(key, txn=txn) + + def close (self) : + return self._db.close() + + self.db = db_py3k(self.db) + else : # Python 2.x + pass + # Initialize the table names list if this is a new database txn = self.env.txn_begin() try: - if not self.db.has_key(_E(_table_names_key), txn): - self.db.put(_E(_table_names_key), pickle.dumps([], 1), txn=txn) + if not getattr(self.db, "has_key")(_table_names_key, txn): + getattr(self.db, "put_bytes", self.db.put) \ + (_table_names_key, pickle.dumps([], 1), txn=txn) # Yes, bare except except: txn.abort() @@ -206,13 +263,13 @@ def checkpoint(self, mins=0): try: self.env.txn_checkpoint(mins) - except DBIncompleteError: + except db.DBIncompleteError: pass def sync(self): try: self.db.sync() - except DBIncompleteError: + except db.DBIncompleteError: pass def _db_print(self) : @@ -223,13 +280,13 @@ key, data = cur.first() while 1: print(repr({key: data})) - next = cur.next() + next = next(cur) if next: key, data = next else: cur.close() return - except DBNotFoundError: + except db.DBNotFoundError: cur.close() @@ -239,6 +296,7 @@ raises TableDBError if it already exists or for other DB errors. """ assert isinstance(columns, list) + txn = None try: # checking sanity of the table and column names here on @@ -252,29 +310,33 @@ "bad column name: contains reserved metastrings") columnlist_key = _columns_key(table) - if self.db.has_key(columnlist_key): + if getattr(self.db, "has_key")(columnlist_key): raise TableAlreadyExists("table already exists") txn = self.env.txn_begin() # store the table's column info - self.db.put(columnlist_key, pickle.dumps(columns, 1), txn=txn) + getattr(self.db, "put_bytes", self.db.put)(columnlist_key, + pickle.dumps(columns, 1), txn=txn) # add the table name to the tablelist - tablelist = pickle.loads(self.db.get(_E(_table_names_key), txn=txn, - flags=DB_RMW)) + tablelist = pickle.loads(getattr(self.db, "get_bytes", + self.db.get) (_table_names_key, txn=txn, flags=db.DB_RMW)) tablelist.append(table) # delete 1st, in case we opened with DB_DUP - self.db.delete(_E(_table_names_key), txn=txn) - self.db.put(_E(_table_names_key), pickle.dumps(tablelist, 1), txn=txn) + self.db.delete(_table_names_key, txn=txn) + getattr(self.db, "put_bytes", self.db.put)(_table_names_key, + pickle.dumps(tablelist, 1), txn=txn) txn.commit() txn = None - except DBError as dberror: - raise TableDBError(dberror.args[1]) - finally: + except db.DBError as dberror: if txn: txn.abort() - txn = None + if sys.version_info[0] < 3 : + raise TableDBError(dberror[1]) + else : + raise TableDBError(dberror.args[1]) + def ListTableColumns(self, table): """Return a list of columns in the given table. @@ -285,9 +347,10 @@ raise ValueError("bad table name: contains reserved metastrings") columnlist_key = _columns_key(table) - if not self.db.has_key(columnlist_key): + if not getattr(self.db, "has_key")(columnlist_key): return [] - pickledcolumnlist = self.db.get(columnlist_key) + pickledcolumnlist = getattr(self.db, "get_bytes", + self.db.get)(columnlist_key) if pickledcolumnlist: return pickle.loads(pickledcolumnlist) else: @@ -295,7 +358,7 @@ def ListTables(self): """Return a list of tables in this database.""" - pickledtablelist = self.db.get(_E(_table_names_key)) + pickledtablelist = self.db.get_get(_table_names_key) if pickledtablelist: return pickle.loads(pickledtablelist) else: @@ -311,6 +374,7 @@ all of its current columns. """ assert isinstance(columns, list) + try: self.CreateTable(table, columns) except TableAlreadyExists: @@ -322,7 +386,8 @@ # load the current column list oldcolumnlist = pickle.loads( - self.db.get(columnlist_key, txn=txn, flags=DB_RMW)) + getattr(self.db, "get_bytes", + self.db.get)(columnlist_key, txn=txn, flags=db.DB_RMW)) # create a hash table for fast lookups of column names in the # loop below oldcolumnhash = {} @@ -340,7 +405,7 @@ if newcolumnlist != oldcolumnlist : # delete the old one first since we opened with DB_DUP self.db.delete(columnlist_key, txn=txn) - self.db.put(columnlist_key, + getattr(self.db, "put_bytes", self.db.put)(columnlist_key, pickle.dumps(newcolumnlist, 1), txn=txn) @@ -348,19 +413,22 @@ txn = None self.__load_column_info(table) - except DBError as dberror: - raise TableDBError(dberror.args[1]) - finally: + except db.DBError as dberror: if txn: txn.abort() + if sys.version_info[0] < 3 : + raise TableDBError(dberror[1]) + else : + raise TableDBError(dberror.args[1]) def __load_column_info(self, table) : """initialize the self.__tablecolumns dict""" # check the column names try: - tcolpickles = self.db.get(_columns_key(table)) - except DBNotFoundError: + tcolpickles = getattr(self.db, "get_bytes", + self.db.get)(_columns_key(table)) + except db.DBNotFoundError: raise TableDBError("unknown table: %r" % (table,)) if not tcolpickles: raise TableDBError("unknown table: %r" % (table,)) @@ -376,13 +444,16 @@ blist = [] for x in range(_rowid_str_len): blist.append(random.randint(0,255)) - newid = bytes(blist) + newid = struct.pack('B'*_rowid_str_len, *blist) + + if sys.version_info[0] >= 3 : + newid = newid.decode("iso8859-1") # 8 bits # Guarantee uniqueness by adding this key to the database try: self.db.put(_rowid_key(table, newid), None, txn=txn, - flags=DB_NOOVERWRITE) - except DBKeyExistError: + flags=db.DB_NOOVERWRITE) + except db.DBKeyExistError: pass else: unique = 1 @@ -394,15 +465,16 @@ """Insert(table, datadict) - Insert a new row into the table using the keys+values from rowdict as the column values. """ + txn = None try: - if not self.db.has_key(_columns_key(table)): + if not getattr(self.db, "has_key")(_columns_key(table)): raise TableDBError("unknown table") # check the validity of each column name if table not in self.__tablecolumns: self.__load_column_info(table) - for column in rowdict.keys() : + for column in list(rowdict.keys()) : if not self.__tablecolumns[table].count(column): raise TableDBError("unknown column: %r" % (column,)) @@ -411,14 +483,14 @@ rowid = self.__new_rowid(table, txn=txn) # insert the row values into the table database - for column, dataitem in rowdict.items(): + for column, dataitem in list(rowdict.items()): # store the value self.db.put(_data_key(table, column, rowid), dataitem, txn=txn) txn.commit() txn = None - except DBError as dberror: + except db.DBError as dberror: # WIBNI we could just abort the txn and re-raise the exception? # But no, because TableDBError is not related to DBError via # inheritance, so it would be backwards incompatible. Do the next @@ -427,11 +499,10 @@ if txn: txn.abort() self.db.delete(_rowid_key(table, rowid)) - txn = None - raise TableDBError(dberror.args[1]).with_traceback(info[2]) - finally: - if txn: - txn.abort() + if sys.version_info[0] < 3 : + raise TableDBError(dberror[1]).with_traceback(info[2]) + else : + raise TableDBError(dberror.args[1]).with_traceback(info[2]) def Modify(self, table, conditions={}, mappings={}): @@ -445,13 +516,13 @@ condition callable expecting the data string as an argument and returning the new string for that column. """ + try: matching_rowids = self.__Select(table, [], conditions) # modify only requested columns - columns = mappings.keys() - for rowid in matching_rowids.keys(): - rowid = rowid.encode("latin-1") + columns = list(mappings.keys()) + for rowid in list(matching_rowids.keys()): txn = None try: for column in columns: @@ -464,7 +535,7 @@ self.db.delete( _data_key(table, column, rowid), txn=txn) - except DBNotFoundError: + except db.DBNotFoundError: # XXXXXXX row key somehow didn't exist, assume no # error dataitem = None @@ -477,12 +548,16 @@ txn = None # catch all exceptions here since we call unknown callables - finally: + except: if txn: txn.abort() + raise - except DBError as dberror: - raise TableDBError(dberror.args[1]) + except db.DBError as dberror: + if sys.version_info[0] < 3 : + raise TableDBError(dberror[1]) + else : + raise TableDBError(dberror.args[1]) def Delete(self, table, conditions={}): """Delete(table, conditions) - Delete items matching the given @@ -492,37 +567,41 @@ condition functions expecting the data string as an argument and returning a boolean. """ + try: matching_rowids = self.__Select(table, [], conditions) # delete row data from all columns columns = self.__tablecolumns[table] - for rowid in matching_rowids.keys(): + for rowid in list(matching_rowids.keys()): txn = None try: txn = self.env.txn_begin() for column in columns: # delete the data key try: - self.db.delete(_data_key(table, column, - rowid.encode("latin-1")), + self.db.delete(_data_key(table, column, rowid), txn=txn) - except DBNotFoundError: + except db.DBNotFoundError: # XXXXXXX column may not exist, assume no error pass try: - self.db.delete(_rowid_key(table, rowid.encode("latin-1")), txn=txn) - except DBNotFoundError: + self.db.delete(_rowid_key(table, rowid), txn=txn) + except db.DBNotFoundError: # XXXXXXX row key somehow didn't exist, assume no error pass txn.commit() txn = None - finally: + except db.DBError as dberror: if txn: txn.abort() - except DBError as dberror: - raise TableDBError(dberror.args[1]) + raise + except db.DBError as dberror: + if sys.version_info[0] < 3 : + raise TableDBError(dberror[1]) + else : + raise TableDBError(dberror.args[1]) def Select(self, table, columns, conditions={}): @@ -541,10 +620,13 @@ if columns is None: columns = self.__tablecolumns[table] matching_rowids = self.__Select(table, columns, conditions) - except DBError as dberror: - raise TableDBError(dberror.args[1]) + except db.DBError as dberror: + if sys.version_info[0] < 3 : + raise TableDBError(dberror[1]) + else : + raise TableDBError(dberror.args[1]) # return the matches as a list of dictionaries - return matching_rowids.values() + return list(matching_rowids.values()) def __Select(self, table, columns, conditions): @@ -595,8 +677,19 @@ # leave all unknown condition callables alone as equals return 0 - conditionlist = list(conditions.items()) - conditionlist.sort(key=CmpToKey(cmp_conditions)) + if sys.version_info[0] < 3 : + conditionlist = list(conditions.items()) + conditionlist.sort(cmp_conditions) + else : # Insertion Sort. Please, improve + conditionlist = [] + for i in list(conditions.items()) : + for j, k in enumerate(conditionlist) : + r = cmp_conditions(k, i) + if r == 1 : + conditionlist.insert(j, i) + break + else : + conditionlist.append(i) # Apply conditions to column data to find what we want cur = self.db.cursor() @@ -614,7 +707,7 @@ key, data = cur.set_range(searchkey) while key[:len(searchkey)] == searchkey: # extract the rowid from the key - rowid = key[-_rowid_str_len:].decode("latin-1") + rowid = key[-_rowid_str_len:] if rowid not in rejected_rowids: # if no condition was specified or the condition @@ -629,11 +722,15 @@ del matching_rowids[rowid] rejected_rowids[rowid] = rowid - key, data = cur.next() + key, data = next(cur) - except DBError as dberror: - if dberror.args[0] != DB_NOTFOUND: - raise + except db.DBError as dberror: + if sys.version_info[0] < 3 : + if dberror[0] != db.DB_NOTFOUND: + raise + else : + if dberror.args[0] != db.DB_NOTFOUND: + raise continue cur.close() @@ -644,17 +741,20 @@ # extract any remaining desired column data from the # database for the matching rows. if len(columns) > 0: - for rowid, rowdata in matching_rowids.items(): - rowid = rowid.encode("latin-1") + for rowid, rowdata in list(matching_rowids.items()): for column in columns: if column in rowdata: continue try: rowdata[column] = self.db.get( _data_key(table, column, rowid)) - except DBError as dberror: - if dberror.args[0] != DB_NOTFOUND: - raise + except db.DBError as dberror: + if sys.version_info[0] < 3 : + if dberror[0] != db.DB_NOTFOUND: + raise + else : + if dberror.args[0] != db.DB_NOTFOUND: + raise rowdata[column] = None # return the matches @@ -677,7 +777,7 @@ while 1: try: key, data = cur.set_range(table_key) - except DBNotFoundError: + except db.DBNotFoundError: break # only delete items in this table if key[:len(table_key)] != table_key: @@ -689,7 +789,7 @@ while 1: try: key, data = cur.set_range(table_key) - except DBNotFoundError: + except db.DBNotFoundError: break # only delete items in this table if key[:len(table_key)] != table_key: @@ -700,15 +800,17 @@ # delete the tablename from the table name list tablelist = pickle.loads( - self.db.get(_E(_table_names_key), txn=txn, flags=DB_RMW)) + getattr(self.db, "get_bytes", self.db.get)(_table_names_key, + txn=txn, flags=db.DB_RMW)) try: tablelist.remove(table) except ValueError: # hmm, it wasn't there, oh well, that's what we want. pass # delete 1st, incase we opened with DB_DUP - self.db.delete(_E(_table_names_key), txn=txn) - self.db.put(_E(_table_names_key), pickle.dumps(tablelist, 1), txn=txn) + self.db.delete(_table_names_key, txn=txn) + getattr(self.db, "put_bytes", self.db.put)(_table_names_key, + pickle.dumps(tablelist, 1), txn=txn) txn.commit() txn = None @@ -716,8 +818,10 @@ if table in self.__tablecolumns: del self.__tablecolumns[table] - except DBError as dberror: - raise TableDBError(dberror.args[1]) - finally: + except db.DBError as dberror: if txn: txn.abort() + if sys.version_info[0] < 3 : + raise TableDBError(dberror[1]) + else : + raise TableDBError(dberror.args[1]) Modified: python/branches/py3k/Lib/bsddb/dbutils.py ============================================================================== --- python/branches/py3k/Lib/bsddb/dbutils.py (original) +++ python/branches/py3k/Lib/bsddb/dbutils.py Sun Aug 31 16:12:11 2008 @@ -19,8 +19,20 @@ # #------------------------------------------------------------------------ -import time -from . import db + +# +# import the time.sleep function in a namespace safe way to allow +# "from bsddb.dbutils import *" +# +from time import sleep as _sleep + +import sys +absolute_import = (sys.version_info[0] >= 3) +if absolute_import : + # Because this syntaxis is not valid before Python 2.5 + exec("from . import db") +else : + from . import db # always sleep at least N seconds between retrys _deadlock_MinSleepTime = 1.0/128 @@ -54,22 +66,17 @@ while True: try: return function(*_args, **_kwargs) - except db.DBLockDeadlockError as e: + except db.DBLockDeadlockError: if _deadlock_VerboseFile: _deadlock_VerboseFile.write( - 'bsddb.dbutils.DeadlockWrap: ' + - 'sleeping %1.3f\n' % sleeptime) - time.sleep(sleeptime) + 'dbutils.DeadlockWrap: sleeping %1.3f\n' % sleeptime) + _sleep(sleeptime) # exponential backoff in the sleep time sleeptime *= 2 if sleeptime > _deadlock_MaxSleepTime: sleeptime = _deadlock_MaxSleepTime max_retries -= 1 if max_retries == -1: - if _deadlock_VerboseFile: - _deadlock_VerboseFile.write( - 'bsddb.dbutils.DeadlockWrap: ' + - 'max_retries reached, reraising %s\n' % e) raise Deleted: python/branches/py3k/Lib/bsddb/test/test_1413192.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_1413192.py Sun Aug 31 16:12:11 2008 +++ (empty file) @@ -1,48 +0,0 @@ -# http://bugs.python.org/issue1413192 -# -# See the bug report for details. -# The problem was that the env was deallocated prior to the txn. - -import shutil -import tempfile -from test.support import catch_warning -import warnings - -try: - # For Pythons w/distutils and add-on pybsddb - from bsddb3 import db -except ImportError: - # For Python >= 2.3 builtin bsddb distribution - from bsddb import db - -env_name = tempfile.mkdtemp() - -# Wrap test operation in a class so we can control destruction rather than -# waiting for the controlling Python executable to exit - -class Context: - - def __init__(self): - self.env = db.DBEnv() - self.env.open(env_name, - db.DB_CREATE | db.DB_INIT_TXN | db.DB_INIT_MPOOL) - self.the_txn = self.env.txn_begin() - - self.map = db.DB(self.env) - self.map.open('xxx.db', "p", - db.DB_HASH, db.DB_CREATE, 0o666, txn=self.the_txn) - del self.env - del self.the_txn - - -with catch_warning(): - warnings.filterwarnings('ignore', 'DBTxn aborted in destructor') - context = Context() - del context - - -# try not to leave a turd -try: - shutil.rmtree(env_name) -except EnvironmentError: - pass Modified: python/branches/py3k/Lib/bsddb/test/test_all.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_all.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_all.py Sun Aug 31 16:12:11 2008 @@ -6,18 +6,377 @@ import unittest try: # For Pythons w/distutils pybsddb - from bsddb3 import db + import bsddb3 as bsddb except ImportError: # For Python 2.3 - from bsddb import db + import bsddb -verbose = False + +if sys.version_info[0] >= 3 : + charset = "iso8859-1" # Full 8 bit + + class cursor_py3k(object) : + def __init__(self, db, *args, **kwargs) : + self._dbcursor = db.cursor(*args, **kwargs) + + def __getattr__(self, v) : + return getattr(self._dbcursor, v) + + def _fix(self, v) : + if v == None : return None + key, value = v + if isinstance(key, bytes) : + key = key.decode(charset) + return (key, value.decode(charset)) + + def __next__(self) : + v = getattr(self._dbcursor, "next")() + return self._fix(v) + + def previous(self) : + v = self._dbcursor.previous() + return self._fix(v) + + def last(self) : + v = self._dbcursor.last() + return self._fix(v) + + def set(self, k) : + if isinstance(k, str) : + k = bytes(k, charset) + v = self._dbcursor.set(k) + return self._fix(v) + + def set_recno(self, num) : + v = self._dbcursor.set_recno(num) + return self._fix(v) + + def set_range(self, k, dlen=-1, doff=-1) : + if isinstance(k, str) : + k = bytes(k, charset) + v = self._dbcursor.set_range(k, dlen=dlen, doff=doff) + return self._fix(v) + + def dup(self, flags=0) : + cursor = self._dbcursor.dup(flags) + return dup_cursor_py3k(cursor) + + def next_dup(self) : + v = self._dbcursor.next_dup() + return self._fix(v) + + def put(self, key, value, flags=0, dlen=-1, doff=-1) : + if isinstance(key, str) : + key = bytes(key, charset) + if isinstance(value, str) : + value = bytes(value, charset) + return self._dbcursor.put(key, value, flags=flags, dlen=dlen, + doff=doff) + + def current(self, flags=0, dlen=-1, doff=-1) : + v = self._dbcursor.current(flags=flags, dlen=dlen, doff=doff) + return self._fix(v) + + def first(self) : + v = self._dbcursor.first() + return self._fix(v) + + def pget(self, key=None, data=None, flags=0) : + # Incorrect because key can be a bare number, + # but enough to pass testsuite + if isinstance(key, int) and (data==None) and (flags==0) : + flags = key + key = None + if isinstance(key, str) : + key = bytes(key, charset) + if isinstance(data, int) and (flags==0) : + flags = data + data = None + if isinstance(data, str) : + data = bytes(data, charset) + v=self._dbcursor.pget(key=key, data=data, flags=flags) + if v != None : + v1, v2, v3 = v + if isinstance(v1, bytes) : + v1 = v1.decode(charset) + if isinstance(v2, bytes) : + v2 = v2.decode(charset) + + v = (v1, v2, v3.decode(charset)) + + return v + + def join_item(self) : + v = self._dbcursor.join_item() + if v != None : + v = v.decode(charset) + return v + + def get(self, *args, **kwargs) : + l = len(args) + if l == 2 : + k, f = args + if isinstance(k, str) : + k = bytes(k, "iso8859-1") + args = (k, f) + elif l == 3 : + k, d, f = args + if isinstance(k, str) : + k = bytes(k, charset) + if isinstance(d, str) : + d = bytes(d, charset) + args =(k, d, f) + + v = self._dbcursor.get(*args, **kwargs) + if v != None : + k, v = v + if isinstance(k, bytes) : + k = k.decode(charset) + v = (k, v.decode(charset)) + return v + + def get_both(self, key, value) : + if isinstance(key, str) : + key = bytes(key, charset) + if isinstance(value, str) : + value = bytes(value, charset) + v=self._dbcursor.get_both(key, value) + return self._fix(v) + + class dup_cursor_py3k(cursor_py3k) : + def __init__(self, dbcursor) : + self._dbcursor = dbcursor + + class DB_py3k(object) : + def __init__(self, *args, **kwargs) : + args2=[] + for i in args : + if isinstance(i, DBEnv_py3k) : + i = i._dbenv + args2.append(i) + args = tuple(args2) + for k, v in list(kwargs.items()) : + if isinstance(v, DBEnv_py3k) : + kwargs[k] = v._dbenv + + self._db = bsddb._db.DB_orig(*args, **kwargs) + + def __contains__(self, k) : + if isinstance(k, str) : + k = bytes(k, charset) + return getattr(self._db, "has_key")(k) + + def __getitem__(self, k) : + if isinstance(k, str) : + k = bytes(k, charset) + v = self._db[k] + if v != None : + v = v.decode(charset) + return v + + def __setitem__(self, k, v) : + if isinstance(k, str) : + k = bytes(k, charset) + if isinstance(v, str) : + v = bytes(v, charset) + self._db[k] = v + + def __delitem__(self, k) : + if isinstance(k, str) : + k = bytes(k, charset) + del self._db[k] + + def __getattr__(self, v) : + return getattr(self._db, v) + + def __len__(self) : + return len(self._db) + + def has_key(self, k, txn=None) : + if isinstance(k, str) : + k = bytes(k, charset) + return self._db.has_key(k, txn=txn) + + def put(self, key, value, txn=None, flags=0, dlen=-1, doff=-1) : + if isinstance(key, str) : + key = bytes(key, charset) + if isinstance(value, str) : + value = bytes(value, charset) + return self._db.put(key, value, flags=flags, txn=txn, dlen=dlen, + doff=doff) + + def append(self, value, txn=None) : + if isinstance(value, str) : + value = bytes(value, charset) + return self._db.append(value, txn=txn) + + def get_size(self, key) : + if isinstance(key, str) : + key = bytes(key, charset) + return self._db.get_size(key) + + def get(self, key, default="MagicCookie", txn=None, flags=0, dlen=-1, doff=-1) : + if isinstance(key, str) : + key = bytes(key, charset) + if default != "MagicCookie" : # Magic for 'test_get_none.py' + v=self._db.get(key, default=default, txn=txn, flags=flags, + dlen=dlen, doff=doff) + else : + v=self._db.get(key, txn=txn, flags=flags, + dlen=dlen, doff=doff) + if (v != None) and isinstance(v, bytes) : + v = v.decode(charset) + return v + + def pget(self, key, txn=None) : + if isinstance(key, str) : + key = bytes(key, charset) + v=self._db.pget(key, txn=txn) + if v != None : + v1, v2 = v + if isinstance(v1, bytes) : + v1 = v1.decode(charset) + + v = (v1, v2.decode(charset)) + return v + + def get_both(self, key, value, txn=None, flags=0) : + if isinstance(key, str) : + key = bytes(key, charset) + if isinstance(value, str) : + value = bytes(value, charset) + v=self._db.get_both(key, value, txn=txn, flags=flags) + if v != None : + v = v.decode(charset) + return v + + def delete(self, key, txn=None) : + if isinstance(key, str) : + key = bytes(key, charset) + return self._db.delete(key, txn=txn) + + def keys(self) : + k = list(self._db.keys()) + if len(k) and isinstance(k[0], bytes) : + return [i.decode(charset) for i in list(self._db.keys())] + else : + return k + + def items(self) : + data = list(self._db.items()) + if not len(data) : return data + data2 = [] + for k, v in data : + if isinstance(k, bytes) : + k = k.decode(charset) + data2.append((k, v.decode(charset))) + return data2 + + def associate(self, secondarydb, callback, flags=0, txn=None) : + class associate_callback(object) : + def __init__(self, callback) : + self._callback = callback + + def callback(self, key, data) : + if isinstance(key, str) : + key = key.decode(charset) + data = data.decode(charset) + key = self._callback(key, data) + if (key != bsddb._db.DB_DONOTINDEX) and isinstance(key, + str) : + key = bytes(key, charset) + return key + + return self._db.associate(secondarydb._db, + associate_callback(callback).callback, flags=flags, txn=txn) + + def cursor(self, txn=None, flags=0) : + return cursor_py3k(self._db, txn=txn, flags=flags) + + def join(self, cursor_list) : + cursor_list = [i._dbcursor for i in cursor_list] + return dup_cursor_py3k(self._db.join(cursor_list)) + + class DBEnv_py3k(object) : + def __init__(self, *args, **kwargs) : + self._dbenv = bsddb._db.DBEnv_orig(*args, **kwargs) + + def __getattr__(self, v) : + return getattr(self._dbenv, v) + + class DBSequence_py3k(object) : + def __init__(self, db, *args, **kwargs) : + self._db=db + self._dbsequence = bsddb._db.DBSequence_orig(db._db, *args, **kwargs) + + def __getattr__(self, v) : + return getattr(self._dbsequence, v) + + def open(self, key, *args, **kwargs) : + return self._dbsequence.open(bytes(key, charset), *args, **kwargs) + + def get_key(self) : + return self._dbsequence.get_key().decode(charset) + + def get_dbp(self) : + return self._db + + import string + string.letters=[chr(i) for i in range(65,91)] + + bsddb._db.DBEnv_orig = bsddb._db.DBEnv + bsddb._db.DB_orig = bsddb._db.DB + bsddb._db.DBSequence_orig = bsddb._db.DBSequence + + def do_proxy_db_py3k(flag) : + flag2 = do_proxy_db_py3k.flag + do_proxy_db_py3k.flag = flag + if flag : + bsddb.DBEnv = bsddb.db.DBEnv = bsddb._db.DBEnv = DBEnv_py3k + bsddb.DB = bsddb.db.DB = bsddb._db.DB = DB_py3k + bsddb._db.DBSequence = DBSequence_py3k + else : + bsddb.DBEnv = bsddb.db.DBEnv = bsddb._db.DBEnv = bsddb._db.DBEnv_orig + bsddb.DB = bsddb.db.DB = bsddb._db.DB = bsddb._db.DB_orig + bsddb._db.DBSequence = bsddb._db.DBSequence_orig + return flag2 + + do_proxy_db_py3k.flag = False + do_proxy_db_py3k(True) + +try: + # For Pythons w/distutils pybsddb + from bsddb3 import db, dbtables, dbutils, dbshelve, \ + hashopen, btopen, rnopen, dbobj +except ImportError: + # For Python 2.3 + from bsddb import db, dbtables, dbutils, dbshelve, \ + hashopen, btopen, rnopen, dbobj + +try: + from bsddb3 import test_support +except ImportError: + from test import test_support + + +try: + if sys.version_info[0] < 3 : + from threading import Thread, currentThread + del Thread, currentThread + else : + from threading import Thread, current_thread + del Thread, current_thread + have_threads = True +except ImportError: + have_threads = False + +verbose = 0 if 'verbose' in sys.argv: - verbose = True + verbose = 1 sys.argv.remove('verbose') if 'silent' in sys.argv: # take care of old flag, just in case - verbose = False + verbose = 0 sys.argv.remove('silent') @@ -28,11 +387,71 @@ print('bsddb.db.version(): %s' % (db.version(), )) print('bsddb.db.__version__: %s' % db.__version__) print('bsddb.db.cvsid: %s' % db.cvsid) + print('py module: %s' % bsddb.__file__) + print('extension module: %s' % bsddb._bsddb.__file__) print('python version: %s' % sys.version) print('My pid: %s' % os.getpid()) print('-=' * 38) +def get_new_path(name) : + get_new_path.mutex.acquire() + try : + import os + path=os.path.join(get_new_path.prefix, + name+"_"+str(os.getpid())+"_"+str(get_new_path.num)) + get_new_path.num+=1 + finally : + get_new_path.mutex.release() + return path + +def get_new_environment_path() : + path=get_new_path("environment") + import os + try: + os.makedirs(path,mode=0o700) + except os.error: + test_support.rmtree(path) + os.makedirs(path) + return path + +def get_new_database_path() : + path=get_new_path("database") + import os + if os.path.exists(path) : + os.remove(path) + return path + + +# This path can be overriden via "set_test_path_prefix()". +import os, os.path +get_new_path.prefix=os.path.join(os.sep,"tmp","z-Berkeley_DB") +get_new_path.num=0 + +def get_test_path_prefix() : + return get_new_path.prefix + +def set_test_path_prefix(path) : + get_new_path.prefix=path + +def remove_test_path_directory() : + test_support.rmtree(get_new_path.prefix) + +if have_threads : + import threading + get_new_path.mutex=threading.Lock() + del threading +else : + class Lock(object) : + def acquire(self) : + pass + def release(self) : + pass + get_new_path.mutex=Lock() + del Lock + + + class PrintInfoFakeTest(unittest.TestCase): def testPrintVersions(self): print_versions() @@ -41,30 +460,26 @@ # This little hack is for when this module is run as main and all the # other modules import it so they will still be able to get the right # verbose setting. It's confusing but it works. -try: - import test_all -except ImportError: - pass -else: +if sys.version_info[0] < 3 : + from . import test_all test_all.verbose = verbose +else : + import sys + print("Work to do!", file=sys.stderr) -def suite(): - try: - # this is special, it used to segfault the interpreter - import test_1413192 - except: - pass - +def suite(module_prefix='', timing_check=None): test_modules = [ 'test_associate', 'test_basics', - 'test_compat', 'test_compare', + 'test_compat', + 'test_cursor_pget_bug', 'test_dbobj', 'test_dbshelve', 'test_dbtables', - 'test_env_close', + 'test_distributed_transactions', + 'test_early_close', 'test_get_none', 'test_join', 'test_lock', @@ -72,15 +487,21 @@ 'test_pickle', 'test_queue', 'test_recno', - 'test_thread', + 'test_replication', 'test_sequence', - 'test_cursor_pget_bug', + 'test_thread', ] alltests = unittest.TestSuite() for name in test_modules: - module = __import__(name) + #module = __import__(name) + # Do it this way so that suite may be called externally via + # python's Lib/test/test_bsddb3. + module = __import__(module_prefix+name, globals(), locals(), name) + alltests.addTest(module.test_suite()) + if timing_check: + alltests.addTest(unittest.makeSuite(timing_check)) return alltests Modified: python/branches/py3k/Lib/bsddb/test/test_associate.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_associate.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_associate.py Sun Aug 31 16:12:11 2008 @@ -2,32 +2,13 @@ TestCases for DB.associate. """ -import shutil -import sys, os -import tempfile +import sys, os, string import time from pprint import pprint -try: - from threading import Thread, current_thread - have_threads = 1 -except ImportError: - have_threads = 0 - import unittest -from bsddb.test.test_all import verbose - -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db, dbshelve -except ImportError: - # For Python 2.3 - from bsddb import db, dbshelve - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +from .test_all import db, dbshelve, test_support, verbose, have_threads, \ + get_new_environment_path #---------------------------------------------------------------------- @@ -97,15 +78,7 @@ class AssociateErrorTestCase(unittest.TestCase): def setUp(self): self.filename = self.__class__.__name__ + '.db' - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - try: - os.mkdir(homeDir) - except os.error: - import glob - files = glob.glob(os.path.join(self.homeDir, '*')) - for file in files: - os.remove(file) + self.homeDir = get_new_environment_path() self.env = db.DBEnv() self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL) @@ -128,7 +101,7 @@ secDB.open(self.filename, "secondary", db.DB_BTREE, db.DB_CREATE) # dupDB has been configured to allow duplicates, it can't - # associate with a secondary. BerkeleyDB will return an error. + # associate with a secondary. Berkeley DB will return an error. try: def f(a,b): return a+b dupDB.associate(secDB, f) @@ -153,15 +126,7 @@ def setUp(self): self.filename = self.__class__.__name__ + '.db' - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - try: - os.mkdir(homeDir) - except os.error: - import glob - files = glob.glob(os.path.join(self.homeDir, '*')) - for file in files: - os.remove(file) + self.homeDir = get_new_environment_path() self.env = db.DBEnv() self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL | db.DB_INIT_LOCK | db.DB_THREAD | self.envFlags) @@ -170,13 +135,13 @@ self.closeDB() self.env.close() self.env = None - shutil.rmtree(self.homeDir) + test_support.rmtree(self.homeDir) def addDataToDB(self, d, txn=None): - for key, value in musicdata.items(): + for key, value in list(musicdata.items()): if type(self.keytype) == type(''): - key = ("%02d" % key).encode("utf-8") - d.put(key, '|'.join(value).encode("utf-8"), txn=txn) + key = "%02d" % key + d.put(key, '|'.join(value), txn=txn) def createDB(self, txn=None): self.cur = None @@ -246,14 +211,14 @@ def finish_test(self, secDB, txn=None): # 'Blues' should not be in the secondary database - vals = secDB.pget(b'Blues', txn=txn) - assert vals == None, vals + vals = secDB.pget('Blues', txn=txn) + self.assertEqual(vals, None, vals) - vals = secDB.pget(b'Unknown', txn=txn) - assert vals[0] == 99 or vals[0] == b'99', vals - vals[1].index(b'Unknown') - vals[1].index(b'Unnamed') - vals[1].index(b'unknown') + vals = secDB.pget('Unknown', txn=txn) + self.assert_(vals[0] == 99 or vals[0] == '99', vals) + vals[1].index('Unknown') + vals[1].index('Unnamed') + vals[1].index('unknown') if verbose: print("Primary key traversal:") @@ -262,14 +227,14 @@ rec = self.cur.first() while rec is not None: if type(self.keytype) == type(''): - assert int(rec[0]) # for primary db, key is a number + self.assert_(int(rec[0])) # for primary db, key is a number else: - assert rec[0] and type(rec[0]) == type(0) + self.assert_(rec[0] and type(rec[0]) == type(0)) count = count + 1 if verbose: print(rec) - rec = self.cur.next() - assert count == len(musicdata) # all items accounted for + rec = getattr(self.cur, "next")() + self.assertEqual(count, len(musicdata)) # all items accounted for if verbose: @@ -278,38 +243,39 @@ count = 0 # test cursor pget - vals = self.cur.pget(b'Unknown', flags=db.DB_LAST) - assert vals[1] == 99 or vals[1] == b'99', vals - assert vals[0] == b'Unknown' - vals[2].index(b'Unknown') - vals[2].index(b'Unnamed') - vals[2].index(b'unknown') + vals = self.cur.pget('Unknown', flags=db.DB_LAST) + self.assert_(vals[1] == 99 or vals[1] == '99', vals) + self.assertEqual(vals[0], 'Unknown') + vals[2].index('Unknown') + vals[2].index('Unnamed') + vals[2].index('unknown') - vals = self.cur.pget(b'Unknown', data=b'wrong value', flags=db.DB_GET_BOTH) - assert vals == None, vals + vals = self.cur.pget('Unknown', data='wrong value', flags=db.DB_GET_BOTH) + self.assertEqual(vals, None, vals) rec = self.cur.first() - assert rec[0] == b"Jazz" + self.assertEqual(rec[0], "Jazz") while rec is not None: count = count + 1 if verbose: print(rec) - rec = self.cur.next() + rec = getattr(self.cur, "next")() # all items accounted for EXCEPT for 1 with "Blues" genre - assert count == len(musicdata)-1 + self.assertEqual(count, len(musicdata)-1) self.cur = None def getGenre(self, priKey, priData): - assert type(priData) == type(b"") - priData = priData.decode("utf-8") + self.assertEqual(type(priData), type("")) + genre = priData.split('|')[2] + if verbose: print('getGenre key: %r data: %r' % (priKey, priData)) - genre = priData.split('|')[2] + if genre == 'Blues': return db.DB_DONOTINDEX else: - return genre.encode("utf-8") + return genre #---------------------------------------------------------------------- @@ -380,21 +346,21 @@ filetype=self.dbtype) def addDataToDB(self, d): - for key, value in musicdata.items(): + for key, value in list(musicdata.items()): if type(self.keytype) == type(''): - key = ("%02d" % key).encode("utf-8") + key = "%02d" % key d.put(key, value) # save the value as is this time def getGenre(self, priKey, priData): - assert type(priData) == type(()) + self.assertEqual(type(priData), type(())) if verbose: print('getGenre key: %r data: %r' % (priKey, priData)) genre = priData[2] if genre == 'Blues': return db.DB_DONOTINDEX else: - return genre.encode("utf-8") + return genre class ShelveAssociateHashTestCase(ShelveAssociateTestCase): @@ -418,15 +384,17 @@ t2 = Thread(target = self.writer2, args = (d, )) + t1.setDaemon(True) + t2.setDaemon(True) t1.start() t2.start() t1.join() t2.join() def writer1(self, d): - for key, value in musicdata.items(): + for key, value in list(musicdata.items()): if type(self.keytype) == type(''): - key = ("%02d" % key).encode("utf-8") + key = "%02d" % key d.put(key, '|'.join(value)) def writer2(self, d): @@ -452,24 +420,23 @@ def test_suite(): suite = unittest.TestSuite() - if db.version() >= (3, 3, 11): - suite.addTest(unittest.makeSuite(AssociateErrorTestCase)) - - suite.addTest(unittest.makeSuite(AssociateHashTestCase)) - suite.addTest(unittest.makeSuite(AssociateBTreeTestCase)) - suite.addTest(unittest.makeSuite(AssociateRecnoTestCase)) - - if db.version() >= (4, 1): - suite.addTest(unittest.makeSuite(AssociateBTreeTxnTestCase)) + suite.addTest(unittest.makeSuite(AssociateErrorTestCase)) - suite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase)) - suite.addTest(unittest.makeSuite(ShelveAssociateBTreeTestCase)) - suite.addTest(unittest.makeSuite(ShelveAssociateRecnoTestCase)) - - if have_threads: - suite.addTest(unittest.makeSuite(ThreadedAssociateHashTestCase)) - suite.addTest(unittest.makeSuite(ThreadedAssociateBTreeTestCase)) - suite.addTest(unittest.makeSuite(ThreadedAssociateRecnoTestCase)) + suite.addTest(unittest.makeSuite(AssociateHashTestCase)) + suite.addTest(unittest.makeSuite(AssociateBTreeTestCase)) + suite.addTest(unittest.makeSuite(AssociateRecnoTestCase)) + + if db.version() >= (4, 1): + suite.addTest(unittest.makeSuite(AssociateBTreeTxnTestCase)) + + suite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase)) + suite.addTest(unittest.makeSuite(ShelveAssociateBTreeTestCase)) + suite.addTest(unittest.makeSuite(ShelveAssociateRecnoTestCase)) + + if have_threads: + suite.addTest(unittest.makeSuite(ThreadedAssociateHashTestCase)) + suite.addTest(unittest.makeSuite(ThreadedAssociateBTreeTestCase)) + suite.addTest(unittest.makeSuite(ThreadedAssociateRecnoTestCase)) return suite Modified: python/branches/py3k/Lib/bsddb/test/test_basics.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_basics.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_basics.py Sun Aug 31 16:12:11 2008 @@ -4,29 +4,17 @@ """ import os -import sys import errno import string -import tempfile from pprint import pprint import unittest import time -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db -except ImportError: - # For Python 2.3 - from bsddb import db - -from bsddb.test.test_all import verbose -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +from .test_all import db, test_support, verbose, get_new_environment_path, \ + get_new_database_path + +DASH = '-' -DASH = b'-' -letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' #---------------------------------------------------------------------- @@ -38,8 +26,8 @@ print('bsddb.db.version(): %s' % (info, )) print(db.DB_VERSION_STRING) print('-=' * 20) - assert info == (db.DB_VERSION_MAJOR, db.DB_VERSION_MINOR, - db.DB_VERSION_PATCH) + self.assertEqual(info, (db.DB_VERSION_MAJOR, db.DB_VERSION_MINOR, + db.DB_VERSION_PATCH)) #---------------------------------------------------------------------- @@ -57,10 +45,7 @@ def setUp(self): if self.useEnv: - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - test_support.rmtree(homeDir) - os.mkdir(homeDir) + self.homeDir=get_new_environment_path() try: self.env = db.DBEnv() self.env.set_lg_max(1024*1024) @@ -68,17 +53,14 @@ self.env.set_tx_timestamp(int(time.time())) self.env.set_flags(self.envsetflags, 1) self.env.open(self.homeDir, self.envflags | db.DB_CREATE) - old_tempfile_tempdir = tempfile.tempdir - tempfile.tempdir = self.homeDir - self.filename = os.path.split(tempfile.mktemp())[1] - tempfile.tempdir = old_tempfile_tempdir + self.filename = "test" # Yes, a bare except is intended, since we're re-raising the exc. except: - test_support.rmtree(homeDir) + test_support.rmtree(self.homeDir) raise else: self.env = None - self.filename = tempfile.mktemp() + self.filename = get_new_database_path() # create and open the DB self.d = db.DB(self.env) @@ -100,13 +82,6 @@ if self.env is not None: self.env.close() test_support.rmtree(self.homeDir) - ## XXX(nnorwitz): is this comment stil valid? - ## Make a new DBEnv to remove the env files from the home dir. - ## (It can't be done while the env is open, nor after it has been - ## closed, so we make a new one to do it.) - #e = db.DBEnv() - #e.remove(self.homeDir) - #os.remove(os.path.join(self.homeDir, self.filename)) else: os.remove(self.filename) @@ -117,15 +92,13 @@ for x in range(self._numKeys//2): key = '%04d' % (self._numKeys - x) # insert keys in reverse order - key = key.encode("utf-8") data = self.makeData(key) d.put(key, data, _txn) - d.put(b'empty value', b'', _txn) + d.put('empty value', '', _txn) for x in range(self._numKeys//2-1): key = '%04d' % x # and now some in forward order - key = key.encode("utf-8") data = self.makeData(key) d.put(key, data, _txn) @@ -151,49 +124,57 @@ print('\n', '-=' * 30) print("Running %s.test01_GetsAndPuts..." % self.__class__.__name__) - for key in [b'0001', b'0100', b'0400', b'0700', b'0999']: + for key in ['0001', '0100', '0400', '0700', '0999']: data = d.get(key) if verbose: print(data) - assert d.get(b'0321') == b'0321-0321-0321-0321-0321' + self.assertEqual(d.get('0321'), '0321-0321-0321-0321-0321') # By default non-existant keys return None... - assert d.get(b'abcd') == None + self.assertEqual(d.get('abcd'), None) # ...but they raise exceptions in other situations. Call # set_get_returns_none() to change it. try: - d.delete(b'abcd') + d.delete('abcd') except db.DBNotFoundError as val: - assert val.args[0] == db.DB_NOTFOUND + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.DB_NOTFOUND) + else : + self.assertEqual(val.args[0], db.DB_NOTFOUND) if verbose: print(val) else: self.fail("expected exception") - d.put(b'abcd', b'a new record') - assert d.get(b'abcd') == b'a new record' + d.put('abcd', 'a new record') + self.assertEqual(d.get('abcd'), 'a new record') - d.put(b'abcd', b'same key') + d.put('abcd', 'same key') if self.dbsetflags & db.DB_DUP: - assert d.get(b'abcd') == b'a new record' + self.assertEqual(d.get('abcd'), 'a new record') else: - assert d.get(b'abcd') == b'same key' + self.assertEqual(d.get('abcd'), 'same key') try: - d.put(b'abcd', b'this should fail', flags=db.DB_NOOVERWRITE) + d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE) except db.DBKeyExistError as val: - assert val.args[0] == db.DB_KEYEXIST + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.DB_KEYEXIST) + else : + self.assertEqual(val.args[0], db.DB_KEYEXIST) if verbose: print(val) else: self.fail("expected exception") if self.dbsetflags & db.DB_DUP: - assert d.get(b'abcd') == b'a new record' + self.assertEqual(d.get('abcd'), 'a new record') else: - assert d.get(b'abcd') == b'same key' + self.assertEqual(d.get('abcd'), 'same key') d.sync() @@ -207,28 +188,28 @@ self.d.open(self.filename) d = self.d - assert d.get(b'0321') == b'0321-0321-0321-0321-0321' + self.assertEqual(d.get('0321'), '0321-0321-0321-0321-0321') if self.dbsetflags & db.DB_DUP: - assert d.get(b'abcd') == b'a new record' + self.assertEqual(d.get('abcd'), 'a new record') else: - assert d.get(b'abcd') == b'same key' + self.assertEqual(d.get('abcd'), 'same key') - rec = d.get_both(b'0555', b'0555-0555-0555-0555-0555') + rec = d.get_both('0555', '0555-0555-0555-0555-0555') if verbose: print(rec) - assert d.get_both(b'0555', b'bad data') == None + self.assertEqual(d.get_both('0555', 'bad data'), None) # test default value - data = d.get(b'bad key', b'bad data') - assert data == b'bad data' + data = d.get('bad key', 'bad data') + self.assertEqual(data, 'bad data') # any object can pass through - data = d.get(b'bad key', self) - assert data == self + data = d.get('bad key', self) + self.assertEqual(data, self) s = d.stat() - assert type(s) == type({}) + self.assertEqual(type(s), type({})) if verbose: print('d.stat() returned this dictionary:') pprint(s) @@ -244,49 +225,51 @@ print("Running %s.test02_DictionaryMethods..." % \ self.__class__.__name__) - for key in [b'0002', b'0101', b'0401', b'0701', b'0998']: + for key in ['0002', '0101', '0401', '0701', '0998']: data = d[key] - assert data == self.makeData(key) + self.assertEqual(data, self.makeData(key)) if verbose: print(data) - assert len(d) == self._numKeys - keys = d.keys() - assert len(keys) == self._numKeys - assert type(keys) == type([]) - - d[b'new record'] = b'a new record' - assert len(d) == self._numKeys+1 - keys = d.keys() - assert len(keys) == self._numKeys+1 - - d[b'new record'] = b'a replacement record' - assert len(d) == self._numKeys+1 - keys = d.keys() - assert len(keys) == self._numKeys+1 + self.assertEqual(len(d), self._numKeys) + keys = list(d.keys()) + self.assertEqual(len(keys), self._numKeys) + self.assertEqual(type(keys), type([])) + + d['new record'] = 'a new record' + self.assertEqual(len(d), self._numKeys+1) + keys = list(d.keys()) + self.assertEqual(len(keys), self._numKeys+1) + + d['new record'] = 'a replacement record' + self.assertEqual(len(d), self._numKeys+1) + keys = list(d.keys()) + self.assertEqual(len(keys), self._numKeys+1) if verbose: print("the first 10 keys are:") pprint(keys[:10]) - assert d[b'new record'] == b'a replacement record' - - assert d.has_key(b'0001') == 1 - assert d.has_key(b'spam') == 0 + self.assertEqual(d['new record'], 'a replacement record') - items = d.items() - assert len(items) == self._numKeys+1 - assert type(items) == type([]) - assert type(items[0]) == type(()) - assert len(items[0]) == 2 +# We check also the positional parameter + self.assertEqual(d.has_key('0001', None), 1) +# We check also the keyword parameter + self.assertEqual(d.has_key('spam', txn=None), 0) + + items = list(d.items()) + self.assertEqual(len(items), self._numKeys+1) + self.assertEqual(type(items), type([])) + self.assertEqual(type(items[0]), type(())) + self.assertEqual(len(items[0]), 2) if verbose: print("the first 10 items are:") pprint(items[:10]) - values = d.values() - assert len(values) == self._numKeys+1 - assert type(values) == type([]) + values = list(d.values()) + self.assertEqual(len(values), self._numKeys+1) + self.assertEqual(type(values), type([])) if verbose: print("the first 10 values are:") @@ -315,17 +298,22 @@ if verbose and count % 100 == 0: print(rec) try: - rec = c.next() + rec = next(c) except db.DBNotFoundError as val: if get_raises_error: - assert val.args[0] == db.DB_NOTFOUND + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.DB_NOTFOUND) + else : + self.assertEqual(val.args[0], db.DB_NOTFOUND) if verbose: print(val) rec = None else: self.fail("unexpected DBNotFoundError") - assert c.get_current_size() == len(c.current()[1]), "%s != len(%r)" % (c.get_current_size(), c.current()[1]) + self.assertEqual(c.get_current_size(), len(c.current()[1]), + "%s != len(%r)" % (c.get_current_size(), c.current()[1])) - assert count == self._numKeys + self.assertEqual(count, self._numKeys) rec = c.last() @@ -338,73 +326,89 @@ rec = c.prev() except db.DBNotFoundError as val: if get_raises_error: - assert val.args[0] == db.DB_NOTFOUND + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.DB_NOTFOUND) + else : + self.assertEqual(val.args[0], db.DB_NOTFOUND) if verbose: print(val) rec = None else: self.fail("unexpected DBNotFoundError") - assert count == self._numKeys + self.assertEqual(count, self._numKeys) - rec = c.set(b'0505') + rec = c.set('0505') rec2 = c.current() - assert rec == rec2, (repr(rec),repr(rec2)) - assert rec[0] == b'0505' - assert rec[1] == self.makeData(b'0505') - assert c.get_current_size() == len(rec[1]) + self.assertEqual(rec, rec2) + self.assertEqual(rec[0], '0505') + self.assertEqual(rec[1], self.makeData('0505')) + self.assertEqual(c.get_current_size(), len(rec[1])) # make sure we get empty values properly - rec = c.set(b'empty value') - assert rec[1] == b'' - assert c.get_current_size() == 0 + rec = c.set('empty value') + self.assertEqual(rec[1], '') + self.assertEqual(c.get_current_size(), 0) try: - n = c.set(b'bad key') + n = c.set('bad key') except db.DBNotFoundError as val: - assert val.args[0] == db.DB_NOTFOUND + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.DB_NOTFOUND) + else : + self.assertEqual(val.args[0], db.DB_NOTFOUND) if verbose: print(val) else: if set_raises_error: self.fail("expected exception") - if n is not None: + if n != None: self.fail("expected None: %r" % (n,)) - rec = c.get_both(b'0404', self.makeData(b'0404')) - assert rec == (b'0404', self.makeData(b'0404')) + rec = c.get_both('0404', self.makeData('0404')) + self.assertEqual(rec, ('0404', self.makeData('0404'))) try: - n = c.get_both(b'0404', b'bad data') + n = c.get_both('0404', 'bad data') except db.DBNotFoundError as val: - assert val.args[0] == db.DB_NOTFOUND + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.DB_NOTFOUND) + else : + self.assertEqual(val.args[0], db.DB_NOTFOUND) if verbose: print(val) else: if get_raises_error: self.fail("expected exception") - if n is not None: + if n != None: self.fail("expected None: %r" % (n,)) if self.d.get_type() == db.DB_BTREE: - rec = c.set_range(b'011') + rec = c.set_range('011') if verbose: print("searched for '011', found: ", rec) - rec = c.set_range(b'011',dlen=0,doff=0) + rec = c.set_range('011',dlen=0,doff=0) if verbose: print("searched (partial) for '011', found: ", rec) - if rec[1] != b'': self.fail('expected empty data portion') + if rec[1] != '': self.fail('expected empty data portion') - ev = c.set_range(b'empty value') + ev = c.set_range('empty value') if verbose: print("search for 'empty value' returned", ev) - if ev[1] != b'': self.fail('empty value lookup failed') + if ev[1] != '': self.fail('empty value lookup failed') - c.set(b'0499') + c.set('0499') c.delete() try: rec = c.current() except db.DBKeyEmptyError as val: if get_raises_error: - assert val.args[0] == db.DB_KEYEMPTY + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.DB_KEYEMPTY) + else : + self.assertEqual(val.args[0], db.DB_KEYEMPTY) if verbose: print(val) else: self.fail("unexpected DBKeyEmptyError") @@ -412,16 +416,16 @@ if get_raises_error: self.fail('DBKeyEmptyError exception expected') - c.next() + next(c) c2 = c.dup(db.DB_POSITION) - assert c.current() == c2.current() + self.assertEqual(c.current(), c2.current()) - c2.put(b'', b'a new value', db.DB_CURRENT) - assert c.current() == c2.current() - assert c.current()[1] == b'a new value' + c2.put('', 'a new value', db.DB_CURRENT) + self.assertEqual(c.current(), c2.current()) + self.assertEqual(c.current()[1], 'a new value') - c2.put(b'', b'er', db.DB_CURRENT, dlen=0, doff=5) - assert c2.current()[1] == b'a newer value' + c2.put('', 'er', db.DB_CURRENT, dlen=0, doff=5) + self.assertEqual(c2.current()[1], 'a newer value') c.close() c2.close() @@ -441,7 +445,7 @@ 'put':('', 'spam', db.DB_CURRENT), 'set': ("0505",), } - for method, args in methods_to_test.items(): + for method, args in list(methods_to_test.items()): try: if verbose: print("attempting to use a closed cursor's %s method" % \ @@ -449,7 +453,11 @@ # a bug may cause a NULL pointer dereference... getattr(c, method)(*args) except db.DBError as val: - assert val.args[0] == 0 + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], 0) + else : + self.assertEqual(val.args[0], 0) if verbose: print(val) else: self.fail("no exception raised when using a buggy cursor's" @@ -474,7 +482,7 @@ self.__class__.__name__) old = self.d.set_get_returns_none(0) - assert old == 2 + self.assertEqual(old, 2) self.test03_SimpleCursorStuff(get_raises_error=1, set_raises_error=1) def test03b_SimpleCursorWithGetReturnsNone1(self): @@ -496,9 +504,9 @@ self.__class__.__name__) old = self.d.set_get_returns_none(1) - assert old == 2 + self.assertEqual(old, 2) old = self.d.set_get_returns_none(2) - assert old == 1 + self.assertEqual(old, 1) self.test03_SimpleCursorStuff(get_raises_error=0, set_raises_error=0) #---------------------------------------- @@ -510,26 +518,27 @@ print("Running %s.test04_PartialGetAndPut..." % \ self.__class__.__name__) - key = b"partialTest" - data = b"1" * 1000 + b"2" * 1000 + key = "partialTest" + data = "1" * 1000 + "2" * 1000 d.put(key, data) - assert d.get(key) == data - assert d.get(key, dlen=20, doff=990) == (b"1" * 10) + (b"2" * 10) + self.assertEqual(d.get(key), data) + self.assertEqual(d.get(key, dlen=20, doff=990), + ("1" * 10) + ("2" * 10)) - d.put(b"partialtest2", (b"1" * 30000) + b"robin" ) - assert d.get(b"partialtest2", dlen=5, doff=30000) == b"robin" + d.put("partialtest2", ("1" * 30000) + "robin" ) + self.assertEqual(d.get("partialtest2", dlen=5, doff=30000), "robin") # There seems to be a bug in DB here... Commented out the test for # now. - ##assert d.get("partialtest2", dlen=5, doff=30010) == "" + ##self.assertEqual(d.get("partialtest2", dlen=5, doff=30010), "") if self.dbsetflags != db.DB_DUP: # Partial put with duplicate records requires a cursor - d.put(key, b"0000", dlen=2000, doff=0) - assert d.get(key) == b"0000" + d.put(key, "0000", dlen=2000, doff=0) + self.assertEqual(d.get(key), "0000") - d.put(key, b"1111", dlen=1, doff=2) - assert d.get(key) == b"0011110" + d.put(key, "1111", dlen=1, doff=2) + self.assertEqual(d.get(key), "0011110") #---------------------------------------- @@ -540,30 +549,27 @@ print("Running %s.test05_GetSize..." % self.__class__.__name__) for i in range(1, 50000, 500): - key = ("size%s" % i).encode("utf-8") + key = "size%s" % i #print "before ", i, - d.put(key, b"1" * i) + d.put(key, "1" * i) #print "after", - assert d.get_size(key) == i + self.assertEqual(d.get_size(key), i) #print "done" #---------------------------------------- def test06_Truncate(self): - if db.version() < (3,3): - # truncate is a feature of BerkeleyDB 3.3 and above - return - d = self.d if verbose: print('\n', '-=' * 30) print("Running %s.test99_Truncate..." % self.__class__.__name__) - d.put(b"abcde", b"ABCDE"); + d.put("abcde", "ABCDE"); num = d.truncate() - assert num >= 1, "truncate returned <= 0 on non-empty database" + self.assert_(num >= 1, "truncate returned <= 0 on non-empty database") num = d.truncate() - assert num == 0, "truncate on empty DB returned nonzero (%r)" % (num,) + self.assertEqual(num, 0, + "truncate on empty DB returned nonzero (%r)" % (num,)) #---------------------------------------- @@ -628,6 +634,11 @@ #---------------------------------------------------------------------- class BasicTransactionTestCase(BasicTestCase): + import sys + if sys.version_info[:3] < (2, 4, 0): + def assertTrue(self, expr, msg=None): + self.failUnless(expr,msg=msg) + dbopenflags = db.DB_THREAD | db.DB_AUTO_COMMIT useEnv = 1 envflags = (db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK | @@ -653,19 +664,21 @@ print('\n', '-=' * 30) print("Running %s.test06_Transactions..." % self.__class__.__name__) - assert d.get(b'new rec', txn=self.txn) == None - d.put(b'new rec', b'this is a new record', self.txn) - assert d.get(b'new rec', txn=self.txn) == b'this is a new record' + self.assertEqual(d.get('new rec', txn=self.txn), None) + d.put('new rec', 'this is a new record', self.txn) + self.assertEqual(d.get('new rec', txn=self.txn), + 'this is a new record') self.txn.abort() - assert d.get(b'new rec') == None + self.assertEqual(d.get('new rec'), None) self.txn = self.env.txn_begin() - assert d.get(b'new rec', txn=self.txn) == None - d.put(b'new rec', b'this is a new record', self.txn) - assert d.get(b'new rec', txn=self.txn) == b'this is a new record' + self.assertEqual(d.get('new rec', txn=self.txn), None) + d.put('new rec', 'this is a new record', self.txn) + self.assertEqual(d.get('new rec', txn=self.txn), + 'this is a new record') self.txn.commit() - assert d.get(b'new rec') == b'this is a new record' + self.assertEqual(d.get('new rec'), 'this is a new record') self.txn = self.env.txn_begin() c = d.cursor(self.txn) @@ -675,8 +688,8 @@ count = count + 1 if verbose and count % 100 == 0: print(rec) - rec = c.next() - assert count == self._numKeys+1 + rec = next(c) + self.assertEqual(count, self._numKeys+1) c.close() # Cursors *MUST* be closed before commit! self.txn.commit() @@ -687,43 +700,39 @@ except db.DBIncompleteError: pass - if db.version() >= (4,0): - statDict = self.env.log_stat(0); - assert 'magic' in statDict - assert 'version' in statDict - assert 'cur_file' in statDict - assert 'region_nowait' in statDict + statDict = self.env.log_stat(0); + self.assert_('magic' in statDict) + self.assert_('version' in statDict) + self.assert_('cur_file' in statDict) + self.assert_('region_nowait' in statDict) # must have at least one log file present: logs = self.env.log_archive(db.DB_ARCH_ABS | db.DB_ARCH_LOG) - assert logs != None + self.assertNotEqual(logs, None) for log in logs: if verbose: print('log file: ' + log) if db.version() >= (4,2): logs = self.env.log_archive(db.DB_ARCH_REMOVE) - assert not logs + self.assertTrue(not logs) self.txn = self.env.txn_begin() #---------------------------------------- def test07_TxnTruncate(self): - if db.version() < (3,3): - # truncate is a feature of BerkeleyDB 3.3 and above - return - d = self.d if verbose: print('\n', '-=' * 30) print("Running %s.test07_TxnTruncate..." % self.__class__.__name__) - d.put(b"abcde", b"ABCDE"); + d.put("abcde", "ABCDE"); txn = self.env.txn_begin() num = d.truncate(txn) - assert num >= 1, "truncate returned <= 0 on non-empty database" + self.assert_(num >= 1, "truncate returned <= 0 on non-empty database") num = d.truncate(txn) - assert num == 0, "truncate on empty DB returned nonzero (%r)" % (num,) + self.assertEqual(num, 0, + "truncate on empty DB returned nonzero (%r)" % (num,)) txn.commit() #---------------------------------------- @@ -769,20 +778,20 @@ print("Running %s.test07_RecnoInBTree..." % self.__class__.__name__) rec = d.get(200) - assert type(rec) == type(()) - assert len(rec) == 2 + self.assertEqual(type(rec), type(())) + self.assertEqual(len(rec), 2) if verbose: print("Record #200 is ", rec) c = d.cursor() - c.set(b'0200') + c.set('0200') num = c.get_recno() - assert type(num) == type(1) + self.assertEqual(type(num), type(1)) if verbose: print("recno of d['0200'] is ", num) rec = c.current() - assert c.set_recno(num) == rec + self.assertEqual(c.set_recno(num), rec) c.close() @@ -803,40 +812,39 @@ print("Running %s.test08_DuplicateKeys..." % \ self.__class__.__name__) - d.put(b"dup0", b"before") + d.put("dup0", "before") for x in "The quick brown fox jumped over the lazy dog.".split(): - x = x.encode("ascii") - d.put(b"dup1", x) - d.put(b"dup2", b"after") + d.put("dup1", x) + d.put("dup2", "after") - data = d.get(b"dup1") - assert data == b"The" + data = d.get("dup1") + self.assertEqual(data, "The") if verbose: print(data) c = d.cursor() - rec = c.set(b"dup1") - assert rec == (b'dup1', b'The') + rec = c.set("dup1") + self.assertEqual(rec, ('dup1', 'The')) - next = c.next() - assert next == (b'dup1', b'quick') + next_reg = next(c) + self.assertEqual(next_reg, ('dup1', 'quick')) - rec = c.set(b"dup1") + rec = c.set("dup1") count = c.count() - assert count == 9 + self.assertEqual(count, 9) next_dup = c.next_dup() - assert next_dup == (b'dup1', b'quick') + self.assertEqual(next_dup, ('dup1', 'quick')) - rec = c.set(b'dup1') + rec = c.set('dup1') while rec is not None: if verbose: print(rec) rec = c.next_dup() - c.set(b'dup1') + c.set('dup1') rec = c.next_nodup() - assert rec[0] != b'dup1' + self.assertNotEqual(rec[0], 'dup1') if verbose: print(rec) @@ -884,11 +892,9 @@ self.dbopenflags|db.DB_CREATE) for x in "The quick brown fox jumped over the lazy dog".split(): - x = x.encode("ascii") d2.put(x, self.makeData(x)) - for x in letters: - x = x.encode("ascii") + for x in string.letters: d3.put(x, x*70) d1.sync() @@ -917,8 +923,8 @@ count = count + 1 if verbose and (count % 50) == 0: print(rec) - rec = c1.next() - assert count == self._numKeys + rec = next(c1) + self.assertEqual(count, self._numKeys) count = 0 rec = c2.first() @@ -926,8 +932,8 @@ count = count + 1 if verbose: print(rec) - rec = c2.next() - assert count == 9 + rec = next(c2) + self.assertEqual(count, 9) count = 0 rec = c3.first() @@ -935,15 +941,14 @@ count = count + 1 if verbose: print(rec) - rec = c3.next() - assert count == 52 + rec = next(c3) + self.assertEqual(count, len(string.letters)) c1.close() c2.close() c3.close() - d1.close() d2.close() d3.close() @@ -965,6 +970,55 @@ envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK +class PrivateObject(unittest.TestCase) : + import sys + if sys.version_info[:3] < (2, 4, 0): + def assertTrue(self, expr, msg=None): + self.failUnless(expr,msg=msg) + + def tearDown(self) : + del self.obj + + def test01_DefaultIsNone(self) : + self.assertEqual(self.obj.get_private(), None) + + def test02_assignment(self) : + a = "example of private object" + self.obj.set_private(a) + b = self.obj.get_private() + self.assertTrue(a is b) # Object identity + + def test03_leak_assignment(self) : + import sys + a = "example of private object" + refcount = sys.getrefcount(a) + self.obj.set_private(a) + self.assertEqual(refcount+1, sys.getrefcount(a)) + self.obj.set_private(None) + self.assertEqual(refcount, sys.getrefcount(a)) + + def test04_leak_GC(self) : + import sys + a = "example of private object" + refcount = sys.getrefcount(a) + self.obj.set_private(a) + self.obj = None + self.assertEqual(refcount, sys.getrefcount(a)) + +class DBEnvPrivateObject(PrivateObject) : + def setUp(self) : + self.obj = db.DBEnv() + +class DBPrivateObject(PrivateObject) : + def setUp(self) : + self.obj = db.DB() + +class CrashAndBurn(unittest.TestCase) : + def test01_OpenCrash(self) : + # See http://bugs.python.org/issue3307 + self.assertRaises(db.DBInvalidArgError, db.DB, None, 65535) + + #---------------------------------------------------------------------- #---------------------------------------------------------------------- @@ -988,6 +1042,9 @@ suite.addTest(unittest.makeSuite(HashDUPWithThreadTestCase)) suite.addTest(unittest.makeSuite(BTreeMultiDBTestCase)) suite.addTest(unittest.makeSuite(HashMultiDBTestCase)) + suite.addTest(unittest.makeSuite(DBEnvPrivateObject)) + suite.addTest(unittest.makeSuite(DBPrivateObject)) + #suite.addTest(unittest.makeSuite(CrashAndBurn)) return suite Modified: python/branches/py3k/Lib/bsddb/test/test_compare.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_compare.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_compare.py Sun Aug 31 16:12:11 2008 @@ -2,55 +2,51 @@ TestCases for python DB Btree key comparison function. """ -import shutil import sys, os, re -from io import StringIO -import tempfile from . import test_all +from io import StringIO import unittest -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db, dbshelve -except ImportError: - # For Python 2.3 - from bsddb import db, dbshelve - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support + +from .test_all import db, dbshelve, test_support, \ + get_new_environment_path, get_new_database_path + lexical_cmp = cmp def lowercase_cmp(left, right): - return cmp (str(left, encoding='ascii').lower(), - str(right, encoding='ascii').lower()) + return cmp (left.lower(), right.lower()) def make_reverse_comparator (cmp): def reverse (left, right, delegate=cmp): return - delegate (left, right) return reverse -_expected_lexical_test_data = [s.encode('ascii') for s in - ('', 'CCCP', 'a', 'aaa', 'b', 'c', 'cccce', 'ccccf')] -_expected_lowercase_test_data = [s.encode('ascii') for s in - ('', 'a', 'aaa', 'b', 'c', 'CC', 'cccce', 'ccccf', 'CCCP')] - - -def CmpToKey(mycmp): - 'Convert a cmp= function into a key= function' - class K(object): - def __init__(self, obj, *args): - self.obj = obj - def __lt__(self, other): - return mycmp(self.obj, other.obj) == -1 - return K +_expected_lexical_test_data = ['', 'CCCP', 'a', 'aaa', 'b', 'c', 'cccce', 'ccccf'] +_expected_lowercase_test_data = ['', 'a', 'aaa', 'b', 'c', 'CC', 'cccce', 'ccccf', 'CCCP'] class ComparatorTests (unittest.TestCase): def comparator_test_helper (self, comparator, expected_data): data = expected_data[:] - data.sort (key=CmpToKey(comparator)) + + import sys + if sys.version_info[0] < 3 : + if sys.version_info[:3] < (2, 4, 0): + data.sort(comparator) + else : + data.sort(cmp=comparator) + else : # Insertion Sort. Please, improve + data2 = [] + for i in data : + for j, k in enumerate(data2) : + r = comparator(k, i) + if r == 1 : + data2.insert(j, i) + break + else : + data2.append(i) + data = data2 + self.failUnless (data == expected_data, "comparator `%s' is not right: %s vs. %s" % (comparator, expected_data, data)) @@ -71,30 +67,24 @@ def setUp (self): self.filename = self.__class__.__name__ + '.db' - homeDir = os.path.join (tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - try: - os.mkdir (homeDir) - except os.error: - pass - - env = db.DBEnv () + self.homeDir = get_new_environment_path() + env = db.DBEnv() env.open (self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL | db.DB_INIT_LOCK | db.DB_THREAD) self.env = env def tearDown (self): - self.closeDB () + self.closeDB() if self.env is not None: - self.env.close () + self.env.close() self.env = None test_support.rmtree(self.homeDir) def addDataToDB (self, data): i = 0 for item in data: - self.db.put (item, str(i).encode("ascii")) + self.db.put (item, str (i)) i = i + 1 def createDB (self, key_comparator): @@ -128,10 +118,10 @@ self.failUnless (index < len (expected), "to many values returned from cursor") self.failUnless (expected[index] == key, - "expected value %r at %d but got %r" + "expected value `%s' at %d but got `%s'" % (expected[index], index, key)) index = index + 1 - rec = curs.next () + rec = next(curs) self.failUnless (index == len (expected), "not enough values returned from cursor") finally: @@ -158,10 +148,10 @@ def socialist_comparator (l, r): return 0 self.createDB (socialist_comparator) - self.addDataToDB ([b'b', b'a', b'd']) + self.addDataToDB (['b', 'a', 'd']) # all things being equal the first key will be the only key # in the database... (with the last key's value fwiw) - self.finishTest ([b'b']) + self.finishTest (['b']) class BtreeExceptionsTestCase (AbstractBtreeKeyCompareTestCase): @@ -200,9 +190,9 @@ finally: temp = sys.stderr sys.stderr = stdErr - errorOut = temp.getvalue() - if not successRe.search(errorOut): - self.fail("unexpected stderr output: %r" % errorOut) + errorOut = temp.getvalue() + if not successRe.search(errorOut): + self.fail("unexpected stderr output:\n"+errorOut) def _test_compare_function_exception (self): self.startTest () @@ -213,7 +203,7 @@ raise RuntimeError("i'm a naughty comparison function") self.createDB (bad_comparator) #print "\n*** test should print 2 uncatchable tracebacks ***" - self.addDataToDB ([b'a', b'b', b'c']) # this should raise, but... + self.addDataToDB (['a', 'b', 'c']) # this should raise, but... self.finishTest () def test_compare_function_exception(self): @@ -231,7 +221,7 @@ return l self.createDB (bad_comparator) #print "\n*** test should print 2 errors about returning an int ***" - self.addDataToDB ([b'a', b'b', b'c']) # this should raise, but... + self.addDataToDB (['a', 'b', 'c']) # this should raise, but... self.finishTest () def test_compare_function_bad_return(self): @@ -250,7 +240,7 @@ self.createDB (my_compare) try: self.db.set_bt_compare (my_compare) - assert False, "this set should fail" + self.assert_(0, "this set should fail") except RuntimeError as msg: pass @@ -259,10 +249,9 @@ res = unittest.TestSuite () res.addTest (unittest.makeSuite (ComparatorTests)) - if db.version () >= (3, 3, 11): - res.addTest (unittest.makeSuite (BtreeExceptionsTestCase)) - res.addTest (unittest.makeSuite (BtreeKeyCompareTestCase)) + res.addTest (unittest.makeSuite (BtreeExceptionsTestCase)) + res.addTest (unittest.makeSuite (BtreeKeyCompareTestCase)) return res if __name__ == '__main__': - unittest.main (defaultTest = 'test_suite') + unittest.main (defaultTest = 'suite') Modified: python/branches/py3k/Lib/bsddb/test/test_compat.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_compat.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_compat.py Sun Aug 31 16:12:11 2008 @@ -3,18 +3,16 @@ regression test suite. """ -import sys, os +import os, string import unittest -import tempfile -from bsddb.test.test_all import verbose - -from bsddb import db, hashopen, btopen, rnopen +from .test_all import db, hashopen, btopen, rnopen, verbose, \ + get_new_database_path class CompatibilityTestCase(unittest.TestCase): def setUp(self): - self.filename = tempfile.mktemp() + self.filename = get_new_database_path() def tearDown(self): try: @@ -36,31 +34,31 @@ f = rnopen(self.filename, 'c') for x in range(len(data)): - f[x+1] = data[x].encode("ascii") + f[x+1] = data[x] getTest = (f[1], f[2], f[3]) if verbose: print('%s %s %s' % getTest) - assert getTest[1] == b'quick', 'data mismatch!' + self.assertEqual(getTest[1], 'quick', 'data mismatch!') rv = f.set_location(3) - if rv != (3, b'brown'): + if rv != (3, 'brown'): self.fail('recno database set_location failed: '+repr(rv)) - f[25] = b'twenty-five' + f[25] = 'twenty-five' f.close() del f f = rnopen(self.filename, 'w') - f[20] = b'twenty' + f[20] = 'twenty' def noRec(f): rec = f[15] self.assertRaises(KeyError, noRec, f) def badKey(f): - rec = f[b'a string'] + rec = f['a string'] self.assertRaises(TypeError, badKey, f) del f[3] @@ -70,7 +68,7 @@ if verbose: print(rec) try: - rec = f.next() + rec = next(f) except KeyError: break @@ -96,42 +94,42 @@ else: if verbose: print("truth test: false") - f[b'0'] = b'' - f[b'a'] = b'Guido' - f[b'b'] = b'van' - f[b'c'] = b'Rossum' - f[b'd'] = b'invented' + f['0'] = '' + f['a'] = 'Guido' + f['b'] = 'van' + f['c'] = 'Rossum' + f['d'] = 'invented' # 'e' intentionally left out - f[b'f'] = b'Python' + f['f'] = 'Python' if verbose: print('%s %s %s' % (f['a'], f['b'], f['c'])) if verbose: print('key ordering...') start = f.set_location(f.first()[0]) - if start != (b'0', b''): + if start != ('0', ''): self.fail("incorrect first() result: "+repr(start)) while 1: try: - rec = f.next() + rec = next(f) except KeyError: - assert rec == f.last(), 'Error, last != last!' + self.assertEqual(rec, f.last(), 'Error, last <> last!') f.previous() break if verbose: print(rec) - assert f.has_key(b'f'), 'Error, missing key!' + self.assert_('f' in f, 'Error, missing key!') # test that set_location() returns the next nearest key, value # on btree databases and raises KeyError on others. if factory == btopen: - e = f.set_location(b'e') - if e != (b'f', b'Python'): + e = f.set_location('e') + if e != ('f', 'Python'): self.fail('wrong key,value returned: '+repr(e)) else: try: - e = f.set_location(b'e') + e = f.set_location('e') except KeyError: pass else: @@ -155,17 +153,17 @@ if verbose: print('modification...') f = factory(self.filename, 'w') - f[b'd'] = b'discovered' + f['d'] = 'discovered' if verbose: print('access...') - for key in f.keys(): + for key in list(f.keys()): word = f[key] if verbose: print(word) def noRec(f): - rec = f[b'no such key'] + rec = f['no such key'] self.assertRaises(KeyError, noRec, f) def badKey(f): Modified: python/branches/py3k/Lib/bsddb/test/test_cursor_pget_bug.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_cursor_pget_bug.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_cursor_pget_bug.py Sun Aug 31 16:12:11 2008 @@ -1,16 +1,8 @@ import unittest -import tempfile -import sys, os, glob -import shutil -import tempfile - -from bsddb import db - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +import os, glob +from .test_all import db, test_support, get_new_environment_path, \ + get_new_database_path #---------------------------------------------------------------------- @@ -19,11 +11,7 @@ db_name = 'test-cursor_pget.db' def setUp(self): - self.homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - try: - os.mkdir(self.homeDir) - except os.error: - pass + self.homeDir = get_new_environment_path() self.env = db.DBEnv() self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL) self.primary_db = db.DB(self.env) @@ -32,9 +20,9 @@ self.secondary_db.set_flags(db.DB_DUP) self.secondary_db.open(self.db_name, 'secondary', db.DB_BTREE, db.DB_CREATE) self.primary_db.associate(self.secondary_db, lambda key, data: data) - self.primary_db.put(b'salad', b'eggs') - self.primary_db.put(b'spam', b'ham') - self.primary_db.put(b'omelet', b'eggs') + self.primary_db.put('salad', 'eggs') + self.primary_db.put('spam', 'ham') + self.primary_db.put('omelet', 'eggs') def tearDown(self): @@ -49,11 +37,11 @@ def test_pget(self): cursor = self.secondary_db.cursor() - self.assertEquals((b'eggs', b'salad', b'eggs'), cursor.pget(key=b'eggs', flags=db.DB_SET)) - self.assertEquals((b'eggs', b'omelet', b'eggs'), cursor.pget(db.DB_NEXT_DUP)) + self.assertEquals(('eggs', 'salad', 'eggs'), cursor.pget(key='eggs', flags=db.DB_SET)) + self.assertEquals(('eggs', 'omelet', 'eggs'), cursor.pget(db.DB_NEXT_DUP)) self.assertEquals(None, cursor.pget(db.DB_NEXT_DUP)) - self.assertEquals((b'ham', b'spam', b'ham'), cursor.pget(b'ham', b'spam', flags=db.DB_SET)) + self.assertEquals(('ham', 'spam', 'ham'), cursor.pget('ham', 'spam', flags=db.DB_SET)) self.assertEquals(None, cursor.pget(db.DB_NEXT_DUP)) cursor.close() Modified: python/branches/py3k/Lib/bsddb/test/test_dbobj.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_dbobj.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_dbobj.py Sun Aug 31 16:12:11 2008 @@ -1,21 +1,9 @@ -import shutil -import sys, os +import os, string import unittest -import tempfile - -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db, dbobj -except ImportError: - # For Python 2.3 - from bsddb import db, dbobj - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +from .test_all import db, dbobj, test_support, get_new_environment_path, \ + get_new_database_path #---------------------------------------------------------------------- @@ -24,10 +12,7 @@ db_name = 'test-dbobj.db' def setUp(self): - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - try: os.mkdir(homeDir) - except os.error: pass + self.homeDir = get_new_environment_path() def tearDown(self): if hasattr(self, 'db'): @@ -40,18 +25,18 @@ class TestDBEnv(dbobj.DBEnv): pass class TestDB(dbobj.DB): def put(self, key, *args, **kwargs): - key = key.decode("ascii").upper().encode("ascii") + key = key.upper() # call our parent classes put method with an upper case key - return dbobj.DB.put(self, key, *args, **kwargs) + return dbobj.DB.put(*(self, key) + args, **kwargs) self.env = TestDBEnv() self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL) self.db = TestDB(self.env) self.db.open(self.db_name, db.DB_HASH, db.DB_CREATE) - self.db.put(b'spam', b'eggs') - assert self.db.get(b'spam') == None, \ - "overridden dbobj.DB.put() method failed [1]" - assert self.db.get(b'SPAM') == b'eggs', \ - "overridden dbobj.DB.put() method failed [2]" + self.db.put('spam', 'eggs') + self.assertEqual(self.db.get('spam'), None, + "overridden dbobj.DB.put() method failed [1]") + self.assertEqual(self.db.get('SPAM'), 'eggs', + "overridden dbobj.DB.put() method failed [2]") self.db.close() self.env.close() @@ -61,14 +46,14 @@ self.db = dbobj.DB(self.env) self.db.open(self.db_name+'02', db.DB_HASH, db.DB_CREATE) # __setitem__ - self.db[b'spam'] = b'eggs' + self.db['spam'] = 'eggs' # __len__ - assert len(self.db) == 1 + self.assertEqual(len(self.db), 1) # __getitem__ - assert self.db[b'spam'] == b'eggs' + self.assertEqual(self.db['spam'], 'eggs') # __del__ - del self.db[b'spam'] - assert self.db.get(b'spam') == None, "dbobj __del__ failed" + del self.db['spam'] + self.assertEqual(self.db.get('spam'), None, "dbobj __del__ failed") self.db.close() self.env.close() Modified: python/branches/py3k/Lib/bsddb/test/test_dbshelve.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_dbshelve.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_dbshelve.py Sun Aug 31 16:12:11 2008 @@ -2,19 +2,14 @@ TestCases for checking dbShelve objects. """ -import os -import shutil -import tempfile, random +import os, string +import random import unittest -from bsddb import db, dbshelve -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +from .test_all import db, dbshelve, test_support, verbose, \ + get_new_environment_path, get_new_database_path -from bsddb.test.test_all import verbose #---------------------------------------------------------------------- @@ -22,43 +17,44 @@ # We want the objects to be comparable so we can test dbshelve.values # later on. class DataClass: - def __init__(self): self.value = random.random() - def __repr__(self): - return "DataClass(%r)" % self.value + def __repr__(self) : # For Python 3.0 comparison + return "DataClass %f" %self.value - def __eq__(self, other): - value = self.value - if isinstance(other, DataClass): - other = other.value - return value == other - - def __lt__(self, other): - value = self.value - if isinstance(other, DataClass): - other = other.value - return value < other + def __cmp__(self, other): # For Python 2.x comparison + return cmp(self.value, other) -letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' class DBShelveTestCase(unittest.TestCase): def setUp(self): - self.filename = tempfile.mktemp() + import sys + if sys.version_info[0] >= 3 : + from .test_all import do_proxy_db_py3k + self._flag_proxy_db_py3k = do_proxy_db_py3k(False) + self.filename = get_new_database_path() self.do_open() def tearDown(self): + import sys + if sys.version_info[0] >= 3 : + from .test_all import do_proxy_db_py3k + do_proxy_db_py3k(self._flag_proxy_db_py3k) self.do_close() test_support.unlink(self.filename) def mk(self, key): """Turn key into an appropriate key type for this db""" # override in child class for RECNO - return key.encode("ascii") + import sys + if sys.version_info[0] < 3 : + return key + else : + return bytes(key, "iso8859-1") # 8 bits def populateDB(self, d): - for x in letters: + for x in string.letters: d[self.mk('S' + x)] = 10 * x # add a string d[self.mk('I' + x)] = ord(x) # add an integer d[self.mk('L' + x)] = [x] * 10 # add a list @@ -86,19 +82,13 @@ print("Running %s.test01_basics..." % self.__class__.__name__) self.populateDB(self.d) - if verbose: - print(1, self.d.keys()) self.d.sync() - if verbose: - print(2, self.d.keys()) self.do_close() self.do_open() - if verbose: - print(3, self.d.keys()) d = self.d l = len(d) - k = d.keys() + k = list(d.keys()) s = d.stat() f = d.fd() @@ -107,30 +97,37 @@ print("keys:", k) print("stats:", s) - self.assertFalse(d.has_key(self.mk('bad key'))) - self.assertTrue(d.has_key(self.mk('IA')), d.keys()) - self.assertTrue(d.has_key(self.mk('OA'))) + self.assertEqual(0, self.mk('bad key') in d) + self.assertEqual(1, self.mk('IA') in d) + self.assertEqual(1, self.mk('OA') in d) d.delete(self.mk('IA')) del d[self.mk('OA')] - self.assertFalse(d.has_key(self.mk('IA'))) - self.assertFalse(d.has_key(self.mk('OA'))) + self.assertEqual(0, self.mk('IA') in d) + self.assertEqual(0, self.mk('OA') in d) self.assertEqual(len(d), l-2) values = [] - for key in d.keys(): + for key in list(d.keys()): value = d[key] values.append(value) if verbose: print("%s: %s" % (key, value)) self.checkrec(key, value) - dbvalues = sorted(d.values(), key=lambda x: (str(type(x)), x)) - self.assertEqual(len(dbvalues), len(d.keys())) - values.sort(key=lambda x: (str(type(x)), x)) - self.assertEqual(values, dbvalues, "%r != %r" % (values, dbvalues)) + dbvalues = list(d.values()) + self.assertEqual(len(dbvalues), len(list(d.keys()))) + import sys + if sys.version_info[0] < 3 : + values.sort() + dbvalues.sort() + self.assertEqual(values, dbvalues) + else : # XXX: Convert all to strings. Please, improve + values.sort(key=lambda x : str(x)) + dbvalues.sort(key=lambda x : str(x)) + self.assertEqual(repr(values), repr(dbvalues)) - items = d.items() + items = list(d.items()) self.assertEqual(len(items), len(values)) for key, value in items: @@ -138,16 +135,16 @@ self.assertEqual(d.get(self.mk('bad key')), None) self.assertEqual(d.get(self.mk('bad key'), None), None) - self.assertEqual(d.get(self.mk('bad key'), b'a string'), b'a string') + self.assertEqual(d.get(self.mk('bad key'), 'a string'), 'a string') self.assertEqual(d.get(self.mk('bad key'), [1, 2, 3]), [1, 2, 3]) d.set_get_returns_none(0) self.assertRaises(db.DBNotFoundError, d.get, self.mk('bad key')) d.set_get_returns_none(1) - d.put(self.mk('new key'), b'new data') - self.assertEqual(d.get(self.mk('new key')), b'new data') - self.assertEqual(d[self.mk('new key')], b'new data') + d.put(self.mk('new key'), 'new data') + self.assertEqual(d.get(self.mk('new key')), 'new data') + self.assertEqual(d[self.mk('new key')], 'new data') @@ -165,10 +162,11 @@ while rec is not None: count = count + 1 if verbose: - print(repr(rec)) + print(rec) key, value = rec self.checkrec(key, value) - rec = c.next() + # Hack to avoid conversion by 2to3 tool + rec = getattr(c, "next")() del c self.assertEqual(count, len(d)) @@ -191,6 +189,7 @@ self.checkrec(key, value) del c + def test03_append(self): # NOTE: this is overridden in RECNO subclass, don't change its name. if verbose: @@ -198,31 +197,44 @@ print("Running %s.test03_append..." % self.__class__.__name__) self.assertRaises(dbshelve.DBShelveError, - self.d.append, b'unit test was here') + self.d.append, 'unit test was here') def checkrec(self, key, value): # override this in a subclass if the key type is different - x = key[1:] - if key[0:1] == b'S': - self.assertEquals(type(value), str) - self.assertEquals(value, 10 * x.decode("ascii")) - - elif key[0:1] == b'I': - self.assertEquals(type(value), int) - self.assertEquals(value, ord(x)) - - elif key[0:1] == b'L': - self.assertEquals(type(value), list) - self.assertEquals(value, [x.decode("ascii")] * 10) - - elif key[0:1] == b'O': - self.assertEquals(value.S, 10 * x.decode("ascii")) - self.assertEquals(value.I, ord(x)) - self.assertEquals(value.L, [x.decode("ascii")] * 10) + + import sys + if sys.version_info[0] >= 3 : + if isinstance(key, bytes) : + key = key.decode("iso8859-1") # 8 bits + + x = key[1] + if key[0] == 'S': + self.assertEqual(type(value), str) + self.assertEqual(value, 10 * x) + + elif key[0] == 'I': + self.assertEqual(type(value), int) + self.assertEqual(value, ord(x)) + + elif key[0] == 'L': + self.assertEqual(type(value), list) + self.assertEqual(value, [x] * 10) + + elif key[0] == 'O': + import sys + if sys.version_info[0] < 3 : + from types import InstanceType + self.assertEqual(type(value), InstanceType) + else : + self.assertEqual(type(value), DataClass) + + self.assertEqual(value.S, 10 * x) + self.assertEqual(value.I, ord(x)) + self.assertEqual(value.L, [x] * 10) else: - self.fail('Unknown key type, fix the test') + self.assert_(0, 'Unknown key type, fix the test') #---------------------------------------------------------------------- @@ -258,19 +270,12 @@ #---------------------------------------------------------------------- class BasicEnvShelveTestCase(DBShelveTestCase): - def setUp(self): - self.homeDir = tempfile.mkdtemp() - self.filename = 'dbshelve_db_file.db' - self.do_open() - def do_open(self): - self.homeDir = homeDir = os.path.join( - tempfile.gettempdir(), 'db_home%d'%os.getpid()) - try: os.mkdir(homeDir) - except os.error: pass self.env = db.DBEnv() - self.env.open(self.homeDir, self.envflags | db.DB_INIT_MPOOL | db.DB_CREATE) + self.env.open(self.homeDir, + self.envflags | db.DB_INIT_MPOOL | db.DB_CREATE) + self.filename = os.path.split(self.filename)[1] self.d = dbshelve.DBShelf(self.env) self.d.open(self.filename, self.dbtype, self.dbflags) @@ -280,7 +285,15 @@ self.env.close() + def setUp(self) : + self.homeDir = get_new_environment_path() + DBShelveTestCase.setUp(self) + def tearDown(self): + import sys + if sys.version_info[0] >= 3 : + from .test_all import do_proxy_db_py3k + do_proxy_db_py3k(self._flag_proxy_db_py3k) self.do_close() test_support.rmtree(self.homeDir) @@ -327,7 +340,7 @@ def mk(self, key): if key not in self.key_map: self.key_map[key] = self.key_pool.pop(0) - self.intkey_map[self.key_map[key]] = key.encode('ascii') + self.intkey_map[self.key_map[key]] = key return self.key_map[key] def checkrec(self, intkey, value): @@ -339,14 +352,14 @@ print('\n', '-=' * 30) print("Running %s.test03_append..." % self.__class__.__name__) - self.d[1] = b'spam' - self.d[5] = b'eggs' - self.assertEqual(6, self.d.append(b'spam')) - self.assertEqual(7, self.d.append(b'baked beans')) - self.assertEqual(b'spam', self.d.get(6)) - self.assertEqual(b'spam', self.d.get(1)) - self.assertEqual(b'baked beans', self.d.get(7)) - self.assertEqual(b'eggs', self.d.get(5)) + self.d[1] = 'spam' + self.d[5] = 'eggs' + self.assertEqual(6, self.d.append('spam')) + self.assertEqual(7, self.d.append('baked beans')) + self.assertEqual('spam', self.d.get(6)) + self.assertEqual('spam', self.d.get(1)) + self.assertEqual('baked beans', self.d.get(7)) + self.assertEqual('eggs', self.d.get(5)) #---------------------------------------------------------------------- Modified: python/branches/py3k/Lib/bsddb/test/test_dbtables.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_dbtables.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_dbtables.py Sun Aug 31 16:12:11 2008 @@ -20,25 +20,16 @@ # # $Id$ -import sys, os, re -import pickle -import tempfile - -import unittest -from bsddb.test.test_all import verbose - -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db, dbtables -except ImportError: - # For Python 2.3 - from bsddb import db, dbtables - +import os, re try: - from bsddb3 import test_support + import pickle + pickle = pickle except ImportError: - from test import support as test_support + import pickle +import unittest +from .test_all import db, dbtables, test_support, verbose, \ + get_new_environment_path, get_new_database_path #---------------------------------------------------------------------- @@ -46,16 +37,21 @@ db_name = 'test-table.db' def setUp(self): - homeDir = tempfile.mkdtemp() - self.testHomeDir = homeDir - try: os.mkdir(homeDir) - except os.error: pass + import sys + if sys.version_info[0] >= 3 : + from .test_all import do_proxy_db_py3k + self._flag_proxy_db_py3k = do_proxy_db_py3k(False) + self.testHomeDir = get_new_environment_path() self.tdb = dbtables.bsdTableDB( - filename='tabletest.db', dbhome=homeDir, create=1) + filename='tabletest.db', dbhome=self.testHomeDir, create=1) def tearDown(self): self.tdb.close() + import sys + if sys.version_info[0] >= 3 : + from .test_all import do_proxy_db_py3k + do_proxy_db_py3k(self._flag_proxy_db_py3k) test_support.rmtree(self.testHomeDir) def test01(self): @@ -66,21 +62,26 @@ except dbtables.TableDBError: pass self.tdb.CreateTable(tabname, [colname]) - try: + import sys + if sys.version_info[0] < 3 : self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, 1)}) - except Exception: - import traceback - traceback.print_exc() + else : + self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, + 1).decode("iso8859-1")}) # 8 bits if verbose: self.tdb._db_print() values = self.tdb.Select( tabname, [colname], conditions={colname: None}) - values = list(values) - colval = pickle.loads(values[0][colname]) - self.assertTrue(colval > 3.141 and colval < 3.142) + import sys + if sys.version_info[0] < 3 : + colval = pickle.loads(values[0][colname]) + else : + colval = pickle.loads(bytes(values[0][colname], "iso8859-1")) + self.assert_(colval > 3.141) + self.assert_(colval < 3.142) def test02(self): @@ -88,11 +89,23 @@ col0 = 'coolness factor' col1 = 'but can it fly?' col2 = 'Species' - testinfo = [ - {col0: pickle.dumps(8, 1), col1: b'no', col2: b'Penguin'}, - {col0: pickle.dumps(-1, 1), col1: b'no', col2: b'Turkey'}, - {col0: pickle.dumps(9, 1), col1: b'yes', col2: b'SR-71A Blackbird'} - ] + + import sys + if sys.version_info[0] < 3 : + testinfo = [ + {col0: pickle.dumps(8, 1), col1: 'no', col2: 'Penguin'}, + {col0: pickle.dumps(-1, 1), col1: 'no', col2: 'Turkey'}, + {col0: pickle.dumps(9, 1), col1: 'yes', col2: 'SR-71A Blackbird'} + ] + else : + testinfo = [ + {col0: pickle.dumps(8, 1).decode("iso8859-1"), + col1: 'no', col2: 'Penguin'}, + {col0: pickle.dumps(-1, 1).decode("iso8859-1"), + col1: 'no', col2: 'Turkey'}, + {col0: pickle.dumps(9, 1).decode("iso8859-1"), + col1: 'yes', col2: 'SR-71A Blackbird'} + ] try: self.tdb.Drop(tabname) @@ -102,19 +115,24 @@ for row in testinfo : self.tdb.Insert(tabname, row) - values = self.tdb.Select(tabname, [col2], - conditions={col0: lambda x: pickle.loads(x) >= 8}) - values = list(values) - - self.assertEquals(len(values), 2) - if values[0]['Species'] == b'Penguin' : - self.assertEquals(values[1]['Species'], b'SR-71A Blackbird') - elif values[0]['Species'] == b'SR-71A Blackbird' : - self.assertEquals(values[1]['Species'], b'Penguin') + import sys + if sys.version_info[0] < 3 : + values = self.tdb.Select(tabname, [col2], + conditions={col0: lambda x: pickle.loads(x) >= 8}) + else : + values = self.tdb.Select(tabname, [col2], + conditions={col0: lambda x: + pickle.loads(bytes(x, "iso8859-1")) >= 8}) + + self.assertEqual(len(values), 2) + if values[0]['Species'] == 'Penguin' : + self.assertEqual(values[1]['Species'], 'SR-71A Blackbird') + elif values[0]['Species'] == 'SR-71A Blackbird' : + self.assertEqual(values[1]['Species'], 'Penguin') else : if verbose: print("values= %r" % (values,)) - self.fail("Wrong values returned!") + raise RuntimeError("Wrong values returned!") def test03(self): tabname = "test03" @@ -140,57 +158,55 @@ {'a': "", 'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1), 'f': "Zero"}) - self.fail("exception not raised") + self.fail('Expected an exception') except dbtables.TableDBError: pass try: self.tdb.Select(tabname, [], conditions={'foo': '123'}) - self.fail("exception not raised") + self.fail('Expected an exception') except dbtables.TableDBError: pass self.tdb.Insert(tabname, - {'a': b'42', - 'b': b'bad', - 'c': b'meep', - 'e': b'Fuzzy wuzzy was a bear'}) + {'a': '42', + 'b': "bad", + 'c': "meep", + 'e': 'Fuzzy wuzzy was a bear'}) self.tdb.Insert(tabname, - {'a': b'581750', - 'b': b'good', - 'd': b'bla', - 'c': b'black', - 'e': b'fuzzy was here'}) + {'a': '581750', + 'b': "good", + 'd': "bla", + 'c': "black", + 'e': 'fuzzy was here'}) self.tdb.Insert(tabname, - {'a': b'800000', - 'b': b'good', - 'd': b'bla', - 'c': b'black', - 'e': b'Fuzzy wuzzy is a bear'}) + {'a': '800000', + 'b': "good", + 'd': "bla", + 'c': "black", + 'e': 'Fuzzy wuzzy is a bear'}) if verbose: self.tdb._db_print() # this should return two rows values = self.tdb.Select(tabname, ['b', 'a', 'd'], - conditions={'e': re.compile(b'wuzzy').search, - 'a': re.compile(b'^[0-9]+$').match}) - self.assertEquals(len(values), 2) + conditions={'e': re.compile('wuzzy').search, + 'a': re.compile('^[0-9]+$').match}) + self.assertEqual(len(values), 2) # now lets delete one of them and try again self.tdb.Delete(tabname, conditions={'b': dbtables.ExactCond('good')}) values = self.tdb.Select( tabname, ['a', 'd', 'b'], conditions={'e': dbtables.PrefixCond('Fuzzy')}) - values = list(values) - self.assertEquals(len(values), 1) - self.assertEquals(values[0]['d'], None) + self.assertEqual(len(values), 1) + self.assertEqual(values[0]['d'], None) values = self.tdb.Select(tabname, ['b'], - conditions={'c': lambda c: c.decode("ascii") == 'meep'}) - values = list(values) - self.assertEquals(len(values), 1) - self.assertEquals(values[0]['b'], b"bad") + conditions={'c': lambda c: c == 'meep'}) + self.assertEqual(len(values), 1) + self.assertEqual(values[0]['b'], "bad") def test04_MultiCondSelect(self): @@ -203,19 +219,19 @@ try: self.tdb.Insert(tabname, - {'a': b"", + {'a': "", 'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1), - 'f': b"Zero"}) - self.fail("exception not raised") + 'f': "Zero"}) + self.fail('Expected an exception') except dbtables.TableDBError: pass - self.tdb.Insert(tabname, {'a': b"A", 'b': b"B", 'c': b"C", - 'd': b"D", 'e': b"E"}) - self.tdb.Insert(tabname, {'a': b"-A", 'b': b"-B", 'c': b"-C", - 'd': b"-D", 'e': b"-E"}) - self.tdb.Insert(tabname, {'a': b"A-", 'b': b"B-", 'c': b"C-", - 'd': b"D-", 'e': b"E-"}) + self.tdb.Insert(tabname, {'a': "A", 'b': "B", 'c': "C", 'd': "D", + 'e': "E"}) + self.tdb.Insert(tabname, {'a': "-A", 'b': "-B", 'c': "-C", 'd': "-D", + 'e': "-E"}) + self.tdb.Insert(tabname, {'a': "A-", 'b': "B-", 'c': "C-", 'd': "D-", + 'e': "E-"}) if verbose: self.tdb._db_print() @@ -230,7 +246,7 @@ 'a': dbtables.ExactCond('A'), 'd': dbtables.PrefixCond('-') } ) - self.assertEquals(len(values), 0, values) + self.assertEqual(len(values), 0, values) def test_CreateOrExtend(self): @@ -240,9 +256,9 @@ tabname, ['name', 'taste', 'filling', 'alcohol content', 'price']) try: self.tdb.Insert(tabname, - {'taste': b'crap', - 'filling': b'no', - 'is it Guinness?': b'no'}) + {'taste': 'crap', + 'filling': 'no', + 'is it Guinness?': 'no'}) self.fail("Insert should've failed due to bad column name") except: pass @@ -250,11 +266,11 @@ ['name', 'taste', 'is it Guinness?']) # these should both succeed as the table should contain the union of both sets of columns. - self.tdb.Insert(tabname, {'taste': b'crap', 'filling': b'no', - 'is it Guinness?': b'no'}) - self.tdb.Insert(tabname, {'taste': b'great', 'filling': b'yes', - 'is it Guinness?': b'yes', - 'name': b'Guinness'}) + self.tdb.Insert(tabname, {'taste': 'crap', 'filling': 'no', + 'is it Guinness?': 'no'}) + self.tdb.Insert(tabname, {'taste': 'great', 'filling': 'yes', + 'is it Guinness?': 'yes', + 'name': 'Guinness'}) def test_CondObjs(self): @@ -262,33 +278,31 @@ self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e', 'p']) - self.tdb.Insert(tabname, {'a': b"the letter A", - 'b': b"the letter B", - 'c': b"is for cookie"}) - self.tdb.Insert(tabname, {'a': b"is for aardvark", - 'e': b"the letter E", - 'c': b"is for cookie", - 'd': b"is for dog"}) - self.tdb.Insert(tabname, {'a': b"the letter A", - 'e': b"the letter E", - 'c': b"is for cookie", - 'p': b"is for Python"}) + self.tdb.Insert(tabname, {'a': "the letter A", + 'b': "the letter B", + 'c': "is for cookie"}) + self.tdb.Insert(tabname, {'a': "is for aardvark", + 'e': "the letter E", + 'c': "is for cookie", + 'd': "is for dog"}) + self.tdb.Insert(tabname, {'a': "the letter A", + 'e': "the letter E", + 'c': "is for cookie", + 'p': "is for Python"}) values = self.tdb.Select( tabname, ['p', 'e'], conditions={'e': dbtables.PrefixCond('the l')}) - values = list(values) - self.assertEquals(len(values), 2) - self.assertEquals(values[0]['e'], values[1]['e']) - self.assertNotEquals(values[0]['p'], values[1]['p']) + self.assertEqual(len(values), 2, values) + self.assertEqual(values[0]['e'], values[1]['e'], values) + self.assertNotEqual(values[0]['p'], values[1]['p'], values) values = self.tdb.Select( tabname, ['d', 'a'], conditions={'a': dbtables.LikeCond('%aardvark%')}) - values = list(values) - self.assertEquals(len(values), 1) - self.assertEquals(values[0]['d'], b"is for dog") - self.assertEquals(values[0]['a'], b"is for aardvark") + self.assertEqual(len(values), 1, values) + self.assertEqual(values[0]['d'], "is for dog", values) + self.assertEqual(values[0]['a'], "is for aardvark", values) values = self.tdb.Select(tabname, None, {'b': dbtables.Cond(), @@ -297,10 +311,9 @@ 'd':dbtables.ExactCond('is for dog'), 'c':dbtables.PrefixCond('is for'), 'p':lambda s: not s}) - values = list(values) - self.assertEquals(len(values), 1) - self.assertEquals(values[0]['d'], b"is for dog") - self.assertEquals(values[0]['a'], b"is for aardvark") + self.assertEqual(len(values), 1, values) + self.assertEqual(values[0]['d'], "is for dog", values) + self.assertEqual(values[0]['a'], "is for aardvark", values) def test_Delete(self): tabname = "test_Delete" @@ -310,30 +323,30 @@ # fail if it encountered any rows that did not have values in # every column. # Hunted and Squashed by (Jukka Santala - donwulff at nic.fi) - self.tdb.Insert(tabname, {'x': b'X1', 'y':b'Y1'}) - self.tdb.Insert(tabname, {'x': b'X2', 'y':b'Y2', 'z': b'Z2'}) + self.tdb.Insert(tabname, {'x': 'X1', 'y':'Y1'}) + self.tdb.Insert(tabname, {'x': 'X2', 'y':'Y2', 'z': 'Z2'}) self.tdb.Delete(tabname, conditions={'x': dbtables.PrefixCond('X')}) values = self.tdb.Select(tabname, ['y'], conditions={'x': dbtables.PrefixCond('X')}) - self.assertEquals(len(values), 0) + self.assertEqual(len(values), 0) def test_Modify(self): tabname = "test_Modify" self.tdb.CreateTable(tabname, ['Name', 'Type', 'Access']) - self.tdb.Insert(tabname, {'Name': b'Index to MP3 files.doc', - 'Type': b'Word', 'Access': b'8'}) - self.tdb.Insert(tabname, {'Name': b'Nifty.MP3', 'Access': b'1'}) - self.tdb.Insert(tabname, {'Type': b'Unknown', 'Access': b'0'}) + self.tdb.Insert(tabname, {'Name': 'Index to MP3 files.doc', + 'Type': 'Word', 'Access': '8'}) + self.tdb.Insert(tabname, {'Name': 'Nifty.MP3', 'Access': '1'}) + self.tdb.Insert(tabname, {'Type': 'Unknown', 'Access': '0'}) def set_type(type): - if type is None: - return b'MP3' + if type == None: + return 'MP3' return type def increment_access(count): - return str(int(count)+1).encode('ascii') + return str(int(count)+1) def remove_value(value): return None @@ -351,7 +364,7 @@ try: self.tdb.Modify(tabname, conditions={'Name': dbtables.LikeCond('%')}, - mappings={'Access': b'What is your quest?'}) + mappings={'Access': 'What is your quest?'}) except TypeError: # success, the string value in mappings isn't callable pass @@ -362,27 +375,24 @@ values = self.tdb.Select( tabname, None, conditions={'Type': dbtables.ExactCond('Unknown')}) - values = list(values) - self.assertEquals(len(values), 1) - self.assertEquals(values[0]['Name'], None) - self.assertEquals(values[0]['Access'], None) + self.assertEqual(len(values), 1, values) + self.assertEqual(values[0]['Name'], None, values) + self.assertEqual(values[0]['Access'], None, values) # Modify value by select conditions values = self.tdb.Select( tabname, None, conditions={'Name': dbtables.ExactCond('Nifty.MP3')}) - values = list(values) - self.assertEquals(len(values), 1) - self.assertEquals(values[0]['Type'], b"MP3") - self.assertEquals(values[0]['Access'], b"2") + self.assertEqual(len(values), 1, values) + self.assertEqual(values[0]['Type'], "MP3", values) + self.assertEqual(values[0]['Access'], "2", values) # Make sure change applied only to select conditions values = self.tdb.Select( tabname, None, conditions={'Name': dbtables.LikeCond('%doc%')}) - values = list(values) - self.assertEquals(len(values), 1) - self.assertEquals(values[0]['Type'], b"Word") - self.assertEquals(values[0]['Access'], b"9") + self.assertEqual(len(values), 1, values) + self.assertEqual(values[0]['Type'], "Word", values) + self.assertEqual(values[0]['Access'], "9", values) def test_suite(): Added: python/branches/py3k/Lib/bsddb/test/test_distributed_transactions.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/bsddb/test/test_distributed_transactions.py Sun Aug 31 16:12:11 2008 @@ -0,0 +1,163 @@ +"""TestCases for distributed transactions. +""" + +import os +import unittest + +from .test_all import db, test_support, get_new_environment_path, \ + get_new_database_path + +try : + a=set() +except : # Python 2.3 + from sets import Set as set +else : + del a + +from .test_all import verbose + +#---------------------------------------------------------------------- + +class DBTxn_distributed(unittest.TestCase): + num_txns=1234 + nosync=True + must_open_db=False + def _create_env(self, must_open_db) : + self.dbenv = db.DBEnv() + self.dbenv.set_tx_max(self.num_txns) + self.dbenv.set_lk_max_lockers(self.num_txns*2) + self.dbenv.set_lk_max_locks(self.num_txns*2) + self.dbenv.set_lk_max_objects(self.num_txns*2) + if self.nosync : + self.dbenv.set_flags(db.DB_TXN_NOSYNC,True) + self.dbenv.open(self.homeDir, db.DB_CREATE | db.DB_THREAD | + db.DB_RECOVER | + db.DB_INIT_TXN | db.DB_INIT_LOG | db.DB_INIT_MPOOL | + db.DB_INIT_LOCK, 0o666) + self.db = db.DB(self.dbenv) + self.db.set_re_len(db.DB_XIDDATASIZE) + if must_open_db : + if db.version() > (4,1) : + txn=self.dbenv.txn_begin() + self.db.open(self.filename, + db.DB_QUEUE, db.DB_CREATE | db.DB_THREAD, 0o666, + txn=txn) + txn.commit() + else : + self.db.open(self.filename, + db.DB_QUEUE, db.DB_CREATE | db.DB_THREAD, 0o666) + + def setUp(self) : + self.homeDir = get_new_environment_path() + self.filename = "test" + return self._create_env(must_open_db=True) + + def _destroy_env(self): + if self.nosync or (db.version()[:2] == (4,6)): # Known bug + self.dbenv.log_flush() + self.db.close() + self.dbenv.close() + + def tearDown(self): + self._destroy_env() + test_support.rmtree(self.homeDir) + + def _recreate_env(self,must_open_db) : + self._destroy_env() + self._create_env(must_open_db) + + def test01_distributed_transactions(self) : + txns=set() + adapt = lambda x : x + import sys + if sys.version_info[0] >= 3 : + adapt = lambda x : bytes(x, "ascii") + # Create transactions, "prepare" them, and + # let them be garbage collected. + for i in range(self.num_txns) : + txn = self.dbenv.txn_begin() + gid = "%%%dd" %db.DB_XIDDATASIZE + gid = adapt(gid %i) + self.db.put(i, gid, txn=txn, flags=db.DB_APPEND) + txns.add(gid) + txn.prepare(gid) + del txn + + self._recreate_env(self.must_open_db) + + # Get "to be recovered" transactions but + # let them be garbage collected. + recovered_txns=self.dbenv.txn_recover() + self.assertEquals(self.num_txns,len(recovered_txns)) + for gid,txn in recovered_txns : + self.assert_(gid in txns) + del txn + del recovered_txns + + self._recreate_env(self.must_open_db) + + # Get "to be recovered" transactions. Commit, abort and + # discard them. + recovered_txns=self.dbenv.txn_recover() + self.assertEquals(self.num_txns,len(recovered_txns)) + discard_txns=set() + committed_txns=set() + state=0 + for gid,txn in recovered_txns : + if state==0 or state==1: + committed_txns.add(gid) + txn.commit() + elif state==2 : + txn.abort() + elif state==3 : + txn.discard() + discard_txns.add(gid) + state=-1 + state+=1 + del txn + del recovered_txns + + self._recreate_env(self.must_open_db) + + # Verify the discarded transactions are still + # around, and dispose them. + recovered_txns=self.dbenv.txn_recover() + self.assertEquals(len(discard_txns),len(recovered_txns)) + for gid,txn in recovered_txns : + txn.abort() + del txn + del recovered_txns + + self._recreate_env(must_open_db=True) + + # Be sure there are not pending transactions. + # Check also database size. + recovered_txns=self.dbenv.txn_recover() + self.assert_(len(recovered_txns)==0) + self.assertEquals(len(committed_txns),self.db.stat()["nkeys"]) + +class DBTxn_distributedSYNC(DBTxn_distributed): + nosync=False + +class DBTxn_distributed_must_open_db(DBTxn_distributed): + must_open_db=True + +class DBTxn_distributedSYNC_must_open_db(DBTxn_distributed): + nosync=False + must_open_db=True + +#---------------------------------------------------------------------- + +def test_suite(): + suite = unittest.TestSuite() + if db.version() >= (4,5) : + suite.addTest(unittest.makeSuite(DBTxn_distributed)) + suite.addTest(unittest.makeSuite(DBTxn_distributedSYNC)) + if db.version() >= (4,6) : + suite.addTest(unittest.makeSuite(DBTxn_distributed_must_open_db)) + suite.addTest(unittest.makeSuite(DBTxn_distributedSYNC_must_open_db)) + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') Added: python/branches/py3k/Lib/bsddb/test/test_early_close.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/bsddb/test/test_early_close.py Sun Aug 31 16:12:11 2008 @@ -0,0 +1,195 @@ +"""TestCases for checking that it does not segfault when a DBEnv object +is closed before its DB objects. +""" + +import os +import unittest + +from .test_all import db, test_support, verbose, get_new_environment_path, get_new_database_path + +# We're going to get warnings in this module about trying to close the db when +# its env is already closed. Let's just ignore those. +try: + import warnings +except ImportError: + pass +else: + warnings.filterwarnings('ignore', + message='DB could not be closed in', + category=RuntimeWarning) + + +#---------------------------------------------------------------------- + +class DBEnvClosedEarlyCrash(unittest.TestCase): + def setUp(self): + self.homeDir = get_new_environment_path() + self.filename = "test" + + def tearDown(self): + test_support.rmtree(self.homeDir) + + def test01_close_dbenv_before_db(self): + dbenv = db.DBEnv() + dbenv.open(self.homeDir, + db.DB_INIT_CDB| db.DB_CREATE |db.DB_THREAD|db.DB_INIT_MPOOL, + 0o666) + + d = db.DB(dbenv) + d2 = db.DB(dbenv) + d.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0o666) + + self.assertRaises(db.DBNoSuchFileError, d2.open, + self.filename+"2", db.DB_BTREE, db.DB_THREAD, 0o666) + + d.put("test","this is a test") + self.assertEqual(d.get("test"), "this is a test", "put!=get") + dbenv.close() # This "close" should close the child db handle also + self.assertRaises(db.DBError, d.get, "test") + + def test02_close_dbenv_before_dbcursor(self): + dbenv = db.DBEnv() + dbenv.open(self.homeDir, + db.DB_INIT_CDB| db.DB_CREATE |db.DB_THREAD|db.DB_INIT_MPOOL, + 0o666) + + d = db.DB(dbenv) + d.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0o666) + + d.put("test","this is a test") + d.put("test2","another test") + d.put("test3","another one") + self.assertEqual(d.get("test"), "this is a test", "put!=get") + c=d.cursor() + c.first() + next(c) + d.close() # This "close" should close the child db handle also + # db.close should close the child cursor + self.assertRaises(db.DBError,c.__next__) + + d = db.DB(dbenv) + d.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0o666) + c=d.cursor() + c.first() + next(c) + dbenv.close() + # The "close" should close the child db handle also, with cursors + self.assertRaises(db.DBError, c.__next__) + + def test03_close_db_before_dbcursor_without_env(self): + import os.path + path=os.path.join(self.homeDir,self.filename) + d = db.DB() + d.open(path, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0o666) + + d.put("test","this is a test") + d.put("test2","another test") + d.put("test3","another one") + self.assertEqual(d.get("test"), "this is a test", "put!=get") + c=d.cursor() + c.first() + next(c) + d.close() + # The "close" should close the child db handle also + self.assertRaises(db.DBError, c.__next__) + + def test04_close_massive(self): + dbenv = db.DBEnv() + dbenv.open(self.homeDir, + db.DB_INIT_CDB| db.DB_CREATE |db.DB_THREAD|db.DB_INIT_MPOOL, + 0o666) + + dbs=[db.DB(dbenv) for i in range(16)] + cursors=[] + for i in dbs : + i.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0o666) + + dbs[10].put("test","this is a test") + dbs[10].put("test2","another test") + dbs[10].put("test3","another one") + self.assertEqual(dbs[4].get("test"), "this is a test", "put!=get") + + for i in dbs : + cursors.extend([i.cursor() for j in range(32)]) + + for i in dbs[::3] : + i.close() + for i in cursors[::3] : + i.close() + + # Check for missing exception in DB! (after DB close) + self.assertRaises(db.DBError, dbs[9].get, "test") + + # Check for missing exception in DBCursor! (after DB close) + self.assertRaises(db.DBError, cursors[101].first) + + cursors[80].first() + next(cursors[80]) + dbenv.close() # This "close" should close the child db handle also + # Check for missing exception! (after DBEnv close) + self.assertRaises(db.DBError, cursors[80].__next__) + + def test05_close_dbenv_delete_db_success(self): + dbenv = db.DBEnv() + dbenv.open(self.homeDir, + db.DB_INIT_CDB| db.DB_CREATE |db.DB_THREAD|db.DB_INIT_MPOOL, + 0o666) + + d = db.DB(dbenv) + d.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0o666) + + dbenv.close() # This "close" should close the child db handle also + + del d + try: + import gc + except ImportError: + gc = None + if gc: + # force d.__del__ [DB_dealloc] to be called + gc.collect() + + def test06_close_txn_before_dup_cursor(self) : + dbenv = db.DBEnv() + dbenv.open(self.homeDir,db.DB_INIT_TXN | db.DB_INIT_MPOOL | + db.DB_INIT_LOG | db.DB_CREATE) + d = db.DB(dbenv) + txn = dbenv.txn_begin() + if db.version() < (4,1) : + d.open(self.filename, dbtype = db.DB_HASH, flags = db.DB_CREATE) + else : + d.open(self.filename, dbtype = db.DB_HASH, flags = db.DB_CREATE, + txn=txn) + d.put("XXX", "yyy", txn=txn) + txn.commit() + txn = dbenv.txn_begin() + c1 = d.cursor(txn) + c2 = c1.dup() + self.assertEquals(("XXX", "yyy"), c1.first()) + import warnings + # Not interested in warnings about implicit close. + warnings.simplefilter("ignore") + txn.commit() + warnings.resetwarnings() + self.assertRaises(db.DBCursorClosedError, c2.first) + + if db.version() > (4,3,0) : + def test07_close_db_before_sequence(self): + import os.path + path=os.path.join(self.homeDir,self.filename) + d = db.DB() + d.open(path, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0o666) + dbs=db.DBSequence(d) + d.close() # This "close" should close the child DBSequence also + dbs.close() # If not closed, core dump (in Berkeley DB 4.6.*) + +#---------------------------------------------------------------------- + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(DBEnvClosedEarlyCrash)) + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') Modified: python/branches/py3k/Lib/bsddb/test/test_get_none.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_get_none.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_get_none.py Sun Aug 31 16:12:11 2008 @@ -2,22 +2,17 @@ TestCases for checking set_get_returns_none. """ -import sys, os, string -import tempfile -from pprint import pprint +import os, string import unittest -from bsddb import db +from .test_all import db, verbose, get_new_database_path -from bsddb.test.test_all import verbose - -letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' #---------------------------------------------------------------------- class GetReturnsNoneTestCase(unittest.TestCase): def setUp(self): - self.filename = tempfile.mktemp() + self.filename = get_new_database_path() def tearDown(self): try: @@ -31,25 +26,24 @@ d.open(self.filename, db.DB_BTREE, db.DB_CREATE) d.set_get_returns_none(1) - for x in letters: - x = x.encode("ascii") + for x in string.letters: d.put(x, x * 40) - data = d.get(b'bad key') - assert data == None + data = d.get('bad key') + self.assertEqual(data, None) - data = d.get(b'a') - assert data == b'a'*40 + data = d.get(string.letters[0]) + self.assertEqual(data, string.letters[0]*40) count = 0 c = d.cursor() rec = c.first() while rec: count = count + 1 - rec = c.next() + rec = next(c) - assert rec == None - assert count == 52 + self.assertEqual(rec, None) + self.assertEqual(count, len(string.letters)) c.close() d.close() @@ -60,15 +54,14 @@ d.open(self.filename, db.DB_BTREE, db.DB_CREATE) d.set_get_returns_none(0) - for x in letters: - x = x.encode("ascii") + for x in string.letters: d.put(x, x * 40) - self.assertRaises(db.DBNotFoundError, d.get, b'bad key') - self.assertRaises(KeyError, d.get, b'bad key') + self.assertRaises(db.DBNotFoundError, d.get, 'bad key') + self.assertRaises(KeyError, d.get, 'bad key') - data = d.get(b'a') - assert data == b'a'*40 + data = d.get(string.letters[0]) + self.assertEqual(data, string.letters[0]*40) count = 0 exceptionHappened = 0 @@ -77,14 +70,14 @@ while rec: count = count + 1 try: - rec = c.next() + rec = next(c) except db.DBNotFoundError: # end of the records exceptionHappened = 1 break - assert rec != None - assert exceptionHappened - assert count == 52 + self.assertNotEqual(rec, None) + self.assert_(exceptionHappened) + self.assertEqual(count, len(string.letters)) c.close() d.close() Modified: python/branches/py3k/Lib/bsddb/test/test_join.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_join.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_join.py Sun Aug 31 16:12:11 2008 @@ -1,27 +1,12 @@ """TestCases for using the DB.join and DBCursor.join_item methods. """ -import shutil -import sys, os -import tempfile -import time -from pprint import pprint - -try: - from threading import Thread, current_thread - have_threads = 1 -except ImportError: - have_threads = 0 +import os import unittest -from bsddb.test.test_all import verbose -from bsddb import db, dbshelve, StringKeys - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +from .test_all import db, dbshelve, test_support, verbose, \ + get_new_environment_path, get_new_database_path #---------------------------------------------------------------------- @@ -44,18 +29,12 @@ ('black', "shotgun"), ] -def ASCII(s): - return s.encode("ascii") - class JoinTestCase(unittest.TestCase): keytype = '' def setUp(self): self.filename = self.__class__.__name__ + '.db' - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - try: os.mkdir(homeDir) - except os.error: pass + self.homeDir = get_new_environment_path() self.env = db.DBEnv() self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL | db.DB_INIT_LOCK ) @@ -72,13 +51,13 @@ # create and populate primary index priDB = db.DB(self.env) priDB.open(self.filename, "primary", db.DB_BTREE, db.DB_CREATE) - [priDB.put(ASCII(k),ASCII(v)) for k,v in ProductIndex] + list(map(lambda t, priDB=priDB: priDB.put(*t), ProductIndex)) # create and populate secondary index secDB = db.DB(self.env) secDB.set_flags(db.DB_DUP | db.DB_DUPSORT) secDB.open(self.filename, "secondary", db.DB_BTREE, db.DB_CREATE) - [secDB.put(ASCII(k),ASCII(v)) for k,v in ColorIndex] + list(map(lambda t, secDB=secDB: secDB.put(*t), ColorIndex)) sCursor = None jCursor = None @@ -87,19 +66,19 @@ sCursor = secDB.cursor() # Don't do the .set() in an assert, or you can get a bogus failure # when running python -O - tmp = sCursor.set(b'red') - assert tmp + tmp = sCursor.set('red') + self.assert_(tmp) # FIXME: jCursor doesn't properly hold a reference to its # cursors, if they are closed before jcursor is used it # can cause a crash. jCursor = priDB.join([sCursor]) - if jCursor.get(0) != (b'apple', b"Convenience Store"): + if jCursor.get(0) != ('apple', "Convenience Store"): self.fail("join cursor positioned wrong") - if jCursor.join_item() != b'chainsaw': + if jCursor.join_item() != 'chainsaw': self.fail("DBCursor.join_item returned wrong item") - if jCursor.get(0)[0] != b'strawberry': + if jCursor.get(0)[0] != 'strawberry': self.fail("join cursor returned wrong thing") if jCursor.get(0): # there were only three red items to return self.fail("join cursor returned too many items") Modified: python/branches/py3k/Lib/bsddb/test/test_lock.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_lock.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_lock.py Sun Aug 31 16:12:11 2008 @@ -2,39 +2,31 @@ TestCases for testing the locking sub-system. """ -import sys -import tempfile import time -try: - from threading import Thread, current_thread - have_threads = 1 -except ImportError: - have_threads = 0 - - import unittest -from bsddb.test.test_all import verbose - -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db -except ImportError: - # For Python 2.3 - from bsddb import db - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +from .test_all import db, test_support, verbose, have_threads, \ + get_new_environment_path, get_new_database_path +if have_threads : + from threading import Thread + import sys + if sys.version_info[0] < 3 : + from threading import currentThread + else : + from threading import current_thread as currentThread #---------------------------------------------------------------------- class LockingTestCase(unittest.TestCase): + import sys + if sys.version_info[:3] < (2, 4, 0): + def assertTrue(self, expr, msg=None): + self.failUnless(expr,msg=msg) + def setUp(self): - self.homeDir = tempfile.mkdtemp('.test_lock') + self.homeDir = get_new_environment_path() self.env = db.DBEnv() self.env.open(self.homeDir, db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK | db.DB_CREATE) @@ -53,15 +45,13 @@ anID = self.env.lock_id() if verbose: print("locker ID: %s" % anID) - lock = self.env.lock_get(anID, b"some locked thing", db.DB_LOCK_WRITE) + lock = self.env.lock_get(anID, "some locked thing", db.DB_LOCK_WRITE) if verbose: print("Aquired lock: %s" % lock) - time.sleep(1) self.env.lock_put(lock) if verbose: print("Released lock: %s" % lock) - if db.version() >= (4,0): - self.env.lock_id_free(anID) + self.env.lock_id_free(anID) def test02_threaded(self): @@ -71,34 +61,35 @@ threads = [] threads.append(Thread(target = self.theThread, - args=(5, db.DB_LOCK_WRITE))) + args=(db.DB_LOCK_WRITE,))) threads.append(Thread(target = self.theThread, - args=(1, db.DB_LOCK_READ))) + args=(db.DB_LOCK_READ,))) threads.append(Thread(target = self.theThread, - args=(1, db.DB_LOCK_READ))) + args=(db.DB_LOCK_READ,))) threads.append(Thread(target = self.theThread, - args=(1, db.DB_LOCK_WRITE))) + args=(db.DB_LOCK_WRITE,))) threads.append(Thread(target = self.theThread, - args=(1, db.DB_LOCK_READ))) + args=(db.DB_LOCK_READ,))) threads.append(Thread(target = self.theThread, - args=(1, db.DB_LOCK_READ))) + args=(db.DB_LOCK_READ,))) threads.append(Thread(target = self.theThread, - args=(1, db.DB_LOCK_WRITE))) + args=(db.DB_LOCK_WRITE,))) threads.append(Thread(target = self.theThread, - args=(1, db.DB_LOCK_WRITE))) + args=(db.DB_LOCK_WRITE,))) threads.append(Thread(target = self.theThread, - args=(1, db.DB_LOCK_WRITE))) + args=(db.DB_LOCK_WRITE,))) for t in threads: + import sys + if sys.version_info[0] < 3 : + t.setDaemon(True) + else : + t.daemon = True t.start() for t in threads: t.join() - def _DISABLED_test03_lock_timeout(self): - # Disabled as this test crashes the python interpreter built in - # debug mode with: - # Fatal Python error: UNREF invalid object - # the error occurs as marked below. + def test03_lock_timeout(self): self.env.set_timeout(0, db.DB_SET_LOCK_TIMEOUT) self.env.set_timeout(0, db.DB_SET_TXN_TIMEOUT) self.env.set_timeout(123456, db.DB_SET_LOCK_TIMEOUT) @@ -117,7 +108,11 @@ deadlock_detection.end=False deadlock_detection.count=0 t=Thread(target=deadlock_detection) - t.daemon = True + import sys + if sys.version_info[0] < 3 : + t.setDaemon(True) + else : + t.daemon = True t.start() self.env.set_timeout(100000, db.DB_SET_LOCK_TIMEOUT) anID = self.env.lock_id() @@ -125,8 +120,6 @@ self.assertNotEqual(anID, anID2) lock = self.env.lock_get(anID, "shared lock", db.DB_LOCK_WRITE) start_time=time.time() - # FIXME: I see the UNREF crash as the interpreter trys to exit - # from this call to lock_get. self.assertRaises(db.DBLockNotGrantedError, self.env.lock_get,anID2, "shared lock", db.DB_LOCK_READ) end_time=time.time() @@ -135,15 +128,19 @@ self.env.lock_put(lock) t.join() - if db.version() >= (4,0): - self.env.lock_id_free(anID) - self.env.lock_id_free(anID2) + self.env.lock_id_free(anID) + self.env.lock_id_free(anID2) if db.version() >= (4,6): self.assertTrue(deadlock_detection.count>0) - def theThread(self, sleepTime, lockType): - name = current_thread().name + def theThread(self, lockType): + import sys + if sys.version_info[0] < 3 : + name = currentThread().getName() + else : + name = currentThread().name + if lockType == db.DB_LOCK_WRITE: lt = "write" else: @@ -153,17 +150,16 @@ if verbose: print("%s: locker ID: %s" % (name, anID)) - lock = self.env.lock_get(anID, b"some locked thing", lockType) - if verbose: - print("%s: Aquired %s lock: %s" % (name, lt, lock)) - - time.sleep(sleepTime) + for i in range(1000) : + lock = self.env.lock_get(anID, "some locked thing", lockType) + if verbose: + print("%s: Aquired %s lock: %s" % (name, lt, lock)) + + self.env.lock_put(lock) + if verbose: + print("%s: Released %s lock: %s" % (name, lt, lock)) - self.env.lock_put(lock) - if verbose: - print("%s: Released %s lock: %s" % (name, lt, lock)) - if db.version() >= (4,0): - self.env.lock_id_free(anID) + self.env.lock_id_free(anID) #---------------------------------------------------------------------- Modified: python/branches/py3k/Lib/bsddb/test/test_misc.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_misc.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_misc.py Sun Aug 31 16:12:11 2008 @@ -2,34 +2,16 @@ """ import os -import shutil -import sys import unittest -import tempfile -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db, dbshelve, hashopen -except ImportError: - # For the bundled bsddb - from bsddb import db, dbshelve, hashopen - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +from .test_all import db, dbshelve, hashopen, test_support, get_new_environment_path, get_new_database_path #---------------------------------------------------------------------- class MiscTestCase(unittest.TestCase): def setUp(self): self.filename = self.__class__.__name__ + '.db' - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - try: - os.mkdir(homeDir) - except OSError: - pass + self.homeDir = get_new_environment_path() def tearDown(self): test_support.unlink(self.filename) @@ -38,14 +20,18 @@ def test01_badpointer(self): dbs = dbshelve.open(self.filename) dbs.close() - self.assertRaises(db.DBError, dbs.get, b"foo") + self.assertRaises(db.DBError, dbs.get, "foo") def test02_db_home(self): env = db.DBEnv() # check for crash fixed when db_home is used before open() - assert env.db_home is None + self.assert_(env.db_home is None) env.open(self.homeDir, db.DB_CREATE) - assert self.homeDir == env.db_home + import sys + if sys.version_info[0] < 3 : + self.assertEqual(self.homeDir, env.db_home) + else : + self.assertEqual(bytes(self.homeDir, "ascii"), env.db_home) def test03_repr_closed_db(self): db = hashopen(self.filename) @@ -53,6 +39,18 @@ rp = repr(db) self.assertEquals(rp, "{}") + def test04_repr_db(self) : + db = hashopen(self.filename) + d = {} + for i in range(100) : + db[repr(i)] = repr(100*i) + d[repr(i)] = repr(100*i) + db.close() + db = hashopen(self.filename) + rp = repr(db) + self.assertEquals(rp, repr(d)) + db.close() + # http://sourceforge.net/tracker/index.php?func=detail&aid=1708868&group_id=13900&atid=313900 # # See the bug report for details. @@ -60,65 +58,65 @@ # The problem was that make_key_dbt() was not allocating a copy of # string keys but FREE_DBT() was always being told to free it when the # database was opened with DB_THREAD. - def test04_double_free_make_key_dbt(self): + def test05_double_free_make_key_dbt(self): try: db1 = db.DB() db1.open(self.filename, None, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD) curs = db1.cursor() - t = curs.get(b"/foo", db.DB_SET) + t = curs.get("/foo", db.DB_SET) # double free happened during exit from DBC_get finally: db1.close() - os.unlink(self.filename) + test_support.unlink(self.filename) - def test05_key_with_null_bytes(self): + def test06_key_with_null_bytes(self): try: db1 = db.DB() db1.open(self.filename, None, db.DB_HASH, db.DB_CREATE) - db1[b'a'] = b'eh?' - db1[b'a\x00'] = b'eh zed.' - db1[b'a\x00a'] = b'eh zed eh?' - db1[b'aaa'] = b'eh eh eh!' - keys = db1.keys() + db1['a'] = 'eh?' + db1['a\x00'] = 'eh zed.' + db1['a\x00a'] = 'eh zed eh?' + db1['aaa'] = 'eh eh eh!' + keys = list(db1.keys()) keys.sort() - self.assertEqual([b'a', b'a\x00', b'a\x00a', b'aaa'], keys) - self.assertEqual(db1[b'a'], b'eh?') - self.assertEqual(db1[b'a\x00'], b'eh zed.') - self.assertEqual(db1[b'a\x00a'], b'eh zed eh?') - self.assertEqual(db1[b'aaa'], b'eh eh eh!') + self.assertEqual(['a', 'a\x00', 'a\x00a', 'aaa'], keys) + self.assertEqual(db1['a'], 'eh?') + self.assertEqual(db1['a\x00'], 'eh zed.') + self.assertEqual(db1['a\x00a'], 'eh zed eh?') + self.assertEqual(db1['aaa'], 'eh eh eh!') finally: db1.close() - os.unlink(self.filename) + test_support.unlink(self.filename) - def test_DB_set_flags_persists(self): + def test07_DB_set_flags_persists(self): if db.version() < (4,2): # The get_flags API required for this to work is only available - # in BerkeleyDB >= 4.2 + # in Berkeley DB >= 4.2 return try: db1 = db.DB() db1.set_flags(db.DB_DUPSORT) db1.open(self.filename, db.DB_HASH, db.DB_CREATE) - db1[b'a'] = b'eh' - db1[b'a'] = b'A' - self.assertEqual([(b'a', b'A')], db1.items()) - db1.put(b'a', b'Aa') - self.assertEqual([(b'a', b'A'), (b'a', b'Aa')], db1.items()) + db1['a'] = 'eh' + db1['a'] = 'A' + self.assertEqual([('a', 'A')], list(db1.items())) + db1.put('a', 'Aa') + self.assertEqual([('a', 'A'), ('a', 'Aa')], list(db1.items())) db1.close() db1 = db.DB() # no set_flags call, we're testing that it reads and obeys # the flags on open. db1.open(self.filename, db.DB_HASH) - self.assertEqual([(b'a', b'A'), (b'a', b'Aa')], db1.items()) + self.assertEqual([('a', 'A'), ('a', 'Aa')], list(db1.items())) # if it read the flags right this will replace all values - # for key b'a' instead of adding a new one. (as a dict should) - db1[b'a'] = b'new A' - self.assertEqual([(b'a', b'new A')], db1.items()) + # for key 'a' instead of adding a new one. (as a dict should) + db1['a'] = 'new A' + self.assertEqual([('a', 'new A')], list(db1.items())) finally: db1.close() - os.unlink(self.filename) + test_support.unlink(self.filename) #---------------------------------------------------------------------- Modified: python/branches/py3k/Lib/bsddb/test/test_pickle.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_pickle.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_pickle.py Sun Aug 31 16:12:11 2008 @@ -1,23 +1,13 @@ -import shutil -import sys, os +import os import pickle -import tempfile -import unittest -import tempfile - -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db -except ImportError as e: - # For Python 2.3 - from bsddb import db - try: - from bsddb3 import test_support + import pickle except ImportError: - from test import support as test_support + pickle = None +import unittest +from .test_all import db, test_support, get_new_environment_path, get_new_database_path #---------------------------------------------------------------------- @@ -26,10 +16,7 @@ db_name = 'test-dbobj.db' def setUp(self): - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - try: os.mkdir(homeDir) - except os.error: pass + self.homeDir = get_new_environment_path() def tearDown(self): if hasattr(self, 'db'): @@ -43,10 +30,10 @@ self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL) self.db = db.DB(self.env) self.db.open(self.db_name, db.DB_HASH, db.DB_CREATE) - self.db.put(b'spam', b'eggs') - self.assertEqual(self.db[b'spam'], b'eggs') + self.db.put('spam', 'eggs') + self.assertEqual(self.db['spam'], 'eggs') try: - self.db.put(b'spam', b'ham', flags=db.DB_NOOVERWRITE) + self.db.put('spam', 'ham', flags=db.DB_NOOVERWRITE) except db.DBError as egg: pickledEgg = pickle.dumps(egg) #print repr(pickledEgg) @@ -54,7 +41,7 @@ if rottenEgg.args != egg.args or type(rottenEgg) != type(egg): raise Exception(rottenEgg, '!=', egg) else: - self.fail("where's my DBError exception?!?") + raise Exception("where's my DBError exception?!?") self.db.close() self.env.close() @@ -62,6 +49,10 @@ def test01_pickle_DBError(self): self._base_test_pickle_DBError(pickle=pickle) + if pickle: + def test02_cPickle_DBError(self): + self._base_test_pickle_DBError(pickle=pickle) + #---------------------------------------------------------------------- def test_suite(): Modified: python/branches/py3k/Lib/bsddb/test/test_queue.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_queue.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_queue.py Sun Aug 31 16:12:11 2008 @@ -2,27 +2,17 @@ TestCases for exercising a Queue DB. """ -import sys, os, string -import tempfile +import os, string from pprint import pprint import unittest -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db -except ImportError: - # For Python 2.3 - from bsddb import db - -from bsddb.test.test_all import verbose - -letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +from .test_all import db, verbose, get_new_database_path #---------------------------------------------------------------------- class SimpleQueueTestCase(unittest.TestCase): def setUp(self): - self.filename = tempfile.mktemp() + self.filename = get_new_database_path() def tearDown(self): try: @@ -46,17 +36,17 @@ print("before appends" + '-' * 30) pprint(d.stat()) - for x in letters: - d.append(x.encode('ascii') * 40) + for x in string.letters: + d.append(x * 40) - assert len(d) == 52 + self.assertEqual(len(d), len(string.letters)) - d.put(100, b"some more data") - d.put(101, b"and some more ") - d.put(75, b"out of order") - d.put(1, b"replacement data") + d.put(100, "some more data") + d.put(101, "and some more ") + d.put(75, "out of order") + d.put(1, "replacement data") - assert len(d) == 55 + self.assertEqual(len(d), len(string.letters)+3) if verbose: print("before close" + '-' * 30) @@ -71,7 +61,11 @@ print("after open" + '-' * 30) pprint(d.stat()) - d.append(b"one more") + # Test "txn" as a positional parameter + d.append("one more", None) + # Test "txn" as a keyword parameter + d.append("another one", txn=None) + c = d.cursor() if verbose: @@ -89,9 +83,9 @@ print("after consume loop" + '-' * 30) pprint(d.stat()) - assert len(d) == 0, \ + self.assertEqual(len(d), 0, \ "if you see this message then you need to rebuild " \ - "BerkeleyDB 3.1.17 with the patch in patches/qam_stat.diff" + "Berkeley DB 3.1.17 with the patch in patches/qam_stat.diff") d.close() @@ -118,17 +112,17 @@ print("before appends" + '-' * 30) pprint(d.stat()) - for x in letters: - d.append(x.encode('ascii') * 40) + for x in string.letters: + d.append(x * 40) - assert len(d) == 52 + self.assertEqual(len(d), len(string.letters)) - d.put(100, b"some more data") - d.put(101, b"and some more ") - d.put(75, b"out of order") - d.put(1, b"replacement data") + d.put(100, "some more data") + d.put(101, "and some more ") + d.put(75, "out of order") + d.put(1, "replacement data") - assert len(d) == 55 + self.assertEqual(len(d), len(string.letters)+3) if verbose: print("before close" + '-' * 30) @@ -144,7 +138,7 @@ print("after open" + '-' * 30) pprint(d.stat()) - d.append(b"one more") + d.append("one more") if verbose: print("after append" + '-' * 30) Modified: python/branches/py3k/Lib/bsddb/test/test_recno.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_recno.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_recno.py Sun Aug 31 16:12:11 2008 @@ -2,26 +2,11 @@ """ import os -import shutil -import sys import errno -import tempfile from pprint import pprint import unittest -from bsddb.test.test_all import verbose - -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db -except ImportError: - # For Python 2.3 - from bsddb import db - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +from .test_all import db, test_support, verbose, get_new_environment_path, get_new_database_path letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' @@ -29,8 +14,13 @@ #---------------------------------------------------------------------- class SimpleRecnoTestCase(unittest.TestCase): + import sys + if sys.version_info[:3] < (2, 4, 0): + def assertFalse(self, expr, msg=None): + self.failIf(expr,msg=msg) + def setUp(self): - self.filename = tempfile.mktemp() + self.filename = get_new_database_path() self.homeDir = None def tearDown(self): @@ -47,9 +37,9 @@ d.open(self.filename, db.DB_RECNO, db.DB_CREATE) for x in letters: - recno = d.append(x.encode('ascii') * 60) - assert type(recno) == type(0) - assert recno >= 1 + recno = d.append(x * 60) + self.assertEqual(type(recno), type(0)) + self.assert_(recno >= 1) if verbose: print(recno, end=' ') @@ -64,20 +54,24 @@ if verbose: print(data) - assert type(data) == bytes - assert data == d.get(recno) + self.assertEqual(type(data), type("")) + self.assertEqual(data, d.get(recno)) try: data = d[0] # This should raise a KeyError!?!?! except db.DBInvalidArgError as val: - assert val.args[0] == db.EINVAL + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.EINVAL) + else : + self.assertEqual(val.args[0], db.EINVAL) if verbose: print(val) else: self.fail("expected exception") # test that has_key raises DB exceptions (fixed in pybsddb 4.3.2) try: - d.has_key(0) + 0 in d except db.DBError as val: pass else: @@ -96,35 +90,35 @@ if get_returns_none: self.fail("unexpected exception") else: - assert data == None + self.assertEqual(data, None) - keys = d.keys() + keys = list(d.keys()) if verbose: print(keys) - assert type(keys) == type([]) - assert type(keys[0]) == type(123) - assert len(keys) == len(d) + self.assertEqual(type(keys), type([])) + self.assertEqual(type(keys[0]), type(123)) + self.assertEqual(len(keys), len(d)) - items = d.items() + items = list(d.items()) if verbose: pprint(items) - assert type(items) == type([]) - assert type(items[0]) == type(()) - assert len(items[0]) == 2 - assert type(items[0][0]) == type(123) - assert type(items[0][1]) == bytes - assert len(items) == len(d) + self.assertEqual(type(items), type([])) + self.assertEqual(type(items[0]), type(())) + self.assertEqual(len(items[0]), 2) + self.assertEqual(type(items[0][0]), type(123)) + self.assertEqual(type(items[0][1]), type("")) + self.assertEqual(len(items), len(d)) - assert d.has_key(25) + self.assert_(25 in d) del d[25] - assert not d.has_key(25) + self.assertFalse(25 in d) d.delete(13) - assert not d.has_key(13) + self.assertFalse(13 in d) - data = d.get_both(26, b"z" * 60) - assert data == b"z" * 60, 'was %r' % data + data = d.get_both(26, "z" * 60) + self.assertEqual(data, "z" * 60, 'was %r' % data) if verbose: print(data) @@ -137,18 +131,18 @@ while rec: if verbose: print(rec) - rec = c.next() + rec = next(c) c.set(50) rec = c.current() if verbose: print(rec) - c.put(-1, b"a replacement record", db.DB_CURRENT) + c.put(-1, "a replacement record", db.DB_CURRENT) c.set(50) rec = c.current() - assert rec == (50, b"a replacement record") + self.assertEqual(rec, (50, "a replacement record")) if verbose: print(rec) @@ -159,7 +153,7 @@ # test that non-existant key lookups work (and that # DBC_set_range doesn't have a memleak under valgrind) rec = c.set_range(999999) - assert rec == None + self.assertEqual(rec, None) if verbose: print(rec) @@ -171,8 +165,8 @@ c = d.cursor() # put a record beyond the consecutive end of the recno's - d[100] = b"way out there" - assert d[100] == b"way out there" + d[100] = "way out there" + self.assertEqual(d[100], "way out there") try: data = d[99] @@ -187,7 +181,7 @@ if get_returns_none: self.fail("unexpected DBKeyEmptyError exception") else: - assert val.args[0] == db.DB_KEYEMPTY + self.assertEqual(val[0], db.DB_KEYEMPTY) if verbose: print(val) else: if not get_returns_none: @@ -197,7 +191,7 @@ while rec: if verbose: print(rec) - rec = c.next() + rec = next(c) c.close() d.close() @@ -209,7 +203,7 @@ just a line in the file, but you can set a different record delimiter if needed. """ - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) + homeDir = get_new_environment_path() self.homeDir = homeDir source = os.path.join(homeDir, 'test_recno.txt') if not os.path.isdir(homeDir): @@ -226,7 +220,7 @@ data = "The quick brown fox jumped over the lazy dog".split() for datum in data: - d.append(datum.encode('ascii')) + d.append(datum) d.sync() d.close() @@ -238,15 +232,15 @@ print(data) print(text.split('\n')) - assert text.split('\n') == data + self.assertEqual(text.split('\n'), data) # open as a DB again d = db.DB() d.set_re_source(source) d.open(self.filename, db.DB_RECNO) - d[3] = b'reddish-brown' - d[8] = b'comatose' + d[3] = 'reddish-brown' + d[8] = 'comatose' d.sync() d.close() @@ -257,8 +251,8 @@ print(text) print(text.split('\n')) - assert text.split('\n') == \ - "The quick reddish-brown fox jumped over the comatose dog".split() + self.assertEqual(text.split('\n'), + "The quick reddish-brown fox jumped over the comatose dog".split()) def test03_FixedLength(self): d = db.DB() @@ -268,14 +262,18 @@ d.open(self.filename, db.DB_RECNO, db.DB_CREATE) for x in letters: - d.append(x.encode('ascii') * 35) # These will be padded + d.append(x * 35) # These will be padded - d.append(b'.' * 40) # this one will be exact + d.append('.' * 40) # this one will be exact try: # this one will fail - d.append(b'bad' * 20) + d.append('bad' * 20) except db.DBInvalidArgError as val: - assert val.args[0] == db.EINVAL + import sys + if sys.version_info[0] < 3 : + self.assertEqual(val[0], db.EINVAL) + else : + self.assertEqual(val.args[0], db.EINVAL) if verbose: print(val) else: self.fail("expected exception") @@ -285,7 +283,7 @@ while rec: if verbose: print(rec) - rec = c.next() + rec = next(c) c.close() d.close() Added: python/branches/py3k/Lib/bsddb/test/test_replication.py ============================================================================== --- (empty file) +++ python/branches/py3k/Lib/bsddb/test/test_replication.py Sun Aug 31 16:12:11 2008 @@ -0,0 +1,444 @@ +"""TestCases for distributed transactions. +""" + +import os +import time +import unittest + +from .test_all import db, test_support, have_threads, verbose, \ + get_new_environment_path, get_new_database_path + + +#---------------------------------------------------------------------- + +class DBReplicationManager(unittest.TestCase): + import sys + if sys.version_info[:3] < (2, 4, 0): + def assertTrue(self, expr, msg=None): + self.failUnless(expr,msg=msg) + + def setUp(self) : + self.homeDirMaster = get_new_environment_path() + self.homeDirClient = get_new_environment_path() + + self.dbenvMaster = db.DBEnv() + self.dbenvClient = db.DBEnv() + + # Must use "DB_THREAD" because the Replication Manager will + # be executed in other threads but will use the same environment. + # http://forums.oracle.com/forums/thread.jspa?threadID=645788&tstart=0 + self.dbenvMaster.open(self.homeDirMaster, db.DB_CREATE | db.DB_INIT_TXN + | db.DB_INIT_LOG | db.DB_INIT_MPOOL | db.DB_INIT_LOCK | + db.DB_INIT_REP | db.DB_RECOVER | db.DB_THREAD, 0o666) + self.dbenvClient.open(self.homeDirClient, db.DB_CREATE | db.DB_INIT_TXN + | db.DB_INIT_LOG | db.DB_INIT_MPOOL | db.DB_INIT_LOCK | + db.DB_INIT_REP | db.DB_RECOVER | db.DB_THREAD, 0o666) + + self.confirmed_master=self.client_startupdone=False + def confirmed_master(a,b,c) : + if b==db.DB_EVENT_REP_MASTER : + self.confirmed_master=True + + def client_startupdone(a,b,c) : + if b==db.DB_EVENT_REP_STARTUPDONE : + self.client_startupdone=True + + self.dbenvMaster.set_event_notify(confirmed_master) + self.dbenvClient.set_event_notify(client_startupdone) + + #self.dbenvMaster.set_verbose(db.DB_VERB_REPLICATION, True) + #self.dbenvMaster.set_verbose(db.DB_VERB_FILEOPS_ALL, True) + #self.dbenvClient.set_verbose(db.DB_VERB_REPLICATION, True) + #self.dbenvClient.set_verbose(db.DB_VERB_FILEOPS_ALL, True) + + self.dbMaster = self.dbClient = None + + + def tearDown(self): + if self.dbClient : + self.dbClient.close() + if self.dbMaster : + self.dbMaster.close() + self.dbenvClient.close() + self.dbenvMaster.close() + test_support.rmtree(self.homeDirClient) + test_support.rmtree(self.homeDirMaster) + + def test01_basic_replication(self) : + master_port = test_support.find_unused_port() + self.dbenvMaster.repmgr_set_local_site("127.0.0.1", master_port) + client_port = test_support.find_unused_port() + self.dbenvClient.repmgr_set_local_site("127.0.0.1", client_port) + self.dbenvMaster.repmgr_add_remote_site("127.0.0.1", client_port) + self.dbenvClient.repmgr_add_remote_site("127.0.0.1", master_port) + self.dbenvMaster.rep_set_nsites(2) + self.dbenvClient.rep_set_nsites(2) + self.dbenvMaster.rep_set_priority(10) + self.dbenvClient.rep_set_priority(0) + + self.dbenvMaster.rep_set_timeout(db.DB_REP_CONNECTION_RETRY,100123) + self.dbenvClient.rep_set_timeout(db.DB_REP_CONNECTION_RETRY,100321) + self.assertEquals(self.dbenvMaster.rep_get_timeout( + db.DB_REP_CONNECTION_RETRY), 100123) + self.assertEquals(self.dbenvClient.rep_get_timeout( + db.DB_REP_CONNECTION_RETRY), 100321) + + self.dbenvMaster.rep_set_timeout(db.DB_REP_ELECTION_TIMEOUT, 100234) + self.dbenvClient.rep_set_timeout(db.DB_REP_ELECTION_TIMEOUT, 100432) + self.assertEquals(self.dbenvMaster.rep_get_timeout( + db.DB_REP_ELECTION_TIMEOUT), 100234) + self.assertEquals(self.dbenvClient.rep_get_timeout( + db.DB_REP_ELECTION_TIMEOUT), 100432) + + self.dbenvMaster.rep_set_timeout(db.DB_REP_ELECTION_RETRY, 100345) + self.dbenvClient.rep_set_timeout(db.DB_REP_ELECTION_RETRY, 100543) + self.assertEquals(self.dbenvMaster.rep_get_timeout( + db.DB_REP_ELECTION_RETRY), 100345) + self.assertEquals(self.dbenvClient.rep_get_timeout( + db.DB_REP_ELECTION_RETRY), 100543) + + self.dbenvMaster.repmgr_set_ack_policy(db.DB_REPMGR_ACKS_ALL) + self.dbenvClient.repmgr_set_ack_policy(db.DB_REPMGR_ACKS_ALL) + + self.dbenvMaster.repmgr_start(1, db.DB_REP_MASTER); + self.dbenvClient.repmgr_start(1, db.DB_REP_CLIENT); + + self.assertEquals(self.dbenvMaster.rep_get_nsites(),2) + self.assertEquals(self.dbenvClient.rep_get_nsites(),2) + self.assertEquals(self.dbenvMaster.rep_get_priority(),10) + self.assertEquals(self.dbenvClient.rep_get_priority(),0) + self.assertEquals(self.dbenvMaster.repmgr_get_ack_policy(), + db.DB_REPMGR_ACKS_ALL) + self.assertEquals(self.dbenvClient.repmgr_get_ack_policy(), + db.DB_REPMGR_ACKS_ALL) + + # The timeout is necessary in BDB 4.5, since DB_EVENT_REP_STARTUPDONE + # is not generated if the master has no new transactions. + # This is solved in BDB 4.6 (#15542). + import time + timeout = time.time()+10 + while (time.time()= (4,6) : + d = self.dbenvMaster.repmgr_stat(flags=db.DB_STAT_CLEAR); + self.assertTrue("msgs_queued" in d) + + self.dbMaster=db.DB(self.dbenvMaster) + txn=self.dbenvMaster.txn_begin() + self.dbMaster.open("test", db.DB_HASH, db.DB_CREATE, 0o666, txn=txn) + txn.commit() + + import time,os.path + timeout=time.time()+10 + while (time.time()= (4,7) : + def test02_test_request(self) : + self.basic_rep_threading() + (minimum, maximum) = self.dbenvClient.rep_get_request() + self.dbenvClient.rep_set_request(minimum-1, maximum+1) + self.assertEqual(self.dbenvClient.rep_get_request(), + (minimum-1, maximum+1)) + + if db.version() >= (4,6) : + def test03_master_election(self) : + # Get ready to hold an election + #self.dbenvMaster.rep_start(flags=db.DB_REP_MASTER) + self.dbenvMaster.rep_start(flags=db.DB_REP_CLIENT) + self.dbenvClient.rep_start(flags=db.DB_REP_CLIENT) + + def thread_do(env, q, envid, election_status, must_be_master) : + while True : + v=q.get() + if v == None : return + r = env.rep_process_message(v[0],v[1],envid) + if must_be_master and self.confirmed_master : + self.dbenvMaster.rep_start(flags = db.DB_REP_MASTER) + must_be_master = False + + if r[0] == db.DB_REP_HOLDELECTION : + def elect() : + while True : + try : + env.rep_elect(2, 1) + election_status[0] = False + break + except db.DBRepUnavailError : + pass + if not election_status[0] and not self.confirmed_master : + from threading import Thread + election_status[0] = True + t=Thread(target=elect) + import sys + if sys.version_info[0] < 3 : + t.setDaemon(True) + else : + t.daemon = True + t.start() + + self.thread_do = thread_do + + self.t_m.start() + self.t_c.start() + + self.dbenvMaster.rep_set_timeout(db.DB_REP_ELECTION_TIMEOUT, 50000) + self.dbenvClient.rep_set_timeout(db.DB_REP_ELECTION_TIMEOUT, 50000) + self.client_doing_election[0] = True + while True : + try : + self.dbenvClient.rep_elect(2, 1) + self.client_doing_election[0] = False + break + except db.DBRepUnavailError : + pass + + self.assertTrue(self.confirmed_master) + +#---------------------------------------------------------------------- + +def test_suite(): + suite = unittest.TestSuite() + if db.version() >= (4, 6) : + dbenv = db.DBEnv() + try : + dbenv.repmgr_get_ack_policy() + ReplicationManager_available=True + except : + ReplicationManager_available=False + dbenv.close() + del dbenv + if ReplicationManager_available : + suite.addTest(unittest.makeSuite(DBReplicationManager)) + + if have_threads : + suite.addTest(unittest.makeSuite(DBBaseReplication)) + + return suite + + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') Modified: python/branches/py3k/Lib/bsddb/test/test_sequence.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_sequence.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_sequence.py Sun Aug 31 16:12:11 2008 @@ -1,33 +1,19 @@ import unittest import os -import shutil -import sys -import tempfile - -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db -except ImportError: - from bsddb import db - -from bsddb.test.test_all import verbose -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support + +from .test_all import db, test_support, get_new_environment_path, get_new_database_path class DBSequenceTest(unittest.TestCase): + import sys + if sys.version_info[:3] < (2, 4, 0): + def assertTrue(self, expr, msg=None): + self.failUnless(expr,msg=msg) + def setUp(self): self.int_32_max = 0x100000000 - self.homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - try: - os.mkdir(self.homeDir) - except os.error: - pass - tempfile.tempdir = self.homeDir - self.filename = os.path.split(tempfile.mktemp())[1] - tempfile.tempdir = None + self.homeDir = get_new_environment_path() + self.filename = "test" self.dbenv = db.DBEnv() self.dbenv.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL, 0o666) @@ -52,39 +38,39 @@ start_value = 10 * self.int_32_max self.assertEqual(0xA00000000, start_value) self.assertEquals(None, self.seq.init_value(start_value)) - self.assertEquals(None, self.seq.open(key=b'id', txn=None, flags=db.DB_CREATE)) + self.assertEquals(None, self.seq.open(key='id', txn=None, flags=db.DB_CREATE)) self.assertEquals(start_value, self.seq.get(5)) self.assertEquals(start_value + 5, self.seq.get()) def test_remove(self): self.seq = db.DBSequence(self.d, flags=0) - self.assertEquals(None, self.seq.open(key=b'foo', txn=None, flags=db.DB_CREATE)) + self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE)) self.assertEquals(None, self.seq.remove(txn=None, flags=0)) del self.seq def test_get_key(self): self.seq = db.DBSequence(self.d, flags=0) - key = b'foo' + key = 'foo' self.assertEquals(None, self.seq.open(key=key, txn=None, flags=db.DB_CREATE)) self.assertEquals(key, self.seq.get_key()) def test_get_dbp(self): self.seq = db.DBSequence(self.d, flags=0) - self.assertEquals(None, self.seq.open(key=b'foo', txn=None, flags=db.DB_CREATE)) + self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE)) self.assertEquals(self.d, self.seq.get_dbp()) def test_cachesize(self): self.seq = db.DBSequence(self.d, flags=0) cashe_size = 10 self.assertEquals(None, self.seq.set_cachesize(cashe_size)) - self.assertEquals(None, self.seq.open(key=b'foo', txn=None, flags=db.DB_CREATE)) + self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE)) self.assertEquals(cashe_size, self.seq.get_cachesize()) def test_flags(self): self.seq = db.DBSequence(self.d, flags=0) flag = db.DB_SEQ_WRAP; self.assertEquals(None, self.seq.set_flags(flag)) - self.assertEquals(None, self.seq.open(key=b'foo', txn=None, flags=db.DB_CREATE)) + self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE)) self.assertEquals(flag, self.seq.get_flags() & flag) def test_range(self): @@ -92,17 +78,59 @@ seq_range = (10 * self.int_32_max, 11 * self.int_32_max - 1) self.assertEquals(None, self.seq.set_range(seq_range)) self.seq.init_value(seq_range[0]) - self.assertEquals(None, self.seq.open(key=b'foo', txn=None, flags=db.DB_CREATE)) + self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE)) self.assertEquals(seq_range, self.seq.get_range()) def test_stat(self): self.seq = db.DBSequence(self.d, flags=0) - self.assertEquals(None, self.seq.open(key=b'foo', txn=None, flags=db.DB_CREATE)) + self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE)) stat = self.seq.stat() for param in ('nowait', 'min', 'max', 'value', 'current', 'flags', 'cache_size', 'last_value', 'wait'): self.assertTrue(param in stat, "parameter %s isn't in stat info" % param) + if db.version() >= (4,7) : + # This code checks a crash solved in Berkeley DB 4.7 + def test_stat_crash(self) : + d=db.DB() + d.open(None,dbtype=db.DB_HASH,flags=db.DB_CREATE) # In RAM + seq = db.DBSequence(d, flags=0) + + self.assertRaises(db.DBNotFoundError, seq.open, + key='id', txn=None, flags=0) + + self.assertRaises(db.DBInvalidArgError, seq.stat) + + d.close() + + def test_64bits(self) : + # We don't use both extremes because they are problematic + value_plus=(1<<63)-2 + self.assertEquals(9223372036854775806,value_plus) + value_minus=(-1<<63)+1 # Two complement + self.assertEquals(-9223372036854775807,value_minus) + self.seq = db.DBSequence(self.d, flags=0) + self.assertEquals(None, self.seq.init_value(value_plus-1)) + self.assertEquals(None, self.seq.open(key='id', txn=None, + flags=db.DB_CREATE)) + self.assertEquals(value_plus-1, self.seq.get(1)) + self.assertEquals(value_plus, self.seq.get(1)) + + self.seq.remove(txn=None, flags=0) + + self.seq = db.DBSequence(self.d, flags=0) + self.assertEquals(None, self.seq.init_value(value_minus)) + self.assertEquals(None, self.seq.open(key='id', txn=None, + flags=db.DB_CREATE)) + self.assertEquals(value_minus, self.seq.get(1)) + self.assertEquals(value_minus+1, self.seq.get(1)) + + def test_multiple_close(self): + self.seq = db.DBSequence(self.d) + self.seq.close() # You can close a Sequence multiple times + self.seq.close() + self.seq.close() + def test_suite(): suite = unittest.TestSuite() if db.version() >= (4,3): Modified: python/branches/py3k/Lib/bsddb/test/test_thread.py ============================================================================== --- python/branches/py3k/Lib/bsddb/test/test_thread.py (original) +++ python/branches/py3k/Lib/bsddb/test/test_thread.py Sun Aug 31 16:12:11 2008 @@ -5,17 +5,9 @@ import sys import time import errno -import tempfile -from pprint import pprint from random import random -DASH = b'-' - -try: - from threading import Thread, current_thread - have_threads = True -except ImportError: - have_threads = False +DASH = '-' try: WindowsError @@ -24,19 +16,16 @@ pass import unittest -from bsddb.test.test_all import verbose +from .test_all import db, dbutils, test_support, verbose, have_threads, \ + get_new_environment_path, get_new_database_path -try: - # For Pythons w/distutils pybsddb - from bsddb3 import db, dbutils -except ImportError: - # For Python 2.3 - from bsddb import db, dbutils - -try: - from bsddb3 import test_support -except ImportError: - from test import support as test_support +if have_threads : + from threading import Thread + import sys + if sys.version_info[0] < 3 : + from threading import currentThread + else : + from threading import current_thread as currentThread #---------------------------------------------------------------------- @@ -47,16 +36,16 @@ dbsetflags = 0 envflags = 0 + import sys + if sys.version_info[:3] < (2, 4, 0): + def assertTrue(self, expr, msg=None): + self.failUnless(expr,msg=msg) + def setUp(self): if verbose: dbutils._deadlock_VerboseFile = sys.stdout - homeDir = os.path.join(tempfile.gettempdir(), 'db_home%d'%os.getpid()) - self.homeDir = homeDir - try: - os.mkdir(homeDir) - except OSError as e: - if e.errno != errno.EEXIST: raise + self.homeDir = get_new_environment_path() self.env = db.DBEnv() self.setEnvOpts() self.env.open(self.homeDir, self.envflags | db.DB_CREATE) @@ -78,33 +67,6 @@ def makeData(self, key): return DASH.join([key] * 5) - def _writerThread(self, *args, **kwargs): - raise RuntimeError("must override this in a subclass") - - def _readerThread(self, *args, **kwargs): - raise RuntimeError("must override this in a subclass") - - def writerThread(self, *args, **kwargs): - try: - self._writerThread(*args, **kwargs) - except db.DBLockDeadlockError: - if verbose: - print(current_thread().name, 'died from', e) - else: - if verbose: - print(current_thread().name, "finished.") - - def readerThread(self, *args, **kwargs): - try: - self._readerThread(*args, **kwargs) - except db.DBLockDeadlockError as e: - if verbose: - print(current_thread().name, 'died from', e) - else: - if verbose: - print(current_thread().name, "finished.") - - #---------------------------------------------------------------------- @@ -121,60 +83,91 @@ print('\n', '-=' * 30) print("Running %s.test01_1WriterMultiReaders..." % \ self.__class__.__name__) - print('Using:', self.homeDir, self.filename) - threads = [] - wt = Thread(target = self.writerThread, - args = (self.d, self.records), - name = 'the writer', - )#verbose = verbose) - threads.append(wt) + keys=list(range(self.records)) + import random + random.shuffle(keys) + records_per_writer=self.records//self.writers + readers_per_writer=self.readers//self.writers + self.assertEqual(self.records,self.writers*records_per_writer) + self.assertEqual(self.readers,self.writers*readers_per_writer) + self.assertTrue((records_per_writer%readers_per_writer)==0) + readers = [] for x in range(self.readers): rt = Thread(target = self.readerThread, args = (self.d, x), name = 'reader %d' % x, )#verbose = verbose) - threads.append(rt) + import sys + if sys.version_info[0] < 3 : + rt.setDaemon(True) + else : + rt.daemon = True + readers.append(rt) - for t in threads: + writers=[] + for x in range(self.writers): + a=keys[records_per_writer*x:records_per_writer*(x+1)] + a.sort() # Generate conflicts + b=readers[readers_per_writer*x:readers_per_writer*(x+1)] + wt = Thread(target = self.writerThread, + args = (self.d, a, b), + name = 'writer %d' % x, + )#verbose = verbose) + writers.append(wt) + + for t in writers: + import sys + if sys.version_info[0] < 3 : + t.setDaemon(True) + else : + t.daemon = True t.start() - for t in threads: + + for t in writers: t.join() + for t in readers: + t.join() + + def writerThread(self, d, keys, readers): + import sys + if sys.version_info[0] < 3 : + name = currentThread().getName() + else : + name = currentThread().name + + if verbose: + print("%s: creating records %d - %d" % (name, start, stop)) + + count=len(keys)//len(readers) + count2=count + for x in keys : + key = '%04d' % x + dbutils.DeadlockWrap(d.put, key, self.makeData(key), + max_retries=12) + if verbose and x % 100 == 0: + print("%s: records %d - %d finished" % (name, start, x)) - def _writerThread(self, d, howMany): - name = current_thread().name - start = 0 - stop = howMany - if verbose: - print(name+": creating records", start, "-", stop) - - for x in range(start, stop): - key = ('%04d' % x).encode("ascii") - d.put(key, self.makeData(key)) - if verbose and x > start and x % 50 == 0: - print(name+": records", start, "-", x, "finished") + count2-=1 + if not count2 : + readers.pop().start() + count2=count if verbose: print("%s: finished creating records" % name) -## # Each write-cursor will be exclusive, the only one that can update the DB... -## if verbose: print "%s: deleting a few records" % name -## c = d.cursor(flags = db.DB_WRITECURSOR) -## for x in range(10): -## key = int(random() * howMany) + start -## key = '%04d' % key -## if d.has_key(key): -## c.set(key) -## c.delete() - -## c.close() - - def _readerThread(self, d, readerNum): - time.sleep(0.01 * readerNum) - name = current_thread().name + if verbose: + print("%s: thread finished" % name) - for loop in range(5): + def readerThread(self, d, readerNum): + import sys + if sys.version_info[0] < 3 : + name = currentThread().getName() + else : + name = currentThread().name + + for i in range(5) : c = d.cursor() count = 0 rec = c.first() @@ -182,24 +175,26 @@ count += 1 key, data = rec self.assertEqual(self.makeData(key), data) - rec = c.next() + rec = next(c) if verbose: - print(name+": found", count, "records") + print("%s: found %d records" % (name, count)) c.close() - time.sleep(0.05) + + if verbose: + print("%s: thread finished" % name) class BTreeConcurrentDataStore(ConcurrentDataStoreBase): dbtype = db.DB_BTREE - writers = 1 + writers = 2 readers = 10 records = 1000 class HashConcurrentDataStore(ConcurrentDataStoreBase): dbtype = db.DB_HASH - writers = 1 - readers = 0 + writers = 2 + readers = 10 records = 1000 @@ -208,8 +203,8 @@ class SimpleThreadedBase(BaseThreadedTestCase): dbopenflags = db.DB_THREAD envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK - readers = 5 - writers = 3 + readers = 10 + writers = 2 records = 1000 def setEnvOpts(self): @@ -220,87 +215,98 @@ print('\n', '-=' * 30) print("Running %s.test02_SimpleLocks..." % self.__class__.__name__) - threads = [] - for x in range(self.writers): - wt = Thread(target = self.writerThread, - args = (self.d, self.records, x), - name = 'writer %d' % x, - )#verbose = verbose) - threads.append(wt) + + keys=list(range(self.records)) + import random + random.shuffle(keys) + records_per_writer=self.records//self.writers + readers_per_writer=self.readers//self.writers + self.assertEqual(self.records,self.writers*records_per_writer) + self.assertEqual(self.readers,self.writers*readers_per_writer) + self.assertTrue((records_per_writer%readers_per_writer)==0) + + readers = [] for x in range(self.readers): rt = Thread(target = self.readerThread, args = (self.d, x), name = 'reader %d' % x, )#verbose = verbose) - threads.append(rt) + import sys + if sys.version_info[0] < 3 : + rt.setDaemon(True) + else : + rt.daemon = True + readers.append(rt) + + writers = [] + for x in range(self.writers): + a=keys[records_per_writer*x:records_per_writer*(x+1)] + a.sort() # Generate conflicts + b=readers[readers_per_writer*x:readers_per_writer*(x+1)] + wt = Thread(target = self.writerThread, + args = (self.d, a, b), + name = 'writer %d' % x, + )#verbose = verbose) + writers.append(wt) - for t in threads: + for t in writers: + import sys + if sys.version_info[0] < 3 : + t.setDaemon(True) + else : + t.daemon = True t.start() - for t in threads: + + for t in writers: + t.join() + for t in readers: t.join() - def _writerThread(self, d, howMany, writerNum): - name = current_thread().name - start = howMany * writerNum - stop = howMany * (writerNum + 1) - 1 + def writerThread(self, d, keys, readers): + import sys + if sys.version_info[0] < 3 : + name = currentThread().getName() + else : + name = currentThread().name if verbose: print("%s: creating records %d - %d" % (name, start, stop)) - # create a bunch of records - for x in range(start, stop): - key = ('%04d' % x).encode("ascii") + count=len(keys)//len(readers) + count2=count + for x in keys : + key = '%04d' % x dbutils.DeadlockWrap(d.put, key, self.makeData(key), - max_retries=20) + max_retries=12) if verbose and x % 100 == 0: print("%s: records %d - %d finished" % (name, start, x)) - # do a bit or reading too - if random() <= 0.05: - for y in range(start, x): - key = ('%04d' % x).encode("ascii") - data = dbutils.DeadlockWrap(d.get, key, max_retries=20) - self.assertEqual(data, self.makeData(key)) - - # flush them - try: - dbutils.DeadlockWrap(d.sync, max_retries=20) - except db.DBIncompleteError as val: - if verbose: - print("could not complete sync()...") - - # read them back, deleting a few - for x in range(start, stop): - key = ('%04d' % x).encode("ascii") - data = dbutils.DeadlockWrap(d.get, key, max_retries=20) - if verbose and x % 100 == 0: - print("%s: fetched record (%s, %s)" % (name, key, data)) - self.assertEqual(data, self.makeData(key)) - if random() <= 0.10: - dbutils.DeadlockWrap(d.delete, key, max_retries=20) - if verbose: - print("%s: deleted record %s" % (name, key)) + count2-=1 + if not count2 : + readers.pop().start() + count2=count if verbose: print("%s: thread finished" % name) - def _readerThread(self, d, readerNum): - time.sleep(0.01 * readerNum) - name = current_thread().name - - for loop in range(5): - c = d.cursor() - count = 0 - rec = dbutils.DeadlockWrap(c.first, max_retries=20) - while rec: - count += 1 - key, data = rec - self.assertEqual(self.makeData(key), data) - rec = dbutils.DeadlockWrap(c.next, max_retries=20) - if verbose: - print("%s: found %d records" % (name, count)) - c.close() - time.sleep(0.05) + def readerThread(self, d, readerNum): + import sys + if sys.version_info[0] < 3 : + name = currentThread().getName() + else : + name = currentThread().name + + c = d.cursor() + count = 0 + rec = dbutils.DeadlockWrap(c.first, max_retries=10) + while rec: + count += 1 + key, data = rec + self.assertEqual(self.makeData(key), data) + rec = dbutils.DeadlockWrap(c.__next__, max_retries=10) + if verbose: + print("%s: found %d records" % (name, count)) + c.close() if verbose: print("%s: thread finished" % name) @@ -340,120 +346,118 @@ print("Running %s.test03_ThreadedTransactions..." % \ self.__class__.__name__) - threads = [] - for x in range(self.writers): - wt = Thread(target = self.writerThread, - args = (self.d, self.records, x), - name = 'writer %d' % x, - )#verbose = verbose) - threads.append(wt) + keys=list(range(self.records)) + import random + random.shuffle(keys) + records_per_writer=self.records//self.writers + readers_per_writer=self.readers//self.writers + self.assertEqual(self.records,self.writers*records_per_writer) + self.assertEqual(self.readers,self.writers*readers_per_writer) + self.assertTrue((records_per_writer%readers_per_writer)==0) + readers=[] for x in range(self.readers): rt = Thread(target = self.readerThread, args = (self.d, x), name = 'reader %d' % x, )#verbose = verbose) - threads.append(rt) + import sys + if sys.version_info[0] < 3 : + rt.setDaemon(True) + else : + rt.daemon = True + readers.append(rt) + + writers = [] + for x in range(self.writers): + a=keys[records_per_writer*x:records_per_writer*(x+1)] + b=readers[readers_per_writer*x:readers_per_writer*(x+1)] + wt = Thread(target = self.writerThread, + args = (self.d, a, b), + name = 'writer %d' % x, + )#verbose = verbose) + writers.append(wt) dt = Thread(target = self.deadlockThread) + import sys + if sys.version_info[0] < 3 : + dt.setDaemon(True) + else : + dt.daemon = True dt.start() - for t in threads: + for t in writers: + import sys + if sys.version_info[0] < 3 : + t.setDaemon(True) + else : + t.daemon = True t.start() - for t in threads: + + for t in writers: + t.join() + for t in readers: t.join() self.doLockDetect = False dt.join() - def doWrite(self, d, name, start, stop): - finished = False - while not finished: + def writerThread(self, d, keys, readers): + import sys + if sys.version_info[0] < 3 : + name = currentThread().getName() + else : + name = currentThread().name + + count=len(keys)//len(readers) + while len(keys): try: txn = self.env.txn_begin(None, self.txnFlag) - for x in range(start, stop): - key = ('%04d' % x).encode("ascii") + keys2=keys[:count] + for x in keys2 : + key = '%04d' % x d.put(key, self.makeData(key), txn) if verbose and x % 100 == 0: print("%s: records %d - %d finished" % (name, start, x)) txn.commit() - finished = True + keys=keys[count:] + readers.pop().start() except (db.DBLockDeadlockError, db.DBLockNotGrantedError) as val: if verbose: - print("%s: Aborting transaction (%s)" % (name, val)) + print("%s: Aborting transaction (%s)" % (name, val[1])) txn.abort() - time.sleep(0.05) - def _writerThread(self, d, howMany, writerNum): - name = current_thread().name - start = howMany * writerNum - stop = howMany * (writerNum + 1) - 1 if verbose: - print("%s: creating records %d - %d" % (name, start, stop)) - - step = 100 - for x in range(start, stop, step): - self.doWrite(d, name, x, min(stop, x+step)) + print("%s: thread finished" % name) - if verbose: - print("%s: finished creating records" % name) - if verbose: - print("%s: deleting a few records" % name) + def readerThread(self, d, readerNum): + import sys + if sys.version_info[0] < 3 : + name = currentThread().getName() + else : + name = currentThread().name finished = False while not finished: try: - recs = [] txn = self.env.txn_begin(None, self.txnFlag) - for x in range(10): - key = int(random() * howMany) + start - key = ('%04d' % key).encode("ascii") - data = d.get(key, None, txn, db.DB_RMW) - if data is not None: - d.delete(key, txn) - recs.append(key) + c = d.cursor(txn) + count = 0 + rec = c.first() + while rec: + count += 1 + key, data = rec + self.assertEqual(self.makeData(key), data) + rec = next(c) + if verbose: print("%s: found %d records" % (name, count)) + c.close() txn.commit() finished = True - if verbose: - print("%s: deleted records %s" % (name, recs)) except (db.DBLockDeadlockError, db.DBLockNotGrantedError) as val: if verbose: - print("%s: Aborting transaction (%s)" % (name, val)) + print("%s: Aborting transaction (%s)" % (name, val[1])) + c.close() txn.abort() - time.sleep(0.05) - - if verbose: - print("%s: thread finished" % name) - - def _readerThread(self, d, readerNum): - time.sleep(0.01 * readerNum + 0.05) - name = current_thread().name - - for loop in range(5): - finished = False - while not finished: - try: - txn = self.env.txn_begin(None, self.txnFlag) - c = d.cursor(txn) - count = 0 - rec = c.first() - while rec: - count += 1 - key, data = rec - self.assertEqual(self.makeData(key), data) - rec = c.next() - if verbose: print("%s: found %d records" % (name, count)) - c.close() - txn.commit() - finished = True - except (db.DBLockDeadlockError, db.DBLockNotGrantedError) as val: - if verbose: - print("%s: Aborting transaction (%s)" % (name, val)) - c.close() - txn.abort() - time.sleep(0.05) - - time.sleep(0.05) if verbose: print("%s: thread finished" % name) @@ -461,7 +465,7 @@ def deadlockThread(self): self.doLockDetect = True while self.doLockDetect: - time.sleep(0.5) + time.sleep(0.05) try: aborted = self.env.lock_detect( db.DB_LOCK_RANDOM, db.DB_LOCK_CONFLICT) @@ -474,28 +478,28 @@ class BTreeThreadedTransactions(ThreadedTransactionsBase): dbtype = db.DB_BTREE - writers = 3 - readers = 5 - records = 2000 + writers = 2 + readers = 10 + records = 1000 class HashThreadedTransactions(ThreadedTransactionsBase): dbtype = db.DB_HASH - writers = 1 - readers = 5 - records = 2000 + writers = 2 + readers = 10 + records = 1000 class BTreeThreadedNoWaitTransactions(ThreadedTransactionsBase): dbtype = db.DB_BTREE - writers = 3 - readers = 5 - records = 2000 + writers = 2 + readers = 10 + records = 1000 txnFlag = db.DB_TXN_NOWAIT class HashThreadedNoWaitTransactions(ThreadedTransactionsBase): dbtype = db.DB_HASH - writers = 1 - readers = 5 - records = 2000 + writers = 2 + readers = 10 + records = 1000 txnFlag = db.DB_TXN_NOWAIT Modified: python/branches/py3k/Misc/NEWS ============================================================================== --- python/branches/py3k/Misc/NEWS (original) +++ python/branches/py3k/Misc/NEWS Sun Aug 31 16:12:11 2008 @@ -63,6 +63,12 @@ - Issue #3643: Added a few more checks to _testcapi to prevent segfaults by exploitation of poor argument checking. +- bsddb code updated to version 4.7.3pre2. This code is the same than + Python 2.6 one, since the intention is to keep an unified 2.x/3.x codebase. + The Python code is automatically translated using "2to3". Please, do not + update this code in Python 3.0 by hand. Update the 2.6 one and then + do "2to3". + Tools/Demos ----------- Modified: python/branches/py3k/Modules/_bsddb.c ============================================================================== --- python/branches/py3k/Modules/_bsddb.c (original) +++ python/branches/py3k/Modules/_bsddb.c Sun Aug 31 16:12:11 2008 @@ -36,7 +36,7 @@ /* * Handwritten code to wrap version 3.x of the Berkeley DB library, * written to replace a SWIG-generated file. It has since been updated - * to compile with BerkeleyDB versions 3.2 through 4.2. + * to compile with Berkeley DB versions 3.2 through 4.2. * * This module was started by Andrew Kuchling to remove the dependency * on SWIG in a package by Gregory P. Smith who based his work on a @@ -48,7 +48,10 @@ * the DB 3.x API and to build a solid unit test suite. Robin has * since gone onto other projects (wxPython). * - * Gregory P. Smith is once again the maintainer. + * Gregory P. Smith was once again the maintainer. + * + * Since January 2008, new maintainer is Jesus Cea . + * Jesus Cea licenses this code to PSF under a Contributor Agreement. * * Use the pybsddb-users at lists.sf.net mailing list for all questions. * Things can change faster than the header of this file is updated. This @@ -92,7 +95,7 @@ #include "bsddb.h" #undef COMPILING_BSDDB_C -static char *svn_id = "$Id$"; +static char *rcs_id = "$Id$"; /* --------------------------------------------------------------------- */ /* Various macro definitions */ @@ -101,6 +104,27 @@ typedef int Py_ssize_t; #endif +#if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */ +/* This code now uses PyBytes* API function names instead of PyString*. + * These #defines map to their equivalent on earlier python versions. */ +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#define PyBytes_FromString PyString_FromString +#define PyBytes_AsStringAndSize PyString_AsStringAndSize +#define PyBytes_Check PyString_Check +#define PyBytes_GET_SIZE PyString_GET_SIZE +#define PyBytes_AS_STRING PyString_AS_STRING +#endif + +#if (PY_VERSION_HEX >= 0x03000000) +#define NUMBER_Check PyLong_Check +#define NUMBER_AsLong PyLong_AsLong +#define NUMBER_FromLong PyLong_FromLong +#else +#define NUMBER_Check PyInt_Check +#define NUMBER_AsLong PyInt_AsLong +#define NUMBER_FromLong PyInt_FromLong +#endif + #ifdef WITH_THREAD /* These are for when calling Python --> C */ @@ -164,10 +188,8 @@ static PyObject* DBNoServerError; /* DB_NOSERVER */ static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */ static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */ -#if (DBVER >= 33) static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */ static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */ -#endif #if !INCOMPLETE_IS_WARNING static PyObject* DBIncompleteError; /* DB_INCOMPLETE */ @@ -183,6 +205,12 @@ static PyObject* DBNoSuchFileError; /* ENOENT */ static PyObject* DBPermissionsError; /* EPERM */ +#if (DBVER >= 42) +static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */ +#endif + +static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */ + #if (DBVER < 43) #define DB_BUFFER_SMALL ENOMEM #endif @@ -201,7 +229,24 @@ #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */ -static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type; +/* See comment in Python 2.6 "object.h" */ +#ifndef staticforward +#define staticforward static +#endif +#ifndef statichere +#define statichere static +#endif + +staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, + DBLock_Type; +#if (DBVER >= 43) +staticforward PyTypeObject DBSequence_Type; +#endif + +#ifndef Py_TYPE +/* for compatibility with Python 2.5 and earlier */ +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type) #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type) @@ -212,10 +257,77 @@ #define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type) #endif +#if (DBVER < 46) + #define _DBC_close(dbc) dbc->c_close(dbc) + #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b) + #define _DBC_del(dbc,a) dbc->c_del(dbc,a) + #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b) + #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c) + #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d) + #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c) +#else + #define _DBC_close(dbc) dbc->close(dbc) + #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b) + #define _DBC_del(dbc,a) dbc->del(dbc,a) + #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b) + #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c) + #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d) + #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c) +#endif + /* --------------------------------------------------------------------- */ /* Utility macros and functions */ +#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \ + { \ + object->sibling_next=backlink; \ + object->sibling_prev_p=&(backlink); \ + backlink=object; \ + if (object->sibling_next) { \ + object->sibling_next->sibling_prev_p=&(object->sibling_next); \ + } \ + } + +#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \ + { \ + if (object->sibling_next) { \ + object->sibling_next->sibling_prev_p=object->sibling_prev_p; \ + } \ + *(object->sibling_prev_p)=object->sibling_next; \ + } + +#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \ + { \ + if (object->sibling_next) { \ + object->sibling_next->sibling_prev_p=object->sibling_prev_p; \ + } \ + if (object->sibling_prev_p) { \ + *(object->sibling_prev_p)=object->sibling_next; \ + } \ + } + +#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \ + { \ + object->sibling_next_txn=backlink; \ + object->sibling_prev_p_txn=&(backlink); \ + backlink=object; \ + if (object->sibling_next_txn) { \ + object->sibling_next_txn->sibling_prev_p_txn= \ + &(object->sibling_next_txn); \ + } \ + } + +#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \ + { \ + if (object->sibling_next_txn) { \ + object->sibling_next_txn->sibling_prev_p_txn= \ + object->sibling_prev_p_txn; \ + } \ + *(object->sibling_prev_p_txn)=object->sibling_next_txn; \ + } + + #define RETURN_IF_ERR() \ if (makeDBError(err)) { \ return NULL; \ @@ -227,8 +339,10 @@ if ((nonNull) == NULL) { \ PyObject *errTuple = NULL; \ errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \ - PyErr_SetObject((pyErrObj), errTuple); \ - Py_DECREF(errTuple); \ + if (errTuple) { \ + PyErr_SetObject((pyErrObj), errTuple); \ + Py_DECREF(errTuple); \ + } \ return NULL; \ } @@ -251,6 +365,9 @@ #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt))) +#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \ + dbt.data != NULL) { free(dbt.data); dbt.data = NULL; } + static int makeDBError(int err); @@ -258,104 +375,34 @@ /* Return the access method type of the DBObject */ static int _DB_get_type(DBObject* self) { -#if (DBVER >= 33) DBTYPE type; int err; + err = self->db->get_type(self->db, &type); if (makeDBError(err)) { return -1; } return type; -#else - return self->db->get_type(self->db); -#endif -} - - -/* Handy function to free a DBT and any self-allocated data within. - To be used on self created DBTs. The make_dbt and make_key_dbt - functions have their own free routines that do more that this. */ -static void free_dbt(DBT *dbt) -{ - if ((dbt->flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && dbt->data != NULL) { - free(dbt->data); - dbt->data = NULL; - } -} - - -/* Cleanup a Python buffer API view created by make_dbt() */ -static void free_buf_view(PyObject *obj, Py_buffer *view) -{ - if (view) { - PyBuffer_Release(view); - PyMem_Free(view); - } -} - - -/* Cleanup a DBT and an associated Python buffer API view - created by make_key_dbt() */ -#define FREE_DBT_VIEW(dbt, obj, view) \ - do { \ - free_dbt(&(dbt)); \ - free_buf_view((obj), (view)); \ - } while(0); - - -static Py_buffer * _malloc_view(PyObject *obj) -{ - Py_buffer *view; - - if (!(view = PyMem_Malloc(sizeof(Py_buffer)))) { - PyErr_SetString(PyExc_MemoryError, - "Py_buffer malloc failed"); - return NULL; - } - - if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE)) - return NULL; - - if (view->ndim > 1) { - PyErr_SetString(PyExc_BufferError, - "buffers must be single dimension"); - PyBuffer_Release(view); - PyMem_Free(view); - return NULL; - } - return view; } /* Create a DBT structure (containing key and data values) from Python - strings. Returns >= 1 on success, 0 on an error. The returned_view_p - may be filled with a newly allocated Py_buffer view on success. - The caller MUST call free_buf_view() on any returned Py_buffer. */ -static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p) -{ - Py_buffer *view; - - /* simple way to ensure the caller can detect if we've returned a - new buffer view or not: require their pointer to start out NULL. */ - assert(*returned_view_p == NULL); - + strings. Returns 1 on success, 0 on an error. */ +static int make_dbt(PyObject* obj, DBT* dbt) +{ CLEAR_DBT(*dbt); if (obj == Py_None) { /* no need to do anything, the structure has already been zeroed */ - return 1; } - if (!PyObject_CheckBuffer(obj)) { + else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) { PyErr_SetString(PyExc_TypeError, - "Data values must support the buffer API or be None."); +#if (PY_VERSION_HEX < 0x03000000) + "Data values must be of type string or None."); +#else + "Data values must be of type bytes or None."); +#endif return 0; } - - if ( !(view = _malloc_view(obj)) ) - return 0; - - dbt->data = view->buf; - dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t); - *returned_view_p = view; return 1; } @@ -363,19 +410,12 @@ /* Recno and Queue DBs can have integer keys. This function figures out what's been given, verifies that it's allowed, and then makes the DBT. - Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all - returned DBT and Py_buffer values when done. */ + Caller MUST call FREE_DBT(key) when done. */ static int -make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags, - Py_buffer** returned_view_p) +make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags) { db_recno_t recno; int type; - Py_buffer *view; - - /* simple way to ensure the caller can detect if we've returned a - new buffer view or not: require their pointer to start out NULL. */ - assert(*returned_view_p == NULL); CLEAR_DBT(*key); if (keyobj == Py_None) { @@ -391,73 +431,76 @@ /* no need to do anything, the structure has already been zeroed */ } - else if (PyLong_Check(keyobj)) { + else if (PyBytes_Check(keyobj)) { /* verify access method type */ type = _DB_get_type(self); if (type == -1) return 0; - if (type == DB_BTREE && pflags != NULL) { - /* if BTREE then an Integer key is allowed with the - * DB_SET_RECNO flag */ - *pflags |= DB_SET_RECNO; - } - else if (type != DB_RECNO && type != DB_QUEUE) { + if (type == DB_RECNO || type == DB_QUEUE) { PyErr_SetString( PyExc_TypeError, - "Integer keys only allowed for Recno and Queue DB's"); +#if (PY_VERSION_HEX < 0x03000000) + "String keys not allowed for Recno and Queue DB's"); +#else + "Bytes keys not allowed for Recno and Queue DB's"); +#endif return 0; } - /* Make a key out of the requested recno, use allocated space so DB - * will be able to realloc room for the real key if needed. */ - recno = PyLong_AS_LONG(keyobj); - key->data = malloc(sizeof(db_recno_t)); + /* + * NOTE(gps): I don't like doing a data copy here, it seems + * wasteful. But without a clean way to tell FREE_DBT if it + * should free key->data or not we have to. Other places in + * the code check for DB_THREAD and forceably set DBT_MALLOC + * when we otherwise would leave flags 0 to indicate that. + */ + key->data = malloc(PyBytes_GET_SIZE(keyobj)); if (key->data == NULL) { PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); return 0; } - key->ulen = key->size = sizeof(db_recno_t); - memcpy(key->data, &recno, sizeof(db_recno_t)); + memcpy(key->data, PyBytes_AS_STRING(keyobj), + PyBytes_GET_SIZE(keyobj)); key->flags = DB_DBT_REALLOC; + key->size = PyBytes_GET_SIZE(keyobj); } - else if (PyObject_CheckBuffer(keyobj)) { + else if (NUMBER_Check(keyobj)) { /* verify access method type */ type = _DB_get_type(self); if (type == -1) return 0; - if (type == DB_RECNO || type == DB_QUEUE) { + if (type == DB_BTREE && pflags != NULL) { + /* if BTREE then an Integer key is allowed with the + * DB_SET_RECNO flag */ + *pflags |= DB_SET_RECNO; + } + else if (type != DB_RECNO && type != DB_QUEUE) { PyErr_SetString( PyExc_TypeError, - "Non-integer keys not allowed for Recno and Queue DB's"); + "Integer keys only allowed for Recno and Queue DB's"); return 0; } - if ( !(view = _malloc_view(keyobj)) ) - return 0; - - /* - * NOTE(gps): I don't like doing a data copy here, it seems - * wasteful. But without a clean way to tell FREE_DBT if it - * should free key->data or not we have to. Other places in - * the code check for DB_THREAD and forceably set DBT_MALLOC - * when we otherwise would leave flags 0 to indicate that. - */ - key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t); - key->data = malloc(key->size); + /* Make a key out of the requested recno, use allocated space so DB + * will be able to realloc room for the real key if needed. */ + recno = NUMBER_AsLong(keyobj); + key->data = malloc(sizeof(db_recno_t)); if (key->data == NULL) { PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); - key->size = 0; return 0; } - memcpy(key->data, view->buf, key->size); + key->ulen = key->size = sizeof(db_recno_t); + memcpy(key->data, &recno, sizeof(db_recno_t)); key->flags = DB_DBT_REALLOC; - *returned_view_p = view; } - else { PyErr_Format(PyExc_TypeError, - "buffer or int object expected for key, %s found", +#if (PY_VERSION_HEX < 0x03000000) + "String or Integer object expected for key, %s found", +#else + "Bytes or Integer object expected for key, %s found", +#endif Py_TYPE(keyobj)->tp_name); return 0; } @@ -518,6 +561,102 @@ } +/* +** We need these functions because some results +** are undefined if pointer is NULL. Some other +** give None instead of "". +** +** This functions are static and will be +** -I hope- inlined. +*/ +static const char *DummyString = "This string is a simple placeholder"; +static PyObject *Build_PyString(const char *p,int s) +{ + if (!p) { + p=DummyString; + assert(s==0); + } + return PyBytes_FromStringAndSize(p,s); +} + +static PyObject *BuildValue_S(const void *p,int s) +{ + if (!p) { + p=DummyString; + assert(s==0); + } + return PyBytes_FromStringAndSize(p, s); +} + +static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2) +{ +PyObject *a, *b, *r; + + if (!p1) { + p1=DummyString; + assert(s1==0); + } + if (!p2) { + p2=DummyString; + assert(s2==0); + } + + if (!(a = PyBytes_FromStringAndSize(p1, s1))) { + return NULL; + } + if (!(b = PyBytes_FromStringAndSize(p2, s2))) { + Py_DECREF(a); + return NULL; + } + +#if (PY_VERSION_HEX >= 0x02040000) + r = PyTuple_Pack(2, a, b) ; +#else + r = Py_BuildValue("OO", a, b); +#endif + Py_DECREF(a); + Py_DECREF(b); + return r; +} + +static PyObject *BuildValue_IS(int i,const void *p,int s) +{ + PyObject *a, *r; + + if (!p) { + p=DummyString; + assert(s==0); + } + + if (!(a = PyBytes_FromStringAndSize(p, s))) { + return NULL; + } + + r = Py_BuildValue("iO", i, a); + Py_DECREF(a); + return r; +} + +static PyObject *BuildValue_LS(long l,const void *p,int s) +{ + PyObject *a, *r; + + if (!p) { + p=DummyString; + assert(s==0); + } + + if (!(a = PyBytes_FromStringAndSize(p, s))) { + return NULL; + } + + r = Py_BuildValue("lO", l, a); + Py_DECREF(a); + return r; +} + + + /* make a nice exception object to raise for errors. */ static int makeDBError(int err) { @@ -542,7 +681,7 @@ strncat(errTxt, _db_errmsg, bytes_left); } _db_errmsg[0] = 0; - exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1); + exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt); #else /* do an exception instead */ errObj = DBIncompleteError; @@ -561,10 +700,8 @@ case DB_NOSERVER: errObj = DBNoServerError; break; case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break; case DB_NOSERVER_ID: errObj = DBNoServerIDError; break; -#if (DBVER >= 33) case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break; case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break; -#endif case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break; #if (DBVER >= 43) @@ -580,6 +717,12 @@ case ENOENT: errObj = DBNoSuchFileError; break; case EPERM : errObj = DBPermissionsError; break; +#if (DBVER >= 42) + case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break; +#endif + + case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break; + default: errObj = DBError; break; } @@ -594,9 +737,13 @@ } _db_errmsg[0] = 0; - errTuple = Py_BuildValue("(is)", err, errTxt); + errTuple = Py_BuildValue("(is)", err, errTxt); + if (errTuple == NULL) { + Py_DECREF(errObj); + return !0; + } PyErr_SetObject(errObj, errTuple); - Py_DECREF(errTuple); + Py_DECREF(errTuple); } return ((errObj != NULL) || exceptionRaised); @@ -683,16 +830,11 @@ flags |= extra_flags; CLEAR_DBT(key); CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - key.flags = DB_DBT_MALLOC; - } if (!add_partial_dbt(&data, dlen, doff)) return NULL; MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags); + err = _DBC_get(self->dbc, &key, &data, flags); MYDB_END_ALLOW_THREADS; if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) @@ -713,21 +855,15 @@ case DB_RECNO: case DB_QUEUE: - retval = Py_BuildValue("iy#", *((db_recno_t*)key.data), - data.data, data.size); + retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); break; case DB_HASH: case DB_BTREE: default: - retval = Py_BuildValue("y#y#", key.data, key.size, - data.data, data.size); + retval = BuildValue_SS(key.data, key.size, data.data, data.size); break; } } - if (!err) { - free_dbt(&key); - free_dbt(&data); - } return retval; } @@ -735,7 +871,7 @@ /* add an integer to a dictionary using the given name as a key */ static void _addIntToDict(PyObject* dict, char *name, int value) { - PyObject* v = PyLong_FromLong((long) value); + PyObject* v = NUMBER_FromLong((long) value); if (!v || PyDict_SetItemString(dict, name, v)) PyErr_Clear(); @@ -747,12 +883,12 @@ { PyObject* v; /* if the value fits in regular int, use that. */ -#ifdef HAVE_LONG_LONG +#ifdef PY_LONG_LONG if (sizeof(time_t) > sizeof(long)) v = PyLong_FromLongLong((PY_LONG_LONG) value); else #endif - v = PyLong_FromLong((long) value); + v = NUMBER_FromLong((long) value); if (!v || PyDict_SetItemString(dict, name, v)) PyErr_Clear(); @@ -771,7 +907,14 @@ } #endif +static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value) +{ + PyObject *v = Py_BuildValue("(ll)",value.file,value.offset); + if (!v || PyDict_SetItemString(dict, name, v)) + PyErr_Clear(); + Py_XDECREF(v); +} /* --------------------------------------------------------------------- */ /* Allocators and deallocators */ @@ -791,11 +934,16 @@ self->flags = 0; self->setflags = 0; self->myenvobj = NULL; -#if (DBVER >= 33) + self->db = NULL; + self->children_cursors = NULL; +#if (DBVER >=43) + self->children_sequences = NULL; +#endif self->associateCallback = NULL; self->btCompareCallback = NULL; self->primaryDBType = 0; -#endif + Py_INCREF(Py_None); + self->private_obj = Py_None; self->in_weakreflist = NULL; /* keep a reference to our python DBEnv object */ @@ -803,7 +951,14 @@ Py_INCREF(arg); self->myenvobj = arg; db_env = arg->db_env; + INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self); + } else { + self->sibling_prev_p=NULL; + self->sibling_next=NULL; } + self->txn=NULL; + self->sibling_prev_p_txn=NULL; + self->sibling_next_txn=NULL; if (self->myenvobj) self->moduleFlags = self->myenvobj->moduleFlags; @@ -815,9 +970,7 @@ err = db_create(&self->db, db_env, flags); if (self->db != NULL) { self->db->set_errcall(self->db, _db_errorCallback); -#if (DBVER >= 33) self->db->app_private = (void*)self; -#endif } MYDB_END_ALLOW_THREADS; /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs @@ -828,32 +981,24 @@ Py_DECREF(self->myenvobj); self->myenvobj = NULL; } - PyObject_Del(self); + Py_DECREF(self); self = NULL; } return self; } +/* Forward declaration */ +static PyObject *DB_close_internal(DBObject* self, int flags); + static void DB_dealloc(DBObject* self) { + PyObject *dummy; + if (self->db != NULL) { - /* avoid closing a DB when its DBEnv has been closed out from under - * it */ - if (!self->myenvobj || - (self->myenvobj && self->myenvobj->db_env)) - { - MYDB_BEGIN_ALLOW_THREADS; - self->db->close(self->db, 0); - MYDB_END_ALLOW_THREADS; - } else { - PyErr_WarnEx(PyExc_RuntimeWarning, - "DB could not be closed in destructor:" - " DBEnv already closed", - 1); - } - self->db = NULL; + dummy=DB_close_internal(self,0); + Py_XDECREF(dummy); } if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); @@ -862,7 +1007,6 @@ Py_DECREF(self->myenvobj); self->myenvobj = NULL; } -#if (DBVER >= 33) if (self->associateCallback != NULL) { Py_DECREF(self->associateCallback); self->associateCallback = NULL; @@ -871,13 +1015,12 @@ Py_DECREF(self->btCompareCallback); self->btCompareCallback = NULL; } -#endif + Py_DECREF(self->private_obj); PyObject_Del(self); } - static DBCursorObject* -newDBCursorObject(DBC* dbc, DBObject* db) +newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db) { DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type); if (self == NULL) @@ -885,40 +1028,37 @@ self->dbc = dbc; self->mydb = db; + + INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self); + if (txn && ((PyObject *)txn!=Py_None)) { + INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self); + self->txn=txn; + } else { + self->txn=NULL; + } + self->in_weakreflist = NULL; Py_INCREF(self->mydb); return self; } +/* Forward declaration */ +static PyObject *DBC_close_internal(DBCursorObject* self); + static void DBCursor_dealloc(DBCursorObject* self) { - int err; + PyObject *dummy; + if (self->dbc != NULL) { + dummy=DBC_close_internal(self); + Py_XDECREF(dummy); + } if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); } - - if (self->dbc != NULL) { - /* If the underlying database has been closed, we don't - need to do anything. If the environment has been closed - we need to leak, as BerkeleyDB will crash trying to access - the environment. There was an exception when the - user closed the environment even though there still was - a database open. */ - if (self->mydb->db && self->mydb->myenvobj && - !self->mydb->myenvobj->closed) - /* test for: open db + no environment or non-closed environment */ - if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj && - !self->mydb->myenvobj->closed))) { - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_close(self->dbc); - MYDB_END_ALLOW_THREADS; - } - self->dbc = NULL; - } - Py_XDECREF( self->mydb ); + Py_DECREF(self->mydb); PyObject_Del(self); } @@ -935,88 +1075,134 @@ self->flags = flags; self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE; self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE; + self->children_dbs = NULL; + self->children_txns = NULL; + Py_INCREF(Py_None); + self->private_obj = Py_None; + Py_INCREF(Py_None); + self->rep_transport = Py_None; self->in_weakreflist = NULL; + self->event_notifyCallback = NULL; MYDB_BEGIN_ALLOW_THREADS; err = db_env_create(&self->db_env, flags); MYDB_END_ALLOW_THREADS; if (makeDBError(err)) { - PyObject_Del(self); + Py_DECREF(self); self = NULL; } else { self->db_env->set_errcall(self->db_env, _db_errorCallback); + self->db_env->app_private = self; } return self; } +/* Forward declaration */ +static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags); static void DBEnv_dealloc(DBEnvObject* self) { - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *) self); - } + PyObject *dummy; if (self->db_env && !self->closed) { - MYDB_BEGIN_ALLOW_THREADS; - self->db_env->close(self->db_env, 0); - MYDB_END_ALLOW_THREADS; + dummy=DBEnv_close_internal(self,0); + Py_XDECREF(dummy); + } + + Py_XDECREF(self->event_notifyCallback); + self->event_notifyCallback = NULL; + + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *) self); } + Py_DECREF(self->private_obj); + Py_DECREF(self->rep_transport); PyObject_Del(self); } static DBTxnObject* -newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags) +newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags) { int err; + DB_TXN *parent_txn = NULL; + DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type); if (self == NULL) return NULL; - Py_INCREF(myenv); - self->env = (PyObject*)myenv; + self->in_weakreflist = NULL; + self->children_txns = NULL; + self->children_dbs = NULL; + self->children_cursors = NULL; + self->children_sequences = NULL; + self->flag_prepare = 0; + self->parent_txn = NULL; + self->env = NULL; - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags); -#else - err = txn_begin(myenv->db_env, parent, &(self->txn), flags); -#endif - MYDB_END_ALLOW_THREADS; - if (makeDBError(err)) { - Py_DECREF(self->env); - PyObject_Del(self); - self = NULL; + if (parent && ((PyObject *)parent!=Py_None)) { + parent_txn = parent->txn; } + + if (txn) { + self->txn = txn; + } else { + MYDB_BEGIN_ALLOW_THREADS; + err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags); + MYDB_END_ALLOW_THREADS; + + if (makeDBError(err)) { + Py_DECREF(self); + return NULL; + } + } + + /* Can't use 'parent' because could be 'parent==Py_None' */ + if (parent_txn) { + self->parent_txn = parent; + Py_INCREF(parent); + self->env = NULL; + INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self); + } else { + self->parent_txn = NULL; + Py_INCREF(myenv); + self->env = myenv; + INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self); + } + return self; } +/* Forward declaration */ +static PyObject * +DBTxn_abort_discard_internal(DBTxnObject* self, int discard); static void DBTxn_dealloc(DBTxnObject* self) { + PyObject *dummy; + + if (self->txn) { + int flag_prepare = self->flag_prepare; + dummy=DBTxn_abort_discard_internal(self,0); + Py_XDECREF(dummy); + if (!flag_prepare) { + PyErr_Warn(PyExc_RuntimeWarning, + "DBTxn aborted in destructor. No prior commit() or abort()."); + } + } + if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); } - if (self->txn) { - /* it hasn't been finalized, abort it! */ - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - self->txn->abort(self->txn); -#else - txn_abort(self->txn); -#endif - MYDB_END_ALLOW_THREADS; - PyErr_WarnEx(PyExc_RuntimeWarning, - "DBTxn aborted in destructor. " - " No prior commit() or abort().", - 1); + if (self->env) { + Py_DECREF(self->env); + } else { + Py_DECREF(self->parent_txn); } - - Py_DECREF(self->env); PyObject_Del(self); } @@ -1032,15 +1218,11 @@ self->in_weakreflist = NULL; MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock); -#else - err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock); -#endif MYDB_END_ALLOW_THREADS; if (makeDBError(err)) { - PyObject_Del(self); + Py_DECREF(self); self = NULL; } @@ -1070,25 +1252,37 @@ return NULL; Py_INCREF(mydb); self->mydb = mydb; - self->in_weakreflist = NULL; + INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self); + self->txn = NULL; + + self->in_weakreflist = NULL; MYDB_BEGIN_ALLOW_THREADS; err = db_sequence_create(&self->sequence, self->mydb->db, flags); MYDB_END_ALLOW_THREADS; if (makeDBError(err)) { - Py_DECREF(self->mydb); - PyObject_Del(self); + Py_DECREF(self); self = NULL; } return self; } +/* Forward declaration */ +static PyObject +*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close); static void DBSequence_dealloc(DBSequenceObject* self) { + PyObject *dummy; + + if (self->sequence != NULL) { + dummy=DBSequence_close_internal(self,0,0); + Py_XDECREF(dummy); + } + if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); } @@ -1102,16 +1296,17 @@ /* DB methods */ static PyObject* -DB_append(DBObject* self, PyObject* args) +DB_append(DBObject* self, PyObject* args, PyObject* kwargs) { PyObject* txnobj = NULL; PyObject* dataobj; - Py_buffer* data_buf_view = NULL; db_recno_t recno; DBT key, data; DB_TXN *txn = NULL; + static char* kwnames[] = { "data", "txn", NULL }; - if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames, + &dataobj, &txnobj)) return NULL; CHECK_DB_NOT_CLOSED(self); @@ -1124,21 +1319,16 @@ key.ulen = key.size; key.flags = DB_DBT_USERMEM; + if (!make_dbt(dataobj, &data)) return NULL; if (!checkTxnObj(txnobj, &txn)) return NULL; - if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL; - if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) { - free_buf_view(dataobj, data_buf_view); + if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) return NULL; - } - free_buf_view(dataobj, data_buf_view); - return PyLong_FromLong(recno); + return NUMBER_FromLong(recno); } -#if (DBVER >= 33) - static int _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData, DBT* secKey) @@ -1155,11 +1345,9 @@ MYDB_BEGIN_BLOCK_THREADS; if (type == DB_RECNO || type == DB_QUEUE) - args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data), - priData->data, priData->size); + args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size); else - args = Py_BuildValue("(y#y#)", priKey->data, priKey->size, - priData->data, priData->size); + args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size); if (args != NULL) { result = PyEval_CallObject(callback, args); } @@ -1169,19 +1357,15 @@ else if (result == Py_None) { retval = DB_DONOTINDEX; } - else if (PyLong_Check(result)) { - retval = PyLong_AsLong(result); + else if (NUMBER_Check(result)) { + retval = NUMBER_AsLong(result); } - else if (PyByteArray_Check(result) || PyBytes_Check(result)) { + else if (PyBytes_Check(result)) { char* data; Py_ssize_t size; CLEAR_DBT(*secKey); - size = Py_SIZE(result); - if (PyByteArray_Check(result)) - data = PyByteArray_AS_STRING(result); - else - data = PyBytes_AS_STRING(result); + PyBytes_AsStringAndSize(result, &data, &size); secKey->flags = DB_DBT_APPMALLOC; /* DB will free */ secKey->data = malloc(size); /* TODO, check this */ if (secKey->data) { @@ -1198,7 +1382,7 @@ else { PyErr_SetString( PyExc_TypeError, - "DB associate callback should return DB_DONOTINDEX or bytes."); + "DB associate callback should return DB_DONOTINDEX or string."); PyErr_Print(); } @@ -1300,25 +1484,51 @@ } -#endif - - static PyObject* -DB_close(DBObject* self, PyObject* args) +DB_close_internal(DBObject* self, int flags) { - int err, flags=0; - if (!PyArg_ParseTuple(args,"|i:close", &flags)) - return NULL; + PyObject *dummy; + int err; + if (self->db != NULL) { - if (self->myenvobj) - CHECK_ENV_NOT_CLOSED(self->myenvobj); - err = self->db->close(self->db, flags); - self->db = NULL; - RETURN_IF_ERR(); + /* Can be NULL if db is not in an environment */ + EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self); + + if (self->txn) { + EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); + self->txn=NULL; + } + + while(self->children_cursors) { + dummy=DBC_close_internal(self->children_cursors); + Py_XDECREF(dummy); + } + +#if (DBVER >= 43) + while(self->children_sequences) { + dummy=DBSequence_close_internal(self->children_sequences,0,0); + Py_XDECREF(dummy); + } +#endif + + MYDB_BEGIN_ALLOW_THREADS; + err = self->db->close(self->db, flags); + MYDB_END_ALLOW_THREADS; + self->db = NULL; + RETURN_IF_ERR(); } RETURN_NONE(); } +static PyObject* +DB_close(DBObject* self, PyObject* args) +{ + int flags=0; + if (!PyArg_ParseTuple(args,"|i:close", &flags)) + return NULL; + return DB_close_internal(self,flags); +} + static PyObject* _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag) @@ -1349,7 +1559,7 @@ CLEAR_DBT(key); CLEAR_DBT(data); if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ + /* Tell Berkeley DB to malloc the return value (thread safe) */ data.flags = DB_DBT_MALLOC; key.flags = DB_DBT_MALLOC; } @@ -1365,10 +1575,9 @@ retval = Py_None; } else if (!err) { - retval = Py_BuildValue("y#y#", key.data, key.size, data.data, - data.size); - free_dbt(&key); - free_dbt(&data); + retval = BuildValue_SS(key.data, key.size, data.data, data.size); + FREE_DBT(key); + FREE_DBT(data); } RETURN_IF_ERR(); @@ -1409,7 +1618,7 @@ err = self->db->cursor(self->db, txn, &dbc, flags); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); - return (PyObject*) newDBCursorObject(dbc, self); + return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self); } @@ -1419,7 +1628,6 @@ PyObject* txnobj = NULL; int flags = 0; PyObject* keyobj; - Py_buffer* key_buf_view = NULL; DBT key; DB_TXN *txn = NULL; static char* kwnames[] = { "key", "txn", "flags", NULL }; @@ -1428,37 +1636,35 @@ &keyobj, &txnobj, &flags)) return NULL; CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL; if (!checkTxnObj(txnobj, &txn)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } if (-1 == _DB_delete(self, txn, &key, 0)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); RETURN_NONE(); } static PyObject* -DB_fd(DBObject* self, PyObject* args) +DB_fd(DBObject* self) { int err, the_fd; - if (!PyArg_ParseTuple(args,":fd")) - return NULL; CHECK_DB_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; err = self->db->fd(self->db, &the_fd); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); - return PyLong_FromLong(the_fd); + return NUMBER_FromLong(the_fd); } @@ -1470,7 +1676,6 @@ PyObject* keyobj; PyObject* dfltobj = NULL; PyObject* retval = NULL; - Py_buffer* key_buf_view = NULL; int dlen = -1; int doff = -1; DBT key, data; @@ -1484,20 +1689,20 @@ return NULL; CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, &flags)) return NULL; if (!checkTxnObj(txnobj, &txn)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } CLEAR_DBT(data); if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ + /* Tell Berkeley DB to malloc the return value (thread safe) */ data.flags = DB_DBT_MALLOC; } if (!add_partial_dbt(&data, dlen, doff)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } @@ -1518,19 +1723,17 @@ } else if (!err) { if (flags & DB_SET_RECNO) /* return both key and data */ - retval = Py_BuildValue("y#y#", key.data, key.size, data.data, - data.size); + retval = BuildValue_SS(key.data, key.size, data.data, data.size); else /* return just the data */ - retval = PyBytes_FromStringAndSize((char*)data.data, data.size); - free_dbt(&data); + retval = Build_PyString(data.data, data.size); + FREE_DBT(data); } - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); RETURN_IF_ERR(); return retval; } -#if (DBVER >= 33) static PyObject* DB_pget(DBObject* self, PyObject* args, PyObject* kwargs) { @@ -1539,7 +1742,6 @@ PyObject* keyobj; PyObject* dfltobj = NULL; PyObject* retval = NULL; - Py_buffer* key_buf_view = NULL; int dlen = -1; int doff = -1; DBT key, pkey, data; @@ -1553,26 +1755,26 @@ return NULL; CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, &flags)) return NULL; if (!checkTxnObj(txnobj, &txn)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } CLEAR_DBT(data); if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ + /* Tell Berkeley DB to malloc the return value (thread safe) */ data.flags = DB_DBT_MALLOC; } if (!add_partial_dbt(&data, dlen, doff)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } CLEAR_DBT(pkey); pkey.flags = DB_DBT_MALLOC; - + MYDB_BEGIN_ALLOW_THREADS; err = self->db->pget(self->db, txn, &key, &pkey, &data, flags); MYDB_END_ALLOW_THREADS; @@ -1591,22 +1793,22 @@ else if (!err) { PyObject *pkeyObj; PyObject *dataObj; - dataObj = PyBytes_FromStringAndSize(data.data, data.size); + dataObj = Build_PyString(data.data, data.size); if (self->primaryDBType == DB_RECNO || self->primaryDBType == DB_QUEUE) - pkeyObj = PyLong_FromLong(*(int *)pkey.data); + pkeyObj = NUMBER_FromLong(*(int *)pkey.data); else - pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size); + pkeyObj = Build_PyString(pkey.data, pkey.size); if (flags & DB_SET_RECNO) /* return key , pkey and data */ { PyObject *keyObj; int type = _DB_get_type(self); if (type == DB_RECNO || type == DB_QUEUE) - keyObj = PyLong_FromLong(*(int *)key.data); + keyObj = NUMBER_FromLong(*(int *)key.data); else - keyObj = PyBytes_FromStringAndSize(key.data, key.size); + keyObj = Build_PyString(key.data, key.size); #if (PY_VERSION_HEX >= 0x02040000) retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); #else @@ -1624,15 +1826,14 @@ } Py_DECREF(dataObj); Py_DECREF(pkeyObj); - free_dbt(&pkey); - free_dbt(&data); + FREE_DBT(pkey); + FREE_DBT(data); } - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); RETURN_IF_ERR(); return retval; } -#endif /* Return size of entry */ @@ -1643,7 +1844,6 @@ PyObject* txnobj = NULL; PyObject* keyobj; PyObject* retval = NULL; - Py_buffer* key_buf_view = NULL; DBT key, data; DB_TXN *txn = NULL; static char* kwnames[] = { "key", "txn", NULL }; @@ -1652,10 +1852,10 @@ &keyobj, &txnobj)) return NULL; CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, &flags)) return NULL; if (!checkTxnObj(txnobj, &txn)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } CLEAR_DBT(data); @@ -1668,12 +1868,12 @@ err = self->db->get(self->db, txn, &key, &data, flags); MYDB_END_ALLOW_THREADS; if (err == DB_BUFFER_SMALL) { - retval = PyLong_FromLong((long)data.size); + retval = NUMBER_FromLong((long)data.size); err = 0; } - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_dbt(&data); + FREE_DBT(key); + FREE_DBT(data); RETURN_IF_ERR(); return retval; } @@ -1687,25 +1887,22 @@ PyObject* keyobj; PyObject* dataobj; PyObject* retval = NULL; - Py_buffer* data_buf_view = NULL; - Py_buffer* key_buf_view = NULL; DBT key, data; void *orig_data; DB_TXN *txn = NULL; static char* kwnames[] = { "key", "data", "txn", "flags", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames, &keyobj, &dataobj, &txnobj, &flags)) return NULL; CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL; - if ( !checkTxnObj(txnobj, &txn) || - !make_dbt(dataobj, &data, &data_buf_view) ) + if ( !make_dbt(dataobj, &data) || + !checkTxnObj(txnobj, &txn) ) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } @@ -1713,7 +1910,7 @@ orig_data = data.data; if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ + /* Tell Berkeley DB to malloc the return value (thread safe) */ /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */ data.flags = DB_DBT_MALLOC; } @@ -1722,8 +1919,6 @@ err = self->db->get(self->db, txn, &key, &data, flags); MYDB_END_ALLOW_THREADS; - free_buf_view(dataobj, data_buf_view); - if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && self->moduleFlags.getReturnsNone) { err = 0; @@ -1732,61 +1927,47 @@ } else if (!err) { /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */ - /* XXX(gps) I think not: buffer API input vs. bytes object output. */ - /* XXX(guido) But what if the input is PyString? */ - retval = PyBytes_FromStringAndSize((char*)data.data, data.size); + retval = Build_PyString(data.data, data.size); /* Even though the flags require DB_DBT_MALLOC, data is not always allocated. 4.4: allocated, 4.5: *not* allocated. :-( */ if (data.data != orig_data) - free_dbt(&data); + FREE_DBT(data); } - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); RETURN_IF_ERR(); return retval; } static PyObject* -DB_get_byteswapped(DBObject* self, PyObject* args) +DB_get_byteswapped(DBObject* self) { -#if (DBVER >= 33) int err = 0; -#endif int retval = -1; - if (!PyArg_ParseTuple(args,":get_byteswapped")) - return NULL; CHECK_DB_NOT_CLOSED(self); -#if (DBVER >= 33) MYDB_BEGIN_ALLOW_THREADS; err = self->db->get_byteswapped(self->db, &retval); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); -#else - MYDB_BEGIN_ALLOW_THREADS; - retval = self->db->get_byteswapped(self->db); - MYDB_END_ALLOW_THREADS; -#endif - return PyLong_FromLong(retval); + return NUMBER_FromLong(retval); } static PyObject* -DB_get_type(DBObject* self, PyObject* args) +DB_get_type(DBObject* self) { int type; - if (!PyArg_ParseTuple(args,":get_type")) - return NULL; CHECK_DB_NOT_CLOSED(self); type = _DB_get_type(self); if (type == -1) return NULL; - return PyLong_FromLong(type); + return NUMBER_FromLong(type); } @@ -1845,7 +2026,7 @@ but does not hold python references to them or prevent them from being closed prematurely. This can cause python to crash when things are done in the wrong order. */ - return (PyObject*) newDBCursorObject(dbc, self); + return (PyObject*) newDBCursorObject(dbc, NULL, self); } @@ -1855,7 +2036,6 @@ int err, flags=0; PyObject* txnobj = NULL; PyObject* keyobj; - Py_buffer* key_buf_view = NULL; DBT key; DB_TXN *txn = NULL; DB_KEY_RANGE range; @@ -1865,18 +2045,16 @@ &keyobj, &txnobj, &flags)) return NULL; CHECK_DB_NOT_CLOSED(self); - if (!checkTxnObj(txnobj, &txn)) - return NULL; - if (!make_dbt(keyobj, &key, &key_buf_view)) + if (!make_dbt(keyobj, &key)) /* BTree only, don't need to allow for an int key */ return NULL; + if (!checkTxnObj(txnobj, &txn)) + return NULL; MYDB_BEGIN_ALLOW_THREADS; err = self->db->key_range(self->db, txn, &key, &range, flags); MYDB_END_ALLOW_THREADS; - free_buf_view(keyobj, key_buf_view); - RETURN_IF_ERR(); return Py_BuildValue("ddd", range.less, range.equal, range.greater); } @@ -1940,11 +2118,24 @@ if (NULL == self->db) { PyObject *t = Py_BuildValue("(is)", 0, "Cannot call open() twice for DB object"); - PyErr_SetObject(DBError, t); - Py_DECREF(t); + if (t) { + PyErr_SetObject(DBError, t); + Py_DECREF(t); + } return NULL; } +#if (DBVER >= 41) + if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */ + INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self); + self->txn=(DBTxnObject *)txnobj; + } else { + self->txn=NULL; + } +#else + self->txn=NULL; +#endif + MYDB_BEGIN_ALLOW_THREADS; #if (DBVER >= 41) err = self->db->open(self->db, txn, filename, dbname, type, flags, mode); @@ -1953,8 +2144,10 @@ #endif MYDB_END_ALLOW_THREADS; if (makeDBError(err)) { - self->db->close(self->db, 0); - self->db = NULL; + PyObject *dummy; + + dummy=DB_close_internal(self,0); + Py_XDECREF(dummy); return NULL; } @@ -1963,6 +2156,7 @@ #endif self->flags = flags; + RETURN_NONE(); } @@ -1974,9 +2168,7 @@ PyObject* txnobj = NULL; int dlen = -1; int doff = -1; - PyObject *keyobj, *dataobj, *retval; - Py_buffer *data_buf_view = NULL; - Py_buffer *key_buf_view = NULL; + PyObject* keyobj, *dataobj, *retval; DBT key, data; DB_TXN *txn = NULL; static char* kwnames[] = { "key", "data", "txn", "flags", "dlen", @@ -1987,31 +2179,28 @@ return NULL; CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL; - if ( !make_dbt(dataobj, &data, &data_buf_view) || + if ( !make_dbt(dataobj, &data) || !add_partial_dbt(&data, dlen, doff) || !checkTxnObj(txnobj, &txn) ) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); return NULL; } if (-1 == _DB_put(self, txn, &key, &data, flags)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); return NULL; } if (flags & DB_APPEND) - retval = PyLong_FromLong(*((db_recno_t*)key.data)); + retval = NUMBER_FromLong(*((db_recno_t*)key.data)); else { retval = Py_None; Py_INCREF(retval); } - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); return retval; } @@ -2030,7 +2219,12 @@ return NULL; CHECK_DB_NOT_CLOSED(self); + EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self); + + MYDB_BEGIN_ALLOW_THREADS; err = self->db->remove(self->db, filename, database, flags); + MYDB_END_ALLOW_THREADS; + self->db = NULL; RETURN_IF_ERR(); RETURN_NONE(); @@ -2060,6 +2254,25 @@ static PyObject* +DB_get_private(DBObject* self) +{ + /* We can give out the private field even if db is closed */ + Py_INCREF(self->private_obj); + return self->private_obj; +} + +static PyObject* +DB_set_private(DBObject* self, PyObject* private_obj) +{ + /* We can set the private field even if db is closed */ + Py_DECREF(self->private_obj); + Py_INCREF(private_obj); + self->private_obj = private_obj; + RETURN_NONE(); +} + + +static PyObject* DB_set_bt_minkey(DBObject* self, PyObject* args) { int err, minkey; @@ -2075,17 +2288,16 @@ RETURN_NONE(); } -#if (DBVER >= 33) -static int +static int _default_cmp(const DBT *leftKey, const DBT *rightKey) { int res; int lsize = leftKey->size, rsize = rightKey->size; - res = memcmp(leftKey->data, rightKey->data, + res = memcmp(leftKey->data, rightKey->data, lsize < rsize ? lsize : rsize); - + if (res == 0) { if (lsize < rsize) { res = -1; @@ -2098,7 +2310,7 @@ } static int -_db_compareCallback(DB* db, +_db_compareCallback(DB* db, const DBT *leftKey, const DBT *rightKey) { @@ -2120,8 +2332,7 @@ } else { MYDB_BEGIN_BLOCK_THREADS; - args = Py_BuildValue("y#y#", leftKey->data, leftKey->size, - rightKey->data, rightKey->size); + args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size); if (args != NULL) { /* XXX(twouters) I highly doubt this INCREF is correct */ Py_INCREF(self); @@ -2131,8 +2342,8 @@ /* we're in a callback within the DB code, we can't raise */ PyErr_Print(); res = _default_cmp(leftKey, rightKey); - } else if (PyLong_Check(result)) { - res = PyLong_AsLong(result); + } else if (NUMBER_Check(result)) { + res = NUMBER_AsLong(result); } else { PyErr_SetString(PyExc_TypeError, "DB_bt_compare callback MUST return an int."); @@ -2140,7 +2351,7 @@ PyErr_Print(); res = _default_cmp(leftKey, rightKey); } - + Py_XDECREF(args); Py_XDECREF(result); @@ -2150,15 +2361,11 @@ } static PyObject* -DB_set_bt_compare(DBObject* self, PyObject* args) +DB_set_bt_compare(DBObject* self, PyObject* comparator) { int err; - PyObject *comparator; PyObject *tuple, *result; - if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator)) - return NULL; - CHECK_DB_NOT_CLOSED(self); if (!PyCallable_Check(comparator)) { @@ -2166,7 +2373,7 @@ return NULL; } - /* + /* * Perform a test call of the comparator function with two empty * string objects here. verify that it returns an int (0). * err if not. @@ -2176,11 +2383,11 @@ Py_DECREF(tuple); if (result == NULL) return NULL; - if (!PyLong_Check(result)) { + if (!NUMBER_Check(result)) { PyErr_SetString(PyExc_TypeError, "callback MUST return an int"); return NULL; - } else if (PyLong_AsLong(result) != 0) { + } else if (NUMBER_AsLong(result) != 0) { PyErr_SetString(PyExc_TypeError, "callback failed to return 0 on two empty strings"); return NULL; @@ -2215,7 +2422,6 @@ RETURN_IF_ERR(); RETURN_NONE(); } -#endif /* DBVER >= 33 */ static PyObject* @@ -2447,10 +2653,8 @@ MYDB_BEGIN_ALLOW_THREADS; #if (DBVER >= 43) err = self->db->stat(self->db, txn, &sp, flags); -#elif (DBVER >= 33) - err = self->db->stat(self->db, &sp, flags); #else - err = self->db->stat(self->db, &sp, NULL, flags); + err = self->db->stat(self->db, &sp, flags); #endif MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); @@ -2474,6 +2678,9 @@ MAKE_HASH_ENTRY(version); MAKE_HASH_ENTRY(nkeys); MAKE_HASH_ENTRY(ndata); +#if (DBVER >= 46) + MAKE_HASH_ENTRY(pagecnt); +#endif MAKE_HASH_ENTRY(pagesize); #if (DBVER < 41) MAKE_HASH_ENTRY(nelem); @@ -2496,6 +2703,9 @@ MAKE_BT_ENTRY(version); MAKE_BT_ENTRY(nkeys); MAKE_BT_ENTRY(ndata); +#if (DBVER >= 46) + MAKE_BT_ENTRY(pagecnt); +#endif MAKE_BT_ENTRY(pagesize); MAKE_BT_ENTRY(minkey); MAKE_BT_ENTRY(re_len); @@ -2505,6 +2715,9 @@ MAKE_BT_ENTRY(leaf_pg); MAKE_BT_ENTRY(dup_pg); MAKE_BT_ENTRY(over_pg); +#if (DBVER >= 43) + MAKE_BT_ENTRY(empty_pg); +#endif MAKE_BT_ENTRY(free); MAKE_BT_ENTRY(int_pgfree); MAKE_BT_ENTRY(leaf_pgfree); @@ -2518,6 +2731,9 @@ MAKE_QUEUE_ENTRY(nkeys); MAKE_QUEUE_ENTRY(ndata); MAKE_QUEUE_ENTRY(pagesize); +#if (DBVER >= 41) + MAKE_QUEUE_ENTRY(extentsize); +#endif MAKE_QUEUE_ENTRY(pages); MAKE_QUEUE_ENTRY(re_len); MAKE_QUEUE_ENTRY(re_pad); @@ -2561,7 +2777,6 @@ } -#if (DBVER >= 33) static PyObject* DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs) { @@ -2582,9 +2797,8 @@ err = self->db->truncate(self->db, txn, &count, flags); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); - return PyLong_FromLong(count); + return NUMBER_FromLong(count); } -#endif static PyObject* @@ -2632,15 +2846,14 @@ if (outFile) fclose(outFile); - /* DB.verify acts as a DB handle destructor (like close); this was - * documented in BerkeleyDB 4.2 but had the undocumented effect - * of not being safe in prior versions while still requiring an explicit - * DB.close call afterwards. Lets call close for the user to emulate - * the safe 4.2 behaviour. */ -#if (DBVER <= 41) - self->db->close(self->db, 0); -#endif - self->db = NULL; + { /* DB.verify acts as a DB handle destructor (like close) */ + PyObject *error; + + error=DB_close_internal(self,0); + if (error ) { + return error; + } + } RETURN_IF_ERR(); RETURN_NONE(); @@ -2663,7 +2876,7 @@ ++oldValue; self->moduleFlags.getReturnsNone = (flags >= 1); self->moduleFlags.cursorSetReturnsNone = (flags >= 2); - return PyLong_FromLong(oldValue); + return NUMBER_FromLong(oldValue); } #if (DBVER >= 41) @@ -2703,8 +2916,10 @@ if (self->db == NULL) { PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed"); - PyErr_SetObject(DBError, t); - Py_DECREF(t); + if (t) { + PyErr_SetObject(DBError, t); + Py_DECREF(t); + } return -1; } @@ -2717,17 +2932,15 @@ redo_stat_for_length: #if (DBVER >= 43) err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags); -#elif (DBVER >= 33) - err = self->db->stat(self->db, &sp, flags); #else - err = self->db->stat(self->db, &sp, NULL, flags); + err = self->db->stat(self->db, &sp, flags); #endif /* All the stat structures have matching fields upto the ndata field, so we can use any of them for the type cast */ size = ((DB_BTREE_STAT*)sp)->bt_ndata; - /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached. + /* A size of 0 could mean that Berkeley DB no longer had the stat values cached. * redo a full stat to make sure. * Fixes SF python bug 1493322, pybsddb bug 1184012 */ @@ -2754,17 +2967,16 @@ { int err; PyObject* retval; - Py_buffer* key_buf_view = NULL; DBT key; DBT data; CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL; CLEAR_DBT(data); if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ + /* Tell Berkeley DB to malloc the return value (thread safe) */ data.flags = DB_DBT_MALLOC; } MYDB_BEGIN_ALLOW_THREADS; @@ -2778,11 +2990,11 @@ retval = NULL; } else { - retval = PyBytes_FromStringAndSize((char*)data.data, data.size); - free_dbt(&data); + retval = Build_PyString(data.data, data.size); + FREE_DBT(data); } - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return retval; } @@ -2793,21 +3005,21 @@ DBT key, data; int retval; int flags = 0; - Py_buffer *data_buf_view = NULL; - Py_buffer *key_buf_view = NULL; if (self->db == NULL) { PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed"); - PyErr_SetObject(DBError, t); - Py_DECREF(t); + if (t) { + PyErr_SetObject(DBError, t); + Py_DECREF(t); + } return -1; } - if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, NULL)) return -1; if (dataobj != NULL) { - if (!make_dbt(dataobj, &data, &data_buf_view)) + if (!make_dbt(dataobj, &data)) retval = -1; else { if (self->setflags & (DB_DUP|DB_DUPSORT)) @@ -2828,29 +3040,30 @@ /* dataobj == NULL, so delete the key */ retval = _DB_delete(self, NULL, &key, 0); } - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); return retval; } static PyObject* -DB_has_key(DBObject* self, PyObject* args) +DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs) { int err; PyObject* keyobj; - Py_buffer* key_buf_view = NULL; DBT key, data; PyObject* txnobj = NULL; DB_TXN *txn = NULL; + static char* kwnames[] = {"key","txn", NULL}; - if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames, + &keyobj, &txnobj)) return NULL; + CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL; if (!checkTxnObj(txnobj, &txn)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); return NULL; } @@ -2864,12 +3077,12 @@ MYDB_BEGIN_ALLOW_THREADS; err = self->db->get(self->db, txn, &key, &data, 0); MYDB_END_ALLOW_THREADS; - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); if (err == DB_BUFFER_SMALL || err == 0) { - return PyLong_FromLong(1); + return NUMBER_FromLong(1); } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { - return PyLong_FromLong(0); + return NUMBER_FromLong(0); } makeDBError(err); @@ -2912,14 +3125,9 @@ return NULL; } - if (CHECK_DBFLAG(self, DB_THREAD)) { - key.flags = DB_DBT_REALLOC; - data.flags = DB_DBT_REALLOC; - } - while (1) { /* use the cursor to traverse the DB, collecting items */ MYDB_BEGIN_ALLOW_THREADS; - err = cursor->c_get(cursor, &key, &data, DB_NEXT); + err = _DBC_get(cursor, &key, &data, DB_NEXT); MYDB_END_ALLOW_THREADS; if (err) { @@ -2933,17 +3141,17 @@ case DB_BTREE: case DB_HASH: default: - item = PyBytes_FromStringAndSize((char*)key.data, key.size); + item = Build_PyString(key.data, key.size); break; case DB_RECNO: case DB_QUEUE: - item = PyLong_FromLong(*((db_recno_t*)key.data)); + item = NUMBER_FromLong(*((db_recno_t*)key.data)); break; } break; case _VALUES_LIST: - item = PyBytes_FromStringAndSize((char*)data.data, data.size); + item = Build_PyString(data.data, data.size); break; case _ITEMS_LIST: @@ -2951,13 +3159,11 @@ case DB_BTREE: case DB_HASH: default: - item = Py_BuildValue("y#y#", key.data, key.size, data.data, - data.size); + item = BuildValue_SS(key.data, key.size, data.data, data.size); break; case DB_RECNO: case DB_QUEUE: - item = Py_BuildValue("iy#", *((db_recno_t*)key.data), - data.data, data.size); + item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); break; } break; @@ -2971,7 +3177,12 @@ list = NULL; goto done; } - PyList_Append(list, item); + if (PyList_Append(list, item)) { + Py_DECREF(list); + Py_DECREF(item); + list = NULL; + goto done; + } Py_DECREF(item); } @@ -2982,10 +3193,8 @@ } done: - free_dbt(&key); - free_dbt(&data); MYDB_BEGIN_ALLOW_THREADS; - cursor->c_close(cursor); + _DBC_close(cursor); MYDB_END_ALLOW_THREADS; return list; } @@ -3037,23 +3246,32 @@ static PyObject* -DBC_close(DBCursorObject* self, PyObject* args) +DBC_close_internal(DBCursorObject* self) { int err = 0; - if (!PyArg_ParseTuple(args, ":close")) - return NULL; - if (self->dbc != NULL) { + EXTRACT_FROM_DOUBLE_LINKED_LIST(self); + if (self->txn) { + EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); + self->txn=NULL; + } + MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_close(self->dbc); - self->dbc = NULL; + err = _DBC_close(self->dbc); MYDB_END_ALLOW_THREADS; + self->dbc = NULL; } RETURN_IF_ERR(); RETURN_NONE(); } +static PyObject* +DBC_close(DBCursorObject* self) +{ + return DBC_close_internal(self); +} + static PyObject* DBC_count(DBCursorObject* self, PyObject* args) @@ -3068,11 +3286,11 @@ CHECK_CURSOR_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_count(self->dbc, &count, flags); + err = _DBC_count(self->dbc, &count, flags); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); - return PyLong_FromLong(count); + return NUMBER_FromLong(count); } @@ -3094,7 +3312,7 @@ CHECK_CURSOR_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_del(self->dbc, flags); + err = _DBC_del(self->dbc, flags); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); @@ -3115,11 +3333,11 @@ CHECK_CURSOR_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_dup(self->dbc, &dbc, flags); + err = _DBC_dup(self->dbc, &dbc, flags); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); - return (PyObject*) newDBCursorObject(dbc, self->mydb); + return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb); } static PyObject* @@ -3136,8 +3354,6 @@ PyObject* keyobj = NULL; PyObject* dataobj = NULL; PyObject* retval = NULL; - Py_buffer* data_buf_view = NULL; - Py_buffer* key_buf_view = NULL; int dlen = -1; int doff = -1; DBT key, data; @@ -3151,7 +3367,7 @@ { PyErr_Clear(); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get", - &kwnames[1], + &kwnames[1], &keyobj, &flags, &dlen, &doff)) { PyErr_Clear(); @@ -3166,25 +3382,17 @@ CHECK_CURSOR_NOT_CLOSED(self); - if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view)) + if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) return NULL; - if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) || + if ( (dataobj && !make_dbt(dataobj, &data)) || (!add_partial_dbt(&data, dlen, doff)) ) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ return NULL; } - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - data.flags = DB_DBT_MALLOC; - if (!(key.flags & DB_DBT_REALLOC)) { - key.flags |= DB_DBT_MALLOC; - } - } - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags); + err = _DBC_get(self->dbc, &key, &data, flags); MYDB_END_ALLOW_THREADS; if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) @@ -3203,23 +3411,18 @@ case DB_BTREE: case DB_HASH: default: - retval = Py_BuildValue("y#y#", key.data, key.size, - data.data, data.size); + retval = BuildValue_SS(key.data, key.size, data.data, data.size); break; case DB_RECNO: case DB_QUEUE: - retval = Py_BuildValue("iy#", *((db_recno_t*)key.data), - data.data, data.size); + retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); break; } - free_dbt(&data); } - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ return retval; } -#if (DBVER >= 33) static PyObject* DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs) { @@ -3227,8 +3430,6 @@ PyObject* keyobj = NULL; PyObject* dataobj = NULL; PyObject* retval = NULL; - Py_buffer* data_buf_view = NULL; - Py_buffer* key_buf_view = NULL; int dlen = -1; int doff = -1; DBT key, pkey, data; @@ -3257,27 +3458,19 @@ CHECK_CURSOR_NOT_CLOSED(self); - if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view)) + if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) return NULL; - if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) || + if ( (dataobj && !make_dbt(dataobj, &data)) || (!add_partial_dbt(&data, dlen, doff)) ) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ return NULL; } - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - data.flags = DB_DBT_MALLOC; - if (!(key.flags & DB_DBT_REALLOC)) { - key.flags |= DB_DBT_MALLOC; - } - } - CLEAR_DBT(pkey); pkey.flags = DB_DBT_MALLOC; MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags); + err = _DBC_pget(self->dbc, &key, &pkey, &data, flags); MYDB_END_ALLOW_THREADS; if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) @@ -3291,76 +3484,71 @@ else { PyObject *pkeyObj; PyObject *dataObj; - dataObj = PyBytes_FromStringAndSize(data.data, data.size); + dataObj = Build_PyString(data.data, data.size); if (self->mydb->primaryDBType == DB_RECNO || self->mydb->primaryDBType == DB_QUEUE) - pkeyObj = PyLong_FromLong(*(int *)pkey.data); + pkeyObj = NUMBER_FromLong(*(int *)pkey.data); else - pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size); + pkeyObj = Build_PyString(pkey.data, pkey.size); if (key.data && key.size) /* return key, pkey and data */ { PyObject *keyObj; int type = _DB_get_type(self->mydb); if (type == DB_RECNO || type == DB_QUEUE) - keyObj = PyLong_FromLong(*(int *)key.data); + keyObj = NUMBER_FromLong(*(int *)key.data); else - keyObj = PyBytes_FromStringAndSize(key.data, key.size); + keyObj = Build_PyString(key.data, key.size); +#if (PY_VERSION_HEX >= 0x02040000) retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); +#else + retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj); +#endif Py_DECREF(keyObj); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ } else /* return just the pkey and data */ { +#if (PY_VERSION_HEX >= 0x02040000) retval = PyTuple_Pack(2, pkeyObj, dataObj); +#else + retval = Py_BuildValue("OO", pkeyObj, dataObj); +#endif } Py_DECREF(dataObj); Py_DECREF(pkeyObj); - free_dbt(&pkey); - free_dbt(&data); + FREE_DBT(pkey); } /* the only time REALLOC should be set is if we used an integer * key that make_key_dbt malloc'd for us. always free these. */ - if (key.flags & DB_DBT_REALLOC) { - free_dbt(&key); + if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */ + FREE_DBT(key); } - free_buf_view(keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); return retval; } -#endif static PyObject* -DBC_get_recno(DBCursorObject* self, PyObject* args) +DBC_get_recno(DBCursorObject* self) { int err; db_recno_t recno; DBT key; DBT data; - if (!PyArg_ParseTuple(args, ":get_recno")) - return NULL; - CHECK_CURSOR_NOT_CLOSED(self); CLEAR_DBT(key); CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - key.flags = DB_DBT_MALLOC; - } MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO); + err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); recno = *((db_recno_t*)data.data); - free_dbt(&key); - free_dbt(&data); - return PyLong_FromLong(recno); + return NUMBER_FromLong(recno); } @@ -3389,9 +3577,7 @@ DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs) { int err, flags = 0; - PyObject *keyobj, *dataobj; - Py_buffer *data_buf_view = NULL; - Py_buffer *key_buf_view = NULL; + PyObject* keyobj, *dataobj; DBT key, data; static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL }; @@ -3404,21 +3590,19 @@ CHECK_CURSOR_NOT_CLOSED(self); - if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) return NULL; - if (!make_dbt(dataobj, &data, &data_buf_view) || + if (!make_dbt(dataobj, &data) || !add_partial_dbt(&data, dlen, doff) ) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ return NULL; } MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_put(self->dbc, &key, &data, flags); + err = _DBC_put(self->dbc, &key, &data, flags); MYDB_END_ALLOW_THREADS; - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ RETURN_IF_ERR(); self->mydb->haveStat = 0; RETURN_NONE(); @@ -3430,8 +3614,7 @@ { int err, flags = 0; DBT key, data; - PyObject *retval, *keyobj; - Py_buffer *key_buf_view = NULL; + PyObject* retval, *keyobj; static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; int dlen = -1; int doff = -1; @@ -3442,21 +3625,17 @@ CHECK_CURSOR_NOT_CLOSED(self); - if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) return NULL; CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - } if (!add_partial_dbt(&data, dlen, doff)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ return NULL; } MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET); + err = _DBC_get(self->dbc, &key, &data, flags|DB_SET); MYDB_END_ALLOW_THREADS; if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && self->mydb->moduleFlags.cursorSetReturnsNone) { @@ -3474,24 +3653,20 @@ case DB_BTREE: case DB_HASH: default: - retval = Py_BuildValue("y#y#", key.data, key.size, - data.data, data.size); + retval = BuildValue_SS(key.data, key.size, data.data, data.size); break; case DB_RECNO: case DB_QUEUE: - retval = Py_BuildValue("iy#", *((db_recno_t*)key.data), - data.data, data.size); + retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); break; } - free_dbt(&data); - free_dbt(&key); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ } /* the only time REALLOC should be set is if we used an integer * key that make_key_dbt malloc'd for us. always free these. */ if (key.flags & DB_DBT_REALLOC) { - free_dbt(&key); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ } - free_buf_view(keyobj, key_buf_view); return retval; } @@ -3502,8 +3677,7 @@ { int err, flags = 0; DBT key, data; - PyObject *retval, *keyobj; - Py_buffer *key_buf_view = NULL; + PyObject* retval, *keyobj; static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; int dlen = -1; int doff = -1; @@ -3514,24 +3688,16 @@ CHECK_CURSOR_NOT_CLOSED(self); - if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) return NULL; CLEAR_DBT(data); if (!add_partial_dbt(&data, dlen, doff)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ return NULL; } - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags |= DB_DBT_MALLOC; - /* only BTREE databases will return anything in the key */ - if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) { - key.flags |= DB_DBT_MALLOC; - } - } MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE); + err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE); MYDB_END_ALLOW_THREADS; if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && self->mydb->moduleFlags.cursorSetReturnsNone) { @@ -3549,24 +3715,20 @@ case DB_BTREE: case DB_HASH: default: - retval = Py_BuildValue("y#y#", key.data, key.size, - data.data, data.size); + retval = BuildValue_SS(key.data, key.size, data.data, data.size); break; case DB_RECNO: case DB_QUEUE: - retval = Py_BuildValue("iy#", *((db_recno_t*)key.data), - data.data, data.size); + retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); break; } - free_dbt(&key); - free_dbt(&data); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ } /* the only time REALLOC should be set is if we used an integer * key that make_key_dbt malloc'd for us. always free these. */ if (key.flags & DB_DBT_REALLOC) { - free_dbt(&key); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ } - free_buf_view(keyobj, key_buf_view); return retval; } @@ -3577,20 +3739,18 @@ { int err; DBT key, data; - PyObject *retval; - Py_buffer *data_buf_view = NULL; - Py_buffer *key_buf_view = NULL; + PyObject* retval; /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */ - if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) return NULL; - if (!make_dbt(dataobj, &data, &data_buf_view)) { - FREE_DBT_VIEW(key, keyobj, key_buf_view); + if (!make_dbt(dataobj, &data)) { + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ return NULL; } MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH); + err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH); MYDB_END_ALLOW_THREADS; if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) { Py_INCREF(Py_None); @@ -3607,19 +3767,16 @@ case DB_BTREE: case DB_HASH: default: - retval = Py_BuildValue("y#y#", key.data, key.size, - data.data, data.size); + retval = BuildValue_SS(key.data, key.size, data.data, data.size); break; case DB_RECNO: case DB_QUEUE: - retval = Py_BuildValue("iy#", *((db_recno_t*)key.data), - data.data, data.size); + retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); break; } } - FREE_DBT_VIEW(key, keyobj, key_buf_view); - free_buf_view(dataobj, data_buf_view); + FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ return retval; } @@ -3641,14 +3798,12 @@ /* Return size of entry */ static PyObject* -DBC_get_current_size(DBCursorObject* self, PyObject* args) +DBC_get_current_size(DBCursorObject* self) { int err, flags=DB_CURRENT; PyObject* retval = NULL; DBT key, data; - if (!PyArg_ParseTuple(args, ":get_current_size")) - return NULL; CHECK_CURSOR_NOT_CLOSED(self); CLEAR_DBT(key); CLEAR_DBT(data); @@ -3658,16 +3813,14 @@ data.flags = DB_DBT_USERMEM; data.ulen = 0; MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags); + err = _DBC_get(self->dbc, &key, &data, flags); MYDB_END_ALLOW_THREADS; if (err == DB_BUFFER_SMALL || !err) { /* DB_BUFFER_SMALL means positive size, !err means zero length value */ - retval = PyLong_FromLong((long)data.size); + retval = NUMBER_FromLong((long)data.size); err = 0; } - free_dbt(&key); - free_dbt(&data); RETURN_IF_ERR(); return retval; } @@ -3721,17 +3874,13 @@ key.flags = DB_DBT_REALLOC; CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - } if (!add_partial_dbt(&data, dlen, doff)) { - free_dbt(&key); + FREE_DBT(key); return NULL; } MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO); + err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO); MYDB_END_ALLOW_THREADS; if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && self->mydb->moduleFlags.cursorSetReturnsNone) { @@ -3742,11 +3891,9 @@ retval = NULL; } else { /* Can only be used for BTrees, so no need to return int key */ - retval = Py_BuildValue("y#y#", key.data, key.size, - data.data, data.size); - free_dbt(&data); + retval = BuildValue_SS(key.data, key.size, data.data, data.size); } - free_dbt(&key); + FREE_DBT(key); return retval; } @@ -3794,13 +3941,9 @@ CLEAR_DBT(key); CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - key.flags = DB_DBT_MALLOC; - } MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM); + err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM); MYDB_END_ALLOW_THREADS; if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && self->mydb->moduleFlags.getReturnsNone) { @@ -3811,8 +3954,7 @@ retval = NULL; } else { - retval = Py_BuildValue("y#", key.data, key.size); - free_dbt(&key); + retval = BuildValue_S(key.data, key.size); } return retval; @@ -3825,18 +3967,26 @@ static PyObject* -DBEnv_close(DBEnvObject* self, PyObject* args) +DBEnv_close_internal(DBEnvObject* self, int flags) { - int err, flags = 0; + PyObject *dummy; + int err; - if (!PyArg_ParseTuple(args, "|i:close", &flags)) - return NULL; if (!self->closed) { /* Don't close more than once */ + while(self->children_txns) { + dummy=DBTxn_abort_discard_internal(self->children_txns,0); + Py_XDECREF(dummy); + } + while(self->children_dbs) { + dummy=DB_close_internal(self->children_dbs,0); + Py_XDECREF(dummy); + } + MYDB_BEGIN_ALLOW_THREADS; err = self->db_env->close(self->db_env, flags); MYDB_END_ALLOW_THREADS; /* after calling DBEnv->close, regardless of error, this DBEnv - * may not be accessed again (BerkeleyDB docs). */ + * may not be accessed again (Berkeley DB docs). */ self->closed = 1; self->db_env = NULL; RETURN_IF_ERR(); @@ -3844,6 +3994,16 @@ RETURN_NONE(); } +static PyObject* +DBEnv_close(DBEnvObject* self, PyObject* args) +{ + int flags = 0; + + if (!PyArg_ParseTuple(args, "|i:close", &flags)) + return NULL; + return DBEnv_close_internal(self,flags); +} + static PyObject* DBEnv_open(DBEnvObject* self, PyObject* args) @@ -3961,7 +4121,6 @@ } #endif /* DBVER >= 41 */ -#if (DBVER >= 40) static PyObject* DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs) { @@ -3982,7 +4141,6 @@ RETURN_IF_ERR(); RETURN_NONE(); } -#endif /* DBVER >= 40 */ static PyObject* DBEnv_set_shm_key(DBEnvObject* self, PyObject* args) @@ -4035,6 +4193,26 @@ } +#if (DBVER >= 47) +static PyObject* +DBEnv_log_set_config(DBEnvObject* self, PyObject* args) +{ + int err, flags, onoff; + + if (!PyArg_ParseTuple(args, "ii:log_set_config", + &flags, &onoff)) + return NULL; + CHECK_ENV_NOT_CLOSED(self); + + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->log_set_config(self->db_env, flags, onoff); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} +#endif /* DBVER >= 47 */ + + static PyObject* DBEnv_set_data_dir(DBEnvObject* self, PyObject* args) { @@ -4103,8 +4281,24 @@ RETURN_NONE(); } +#if (DBVER >= 42) +static PyObject* +DBEnv_get_lg_max(DBEnvObject* self) +{ + int err; + u_int32_t lg_max; + + CHECK_ENV_NOT_CLOSED(self); + + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->get_lg_max(self->db_env, &lg_max); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return NUMBER_FromLong(lg_max); +} +#endif + -#if (DBVER >= 33) static PyObject* DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args) { @@ -4120,7 +4314,6 @@ RETURN_IF_ERR(); RETURN_NONE(); } -#endif static PyObject* @@ -4247,6 +4440,79 @@ static PyObject* +DBEnv_txn_recover(DBEnvObject* self) +{ + int flags = DB_FIRST; + int err, i; + PyObject *list, *tuple, *gid; + DBTxnObject *txn; +#define PREPLIST_LEN 16 + DB_PREPLIST preplist[PREPLIST_LEN]; + long retp; + + CHECK_ENV_NOT_CLOSED(self); + + list=PyList_New(0); + if (!list) + return NULL; + while (!0) { + MYDB_BEGIN_ALLOW_THREADS + err=self->db_env->txn_recover(self->db_env, + preplist, PREPLIST_LEN, &retp, flags); +#undef PREPLIST_LEN + MYDB_END_ALLOW_THREADS + if (err) { + Py_DECREF(list); + RETURN_IF_ERR(); + } + if (!retp) break; + flags=DB_NEXT; /* Prepare for next loop pass */ + for (i=0; iflag_prepare=1; /* Recover state */ + tuple=PyTuple_New(2); + if (!tuple) { + Py_DECREF(list); + Py_DECREF(gid); + Py_DECREF(txn); + return NULL; + } + if (PyTuple_SetItem(tuple, 0, gid)) { + Py_DECREF(list); + Py_DECREF(gid); + Py_DECREF(txn); + Py_DECREF(tuple); + return NULL; + } + if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) { + Py_DECREF(list); + Py_DECREF(txn); + Py_DECREF(tuple); /* This delete the "gid" also */ + return NULL; + } + if (PyList_Append(list, tuple)) { + Py_DECREF(list); + Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */ + return NULL; + } + Py_DECREF(tuple); + } + } + return list; +} + +static PyObject* DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs) { int flags = 0; @@ -4262,7 +4528,7 @@ return NULL; CHECK_ENV_NOT_CLOSED(self); - return (PyObject*)newDBTxnObject(self, txn, flags); + return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags); } @@ -4276,11 +4542,7 @@ CHECK_ENV_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags); -#else - err = txn_checkpoint(self->db_env, kbyte, min, flags); -#endif MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); RETURN_NONE(); @@ -4330,14 +4592,10 @@ CHECK_ENV_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted); -#else - err = lock_detect(self->db_env, flags, atype, &aborted); -#endif MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); - return PyLong_FromLong(aborted); + return NUMBER_FromLong(aborted); } @@ -4347,44 +4605,34 @@ int flags=0; int locker, lock_mode; DBT obj; - PyObject *objobj, *retval; - Py_buffer *obj_buf_view = NULL; + PyObject* objobj; if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags)) return NULL; - if (!make_dbt(objobj, &obj, &obj_buf_view)) + + if (!make_dbt(objobj, &obj)) return NULL; - retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags); - free_buf_view(objobj, obj_buf_view); - return retval; + return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags); } static PyObject* -DBEnv_lock_id(DBEnvObject* self, PyObject* args) +DBEnv_lock_id(DBEnvObject* self) { int err; u_int32_t theID; - if (!PyArg_ParseTuple(args, ":lock_id")) - return NULL; - CHECK_ENV_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) err = self->db_env->lock_id(self->db_env, &theID); -#else - err = lock_id(self->db_env, &theID); -#endif MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); - return PyLong_FromLong((long)theID); + return NUMBER_FromLong((long)theID); } -#if (DBVER >= 40) static PyObject* DBEnv_lock_id_free(DBEnvObject* self, PyObject* args) { @@ -4401,7 +4649,6 @@ RETURN_IF_ERR(); RETURN_NONE(); } -#endif static PyObject* DBEnv_lock_put(DBEnvObject* self, PyObject* args) @@ -4414,11 +4661,7 @@ CHECK_ENV_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) err = self->db_env->lock_put(self->db_env, &dblockobj->lock); -#else - err = lock_put(self->db_env, &dblockobj->lock); -#endif MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); RETURN_NONE(); @@ -4446,7 +4689,6 @@ } #endif /* DBVER >= 4.4 */ -#if (DBVER >= 40) static PyObject* DBEnv_log_stat(DBEnvObject* self, PyObject* args) { @@ -4482,7 +4724,7 @@ MAKE_ENTRY(lg_size); MAKE_ENTRY(record); #endif -#if (DBVER <= 40) +#if (DBVER < 41) MAKE_ENTRY(lg_max); #endif MAKE_ENTRY(w_mbytes); @@ -4509,7 +4751,6 @@ free(statp); return d; } /* DBEnv_log_stat */ -#endif /* DBVER >= 4.0 for log_stat method */ static PyObject* @@ -4525,15 +4766,7 @@ CHECK_ENV_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) err = self->db_env->lock_stat(self->db_env, &sp, flags); -#else -#if (DBVER >= 33) - err = lock_stat(self->db_env, &sp); -#else - err = lock_stat(self->db_env, &sp, NULL); -#endif -#endif MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); @@ -4549,6 +4782,10 @@ #if (DBVER < 41) MAKE_ENTRY(lastid); #endif +#if (DBVER >=41) + MAKE_ENTRY(id); + MAKE_ENTRY(cur_maxid); +#endif MAKE_ENTRY(nmodes); MAKE_ENTRY(maxlocks); MAKE_ENTRY(maxlockers); @@ -4561,6 +4798,10 @@ MAKE_ENTRY(maxnobjects); MAKE_ENTRY(nrequests); MAKE_ENTRY(nreleases); +#if (DBVER >= 44) + MAKE_ENTRY(nupgrade); + MAKE_ENTRY(ndowngrade); +#endif #if (DBVER < 44) MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */ MAKE_ENTRY(nconflicts); @@ -4569,6 +4810,26 @@ MAKE_ENTRY(lock_wait); #endif MAKE_ENTRY(ndeadlocks); +#if (DBVER >= 41) + MAKE_ENTRY(locktimeout); + MAKE_ENTRY(txntimeout); +#endif + MAKE_ENTRY(nlocktimeouts); + MAKE_ENTRY(ntxntimeouts); +#if (DBVER >= 46) + MAKE_ENTRY(objs_wait); + MAKE_ENTRY(objs_nowait); + MAKE_ENTRY(lockers_wait); + MAKE_ENTRY(lockers_nowait); +#if (DBVER >= 47) + MAKE_ENTRY(lock_wait); + MAKE_ENTRY(lock_nowait); +#else + MAKE_ENTRY(locks_wait); + MAKE_ENTRY(locks_nowait); +#endif + MAKE_ENTRY(hash_len); +#endif MAKE_ENTRY(regsize); MAKE_ENTRY(region_wait); MAKE_ENTRY(region_nowait); @@ -4578,28 +4839,36 @@ return d; } - static PyObject* -DBEnv_log_archive(DBEnvObject* self, PyObject* args) +DBEnv_log_flush(DBEnvObject* self) { - int flags=0; int err; - char **log_list = NULL; - PyObject* list; - PyObject* item = NULL; - - if (!PyArg_ParseTuple(args, "|i:log_archive", &flags)) - return NULL; CHECK_ENV_NOT_CLOSED(self); - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->db_env->log_archive(self->db_env, &log_list, flags); -#elif (DBVER == 33) - err = log_archive(self->db_env, &log_list, flags); -#else - err = log_archive(self->db_env, &log_list, flags, NULL); -#endif + + MYDB_BEGIN_ALLOW_THREADS + err = self->db_env->log_flush(self->db_env, NULL); + MYDB_END_ALLOW_THREADS + + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_log_archive(DBEnvObject* self, PyObject* args) +{ + int flags=0; + int err; + char **log_list = NULL; + PyObject* list; + PyObject* item = NULL; + + if (!PyArg_ParseTuple(args, "|i:log_archive", &flags)) + return NULL; + + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->log_archive(self->db_env, &log_list, flags); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); @@ -4613,13 +4882,18 @@ if (log_list) { char **log_list_start; for (log_list_start = log_list; *log_list != NULL; ++log_list) { - item = PyUnicode_FromString (*log_list); + item = PyBytes_FromString (*log_list); if (item == NULL) { Py_DECREF(list); list = NULL; break; } - PyList_Append(list, item); + if (PyList_Append(list, item)) { + Py_DECREF(list); + list = NULL; + Py_DECREF(item); + break; + } Py_DECREF(item); } free(log_list_start); @@ -4641,13 +4915,7 @@ CHECK_ENV_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) err = self->db_env->txn_stat(self->db_env, &sp, flags); -#elif (DBVER == 33) - err = txn_stat(self->db_env, &sp); -#else - err = txn_stat(self->db_env, &sp, NULL); -#endif MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); @@ -4658,21 +4926,29 @@ return NULL; } -#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) -#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name) +#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) +#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name) +#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name) + MAKE_DB_LSN_ENTRY(last_ckp); MAKE_TIME_T_ENTRY(time_ckp); MAKE_ENTRY(last_txnid); MAKE_ENTRY(maxtxns); MAKE_ENTRY(nactive); MAKE_ENTRY(maxnactive); +#if (DBVER >= 45) + MAKE_ENTRY(nsnapshot); + MAKE_ENTRY(maxnsnapshot); +#endif MAKE_ENTRY(nbegins); MAKE_ENTRY(naborts); MAKE_ENTRY(ncommits); + MAKE_ENTRY(nrestores); MAKE_ENTRY(regsize); MAKE_ENTRY(region_wait); MAKE_ENTRY(region_nowait); +#undef MAKE_DB_LSN_ENTRY #undef MAKE_ENTRY #undef MAKE_TIME_T_ENTRY free(sp); @@ -4696,151 +4972,1043 @@ ++oldValue; self->moduleFlags.getReturnsNone = (flags >= 1); self->moduleFlags.cursorSetReturnsNone = (flags >= 2); - return PyLong_FromLong(oldValue); + return NUMBER_FromLong(oldValue); } +static PyObject* +DBEnv_get_private(DBEnvObject* self) +{ + /* We can give out the private field even if dbenv is closed */ + Py_INCREF(self->private_obj); + return self->private_obj; +} -/* --------------------------------------------------------------------- */ -/* DBTxn methods */ +static PyObject* +DBEnv_set_private(DBEnvObject* self, PyObject* private_obj) +{ + /* We can set the private field even if dbenv is closed */ + Py_DECREF(self->private_obj); + Py_INCREF(private_obj); + self->private_obj = private_obj; + RETURN_NONE(); +} static PyObject* -DBTxn_commit(DBTxnObject* self, PyObject* args) +DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs) { - int flags=0, err; - DB_TXN *txn; + int err; + char *host; + long cl_timeout=0, sv_timeout=0; - if (!PyArg_ParseTuple(args, "|i:commit", &flags)) + static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames, + &host, &cl_timeout, &sv_timeout)) return NULL; + CHECK_ENV_NOT_CLOSED(self); - if (!self->txn) { - PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " - "after txn_commit or txn_abort"); - PyErr_SetObject(DBError, t); - Py_DECREF(t); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout, + sv_timeout, 0); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_set_verbose(DBEnvObject* self, PyObject* args) +{ + int err; + int which, onoff; + + if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) { return NULL; } - txn = self->txn; - self->txn = NULL; /* this DB_TXN is no longer valid after this call */ + CHECK_ENV_NOT_CLOSED(self); MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = txn->commit(txn, flags); -#else - err = txn_commit(txn, flags); + err = self->db_env->set_verbose(self->db_env, which, onoff); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +#if (DBVER >= 42) +static PyObject* +DBEnv_get_verbose(DBEnvObject* self, PyObject* args) +{ + int err; + int which; + int verbose; + + if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->get_verbose(self->db_env, which, &verbose); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return PyBool_FromLong(verbose); +} +#endif + +#if (DBVER >= 45) +static void +_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info) +{ + DBEnvObject *dbenv; + PyObject* callback; + PyObject* args; + PyObject* result = NULL; + + MYDB_BEGIN_BLOCK_THREADS; + dbenv = (DBEnvObject *)db_env->app_private; + callback = dbenv->event_notifyCallback; + if (callback) { + if (event == DB_EVENT_REP_NEWMASTER) { + args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info)); + } else { + args = Py_BuildValue("(OiO)", dbenv, event, Py_None); + } + if (args) { + result = PyEval_CallObject(callback, args); + } + if ((!args) || (!result)) { + PyErr_Print(); + } + Py_XDECREF(args); + Py_XDECREF(result); + } + MYDB_END_BLOCK_THREADS; +} +#endif + +#if (DBVER >= 45) +static PyObject* +DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc) +{ + int err; + + CHECK_ENV_NOT_CLOSED(self); + + if (!PyCallable_Check(notifyFunc)) { + makeTypeError("Callable", notifyFunc); + return NULL; + } + + Py_XDECREF(self->event_notifyCallback); + Py_INCREF(notifyFunc); + self->event_notifyCallback = notifyFunc; + + /* This is to workaround a problem with un-initialized threads (see + comment in DB_associate) */ +#ifdef WITH_THREAD + PyEval_InitThreads(); #endif + + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback); MYDB_END_ALLOW_THREADS; + + if (err) { + Py_DECREF(notifyFunc); + self->event_notifyCallback = NULL; + } + RETURN_IF_ERR(); RETURN_NONE(); } +#endif + + +/* --------------------------------------------------------------------- */ +/* REPLICATION METHODS: Base Replication */ + static PyObject* -DBTxn_prepare(DBTxnObject* self, PyObject* args) +DBEnv_rep_process_message(DBEnvObject* self, PyObject* args) { -#if (DBVER >= 33) int err; - char* gid=NULL; - int gid_size=0; + PyObject *control_py, *rec_py; + DBT control, rec; + int envid; +#if (DBVER >= 42) + DB_LSN lsn; +#endif - if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size)) + if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py, + &rec_py, &envid)) return NULL; + CHECK_ENV_NOT_CLOSED(self); - if (gid_size != DB_XIDDATASIZE) { - PyErr_SetString(PyExc_TypeError, - "gid must be DB_XIDDATASIZE bytes long"); + if (!make_dbt(control_py, &control)) return NULL; + if (!make_dbt(rec_py, &rec)) + return NULL; + + MYDB_BEGIN_ALLOW_THREADS; +#if (DBVER >= 46) + err = self->db_env->rep_process_message(self->db_env, &control, &rec, + envid, &lsn); +#else +#if (DBVER >= 42) + err = self->db_env->rep_process_message(self->db_env, &control, &rec, + &envid, &lsn); +#else + err = self->db_env->rep_process_message(self->db_env, &control, &rec, + &envid); +#endif +#endif + MYDB_END_ALLOW_THREADS; + switch (err) { + case DB_REP_NEWMASTER : + return Py_BuildValue("(iO)", envid, Py_None); + break; + + case DB_REP_DUPMASTER : + case DB_REP_HOLDELECTION : +#if (DBVER >= 44) + case DB_REP_IGNORE : + case DB_REP_JOIN_FAILURE : +#endif + return Py_BuildValue("(iO)", err, Py_None); + break; + case DB_REP_NEWSITE : + { + PyObject *tmp, *r; + + if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) { + return NULL; + } + + r = Py_BuildValue("(iO)", err, tmp); + Py_DECREF(tmp); + return r; + break; + } +#if (DBVER >= 42) + case DB_REP_NOTPERM : + case DB_REP_ISPERM : + return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset); + break; +#endif } + RETURN_IF_ERR(); + return Py_BuildValue("(OO)", Py_None, Py_None); +} - if (!self->txn) { - PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used " - "after txn_commit or txn_abort"); - PyErr_SetObject(DBError, t); - Py_DECREF(t); +static int +_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec, + const DB_LSN *lsn, int envid, u_int32_t flags) +{ + DBEnvObject *dbenv; + PyObject* rep_transport; + PyObject* args; + PyObject *a, *b; + PyObject* result = NULL; + int ret=0; + + MYDB_BEGIN_BLOCK_THREADS; + dbenv = (DBEnvObject *)db_env->app_private; + rep_transport = dbenv->rep_transport; + + /* + ** The errors in 'a' or 'b' are detected in "Py_BuildValue". + */ + a = PyBytes_FromStringAndSize(control->data, control->size); + b = PyBytes_FromStringAndSize(rec->data, rec->size); + + args = Py_BuildValue( +#if (PY_VERSION_HEX >= 0x02040000) + "(OOO(ll)iI)", +#else + "(OOO(ll)ii)", +#endif + dbenv, + a, b, + lsn->file, lsn->offset, envid, flags); + if (args) { + result = PyEval_CallObject(rep_transport, args); + } + + if ((!args) || (!result)) { + PyErr_Print(); + ret = -1; + } + Py_XDECREF(a); + Py_XDECREF(b); + Py_XDECREF(args); + Py_XDECREF(result); + MYDB_END_BLOCK_THREADS; + return ret; +} + +#if (DBVER <= 41) +static int +_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec, + int envid, u_int32_t flags) +{ + DB_LSN lsn; + + lsn.file = -1; /* Dummy values */ + lsn.offset = -1; + return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid, + flags); +} +#endif + +static PyObject* +DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args) +{ + int err; + int envid; + PyObject *rep_transport; + + if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport)) + return NULL; + CHECK_ENV_NOT_CLOSED(self); + if (!PyCallable_Check(rep_transport)) { + makeTypeError("Callable", rep_transport); return NULL; } + MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->txn->prepare(self->txn, (u_int8_t*)gid); +#if (DBVER >=45) + err = self->db_env->rep_set_transport(self->db_env, envid, + &_DBEnv_rep_transportCallback); +#else +#if (DBVER >= 42) + err = self->db_env->set_rep_transport(self->db_env, envid, + &_DBEnv_rep_transportCallback); #else - err = txn_prepare(self->txn, (u_int8_t*)gid); + err = self->db_env->set_rep_transport(self->db_env, envid, + &_DBEnv_rep_transportCallbackOLD); +#endif #endif MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); + + Py_DECREF(self->rep_transport); + Py_INCREF(rep_transport); + self->rep_transport = rep_transport; + RETURN_NONE(); +} + +#if (DBVER >= 47) +static PyObject* +DBEnv_rep_set_request(DBEnvObject* self, PyObject* args) +{ + int err; + unsigned int minimum, maximum; + + if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum)) + return NULL; + CHECK_ENV_NOT_CLOSED(self); + + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_set_request(self->db_env, minimum, maximum); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); RETURN_NONE(); +} + +static PyObject* +DBEnv_rep_get_request(DBEnvObject* self) +{ + int err; + u_int32_t minimum, maximum; + + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); +#if (PY_VERSION_HEX >= 0x02040000) + return Py_BuildValue("II", minimum, maximum); #else + return Py_BuildValue("ii", minimum, maximum); +#endif +} +#endif + +#if (DBVER >= 45) +static PyObject* +DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args) +{ int err; + int limit; - if (!PyArg_ParseTuple(args, ":prepare")) + if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit)) return NULL; + CHECK_ENV_NOT_CLOSED(self); - if (!self->txn) { - PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " - "after txn_commit or txn_abort"); - PyErr_SetObject(DBError, t); - Py_DECREF(t); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_set_limit(self->db_env, 0, limit); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_rep_get_limit(DBEnvObject* self) +{ + int err; + u_int32_t gbytes, bytes; + + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return NUMBER_FromLong(bytes); +} +#endif + +#if (DBVER >= 44) +static PyObject* +DBEnv_rep_set_config(DBEnvObject* self, PyObject* args) +{ + int err; + int which; + int onoff; + + if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff)) + return NULL; + CHECK_ENV_NOT_CLOSED(self); + + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_set_config(self->db_env, which, onoff); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_rep_get_config(DBEnvObject* self, PyObject* args) +{ + int err; + int which; + int onoff; + + if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_get_config(self->db_env, which, &onoff); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return PyBool_FromLong(onoff); +} +#endif + +#if (DBVER >= 46) +static PyObject* +DBEnv_rep_elect(DBEnvObject* self, PyObject* args) +{ + int err; + u_int32_t nsites, nvotes; + + if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} +#endif + +static PyObject* +DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs) +{ + int err; + PyObject *cdata_py = Py_None; + DBT cdata; + int flags; + static char* kwnames[] = {"flags","cdata", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i|O:rep_start", kwnames, &flags, &cdata_py)) + { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + + if (!make_dbt(cdata_py, &cdata)) + return NULL; + + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL, + flags); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +#if (DBVER >= 44) +static PyObject* +DBEnv_rep_sync(DBEnvObject* self) +{ + int err; + + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_sync(self->db_env, 0); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} +#endif + + +#if (DBVER >= 45) +static PyObject* +DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args) +{ + int err; + int nsites; + + if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_set_nsites(self->db_env, nsites); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_rep_get_nsites(DBEnvObject* self) +{ + int err; +#if (DBVER >= 47) + u_int32_t nsites; +#else + int nsites; +#endif + + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_get_nsites(self->db_env, &nsites); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return NUMBER_FromLong(nsites); +} + +static PyObject* +DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args) +{ + int err; + int priority; + + if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_set_priority(self->db_env, priority); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_rep_get_priority(DBEnvObject* self) +{ + int err; +#if (DBVER >= 47) + u_int32_t priority; +#else + int priority; +#endif + + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_get_priority(self->db_env, &priority); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return NUMBER_FromLong(priority); +} + +static PyObject* +DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args) +{ + int err; + int which, timeout; + + if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_set_timeout(self->db_env, which, timeout); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args) +{ + int err; + int which; + u_int32_t timeout; + + if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->rep_get_timeout(self->db_env, which, &timeout); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return NUMBER_FromLong(timeout); +} +#endif + +/* --------------------------------------------------------------------- */ +/* REPLICATION METHODS: Replication Manager */ + +#if (DBVER >= 45) +static PyObject* +DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject* + kwargs) +{ + int err; + int nthreads, flags; + static char* kwnames[] = {"nthreads","flags", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "ii:repmgr_start", kwnames, &nthreads, &flags)) + { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->repmgr_start(self->db_env, nthreads, flags); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject* + kwargs) +{ + int err; + char *host; + int port; + int flags = 0; + static char* kwnames[] = {"host", "port", "flags", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags)) + { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject* + kwargs) +{ + int err; + char *host; + int port; + int flags = 0; + int eidp; + static char* kwnames[] = {"host", "port", "flags", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags)) + { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return NUMBER_FromLong(eidp); +} + +static PyObject* +DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args) +{ + int err; + int ack_policy; + + if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy)) + { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_repmgr_get_ack_policy(DBEnvObject* self) +{ + int err; + int ack_policy; + + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + return NUMBER_FromLong(ack_policy); +} + +static PyObject* +DBEnv_repmgr_site_list(DBEnvObject* self) +{ + int err; + unsigned int countp; + DB_REPMGR_SITE *listp; + PyObject *stats, *key, *tuple; + + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + + stats=PyDict_New(); + if (stats == NULL) { + free(listp); + return NULL; + } + + for(;countp--;) { + key=NUMBER_FromLong(listp[countp].eid); + if(!key) { + Py_DECREF(stats); + free(listp); + return NULL; + } +#if (PY_VERSION_HEX >= 0x02040000) + tuple=Py_BuildValue("(sII)", listp[countp].host, + listp[countp].port, listp[countp].status); +#else + tuple=Py_BuildValue("(sii)", listp[countp].host, + listp[countp].port, listp[countp].status); +#endif + if(!tuple) { + Py_DECREF(key); + Py_DECREF(stats); + free(listp); + return NULL; + } + if(PyDict_SetItem(stats, key, tuple)) { + Py_DECREF(key); + Py_DECREF(tuple); + Py_DECREF(stats); + free(listp); + return NULL; + } + } + free(listp); + return stats; +} +#endif + +#if (DBVER >= 46) +static PyObject* +DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) +{ + int err; + int flags=0; + static char* kwnames[] = { "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print", + kwnames, &flags)) + { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->repmgr_stat_print(self->db_env, flags); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs) +{ + int err; + int flags=0; + DB_REPMGR_STAT *statp; + PyObject *stats; + static char* kwnames[] = { "flags", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat", + kwnames, &flags)) + { + return NULL; + } + CHECK_ENV_NOT_CLOSED(self); + MYDB_BEGIN_ALLOW_THREADS; + err = self->db_env->repmgr_stat(self->db_env, &statp, flags); + MYDB_END_ALLOW_THREADS; + RETURN_IF_ERR(); + + stats=PyDict_New(); + if (stats == NULL) { + free(statp); + return NULL; + } + +#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name) + + MAKE_ENTRY(perm_failed); + MAKE_ENTRY(msgs_queued); + MAKE_ENTRY(msgs_dropped); + MAKE_ENTRY(connection_drop); + MAKE_ENTRY(connect_fail); + +#undef MAKE_ENTRY + + free(statp); + return stats; +} +#endif + + +/* --------------------------------------------------------------------- */ +/* DBTxn methods */ + + +static void _close_transaction_cursors(DBTxnObject* txn) +{ + PyObject *dummy; + + while(txn->children_cursors) { + PyErr_Warn(PyExc_RuntimeWarning, + "Must close cursors before resolving a transaction."); + dummy=DBC_close_internal(txn->children_cursors); + Py_XDECREF(dummy); + } +} + +static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn) +{ + DBObject *db; +#if (DBVER >= 43) + DBSequenceObject *dbs; +#endif + + while (txn->children_dbs) { + db=txn->children_dbs; + EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db); + if (txn->parent_txn) { + INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db); + db->txn=txn->parent_txn; + } else { + /* The db is already linked to its environment, + ** so nothing to do. + */ + db->txn=NULL; + } + } + +#if (DBVER >= 43) + while (txn->children_sequences) { + dbs=txn->children_sequences; + EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs); + if (txn->parent_txn) { + INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs); + dbs->txn=txn->parent_txn; + } else { + /* The sequence is already linked to its + ** parent db. Nothing to do. + */ + dbs->txn=NULL; + } + } +#endif +} + + +static PyObject* +DBTxn_commit(DBTxnObject* self, PyObject* args) +{ + int flags=0, err; + DB_TXN *txn; + + if (!PyArg_ParseTuple(args, "|i:commit", &flags)) + return NULL; + + _close_transaction_cursors(self); + + if (!self->txn) { + PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " + "after txn_commit, txn_abort " + "or txn_discard"); + if (t) { + PyErr_SetObject(DBError, t); + Py_DECREF(t); + } + return NULL; + } + self->flag_prepare=0; + txn = self->txn; + self->txn = NULL; /* this DB_TXN is no longer valid after this call */ + + EXTRACT_FROM_DOUBLE_LINKED_LIST(self); + + MYDB_BEGIN_ALLOW_THREADS; + err = txn->commit(txn, flags); + MYDB_END_ALLOW_THREADS; + + _promote_transaction_dbs_and_sequences(self); + + RETURN_IF_ERR(); + RETURN_NONE(); +} + +static PyObject* +DBTxn_prepare(DBTxnObject* self, PyObject* args) +{ + int err; + char* gid=NULL; + int gid_size=0; + + if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size)) + return NULL; + + if (gid_size != DB_XIDDATASIZE) { + PyErr_SetString(PyExc_TypeError, + "gid must be DB_XIDDATASIZE bytes long"); + return NULL; + } + + if (!self->txn) { + PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used " + "after txn_commit, txn_abort " + "or txn_discard"); + if (t) { + PyErr_SetObject(DBError, t); + Py_DECREF(t); + } return NULL; } + self->flag_prepare=1; /* Prepare state */ MYDB_BEGIN_ALLOW_THREADS; - err = txn_prepare(self->txn); + err = self->txn->prepare(self->txn, (u_int8_t*)gid); MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); RETURN_NONE(); -#endif } static PyObject* -DBTxn_abort(DBTxnObject* self, PyObject* args) +DBTxn_abort_discard_internal(DBTxnObject* self, int discard) { - int err; + PyObject *dummy; + int err=0; DB_TXN *txn; - if (!PyArg_ParseTuple(args, ":abort")) - return NULL; - if (!self->txn) { PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " - "after txn_commit or txn_abort"); - PyErr_SetObject(DBError, t); - Py_DECREF(t); + "after txn_commit, txn_abort " + "or txn_discard"); + if (t) { + PyErr_SetObject(DBError, t); + Py_DECREF(t); + } return NULL; } txn = self->txn; self->txn = NULL; /* this DB_TXN is no longer valid after this call */ - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = txn->abort(txn); -#else - err = txn_abort(txn); + + _close_transaction_cursors(self); +#if (DBVER >= 43) + while (self->children_sequences) { + dummy=DBSequence_close_internal(self->children_sequences,0,0); + Py_XDECREF(dummy); + } #endif + while (self->children_dbs) { + dummy=DB_close_internal(self->children_dbs,0); + Py_XDECREF(dummy); + } + + EXTRACT_FROM_DOUBLE_LINKED_LIST(self); + + MYDB_BEGIN_ALLOW_THREADS; + if (discard) { + assert(!self->flag_prepare); + err = txn->discard(txn,0); + } else { + /* + ** If the transaction is in the "prepare" or "recover" state, + ** we better do not implicitly abort it. + */ + if (!self->flag_prepare) { + err = txn->abort(txn); + } + } MYDB_END_ALLOW_THREADS; RETURN_IF_ERR(); RETURN_NONE(); } +static PyObject* +DBTxn_abort(DBTxnObject* self) +{ + self->flag_prepare=0; + _close_transaction_cursors(self); + + return DBTxn_abort_discard_internal(self,0); +} + +static PyObject* +DBTxn_discard(DBTxnObject* self) +{ + self->flag_prepare=0; + _close_transaction_cursors(self); + + return DBTxn_abort_discard_internal(self,1); +} + static PyObject* -DBTxn_id(DBTxnObject* self, PyObject* args) +DBTxn_id(DBTxnObject* self) { int id; - if (!PyArg_ParseTuple(args, ":id")) - return NULL; - if (!self->txn) { PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " - "after txn_commit or txn_abort"); - PyErr_SetObject(DBError, t); - Py_DECREF(t); + "after txn_commit, txn_abort " + "or txn_discard"); + if (t) { + PyErr_SetObject(DBError, t); + Py_DECREF(t); + } return NULL; } MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) id = self->txn->id(self->txn); -#else - id = txn_id(self->txn); -#endif MYDB_END_ALLOW_THREADS; - return PyLong_FromLong(id); + return NUMBER_FromLong(id); } #if (DBVER >= 43) @@ -4849,24 +6017,41 @@ static PyObject* -DBSequence_close(DBSequenceObject* self, PyObject* args) +DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close) { - int err, flags=0; - if (!PyArg_ParseTuple(args,"|i:close", &flags)) - return NULL; - CHECK_SEQUENCE_NOT_CLOSED(self) + int err=0; - MYDB_BEGIN_ALLOW_THREADS - err = self->sequence->close(self->sequence, flags); - self->sequence = NULL; - MYDB_END_ALLOW_THREADS + if (self->sequence!=NULL) { + EXTRACT_FROM_DOUBLE_LINKED_LIST(self); + if (self->txn) { + EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); + self->txn=NULL; + } - RETURN_IF_ERR(); + if (!do_not_close) { + MYDB_BEGIN_ALLOW_THREADS + err = self->sequence->close(self->sequence, flags); + MYDB_END_ALLOW_THREADS + } + self->sequence = NULL; + + RETURN_IF_ERR(); + } RETURN_NONE(); } static PyObject* +DBSequence_close(DBSequenceObject* self, PyObject* args) +{ + int flags=0; + if (!PyArg_ParseTuple(args,"|i:close", &flags)) + return NULL; + + return DBSequence_close_internal(self,flags,0); +} + +static PyObject* DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs) { int err, flags = 0; @@ -4888,25 +6073,23 @@ RETURN_IF_ERR(); return PyLong_FromLongLong(value); - } static PyObject* -DBSequence_get_dbp(DBSequenceObject* self, PyObject* args) +DBSequence_get_dbp(DBSequenceObject* self) { - if (!PyArg_ParseTuple(args,":get_dbp")) - return NULL; CHECK_SEQUENCE_NOT_CLOSED(self) Py_INCREF(self->mydb); return (PyObject* )self->mydb; } static PyObject* -DBSequence_get_key(DBSequenceObject* self, PyObject* args) +DBSequence_get_key(DBSequenceObject* self) { int err; DBT key; PyObject *retval = NULL; + key.flags = DB_DBT_MALLOC; CHECK_SEQUENCE_NOT_CLOSED(self) MYDB_BEGIN_ALLOW_THREADS @@ -4914,9 +6097,9 @@ MYDB_END_ALLOW_THREADS if (!err) - retval = PyBytes_FromStringAndSize(key.data, key.size); + retval = Build_PyString(key.data, key.size); - free_dbt(&key); + FREE_DBT(key); RETURN_IF_ERR(); return retval; @@ -4926,13 +6109,15 @@ DBSequence_init_value(DBSequenceObject* self, PyObject* args) { int err; - db_seq_t value; + PY_LONG_LONG value; + db_seq_t value2; if (!PyArg_ParseTuple(args,"L:init_value", &value)) return NULL; CHECK_SEQUENCE_NOT_CLOSED(self) + value2=value; /* If truncation, compiler should show a warning */ MYDB_BEGIN_ALLOW_THREADS - err = self->sequence->initial_value(self->sequence, value); + err = self->sequence->initial_value(self->sequence, value2); MYDB_END_ALLOW_THREADS RETURN_IF_ERR(); @@ -4944,8 +6129,7 @@ DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs) { int err, flags = 0; - PyObject *keyobj; - Py_buffer *key_buf_view = NULL; + PyObject* keyobj; PyObject *txnobj = NULL; DB_TXN *txn = NULL; DBT key; @@ -4957,22 +6141,28 @@ if (!checkTxnObj(txnobj, &txn)) return NULL; - if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view)) + if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) return NULL; MYDB_BEGIN_ALLOW_THREADS err = self->sequence->open(self->sequence, txn, &key, flags); MYDB_END_ALLOW_THREADS - FREE_DBT_VIEW(key, keyobj, key_buf_view); + CLEAR_DBT(key); RETURN_IF_ERR(); + if (txn) { + INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self); + self->txn=(DBTxnObject *)txnobj; + } + RETURN_NONE(); } static PyObject* DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs) { + PyObject *dummy; int err, flags = 0; PyObject *txnobj = NULL; DB_TXN *txn = NULL; @@ -4990,6 +6180,9 @@ err = self->sequence->remove(self->sequence, txn, flags); MYDB_END_ALLOW_THREADS + dummy=DBSequence_close_internal(self,flags,1); + Py_XDECREF(dummy); + RETURN_IF_ERR(); RETURN_NONE(); } @@ -5011,11 +6204,10 @@ } static PyObject* -DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args) +DBSequence_get_cachesize(DBSequenceObject* self) { int err, size; - if (!PyArg_ParseTuple(args,":get_cachesize")) - return NULL; + CHECK_SEQUENCE_NOT_CLOSED(self) MYDB_BEGIN_ALLOW_THREADS @@ -5023,7 +6215,7 @@ MYDB_END_ALLOW_THREADS RETURN_IF_ERR(); - return PyLong_FromLong(size); + return NUMBER_FromLong(size); } static PyObject* @@ -5040,16 +6232,14 @@ RETURN_IF_ERR(); RETURN_NONE(); - } static PyObject* -DBSequence_get_flags(DBSequenceObject* self, PyObject* args) +DBSequence_get_flags(DBSequenceObject* self) { unsigned int flags; int err; - if (!PyArg_ParseTuple(args,":get_flags")) - return NULL; + CHECK_SEQUENCE_NOT_CLOSED(self) MYDB_BEGIN_ALLOW_THREADS @@ -5057,20 +6247,23 @@ MYDB_END_ALLOW_THREADS RETURN_IF_ERR(); - return PyLong_FromLong((int)flags); + return NUMBER_FromLong((int)flags); } static PyObject* DBSequence_set_range(DBSequenceObject* self, PyObject* args) { int err; - db_seq_t min, max; + PY_LONG_LONG min, max; + db_seq_t min2, max2; if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max)) return NULL; CHECK_SEQUENCE_NOT_CLOSED(self) + min2=min; /* If truncation, compiler should show a warning */ + max2=max; MYDB_BEGIN_ALLOW_THREADS - err = self->sequence->set_range(self->sequence, min, max); + err = self->sequence->set_range(self->sequence, min2, max2); MYDB_END_ALLOW_THREADS RETURN_IF_ERR(); @@ -5078,19 +6271,21 @@ } static PyObject* -DBSequence_get_range(DBSequenceObject* self, PyObject* args) +DBSequence_get_range(DBSequenceObject* self) { int err; - db_seq_t min, max; - if (!PyArg_ParseTuple(args,":get_range")) - return NULL; + PY_LONG_LONG min, max; + db_seq_t min2, max2; + CHECK_SEQUENCE_NOT_CLOSED(self) MYDB_BEGIN_ALLOW_THREADS - err = self->sequence->get_range(self->sequence, &min, &max); + err = self->sequence->get_range(self->sequence, &min2, &max2); MYDB_END_ALLOW_THREADS RETURN_IF_ERR(); + min=min2; /* If truncation, compiler should show a warning */ + max=max2; return Py_BuildValue("(LL)", min, max); } @@ -5142,27 +6337,23 @@ /* Method definition tables and type objects */ static PyMethodDef DB_methods[] = { - {"append", (PyCFunction)DB_append, METH_VARARGS}, -#if (DBVER >= 33) + {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS}, {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS}, -#endif {"close", (PyCFunction)DB_close, METH_VARARGS}, {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS}, {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS}, {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS}, {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS}, - {"fd", (PyCFunction)DB_fd, METH_VARARGS}, + {"fd", (PyCFunction)DB_fd, METH_NOARGS}, {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 33) {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS}, -#endif {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS}, - {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS}, + {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS}, {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS}, - {"get_type", (PyCFunction)DB_get_type, METH_VARARGS}, + {"get_type", (PyCFunction)DB_get_type, METH_NOARGS}, {"join", (PyCFunction)DB_join, METH_VARARGS}, {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS}, - {"has_key", (PyCFunction)DB_has_key, METH_VARARGS}, + {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS}, {"items", (PyCFunction)DB_items, METH_VARARGS}, {"keys", (PyCFunction)DB_keys, METH_VARARGS}, {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS}, @@ -5170,9 +6361,7 @@ {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS}, {"rename", (PyCFunction)DB_rename, METH_VARARGS}, {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS}, -#if (DBVER >= 33) - {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS}, -#endif + {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O}, {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS}, #if (DBVER >= 41) {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS}, @@ -5186,13 +6375,13 @@ {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS}, {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS}, {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS}, - {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS}, + {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS}, + {"set_private", (PyCFunction)DB_set_private, METH_O}, + {"get_private", (PyCFunction)DB_get_private, METH_NOARGS}, {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS}, {"sync", (PyCFunction)DB_sync, METH_VARARGS}, -#if (DBVER >= 33) {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS}, -#endif - {"type", (PyCFunction)DB_get_type, METH_VARARGS}, + {"type", (PyCFunction)DB_get_type, METH_NOARGS}, {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS}, {"values", (PyCFunction)DB_values, METH_VARARGS}, {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS}, @@ -5209,17 +6398,15 @@ static PyMethodDef DBCursor_methods[] = { - {"close", (PyCFunction)DBC_close, METH_VARARGS}, + {"close", (PyCFunction)DBC_close, METH_NOARGS}, {"count", (PyCFunction)DBC_count, METH_VARARGS}, {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS}, {"delete", (PyCFunction)DBC_delete, METH_VARARGS}, {"dup", (PyCFunction)DBC_dup, METH_VARARGS}, {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS}, {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 33) {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS}, -#endif - {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS}, + {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS}, {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS}, {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS}, {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS}, @@ -5227,7 +6414,7 @@ {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS}, {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS}, {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS}, - {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS}, + {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS}, {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS}, {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS}, {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS}, @@ -5248,19 +6435,21 @@ {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS}, {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS}, #endif -#if (DBVER >= 40) {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS}, -#endif {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS}, {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS}, {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS}, {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS}, +#if (DBVER >= 47) + {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS}, +#endif {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS}, {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS}, {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS}, -#if (DBVER >= 33) - {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS}, +#if (DBVER >= 42) + {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS}, #endif + {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS}, {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS}, #if (DBVER < 45) {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS}, @@ -5277,20 +6466,78 @@ {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS}, {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS}, {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS}, - {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS}, -#if (DBVER >= 40) + {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS}, {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS}, -#endif {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS}, {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS}, {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS}, -#if (DBVER >= 40) + {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS}, {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS}, -#endif #if (DBVER >= 44) {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS}, #endif {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS}, + {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS}, + {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server, + METH_VARARGS||METH_KEYWORDS}, + {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS}, +#if (DBVER >= 42) + {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS}, +#endif + {"set_private", (PyCFunction)DBEnv_set_private, METH_O}, + {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS}, + {"rep_start", (PyCFunction)DBEnv_rep_start, + METH_VARARGS|METH_KEYWORDS}, + {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS}, + {"rep_process_message", (PyCFunction)DBEnv_rep_process_message, + METH_VARARGS}, +#if (DBVER >= 46) + {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS}, +#endif +#if (DBVER >= 44) + {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS}, + {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS}, + {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS}, +#endif +#if (DBVER >= 45) + {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS}, + {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS}, +#endif +#if (DBVER >= 47) + {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS}, + {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS}, +#endif +#if (DBVER >= 45) + {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O}, +#endif +#if (DBVER >= 45) + {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS}, + {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS}, + {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS}, + {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS}, + {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS}, + {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS}, +#endif +#if (DBVER >= 45) + {"repmgr_start", (PyCFunction)DBEnv_repmgr_start, + METH_VARARGS|METH_KEYWORDS}, + {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site, + METH_VARARGS|METH_KEYWORDS}, + {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site, + METH_VARARGS|METH_KEYWORDS}, + {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy, + METH_VARARGS}, + {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy, + METH_NOARGS}, + {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list, + METH_NOARGS}, +#endif +#if (DBVER >= 46) + {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat, + METH_VARARGS|METH_KEYWORDS}, + {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print, + METH_VARARGS|METH_KEYWORDS}, +#endif {NULL, NULL} /* sentinel */ }; @@ -5298,8 +6545,9 @@ static PyMethodDef DBTxn_methods[] = { {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS}, {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS}, - {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS}, - {"id", (PyCFunction)DBTxn_id, METH_VARARGS}, + {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS}, + {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS}, + {"id", (PyCFunction)DBTxn_id, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; @@ -5308,30 +6556,40 @@ static PyMethodDef DBSequence_methods[] = { {"close", (PyCFunction)DBSequence_close, METH_VARARGS}, {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS}, - {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS}, - {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS}, + {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS}, + {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS}, {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS}, {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS}, {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS}, {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS}, - {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS}, + {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS}, {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS}, - {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS}, + {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS}, {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS}, - {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS}, + {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS}, {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS}, {NULL, NULL} /* sentinel */ }; #endif + static PyObject* DBEnv_db_home_get(DBEnvObject* self) { + const char *home = NULL; + CHECK_ENV_NOT_CLOSED(self); - if (self->db_env->db_home == NULL) { + +#if (DBVER >= 42) + self->db_env->get_home(self->db_env, &home); +#else + home=self->db_env->db_home; +#endif + + if (home == NULL) { RETURN_NONE(); } - return PyUnicode_FromString(self->db_env->db_home); + return PyBytes_FromString(home); } static PyGetSetDef DBEnv_getsets[] = { @@ -5340,16 +6598,21 @@ }; -static PyTypeObject DB_Type = { +statichere PyTypeObject DB_Type = { +#if (PY_VERSION_HEX < 0x03000000) + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ +#else PyVarObject_HEAD_INIT(NULL, 0) +#endif "DB", /*tp_name*/ sizeof(DBObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)DB_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ @@ -5359,55 +6622,75 @@ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ - 0, /* tp_setattro */ + 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ +#if (PY_VERSION_HEX < 0x03000000) + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ +#else + Py_TPFLAGS_DEFAULT, /* tp_flags */ +#endif + 0, /* tp_doc */ + 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - DB_methods, /* tp_methods */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + DB_methods, /*tp_methods*/ + 0, /*tp_members*/ }; -static PyTypeObject DBCursor_Type = { +statichere PyTypeObject DBCursor_Type = { +#if (PY_VERSION_HEX < 0x03000000) + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ +#else PyVarObject_HEAD_INIT(NULL, 0) +#endif "DBCursor", /*tp_name*/ sizeof(DBCursorObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + 0, /*tp_itemsize*/ /* methods */ (destructor)DBCursor_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ +#if (PY_VERSION_HEX < 0x03000000) + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ +#else + Py_TPFLAGS_DEFAULT, /* tp_flags */ +#endif + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - DBCursor_methods, /* tp_methods */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + DBCursor_methods, /*tp_methods*/ + 0, /*tp_members*/ }; -static PyTypeObject DBEnv_Type = { +statichere PyTypeObject DBEnv_Type = { +#if (PY_VERSION_HEX < 0x03000000) + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ +#else PyVarObject_HEAD_INIT(NULL, 0) +#endif "DBEnv", /*tp_name*/ sizeof(DBEnvObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -5425,23 +6708,32 @@ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ - 0, /* tp_setattro */ + 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ +#if (PY_VERSION_HEX < 0x03000000) + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ +#else + Py_TPFLAGS_DEFAULT, /* tp_flags */ +#endif + 0, /* tp_doc */ + 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ + 0, /* tp_iter */ + 0, /* tp_iternext */ DBEnv_methods, /* tp_methods */ - 0, /* tp_members */ + 0, /* tp_members */ DBEnv_getsets, /* tp_getsets */ }; -static PyTypeObject DBTxn_Type = { +statichere PyTypeObject DBTxn_Type = { +#if (PY_VERSION_HEX < 0x03000000) + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ +#else PyVarObject_HEAD_INIT(NULL, 0) +#endif "DBTxn", /*tp_name*/ sizeof(DBTxnObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -5459,22 +6751,32 @@ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ - 0, /* tp_setattro */ + 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ +#if (PY_VERSION_HEX < 0x03000000) + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ +#else + Py_TPFLAGS_DEFAULT, /* tp_flags */ +#endif + 0, /* tp_doc */ + 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - DBTxn_methods, /* tp_methods */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + DBTxn_methods, /*tp_methods*/ + 0, /*tp_members*/ }; -static PyTypeObject DBLock_Type = { +statichere PyTypeObject DBLock_Type = { +#if (PY_VERSION_HEX < 0x03000000) + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ +#else PyVarObject_HEAD_INIT(NULL, 0) +#endif "DBLock", /*tp_name*/ sizeof(DBLockObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -5492,19 +6794,28 @@ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ - 0, /* tp_setattro */ + 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ +#if (PY_VERSION_HEX < 0x03000000) + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ +#else + Py_TPFLAGS_DEFAULT, /* tp_flags */ +#endif + 0, /* tp_doc */ + 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */ }; #if (DBVER >= 43) -static PyTypeObject DBSequence_Type = { +statichere PyTypeObject DBSequence_Type = { +#if (PY_VERSION_HEX < 0x03000000) + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ +#else PyVarObject_HEAD_INIT(NULL, 0) +#endif "DBSequence", /*tp_name*/ sizeof(DBSequenceObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -5524,15 +6835,20 @@ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ +#if (PY_VERSION_HEX < 0x03000000) + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ +#else + Py_TPFLAGS_DEFAULT, /* tp_flags */ +#endif 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - DBSequence_methods, /* tp_methods */ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + DBSequence_methods, /*tp_methods*/ + 0, /*tp_members*/ }; #endif @@ -5591,29 +6907,27 @@ underlying DB library."; static PyObject* -bsddb_version(PyObject* self, PyObject* args) +bsddb_version(PyObject* self) { int major, minor, patch; - if (!PyArg_ParseTuple(args, ":version")) - return NULL; - db_version(&major, &minor, &patch); - return Py_BuildValue("(iii)", major, minor, patch); + db_version(&major, &minor, &patch); + return Py_BuildValue("(iii)", major, minor, patch); } /* List of functions defined in the module */ - static PyMethodDef bsddb_methods[] = { {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS }, {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS}, -#if (DBVER >= 43) +#if (DBVER >= 43) {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS }, -#endif - {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc}, +#endif + {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc}, {NULL, NULL} /* sentinel */ }; + /* API structure */ static BSDDB_api bsddb_api; @@ -5630,44 +6944,51 @@ #define MODULE_NAME_MAX_LEN 11 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb"; - -static struct PyModuleDef _bsddbmodule = { - PyModuleDef_HEAD_INIT, - _bsddbModuleName, - NULL, - -1, - bsddb_methods, - NULL, - NULL, - NULL, - NULL +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef bsddbmodule = { + PyModuleDef_HEAD_INIT, + _bsddbModuleName, /* Name of module */ + NULL, /* module documentation, may be NULL */ + -1, /* size of per-interpreter state of the module, + or -1 if the module keeps state in global variables. */ + bsddb_methods, + NULL, /* Reload */ + NULL, /* Traverse */ + NULL, /* Clear */ + NULL /* Free */ }; +#endif -PyMODINIT_FUNC PyInit__bsddb(void) + +#if (PY_VERSION_HEX < 0x03000000) +DL_EXPORT(void) init_bsddb(void) +#else +PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */ +#endif { PyObject* m; PyObject* d; - PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION); - PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING); - PyObject* svnid_s = PyUnicode_FromString(svn_id); + PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION ); + PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING ); + PyObject* cvsid_s = PyBytes_FromString( rcs_id ); PyObject* py_api; /* Initialize object types */ - if (PyType_Ready(&DB_Type) < 0) - return NULL; - if (PyType_Ready(&DBCursor_Type) < 0) - return NULL; - if (PyType_Ready(&DBEnv_Type) < 0) - return NULL; - if (PyType_Ready(&DBTxn_Type) < 0) - return NULL; - if (PyType_Ready(&DBLock_Type) < 0) - return NULL; + if ((PyType_Ready(&DB_Type) < 0) + || (PyType_Ready(&DBCursor_Type) < 0) + || (PyType_Ready(&DBEnv_Type) < 0) + || (PyType_Ready(&DBTxn_Type) < 0) + || (PyType_Ready(&DBLock_Type) < 0) #if (DBVER >= 43) - if (PyType_Ready(&DBSequence_Type) < 0) + || (PyType_Ready(&DBSequence_Type) < 0) +#endif + ) { +#if (PY_VERSION_HEX < 0x03000000) + return; +#else return NULL; #endif - + } #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE) /* Save the current interpreter, so callbacks can do the right thing. */ @@ -5675,19 +6996,28 @@ #endif /* Create the module and add the functions */ - m = PyModule_Create(&_bsddbmodule); - if (m == NULL) +#if (PY_VERSION_HEX < 0x03000000) + m = Py_InitModule(_bsddbModuleName, bsddb_methods); +#else + m=PyModule_Create(&bsddbmodule); +#endif + if (m == NULL) { +#if (PY_VERSION_HEX < 0x03000000) + return; +#else return NULL; +#endif + } /* Add some symbolic constants to the module */ d = PyModule_GetDict(m); PyDict_SetItemString(d, "__version__", pybsddb_version_s); - PyDict_SetItemString(d, "cvsid", svnid_s); + PyDict_SetItemString(d, "cvsid", cvsid_s); PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s); Py_DECREF(pybsddb_version_s); pybsddb_version_s = NULL; - Py_DECREF(svnid_s); - svnid_s = NULL; + Py_DECREF(cvsid_s); + cvsid_s = NULL; Py_DECREF(db_version_s); db_version_s = NULL; @@ -5702,7 +7032,7 @@ ADD_INT(d, DB_RPCCLIENT); #else ADD_INT(d, DB_CLIENT); - /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */ + /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */ _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT); #endif ADD_INT(d, DB_XA_CREATE); @@ -5710,6 +7040,9 @@ ADD_INT(d, DB_CREATE); ADD_INT(d, DB_NOMMAP); ADD_INT(d, DB_THREAD); +#if (DBVER >= 45) + ADD_INT(d, DB_MULTIVERSION); +#endif ADD_INT(d, DB_FORCE); ADD_INT(d, DB_INIT_CDB); @@ -5719,6 +7052,8 @@ ADD_INT(d, DB_INIT_TXN); ADD_INT(d, DB_JOINENV); + ADD_INT(d, DB_XIDDATASIZE); + ADD_INT(d, DB_RECOVER); ADD_INT(d, DB_RECOVER_FATAL); ADD_INT(d, DB_TXN_NOSYNC); @@ -5747,10 +7082,7 @@ ADD_INT(d, DB_NOORDERCHK); ADD_INT(d, DB_ORDERCHKONLY); ADD_INT(d, DB_PR_PAGE); -#if ! (DBVER >= 33) - ADD_INT(d, DB_VRFY_FLAGMASK); - ADD_INT(d, DB_PR_HEADERS); -#endif + ADD_INT(d, DB_PR_RECOVERYTEST); ADD_INT(d, DB_SALVAGE); @@ -5759,19 +7091,16 @@ ADD_INT(d, DB_LOCK_OLDEST); ADD_INT(d, DB_LOCK_RANDOM); ADD_INT(d, DB_LOCK_YOUNGEST); -#if (DBVER >= 33) ADD_INT(d, DB_LOCK_MAXLOCKS); ADD_INT(d, DB_LOCK_MINLOCKS); ADD_INT(d, DB_LOCK_MINWRITE); -#endif + ADD_INT(d, DB_LOCK_EXPIRE); +#if (DBVER >= 43) + ADD_INT(d, DB_LOCK_MAXWRITE); +#endif -#if (DBVER >= 33) - /* docs say to use zero instead */ _addIntToDict(d, "DB_LOCK_CONFLICT", 0); -#else - ADD_INT(d, DB_LOCK_CONFLICT); -#endif ADD_INT(d, DB_LOCK_DUMP); ADD_INT(d, DB_LOCK_GET); @@ -5788,39 +7117,31 @@ ADD_INT(d, DB_LOCK_IWRITE); ADD_INT(d, DB_LOCK_IREAD); ADD_INT(d, DB_LOCK_IWR); -#if (DBVER >= 33) #if (DBVER < 44) ADD_INT(d, DB_LOCK_DIRTY); #else ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */ #endif ADD_INT(d, DB_LOCK_WWRITE); -#endif ADD_INT(d, DB_LOCK_RECORD); ADD_INT(d, DB_LOCK_UPGRADE); ADD_INT(d, DB_LOCK_SWITCH); -#if (DBVER >= 33) ADD_INT(d, DB_LOCK_UPGRADE_WRITE); -#endif ADD_INT(d, DB_LOCK_NOWAIT); ADD_INT(d, DB_LOCK_RECORD); ADD_INT(d, DB_LOCK_UPGRADE); -#if (DBVER >= 33) ADD_INT(d, DB_LSTAT_ABORTED); #if (DBVER < 43) ADD_INT(d, DB_LSTAT_ERR); #endif ADD_INT(d, DB_LSTAT_FREE); ADD_INT(d, DB_LSTAT_HELD); -#if (DBVER == 33) - ADD_INT(d, DB_LSTAT_NOGRANT); -#endif + ADD_INT(d, DB_LSTAT_PENDING); ADD_INT(d, DB_LSTAT_WAITING); -#endif ADD_INT(d, DB_ARCH_ABS); ADD_INT(d, DB_ARCH_DATA); @@ -5850,21 +7171,20 @@ #if (DBVER < 45) ADD_INT(d, DB_CACHED_COUNTS); #endif + #if (DBVER >= 41) _addIntToDict(d, "DB_CHECKPOINT", 0); #else ADD_INT(d, DB_CHECKPOINT); ADD_INT(d, DB_CURLSN); #endif -#if ((DBVER >= 33) && (DBVER <= 41)) +#if (DBVER <= 41) ADD_INT(d, DB_COMMIT); #endif ADD_INT(d, DB_CONSUME); ADD_INT(d, DB_CONSUME_WAIT); ADD_INT(d, DB_CURRENT); -#if (DBVER >= 33) ADD_INT(d, DB_FAST_STAT); -#endif ADD_INT(d, DB_FIRST); ADD_INT(d, DB_FLUSH); ADD_INT(d, DB_GET_BOTH); @@ -5892,21 +7212,16 @@ ADD_INT(d, DB_OPFLAGS_MASK); ADD_INT(d, DB_RMW); -#if (DBVER >= 33) ADD_INT(d, DB_DIRTY_READ); ADD_INT(d, DB_MULTIPLE); ADD_INT(d, DB_MULTIPLE_KEY); -#endif #if (DBVER >= 44) ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */ ADD_INT(d, DB_READ_COMMITTED); #endif -#if (DBVER >= 33) ADD_INT(d, DB_DONOTINDEX); - ADD_INT(d, DB_XIDDATASIZE); -#endif #if (DBVER >= 41) _addIntToDict(d, "DB_INCOMPLETE", 0); @@ -5924,17 +7239,17 @@ ADD_INT(d, DB_OLD_VERSION); ADD_INT(d, DB_RUNRECOVERY); ADD_INT(d, DB_VERIFY_BAD); -#if (DBVER >= 33) ADD_INT(d, DB_PAGE_NOTFOUND); ADD_INT(d, DB_SECONDARY_BAD); -#endif -#if (DBVER >= 40) ADD_INT(d, DB_STAT_CLEAR); ADD_INT(d, DB_REGION_INIT); ADD_INT(d, DB_NOLOCKING); ADD_INT(d, DB_YIELDCPU); ADD_INT(d, DB_PANIC_ENVIRONMENT); ADD_INT(d, DB_NOPANIC); + +#if (DBVER >= 41) + ADD_INT(d, DB_OVERWRITE); #endif #ifdef DB_REGISTER @@ -5945,27 +7260,118 @@ ADD_INT(d, DB_TIME_NOTGRANTED); ADD_INT(d, DB_TXN_NOT_DURABLE); ADD_INT(d, DB_TXN_WRITE_NOSYNC); - ADD_INT(d, DB_LOG_AUTOREMOVE); - ADD_INT(d, DB_DIRECT_LOG); ADD_INT(d, DB_DIRECT_DB); ADD_INT(d, DB_INIT_REP); ADD_INT(d, DB_ENCRYPT); ADD_INT(d, DB_CHKSUM); #endif +#if (DBVER >= 42) && (DBVER < 47) + ADD_INT(d, DB_LOG_AUTOREMOVE); + ADD_INT(d, DB_DIRECT_LOG); +#endif + +#if (DBVER >= 47) + ADD_INT(d, DB_LOG_DIRECT); + ADD_INT(d, DB_LOG_DSYNC); + ADD_INT(d, DB_LOG_IN_MEMORY); + ADD_INT(d, DB_LOG_AUTO_REMOVE); + ADD_INT(d, DB_LOG_ZERO); +#endif + +#if (DBVER >= 44) + ADD_INT(d, DB_DSYNC_DB); +#endif + +#if (DBVER >= 45) + ADD_INT(d, DB_TXN_SNAPSHOT); +#endif + + ADD_INT(d, DB_VERB_DEADLOCK); +#if (DBVER >= 46) + ADD_INT(d, DB_VERB_FILEOPS); + ADD_INT(d, DB_VERB_FILEOPS_ALL); +#endif + ADD_INT(d, DB_VERB_RECOVERY); +#if (DBVER >= 44) + ADD_INT(d, DB_VERB_REGISTER); +#endif + ADD_INT(d, DB_VERB_REPLICATION); + ADD_INT(d, DB_VERB_WAITSFOR); + +#if (DBVER >= 45) + ADD_INT(d, DB_EVENT_PANIC); + ADD_INT(d, DB_EVENT_REP_CLIENT); +#if (DBVER >= 46) + ADD_INT(d, DB_EVENT_REP_ELECTED); +#endif + ADD_INT(d, DB_EVENT_REP_MASTER); + ADD_INT(d, DB_EVENT_REP_NEWMASTER); +#if (DBVER >= 46) + ADD_INT(d, DB_EVENT_REP_PERM_FAILED); +#endif + ADD_INT(d, DB_EVENT_REP_STARTUPDONE); + ADD_INT(d, DB_EVENT_WRITE_FAILED); +#endif + + ADD_INT(d, DB_REP_DUPMASTER); + ADD_INT(d, DB_REP_HOLDELECTION); +#if (DBVER >= 44) + ADD_INT(d, DB_REP_IGNORE); + ADD_INT(d, DB_REP_JOIN_FAILURE); +#endif +#if (DBVER >= 42) + ADD_INT(d, DB_REP_ISPERM); + ADD_INT(d, DB_REP_NOTPERM); +#endif + ADD_INT(d, DB_REP_NEWSITE); + + ADD_INT(d, DB_REP_MASTER); + ADD_INT(d, DB_REP_CLIENT); +#if (DBVER >= 45) + ADD_INT(d, DB_REP_ELECTION); + + ADD_INT(d, DB_REP_ACK_TIMEOUT); + ADD_INT(d, DB_REP_CONNECTION_RETRY); + ADD_INT(d, DB_REP_ELECTION_TIMEOUT); + ADD_INT(d, DB_REP_ELECTION_RETRY); +#endif +#if (DBVER >= 46) + ADD_INT(d, DB_REP_CHECKPOINT_DELAY); + ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT); +#endif + +#if (DBVER >= 45) + ADD_INT(d, DB_REPMGR_PEER); + ADD_INT(d, DB_REPMGR_ACKS_ALL); + ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS); + ADD_INT(d, DB_REPMGR_ACKS_NONE); + ADD_INT(d, DB_REPMGR_ACKS_ONE); + ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER); + ADD_INT(d, DB_REPMGR_ACKS_QUORUM); + ADD_INT(d, DB_REPMGR_CONNECTED); + ADD_INT(d, DB_REPMGR_DISCONNECTED); + ADD_INT(d, DB_STAT_CLEAR); + ADD_INT(d, DB_STAT_ALL); +#endif + #if (DBVER >= 43) - ADD_INT(d, DB_LOG_INMEMORY); ADD_INT(d, DB_BUFFER_SMALL); ADD_INT(d, DB_SEQ_DEC); ADD_INT(d, DB_SEQ_INC); ADD_INT(d, DB_SEQ_WRAP); #endif +#if (DBVER >= 43) && (DBVER < 47) + ADD_INT(d, DB_LOG_INMEMORY); + ADD_INT(d, DB_DSYNC_LOG); +#endif + #if (DBVER >= 41) ADD_INT(d, DB_ENCRYPT_AES); ADD_INT(d, DB_AUTO_COMMIT); #else - /* allow berkeleydb 4.1 aware apps to run on older versions */ + /* allow Berkeley DB 4.1 aware apps to run on older versions */ _addIntToDict(d, "DB_AUTO_COMMIT", 0); #endif @@ -5979,10 +7385,8 @@ ADD_INT(d, ENOENT); ADD_INT(d, EPERM); -#if (DBVER >= 40) ADD_INT(d, DB_SET_LOCK_TIMEOUT); ADD_INT(d, DB_SET_TXN_TIMEOUT); -#endif /* The exception name must be correct for pickled exception * * objects to unpickle properly. */ @@ -6000,20 +7404,37 @@ DBError = NULL; /* used in MAKE_EX so that it derives from nothing */ MAKE_EX(DBError); +#if (PY_VERSION_HEX < 0x03000000) /* Some magic to make DBNotFoundError and DBKeyEmptyError derive * from both DBError and KeyError, since the API only supports * using one base class. */ PyDict_SetItemString(d, "KeyError", PyExc_KeyError); - { - PyObject *builtin_mod = PyImport_ImportModule("builtins"); - PyDict_SetItemString(d, "__builtins__", builtin_mod); - } PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n" "class DBKeyEmptyError(DBError, KeyError): pass", Py_file_input, d, d); DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError"); DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError"); PyDict_DelItemString(d, "KeyError"); +#else + /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to + ** derive from several classes. We use this new API only for Python 3.0, + ** though. + */ + { + PyObject* bases; + + bases = PyTuple_Pack(2, DBError, PyExc_KeyError); + +#define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \ + PyDict_SetItemString(d, #name, name) + MAKE_EX2(DBNotFoundError); + MAKE_EX2(DBKeyEmptyError); + +#undef MAKE_EX2 + + Py_XDECREF(bases); + } +#endif #if !INCOMPLETE_IS_WARNING @@ -6030,10 +7451,8 @@ MAKE_EX(DBNoServerError); MAKE_EX(DBNoServerHomeError); MAKE_EX(DBNoServerIDError); -#if (DBVER >= 33) MAKE_EX(DBPageNotFoundError); MAKE_EX(DBSecondaryBadError); -#endif MAKE_EX(DBInvalidArgError); MAKE_EX(DBAccessError); @@ -6045,6 +7464,12 @@ MAKE_EX(DBNoSuchFileError); MAKE_EX(DBPermissionsError); +#if (DBVER >= 42) + MAKE_EX(DBRepHandleDeadError); +#endif + + MAKE_EX(DBRepUnavailError); + #undef MAKE_EX /* Initiliase the C API structure and add it to the module */ @@ -6065,18 +7490,31 @@ /* Check for errors */ if (PyErr_Occurred()) { PyErr_Print(); - Py_FatalError("can't initialize module _bsddb"); - Py_DECREF(m); - m = NULL; + Py_FatalError("can't initialize module _bsddb/_pybsddb"); + Py_DECREF(m); + m = NULL; } +#if (PY_VERSION_HEX < 0x03000000) + return; +#else return m; +#endif } /* allow this module to be named _pybsddb so that it can be installed * and imported on top of python >= 2.3 that includes its own older * copy of the library named _bsddb without importing the old version. */ -PyMODINIT_FUNC init_pybsddb(void) +#if (PY_VERSION_HEX < 0x03000000) +DL_EXPORT(void) init_pybsddb(void) +#else +PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */ +#endif { strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN); - return PyInit__bsddb(); +#if (PY_VERSION_HEX < 0x03000000) + init_bsddb(); +#else + return PyInit__bsddb(); /* Note the two underscores */ +#endif } + Modified: python/branches/py3k/Modules/bsddb.h ============================================================================== --- python/branches/py3k/Modules/bsddb.h (original) +++ python/branches/py3k/Modules/bsddb.h Sun Aug 31 16:12:11 2008 @@ -36,7 +36,7 @@ /* * Handwritten code to wrap version 3.x of the Berkeley DB library, * written to replace a SWIG-generated file. It has since been updated - * to compile with BerkeleyDB versions 3.2 through 4.2. + * to compile with Berkeley DB versions 3.2 through 4.2. * * This module was started by Andrew Kuchling to remove the dependency * on SWIG in a package by Gregory P. Smith who based his work on a @@ -105,7 +105,7 @@ #error "eek! DBVER can't handle minor versions > 9" #endif -#define PY_BSDDB_VERSION "4.6.0" +#define PY_BSDDB_VERSION "4.7.3pre2" /* Python object definitions */ @@ -119,17 +119,27 @@ }; + +struct DBObject; /* Forward declaration */ +struct DBCursorObject; /* Forward declaration */ +struct DBTxnObject; /* Forward declaration */ +struct DBSequenceObject; /* Forward declaration */ + typedef struct { PyObject_HEAD DB_ENV* db_env; u_int32_t flags; /* saved flags from open() */ int closed; struct behaviourFlags moduleFlags; + PyObject* event_notifyCallback; + struct DBObject *children_dbs; + struct DBTxnObject *children_txns; + PyObject *private_obj; + PyObject *rep_transport; PyObject *in_weakreflist; /* List of weak references */ } DBEnvObject; - -typedef struct { +typedef struct DBObject { PyObject_HEAD DB* db; DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */ @@ -137,27 +147,48 @@ u_int32_t setflags; /* saved flags from set_flags() */ int haveStat; struct behaviourFlags moduleFlags; -#if (DBVER >= 33) + struct DBTxnObject *txn; + struct DBCursorObject *children_cursors; +#if (DBVER >=43) + struct DBSequenceObject *children_sequences; +#endif + struct DBObject **sibling_prev_p; + struct DBObject *sibling_next; + struct DBObject **sibling_prev_p_txn; + struct DBObject *sibling_next_txn; PyObject* associateCallback; PyObject* btCompareCallback; int primaryDBType; -#endif + PyObject *private_obj; PyObject *in_weakreflist; /* List of weak references */ } DBObject; -typedef struct { +typedef struct DBCursorObject { PyObject_HEAD DBC* dbc; + struct DBCursorObject **sibling_prev_p; + struct DBCursorObject *sibling_next; + struct DBCursorObject **sibling_prev_p_txn; + struct DBCursorObject *sibling_next_txn; DBObject* mydb; + struct DBTxnObject *txn; PyObject *in_weakreflist; /* List of weak references */ } DBCursorObject; -typedef struct { +typedef struct DBTxnObject { PyObject_HEAD DB_TXN* txn; - PyObject *env; + DBEnvObject* env; + int flag_prepare; + struct DBTxnObject *parent_txn; + struct DBTxnObject **sibling_prev_p; + struct DBTxnObject *sibling_next; + struct DBTxnObject *children_txns; + struct DBObject *children_dbs; + struct DBSequenceObject *children_sequences; + struct DBCursorObject *children_cursors; PyObject *in_weakreflist; /* List of weak references */ } DBTxnObject; @@ -170,13 +201,17 @@ #if (DBVER >= 43) -typedef struct { +typedef struct DBSequenceObject { PyObject_HEAD DB_SEQUENCE* sequence; DBObject* mydb; + struct DBTxnObject *txn; + struct DBSequenceObject **sibling_prev_p; + struct DBSequenceObject *sibling_next; + struct DBSequenceObject **sibling_prev_p_txn; + struct DBSequenceObject *sibling_next_txn; PyObject *in_weakreflist; /* List of weak references */ } DBSequenceObject; -static PyTypeObject DBSequence_Type; #endif Modified: python/branches/py3k/setup.py ============================================================================== --- python/branches/py3k/setup.py (original) +++ python/branches/py3k/setup.py Sun Aug 31 16:12:11 2008 @@ -673,12 +673,8 @@ # a release. Most open source OSes come with one or more # versions of BerkeleyDB already installed. - max_db_ver = (4, 5) # XXX(gregory.p.smith): 4.6 "works" but seems to - # have issues on many platforms. I've temporarily - # disabled 4.6 to see what the odd platform - # buildbots say. - max_db_ver = (4, 7) # XXX(matthias.klose): test with 4.7 on some buildds - min_db_ver = (3, 3) + max_db_ver = (4, 7) + min_db_ver = (4, 0) db_setup_debug = False # verbose debug prints from this script? # construct a list of paths to look for the header file in on From python-3000-checkins at python.org Sun Aug 31 18:35:01 2008 From: python-3000-checkins at python.org (gregory.p.smith) Date: Sun, 31 Aug 2008 18:35:01 +0200 (CEST) Subject: [Python-3000-checkins] r66094 - python/branches/py3k/Lib/hashlib.py Message-ID: <20080831163501.71B961E4005@bag.python.org> Author: gregory.p.smith Date: Sun Aug 31 18:35:01 2008 New Revision: 66094 Log: issue3715: docstring representation of hex escaped string needs to be double escaped. Modified: python/branches/py3k/Lib/hashlib.py Modified: python/branches/py3k/Lib/hashlib.py ============================================================================== --- python/branches/py3k/Lib/hashlib.py (original) +++ python/branches/py3k/Lib/hashlib.py Sun Aug 31 18:35:01 2008 @@ -44,7 +44,7 @@ >>> m.update(b"Nobody inspects") >>> m.update(b" the spammish repetition") >>> m.digest() - b'\xbbd\x9c\x83\xdd\x1e\xa5\xc9\xd9\xde\xc9\xa1\x8d\xf0\xff\xe9' + b'\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9' More condensed: