From bwarsaw@users.sourceforge.net Fri Mar 1 00:42:51 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Thu, 28 Feb 2002 16:42:51 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0001.txt,1.28,1.29 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv737 Modified Files: pep-0001.txt Log Message: Last-Modified: is now a required header. Index: pep-0001.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0001.txt,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** pep-0001.txt 12 Nov 2001 14:57:18 -0000 1.28 --- pep-0001.txt 1 Mar 2002 00:42:48 -0000 1.29 *************** *** 186,190 **** Title: Version: ! * Last-Modified: Author: * Discussions-To: --- 186,190 ---- Title: Version: ! Last-Modified: Author: * Discussions-To: From mal@lemburg.com Fri Mar 1 08:28:31 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Fri, 01 Mar 2002 09:28:31 +0100 Subject: [Python-checkins] CVS: python/nondist/peps pep-0001.txt,1.28,1.29 References: Message-ID: <3C7F3BAF.56514E85@lemburg.com> Barry Warsaw wrote: > > Update of /cvsroot/python/python/nondist/peps > In directory usw-pr-cvs1:/tmp/cvs-serv737 > > Modified Files: > pep-0001.txt > Log Message: > Last-Modified: is now a required header. Isn't this unnecessary duplication ? The CVS history has all this information available, including patches, comments, etc. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From loewis@users.sourceforge.net Fri Mar 1 08:31:09 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 00:31:09 -0800 Subject: [Python-checkins] CVS: python/dist/src/PC pyconfig.h,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/PC In directory usw-pr-cvs1:/tmp/cvs-serv30289/PC Modified Files: pyconfig.h Log Message: Patch #520062: Support IPv6 with VC.NET. Index: pyconfig.h =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/pyconfig.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pyconfig.h 21 Dec 2001 22:06:12 -0000 1.6 --- pyconfig.h 1 Mar 2002 08:31:07 -0000 1.7 *************** *** 409,413 **** --- 409,417 ---- /* Define to `int' if doesn't define. */ + #if _MSC_VER + 0 >= 1300 + /* VC.NET typedefs socklen_t in ws2tcpip.h. */ + #else #define socklen_t int + #endif /* Define if you have the ANSI C header files. */ From loewis@users.sourceforge.net Fri Mar 1 08:31:09 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 00:31:09 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules socketmodule.c,1.208,1.209 socketmodule.h,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv30289/Modules Modified Files: socketmodule.c socketmodule.h Log Message: Patch #520062: Support IPv6 with VC.NET. Index: socketmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/socketmodule.c,v retrieving revision 1.208 retrieving revision 1.209 diff -C2 -d -r1.208 -r1.209 *** socketmodule.c 17 Feb 2002 04:13:21 -0000 1.208 --- socketmodule.c 1 Mar 2002 08:31:07 -0000 1.209 *************** *** 410,415 **** --- 410,418 ---- PyObject *v; + #ifdef EAI_SYSTEM + /* EAI_SYSTEM is not available on Windows XP. */ if (error == EAI_SYSTEM) return PySocket_Err(); + #endif #ifdef HAVE_GAI_STRERROR Index: socketmodule.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/socketmodule.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** socketmodule.h 25 Feb 2002 14:45:40 -0000 1.4 --- socketmodule.h 1 Mar 2002 08:31:07 -0000 1.5 *************** *** 10,14 **** --- 10,24 ---- #else /* MS_WINDOWS */ + #if _MSC_VER >= 1300 + # include + # include + # define HAVE_ADDRINFO + # define HAVE_SOCKADDR_STORAGE + # define HAVE_GETADDRINFO + # define HAVE_GETNAMEINFO + # define ENABLE_IPV6 + #else # include + #endif #endif From mwh@users.sourceforge.net Fri Mar 1 08:58:34 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Fri, 01 Mar 2002 00:58:34 -0800 Subject: [Python-checkins] CVS: python/dist/src setup.py,1.73,1.73.4.1 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv3842 Modified Files: Tag: release22-maint setup.py Log Message: Whitespace normalization. Index: setup.py =================================================================== RCS file: /cvsroot/python/python/dist/src/setup.py,v retrieving revision 1.73 retrieving revision 1.73.4.1 diff -C2 -d -r1.73 -r1.73.4.1 *** setup.py 17 Dec 2001 17:24:43 -0000 1.73 --- setup.py 1 Mar 2002 08:58:32 -0000 1.73.4.1 *************** *** 65,69 **** self.announce("WARNING: multiple copies of %s found"%module) return os.path.join(list[0], module) ! class PyBuildExt(build_ext): --- 65,69 ---- self.announce("WARNING: multiple copies of %s found"%module) return os.path.join(list[0], module) ! class PyBuildExt(build_ext): *************** *** 87,94 **** srcdir = os.path.normpath(srcdir) moddir = os.path.normpath(moddir) ! moddirlist = [moddir] incdirlist = ['./Include'] ! # Platform-dependent module source and include directories platform = self.get_platform() --- 87,94 ---- srcdir = os.path.normpath(srcdir) moddir = os.path.normpath(moddir) ! moddirlist = [moddir] incdirlist = ['./Include'] ! # Platform-dependent module source and include directories platform = self.get_platform() *************** *** 116,120 **** # Parse Modules/Setup to figure out which modules are turned ! # on in the file. input = text_file.TextFile('Modules/Setup', join_lines=1) remove_modules = [] --- 116,120 ---- # Parse Modules/Setup to figure out which modules are turned ! # on in the file. input = text_file.TextFile('Modules/Setup', join_lines=1) remove_modules = [] *************** *** 125,133 **** remove_modules.append( line[0] ) input.close() ! for ext in self.extensions[:]: if ext.name in remove_modules: self.extensions.remove(ext) ! # When you run "make CC=altcc" or something similar, you really want # those environment variables passed into the setup.py phase. Here's --- 125,133 ---- remove_modules.append( line[0] ) input.close() ! for ext in self.extensions[:]: if ext.name in remove_modules: self.extensions.remove(ext) ! # When you run "make CC=altcc" or something similar, you really want # those environment variables passed into the setup.py phase. Here's *************** *** 158,165 **** # reliably imported into a command-line Python if 'Carbon' in ext.extra_link_args: ! self.announce( ! 'WARNING: skipping import check for Carbon-based "%s"' % ! ext.name) ! return try: __import__(ext.name) --- 158,165 ---- # reliably imported into a command-line Python if 'Carbon' in ext.extra_link_args: ! self.announce( ! 'WARNING: skipping import check for Carbon-based "%s"' % ! ext.name) ! return try: __import__(ext.name) *************** *** 208,221 **** # be assumed that no additional -I,-L directives are needed. lib_dirs = self.compiler.library_dirs + ['/lib', '/usr/lib'] ! inc_dirs = self.compiler.include_dirs + ['/usr/include'] exts = [] platform = self.get_platform() ! # Check for MacOS X, which doesn't need libm.a at all math_libs = ['m'] if platform in ['darwin', 'beos']: math_libs = [] ! # XXX Omitted modules: gl, pure, dl, SGI-specific modules --- 208,221 ---- # be assumed that no additional -I,-L directives are needed. lib_dirs = self.compiler.library_dirs + ['/lib', '/usr/lib'] ! inc_dirs = self.compiler.include_dirs + ['/usr/include'] exts = [] platform = self.get_platform() ! # Check for MacOS X, which doesn't need libm.a at all math_libs = ['m'] if platform in ['darwin', 'beos']: math_libs = [] ! # XXX Omitted modules: gl, pure, dl, SGI-specific modules *************** *** 414,418 **** elif self.compiler.find_library_file(lib_dirs, 'db'): dblib = ['db'] ! db185_incs = find_file('db_185.h', inc_dirs, ['/usr/include/db3', '/usr/include/db2']) --- 414,418 ---- elif self.compiler.find_library_file(lib_dirs, 'db'): dblib = ['db'] ! db185_incs = find_file('db_185.h', inc_dirs, ['/usr/include/db3', '/usr/include/db2']) *************** *** 475,480 **** elif (self.compiler.find_library_file(lib_dirs, 'curses') and platform != 'darwin'): ! # OSX has an old Berkeley curses, not good enough for ! # the _curses module. if (self.compiler.find_library_file(lib_dirs, 'terminfo')): curses_libs = ['curses', 'terminfo'] --- 475,480 ---- elif (self.compiler.find_library_file(lib_dirs, 'curses') and platform != 'darwin'): ! # OSX has an old Berkeley curses, not good enough for ! # the _curses module. if (self.compiler.find_library_file(lib_dirs, 'terminfo')): curses_libs = ['curses', 'terminfo'] *************** *** 576,580 **** # SunOS specific modules exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) ) ! if platform == 'darwin': # Mac OS X specific modules. These are ported over from MacPython --- 576,580 ---- # SunOS specific modules exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) ) ! if platform == 'darwin': # Mac OS X specific modules. These are ported over from MacPython *************** *** 589,639 **** exts.append( Extension('gestalt', ['gestaltmodule.c']) ) exts.append( Extension('MacOS', ['macosmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('icglue', ['icgluemodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('macfs', ['macfsmodule.c', '../Python/getapplbycreator.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_CF', ['cf/_CFmodule.c']) ) exts.append( Extension('_Res', ['res/_Resmodule.c']) ) exts.append( Extension('_Snd', ['snd/_Sndmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) if frameworkdir: exts.append( Extension('Nav', ['Nav.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_AE', ['ae/_AEmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_App', ['app/_Appmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_CarbonEvt', ['carbonevt/_CarbonEvtmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_CG', ['cg/_CGmodule.c'], ! extra_link_args=['-framework', 'ApplicationServices', '-framework', 'Carbon']) ) exts.append( Extension('_Cm', ['cm/_Cmmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Ctl', ['ctl/_Ctlmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Dlg', ['dlg/_Dlgmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Drag', ['drag/_Dragmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Evt', ['evt/_Evtmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Fm', ['fm/_Fmmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Icn', ['icn/_Icnmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_List', ['list/_Listmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Menu', ['menu/_Menumodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Mlte', ['mlte/_Mltemodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Qd', ['qd/_Qdmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Qdoffs', ['qdoffs/_Qdoffsmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Qt', ['qt/_Qtmodule.c'], extra_link_args=['-framework', 'QuickTime', --- 589,639 ---- exts.append( Extension('gestalt', ['gestaltmodule.c']) ) exts.append( Extension('MacOS', ['macosmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('icglue', ['icgluemodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('macfs', ['macfsmodule.c', '../Python/getapplbycreator.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_CF', ['cf/_CFmodule.c']) ) exts.append( Extension('_Res', ['res/_Resmodule.c']) ) exts.append( Extension('_Snd', ['snd/_Sndmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) if frameworkdir: exts.append( Extension('Nav', ['Nav.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_AE', ['ae/_AEmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_App', ['app/_Appmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_CarbonEvt', ['carbonevt/_CarbonEvtmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_CG', ['cg/_CGmodule.c'], ! extra_link_args=['-framework', 'ApplicationServices', '-framework', 'Carbon']) ) exts.append( Extension('_Cm', ['cm/_Cmmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Ctl', ['ctl/_Ctlmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Dlg', ['dlg/_Dlgmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Drag', ['drag/_Dragmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Evt', ['evt/_Evtmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Fm', ['fm/_Fmmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Icn', ['icn/_Icnmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_List', ['list/_Listmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Menu', ['menu/_Menumodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Mlte', ['mlte/_Mltemodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Qd', ['qd/_Qdmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Qdoffs', ['qdoffs/_Qdoffsmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Qt', ['qt/_Qtmodule.c'], extra_link_args=['-framework', 'QuickTime', *************** *** 641,645 **** ## exts.append( Extension('_Scrap', ['scrap/_Scrapmodule.c']) ) exts.append( Extension('_TE', ['te/_TEmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) # As there is no standardized place (yet) to put user-installed # Mac libraries on OSX you should put a symlink to your Waste --- 641,645 ---- ## exts.append( Extension('_Scrap', ['scrap/_Scrapmodule.c']) ) exts.append( Extension('_TE', ['te/_TEmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) # As there is no standardized place (yet) to put user-installed # Mac libraries on OSX you should put a symlink to your Waste *************** *** 650,654 **** ["../waste/Static Libraries"]) if waste_incs != None and waste_libs != None: ! exts.append( Extension('waste', ['waste/wastemodule.c', 'Mac/Wastemods/WEObjectHandlers.c', --- 650,654 ---- ["../waste/Static Libraries"]) if waste_incs != None and waste_libs != None: ! exts.append( Extension('waste', ['waste/wastemodule.c', 'Mac/Wastemods/WEObjectHandlers.c', *************** *** 662,667 **** ) ) exts.append( Extension('_Win', ['win/_Winmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) ! self.extensions.extend(exts) --- 662,667 ---- ) ) exts.append( Extension('_Win', ['win/_Winmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) ! self.extensions.extend(exts) *************** *** 672,676 **** def detect_tkinter(self, inc_dirs, lib_dirs): # The _tkinter module. ! # Assume we haven't found any of the libraries or include files # The versions with dots are used on Unix, and the versions without --- 672,676 ---- def detect_tkinter(self, inc_dirs, lib_dirs): # The _tkinter module. ! # Assume we haven't found any of the libraries or include files # The versions with dots are used on Unix, and the versions without *************** *** 679,687 **** for version in ['8.4', '84', '8.3', '83', '8.2', '82', '8.1', '81', '8.0', '80']: ! tklib = self.compiler.find_library_file(lib_dirs, ! 'tk' + version ) ! tcllib = self.compiler.find_library_file(lib_dirs, ! 'tcl' + version ) ! if tklib and tcllib: # Exit the loop when we've found the Tcl/Tk libraries break --- 679,687 ---- for version in ['8.4', '84', '8.3', '83', '8.2', '82', '8.1', '81', '8.0', '80']: ! tklib = self.compiler.find_library_file(lib_dirs, ! 'tk' + version ) ! tcllib = self.compiler.find_library_file(lib_dirs, ! 'tcl' + version ) ! if tklib and tcllib: # Exit the loop when we've found the Tcl/Tk libraries break *************** *** 772,776 **** install.initialize_options(self) self.warn_dir=0 ! def main(): # turn off warnings when deprecated modules are imported --- 772,776 ---- install.initialize_options(self) self.warn_dir=0 ! def main(): # turn off warnings when deprecated modules are imported From loewis@users.sourceforge.net Fri Mar 1 10:27:03 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 02:27:03 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_array.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv25235/Lib/test Modified Files: test_array.py Log Message: Patch 520694: arraymodule.c improvements: - make array.array a type - add Py_UNICODE arrays - support +=, *= Index: test_array.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_array.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** test_array.py 17 Jan 2001 21:51:36 -0000 1.13 --- test_array.py 1 Mar 2002 10:27:01 -0000 1.14 *************** *** 7,18 **** def main(): - testtype('c', 'c') ! for type in (['b', 'h', 'i', 'l', 'f', 'd']): testtype(type, 1) ! unlink(TESTFN) def testoverflow(type, lowerLimit, upperLimit): --- 7,91 ---- def main(): testtype('c', 'c') ! testtype('u', u'\u263a') for type in (['b', 'h', 'i', 'l', 'f', 'd']): testtype(type, 1) ! testunicode() ! testsubclassing() unlink(TESTFN) + def testunicode(): + try: + array.array('b', u'foo') + except TypeError: + pass + else: + raise TestFailed("creating a non-unicode array from " + "a Unicode string should fail") + + x = array.array('u', u'\xa0\xc2\u1234') + x.fromunicode(u' ') + x.fromunicode(u'') + x.fromunicode(u'') + x.fromunicode(u'\x11abc\xff\u1234') + s = x.tounicode() + if s != u'\xa0\xc2\u1234 \x11abc\xff\u1234': + raise TestFailed("fromunicode()/tounicode()") + + s = u'\x00="\'a\\b\x80\xff\u0000\u0001\u1234' + a = array.array('u', s) + if verbose: + print "repr of type 'u' array:", repr(a) + print " expected: array('u', %r)" % s + + def testsubclassing(): + class EditableString(array.array): + def __new__(cls, s, *args, **kwargs): + return array.array.__new__(cls, 'c', s) + + def __init__(self, s, color='blue'): + array.array.__init__(self, 'c', s) + self.color = color + + def strip(self): + self[:] = array.array('c', self.tostring().strip()) + + def __repr__(self): + return 'EditableString(%r)' % self.tostring() + + s = EditableString("\ttest\r\n") + s.strip() + if s.tostring() != 'test': + raise TestFailed, "subclassing array.array failed somewhere" + if s.color != 'blue': + raise TestFailed, "assigning attributes to instance of array subclass" + s.color = 'red' + if s.color != 'red': + raise TestFailed, "assigning attributes to instance of array subclass" + if s.__dict__.keys() != ['color']: + raise TestFailed, "array subclass __dict__" + + class ExaggeratingArray(array.array): + __slots__ = ['offset'] + + def __new__(cls, typecode, data, offset): + return array.array.__new__(cls, typecode, data) + + def __init__(self, typecode, data, offset): + self.offset = offset + + def __getitem__(self, i): + return array.array.__getitem__(self, i) + self.offset + + a = ExaggeratingArray('i', [3, 6, 7, 11], 4) + if a[0] != 7: + raise TestFailed, "array subclass overriding __getitem__" + try: + a.color = 'blue' + except AttributeError: + pass + else: + raise TestFailed, "array subclass __slots__ was ignored" + def testoverflow(type, lowerLimit, upperLimit): *************** *** 55,59 **** def testtype(type, example): - a = array.array(type) a.append(example) --- 128,131 ---- *************** *** 98,101 **** --- 170,200 ---- % a.typecode, `a.tostring()` + # Try out inplace addition and multiplication + a = array.array(type, [example]) + b = a + a += array.array(type, [example]*2) + if a is not b: + raise TestFailed, "array(%s) inplace addition" % `type` + if a != array.array(type, [example] * 3): + raise TestFailed, "array(%s) inplace addition" % `type` + + a *= 5 + if a is not b: + raise TestFailed, "array(%s) inplace multiplication" % `type` + if a != array.array(type, [example] * 15): + raise TestFailed, "array(%s) inplace multiplication" % `type` + + a *= 0 + if a is not b: + raise TestFailed, "array(%s) inplace multiplication by 0" % `type` + if a != array.array(type, []): + raise TestFailed, "array(%s) inplace multiplication by 0" % `type` + + a *= 1000 + if a is not b: + raise TestFailed, "empty array(%s) inplace multiplication" % `type` + if a != array.array(type, []): + raise TestFailed, "empty array(%s) inplace multiplication" % `type` + if type == 'c': a = array.array(type, "abcde") *************** *** 135,138 **** --- 234,275 ---- a.reverse() if a != array.array(type, "dca"): + raise TestFailed, "array(%s) reverse-test" % `type` + elif type == 'u': + a = array.array(type, u"abcde") + a[:-1] = a + if a != array.array(type, u"abcdee"): + raise TestFailed, "array(%s) self-slice-assign (head)" % `type` + a = array.array(type, u"abcde") + a[1:] = a + if a != array.array(type, u"aabcde"): + raise TestFailed, "array(%s) self-slice-assign (tail)" % `type` + a = array.array(type, u"abcde") + a[1:-1] = a + if a != array.array(type, u"aabcdee"): + raise TestFailed, "array(%s) self-slice-assign (cntr)" % `type` + if a.index(u"e") != 5: + raise TestFailed, "array(%s) index-test" % `type` + if a.count(u"a") != 2: + raise TestFailed, "array(%s) count-test" % `type` + a.remove(u"e") + if a != array.array(type, u"aabcde"): + raise TestFailed, "array(%s) remove-test" % `type` + if a.pop(0) != u"a": + raise TestFailed, "array(%s) pop-test" % `type` + if a.pop(1) != u"b": + raise TestFailed, "array(%s) pop-test" % `type` + a.extend(array.array(type, u"xyz")) + if a != array.array(type, u"acdexyz"): + raise TestFailed, "array(%s) extend-test" % `type` + a.pop() + a.pop() + a.pop() + x = a.pop() + if x != u'e': + raise TestFailed, "array(%s) pop-test" % `type` + if a != array.array(type, u"acd"): + raise TestFailed, "array(%s) pop-test" % `type` + a.reverse() + if a != array.array(type, u"dca"): raise TestFailed, "array(%s) reverse-test" % `type` else: From loewis@users.sourceforge.net Fri Mar 1 10:27:03 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 02:27:03 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules arraymodule.c,2.66,2.67 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv25235/Modules Modified Files: arraymodule.c Log Message: Patch 520694: arraymodule.c improvements: - make array.array a type - add Py_UNICODE arrays - support +=, *= Index: arraymodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/arraymodule.c,v retrieving revision 2.66 retrieving revision 2.67 diff -C2 -d -r2.66 -r2.67 *** arraymodule.c 8 Dec 2001 18:02:55 -0000 2.66 --- arraymodule.c 1 Mar 2002 10:27:01 -0000 2.67 *************** *** 28,32 **** typedef struct arrayobject { ! PyObject_VAR_HEAD char *ob_item; struct arraydescr *ob_descr; --- 28,33 ---- typedef struct arrayobject { ! PyObject_HEAD ! int ob_size; char *ob_item; struct arraydescr *ob_descr; *************** *** 35,39 **** staticforward PyTypeObject Arraytype; ! #define is_arrayobject(op) ((op)->ob_type == &Arraytype) /**************************************************************************** --- 36,41 ---- staticforward PyTypeObject Arraytype; ! #define array_Check(op) PyObject_TypeCheck(op, &Arraytype) ! #define array_CheckExact(op) ((op)->ob_type == &Arraytype) /**************************************************************************** *************** *** 62,66 **** return -1; if (i >= 0) ! ((char *)ap->ob_item)[i] = x; return 0; } --- 64,68 ---- return -1; if (i >= 0) ! ((char *)ap->ob_item)[i] = x; return 0; } *************** *** 114,121 **** return -1; if (i >= 0) ! ((char *)ap->ob_item)[i] = x; return 0; } static PyObject * h_getitem(arrayobject *ap, int i) --- 116,148 ---- return -1; if (i >= 0) ! ((char *)ap->ob_item)[i] = x; return 0; } + #ifdef Py_USING_UNICODE + static PyObject * + u_getitem(arrayobject *ap, int i) + { + return PyUnicode_FromUnicode(&((Py_UNICODE *) ap->ob_item)[i], 1); + } + + static int + u_setitem(arrayobject *ap, int i, PyObject *v) + { + Py_UNICODE *p; + int len; + + if (!PyArg_Parse(v, "u#;array item must be unicode character", &p, &len)) + return -1; + if (len != 1) { + PyErr_SetString(PyExc_TypeError, "array item must be unicode character"); + return -1; + } + if (i >= 0) + ((Py_UNICODE *)ap->ob_item)[i] = p[0]; + return 0; + } + #endif + static PyObject * h_getitem(arrayobject *ap, int i) *************** *** 316,319 **** --- 343,349 ---- {'b', sizeof(char), b_getitem, b_setitem}, {'B', sizeof(char), BB_getitem, BB_setitem}, + #ifdef Py_USING_UNICODE + {'u', sizeof(Py_UNICODE), u_getitem, u_setitem}, + #endif {'h', sizeof(short), h_getitem, h_setitem}, {'H', sizeof(short), HH_getitem, HH_setitem}, *************** *** 332,343 **** static PyObject * ! newarrayobject(int size, struct arraydescr *descr) { arrayobject *op; size_t nbytes; if (size < 0) { PyErr_BadInternalCall(); return NULL; } nbytes = size * descr->itemsize; /* Check for overflow */ --- 362,375 ---- static PyObject * ! newarrayobject(PyTypeObject *type, int size, struct arraydescr *descr) { arrayobject *op; size_t nbytes; + if (size < 0) { PyErr_BadInternalCall(); return NULL; } + nbytes = size * descr->itemsize; /* Check for overflow */ *************** *** 345,352 **** return PyErr_NoMemory(); } ! op = PyObject_NewVar(arrayobject, &Arraytype, size); if (op == NULL) { ! return PyErr_NoMemory(); } if (size <= 0) { op->ob_item = NULL; --- 377,385 ---- return PyErr_NoMemory(); } ! op = (arrayobject *) type->tp_alloc(type, 0); if (op == NULL) { ! return NULL; } + op->ob_size = size; if (size <= 0) { op->ob_item = NULL; *************** *** 367,371 **** { register arrayobject *ap; ! assert(is_arrayobject(op)); ap = (arrayobject *)op; if (i < 0 || i >= ap->ob_size) { --- 400,404 ---- { register arrayobject *ap; ! assert(array_Check(op)); ap = (arrayobject *)op; if (i < 0 || i >= ap->ob_size) { *************** *** 412,416 **** if (op->ob_item != NULL) PyMem_DEL(op->ob_item); ! PyObject_Del(op); } --- 445,449 ---- if (op->ob_item != NULL) PyMem_DEL(op->ob_item); ! op->ob_type->tp_free((PyObject *)op); } *************** *** 424,428 **** PyObject *res; ! if (!is_arrayobject(v) || !is_arrayobject(w)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; --- 457,461 ---- PyObject *res; ! if (!array_Check(v) || !array_Check(w)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; *************** *** 531,535 **** else if (ihigh > a->ob_size) ihigh = a->ob_size; ! np = (arrayobject *) newarrayobject(ihigh - ilow, a->ob_descr); if (np == NULL) return NULL; --- 564,568 ---- else if (ihigh > a->ob_size) ihigh = a->ob_size; ! np = (arrayobject *) newarrayobject(&Arraytype, ihigh - ilow, a->ob_descr); if (np == NULL) return NULL; *************** *** 544,548 **** int size; arrayobject *np; ! if (!is_arrayobject(bb)) { PyErr_Format(PyExc_TypeError, "can only append array (not \"%.200s\") to array", --- 577,581 ---- int size; arrayobject *np; ! if (!array_Check(bb)) { PyErr_Format(PyExc_TypeError, "can only append array (not \"%.200s\") to array", *************** *** 556,560 **** } size = a->ob_size + b->ob_size; ! np = (arrayobject *) newarrayobject(size, a->ob_descr); if (np == NULL) { return NULL; --- 589,593 ---- } size = a->ob_size + b->ob_size; ! np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); if (np == NULL) { return NULL; *************** *** 578,582 **** n = 0; size = a->ob_size * n; ! np = (arrayobject *) newarrayobject(size, a->ob_descr); if (np == NULL) return NULL; --- 611,615 ---- n = 0; size = a->ob_size * n; ! np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr); if (np == NULL) return NULL; *************** *** 599,603 **** if (v == NULL) n = 0; ! else if (is_arrayobject(v)) { n = b->ob_size; if (a == b) { --- 632,636 ---- if (v == NULL) n = 0; ! else if (array_Check(v)) { n = b->ob_size; if (a == b) { *************** *** 677,684 **** setarrayitem(PyObject *a, int i, PyObject *v) { ! assert(is_arrayobject(a)); return array_ass_item((arrayobject *)a, i, v); } static PyObject * ins(arrayobject *self, int where, PyObject *v) --- 710,792 ---- setarrayitem(PyObject *a, int i, PyObject *v) { ! assert(array_Check(a)); return array_ass_item((arrayobject *)a, i, v); } + static int + array_do_extend(arrayobject *self, PyObject *bb) + { + int size; + + if (!array_Check(bb)) { + PyErr_Format(PyExc_TypeError, + "can only extend array with array (not \"%.200s\")", + bb->ob_type->tp_name); + return -1; + } + #define b ((arrayobject *)bb) + if (self->ob_descr != b->ob_descr) { + PyErr_SetString(PyExc_TypeError, + "can only extend with array of same kind"); + return -1; + } + size = self->ob_size + b->ob_size; + PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize); + if (self->ob_item == NULL) { + PyObject_Del(self); + PyErr_NoMemory(); + return -1; + } + memcpy(self->ob_item + self->ob_size*self->ob_descr->itemsize, + b->ob_item, b->ob_size*b->ob_descr->itemsize); + self->ob_size = size; + + return 0; + #undef b + } + + static PyObject * + array_inplace_concat(arrayobject *self, PyObject *bb) + { + if (array_do_extend(self, bb) == -1) + return NULL; + Py_INCREF(self); + return (PyObject *)self; + } + + static PyObject * + array_inplace_repeat(arrayobject *self, int n) + { + char *items, *p; + int size, i; + + if (self->ob_size > 0) { + if (n < 0) + n = 0; + items = self->ob_item; + size = self->ob_size * self->ob_descr->itemsize; + if (n == 0) { + PyMem_FREE(items); + self->ob_item = NULL; + self->ob_size = 0; + } + else { + PyMem_Resize(items, char, n * size); + if (items == NULL) + return PyErr_NoMemory(); + p = items; + for (i = 1; i < n; i++) { + p += size; + memcpy(p, items, size); + } + self->ob_item = items; + self->ob_size *= n; + } + } + Py_INCREF(self); + return (PyObject *)self; + } + + static PyObject * ins(arrayobject *self, int where, PyObject *v) *************** *** 808,841 **** array_extend(arrayobject *self, PyObject *args) { - int size; PyObject *bb; if (!PyArg_ParseTuple(args, "O:extend", &bb)) - return NULL; - - if (!is_arrayobject(bb)) { - PyErr_Format(PyExc_TypeError, - "can only extend array with array (not \"%.200s\")", - bb->ob_type->tp_name); return NULL; ! } ! #define b ((arrayobject *)bb) ! if (self->ob_descr != b->ob_descr) { ! PyErr_SetString(PyExc_TypeError, ! "can only extend with array of same kind"); return NULL; ! } ! size = self->ob_size + b->ob_size; ! PyMem_RESIZE(self->ob_item, char, size*self->ob_descr->itemsize); ! if (self->ob_item == NULL) { ! PyObject_Del(self); ! return PyErr_NoMemory(); ! } ! memcpy(self->ob_item + self->ob_size*self->ob_descr->itemsize, ! b->ob_item, b->ob_size*b->ob_descr->itemsize); ! self->ob_size = size; ! Py_INCREF(Py_None); return Py_None; - #undef b } --- 916,927 ---- array_extend(arrayobject *self, PyObject *args) { PyObject *bb; if (!PyArg_ParseTuple(args, "O:extend", &bb)) return NULL; ! if (array_do_extend(self, bb) == -1) return NULL; ! Py_INCREF(Py_None); return Py_None; } *************** *** 1204,1207 **** --- 1290,1381 ---- representation."; + + + #ifdef Py_USING_UNICODE + static PyObject * + array_fromunicode(arrayobject *self, PyObject *args) + { + Py_UNICODE *ustr; + int n; + + if (!PyArg_ParseTuple(args, "u#:fromunicode", &ustr, &n)) + return NULL; + if (self->ob_descr->typecode != 'u') { + PyErr_SetString(PyExc_ValueError, + "fromunicode() may only be called on " + "type 'u' arrays"); + return NULL; + } + if (n > 0) { + Py_UNICODE *item = (Py_UNICODE *) self->ob_item; + PyMem_RESIZE(item, Py_UNICODE, self->ob_size + n); + if (item == NULL) { + PyErr_NoMemory(); + return NULL; + } + self->ob_item = (char *) item; + self->ob_size += n; + memcpy(item + self->ob_size - n, + ustr, n * sizeof(Py_UNICODE)); + } + + Py_INCREF(Py_None); + return Py_None; + } + + static char fromunicode_doc[] = + "fromunicode(ustr)\n\ + \n\ + Extends this array with data from the unicode string ustr.\n\ + The array must be a type 'u' array; otherwise a ValueError\n\ + is raised. Use array.fromstring(ustr.decode(...)) to\n\ + append Unicode data to an array of some other type."; + + + static PyObject * + array_tounicode(arrayobject *self, PyObject *args) + { + if (!PyArg_ParseTuple(args, ":tounicode")) + return NULL; + if (self->ob_descr->typecode != 'u') { + PyErr_SetString(PyExc_ValueError, + "tounicode() may only be called on type 'u' arrays"); + return NULL; + } + return PyUnicode_FromUnicode((Py_UNICODE *) self->ob_item, self->ob_size); + } + + static char tounicode_doc [] = + "tounicode() -> unicode\n\ + \n\ + Convert the array to a unicode string. The array must be\n\ + a type 'u' array; otherwise a ValueError is raised. Use\n\ + array.tostring().decode() to obtain a unicode string from\n\ + an array of some other type."; + + #endif /* Py_USING_UNICODE */ + + + static PyObject * + array_get_typecode(arrayobject *a, void *closure) + { + char tc = a->ob_descr->typecode; + return PyString_FromStringAndSize(&tc, 1); + } + + static PyObject * + array_get_itemsize(arrayobject *a, void *closure) + { + return PyInt_FromLong((long)a->ob_descr->itemsize); + } + + static PyGetSetDef array_getsets [] = { + {"typecode", (getter) array_get_typecode, NULL, + "the typecode character used to create the array"}, + {"itemsize", (getter) array_get_itemsize, NULL, + "the size, in bytes, of one array item"}, + {NULL} + }; + PyMethodDef array_methods[] = { {"append", (PyCFunction)array_append, METH_VARARGS, *************** *** 1221,1224 **** --- 1395,1402 ---- {"fromstring", (PyCFunction)array_fromstring, METH_VARARGS, fromstring_doc}, + #ifdef Py_USING_UNICODE + {"fromunicode", (PyCFunction)array_fromunicode, METH_VARARGS, + fromunicode_doc}, + #endif {"index", (PyCFunction)array_index, METH_VARARGS, index_doc}, *************** *** 1241,1244 **** --- 1419,1426 ---- {"tostring", (PyCFunction)array_tostring, METH_VARARGS, tostring_doc}, + #ifdef Py_USING_UNICODE + {"tounicode", (PyCFunction)array_tounicode, METH_VARARGS, + tounicode_doc}, + #endif {"write", (PyCFunction)array_tofile, METH_VARARGS, tofile_doc}, *************** *** 1246,1276 **** }; - static PyObject * - array_getattr(arrayobject *a, char *name) - { - if (strcmp(name, "typecode") == 0) { - char tc = a->ob_descr->typecode; - return PyString_FromStringAndSize(&tc, 1); - } - if (strcmp(name, "itemsize") == 0) { - return PyInt_FromLong((long)a->ob_descr->itemsize); - } - if (strcmp(name, "__members__") == 0) { - PyObject *list = PyList_New(2); - if (list) { - PyList_SetItem(list, 0, - PyString_FromString("typecode")); - PyList_SetItem(list, 1, - PyString_FromString("itemsize")); - if (PyErr_Occurred()) { - Py_DECREF(list); - list = NULL; - } - } - return list; - } - return Py_FindMethod(array_methods, (PyObject *)a, name); - } - static int array_print(arrayobject *a, FILE *fp, int flags) --- 1428,1431 ---- *************** *** 1309,1326 **** array_repr(arrayobject *a) { ! char buf[256]; PyObject *s, *t, *comma, *v; int i, len; len = a->ob_size; if (len == 0) { ! PyOS_snprintf(buf, sizeof(buf), "array('%c')", ! a->ob_descr->typecode); return PyString_FromString(buf); } ! if (a->ob_descr->typecode == 'c') { PyObject *t_empty = PyTuple_New(0); ! PyOS_snprintf(buf, sizeof(buf), "array('c', "); s = PyString_FromString(buf); ! v = array_tostring(a, t_empty); Py_DECREF(t_empty); t = PyObject_Repr(v); --- 1464,1486 ---- array_repr(arrayobject *a) { ! char buf[256], typecode; PyObject *s, *t, *comma, *v; int i, len; + len = a->ob_size; + typecode = a->ob_descr->typecode; if (len == 0) { ! PyOS_snprintf(buf, sizeof(buf), "array('%c')", typecode); return PyString_FromString(buf); } ! ! if (typecode == 'c' || typecode == 'u') { PyObject *t_empty = PyTuple_New(0); ! PyOS_snprintf(buf, sizeof(buf), "array('%c', ", typecode); s = PyString_FromString(buf); ! if (typecode == 'c') ! v = array_tostring(a, t_empty); ! else ! v = array_tounicode(a, t_empty); Py_DECREF(t_empty); t = PyObject_Repr(v); *************** *** 1330,1334 **** return s; } ! PyOS_snprintf(buf, sizeof(buf), "array('%c', [", a->ob_descr->typecode); s = PyString_FromString(buf); comma = PyString_FromString(", "); --- 1490,1494 ---- return s; } ! PyOS_snprintf(buf, sizeof(buf), "array('%c', [", typecode); s = PyString_FromString(buf); comma = PyString_FromString(", "); *************** *** 1386,1389 **** --- 1546,1552 ---- (intobjargproc)array_ass_item, /*sq_ass_item*/ (intintobjargproc)array_ass_slice, /*sq_ass_slice*/ + NULL, /*sq_contains*/ + (binaryfunc)array_inplace_concat, /*sq_inplace_concat*/ + (intargfunc)array_inplace_repeat /*sq_inplace_repeat*/ }; *************** *** 1395,1413 **** static PyObject * ! a_array(PyObject *self, PyObject *args) { char c; PyObject *initial = NULL; struct arraydescr *descr; ! if (!PyArg_ParseTuple(args, "c:array", &c)) { ! PyErr_Clear(); ! if (!PyArg_ParseTuple(args, "cO:array", &c, &initial)) return NULL; ! if (!PyList_Check(initial) && !PyString_Check(initial)) { PyErr_SetString(PyExc_TypeError, ! "array initializer must be list or string"); return NULL; } } for (descr = descriptors; descr->typecode != '\0'; descr++) { if (descr->typecode == c) { --- 1558,1589 ---- static PyObject * ! array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { char c; PyObject *initial = NULL; struct arraydescr *descr; ! ! if (kwds != NULL) { ! int i = PyObject_Length(kwds); ! if (i < 0) return NULL; ! else if (i > 0) { PyErr_SetString(PyExc_TypeError, ! "array.array constructor takes " ! "no keyword arguments"); return NULL; } } + + if (!PyArg_ParseTuple(args, "c|O:array", &c, &initial)) + return NULL; + + if (!(initial == NULL || PyList_Check(initial) + || PyString_Check(initial) + || (c == 'u' && PyUnicode_Check(initial)))) { + PyErr_SetString(PyExc_TypeError, + "array initializer must be list or string"); + return NULL; + } for (descr = descriptors; descr->typecode != '\0'; descr++) { if (descr->typecode == c) { *************** *** 1418,1429 **** else len = PyList_Size(initial); ! a = newarrayobject(len, descr); if (a == NULL) return NULL; if (len > 0) { int i; for (i = 0; i < len; i++) { PyObject *v = ! PyList_GetItem(initial, i); if (setarrayitem(a, i, v) != 0) { Py_DECREF(a); --- 1594,1607 ---- else len = PyList_Size(initial); ! ! a = newarrayobject(type, len, descr); if (a == NULL) return NULL; + if (len > 0) { int i; for (i = 0; i < len; i++) { PyObject *v = ! PyList_GetItem(initial, i); if (setarrayitem(a, i, v) != 0) { Py_DECREF(a); *************** *** 1438,1442 **** array_fromstring((arrayobject *)a, t_initial); ! Py_DECREF(t_initial); if (v == NULL) { Py_DECREF(a); --- 1616,1620 ---- array_fromstring((arrayobject *)a, t_initial); ! Py_DECREF(t_initial); if (v == NULL) { Py_DECREF(a); *************** *** 1444,1447 **** --- 1622,1642 ---- } Py_DECREF(v); + #ifdef Py_USING_UNICODE + } else if (initial != NULL && PyUnicode_Check(initial)) { + int n = PyUnicode_GET_DATA_SIZE(initial); + if (n > 0) { + arrayobject *self = (arrayobject *)a; + char *item = self->ob_item; + item = PyMem_Realloc(item, n); + if (item == NULL) { + PyErr_NoMemory(); + Py_DECREF(a); + return NULL; + } + self->ob_item = item; + self->ob_size = n / sizeof(Py_UNICODE); + memcpy(item, PyUnicode_AS_DATA(initial), n); + } + #endif } return a; *************** *** 1449,1470 **** } PyErr_SetString(PyExc_ValueError, ! "bad typecode (must be c, b, B, h, H, i, I, l, L, f or d)"); return NULL; } - static char a_array_doc [] = - "array(typecode [, initializer]) -> array\n\ - \n\ - Return a new array whose items are restricted by typecode, and\n\ - initialized from the optional initializer value, which must be a list\n\ - or a string."; - - static PyMethodDef a_methods[] = { - {"array", a_array, METH_VARARGS, a_array_doc}, - {NULL, NULL} /* sentinel */ - }; static char module_doc [] = ! "This module defines a new object type which can efficiently represent\n\ an array of basic values: characters, integers, floating point\n\ numbers. Arrays are sequence types and behave very much like lists,\n\ --- 1644,1654 ---- } PyErr_SetString(PyExc_ValueError, ! "bad typecode (must be c, b, B, u, h, H, i, I, l, L, f or d)"); return NULL; } static char module_doc [] = ! "This module defines an object type which can efficiently represent\n\ an array of basic values: characters, integers, floating point\n\ numbers. Arrays are sequence types and behave very much like lists,\n\ *************** *** 1477,1480 **** --- 1661,1665 ---- 'b' signed integer 1 \n\ 'B' unsigned integer 1 \n\ + 'u' Unicode character 2 \n\ 'h' signed integer 2 \n\ 'H' unsigned integer 2 \n\ *************** *** 1486,1500 **** 'd' floating point 8 \n\ \n\ ! Functions:\n\ \n\ array(typecode [, initializer]) -- create a new array\n\ - \n\ - Special Objects:\n\ - \n\ - ArrayType -- type object for array objects\n\ "; static char arraytype_doc [] = ! "An array represents basic values and behave very much like lists, except\n\ the type of objects stored in them is constrained.\n\ \n\ --- 1671,1687 ---- 'd' floating point 8 \n\ \n\ ! The constructor is:\n\ \n\ array(typecode [, initializer]) -- create a new array\n\ "; static char arraytype_doc [] = ! "array(typecode [, initializer]) -> array\n\ ! \n\ ! Return a new array whose items are restricted by typecode, and\n\ ! initialized from the optional initializer value, which must be a list\n\ ! or a string.\n\ ! \n\ ! Arrays represent basic values and behave very much like lists, except\n\ the type of objects stored in them is constrained.\n\ \n\ *************** *** 1520,1524 **** write() -- DEPRECATED, use tofile()\n\ \n\ ! Variables:\n\ \n\ typecode -- the typecode character used to create the array\n\ --- 1707,1711 ---- write() -- DEPRECATED, use tofile()\n\ \n\ ! Attributes:\n\ \n\ typecode -- the typecode character used to create the array\n\ *************** *** 1534,1538 **** (destructor)array_dealloc, /* tp_dealloc */ (printfunc)array_print, /* tp_print */ ! (getattrfunc)array_getattr, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ --- 1721,1725 ---- (destructor)array_dealloc, /* tp_dealloc */ (printfunc)array_print, /* tp_print */ ! 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ *************** *** 1544,1557 **** 0, /* tp_call */ 0, /* tp_str */ ! 0, /* tp_getattro */ 0, /* tp_setattro */ &array_as_buffer, /* tp_as_buffer*/ ! Py_TPFLAGS_DEFAULT, /* tp_flags */ arraytype_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ array_richcompare, /* tp_richcompare */ }; DL_EXPORT(void) initarray(void) --- 1731,1765 ---- 0, /* tp_call */ 0, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &array_as_buffer, /* tp_as_buffer*/ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ arraytype_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ array_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + array_methods, /* tp_methods */ + 0, /* tp_members */ + array_getsets, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + array_new, /* tp_new */ + _PyObject_Del, /* tp_free */ }; + /* No functions in array module. */ + static PyMethodDef a_methods[] = { + {NULL, NULL, 0, NULL} /* Sentinel */ + }; + + DL_EXPORT(void) initarray(void) *************** *** 1559,1566 **** PyObject *m, *d; ! Arraytype.ob_type = &PyType_Type; m = Py_InitModule3("array", a_methods, module_doc); d = PyModule_GetDict(m); PyDict_SetItemString(d, "ArrayType", (PyObject *)&Arraytype); /* No need to check the error here, the caller will do that */ } --- 1767,1775 ---- PyObject *m, *d; ! Arraytype.ob_type = &PyType_Type; m = Py_InitModule3("array", a_methods, module_doc); d = PyModule_GetDict(m); PyDict_SetItemString(d, "ArrayType", (PyObject *)&Arraytype); + PyDict_SetItemString(d, "array", (PyObject *)&Arraytype); /* No need to check the error here, the caller will do that */ } From loewis@users.sourceforge.net Fri Mar 1 10:27:03 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 02:27:03 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.357,1.358 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv25235/Misc Modified Files: NEWS Log Message: Patch 520694: arraymodule.c improvements: - make array.array a type - add Py_UNICODE arrays - support +=, *= Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.357 retrieving revision 1.358 diff -C2 -d -r1.357 -r1.358 *** NEWS 16 Feb 2002 23:35:41 -0000 1.357 --- NEWS 1 Mar 2002 10:27:01 -0000 1.358 *************** *** 18,21 **** --- 18,26 ---- Extension modules + - array.array is now a type object. A new format character + 'u' indicates Py_UNICODE arrays. For those, .tounicode and + .fromunicode methods are available. Arrays now support __iadd__ + and __imul__. + - dl now builds on every system that has dlfcn.h. Failure in case of sizeof(int)!=sizeof(long)!=sizeof(void*) is delayed until dl.open From loewis@users.sourceforge.net Fri Mar 1 10:27:03 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 02:27:03 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libarray.tex,1.31,1.32 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv25235/Doc/lib Modified Files: libarray.tex Log Message: Patch 520694: arraymodule.c improvements: - make array.array a type - add Py_UNICODE arrays - support +=, *= Index: libarray.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libarray.tex,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** libarray.tex 20 Oct 2001 04:24:09 -0000 1.31 --- libarray.tex 1 Mar 2002 10:27:01 -0000 1.32 *************** *** 6,10 **** ! This module defines a new object type which can efficiently represent an array of basic values: characters, integers, floating point numbers. Arrays\index{arrays} are sequence types and behave very much --- 6,10 ---- ! This module defines an object type which can efficiently represent an array of basic values: characters, integers, floating point numbers. Arrays\index{arrays} are sequence types and behave very much *************** *** 18,21 **** --- 18,22 ---- \lineiii{'b'}{signed int}{1} \lineiii{'B'}{unsigned int}{1} + \lineiii{'u'}{Unicode character}{2} \lineiii{'h'}{signed int}{2} \lineiii{'H'}{unsigned int}{2} *************** *** 36,56 **** ! The module defines the following function and type object: \begin{funcdesc}{array}{typecode\optional{, initializer}} ! Return a new array whose items are restricted by \var{typecode}, and ! initialized from the optional \var{initializer} value, which must be a ! list or a string. The list or string is passed to the new array's ! \method{fromlist()} or \method{fromstring()} method (see below) to add ! initial items to the array. \end{funcdesc} \begin{datadesc}{ArrayType} ! Type object corresponding to the objects returned by ! \function{array()}. \end{datadesc} ! Array objects support the following data items and methods: \begin{memberdesc}[array]{typecode} --- 37,59 ---- ! The module defines the following type: \begin{funcdesc}{array}{typecode\optional{, initializer}} ! Return a new array whose items are restricted by \var{typecode}, ! and initialized from the optional \var{initializer} value, which ! must be a list or a string. The list or string is passed to the ! new array's \method{fromlist()}, \method{fromstring()}, or ! \method{fromunicode()} method (see below) to add initial items to ! the array. \end{funcdesc} \begin{datadesc}{ArrayType} ! Obsolete alias for \function{array}. \end{datadesc} ! Array objects support the ordinary sequence operations of ! indexing, slicing, concatenation, and multiplication. The ! following data items and methods are also supported: \begin{memberdesc}[array]{typecode} *************** *** 122,125 **** --- 125,135 ---- \end{methoddesc} + \begin{methoddesc}[array]{fromunicode}{s} + Extends this array with data from the given unicode string. + The array must be a type 'u' array; otherwise a ValueError + is raised. Use \samp{array.fromstring(ustr.decode(enc))} to + append Unicode data to an array of some other type. + \end{methoddesc} + \begin{methoddesc}[array]{index}{x} Return the smallest \var{i} such that \var{i} is the index of *************** *** 135,139 **** Removes the item with the index \var{i} from the array and returns it. The optional argument defaults to \code{-1}, so that by default ! the last item is removed and returned. \end{methoddesc} --- 145,149 ---- Removes the item with the index \var{i} from the array and returns it. The optional argument defaults to \code{-1}, so that by default ! the last item is removed and returned. \end{methoddesc} *************** *** 171,174 **** --- 181,191 ---- \end{methoddesc} + \begin{methoddesc}[array]{tounicode}{} + Convert the array to a unicode string. The array must be + a type 'u' array; otherwise a ValueError is raised. Use + array.tostring().decode(enc) to obtain a unicode string + from an array of some other type. + \end{methoddesc} + \begin{methoddesc}[array]{write}{f} \deprecated {1.5.1} *************** *** 189,192 **** --- 206,210 ---- array('l') array('c', 'hello world') + array('u', u'hello \textbackslash u2641') array('l', [1, 2, 3, 4, 5]) array('d', [1.0, 2.0, 3.14]) From loewis@users.sourceforge.net Fri Mar 1 10:38:46 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 02:38:46 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libgrp.tex,1.15,1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv28176/Doc/lib Modified Files: libgrp.tex Log Message: Patch #523268, #522027: return enhanced tuples. Index: libgrp.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libgrp.tex,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** libgrp.tex 8 Jul 2000 16:59:03 -0000 1.15 --- libgrp.tex 1 Mar 2002 10:38:44 -0000 1.16 *************** *** 10,17 **** It is available on all \UNIX{} versions. ! Group database entries are reported as 4-tuples containing the ! following items from the group database (see \code{}), in order: ! \begin{tableiii}{r|l|l}{textrm}{Index}{Field}{Meaning} \lineiii{0}{gr_name}{the name of the group} \lineiii{1}{gr_passwd}{the (encrypted) group password; often empty} --- 10,18 ---- It is available on all \UNIX{} versions. ! Group database entries are reported as a tuple-like object, whose ! attributes correspond to the members of the \code{group} structure ! (Attribute field below, see \code{}): ! \begin{tableiii}{r|l|l}{textrm}{Index}{Attribute}{Meaning} \lineiii{0}{gr_name}{the name of the group} \lineiii{1}{gr_passwd}{the (encrypted) group password; often empty} From loewis@users.sourceforge.net Fri Mar 1 10:38:47 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 02:38:47 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules grpmodule.c,2.16,2.17 pwdmodule.c,1.26,1.27 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv28176/Modules Modified Files: grpmodule.c pwdmodule.c Log Message: Patch #523268, #522027: return enhanced tuples. Index: grpmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/grpmodule.c,v retrieving revision 2.16 retrieving revision 2.17 diff -C2 -d -r2.16 -r2.17 *** grpmodule.c 1 Feb 2002 15:46:29 -0000 2.16 --- grpmodule.c 1 Mar 2002 10:38:44 -0000 2.17 *************** *** 3,17 **** #include "Python.h" #include #include static PyObject * mkgrent(struct group *p) { ! PyObject *v, *w; char **member; if ((w = PyList_New(0)) == NULL) { return NULL; } --- 3,47 ---- #include "Python.h" + #include "structseq.h" #include #include + static PyStructSequence_Field struct_group_type_fields[] = { + {"gr_name", "group name"}, + {"gr_passwd", "password"}, + {"gr_gid", "group id"}, + {"gr_mem", "group memebers"}, + {0} + }; + + static char struct_group__doc__[] = + "grp.struct_group: Results from getgr*() routines.\n\n\ + This object may be accessed either as a tuple of\n\ + (gr_name,gr_passwd,gr_gid,gr_mem)\n\ + or via the object attributes as named in the above tuple.\n"; + + static PyStructSequence_Desc struct_group_type_desc = { + "grp.struct_group", + struct_group__doc__, + struct_group_type_fields, + 4, + }; + + + static PyTypeObject StructGrpType; static PyObject * mkgrent(struct group *p) { ! int setIndex = 0; ! PyObject *v = PyStructSequence_New(&StructGrpType), *w; char **member; + + if (v == NULL) + return NULL; + if ((w = PyList_New(0)) == NULL) { + Py_DECREF(v); return NULL; } *************** *** 21,34 **** Py_XDECREF(x); Py_DECREF(w); return NULL; } Py_DECREF(x); } ! v = Py_BuildValue("(sslO)", ! p->gr_name, ! p->gr_passwd, ! (long)p->gr_gid, ! w); ! Py_DECREF(w); return v; } --- 51,73 ---- Py_XDECREF(x); Py_DECREF(w); + Py_DECREF(v); return NULL; } Py_DECREF(x); } ! ! #define SET(i,val) PyStructSequence_SET_ITEM(v, i, val) ! SET(setIndex++, PyString_FromString(p->gr_name)); ! SET(setIndex++, PyString_FromString(p->gr_passwd)); ! SET(setIndex++, PyInt_FromLong((long) p->gr_gid)); ! SET(setIndex++, w); ! #undef SET ! ! if (PyErr_Occurred()) { ! Py_DECREF(v); ! Py_DECREF(w); ! return NULL; ! } ! return v; } *************** *** 121,124 **** initgrp(void) { ! Py_InitModule3("grp", grp_methods, grp__doc__); } --- 160,167 ---- initgrp(void) { ! PyObject *m, *d; ! m = Py_InitModule3("grp", grp_methods, grp__doc__); ! d = PyModule_GetDict(m); ! PyStructSequence_InitType(&StructGrpType, &struct_group_type_desc); ! PyDict_SetItemString(d, "struct_group", (PyObject *) &StructGrpType); } Index: pwdmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/pwdmodule.c,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** pwdmodule.c 1 Feb 2002 15:46:29 -0000 1.26 --- pwdmodule.c 1 Mar 2002 10:38:44 -0000 1.27 *************** *** 3,10 **** --- 3,35 ---- #include "Python.h" + #include "structseq.h" #include #include + static PyStructSequence_Field struct_pwd_type_fields[] = { + {"pw_name", "user name"}, + {"pw_passwd", "password"}, + {"pw_uid", "user id"}, + {"pw_gid", "group id"}, + {"pw_gecos", "real name"}, + {"pw_dir", "home directory"}, + {"pw_shell", "shell program"}, + {0} + }; + + static char struct_passwd__doc__[] = + "pwd.struct_passwd: Results from getpw*() routines.\n\n\ + This object may be accessed either as a tuple of\n\ + (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)\n\ + or via the object attributes as named in the above tuple.\n"; + + static PyStructSequence_Desc struct_pwd_type_desc = { + "pwd.struct_passwd", + struct_passwd__doc__, + struct_pwd_type_fields, + 7, + }; + static char pwd__doc__ [] = "\ This module provides access to the Unix password database.\n\ *************** *** 18,37 **** static PyObject * mkpwent(struct passwd *p) { ! return Py_BuildValue( ! "(ssllsss)", ! p->pw_name, ! p->pw_passwd, ! (long)p->pw_uid, ! (long)p->pw_gid, ! p->pw_gecos, ! p->pw_dir, ! p->pw_shell); } static char pwd_getpwuid__doc__[] = "\ ! getpwuid(uid) -> entry\n\ Return the password database entry for the given numeric user ID.\n\ See pwd.__doc__ for more on password database entries."; --- 43,80 ---- + static PyTypeObject StructPwdType; + static PyObject * mkpwent(struct passwd *p) { ! int setIndex = 0; ! PyObject *v = PyStructSequence_New(&StructPwdType); ! if (v == NULL) ! return NULL; ! ! #define SETI(i,val) PyStructSequence_SET_ITEM(v, i, PyInt_FromLong((long) val)) ! #define SETS(i,val) PyStructSequence_SET_ITEM(v, i, PyString_FromString(val)) ! ! SETS(setIndex++, p->pw_name); ! SETS(setIndex++, p->pw_passwd); ! SETI(setIndex++, p->pw_uid); ! SETI(setIndex++, p->pw_gid); ! SETS(setIndex++, p->pw_gecos); ! SETS(setIndex++, p->pw_dir); ! SETS(setIndex++, p->pw_shell); ! ! #undef SETS ! #undef SETI ! ! if (PyErr_Occurred()) { ! Py_XDECREF(v); ! return NULL; ! } ! ! return v; } static char pwd_getpwuid__doc__[] = "\ ! getpwuid(uid) -> (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)\n\ Return the password database entry for the given numeric user ID.\n\ See pwd.__doc__ for more on password database entries."; *************** *** 52,56 **** static char pwd_getpwnam__doc__[] = "\ ! getpwnam(name) -> entry\n\ Return the password database entry for the given user name.\n\ See pwd.__doc__ for more on password database entries."; --- 95,99 ---- static char pwd_getpwnam__doc__[] = "\ ! getpwnam(name) -> (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)\n\ Return the password database entry for the given user name.\n\ See pwd.__doc__ for more on password database entries."; *************** *** 113,117 **** initpwd(void) { ! Py_InitModule4("pwd", pwd_methods, pwd__doc__, (PyObject *)NULL, PYTHON_API_VERSION); } --- 156,164 ---- initpwd(void) { ! PyObject *m, *d; ! m = Py_InitModule4("pwd", pwd_methods, pwd__doc__, (PyObject *)NULL, PYTHON_API_VERSION); + d = PyModule_GetDict(m); + PyStructSequence_InitType(&StructPwdType, &struct_pwd_type_desc); + PyDict_SetItemString(d, "struct_pwent", (PyObject *) &StructPwdType); } From loewis@users.sourceforge.net Fri Mar 1 10:47:39 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 02:47:39 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.358,1.359 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv30618/Misc Modified Files: NEWS Log Message: Patch #523268, #522027: return enhanced tuples. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.358 retrieving revision 1.359 diff -C2 -d -r1.358 -r1.359 *** NEWS 1 Mar 2002 10:27:01 -0000 1.358 --- NEWS 1 Mar 2002 10:47:37 -0000 1.359 *************** *** 18,21 **** --- 18,23 ---- Extension modules + - pwd and grp return enhanced tuples now, with symbolic field names. + - array.array is now a type object. A new format character 'u' indicates Py_UNICODE arrays. For those, .tounicode and From loewis@users.sourceforge.net Fri Mar 1 10:47:39 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 02:47:39 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libpwd.tex,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv30618/Doc/lib Modified Files: libpwd.tex Log Message: Patch #523268, #522027: return enhanced tuples. Index: libpwd.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libpwd.tex,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** libpwd.tex 20 Oct 2001 04:24:09 -0000 1.13 --- libpwd.tex 1 Mar 2002 10:47:36 -0000 1.14 *************** *** 9,16 **** database. It is available on all \UNIX{} versions. ! Password database entries are reported as 7-tuples containing the ! following items from the password database (see \code{}), in order: ! \begin{tableiii}{r|l|l}{textrm}{Index}{Field}{Meaning} \lineiii{0}{\code{pw_name}}{Login name} \lineiii{1}{\code{pw_passwd}}{Optional encrypted password} --- 9,17 ---- database. It is available on all \UNIX{} versions. ! Password database entries are reported as a tuple-like object, whose ! attributes correspond to the members of the \code{passwd} structure ! (Attribute field below, see \code{}): ! \begin{tableiii}{r|l|l}{textrm}{Index}{Attribute}{Meaning} \lineiii{0}{\code{pw_name}}{Login name} \lineiii{1}{\code{pw_passwd}}{Optional encrypted password} From barry@zope.com Fri Mar 1 12:52:48 2002 From: barry@zope.com (Barry A. Warsaw) Date: Fri, 1 Mar 2002 07:52:48 -0500 Subject: [Python-checkins] CVS: python/nondist/peps pep-0001.txt,1.28,1.29 References: <3C7F3BAF.56514E85@lemburg.com> Message-ID: <15487.31136.344196.234047@anthem.wooz.org> >>>>> "MAL" == M writes: MAL> Isn't this unnecessary duplication ? The CVS history has all MAL> this information available, including patches, comments, etc. I think it's helpful when viewing the file on the web. -Barry From nnorwitz@users.sourceforge.net Fri Mar 1 13:10:05 2002 From: nnorwitz@users.sourceforge.net (Neal Norwitz) Date: Fri, 01 Mar 2002 05:10:05 -0800 Subject: [Python-checkins] CVS: python/dist/src/Demo/tix tixwidgets.py,1.4,1.4.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Demo/tix In directory usw-pr-cvs1:/tmp/cvs-serv31408 Modified Files: Tag: release22-maint tixwidgets.py Log Message: SF #517447, correct syntax error Index: tixwidgets.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Demo/tix/tixwidgets.py,v retrieving revision 1.4 retrieving revision 1.4.6.1 diff -C2 -d -r1.4 -r1.4.6.1 *** tixwidgets.py 25 Nov 2001 14:50:55 -0000 1.4 --- tixwidgets.py 1 Mar 2002 13:10:02 -0000 1.4.6.1 *************** *** 136,141 **** while self.exit < 0: try: ! while self.exit < 0: ! self.root.tk.dooneevent(TCL_ALL_EVENTS) except SystemExit: #print 'Exit' --- 136,140 ---- while self.exit < 0: try: ! self.root.tk.dooneevent(TCL_ALL_EVENTS) except SystemExit: #print 'Exit' From loewis@users.sourceforge.net Fri Mar 1 13:15:33 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Fri, 01 Mar 2002 05:15:33 -0800 Subject: [Python-checkins] CVS: python/dist/src/Demo/pysvr pysvr.c,1.10,1.11 Message-ID: Update of /cvsroot/python/python/dist/src/Demo/pysvr In directory usw-pr-cvs1:/tmp/cvs-serv32447 Modified Files: pysvr.c Log Message: Patch #524008: Fix portability bug on new POSIX hosts Index: pysvr.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Demo/pysvr/pysvr.c,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** pysvr.c 28 Nov 2001 20:27:42 -0000 1.10 --- pysvr.c 1 Mar 2002 13:15:30 -0000 1.11 *************** *** 366,370 **** char buffer[100]; PyOS_snprintf(buffer, sizeof(buffer), ! "ps -l -p %d Update of /cvsroot/python/python/dist/src/Demo/tix In directory usw-pr-cvs1:/tmp/cvs-serv30904 Modified Files: tixwidgets.py Log Message: SF #517447, correct syntax error Index: tixwidgets.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Demo/tix/tixwidgets.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** tixwidgets.py 25 Nov 2001 14:50:55 -0000 1.4 --- tixwidgets.py 1 Mar 2002 13:07:34 -0000 1.5 *************** *** 136,141 **** while self.exit < 0: try: ! while self.exit < 0: ! self.root.tk.dooneevent(TCL_ALL_EVENTS) except SystemExit: #print 'Exit' --- 136,140 ---- while self.exit < 0: try: ! self.root.tk.dooneevent(TCL_ALL_EVENTS) except SystemExit: #print 'Exit' From mwh@users.sourceforge.net Fri Mar 1 14:16:34 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Fri, 01 Mar 2002 06:16:34 -0800 Subject: [Python-checkins] CVS: python/dist/src setup.py,1.82,1.83 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv15478 Modified Files: setup.py Log Message: Changes to what we do to modules that don't import, as discussed on python-dev. Index: setup.py =================================================================== RCS file: /cvsroot/python/python/dist/src/setup.py,v retrieving revision 1.82 retrieving revision 1.83 diff -C2 -d -r1.82 -r1.83 *** setup.py 16 Feb 2002 18:23:29 -0000 1.82 --- setup.py 1 Mar 2002 14:16:31 -0000 1.83 *************** *** 177,187 **** if 1: ! self.announce('*** WARNING: removing "%s" since importing it' ' failed: %s' % (ext.name, why)) assert not self.inplace ! fullname = self.get_ext_fullname(ext.name) ! ext_filename = os.path.join(self.build_lib, ! self.get_ext_filename(fullname)) ! os.remove(ext_filename) # XXX -- This relies on a Vile HACK in --- 177,187 ---- if 1: ! self.announce('*** WARNING: renaming "%s" since importing it' ' failed: %s' % (ext.name, why)) assert not self.inplace ! basename, tail = os.path.splitext(ext_filename) ! newname = basename + "_failed" + tail ! if os.path.exists(newname): os.remove(newname) ! os.rename(ext_filename, newname) # XXX -- This relies on a Vile HACK in From mal@lemburg.com Fri Mar 1 18:17:38 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Fri, 01 Mar 2002 19:17:38 +0100 Subject: [Python-checkins] CVS: python/nondist/peps pep-0001.txt,1.28,1.29 References: <3C7F3BAF.56514E85@lemburg.com> <15487.31136.344196.234047@anthem.wooz.org> Message-ID: <3C7FC5C2.616B707E@lemburg.com> "Barry A. Warsaw" wrote: > > >>>>> "MAL" == M writes: > > MAL> Isn't this unnecessary duplication ? The CVS history has all > MAL> this information available, including patches, comments, etc. > > I think it's helpful when viewing the file on the web. A direct link to the ViewCVS entry on SF would be a lot more helpful, IMHO, since it offers more background information than the simple Last-Modified notice. pep2html.py could easily generate this link (and also the Last-Modified entry; perhaps both ;-): http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/python/python/nondist/peps/pep-.txt -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From lemburg@users.sourceforge.net Fri Mar 1 19:07:49 2002 From: lemburg@users.sourceforge.net (M.-A. Lemburg) Date: Fri, 01 Mar 2002 11:07:49 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep2html.py,1.31,1.32 pep-0263.txt,1.8,1.9 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv2473 Modified Files: pep2html.py pep-0263.txt Log Message: Added support for Last-Modified header and its (possibly automatic) generation. Index: pep2html.py =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep2html.py,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** pep2html.py 16 Feb 2002 10:44:32 -0000 1.31 --- pep2html.py 1 Mar 2002 19:07:46 -0000 1.32 *************** *** 32,40 **** import getopt import errno PROGRAM = sys.argv[0] RFCURL = 'http://www.faqs.org/rfcs/rfc%d.html' PEPURL = 'pep-%04d.html' ! --- 32,41 ---- import getopt import errno + import time PROGRAM = sys.argv[0] RFCURL = 'http://www.faqs.org/rfcs/rfc%d.html' PEPURL = 'pep-%04d.html' ! PEPCVSURL = 'http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/python/python/nondist/peps/pep-%04d.txt' *************** *** 159,167 **** v = SPACE.join(mailtos) elif k.lower() in ('replaces', 'replaced-by'): ! peps = '' ! for pep in v.split(): ! pep = int(pep) ! peps += '%i ' % (pep, pep) ! v = peps else: v = cgi.escape(v) --- 160,174 ---- v = SPACE.join(mailtos) elif k.lower() in ('replaces', 'replaced-by'): ! otherpeps = '' ! for otherpep in v.split(): ! otherpep = int(otherpep) ! otherpeps += '%i ' % (otherpep, ! otherpep) ! v = otherpeps ! elif k.lower() in ('last-modified',): ! url = PEPCVSURL % int(pep) ! date = v or time.strftime('%d-%b-%Y', ! time.localtime(os.stat(infile)[8])) ! v = '%s ' % (url, cgi.escape(date)) else: v = cgi.escape(v) Index: pep-0263.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0263.txt,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** pep-0263.txt 28 Feb 2002 09:08:39 -0000 1.8 --- pep-0263.txt 1 Mar 2002 19:07:46 -0000 1.9 *************** *** 7,10 **** --- 7,11 ---- Python-Version: 2.3 Created: 06-Jun-2001 + Last-Modified: Post-History: From mal@lemburg.com Fri Mar 1 19:11:21 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Fri, 01 Mar 2002 20:11:21 +0100 Subject: [Python-checkins] CVS: python/nondist/peps pep-0001.txt,1.28,1.29 References: <3C7F3BAF.56514E85@lemburg.com> <15487.31136.344196.234047@anthem.wooz.org> <3C7FC5C2.616B707E@lemburg.com> Message-ID: <3C7FD259.4D835FA2@lemburg.com> "M.-A. Lemburg" wrote: > > "Barry A. Warsaw" wrote: > > > > >>>>> "MAL" == M writes: > > > > MAL> Isn't this unnecessary duplication ? The CVS history has all > > MAL> this information available, including patches, comments, etc. > > > > I think it's helpful when viewing the file on the web. > > A direct link to the ViewCVS entry on SF would be a lot > more helpful, IMHO, since it offers more background > information than the simple Last-Modified notice. > > pep2html.py could easily generate this link (and > also the Last-Modified entry; perhaps both ;-): > > http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/python/python/nondist/peps/pep-.txt I just added support for this to pep2html.py. If the Last-Modified is present, but empty, it is autogenerated. If available, the value is taken as is. In both cases the date links to the CVS entry on SF. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal@lemburg.com Fri Mar 1 19:15:29 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Fri, 01 Mar 2002 20:15:29 +0100 Subject: [Python-checkins] CVS: python/nondist/peps pep-0001.txt,1.28,1.29 References: <3C7F3BAF.56514E85@lemburg.com> <15487.31136.344196.234047@anthem.wooz.org> <3C7FC5C2.616B707E@lemburg.com> <3C7FD259.4D835FA2@lemburg.com> Message-ID: <3C7FD351.24B7CCDC@lemburg.com> "M.-A. Lemburg" wrote: > > I just added support for this to pep2html.py. If the Last-Modified > is present, but empty, it is autogenerated. If available, the > value is taken as is. In both cases the date links to the > CVS entry on SF. See http://python.sourceforge.net/peps/pep-0263.html for an example. FYI, I've converted all PEPs on the SF page to the new format. Hope I didn't break anything... -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From barry@zope.com Fri Mar 1 19:17:35 2002 From: barry@zope.com (Barry A. Warsaw) Date: Fri, 1 Mar 2002 14:17:35 -0500 Subject: [Python-checkins] CVS: python/nondist/peps pep-0001.txt,1.28,1.29 References: <3C7F3BAF.56514E85@lemburg.com> <15487.31136.344196.234047@anthem.wooz.org> <3C7FC5C2.616B707E@lemburg.com> <3C7FD259.4D835FA2@lemburg.com> <3C7FD351.24B7CCDC@lemburg.com> Message-ID: <15487.54223.483081.28063@anthem.wooz.org> >>>>> "MAL" == M writes: MAL> See http://python.sourceforge.net/peps/pep-0263.html MAL> for an example. MAL> FYI, I've converted all PEPs on the SF page to the new MAL> format. Hope I didn't break anything... As an alternative format, what about adding a link to the CVS history in the title bar, e.g. [History] right after [PEP source]? BTW, thanks! -Barry From guido@python.org Fri Mar 1 19:21:52 2002 From: guido@python.org (Guido van Rossum) Date: Fri, 01 Mar 2002 14:21:52 -0500 Subject: [Python-checkins] CVS: python/nondist/peps pep-0001.txt,1.28,1.29 In-Reply-To: Your message of "Fri, 01 Mar 2002 20:15:29 +0100." <3C7FD351.24B7CCDC@lemburg.com> References: <3C7F3BAF.56514E85@lemburg.com> <15487.31136.344196.234047@anthem.wooz.org> <3C7FC5C2.616B707E@lemburg.com> <3C7FD259.4D835FA2@lemburg.com> <3C7FD351.24B7CCDC@lemburg.com> Message-ID: <200203011921.g21JLv006833@pcp742651pcs.reston01.va.comcast.net> > See http://python.sourceforge.net/peps/pep-0263.html > for an example. Oh, very cool, very subtle! --Guido van Rossum (home page: http://www.python.org/~guido/) From gvanrossum@users.sourceforge.net Fri Mar 1 20:58:37 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 01 Mar 2002 12:58:37 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime - New directory Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv4777/datetime Log Message: Directory /cvsroot/python/python/nondist/sandbox/datetime added to the repository From gvanrossum@users.sourceforge.net Fri Mar 1 21:00:52 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 01 Mar 2002 13:00:52 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,NONE,1.1 test_datetime.py,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv5784 Added Files: datetime.py test_datetime.py Log Message: datetime prototype in Python --- NEW FILE: datetime.py --- import time as _time class basetime(object): """Abstract date/time type. See http://effbot.org/ideas/time-type.htm """ __slots__ = [] def timetuple(self): raise NotImplementedError def utctimetuple(self): raise NotImplementedError def __cmp__(self, other): raise NotImplementedError def __hash__(self): raise NotImplementedError # XXX deltaobject? class datetime(basetime): """Concrete date/time type -- prototype implemented in Python. See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage """ __isdst = None def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzoffset=None): assert 1 <= year <= 9999 assert 1 <= month <= 12 assert 1 <= day <= 31 # XXX calendrical check assert 0 <= hour <= 23 assert 0 <= minute <= 59 assert 0 <= second <= 59 assert 0 <= microsecond <= 999999 if tzoffset is None: if datetime.__isdst is None: datetime.__isdst = _time.localtime()[-1] if datetime.__isdst > 0: tzoffset = -(_time.altzone/60) else: tzoffset = -(_time.timezone/60) assert -1439 <= tzoffset <= 1439 self.__year = year self.__month = month self.__day = day self.__hour = hour self.__minute = minute self.__second = second self.__microsecond = microsecond self.__tzoffset = tzoffset # minutes east of UTC def new(cls, *args, **kwds): return cls(*args, **kwds) new = classmethod(new) def fromtimestamp(cls, t): y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t) us = int((t % 1.0) * 1000000) if dst > 0: tz = - _time.altzone/60 else: tz = - _time.timezone/60 return cls(y, m, d, hh, mm, ss, us, tz) fromtimestamp = classmethod(fromtimestamp) def now(cls): t = _time.time() return cls.fromtimestamp(t) now = classmethod(now) def utcfromtimestamp(cls, t): y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t) us = int((t % 1.0) * 1000000) return cls(y, m, d, hh, mm, ss, us, 0) utcfromtimestamp = classmethod(utcfromtimestamp) def utcnow(cls): t = _time.time() return cls.utcfromtimestamp(t) utcnow = classmethod(utcnow) # Read-only field accessors year = property(lambda self: self.__year, doc="year (1-9999)") month = property(lambda self: self.__month, doc="month (1-12)") day = property(lambda self: self.__day, doc="day (1-31)") hour = property(lambda self: self.__hour, doc="hour (0-23)") minute = property(lambda self: self.__minute, doc="minute (0-59)") second = property(lambda self: self.__second, doc="second (0-59)") microsecond = property(lambda self: self.__microsecond, doc="microsecond (0-999999)") tzoffset = property(lambda self: self.__tzoffset, doc="time zone offset in minutes east of UTC") def _mktime(self): # Helper to call time.mktime() y, m, d = self.__year, self.__month, self.__day hh, mm, ss = self.__hour, self.__minute, self.__second mm -= self.__tzoffset # tzoffset is negative in the US ss -= _time.timezone # but time.timezone has the opposite sign! return _time.mktime((y, m, d, hh, mm, ss, -1, -1, -1)) def _timestamp(self): # Helper like _mktime() that adds microseconds return self._mktime() + 0.000001 * self.__microsecond def timetuple(self): """Return local time tuple compatible with time.localtime().""" return _time.localtime(self._mktime()) def utctimetuple(self): """Return UTC time tuple compatible with time.gmtime().""" return _time.gmtime(self._mktime()) def __cmp__(self, other): """Three-way comparison.""" if isinstance(other, datetime): if other.__tzoffset == self.__tzoffset: y, m, d = self.__year, self.__month, self.__day hh, mm, ss = self.__hour, self.__minute, self.__second tz = self.__tzoffset y2, m2, d2 = other.__year, other.__month, other.__day hh2, mm2, ss2 = other.__hour, other.__minute, other.__second tz2 = other.__tzoffset return cmp((y, m, d, hh, mm, ss, tz), (y2, m2, d2, hh2, mm2, ss2, tz2)) else: return cmp(self._timestamp(), other._timestamp()) else: return NotImplemented def __hash__(self): """Hash.""" y, m, d = self.__year, self.__month, self.__day hh, mm, ss = self.__hour, self.__minute, self.__second us, tz = self.__microsecond, self.__tzoffset return hash((y, m, d, hh, mm, ss, us, tz)) def ctime(self): return _time.strftime("%c", _time.localtime(self._mktime())) def strftime(self, fmt): return _time.strftime(fmt, _time.localtime(self._mktime())) def utcctime(self): return _time.strftime("%c", _time.gmtime(self._mktime())) def utcstrftime(self, fmt): return _time.strftime(fmt, _time.gmtime(self._mktime())) # __add__, __sub__? def _test(): now = _time.time() print _time.ctime(now) t = datetime.fromtimestamp(now) print t.ctime(), divmod(t.tzoffset, 60), t.hour u = datetime.utcfromtimestamp(now) print u.utcctime(), divmod(u.tzoffset, 60), u.hour assert t == u if __name__ == "__main__": _test() --- NEW FILE: test_datetime.py --- """Test date/time type. See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ import sys import unittest from datetime import datetime class TestDateTime(unittest.TestCase): def test_basic_attributes(self): dt = datetime.new(2002, 3, 1, 12, 0, 0) self.assertEqual(dt.year, 2002) self.assertEqual(dt.month, 3) self.assertEqual(dt.day, 1) self.assertEqual(dt.hour, 12) self.assertEqual(dt.minute, 0) self.assertEqual(dt.second, 0) def test_tz_independent_comparing(self): dt1 = datetime.new(2002, 3, 1, 9, 0, 0, tzoffset=-60) dt2 = datetime.new(2002, 3, 1, 10, 0, 0, tzoffset=-60) dt3 = datetime.new(2002, 3, 1, 10, 0, 0, tzoffset=0) self.assertEqual(dt1, dt3) self.assert_(dt2 > dt3) def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') return unittest.TestSuite([s1]) def test_main(): r = unittest.TextTestRunner(stream=sys.stdout, verbosity=2) s = test_suite() r.run(s) if __name__ == "__main__": test_main() From gvanrossum@users.sourceforge.net Fri Mar 1 21:30:57 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 01 Mar 2002 13:30:57 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules mpzmodule.c,2.39,2.40 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv15797 Modified Files: mpzmodule.c Log Message: SF patch 517245 by Marc Recht. Support GMP version >= 2. Bugfix candidate. Index: mpzmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/mpzmodule.c,v retrieving revision 2.39 retrieving revision 2.40 diff -C2 -d -r2.39 -r2.40 *** mpzmodule.c 17 Jan 2002 23:15:58 -0000 2.39 --- mpzmodule.c 1 Mar 2002 21:30:55 -0000 2.40 *************** *** 63,67 **** #include "gmp.h" ! #if __GNU_MP__ + 0 == 2 #define GMP2 #define BITS_PER_MP_LIMB mp_bits_per_limb --- 63,67 ---- #include "gmp.h" ! #if __GNU_MP__ + 0 >= 2 #define GMP2 #define BITS_PER_MP_LIMB mp_bits_per_limb From gvanrossum@users.sourceforge.net Fri Mar 1 21:31:30 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 01 Mar 2002 13:31:30 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc ACKS,1.161,1.162 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv16005 Modified Files: ACKS Log Message: SF patch 517245 by Marc Recht. Support GMP version >= 2. Bugfix candidate. Index: ACKS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/ACKS,v retrieving revision 1.161 retrieving revision 1.162 diff -C2 -d -r1.161 -r1.162 *** ACKS 28 Feb 2002 23:19:52 -0000 1.161 --- ACKS 1 Mar 2002 21:31:27 -0000 1.162 *************** *** 356,359 **** --- 356,360 ---- Eric Raymond Edward K. Ream + Marc Recht John Redford Terry Reedy From tim_one@users.sourceforge.net Fri Mar 1 21:40:31 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 13:40:31 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv17907 Modified Files: datetime.py Log Message: Parameterize min year and max year (in part because the code doesn't match the docs). Arrange for failing asserts to display the offending value. Force integer division where appropriate. Force consistent order of evaluation when mixing unary minus with //. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** datetime.py 1 Mar 2002 21:00:49 -0000 1.1 --- datetime.py 1 Mar 2002 21:40:28 -0000 1.2 *************** *** 1,4 **** --- 1,7 ---- import time as _time + MINYEAR = 1 # XXX The design doc says 0 + MAXYEAR = 9999 # XXX The design doc says 65535 + class basetime(object): """Abstract date/time type. *************** *** 34,52 **** def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzoffset=None): ! assert 1 <= year <= 9999 ! assert 1 <= month <= 12 ! assert 1 <= day <= 31 # XXX calendrical check ! assert 0 <= hour <= 23 ! assert 0 <= minute <= 59 ! assert 0 <= second <= 59 ! assert 0 <= microsecond <= 999999 if tzoffset is None: if datetime.__isdst is None: datetime.__isdst = _time.localtime()[-1] if datetime.__isdst > 0: ! tzoffset = -(_time.altzone/60) else: ! tzoffset = -(_time.timezone/60) ! assert -1439 <= tzoffset <= 1439 self.__year = year self.__month = month --- 37,55 ---- def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzoffset=None): ! assert MINYEAR <= year <= MAXYEAR, year ! assert 1 <= month <= 12, month ! assert 1 <= day <= 31, day # XXX calendrical check ! assert 0 <= hour <= 23, hour ! assert 0 <= minute <= 59, minute ! assert 0 <= second <= 59, second ! assert 0 <= microsecond <= 999999, microsecond if tzoffset is None: if datetime.__isdst is None: datetime.__isdst = _time.localtime()[-1] if datetime.__isdst > 0: ! tzoffset = -(_time.altzone // 60) else: ! tzoffset = -(_time.timezone // 60) ! assert -1439 <= tzoffset <= 1439, tzoffset self.__year = year self.__month = month *************** *** 66,72 **** us = int((t % 1.0) * 1000000) if dst > 0: ! tz = - _time.altzone/60 else: ! tz = - _time.timezone/60 return cls(y, m, d, hh, mm, ss, us, tz) fromtimestamp = classmethod(fromtimestamp) --- 69,75 ---- us = int((t % 1.0) * 1000000) if dst > 0: ! tz = -(_time.altzone // 60) else: ! tz = -(_time.timezone // 60) return cls(y, m, d, hh, mm, ss, us, tz) fromtimestamp = classmethod(fromtimestamp) *************** *** 89,93 **** # Read-only field accessors ! year = property(lambda self: self.__year, doc="year (1-9999)") month = property(lambda self: self.__month, doc="month (1-12)") day = property(lambda self: self.__day, doc="day (1-31)") --- 92,97 ---- # Read-only field accessors ! year = property(lambda self: self.__year, ! doc="year (%d-%d)" % (MINYEAR, MAXYEAR)) month = property(lambda self: self.__month, doc="month (1-12)") day = property(lambda self: self.__day, doc="day (1-31)") From gvanrossum@users.sourceforge.net Fri Mar 1 22:19:43 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 01 Mar 2002 14:19:43 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv28789 Modified Files: datetime.py Log Message: __cmp__ must raise an error when other isn't a datetime, otherwise the default (meaningless) comparison will be used. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** datetime.py 1 Mar 2002 21:40:28 -0000 1.2 --- datetime.py 1 Mar 2002 22:19:41 -0000 1.3 *************** *** 139,143 **** return cmp(self._timestamp(), other._timestamp()) else: ! return NotImplemented def __hash__(self): --- 139,144 ---- return cmp(self._timestamp(), other._timestamp()) else: ! raise TypeError, ("can't compare datetime to %s instance" % ! type(other).__name__) def __hash__(self): From gvanrossum@users.sourceforge.net Fri Mar 1 22:23:55 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 01 Mar 2002 14:23:55 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.94,2.95 object.c,2.162,2.163 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv29045 Modified Files: abstract.c object.c Log Message: SF patch 514641 (Naofumi Honda) - Negative ob_size of LongObjects Due to the bizarre definition of _PyLong_Copy(), creating an instance of a subclass of long with a negative value could cause core dumps later on. Unfortunately it looks like the behavior of _PyLong_Copy() is quite intentional, so the fix is more work than feels comfortable. This fix is almost, but not quite, the code that Naofumi Honda added; in addition, I added a test case. Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.94 retrieving revision 2.95 diff -C2 -d -r2.94 -r2.95 *** abstract.c 5 Jan 2002 10:50:30 -0000 2.94 --- abstract.c 1 Mar 2002 22:23:53 -0000 2.95 *************** *** 934,939 **** return o; } ! if (PyLong_Check(o)) ! return _PyLong_Copy((PyLongObject *)o); if (PyString_Check(o)) /* need to do extra error checking that PyLong_FromString() --- 934,947 ---- return o; } ! if (PyLong_Check(o)) { ! PyObject *res; ! ! res = _PyLong_Copy((PyLongObject *)o); ! if (res != NULL) ! ((PyLongObject *)res)->ob_size = ! ((PyLongObject *)o)->ob_size; ! ! return res; ! } if (PyString_Check(o)) /* need to do extra error checking that PyLong_FromString() Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.162 retrieving revision 2.163 diff -C2 -d -r2.162 -r2.163 *** object.c 4 Dec 2001 15:54:53 -0000 2.162 --- object.c 1 Mar 2002 22:23:53 -0000 2.163 *************** *** 1192,1197 **** return NULL; if (dictoffset < 0) { ! const size_t size = _PyObject_VAR_SIZE(tp, ! ((PyVarObject *)obj)->ob_size); dictoffset += (long)size; assert(dictoffset > 0); --- 1192,1203 ---- return NULL; if (dictoffset < 0) { ! int tsize; ! size_t size; ! ! tsize = ((PyVarObject *)obj)->ob_size; ! if (tsize < 0) ! tsize = -tsize; ! size = _PyObject_VAR_SIZE(tp, tsize); ! dictoffset += (long)size; assert(dictoffset > 0); From gvanrossum@users.sourceforge.net Fri Mar 1 22:24:26 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 01 Mar 2002 14:24:26 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.114,1.115 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv30224 Modified Files: test_descr.py Log Message: SF patch 514641 (Naofumi Honda) - Negative ob_size of LongObjects Due to the bizarre definition of _PyLong_Copy(), creating an instance of a subclass of long with a negative value could cause core dumps later on. Unfortunately it looks like the behavior of _PyLong_Copy() is quite intentional, so the fix is more work than feels comfortable. This fix is almost, but not quite, the code that Naofumi Honda added; in addition, I added a test case. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.114 retrieving revision 1.115 diff -C2 -d -r1.114 -r1.115 *** test_descr.py 28 Dec 2001 21:39:03 -0000 1.114 --- test_descr.py 1 Mar 2002 22:24:24 -0000 1.115 *************** *** 1749,1752 **** --- 1749,1756 ---- verify((0 + a).__class__ is long) + # Check that negative clones don't segfault + a = longclone(-1) + vereq(a.__dict__, {}) + class precfloat(float): __slots__ = ['prec'] From gvanrossum@users.sourceforge.net Fri Mar 1 22:24:51 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 01 Mar 2002 14:24:51 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc ACKS,1.162,1.163 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv30349 Modified Files: ACKS Log Message: SF patch 514641 (Naofumi Honda) - Negative ob_size of LongObjects Due to the bizarre definition of _PyLong_Copy(), creating an instance of a subclass of long with a negative value could cause core dumps later on. Unfortunately it looks like the behavior of _PyLong_Copy() is quite intentional, so the fix is more work than feels comfortable. This fix is almost, but not quite, the code that Naofumi Honda added; in addition, I added a test case. Index: ACKS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/ACKS,v retrieving revision 1.162 retrieving revision 1.163 diff -C2 -d -r1.162 -r1.163 *** ACKS 1 Mar 2002 21:31:27 -0000 1.162 --- ACKS 1 Mar 2002 22:24:49 -0000 1.163 *************** *** 204,207 **** --- 204,208 ---- Gerrit Holl Philip Homburg + Naofumi Honda Jeffrey Honig Rob Hooft From bwarsaw@users.sourceforge.net Fri Mar 1 22:39:16 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Fri, 01 Mar 2002 14:39:16 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib mailbox.py,1.33,1.34 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv1556 Modified Files: mailbox.py Log Message: Added PortableUnixMailbox to the __all__ variable, and in the __main__ section use this class instead of UnixMailbox as per the comments in the latter's class. Bug fix candidate for 2.2.1. Index: mailbox.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/mailbox.py,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -d -r1.33 -r1.34 *** mailbox.py 13 Sep 2001 01:29:13 -0000 1.33 --- mailbox.py 1 Mar 2002 22:39:14 -0000 1.34 *************** *** 7,11 **** import os ! __all__ = ["UnixMailbox","MmdfMailbox","MHMailbox","Maildir","BabylMailbox"] class _Mailbox: --- 7,12 ---- import os ! __all__ = ["UnixMailbox","MmdfMailbox","MHMailbox","Maildir","BabylMailbox", ! "PortableUnixMailbox"] class _Mailbox: *************** *** 92,95 **** --- 93,97 ---- + # Recommended to use PortableUnixMailbox instead! class UnixMailbox(_Mailbox): def _search_start(self): *************** *** 283,287 **** else: fp = open(mbox, 'r') ! mb = UnixMailbox(fp) msgs = [] --- 285,289 ---- else: fp = open(mbox, 'r') ! mb = PortableUnixMailbox(fp) msgs = [] From tim_one@users.sourceforge.net Fri Mar 1 22:42:30 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 14:42:30 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.3,1.4 test_datetime.py,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv1524 Modified Files: datetime.py test_datetime.py Log Message: Incorporate a pile of utility functions from Demo/classes/Dates.py, which also assumes the Gregorian calender indefinitely extended. In particular, this gives us _date2num() and _num2date() utilities that establish a bijection between datetime objects and a contiguous range of integers, such that consecutive days are associated with consecutive integers. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** datetime.py 1 Mar 2002 22:19:41 -0000 1.3 --- datetime.py 1 Mar 2002 22:42:28 -0000 1.4 *************** *** 4,7 **** --- 4,75 ---- MAXYEAR = 9999 # XXX The design doc says 65535 + # Utility functions, adapted from Python's Demo/classes/Dates.py, which + # also assumes the current Gregorian calendar indefinitely extended in + # both directions. + + _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + + _DAYS_BEFORE_MONTH = [] + dbm = 0 + for dim in _DAYS_IN_MONTH: + _DAYS_BEFORE_MONTH.append(dbm) + dbm = dbm + dim + del dbm, dim + + def _is_leap(year): + "year -> 1 if leap year, else 0." + return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) + + def _days_in_year(year): + "year -> number of days in year (366 if a leap year, else 365)." + return 365 + _is_leap(year) + + def _days_before_year(year): + "year -> number of days before January 1st of year." + return year*365 + (year+3)//4 - (year+99)//100 + (year+399)//400 + + def _days_in_month(month, year): + "month, year -> number of days in that month in that year." + assert 1 <= month <= 12, month + if month == 2 and _is_leap(year): + return 29 + return _DAYS_IN_MONTH[month-1] + + def _days_before_month(month, year): + "month, year -> number of days in year preceeding first day of month." + return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year)) + + def _date2num(date): + "datetime object -> day ordinal, considering 01-Jan-0000 as day 1." + assert isinstance(date, datetime) + return (_days_before_year(date.year) + + _days_before_month(date.month, date.year) + + date.day) + + _DI400Y = _days_before_year(400) # number of days in 400 years + + def _num2date(n): + "day ordinal -> datetime object." + + n400 = (n-1) // _DI400Y # number of 400-year blocks preceding + year = n400 * 400 + n -= n400 * _DI400Y + + more = n // 365 + dby = _days_before_year(more) + if dby >= n: + more -= 1 + dby -= _days_in_year(more) + year += more + n -= dby + + month = min(n//29 + 1, 12) + dbm = _days_before_month(month, year) + if dbm >= n: + month -= 1 + dbm -= _days_in_month(month, year) + + return datetime(year, month, n-dbm) + class basetime(object): """Abstract date/time type. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** test_datetime.py 1 Mar 2002 21:00:49 -0000 1.1 --- test_datetime.py 1 Mar 2002 22:42:28 -0000 1.2 *************** *** 27,30 **** --- 27,39 ---- self.assert_(dt2 > dt3) + def test_ordinal_conversions(self): + import datetime as _datetime + for year in range(_datetime.MINYEAR, _datetime.MAXYEAR + 1): + for month, day in (1, 1), (12, 31), (6, 17): + base = datetime(year, month, day) + ordinal = _datetime._date2num(base) + derived = _datetime._num2date(ordinal) + self.assertEqual(base, derived) + def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') From tim_one@users.sourceforge.net Fri Mar 1 22:53:45 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 14:53:45 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv5305 Modified Files: datetime.py Log Message: Cut the number of rounding errors in datetime._timestamp(). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** datetime.py 1 Mar 2002 22:42:28 -0000 1.4 --- datetime.py 1 Mar 2002 22:53:43 -0000 1.5 *************** *** 182,186 **** def _timestamp(self): # Helper like _mktime() that adds microseconds ! return self._mktime() + 0.000001 * self.__microsecond def timetuple(self): --- 182,186 ---- def _timestamp(self): # Helper like _mktime() that adds microseconds ! return self._mktime() + self.__microsecond / 1e6 def timetuple(self): From tim.one@comcast.net Fri Mar 1 23:18:34 2002 From: tim.one@comcast.net (Tim Peters) Date: Fri, 01 Mar 2002 18:18:34 -0500 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.114,1.115 In-Reply-To: Message-ID: [Guido] > Due to the bizarre definition of _PyLong_Copy(), creating an instance > of a subclass of long with a negative value could cause core dumps > later on. Unfortunately it looks like the behavior of _PyLong_Copy() > is quite intentional, so the fix is more work than feels comfortable. What specifically is bizarre? Looks to me like _PyLong_Copy() is plain wrong, and I probably wrote it . result->ob_size = i; should be result->ob_size = src->ob_size; if I'm guessing what bizarre means to you. Is that what you mean, or something else? The bizarreness *begins* with that _longobject fakes a PyObject_VAR_HEAD header by hand, then abuses the ob_size member to store the sign bit of the long as well as the number of bytes. So I expect there was more than one bug here (and that _PyLong_Copy() is one of them). From tim_one@users.sourceforge.net Fri Mar 1 23:53:49 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 15:53:49 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.5,1.6 test_datetime.py,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv20152 Modified Files: datetime.py test_datetime.py Log Message: Change constructor to raise ValueError on out-of-range arguments instead of assert-failing. Change day range test to use the correct largest day number for the given month and year. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** datetime.py 1 Mar 2002 22:53:43 -0000 1.5 --- datetime.py 1 Mar 2002 23:53:47 -0000 1.6 *************** *** 105,115 **** def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzoffset=None): ! assert MINYEAR <= year <= MAXYEAR, year ! assert 1 <= month <= 12, month ! assert 1 <= day <= 31, day # XXX calendrical check ! assert 0 <= hour <= 23, hour ! assert 0 <= minute <= 59, minute ! assert 0 <= second <= 59, second ! assert 0 <= microsecond <= 999999, microsecond if tzoffset is None: if datetime.__isdst is None: --- 105,124 ---- def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzoffset=None): ! if not MINYEAR <= year <= MAXYEAR: ! raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), ! year) ! if not 1 <= month <= 12: ! raise ValueError('month must be in 1..12', month) ! dim = _days_in_month(month, year) ! if not 1 <= day <= dim: ! raise ValueError('day must be in 1..%d' % dim, day) ! if not 0 <= hour <= 23: ! raise ValueError('hour must be in 0..23', hour) ! if not 0 <= minute <= 59: ! raise ValueError('minute must be in 0..59', minute) ! if not 0 <= second <= 59: ! raise ValueError('second must be in 0..59', second) ! if not 0 <= microsecond <= 999999: ! raise ValueError('second must be in 0..999999', microsecond) if tzoffset is None: if datetime.__isdst is None: *************** *** 119,123 **** else: tzoffset = -(_time.timezone // 60) ! assert -1439 <= tzoffset <= 1439, tzoffset self.__year = year self.__month = month --- 128,133 ---- else: tzoffset = -(_time.timezone // 60) ! if not -1439 <= tzoffset <= 1439: ! raise ValueError('tzoffset must be in -1439..1439', tzoffset) self.__year = year self.__month = month Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** test_datetime.py 1 Mar 2002 22:42:28 -0000 1.2 --- test_datetime.py 1 Mar 2002 23:53:47 -0000 1.3 *************** *** 36,39 **** --- 36,78 ---- self.assertEqual(base, derived) + def test_bad_constructor_arguments(self): + from datetime import MINYEAR, MAXYEAR + # bad years + datetime(MINYEAR, 1, 1) # no exception + datetime(MAXYEAR, 1, 1) # no exception + self.assertRaises(ValueError, datetime, MINYEAR-1, 1, 1) + self.assertRaises(ValueError, datetime, MAXYEAR+1, 1, 1) + # bad months + datetime(2000, 1, 1) # no exception + datetime(2000, 12, 1) # no exception + self.assertRaises(ValueError, datetime, 2000, 0, 1) + self.assertRaises(ValueError, datetime, 2000, 13, 1) + # bad days + datetime(2000, 2, 29) # no exception + datetime(2004, 2, 29) # no exception + datetime(2400, 2, 29) # no exception + self.assertRaises(ValueError, datetime, 2000, 2, 30) + self.assertRaises(ValueError, datetime, 2001, 2, 29) + self.assertRaises(ValueError, datetime, 2100, 2, 29) + self.assertRaises(ValueError, datetime, 1900, 2, 29) + self.assertRaises(ValueError, datetime, 1900, 2, 29) + self.assertRaises(ValueError, datetime, 2000, 1, 0) + self.assertRaises(ValueError, datetime, 2000, 1, 32) + # bad hours + datetime(2000, 1, 31, 0) # no exception + datetime(2000, 1, 31, 23) # no exception + self.assertRaises(ValueError, datetime, 2000, 1, 31, -1) + self.assertRaises(ValueError, datetime, 2000, 1, 31, 24) + # bad minutes + datetime(2000, 1, 31, 23, 0) # no exception + datetime(2000, 1, 31, 23, 59) # no exception + self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, -1) + self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 60) + # bad seconds + datetime(2000, 1, 31, 23, 59, 0) # no exception + datetime(2000, 1, 31, 23, 59, 59) # no exception + self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, -1) + self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 60) + def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') From tim_one@users.sourceforge.net Fri Mar 1 23:55:57 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 15:55:57 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.6,1.7 test_datetime.py,1.3,1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv21041 Modified Files: datetime.py test_datetime.py Log Message: Typo repair. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** datetime.py 1 Mar 2002 23:53:47 -0000 1.6 --- datetime.py 1 Mar 2002 23:55:55 -0000 1.7 *************** *** 120,124 **** raise ValueError('second must be in 0..59', second) if not 0 <= microsecond <= 999999: ! raise ValueError('second must be in 0..999999', microsecond) if tzoffset is None: if datetime.__isdst is None: --- 120,124 ---- raise ValueError('second must be in 0..59', second) if not 0 <= microsecond <= 999999: ! raise ValueError('microsecond must be in 0..999999', microsecond) if tzoffset is None: if datetime.__isdst is None: Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** test_datetime.py 1 Mar 2002 23:53:47 -0000 1.3 --- test_datetime.py 1 Mar 2002 23:55:55 -0000 1.4 *************** *** 56,60 **** self.assertRaises(ValueError, datetime, 2100, 2, 29) self.assertRaises(ValueError, datetime, 1900, 2, 29) - self.assertRaises(ValueError, datetime, 1900, 2, 29) self.assertRaises(ValueError, datetime, 2000, 1, 0) self.assertRaises(ValueError, datetime, 2000, 1, 32) --- 56,59 ---- From tim_one@users.sourceforge.net Sat Mar 2 00:09:57 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 16:09:57 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.7,1.8 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv23990 Modified Files: datetime.py Log Message: Added XXX comment noting a nasty bug in datetime.__hash__(). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** datetime.py 1 Mar 2002 23:55:55 -0000 1.7 --- datetime.py 2 Mar 2002 00:09:55 -0000 1.8 *************** *** 222,225 **** --- 222,228 ---- def __hash__(self): """Hash.""" + # XXX Bug: objects that compare equal must have equal hashcodes, + # XXX and two datetimes can be equal even if their fields aren't + # XXX (due to tzoffset). Do we have to hash the timestamp instead? y, m, d = self.__year, self.__month, self.__day hh, mm, ss = self.__hour, self.__minute, self.__second From tim_one@users.sourceforge.net Sat Mar 2 01:03:10 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 17:03:10 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.8,1.9 test_datetime.py,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv2483 Modified Files: datetime.py test_datetime.py Log Message: Repair __hash__ so that equal values have equal hashcodes. This is done by normalizing (year, month, day, hour, minute) to UTC (and a new method computes that), then leaving tzoffset out of the hash computation. May not be cheap enough; normalizing to UTC *can* propagate all the way to the year (and a new test verifies that it can). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** datetime.py 2 Mar 2002 00:09:55 -0000 1.8 --- datetime.py 2 Mar 2002 01:03:08 -0000 1.9 *************** *** 220,232 **** type(other).__name__) def __hash__(self): """Hash.""" ! # XXX Bug: objects that compare equal must have equal hashcodes, ! # XXX and two datetimes can be equal even if their fields aren't ! # XXX (due to tzoffset). Do we have to hash the timestamp instead? ! y, m, d = self.__year, self.__month, self.__day ! hh, mm, ss = self.__hour, self.__minute, self.__second ! us, tz = self.__microsecond, self.__tzoffset ! return hash((y, m, d, hh, mm, ss, us, tz)) def ctime(self): --- 220,265 ---- type(other).__name__) + def _utc_ymdHM(self): + "Return (year, month, day, hour, minute) in UTC equivalent." + y, m, d = self.__year, self.__month, self.__day + H, M = self.__hour, self.__minute + if self.__tzoffset: + M -= self.__tzoffset + if not 0 <= M <= 59: + carry, M = divmod(M, 60) + H += carry + if not 0 <= H <= 23: + carry, H = divmod(H, 24) + # tzoffset is less than a day, so carry is no more than 1. + if carry > 0: + assert carry == 1 + d += 1 + if d > _days_in_month(m, y): + d = 1 + m += 1 + if m > 12: + m = 1 + y += 1 + else: + assert carry == -1 + d -= 1 + if d == 0: + m -= 1 + if m > 0: + d = _days_in_month(m, y) + else: + d = 31 + m = 12 + y -= 1 + return y, m, d, H, M + def __hash__(self): """Hash.""" ! # Caution: objects that compare equal must have equal hashcodes, ! # and two datetimes can be equal even if their fields aren't ! # (due to tzoffset). So we have to compute a UTC-normalized hash. ! # XXX _utc_ymdHM can be expensive; dream up a quicker correct way. ! y, m, d, H, M = self._utc_ymdHM() ! return hash((y, m, d, H, M, self.__second, self.__microsecond)) def ctime(self): Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** test_datetime.py 1 Mar 2002 23:55:55 -0000 1.4 --- test_datetime.py 2 Mar 2002 01:03:08 -0000 1.5 *************** *** 74,77 **** --- 74,88 ---- self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 60) + def test_hash_equality(self): + d = datetime(2000, 12, 31, 23, 30, 17, tzoffset=-35) + # same thing in UTC. + e = datetime(2001, 1, 1, 0, 5, 17, tzoffset=0) + self.assertEqual(hash(d), hash(e)) + + d = datetime(2001, 1, 1, 0, 5, 17, tzoffset=35) + # same thing in UTC. + e = datetime(2000, 12, 31, 23, 30, 17, tzoffset=0) + self.assertEqual(hash(d), hash(e)) + def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') From tim_one@users.sourceforge.net Sat Mar 2 01:10:37 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 17:10:37 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.5,1.6 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv5096 Modified Files: test_datetime.py Log Message: test_hash_equality(): assert that the objects are equal, as well as their hashes. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** test_datetime.py 2 Mar 2002 01:03:08 -0000 1.5 --- test_datetime.py 2 Mar 2002 01:10:35 -0000 1.6 *************** *** 78,81 **** --- 78,82 ---- # same thing in UTC. e = datetime(2001, 1, 1, 0, 5, 17, tzoffset=0) + self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) *************** *** 83,86 **** --- 84,88 ---- # same thing in UTC. e = datetime(2000, 12, 31, 23, 30, 17, tzoffset=0) + self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) From tim_one@users.sourceforge.net Sat Mar 2 04:14:23 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 20:14:23 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.95,2.96 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9137 Modified Files: abstract.c Log Message: Revert the last odd change to PyNumber_Long: the problem it was trying to fix was almost certainly a bug in _PyLong_Copy (which I'll fix next). Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.95 retrieving revision 2.96 diff -C2 -d -r2.95 -r2.96 *** abstract.c 1 Mar 2002 22:23:53 -0000 2.95 --- abstract.c 2 Mar 2002 04:14:21 -0000 2.96 *************** *** 934,947 **** return o; } ! if (PyLong_Check(o)) { ! PyObject *res; ! ! res = _PyLong_Copy((PyLongObject *)o); ! if (res != NULL) ! ((PyLongObject *)res)->ob_size = ! ((PyLongObject *)o)->ob_size; ! ! return res; ! } if (PyString_Check(o)) /* need to do extra error checking that PyLong_FromString() --- 934,939 ---- return o; } ! if (PyLong_Check(o)) ! return _PyLong_Copy((PyLongObject *)o); if (PyString_Check(o)) /* need to do extra error checking that PyLong_FromString() From tim_one@users.sourceforge.net Sat Mar 2 04:18:06 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 20:18:06 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.115,1.116 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv9574/python/Lib/test Modified Files: test_descr.py Log Message: _PyLong_Copy(): was creating a copy of the absolute value, but should copy the sign too. Added a test to test_descr to ensure that it does. Bugfix candidate. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.115 retrieving revision 1.116 diff -C2 -d -r1.115 -r1.116 *** test_descr.py 1 Mar 2002 22:24:24 -0000 1.115 --- test_descr.py 2 Mar 2002 04:18:04 -0000 1.116 *************** *** 1752,1755 **** --- 1752,1756 ---- a = longclone(-1) vereq(a.__dict__, {}) + vereq(long(a), -1) # verify PyNumber_Long() copies the sign bit class precfloat(float): From tim_one@users.sourceforge.net Sat Mar 2 04:18:07 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 20:18:07 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.113,1.114 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv9574/python/Objects Modified Files: longobject.c Log Message: _PyLong_Copy(): was creating a copy of the absolute value, but should copy the sign too. Added a test to test_descr to ensure that it does. Bugfix candidate. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.113 retrieving revision 1.114 diff -C2 -d -r1.113 -r1.114 *** longobject.c 16 Feb 2002 23:39:10 -0000 1.113 --- longobject.c 2 Mar 2002 04:18:04 -0000 1.114 *************** *** 64,68 **** result = _PyLong_New(i); if (result != NULL) { ! result->ob_size = i; while (--i >= 0) result->ob_digit[i] = src->ob_digit[i]; --- 64,68 ---- result = _PyLong_New(i); if (result != NULL) { ! result->ob_size = src->ob_size; while (--i >= 0) result->ob_digit[i] = src->ob_digit[i]; From tim_one@users.sourceforge.net Sat Mar 2 04:33:11 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 01 Mar 2002 20:33:11 -0800 Subject: [Python-checkins] CVS: python/dist/src/Include longintrepr.h,2.12,2.13 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv12140/python/Include Modified Files: longintrepr.h Log Message: For clarity, change _longobject to build directly from PyObject_VAR_HEAD instead of faking it by hand. It *is* a var object, and nothing but hysterical raisins to pretend it's an oddball. Index: longintrepr.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/longintrepr.h,v retrieving revision 2.12 retrieving revision 2.13 diff -C2 -d -r2.12 -r2.13 *** longintrepr.h 10 Sep 2001 20:52:47 -0000 2.12 --- longintrepr.h 2 Mar 2002 04:33:09 -0000 2.13 *************** *** 37,45 **** 0 <= ob_digit[i] <= MASK. The allocation function takes care of allocating extra memory ! so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available. */ struct _longobject { ! PyObject_HEAD ! int ob_size; digit ob_digit[1]; }; --- 37,48 ---- 0 <= ob_digit[i] <= MASK. The allocation function takes care of allocating extra memory ! so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available. ! ! CAUTION: Generic code manipulating subtypes of PyVarObject has to ! aware that longs abuse ob_size's sign bit. ! */ struct _longobject { ! PyObject_VAR_HEAD digit ob_digit[1]; }; From tim_one@users.sourceforge.net Sat Mar 2 08:43:21 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 00:43:21 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects object.c,2.163,2.164 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv18886/python/Objects Modified Files: object.c Log Message: Whether platform malloc(0) returns NULL has nothing to do with whether platform realloc(p, 0) returns NULL, so MALLOC_ZERO_RETURNS_NULL can be correctly undefined yet realloc(p, 0) can return NULL anyway. Prevent realloc(p, 0) doing free(p) and returning NULL via a different hack. Would probably be better to get rid of MALLOC_ZERO_RETURNS_NULL entirely. Bugfix candidate. Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.163 retrieving revision 2.164 diff -C2 -d -r2.163 -r2.164 *** object.c 1 Mar 2002 22:23:53 -0000 2.163 --- object.c 2 Mar 2002 08:43:19 -0000 2.164 *************** *** 1895,1903 **** PyMem_Realloc(void *p, size_t nbytes) { ! #if _PyMem_EXTRA > 0 ! if (nbytes == 0) ! nbytes = _PyMem_EXTRA; ! #endif ! return PyMem_REALLOC(p, nbytes); } --- 1895,1900 ---- PyMem_Realloc(void *p, size_t nbytes) { ! /* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */ ! return PyMem_REALLOC(p, nbytes ? nbytes : 1); } From tim_one@users.sourceforge.net Sat Mar 2 08:43:21 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 00:43:21 -0800 Subject: [Python-checkins] CVS: python/dist/src/Include pymem.h,2.4,2.5 pyport.h,2.43,2.44 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv18886/python/Include Modified Files: pymem.h pyport.h Log Message: Whether platform malloc(0) returns NULL has nothing to do with whether platform realloc(p, 0) returns NULL, so MALLOC_ZERO_RETURNS_NULL can be correctly undefined yet realloc(p, 0) can return NULL anyway. Prevent realloc(p, 0) doing free(p) and returning NULL via a different hack. Would probably be better to get rid of MALLOC_ZERO_RETURNS_NULL entirely. Bugfix candidate. Index: pymem.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pymem.h,v retrieving revision 2.4 retrieving revision 2.5 diff -C2 -d -r2.4 -r2.5 *** pymem.h 26 Jul 2001 21:34:59 -0000 2.4 --- pymem.h 2 Mar 2002 08:43:19 -0000 2.5 *************** *** 112,122 **** #define PyMem_NEW(type, n) \ ( (type *) PyMem_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)) ) ! #define PyMem_RESIZE(p, type, n) \ ! if ((p) == NULL) \ ! (p) = (type *)(PyMem_MALLOC( \ ! _PyMem_EXTRA + (n) * sizeof(type))); \ ! else \ ! (p) = (type *)(PyMem_REALLOC((p), \ ! _PyMem_EXTRA + (n) * sizeof(type))) #define PyMem_DEL(p) PyMem_FREE(p) --- 112,127 ---- #define PyMem_NEW(type, n) \ ( (type *) PyMem_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)) ) ! ! /* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */ ! #define PyMem_RESIZE(p, type, n) \ ! do { \ ! size_t _sum = (n) * sizeof(type); \ ! if (!_sum) \ ! _sum = 1; \ ! (p) = (type *)((p) ? \ ! PyMem_REALLOC(p, _sum) : \ ! PyMem_MALLOC(_sum)); \ ! } while (0) ! #define PyMem_DEL(p) PyMem_FREE(p) Index: pyport.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pyport.h,v retrieving revision 2.43 retrieving revision 2.44 diff -C2 -d -r2.43 -r2.44 *** pyport.h 26 Feb 2002 11:20:01 -0000 2.43 --- pyport.h 2 Mar 2002 08:43:19 -0000 2.44 *************** *** 367,372 **** #ifdef MALLOC_ZERO_RETURNS_NULL ! /* XXX Always allocate one extra byte, since some malloc's return NULL ! XXX for malloc(0) or realloc(p, 0). */ #define _PyMem_EXTRA 1 #else --- 367,380 ---- #ifdef MALLOC_ZERO_RETURNS_NULL ! /* Allocate an extra byte if the platform malloc(0) returns NULL. ! Caution: this bears no relation to whether realloc(p, 0) returns NULL ! when p != NULL. Even on platforms where malloc(0) does not return NULL, ! realloc(p, 0) may act like free(p) and return NULL. Examples include ! Windows, and Python's own obmalloc.c (as of 2-Mar-2002). For whatever ! reason, our docs promise that PyMem_Realloc(p, 0) won't act like ! free(p) or return NULL, so realloc() calls may have to be hacked ! too, but MALLOC_ZERO_RETURNS_NULL's state is irrelevant to realloc (it ! needs a different hack). ! */ #define _PyMem_EXTRA 1 #else From jvr@users.sourceforge.net Sat Mar 2 10:20:46 2002 From: jvr@users.sourceforge.net (Just van Rossum) Date: Sat, 02 Mar 2002 02:20:46 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/cg CGStubLib,1.1,1.2 CGStubLib.exp,1.1,1.2 _CGmodule.c,1.3,1.4 cgsupport.py,1.2,1.3 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cg In directory usw-pr-cvs1:/tmp/cvs-serv2641 Modified Files: CGStubLib CGStubLib.exp _CGmodule.c cgsupport.py Log Message: Added support for SyncCGContextOriginWithPort(). Index: CGStubLib =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/CGStubLib,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 Binary files /tmp/cvsoGvkHU and /tmp/cvsyUg6gF differ Index: CGStubLib.exp =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/CGStubLib.exp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** CGStubLib.exp 13 Dec 2001 13:17:20 -0000 1.1 --- CGStubLib.exp 2 Mar 2002 10:20:44 -0000 1.2 *************** *** 57,58 **** --- 57,59 ---- CGContextRelease CreateCGContextForPort + SyncCGContextOriginWithPort Index: _CGmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/_CGmodule.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** _CGmodule.c 18 Dec 2001 15:38:24 -0000 1.3 --- _CGmodule.c 2 Mar 2002 10:20:44 -0000 1.4 *************** *** 1116,1119 **** --- 1116,1133 ---- } + static PyObject *CGContextRefObj_SyncCGContextOriginWithPort(CGContextRefObject *_self, PyObject *_args) + { + PyObject *_res = NULL; + CGrafPtr port; + if (!PyArg_ParseTuple(_args, "O&", + GrafObj_Convert, &port)) + return NULL; + SyncCGContextOriginWithPort(_self->ob_itself, + port); + Py_INCREF(Py_None); + _res = Py_None; + return _res; + } + static PyMethodDef CGContextRefObj_methods[] = { {"CGContextSaveGState", (PyCFunction)CGContextRefObj_CGContextSaveGState, 1, *************** *** 1229,1232 **** --- 1243,1248 ---- {"CGContextSetShouldAntialias", (PyCFunction)CGContextRefObj_CGContextSetShouldAntialias, 1, "(int shouldAntialias) -> None"}, + {"SyncCGContextOriginWithPort", (PyCFunction)CGContextRefObj_SyncCGContextOriginWithPort, 1, + "(CGrafPtr port) -> None"}, {NULL, NULL, 0} }; Index: cgsupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/cgsupport.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** cgsupport.py 13 Dec 2001 13:40:04 -0000 1.2 --- cgsupport.py 2 Mar 2002 10:20:44 -0000 1.3 *************** *** 18,21 **** --- 18,22 ---- from macsupport import * + CGrafPtr = OpaqueByValueType("CGrafPtr", "GrafObj") # Create the type objects *************** *** 275,278 **** --- 276,286 ---- # ADD _methods initializer here execfile(INPUTFILE) + + # manual method, lives in Quickdraw.h + f = Method(void, 'SyncCGContextOriginWithPort', + (CGContextRef, 'ctx', InMode), + (CGrafPtr, 'port', InMode), + ) + CGContextRef_methods.append(f) CreateCGContextForPort_body = """\ From gvanrossum@users.sourceforge.net Sat Mar 2 13:59:34 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 02 Mar 2002 05:59:34 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.9,1.10 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv14179 Modified Files: datetime.py Log Message: Add XXX comment about duplication with calendar.py. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** datetime.py 2 Mar 2002 01:03:08 -0000 1.9 --- datetime.py 2 Mar 2002 13:59:32 -0000 1.10 *************** *** 7,10 **** --- 7,11 ---- # also assumes the current Gregorian calendar indefinitely extended in # both directions. + # XXX Why not borrow from calendar.py? _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] From guido@python.org Sat Mar 2 17:31:56 2002 From: guido@python.org (Guido van Rossum) Date: Sat, 02 Mar 2002 12:31:56 -0500 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.114,1.115 In-Reply-To: Your message of "Fri, 01 Mar 2002 18:18:34 EST." References: Message-ID: <200203021731.g22HVu715656@pcp742651pcs.reston01.va.comcast.net> > [Guido] > > Due to the bizarre definition of _PyLong_Copy(), creating an instance > > of a subclass of long with a negative value could cause core dumps > > later on. Unfortunately it looks like the behavior of _PyLong_Copy() > > is quite intentional, so the fix is more work than feels comfortable. > > What specifically is bizarre? Looks to me like _PyLong_Copy() is plain > wrong, and I probably wrote it . > > result->ob_size = i; > > should be > > result->ob_size = src->ob_size; > > if I'm guessing what bizarre means to you. > > Is that what you mean, or something else? I had misread the code and thought that long_pos() was depending on this property. But it isn't -- I somehow confused long_pos and long_abs. So thanks for fixing this. > The bizarreness *begins* with that _longobject fakes a > PyObject_VAR_HEAD header by hand, then abuses the ob_size member to > store the sign bit of the long as well as the number of bytes. So I > expect there was more than one bug here (and that _PyLong_Copy() is > one of them). I have half a feeling that the header was explicitly not using VAR_HEAD because it isn't quite a standard variable size object. But since PyLong_Type sets tp_itemsize, it really should be defined a variable size object. I wonder if there could be places where the assumption ob_size >= 0 is made. (I checked _PyObject_GetDictPtr() and it correctly checks for tsize < 0.) --Guido van Rossum (home page: http://www.python.org/~guido/) From tim.one@comcast.net Sat Mar 2 18:36:40 2002 From: tim.one@comcast.net (Tim Peters) Date: Sat, 02 Mar 2002 13:36:40 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.9,1.10 In-Reply-To: Message-ID: [Guido] > + # XXX Why not borrow from calendar.py? Primarily because it relies on platform mktime() and localtime(), which can't be counted on outside of 1970-2038. The Dates.py code is self-contained, and works for all years. Replace calendar's use of mktime() with something that works everywhere for all years, and you'd end up reinventing Dates.py. If we're going to recode this in C some day, it's vital to prototype algorithms that don't rely on inadequate C datetime functions. From tim.one@comcast.net Sat Mar 2 19:15:20 2002 From: tim.one@comcast.net (Tim Peters) Date: Sat, 02 Mar 2002 14:15:20 -0500 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.114,1.115 In-Reply-To: <200203021731.g22HVu715656@pcp742651pcs.reston01.va.comcast.net> Message-ID: [Guido, on _PyLong_Copy()] > I had misread the code and thought that long_pos() was depending on > this property. But it isn't -- I somehow confused long_pos and > long_abs. Ah, understandable. I'm glad we were looking at the same thing. > So thanks for fixing this. My pleasure. [on whether longs should use PyObject_VAR_HEAD] > I have half a feeling that the header was explicitly not using > VAR_HEAD because it isn't quite a standard variable size object. But > since PyLong_Type sets tp_itemsize, it really should be defined a > variable size object. In 2.2, pointers to long subtype instances can get cast to PyVarObject*, so I changed the decl to use VAR_HEAD, and added a caution there about the sign bit. > I wonder if there could be places where the assumption ob_size >= 0 is > made. (I checked _PyObject_GetDictPtr() and it correctly checks for > tsize < 0.) That's the only place I found that I believe can cast a pointer to a long subtype instance to a PyVarObject*. There are several hundred instances of ob_size in the codebase, though, so I wouldn't call this proof . From guido@python.org Sat Mar 2 20:42:48 2002 From: guido@python.org (Guido van Rossum) Date: Sat, 02 Mar 2002 15:42:48 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.9,1.10 In-Reply-To: Your message of "Sat, 02 Mar 2002 13:36:40 EST." References: Message-ID: <200203022042.g22Kgmv15937@pcp742651pcs.reston01.va.comcast.net> > [Guido] > > + # XXX Why not borrow from calendar.py? > > Primarily because it relies on platform mktime() and localtime(), > which can't be counted on outside of 1970-2038. The Dates.py code > is self-contained, and works for all years. Replace calendar's use > of mktime() with something that works everywhere for all years, and > you'd end up reinventing Dates.py. If we're going to recode this in > C some day, it's vital to prototype algorithms that don't rely on > inadequate C datetime functions. You're right, I missed that calendar.weekday() calls mktime() and localtime(). We're definitely going to recode this in C! --Guido van Rossum (home page: http://www.python.org/~guido/) From tim_one@users.sourceforge.net Sat Mar 2 20:42:49 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 12:42:49 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.10,1.11 test_datetime.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv13899 Modified Files: datetime.py test_datetime.py Log Message: Fiddle to compute day ordinals consistent with the "proleptic Gregorian" calendar at the heart of Dershowitz and Reingold's "Calendrical Calculations" book. They're the experts, and they call 1 Jan 1 "day 1" (the Dates.py code called 1 Jan 0 "day 1" -- same calendar, different origin). Their book gives algorithms for converting between proleptic Gregorian ordinals and many other calendar systems, so supplying these ordinals should make life much easier for people with other needs. Note that we're going to need *some* form of ordinal conversion regardless, in order to get around C limitations on timestamps and mktime(). Bummer: while putting the origin at year 1 simplifies _days_before_year(), it makes the details in _num2date significantly harder to understand; it's a net loss in clarity. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** datetime.py 2 Mar 2002 13:59:32 -0000 1.10 --- datetime.py 2 Mar 2002 20:42:47 -0000 1.11 *************** *** 6,11 **** # Utility functions, adapted from Python's Demo/classes/Dates.py, which # also assumes the current Gregorian calendar indefinitely extended in ! # both directions. ! # XXX Why not borrow from calendar.py? _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] --- 6,16 ---- # Utility functions, adapted from Python's Demo/classes/Dates.py, which # also assumes the current Gregorian calendar indefinitely extended in ! # both directions. Difference: Dates.py calls January 1 of year 0 day ! # number 1. The code here calls January 1 of year 1 day number 1. This is ! # to match the definition of the "proleptic Gregorian" calendar in Dershowitz ! # and Reingold's "Calendrical Calculations", where it's the base calendar ! # for all computations. See the book for algorithms for converting between ! # day ordinals in the proleptic Gregorian calendar and many other calendar ! # systems. _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] *************** *** 28,32 **** def _days_before_year(year): "year -> number of days before January 1st of year." ! return year*365 + (year+3)//4 - (year+99)//100 + (year+399)//400 def _days_in_month(month, year): --- 33,38 ---- def _days_before_year(year): "year -> number of days before January 1st of year." ! y = year - 1 ! return y*365 + y//4 - y//100 + y//400 def _days_in_month(month, year): *************** *** 48,52 **** date.day) ! _DI400Y = _days_before_year(400) # number of days in 400 years def _num2date(n): --- 54,58 ---- date.day) ! _DI400Y = _days_before_year(401) # number of days in 400 years def _num2date(n): *************** *** 54,66 **** n400 = (n-1) // _DI400Y # number of 400-year blocks preceding ! year = n400 * 400 n -= n400 * _DI400Y more = n // 365 ! dby = _days_before_year(more) if dby >= n: - more -= 1 dby -= _days_in_year(more) year += more n -= dby --- 60,73 ---- n400 = (n-1) // _DI400Y # number of 400-year blocks preceding ! year = n400 * 400 + 1 n -= n400 * _DI400Y more = n // 365 ! dby = _days_before_year(more + 1) if dby >= n: dby -= _days_in_year(more) + more -= 1 year += more + assert n > dby n -= dby *************** *** 70,74 **** month -= 1 dbm -= _days_in_month(month, year) ! return datetime(year, month, n-dbm) --- 77,81 ---- month -= 1 dbm -= _days_in_month(month, year) ! assert n > dbm return datetime(year, month, n-dbm) Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** test_datetime.py 2 Mar 2002 01:10:35 -0000 1.6 --- test_datetime.py 2 Mar 2002 20:42:47 -0000 1.7 *************** *** 28,38 **** def test_ordinal_conversions(self): ! import datetime as _datetime ! for year in range(_datetime.MINYEAR, _datetime.MAXYEAR + 1): ! for month, day in (1, 1), (12, 31), (6, 17): ! base = datetime(year, month, day) ! ordinal = _datetime._date2num(base) ! derived = _datetime._num2date(ordinal) ! self.assertEqual(base, derived) def test_bad_constructor_arguments(self): --- 28,53 ---- def test_ordinal_conversions(self): ! from datetime import _date2num, _num2date, MINYEAR, MAXYEAR ! ! # Verify 1 Jan 1 has ordinal 1. ! one = datetime.new(1, 1, 1) ! self.assertEqual(_date2num(one), 1) ! self.assertEqual(_num2date(1), one) ! ! # The first example in "Calendrical Calculations". ! d = datetime.new(1945, 11, 12) ! self.assertEqual(_date2num(d), 710347) ! self.assertEqual(_num2date(710347), d) ! ! for year in range(MINYEAR, MAXYEAR + 1): ! base = datetime(year, 1, 1) ! ordinal = _date2num(base) ! derived = _num2date(ordinal) ! self.assertEqual(base, derived) ! if year > MINYEAR: ! # Verify that moving back a day gets to the end of year-1. ! lastyear = datetime(year-1, 12, 31) ! derived = _num2date(ordinal - 1) ! self.assertEqual(lastyear, derived) def test_bad_constructor_arguments(self): From gvanrossum@users.sourceforge.net Sat Mar 2 21:09:52 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 02 Mar 2002 13:09:52 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.11,1.12 test_datetime.py,1.7,1.8 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv23789 Modified Files: datetime.py test_datetime.py Log Message: Add timedelta class, with unit tests. This doesn't yet interoperate with the datetime class, but will be on the next iteration. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** datetime.py 2 Mar 2002 20:42:47 -0000 1.11 --- datetime.py 2 Mar 2002 21:09:50 -0000 1.12 *************** *** 101,105 **** ! # XXX deltaobject? class datetime(basetime): --- 101,207 ---- ! class timedelta(object): ! """Represent the difference between two datetime objects. ! ! Supported operators: ! ! - add, subtract timedelta ! - unary plus, minus, abs ! - compare to timedelta ! - multiply, divide by int/long ! ! In addition, datetime supports subtraction of two datetime objects ! returning a timedelta, and addition or subtraction of a datetime ! and a timedelta giving a datetime. ! ! Representation: (days, seconds, microseconds). Why? Because I ! felt like it. ! """ ! ! def __init__(self, days=0, seconds=0, microseconds=0): ! s, us = divmod(microseconds, 1000000) ! assert us >= 0 ! d, s = divmod(s + seconds, 24*3600) ! assert s >= 0 ! d += days ! # d may be < 0 ! self.__days = d ! self.__seconds = s ! self.__microseconds = us ! ! def __repr__(self): ! if self.__microseconds: ! return "timedelta(%d, %d, %d)" % (self.__days, ! self.__seconds, ! self.__microseconds) ! if self.__seconds: ! return "timedelta(%d, %d)" % (self.__days, self.__seconds) ! return "timedelta(%d)" % self.__days ! ! days = property(lambda self: self.__days, doc="days") ! seconds = property(lambda self: self.__seconds, doc="seconds") ! microseconds = property(lambda self: self.__microseconds, ! doc="microseconds") ! ! def __add__(self, other): ! if isinstance(other, timedelta): ! return timedelta(self.__days + other.__days, ! self.__seconds + other.__seconds, ! self.__microseconds + other.__microseconds) ! return NotImplemented ! ! __radd__ = __add__ ! ! def __sub__(self, other): ! if isinstance(other, timedelta): ! return self + -other ! return NotImplemented ! ! def __rsub__(self, other): ! if isinstance(other, timedelta): ! return -self + other ! return NotImplemented ! ! def __neg__(self): ! return timedelta(-self.__days, -self.__seconds, -self.__microseconds) ! ! def __pos__(self): ! return self ! ! def __abs__(self): ! if self.__days < 0: ! return -self ! else: ! return self ! ! def __mul__(self, other): ! if isinstance(other, (int, long)): ! return timedelta(self.__days * other, ! self.__seconds * other, ! self.__microseconds * other) ! return NotImplemented ! ! __rmul__ = __mul__ ! ! def __div__(self, other): ! if isinstance(other, (int, long)): ! return timedelta(self.__days // other, ! self.__seconds // other, ! self.__microseconds // other) ! return NotImplemented ! ! __floordiv__ = __div__ ! ! def __cmp__(self, other): ! if not isinstance(other, timedelta): ! raise TypeError, ("can't compare timedelta to %s instance" % ! type(other).__name__) ! diff = self - other ! if diff.__days < 0: ! return -1 ! if diff.__days == 0 == diff.__seconds == diff.__microseconds: ! return 0 ! return 1 ! class datetime(basetime): Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** test_datetime.py 2 Mar 2002 20:42:47 -0000 1.7 --- test_datetime.py 2 Mar 2002 21:09:50 -0000 1.8 *************** *** 7,11 **** import unittest ! from datetime import datetime class TestDateTime(unittest.TestCase): --- 7,11 ---- import unittest ! from datetime import datetime, timedelta class TestDateTime(unittest.TestCase): *************** *** 101,104 **** --- 101,135 ---- self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) + + def test_timedelta(self): + a = timedelta(7) # One week + b = timedelta(0, 60) # One minute + c = timedelta(0, 0, 1000) # One millisecond + self.assertEqual(a+b+c, timedelta(7, 60, 1000)) + self.assertEqual(a-b, timedelta(6, 24*3600 - 60)) + self.assertEqual(-a, timedelta(-7)) + self.assertEqual(+a, timedelta(7)) + self.assertEqual(-b, timedelta(-1, 24*3600 - 60)) + self.assertEqual(-c, timedelta(-1, 24*3600 - 1, 999000)) + self.assertEqual(abs(a), a) + self.assertEqual(abs(-a), a) + self.assertEqual(timedelta(6, 24*3600), a) + self.assertEqual(timedelta(0, 0, 60*1000000), b) + self.assertEqual(a*10, timedelta(70)) + self.assertEqual(a*10, 10*a) + self.assertEqual(a*10L, 10*a) + self.assertEqual(b*10, timedelta(0, 600)) + self.assertEqual(10*b, timedelta(0, 600)) + self.assertEqual(b*10L, timedelta(0, 600)) + self.assertEqual(c*10, timedelta(0, 0, 10000)) + self.assertEqual(10*c, timedelta(0, 0, 10000)) + self.assertEqual(c*10L, timedelta(0, 0, 10000)) + self.assertEqual(a*-1, -a) + self.assertEqual(b*-2, -b-b) + self.assertEqual(c*-2, -c+-c) + self.assertEqual(b*(60*24), (b*60)*24) + self.assertEqual(b*(60*24), (60*b)*24) + self.assertEqual(c*1000, timedelta(0, 1)) + self.assertEqual(1000*c, timedelta(0, 1)) def test_suite(): From gvanrossum@users.sourceforge.net Sat Mar 2 22:33:49 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 02 Mar 2002 14:33:49 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.12,1.13 test_datetime.py,1.8,1.9 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv12052 Modified Files: datetime.py test_datetime.py Log Message: - Add computations on datetime instances (__add__, __radd__ and __sub__) - Fix docstring of _date2num() - Add XXX comment about how we derive the default tzoffset - Add __repr__ and __str__ to class datetime - In _test(), run the tests from test_datetime Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** datetime.py 2 Mar 2002 21:09:50 -0000 1.12 --- datetime.py 2 Mar 2002 22:33:46 -0000 1.13 *************** *** 48,52 **** def _date2num(date): ! "datetime object -> day ordinal, considering 01-Jan-0000 as day 1." assert isinstance(date, datetime) return (_days_before_year(date.year) + --- 48,52 ---- def _date2num(date): ! "datetime object -> day ordinal, considering 01-Jan-0001 as day 1." assert isinstance(date, datetime) return (_days_before_year(date.year) + *************** *** 232,235 **** --- 232,237 ---- raise ValueError('microsecond must be in 0..999999', microsecond) if tzoffset is None: + # XXX This decides whether local time is DST or not once, + # and never changes its mind, regardless how long we run if datetime.__isdst is None: datetime.__isdst = _time.localtime()[-1] *************** *** 279,282 **** --- 281,302 ---- utcnow = classmethod(utcnow) + def __repr__(self): + L = [self.__year, self.__month, self.__day, # These are never zero + self.__hour, self.__minute, self.__second, self.__microsecond] + while L[-1] == 0: + del L[-1] + s = ", ".join(map(str, L)) + return "datetime(%s, tzoffset=%d)" % (s, self.__tzoffset) + + def __str__(self): + if self.__tzoffset == 0: + return self.ctime() + " UTC" + if self.__tzoffset > 0: + h, m = divmod(self.__tzoffset, 60) + else: + h, m = divmod(-self.__tzoffset, 60) + h = -h + return self.ctime() + " %+03d:%02d" % (h, m) + # Read-only field accessors year = property(lambda self: self.__year, *************** *** 385,398 **** return _time.strftime(fmt, _time.gmtime(self._mktime())) ! # __add__, __sub__? def _test(): ! now = _time.time() ! print _time.ctime(now) ! t = datetime.fromtimestamp(now) ! print t.ctime(), divmod(t.tzoffset, 60), t.hour ! u = datetime.utcfromtimestamp(now) ! print u.utcctime(), divmod(u.tzoffset, 60), u.hour ! assert t == u if __name__ == "__main__": --- 405,449 ---- return _time.strftime(fmt, _time.gmtime(self._mktime())) ! # Computations ! ! def __add__(self, other): ! if isinstance(other, timedelta): ! hh, mm, ss, us = (self.__hour, ! self.__minute, ! self.__second + other.seconds, ! self.__microsecond + other.microseconds) ! carry_ss, us = divmod(us, 1000000) ! carry_mm, ss = divmod(ss+carry_ss, 60) ! carry_hh, mm = divmod(mm+carry_mm, 60) ! days, hh = divmod(hh+carry_hh, 24) ! result = _num2date(days + other.days + _date2num(self)) ! result.__hour = hh ! result.__minute = mm ! result.__second = ss ! result.__microsecond = us ! result.__tzoffset = self.__tzoffset ! return result ! return NotImplemented ! ! __radd__ = __add__ ! ! def __sub__(self, other): ! if isinstance(other, timedelta): ! return self + -other ! if isinstance(other, datetime): ! days1 = _date2num(self) ! days2 = _date2num(other) ! secs1 = (self.__second + 60 * (self.__minute - self.__tzoffset) + ! self.__hour * 3600) ! secs2 = (other.__second + 60 * (other.__minute - other.__tzoffset) + ! other.__hour * 3600) ! return timedelta(days1 - days2, secs1 - secs2, ! self.__microsecond - other.__microsecond) ! return NotImplemented ! def _test(): ! import test_datetime ! test_datetime.test_main() if __name__ == "__main__": Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** test_datetime.py 2 Mar 2002 21:09:50 -0000 1.8 --- test_datetime.py 2 Mar 2002 22:33:46 -0000 1.9 *************** *** 40,43 **** --- 40,44 ---- self.assertEqual(_num2date(710347), d) + # XXX To speed up this loop, use range(MINYEAR, MAXYEAR + 1, 11) for year in range(MINYEAR, MAXYEAR + 1): base = datetime(year, 1, 1) *************** *** 132,135 **** --- 133,184 ---- self.assertEqual(c*1000, timedelta(0, 1)) self.assertEqual(1000*c, timedelta(0, 1)) + + def test_computations(self): + a = datetime(2002, 1, 31) + b = datetime(1956, 1, 31) + diff = a-b + self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) + self.assertEqual(diff.seconds, 0) + self.assertEqual(diff.microseconds, 0) + a = datetime(2002, 3, 2, 17, 6) + millisec = timedelta(0, 0, 1000) + hour = timedelta(0, 3600) + day = timedelta(1) + week = timedelta(7) + self.assertEqual(a + hour, datetime(2002, 3, 2, 18, 6)) + self.assertEqual(a + 10*hour, datetime(2002, 3, 3, 3, 6)) + self.assertEqual(a - hour, datetime(2002, 3, 2, 16, 6)) + self.assertEqual(a - hour, a + -hour) + self.assertEqual(a - 20*hour, datetime(2002, 3, 1, 21, 6)) + self.assertEqual(a + day, datetime(2002, 3, 3, 17, 6)) + self.assertEqual(a - day, datetime(2002, 3, 1, 17, 6)) + self.assertEqual(a + week, datetime(2002, 3, 9, 17, 6)) + self.assertEqual(a - week, datetime(2002, 2, 23, 17, 6)) + self.assertEqual(a + 52*week, datetime(2003, 3, 1, 17, 6)) + self.assertEqual(a - 52*week, datetime(2001, 3, 3, 17, 6)) + self.assertEqual((a + week) - a, week) + self.assertEqual((a + day) - a, day) + self.assertEqual((a + hour) - a, hour) + self.assertEqual((a + millisec) - a, millisec) + self.assertEqual((a - week) - a, -week) + self.assertEqual((a - day) - a, -day) + self.assertEqual((a - hour) - a, -hour) + self.assertEqual((a - millisec) - a, -millisec) + self.assertEqual(a - (a + week), -week) + self.assertEqual(a - (a + day), -day) + self.assertEqual(a - (a + hour), -hour) + self.assertEqual(a - (a + millisec), -millisec) + self.assertEqual(a - (a - week), week) + self.assertEqual(a - (a - day), day) + self.assertEqual(a - (a - hour), hour) + self.assertEqual(a - (a - millisec), millisec) + self.assertEqual(a + (week + day + hour + millisec), + datetime(2002, 3, 10, 18, 6, 0, 1000)) + self.assertEqual(a + (week + day + hour + millisec), + (((a + week) + day) + hour) + millisec) + self.assertEqual(a - (week + day + hour + millisec), + datetime(2002, 2, 22, 16, 5, 59, 999000)) + self.assertEqual(a - (week + day + hour + millisec), + (((a - week) - day) - hour) - millisec) def test_suite(): From gvanrossum@users.sourceforge.net Sat Mar 2 22:57:56 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 02 Mar 2002 14:57:56 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv19164 Modified Files: datetime.py Log Message: - Add docstrings to all public methods. - Add module docstring. - Augment datetime class docstring. - Reformat mis-indented __sub__. - Add a few comments for groups of methods. - Change the _utc_ymdHM() docstring to a comment. - Change triple quotes around 1-line docstrings to regular quotes. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** datetime.py 2 Mar 2002 22:33:46 -0000 1.13 --- datetime.py 2 Mar 2002 22:57:54 -0000 1.14 *************** *** 1,2 **** --- 1,9 ---- + """Concrete date/time type -- prototype implemented in Python. + + See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage + + See also http://dir.yahoo.com/Reference/calendars/ + """ + import time as _time *************** *** 206,212 **** class datetime(basetime): ! """Concrete date/time type -- prototype implemented in Python. ! See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage """ --- 213,238 ---- class datetime(basetime): ! """Concrete date/time type. ! Constructors: ! ! __init__() == new() ! now(), utcnow() ! fromtimestamp(), utcfromtimestamp() ! ! Operators: ! ! __repr__, __str__ ! __cmp__, __hash__ ! __add__, __radd__, __sub__ (add/radd only with timedelta other arg) ! ! Methods: ! ! timetuple(), utctimetuple() ! ctime(), utcctime() ! strftime(), utcstrftime() ! ! Properties (readonly): ! year, month, day, hour, minute, second, microsecond, tzoffset """ *************** *** 215,218 **** --- 241,253 ---- def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzoffset=None): + """Constructor. + + Arguments: + + year, month, day (required, base 1) + hour, minute, second, microsecond (default to zero) + tzoffset (minutes east of UTC; defaults to local time) + + """ if not MINYEAR <= year <= MAXYEAR: raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), *************** *** 251,259 **** --- 286,298 ---- self.__tzoffset = tzoffset # minutes east of UTC + # Additional constructors + def new(cls, *args, **kwds): + "Constructor. Same arguments as __init__." return cls(*args, **kwds) new = classmethod(new) def fromtimestamp(cls, t): + "Construct a datetime from a POSIX timestamp (like time.time())." y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t) us = int((t % 1.0) * 1000000) *************** *** 266,269 **** --- 305,309 ---- def now(cls): + "Construct a datetime from time.time()." t = _time.time() return cls.fromtimestamp(t) *************** *** 271,274 **** --- 311,315 ---- def utcfromtimestamp(cls, t): + "Construct a UTC datetime from a POSIX timestamp (like time.time())." y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t) us = int((t % 1.0) * 1000000) *************** *** 277,285 **** --- 318,330 ---- def utcnow(cls): + "Construct a UTC datetime from time.time()." t = _time.time() return cls.utcfromtimestamp(t) utcnow = classmethod(utcnow) + # Conversions to string + def __repr__(self): + "Convert to formal string, for repr()." L = [self.__year, self.__month, self.__day, # These are never zero self.__hour, self.__minute, self.__second, self.__microsecond] *************** *** 290,293 **** --- 335,339 ---- def __str__(self): + "Convert to pretty string, for str()." if self.__tzoffset == 0: return self.ctime() + " UTC" *************** *** 312,315 **** --- 358,363 ---- doc="time zone offset in minutes east of UTC") + # Standard conversions, __cmp__, __hash__ (and helpers) + def _mktime(self): # Helper to call time.mktime() *************** *** 325,337 **** def timetuple(self): ! """Return local time tuple compatible with time.localtime().""" return _time.localtime(self._mktime()) def utctimetuple(self): ! """Return UTC time tuple compatible with time.gmtime().""" return _time.gmtime(self._mktime()) def __cmp__(self, other): ! """Three-way comparison.""" if isinstance(other, datetime): if other.__tzoffset == self.__tzoffset: --- 373,385 ---- def timetuple(self): ! "Return local time tuple compatible with time.localtime()." return _time.localtime(self._mktime()) def utctimetuple(self): ! "Return UTC time tuple compatible with time.gmtime()." return _time.gmtime(self._mktime()) def __cmp__(self, other): ! "Three-way comparison." if isinstance(other, datetime): if other.__tzoffset == self.__tzoffset: *************** *** 351,355 **** def _utc_ymdHM(self): ! "Return (year, month, day, hour, minute) in UTC equivalent." y, m, d = self.__year, self.__month, self.__day H, M = self.__hour, self.__minute --- 399,403 ---- def _utc_ymdHM(self): ! # Helper to return (year, month, day, hour, minute) in UTC equivalent y, m, d = self.__year, self.__month, self.__day H, M = self.__hour, self.__minute *************** *** 385,389 **** def __hash__(self): ! """Hash.""" # Caution: objects that compare equal must have equal hashcodes, # and two datetimes can be equal even if their fields aren't --- 433,437 ---- def __hash__(self): ! "Hash." # Caution: objects that compare equal must have equal hashcodes, # and two datetimes can be equal even if their fields aren't *************** *** 393,406 **** --- 441,460 ---- return hash((y, m, d, H, M, self.__second, self.__microsecond)) + # Formatting methods + def ctime(self): + "Format a la ctime() in local time." return _time.strftime("%c", _time.localtime(self._mktime())) def strftime(self, fmt): + "Format using strftime() in local time." return _time.strftime(fmt, _time.localtime(self._mktime())) def utcctime(self): + "Format a la ctime() in UTC." return _time.strftime("%c", _time.gmtime(self._mktime())) def utcstrftime(self, fmt): + "Format using strftime() in UTC." return _time.strftime(fmt, _time.gmtime(self._mktime())) *************** *** 408,411 **** --- 462,466 ---- def __add__(self, other): + "Add a datetime to a timedelta." if isinstance(other, timedelta): hh, mm, ss, us = (self.__hour, *************** *** 429,444 **** def __sub__(self, other): ! if isinstance(other, timedelta): ! return self + -other ! if isinstance(other, datetime): ! days1 = _date2num(self) ! days2 = _date2num(other) ! secs1 = (self.__second + 60 * (self.__minute - self.__tzoffset) + ! self.__hour * 3600) ! secs2 = (other.__second + 60 * (other.__minute - other.__tzoffset) + ! other.__hour * 3600) ! return timedelta(days1 - days2, secs1 - secs2, ! self.__microsecond - other.__microsecond) ! return NotImplemented --- 484,502 ---- def __sub__(self, other): ! "Subtract two datetimes, or a datetime and a timedelta." ! if isinstance(other, timedelta): ! return self + -other ! if isinstance(other, datetime): ! days1 = _date2num(self) ! days2 = _date2num(other) ! secs1 = (self.__second + ! (self.__minute - self.__tzoffset) * 60 + ! self.__hour * 3600) ! secs2 = (other.__second + ! (other.__minute - other.__tzoffset) * 60 + ! other.__hour * 3600) ! return timedelta(days1 - days2, secs1 - secs2, ! self.__microsecond - other.__microsecond) ! return NotImplemented From gvanrossum@users.sourceforge.net Sat Mar 2 23:33:40 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 02 Mar 2002 15:33:40 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.14,1.15 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv27887 Modified Files: datetime.py Log Message: Add __str__ to timedelta that returns something like "7 days, 1 hour, 1 minute, 18 seconds, 321623 microseconds" Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** datetime.py 2 Mar 2002 22:57:54 -0000 1.14 --- datetime.py 2 Mar 2002 23:33:38 -0000 1.15 *************** *** 146,149 **** --- 146,168 ---- return "timedelta(%d)" % self.__days + def __str__(self): + def plural(n): + return n, n != 1 and "s" or "" + L = [] + if self.__days: + L.append("%d day%s" % plural(self.__days)) + if self.__seconds: + mm, ss = divmod(self.__seconds, 60) + hh, mm = divmod(mm, 60) + if hh: + L.append("%d hour%s" % plural(hh)) + if mm: + L.append("%d minute%s" % plural(mm)) + if ss: + L.append("%d second%s" % plural(ss)) + if self.__microseconds: + L.append("%d microsecond%s" % plural(self.__microseconds)) + return ", ".join(L) + days = property(lambda self: self.__days, doc="days") seconds = property(lambda self: self.__seconds, doc="seconds") From tim_one@users.sourceforge.net Sun Mar 3 02:10:26 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 18:10:26 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.15,1.16 test_datetime.py,1.9,1.10 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv23159 Modified Files: datetime.py test_datetime.py Log Message: Broke dependence of _num2date and _date2num on datetime objects, and renamed to _ord2ymd and _ymd2ord. Proper testing of these functions requires exercising negative ordinals and years, and using datetime objects blocked that. Added a datetime.fromordinal() constructor, and a toordinal() method. "Something like that" is needed for people who want to build other calendar systems on top of this basic one. Changed test_ordinal_conversions() to do exhaustive testing on both sides of the origin, and every 7th year across the datetime range. This is less testing than it was doing before, but the test runs much faster now than can be accounted for by that alone. I suspect it's avoiding object hair that makes the difference (the test uses _ord2ymd and _ymd2ord directly now, never constructing a datetime object). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** datetime.py 2 Mar 2002 23:33:38 -0000 1.15 --- datetime.py 3 Mar 2002 02:10:24 -0000 1.16 *************** *** 52,68 **** def _days_before_month(month, year): "month, year -> number of days in year preceeding first day of month." return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year)) ! def _date2num(date): ! "datetime object -> day ordinal, considering 01-Jan-0001 as day 1." ! assert isinstance(date, datetime) ! return (_days_before_year(date.year) + ! _days_before_month(date.month, date.year) + ! date.day) _DI400Y = _days_before_year(401) # number of days in 400 years ! def _num2date(n): ! "day ordinal -> datetime object." n400 = (n-1) // _DI400Y # number of 400-year blocks preceding --- 52,74 ---- def _days_before_month(month, year): "month, year -> number of days in year preceeding first day of month." + if not 1 <= month <= 12: + raise ValueError('month must be in 1..12', month) return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year)) ! def _ymd2ord(year, month, day): ! "year, month, day -> ordinal, considering 01-Jan-0001 as day 1." ! if not 1 <= month <= 12: ! raise ValueError('month must be in 1..12', month) ! dim = _days_in_month(month, year) ! if not 1 <= day <= dim: ! raise ValueError('day must be in 1..%d' % dim, day) ! return (_days_before_year(year) + ! _days_before_month(month, year) + ! day) _DI400Y = _days_before_year(401) # number of days in 400 years ! def _ord2ymd(n): ! "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1." n400 = (n-1) // _DI400Y # number of 400-year blocks preceding *************** *** 85,89 **** dbm -= _days_in_month(month, year) assert n > dbm ! return datetime(year, month, n-dbm) class basetime(object): --- 91,95 ---- dbm -= _days_in_month(month, year) assert n > dbm ! return year, month, n-dbm class basetime(object): *************** *** 239,242 **** --- 245,249 ---- now(), utcnow() fromtimestamp(), utcfromtimestamp() + fromordinal() Operators: *************** *** 251,254 **** --- 258,262 ---- ctime(), utcctime() strftime(), utcstrftime() + toordinal() Properties (readonly): *************** *** 342,345 **** --- 350,363 ---- utcnow = classmethod(utcnow) + def fromordinal(cls, n): + """Contruct a datetime from a proleptic Gregorian ordinal. + + January 1 of year 1 is day 1. Only the year, month and day are + non-zero in the result. + """ + y, m, d = _ord2ymd(n) + return cls(y, m, d) + fromordinal = classmethod(fromordinal) + # Conversions to string *************** *** 399,402 **** --- 417,428 ---- return _time.gmtime(self._mktime()) + def toordinal(self): + """Return proleptic Gregorian ordinal for the year, month and day. + + January 1 of year 1 is day 1. Only the year, month and day values + contribute to the result. + """ + return _ymd2ord(self.year, self.month, self.day) + def __cmp__(self, other): "Three-way comparison." *************** *** 491,495 **** carry_hh, mm = divmod(mm+carry_mm, 60) days, hh = divmod(hh+carry_hh, 24) ! result = _num2date(days + other.days + _date2num(self)) result.__hour = hh result.__minute = mm --- 517,521 ---- carry_hh, mm = divmod(mm+carry_mm, 60) days, hh = divmod(hh+carry_hh, 24) ! result = datetime.fromordinal(days + other.days + self.toordinal()) result.__hour = hh result.__minute = mm *************** *** 507,512 **** return self + -other if isinstance(other, datetime): ! days1 = _date2num(self) ! days2 = _date2num(other) secs1 = (self.__second + (self.__minute - self.__tzoffset) * 60 + --- 533,538 ---- return self + -other if isinstance(other, datetime): ! days1 = self.toordinal() ! days2 = other.toordinal() secs1 = (self.__second + (self.__minute - self.__tzoffset) * 60 + Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** test_datetime.py 2 Mar 2002 22:33:46 -0000 1.9 --- test_datetime.py 3 Mar 2002 02:10:24 -0000 1.10 *************** *** 28,54 **** def test_ordinal_conversions(self): ! from datetime import _date2num, _num2date, MINYEAR, MAXYEAR ! ! # Verify 1 Jan 1 has ordinal 1. ! one = datetime.new(1, 1, 1) ! self.assertEqual(_date2num(one), 1) ! self.assertEqual(_num2date(1), one) ! # The first example in "Calendrical Calculations". ! d = datetime.new(1945, 11, 12) ! self.assertEqual(_date2num(d), 710347) ! self.assertEqual(_num2date(710347), d) ! # XXX To speed up this loop, use range(MINYEAR, MAXYEAR + 1, 11) ! for year in range(MINYEAR, MAXYEAR + 1): ! base = datetime(year, 1, 1) ! ordinal = _date2num(base) ! derived = _num2date(ordinal) ! self.assertEqual(base, derived) ! if year > MINYEAR: ! # Verify that moving back a day gets to the end of year-1. ! lastyear = datetime(year-1, 12, 31) ! derived = _num2date(ordinal - 1) ! self.assertEqual(lastyear, derived) def test_bad_constructor_arguments(self): --- 28,52 ---- def test_ordinal_conversions(self): ! from datetime import _ymd2ord, _ord2ymd, MINYEAR, MAXYEAR ! # Check some fixed values. ! for y, m, d, n in [(1, 1, 1, 1), # calendar origin ! (0, 12, 31, 0), ! (0, 12, 30, -1), ! # first example from "Calendrical Calculations" ! (1945, 11, 12, 710347)]: ! self.assertEqual(n, _ymd2ord(y, m, d)) ! self.assertEqual((y, m, d), _ord2ymd(n)) ! # Check first and last days of year exhaustively across 2000 years ! # centered at the origin, and spottily over the whole range of ! # years datetime objects support. ! for year in range(-1001, 1002) + range(MINYEAR, MAXYEAR+1, 7): ! # Verify (year, 1, 1) -> ordinal -> y, m, d is identity. ! n = _ymd2ord(year, 1, 1) ! self.assertEqual((year, 1, 1), _ord2ymd(n)) ! # Verify that moving back a day gets to the end of year-1. ! self.assertEqual((year-1, 12, 31), _ord2ymd(n-1)) ! self.assertEqual(_ymd2ord(year-1, 12, 31), n-1) def test_bad_constructor_arguments(self): From tim_one@users.sourceforge.net Sun Mar 3 02:15:36 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 18:15:36 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.10,1.11 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv25139 Modified Files: test_datetime.py Log Message: Added test_roundtrip(), to verify datetime->string->datetime identity, and to verify that a datetime object can be reconstructed exactly from its pieces. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** test_datetime.py 3 Mar 2002 02:10:24 -0000 1.10 --- test_datetime.py 3 Mar 2002 02:15:34 -0000 1.11 *************** *** 20,23 **** --- 20,37 ---- self.assertEqual(dt.second, 0) + def test_roundtrip(self): + for dt in (datetime.new(1, 2, 3, 4, 5, 6, 7, 8), + datetime.now()): + # Verify dt -> string -> datetime identity. + s = repr(dt) + dt2 = eval(s) + self.assertEqual(dt, dt2) + + # Verify identity via reconstructing from pieces. + dt2 = datetime.new(dt.year, dt.month, dt.day, + dt.hour, dt.minute, dt.second, + dt.microsecond, dt.tzoffset) + self.assertEqual(dt, dt2) + def test_tz_independent_comparing(self): dt1 = datetime.new(2002, 3, 1, 9, 0, 0, tzoffset=-60) From gvanrossum@users.sourceforge.net Sun Mar 3 02:50:54 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 02 Mar 2002 18:50:54 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.16,1.17 test_datetime.py,1.11,1.12 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv31633 Modified Files: datetime.py test_datetime.py Log Message: Add weekday() and iso_calendar() methods. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** datetime.py 3 Mar 2002 02:10:24 -0000 1.16 --- datetime.py 3 Mar 2002 02:50:52 -0000 1.17 *************** *** 545,548 **** --- 545,594 ---- return NotImplemented + # Day-of-the-week and week-of-the-year, according to ISO + + def weekday(self): + "Return day of the week, where Monday == 0 (according to ISO)." + # The constant 6 was obtained experimentally :-) + return (_ymd2ord(self.__year, self.__month, self.__day) + 6) % 7 + + def isocalendar(self): + """Return a 3-tuple containing ISO year, week number, and weekday. + + The first ISO week of the year is the (Mon-Sun) week + containing the year's first Thursday; everything rest derives + from that. + + Note that the first week is 1, but Monday is 0. + + ISO calendar algorithm taken from + http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm + """ + year = self.__year + week1monday = _isoweek1monday(year) + today = _ymd2ord(self.__year, self.__month, self.__day) + # Internally, week has origin 0 + week, day = divmod(today - week1monday, 7) + if week < 0: + year -= 1 + week1monday = _isoweek1monday(year) + week, day = divmod(today - week1monday, 7) + elif week >= 52: + if today >= _isoweek1monday(year+1): + year += 1 + week = 0 + return year, week+1, day + + + def _isoweek1monday(year): + # Helper to calculate the day number of the Monday starting week 1 + # XXX This could be done more efficiently + THURSDAY = 3 + firstday = _ymd2ord(year, 1, 1) + firstweekday = (firstday + 6) % 7 # See weekday() above + week1monday = firstday - firstweekday + if firstweekday > THURSDAY: + week1monday += 7 + return week1monday + def _test(): Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** test_datetime.py 3 Mar 2002 02:15:34 -0000 1.11 --- test_datetime.py 3 Mar 2002 02:50:52 -0000 1.12 *************** *** 194,197 **** --- 194,261 ---- (((a - week) - day) - hour) - millisec) + def test_weekday(self): + for i in range(7): + # March 4, 2002 is a Monday + self.assertEqual(datetime(2002, 3, 4+i).weekday(), i) + # January 2, 1956 is a Monday + self.assertEqual(datetime(1956, 1, 2+i).weekday(), i) + + def test_isocalendar(self): + # Check examples from + # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm + for i in range(7): + d = datetime(2003, 12, 22+i) + self.assertEqual(d.isocalendar(), (2003, 52, i)) + d = datetime(2003, 12, 29) + timedelta(i) + self.assertEqual(d.isocalendar(), (2004, 1, i)) + d = datetime(2004, 1, 5+i) + self.assertEqual(d.isocalendar(), (2004, 2, i)) + d = datetime(2009, 12, 21+i) + self.assertEqual(d.isocalendar(), (2009, 52, i)) + d = datetime(2009, 12, 28) + timedelta(i) + self.assertEqual(d.isocalendar(), (2009, 53, i)) + d = datetime(2010, 1, 4+i) + self.assertEqual(d.isocalendar(), (2010, 1, i)) + + def test_iso_long_years(self): + # Calculate long ISO years and compare to table from + # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm + ISO_LONG_YEARS_TABLE = """ + 4 32 60 88 + 9 37 65 93 + 15 43 71 99 + 20 48 76 + 26 54 82 + + 105 133 161 189 + 111 139 167 195 + 116 144 172 + 122 150 178 + 128 156 184 + + 201 229 257 285 + 207 235 263 291 + 212 240 268 296 + 218 246 274 + 224 252 280 + + 303 331 359 387 + 308 336 364 392 + 314 342 370 398 + 320 348 376 + 325 353 381 + """ + iso_long_years = map(int, ISO_LONG_YEARS_TABLE.split()) + iso_long_years.sort() + L = [] + for i in range(400): + d = datetime(2000+i, 12, 31) + d1 = datetime(1600+i, 12, 31) + self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:]) + if d.isocalendar()[1] == 53: + L.append(i) + self.assertEqual(L, iso_long_years) + + def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') From aimacintyre@users.sourceforge.net Sun Mar 3 02:59:18 2002 From: aimacintyre@users.sourceforge.net (Andrew I MacIntyre) Date: Sat, 02 Mar 2002 18:59:18 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules _hotshot.c,1.14,1.15 dbmmodule.c,2.28,2.29 fcntlmodule.c,2.33,2.34 main.c,1.63,1.64 pwdmodule.c,1.27,1.28 readline.c,2.43,2.44 selectmodule.c,2.60,2.61 signalmodule.c,2.62,2.63 termios.c,2.33,2.34 timemodule.c,2.122,2.123 unicodedata.c,2.14,2.15 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv430 Modified Files: _hotshot.c dbmmodule.c fcntlmodule.c main.c pwdmodule.c readline.c selectmodule.c signalmodule.c termios.c timemodule.c unicodedata.c Log Message: OS/2 EMX port changes (Modules part of patch #450267): Modules/ _hotshot.c dbmmodule.c fcntlmodule.c main.c pwdmodule.c readline.c selectmodule.c signalmodule.c termios.c timemodule.c unicodedata.c Index: _hotshot.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_hotshot.c,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** _hotshot.c 12 Feb 2002 04:02:33 -0000 1.14 --- _hotshot.c 3 Mar 2002 02:59:15 -0000 1.15 *************** *** 27,31 **** #error "This module requires gettimeofday() on non-Windows platforms!" #endif ! #ifdef macintosh #include #else --- 27,31 ---- #error "This module requires gettimeofday() on non-Windows platforms!" #endif ! #if defined(macintosh) || (defined(PYOS_OS2) && defined(PYCC_GCC)) #include #else *************** *** 52,55 **** --- 52,59 ---- #endif + #if defined(PYOS_OS2) && defined(PYCC_GCC) + #define PATH_MAX 260 + #endif + #ifndef PATH_MAX # ifdef MAX_PATH *************** *** 988,992 **** #endif } ! #if defined(MS_WIN32) || defined(macintosh) rusage_diff = -1; #else --- 992,996 ---- #endif } ! #if defined(MS_WIN32) || defined(macintosh) || defined(PYOS_OS2) rusage_diff = -1; #else Index: dbmmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/dbmmodule.c,v retrieving revision 2.28 retrieving revision 2.29 diff -C2 -d -r2.28 -r2.29 *** dbmmodule.c 8 Dec 2001 18:02:56 -0000 2.28 --- dbmmodule.c 3 Mar 2002 02:59:15 -0000 2.29 *************** *** 14,18 **** --- 14,22 ---- #if defined(HAVE_NDBM_H) #include + #if defined(PYOS_OS2) && !defined(PYCC_GCC) static char *which_dbm = "ndbm"; + #else + static char *which_dbm = "GNU gdbm"; /* EMX port of GDBM */ + #endif #elif defined(HAVE_DB1_NDBM_H) #include Index: fcntlmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/fcntlmodule.c,v retrieving revision 2.33 retrieving revision 2.34 diff -C2 -d -r2.33 -r2.34 *** fcntlmodule.c 12 Jan 2002 11:05:06 -0000 2.33 --- fcntlmodule.c 3 Mar 2002 02:59:15 -0000 2.34 *************** *** 223,226 **** --- 223,231 ---- return NULL; + #if defined(PYOS_OS2) && defined(PYCC_GCC) + PyErr_SetString(PyExc_NotImplementedError, + "lockf not supported on OS/2 (EMX)"); + return NULL; + #else #ifndef LOCK_SH #define LOCK_SH 1 /* shared lock */ *************** *** 228,232 **** #define LOCK_NB 4 /* don't block when locking */ #define LOCK_UN 8 /* unlock */ ! #endif { struct flock l; --- 233,237 ---- #define LOCK_NB 4 /* don't block when locking */ #define LOCK_UN 8 /* unlock */ ! #endif /* LOCK_SH */ { struct flock l; *************** *** 276,279 **** --- 281,285 ---- Py_INCREF(Py_None); return Py_None; + #endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */ } Index: main.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/main.c,v retrieving revision 1.63 retrieving revision 1.64 diff -C2 -d -r1.63 -r1.64 *** main.c 11 Feb 2002 18:46:47 -0000 1.63 --- main.c 3 Mar 2002 02:59:16 -0000 1.64 *************** *** 9,16 **** #endif ! #if defined(PYOS_OS2) || defined(MS_WINDOWS) #define PYTHONHOMEHELP "\\lib" #else #define PYTHONHOMEHELP "/pythonX.X" #endif --- 9,20 ---- #endif ! #if (defined(PYOS_OS2) && !defined(PYCC_GCC)) || defined(MS_WINDOWS) #define PYTHONHOMEHELP "\\lib" #else + #if defined(PYOS_OS2) && defined(PYCC_GCC) + #define PYTHONHOMEHELP "/Lib" + #else #define PYTHONHOMEHELP "/pythonX.X" + #endif #endif Index: pwdmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/pwdmodule.c,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** pwdmodule.c 1 Mar 2002 10:38:44 -0000 1.27 --- pwdmodule.c 3 Mar 2002 02:59:16 -0000 1.28 *************** *** 129,134 **** --- 129,138 ---- if ((d = PyList_New(0)) == NULL) return NULL; + #if defined(PYOS_OS2) && defined(PYCC_GCC) + if ((p = getpwuid(0)) != NULL) { + #else setpwent(); while ((p = getpwent()) != NULL) { + #endif PyObject *v = mkpwent(p); if (v == NULL || PyList_Append(d, v) != 0) { Index: readline.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/readline.c,v retrieving revision 2.43 retrieving revision 2.44 diff -C2 -d -r2.43 -r2.44 *** readline.c 13 Feb 2002 11:58:25 -0000 2.43 --- readline.c 3 Mar 2002 02:59:16 -0000 2.44 *************** *** 508,511 **** --- 508,515 ---- { rl_readline_name = "python"; + #if defined(PYOS_OS2) && defined(PYCC_GCC) + /* Allow $if term= in .inputrc to work */ + rl_terminal_name = getenv("TERM"); + #endif /* Force rebind of TAB to insert-tab */ rl_bind_key('\t', rl_insert); Index: selectmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/selectmodule.c,v retrieving revision 2.60 retrieving revision 2.61 diff -C2 -d -r2.60 -r2.61 *** selectmodule.c 12 Jan 2002 11:05:08 -0000 2.60 --- selectmodule.c 3 Mar 2002 02:59:16 -0000 2.61 *************** *** 34,38 **** #endif ! #if defined(PYOS_OS2) #include #include --- 34,38 ---- #endif ! #if defined(PYOS_OS2) && !defined(PYCC_GCC) #include #include Index: signalmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/signalmodule.c,v retrieving revision 2.62 retrieving revision 2.63 diff -C2 -d -r2.62 -r2.63 *** signalmodule.c 12 Jan 2002 11:43:25 -0000 2.62 --- signalmodule.c 3 Mar 2002 02:59:16 -0000 2.63 *************** *** 17,21 **** #endif ! #if defined(PYOS_OS2) #define NSIG 12 #include --- 17,21 ---- #endif ! #if defined(PYOS_OS2) && !defined(PYCC_GCC) #define NSIG 12 #include Index: termios.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/termios.c,v retrieving revision 2.33 retrieving revision 2.34 diff -C2 -d -r2.33 -r2.34 *** termios.c 14 Feb 2002 07:08:31 -0000 2.33 --- termios.c 3 Mar 2002 02:59:16 -0000 2.34 *************** *** 385,389 **** --- 385,391 ---- {"OLCUC", OLCUC}, #endif + #ifdef ONLCR {"ONLCR", ONLCR}, + #endif #ifdef OCRNL {"OCRNL", OCRNL}, *************** *** 553,557 **** --- 555,561 ---- {"VLNEXT", VLNEXT}, #endif + #ifdef VEOL2 {"VEOL2", VEOL2}, + #endif Index: timemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/timemodule.c,v retrieving revision 2.122 retrieving revision 2.123 diff -C2 -d -r2.122 -r2.123 *** timemodule.c 13 Feb 2002 05:14:18 -0000 2.122 --- timemodule.c 3 Mar 2002 02:59:16 -0000 2.123 *************** *** 55,58 **** --- 55,64 ---- #endif /* MS_WIN32 && !MS_WIN64 */ + #if defined(PYOS_OS2) + #define INCL_DOS + #define INCL_ERRORS + #include + #endif + #if defined(PYCC_VACPP) #include *************** *** 753,757 **** { /* XXX Should test for MS_WIN32 first! */ ! #if defined(HAVE_SELECT) && !defined(__BEOS__) struct timeval t; double frac; --- 759,763 ---- { /* XXX Should test for MS_WIN32 first! */ ! #if defined(HAVE_SELECT) && !defined(__BEOS__) && !defined(__EMX__) struct timeval t; double frac; Index: unicodedata.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/unicodedata.c,v retrieving revision 2.14 retrieving revision 2.15 diff -C2 -d -r2.14 -r2.15 *** unicodedata.c 30 Nov 2001 07:23:05 -0000 2.14 --- unicodedata.c 3 Mar 2002 02:59:16 -0000 2.15 *************** *** 278,282 **** static int ! _getname(Py_UCS4 code, char* buffer, int buflen) { int offset; --- 278,282 ---- static int ! _Py_getname(Py_UCS4 code, char* buffer, int buflen) { int offset; *************** *** 335,339 **** int i; char buffer[NAME_MAXLEN]; ! if (!_getname(code, buffer, sizeof(buffer))) return 0; for (i = 0; i < namelen; i++) { --- 335,339 ---- int i; char buffer[NAME_MAXLEN]; ! if (!_Py_getname(code, buffer, sizeof(buffer))) return 0; for (i = 0; i < namelen; i++) { *************** *** 385,389 **** { sizeof(_PyUnicode_Name_CAPI), ! _getname, _getcode }; --- 385,389 ---- { sizeof(_PyUnicode_Name_CAPI), ! _Py_getname, _getcode }; *************** *** 408,412 **** } ! if (!_getname((Py_UCS4) *PyUnicode_AS_UNICODE(v), name, sizeof(name))) { if (defobj == NULL) { --- 408,412 ---- } ! if (!_Py_getname((Py_UCS4) *PyUnicode_AS_UNICODE(v), name, sizeof(name))) { if (defobj == NULL) { From aimacintyre@users.sourceforge.net Sun Mar 3 03:03:54 2002 From: aimacintyre@users.sourceforge.net (Andrew I MacIntyre) Date: Sat, 02 Mar 2002 19:03:54 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules socketmodule.c,1.209,1.210 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv1397 Modified Files: socketmodule.c Log Message: OS/2 EMX port changes (Modules part of patch #450267): Modules/ socketmodule.c EMX handles sockets like Posix, rather than use native APIs Index: socketmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/socketmodule.c,v retrieving revision 1.209 retrieving revision 1.210 diff -C2 -d -r1.209 -r1.210 *** socketmodule.c 1 Mar 2002 08:31:07 -0000 1.209 --- socketmodule.c 3 Mar 2002 03:03:52 -0000 1.210 *************** *** 228,232 **** #endif ! #if defined(PYOS_OS2) #define SOCKETCLOSE soclose #define NO_DUP /* Sockets are Not Actual File Handles under OS/2 */ --- 228,232 ---- #endif ! #if defined(PYOS_OS2) && !defined(PYCC_GCC) #define SOCKETCLOSE soclose #define NO_DUP /* Sockets are Not Actual File Handles under OS/2 */ *************** *** 353,357 **** #endif ! #if defined(PYOS_OS2) if (sock_errno() != NO_ERROR) { APIRET rc; --- 353,357 ---- #endif ! #if defined(PYOS_OS2) && !defined(PYCC_GCC) if (sock_errno() != NO_ERROR) { APIRET rc; *************** *** 932,936 **** #ifndef RISCOS #ifndef MS_WINDOWS ! #ifdef PYOS_OS2 block = !block; ioctl(s->sock_fd, FIONBIO, (caddr_t)&block, sizeof(block)); --- 932,936 ---- #ifndef RISCOS #ifndef MS_WINDOWS ! #if defined(PYOS_OS2) && !defined(PYCC_GCC) block = !block; ioctl(s->sock_fd, FIONBIO, (caddr_t)&block, sizeof(block)); *************** *** 1442,1446 **** n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags, #ifndef MS_WINDOWS ! #if defined(PYOS_OS2) (struct sockaddr *)addrbuf, &addrlen #else --- 1442,1446 ---- n = recvfrom(s->sock_fd, PyString_AS_STRING(buf), len, flags, #ifndef MS_WINDOWS ! #if defined(PYOS_OS2) && !defined(PYCC_GCC) (struct sockaddr *)addrbuf, &addrlen #else *************** *** 2634,2637 **** --- 2634,2638 ---- OS2init(void) { + #if !defined(PYCC_GCC) char reason[64]; int rc = sock_init(); *************** *** 2647,2650 **** --- 2648,2655 ---- return 0; /* Indicate Failure */ + #else + /* no need to initialise sockets with GCC/EMX */ + return 1; + #endif } *************** *** 2696,2703 **** return; #else ! #if defined(__TOS_OS2__) if (!OS2init()) return; ! #endif /* __TOS_OS2__ */ #endif /* MS_WINDOWS */ #endif /* RISCOS */ --- 2701,2708 ---- return; #else ! #if defined(PYOS_OS2) if (!OS2init()) return; ! #endif /* PYOS_OS2 */ #endif /* MS_WINDOWS */ #endif /* RISCOS */ From aimacintyre@users.sourceforge.net Sun Mar 3 03:07:10 2002 From: aimacintyre@users.sourceforge.net (Andrew I MacIntyre) Date: Sat, 02 Mar 2002 19:07:10 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.222,2.223 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv1868 Modified Files: posixmodule.c Log Message: OS/2 EMX port changes (Modules part of patch #450267): Modules/ posixmodule.c - use SEP,ALTSEP #defines instead of hard coded path separator chars - use EMX specific variants of chdir2(),getcwd() that support drive letters - OS/2+EMX spawnv(),spawnve() support - EMX specific popen[234]() derived from Win32 popen[234]() code Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.222 retrieving revision 2.223 diff -C2 -d -r2.222 -r2.223 *** posixmodule.c 16 Feb 2002 23:33:23 -0000 2.222 --- posixmodule.c 3 Mar 2002 03:07:07 -0000 2.223 *************** *** 2,11 **** /* POSIX module implementation */ ! /* This file is also used for Windows NT and MS-Win. In that case the module ! actually calls itself 'nt', not 'posix', and a few functions are ! either unimplemented or implemented differently. The source assumes that for Windows NT, the macro 'MS_WIN32' is defined independent of the compiler used. Different compilers define their own feature ! test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */ /* See also ../Dos/dosmodule.c */ --- 2,14 ---- /* POSIX module implementation */ ! /* This file is also used for Windows NT/MS-Win and OS/2. In that case the ! module actually calls itself 'nt' or 'os2', not 'posix', and a few ! functions are either unimplemented or implemented differently. The source assumes that for Windows NT, the macro 'MS_WIN32' is defined independent of the compiler used. Different compilers define their own feature ! test macro, e.g. '__BORLANDC__' or '_MSC_VER'. For OS/2, the compiler ! independent macro PYOS_OS2 should be defined. On OS/2 the default ! compiler is assumed to be IBM's VisualAge C++ (VACPP). PYCC_GCC is used ! as the compiler specific macro for the EMX port of gcc to OS/2. */ /* See also ../Dos/dosmodule.c */ *************** *** 26,29 **** --- 29,39 ---- #define INCL_NOPMAPI #include + #if defined(PYCC_GCC) + #include + #include + #include + #include + #include "osdefs.h" + #endif #endif *************** *** 82,85 **** --- 92,98 ---- #else /* 16-bit Windows */ #endif /* !MS_WIN32 */ + #else + #if defined(PYOS_OS2) && defined(PYCC_GCC) + /* Everything needed is defined in PC/os2emx/pyconfig.h */ #else /* all other compilers */ /* Unix functions that the configure script doesn't check for */ *************** *** 102,105 **** --- 115,119 ---- #define HAVE_WAIT 1 #define HAVE_TTYNAME 1 + #endif /* PYOS_OS2 && PYCC_GCC */ #endif /* _MSC_VER */ #endif /* __BORLANDC__ */ *************** *** 802,806 **** --- 816,824 ---- posix_chdir(PyObject *self, PyObject *args) { + #if defined(PYOS_OS2) && defined(PYCC_GCC) + return posix_1str(args, "et:chdir", _chdir2); + #else return posix_1str(args, "et:chdir", chdir); + #endif } *************** *** 913,917 **** --- 931,939 ---- return NULL; Py_BEGIN_ALLOW_THREADS + #if defined(PYOS_OS2) && defined(PYCC_GCC) + res = _getcwd2(buf, sizeof buf); + #else res = getcwd(buf, sizeof buf); + #endif Py_END_ALLOW_THREADS if (res == NULL) *************** *** 964,968 **** return NULL; ch = namebuf[len-1]; ! if (ch != '/' && ch != '\\' && ch != ':') namebuf[len++] = '/'; strcpy(namebuf + len, "*.*"); --- 986,990 ---- return NULL; ch = namebuf[len-1]; ! if (ch != SEP && ch != ALTSEP && ch != ':') namebuf[len++] = '/'; strcpy(namebuf + len, "*.*"); *************** *** 1023,1030 **** strcpy(namebuf, name); for (pt = namebuf; *pt; pt++) ! if (*pt == '/') ! *pt = '\\'; ! if (namebuf[len-1] != '\\') ! namebuf[len++] = '\\'; strcpy(namebuf + len, "*.*"); --- 1045,1052 ---- strcpy(namebuf, name); for (pt = namebuf; *pt; pt++) ! if (*pt == ALTSEP) ! *pt = SEP; ! if (namebuf[len-1] != SEP) ! namebuf[len++] = SEP; strcpy(namebuf + len, "*.*"); *************** *** 1087,1094 **** strcpy(namebuf, name); for (pt = namebuf; *pt; pt++) ! if (*pt == '/') ! *pt = '\\'; ! if (namebuf[len-1] != '\\') ! namebuf[len++] = '\\'; strcpy(namebuf + len, "*.*"); --- 1109,1116 ---- strcpy(namebuf, name); for (pt = namebuf; *pt; pt++) ! if (*pt == ALTSEP) ! *pt = SEP; ! if (namebuf[len-1] != SEP) ! namebuf[len++] = SEP; strcpy(namebuf + len, "*.*"); *************** *** 1111,1115 **** do { if (ep.achName[0] == '.' ! && (ep.achName[1] == '\0' || ep.achName[1] == '.' && ep.achName[2] == '\0')) continue; /* Skip Over "." and ".." Names */ --- 1133,1137 ---- do { if (ep.achName[0] == '.' ! && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0'))) continue; /* Skip Over "." and ".." Names */ *************** *** 1705,1708 **** --- 1727,1735 ---- argvlist[argc] = NULL; + #if defined(PYOS_OS2) && defined(PYCC_GCC) + Py_BEGIN_ALLOW_THREADS + spawnval = spawnv(mode, path, argvlist); + Py_END_ALLOW_THREADS + #else if (mode == _OLD_P_OVERLAY) mode = _P_OVERLAY; *************** *** 1711,1714 **** --- 1738,1742 ---- spawnval = _spawnv(mode, path, argvlist); Py_END_ALLOW_THREADS + #endif PyMem_DEL(argvlist); *************** *** 1821,1824 **** --- 1849,1857 ---- envlist[envc] = 0; + #if defined(PYOS_OS2) && defined(PYCC_GCC) + Py_BEGIN_ALLOW_THREADS + spawnval = spawnve(mode, path, argvlist, envlist); + Py_END_ALLOW_THREADS + #else if (mode == _OLD_P_OVERLAY) mode = _P_OVERLAY; *************** *** 1827,1830 **** --- 1860,1864 ---- spawnval = _spawnve(mode, path, argvlist, envlist); Py_END_ALLOW_THREADS + #endif if (spawnval == -1) *************** *** 2178,2182 **** if (!PyArg_ParseTuple(args, "ii:kill", &pid, &sig)) return NULL; ! #if defined(PYOS_OS2) if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) { APIRET rc; --- 2212,2216 ---- if (!PyArg_ParseTuple(args, "ii:kill", &pid, &sig)) return NULL; ! #if defined(PYOS_OS2) && !defined(PYCC_GCC) if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) { APIRET rc; *************** *** 2248,2251 **** --- 2282,2286 ---- #if defined(PYOS_OS2) + #if defined(PYCC_VACPP) static int async_system(const char *command) *************** *** 2355,2358 **** --- 2390,3014 ---- } + #elif defined(PYCC_GCC) + + /* standard posix version of popen() support */ + static PyObject * + posix_popen(PyObject *self, PyObject *args) + { + char *name; + char *mode = "r"; + int bufsize = -1; + FILE *fp; + PyObject *f; + if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize)) + return NULL; + Py_BEGIN_ALLOW_THREADS + fp = popen(name, mode); + Py_END_ALLOW_THREADS + if (fp == NULL) + return posix_error(); + f = PyFile_FromFile(fp, name, mode, pclose); + if (f != NULL) + PyFile_SetBufSize(f, bufsize); + return f; + } + + /* fork() under OS/2 has lots'o'warts + * EMX supports pipe() and spawn*() so we can synthesize popen[234]() + * most of this code is a ripoff of the win32 code, but using the + * capabilities of EMX's C library routines + */ + + /* These tell _PyPopen() whether to return 1, 2, or 3 file objects. */ + #define POPEN_1 1 + #define POPEN_2 2 + #define POPEN_3 3 + #define POPEN_4 4 + + static PyObject *_PyPopen(char *, int, int, int); + static int _PyPclose(FILE *file); + + /* + * Internal dictionary mapping popen* file pointers to process handles, + * for use when retrieving the process exit code. See _PyPclose() below + * for more information on this dictionary's use. + */ + static PyObject *_PyPopenProcs = NULL; + + /* os2emx version of popen2() + * + * The result of this function is a pipe (file) connected to the + * process's stdin, and a pipe connected to the process's stdout. + */ + + static PyObject * + os2emx_popen2(PyObject *self, PyObject *args) + { + PyObject *f; + int tm=0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'"); + return NULL; + } else + tm = O_BINARY; + + f = _PyPopen(cmdstring, tm, POPEN_2, bufsize); + + return f; + } + + /* + * Variation on os2emx.popen2 + * + * The result of this function is 3 pipes - the process's stdin, + * stdout and stderr + */ + + static PyObject * + os2emx_popen3(PyObject *self, PyObject *args) + { + PyObject *f; + int tm = 0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen3", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'"); + return NULL; + } else + tm = O_BINARY; + + f = _PyPopen(cmdstring, tm, POPEN_3, bufsize); + + return f; + } + + /* + * Variation on os2emx.popen2 + * + * The result of this function is 2 pipes - the processes stdin, + * and stdout+stderr combined as a single pipe. + */ + + static PyObject * + os2emx_popen4(PyObject *self, PyObject *args) + { + PyObject *f; + int tm = 0; + + char *cmdstring; + char *mode = "t"; + int bufsize = -1; + if (!PyArg_ParseTuple(args, "s|si:popen4", &cmdstring, &mode, &bufsize)) + return NULL; + + if (*mode == 't') + tm = O_TEXT; + else if (*mode != 'b') { + PyErr_SetString(PyExc_ValueError, "mode must be 't' or 'b'"); + return NULL; + } else + tm = O_BINARY; + + f = _PyPopen(cmdstring, tm, POPEN_4, bufsize); + + return f; + } + + /* a couple of structures for convenient handling of multiple + * file handles and pipes + */ + struct file_ref + { + int handle; + int flags; + }; + + struct pipe_ref + { + int rd; + int wr; + }; + + /* The following code is derived from the win32 code */ + + static PyObject * + _PyPopen(char *cmdstring, int mode, int n, int bufsize) + { + struct file_ref stdio[3]; + struct pipe_ref p_fd[3]; + FILE *p_s[3]; + int file_count, i, pipe_err, pipe_pid; + char *shell, *sh_name, *opt, *rd_mode, *wr_mode; + PyObject *f, *p_f[3]; + + /* file modes for subsequent fdopen's on pipe handles */ + if (mode == O_TEXT) + { + rd_mode = "rt"; + wr_mode = "wt"; + } + else + { + rd_mode = "rb"; + wr_mode = "wb"; + } + + /* prepare shell references */ + if ((shell = getenv("EMXSHELL")) == NULL) + if ((shell = getenv("COMSPEC")) == NULL) + { + errno = ENOENT; + return posix_error(); + } + + sh_name = _getname(shell); + if (stricmp(sh_name, "cmd.exe") == 0 || stricmp(sh_name, "4os2.exe") == 0) + opt = "/c"; + else + opt = "-c"; + + /* save current stdio fds + their flags, and set not inheritable */ + i = pipe_err = 0; + while (pipe_err >= 0 && i < 3) + { + pipe_err = stdio[i].handle = dup(i); + stdio[i].flags = fcntl(i, F_GETFD, 0); + fcntl(stdio[i].handle, F_SETFD, stdio[i].flags | FD_CLOEXEC); + i++; + } + if (pipe_err < 0) + { + /* didn't get them all saved - clean up and bail out */ + int saved_err = errno; + while (i-- > 0) + { + close(stdio[i].handle); + } + errno = saved_err; + return posix_error(); + } + + /* create pipe ends */ + file_count = 2; + if (n == POPEN_3) + file_count = 3; + i = pipe_err = 0; + while ((pipe_err == 0) && (i < file_count)) + pipe_err = pipe((int *)&p_fd[i++]); + if (pipe_err < 0) + { + /* didn't get them all made - clean up and bail out */ + while (i-- > 0) + { + close(p_fd[i].wr); + close(p_fd[i].rd); + } + errno = EPIPE; + return posix_error(); + } + + /* change the actual standard IO streams over temporarily, + * making the retained pipe ends non-inheritable + */ + pipe_err = 0; + + /* - stdin */ + if (dup2(p_fd[0].rd, 0) == 0) + { + close(p_fd[0].rd); + i = fcntl(p_fd[0].wr, F_GETFD, 0); + fcntl(p_fd[0].wr, F_SETFD, i | FD_CLOEXEC); + if ((p_s[0] = fdopen(p_fd[0].wr, wr_mode)) == NULL) + { + close(p_fd[0].wr); + pipe_err = -1; + } + } + else + { + pipe_err = -1; + } + + /* - stdout */ + if (pipe_err == 0) + { + if (dup2(p_fd[1].wr, 1) == 1) + { + close(p_fd[1].wr); + i = fcntl(p_fd[1].rd, F_GETFD, 0); + fcntl(p_fd[1].rd, F_SETFD, i | FD_CLOEXEC); + if ((p_s[1] = fdopen(p_fd[1].rd, rd_mode)) == NULL) + { + close(p_fd[1].rd); + pipe_err = -1; + } + } + else + { + pipe_err = -1; + } + } + + /* - stderr, as required */ + if (pipe_err == 0) + switch (n) + { + case POPEN_3: + { + if (dup2(p_fd[2].wr, 2) == 2) + { + close(p_fd[2].wr); + i = fcntl(p_fd[2].rd, F_GETFD, 0); + fcntl(p_fd[2].rd, F_SETFD, i | FD_CLOEXEC); + if ((p_s[2] = fdopen(p_fd[2].rd, rd_mode)) == NULL) + { + close(p_fd[2].rd); + pipe_err = -1; + } + } + else + { + pipe_err = -1; + } + break; + } + + case POPEN_4: + { + if (dup2(1, 2) != 2) + { + pipe_err = -1; + } + break; + } + } + + /* spawn the child process */ + if (pipe_err == 0) + { + pipe_pid = spawnlp(P_NOWAIT, shell, shell, opt, cmdstring, (char *)0); + if (pipe_pid == -1) + { + pipe_err = -1; + } + else + { + /* save the PID into the FILE structure + * NOTE: this implementation doesn't actually + * take advantage of this, but do it for + * completeness - AIM Apr01 + */ + for (i = 0; i < file_count; i++) + p_s[i]->_pid = pipe_pid; + } + } + + /* reset standard IO to normal */ + for (i = 0; i < 3; i++) + { + dup2(stdio[i].handle, i); + fcntl(i, F_SETFD, stdio[i].flags); + close(stdio[i].handle); + } + + /* if any remnant problems, clean up and bail out */ + if (pipe_err < 0) + { + for (i = 0; i < 3; i++) + { + close(p_fd[i].rd); + close(p_fd[i].wr); + } + errno = EPIPE; + return posix_error_with_filename(cmdstring); + } + + /* build tuple of file objects to return */ + if ((p_f[0] = PyFile_FromFile(p_s[0], cmdstring, wr_mode, _PyPclose)) != NULL) + PyFile_SetBufSize(p_f[0], bufsize); + if ((p_f[1] = PyFile_FromFile(p_s[1], cmdstring, rd_mode, _PyPclose)) != NULL) + PyFile_SetBufSize(p_f[1], bufsize); + if (n == POPEN_3) + { + if ((p_f[2] = PyFile_FromFile(p_s[2], cmdstring, rd_mode, _PyPclose)) != NULL) + PyFile_SetBufSize(p_f[0], bufsize); + f = Py_BuildValue("OOO", p_f[0], p_f[1], p_f[2]); + } + else + f = Py_BuildValue("OO", p_f[0], p_f[1]); + + /* + * Insert the files we've created into the process dictionary + * all referencing the list with the process handle and the + * initial number of files (see description below in _PyPclose). + * Since if _PyPclose later tried to wait on a process when all + * handles weren't closed, it could create a deadlock with the + * child, we spend some energy here to try to ensure that we + * either insert all file handles into the dictionary or none + * at all. It's a little clumsy with the various popen modes + * and variable number of files involved. + */ + if (!_PyPopenProcs) + { + _PyPopenProcs = PyDict_New(); + } + + if (_PyPopenProcs) + { + PyObject *procObj, *pidObj, *intObj, *fileObj[3]; + int ins_rc[3]; + + fileObj[0] = fileObj[1] = fileObj[2] = NULL; + ins_rc[0] = ins_rc[1] = ins_rc[2] = 0; + + procObj = PyList_New(2); + pidObj = PyInt_FromLong((long) pipe_pid); + intObj = PyInt_FromLong((long) file_count); + + if (procObj && pidObj && intObj) + { + PyList_SetItem(procObj, 0, pidObj); + PyList_SetItem(procObj, 1, intObj); + + fileObj[0] = PyLong_FromVoidPtr(p_s[0]); + if (fileObj[0]) + { + ins_rc[0] = PyDict_SetItem(_PyPopenProcs, + fileObj[0], + procObj); + } + fileObj[1] = PyLong_FromVoidPtr(p_s[1]); + if (fileObj[1]) + { + ins_rc[1] = PyDict_SetItem(_PyPopenProcs, + fileObj[1], + procObj); + } + if (file_count >= 3) + { + fileObj[2] = PyLong_FromVoidPtr(p_s[2]); + if (fileObj[2]) + { + ins_rc[2] = PyDict_SetItem(_PyPopenProcs, + fileObj[2], + procObj); + } + } + + if (ins_rc[0] < 0 || !fileObj[0] || + ins_rc[1] < 0 || (file_count > 1 && !fileObj[1]) || + ins_rc[2] < 0 || (file_count > 2 && !fileObj[2])) + { + /* Something failed - remove any dictionary + * entries that did make it. + */ + if (!ins_rc[0] && fileObj[0]) + { + PyDict_DelItem(_PyPopenProcs, + fileObj[0]); + } + if (!ins_rc[1] && fileObj[1]) + { + PyDict_DelItem(_PyPopenProcs, + fileObj[1]); + } + if (!ins_rc[2] && fileObj[2]) + { + PyDict_DelItem(_PyPopenProcs, + fileObj[2]); + } + } + } + + /* + * Clean up our localized references for the dictionary keys + * and value since PyDict_SetItem will Py_INCREF any copies + * that got placed in the dictionary. + */ + Py_XDECREF(procObj); + Py_XDECREF(fileObj[0]); + Py_XDECREF(fileObj[1]); + Py_XDECREF(fileObj[2]); + } + + /* Child is launched. */ + return f; + } + + /* + * Wrapper for fclose() to use for popen* files, so we can retrieve the + * exit code for the child process and return as a result of the close. + * + * This function uses the _PyPopenProcs dictionary in order to map the + * input file pointer to information about the process that was + * originally created by the popen* call that created the file pointer. + * The dictionary uses the file pointer as a key (with one entry + * inserted for each file returned by the original popen* call) and a + * single list object as the value for all files from a single call. + * The list object contains the Win32 process handle at [0], and a file + * count at [1], which is initialized to the total number of file + * handles using that list. + * + * This function closes whichever handle it is passed, and decrements + * the file count in the dictionary for the process handle pointed to + * by this file. On the last close (when the file count reaches zero), + * this function will wait for the child process and then return its + * exit code as the result of the close() operation. This permits the + * files to be closed in any order - it is always the close() of the + * final handle that will return the exit code. + */ + + /* RED_FLAG 31-Aug-2000 Tim + * This is always called (today!) between a pair of + * Py_BEGIN_ALLOW_THREADS/ Py_END_ALLOW_THREADS + * macros. So the thread running this has no valid thread state, as + * far as Python is concerned. However, this calls some Python API + * functions that cannot be called safely without a valid thread + * state, in particular PyDict_GetItem. + * As a temporary hack (although it may last for years ...), we + * *rely* on not having a valid thread state in this function, in + * order to create our own "from scratch". + * This will deadlock if _PyPclose is ever called by a thread + * holding the global lock. + * (The OS/2 EMX thread support appears to cover the case where the + * lock is already held - AIM Apr01) + */ + + static int _PyPclose(FILE *file) + { + int result; + int exit_code; + int pipe_pid; + PyObject *procObj, *pidObj, *intObj, *fileObj; + int file_count; + #ifdef WITH_THREAD + PyInterpreterState* pInterpreterState; + PyThreadState* pThreadState; + #endif + + /* Close the file handle first, to ensure it can't block the + * child from exiting if it's the last handle. + */ + result = fclose(file); + + #ifdef WITH_THREAD + /* Bootstrap a valid thread state into existence. */ + pInterpreterState = PyInterpreterState_New(); + if (!pInterpreterState) { + /* Well, we're hosed now! We don't have a thread + * state, so can't call a nice error routine, or raise + * an exception. Just die. + */ + Py_FatalError("unable to allocate interpreter state " + "when closing popen object."); + return -1; /* unreachable */ + } + pThreadState = PyThreadState_New(pInterpreterState); + if (!pThreadState) { + Py_FatalError("unable to allocate thread state " + "when closing popen object."); + return -1; /* unreachable */ + } + /* Grab the global lock. Note that this will deadlock if the + * current thread already has the lock! (see RED_FLAG comments + * before this function) + */ + PyEval_RestoreThread(pThreadState); + #endif + + if (_PyPopenProcs) + { + if ((fileObj = PyLong_FromVoidPtr(file)) != NULL && + (procObj = PyDict_GetItem(_PyPopenProcs, + fileObj)) != NULL && + (pidObj = PyList_GetItem(procObj,0)) != NULL && + (intObj = PyList_GetItem(procObj,1)) != NULL) + { + pipe_pid = (int) PyInt_AsLong(pidObj); + file_count = (int) PyInt_AsLong(intObj); + + if (file_count > 1) + { + /* Still other files referencing process */ + file_count--; + PyList_SetItem(procObj,1, + PyInt_FromLong((long) file_count)); + } + else + { + /* Last file for this process */ + if (result != EOF && + waitpid(pipe_pid, &exit_code, 0) == pipe_pid) + { + /* extract exit status */ + if (WIFEXITED(exit_code)) + { + result = WEXITSTATUS(exit_code); + } + else + { + errno = EPIPE; + result = -1; + } + } + else + { + /* Indicate failure - this will cause the file object + * to raise an I/O error and translate the last + * error code from errno. We do have a problem with + * last errors that overlap the normal errno table, + * but that's a consistent problem with the file object. + */ + result = -1; + } + } + + /* Remove this file pointer from dictionary */ + PyDict_DelItem(_PyPopenProcs, fileObj); + + if (PyDict_Size(_PyPopenProcs) == 0) + { + Py_DECREF(_PyPopenProcs); + _PyPopenProcs = NULL; + } + + } /* if object retrieval ok */ + + Py_XDECREF(fileObj); + } /* if _PyPopenProcs */ + + #ifdef WITH_THREAD + /* Tear down the thread & interpreter states. + * Note that interpreter state clear & delete functions automatically + * call the thread clear & delete functions, and indeed insist on + * doing that themselves. The lock must be held during the clear, but + * need not be held during the delete. + */ + PyInterpreterState_Clear(pInterpreterState); + PyEval_ReleaseThread(pThreadState); + PyInterpreterState_Delete(pInterpreterState); + #endif + + return result; + } + + #endif /* PYCC_??? */ + #elif defined(MS_WIN32) *************** *** 2585,2589 **** GetModuleFileName(NULL, modulepath, sizeof(modulepath)); for (i = x = 0; modulepath[i]; i++) ! if (modulepath[i] == '\\') x = i+1; modulepath[x] = '\0'; --- 3241,3245 ---- GetModuleFileName(NULL, modulepath, sizeof(modulepath)); for (i = x = 0; modulepath[i]; i++) ! if (modulepath[i] == SEP) x = i+1; modulepath[x] = '\0'; *************** *** 3149,3154 **** return f; } - #endif #endif /* HAVE_POPEN */ --- 3805,3810 ---- return f; } + #endif /* PYOS_??? */ #endif /* HAVE_POPEN */ *************** *** 5605,5608 **** --- 6261,6270 ---- {"popen4", win32_popen4, METH_VARARGS}, {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__}, + #else + #if defined(PYOS_OS2) && defined(PYCC_GCC) + {"popen2", os2emx_popen2, METH_VARARGS}, + {"popen3", os2emx_popen3, METH_VARARGS}, + {"popen4", os2emx_popen4, METH_VARARGS}, + #endif #endif #endif /* HAVE_POPEN */ *************** *** 5920,5923 **** --- 6582,6607 ---- #ifdef HAVE_SPAWNV + #if defined(PYOS_OS2) && defined(PYCC_GCC) + if (ins(d, "P_WAIT", (long)P_WAIT)) return -1; + if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1; + if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1; + if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1; + if (ins(d, "P_SESSION", (long)P_SESSION)) return -1; + if (ins(d, "P_DETACH", (long)P_DETACH)) return -1; + if (ins(d, "P_PM", (long)P_PM)) return -1; + if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1; + if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1; + if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1; + if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1; + if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1; + if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1; + if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1; + if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1; + if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1; + if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1; + if (ins(d, "P_TILDE", (long)P_TILDE)) return -1; + if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1; + if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1; + #else if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1; if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1; *************** *** 5925,5928 **** --- 6609,6613 ---- if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1; if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1; + #endif #endif From aimacintyre@users.sourceforge.net Sun Mar 3 03:12:33 2002 From: aimacintyre@users.sourceforge.net (Andrew I MacIntyre) Date: Sat, 02 Mar 2002 19:12:33 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib pydoc.py,1.56,1.57 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv2835 Modified Files: pydoc.py Log Message: OS/2 more program behaves like Win32 more (see patch #514490, by Stefan Schwarzer) Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.56 retrieving revision 1.57 diff -C2 -d -r1.56 -r1.57 *** pydoc.py 31 Oct 2001 04:20:26 -0000 1.56 --- pydoc.py 3 Mar 2002 03:12:30 -0000 1.57 *************** *** 1185,1189 **** else: return lambda text: pipepager(text, os.environ['PAGER']) ! if sys.platform == 'win32': return lambda text: tempfilepager(plain(text), 'more <') if hasattr(os, 'system') and os.system('less 2>/dev/null') == 0: --- 1185,1189 ---- else: return lambda text: pipepager(text, os.environ['PAGER']) ! if sys.platform == 'win32' or sys.platform.startswith('os2'): return lambda text: tempfilepager(plain(text), 'more <') if hasattr(os, 'system') and os.system('less 2>/dev/null') == 0: From gvanrossum@users.sourceforge.net Sun Mar 3 03:21:47 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 02 Mar 2002 19:21:47 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.17,1.18 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv4386 Modified Files: datetime.py Log Message: Add some XXX comments about brokenness relating to ctime(). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** datetime.py 3 Mar 2002 02:50:52 -0000 1.17 --- datetime.py 3 Mar 2002 03:21:45 -0000 1.18 *************** *** 380,383 **** --- 380,384 ---- h, m = divmod(-self.__tzoffset, 60) h = -h + # XXX This is broken! ctime() renormalizes to local time. :-( return self.ctime() + " %+03d:%02d" % (h, m) *************** *** 487,490 **** --- 488,500 ---- # Formatting methods + + # XXX These shouldn't depend on time.localtime(), because that + # clips the usable dates to [1970 .. 2038). At least ctime() is + # easily done without using strftime() -- that's better too because + # strftime("%c", ...) is locale specific. + + # XXX An additional question is whether ctime() should renormalize + # to local time, or display the time as entered (which may be + # confusing since it doesn't show the timezone). def ctime(self): From tim.one@comcast.net Sun Mar 3 03:35:39 2002 From: tim.one@comcast.net (Tim Peters) Date: Sat, 02 Mar 2002 22:35:39 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.16,1.17 test_datetime.py,1.11,1.12 In-Reply-To: Message-ID: > def weekday(self): > "Return day of the week, where Monday == 0 (according to ISO)." > # The constant 6 was obtained experimentally :-) > return (_ymd2ord(self.__year, self.__month, self.__day) + 6) % 7 I'm not sure why we're mucking with the ISO calendar too, but if we want to then I believe this function is incorrect. According to ISO 8601 http://www.pvv.org/~nsaa/8601v2000.pdf section 4.3.2.2 says ISO day ordinals are from 1 (Monday) through 7 (Sunday). "Day 1" in the proleptic Gregorian system is a Monday, so return self.toordinal() % 7 or 7 implements the ISO rule. > def isocalendar(self): > """Return a 3-tuple containing ISO year, week number, > and weekday. Why <0.7 wink>? From tim_one@users.sourceforge.net Sun Mar 3 03:58:14 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 19:58:14 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.18,1.19 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv10966 Modified Files: datetime.py Log Message: toordinal(): Made more efficient by referencing fields directly instead of going thru the properties. weekday(): Recorded disagreement in a XXX block. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** datetime.py 3 Mar 2002 03:21:45 -0000 1.18 --- datetime.py 3 Mar 2002 03:58:12 -0000 1.19 *************** *** 424,428 **** contribute to the result. """ ! return _ymd2ord(self.year, self.month, self.day) def __cmp__(self, other): --- 424,428 ---- contribute to the result. """ ! return _ymd2ord(self.__year, self.__month, self.__day) def __cmp__(self, other): *************** *** 560,563 **** --- 560,567 ---- "Return day of the week, where Monday == 0 (according to ISO)." # The constant 6 was obtained experimentally :-) + # XXX I (tim) believe this is incorrect: ISO defines day ordinals + # XXX as ranging from 1 (Monday) through 7 (Sunday). The next line + # XXX (commented out) implements that: + # return self.toordinal() % 7 or 7 return (_ymd2ord(self.__year, self.__month, self.__day) + 6) % 7 From tim_one@users.sourceforge.net Sun Mar 3 03:59:39 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 19:59:39 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.19,1.20 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv11462 Modified Files: datetime.py Log Message: Simplified a comment. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** datetime.py 3 Mar 2002 03:58:12 -0000 1.19 --- datetime.py 3 Mar 2002 03:59:37 -0000 1.20 *************** *** 18,23 **** # and Reingold's "Calendrical Calculations", where it's the base calendar # for all computations. See the book for algorithms for converting between ! # day ordinals in the proleptic Gregorian calendar and many other calendar ! # systems. _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] --- 18,22 ---- # and Reingold's "Calendrical Calculations", where it's the base calendar # for all computations. See the book for algorithms for converting between ! # proleptic Gregorian ordinals and many other calendar systems. _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] From tim_one@users.sourceforge.net Sun Mar 3 04:03:24 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 20:03:24 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.20,1.21 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv12420 Modified Files: datetime.py Log Message: Bug alert for timedelta.__div__. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** datetime.py 3 Mar 2002 03:59:37 -0000 1.20 --- datetime.py 3 Mar 2002 04:03:22 -0000 1.21 *************** *** 217,220 **** --- 217,222 ---- def __div__(self, other): if isinstance(other, (int, long)): + # XXX If, e.g., this is a delta of 1 day, dividing by 2 and + # XXX getting back 0 is pretty surprising. return timedelta(self.__days // other, self.__seconds // other, From tim_one@users.sourceforge.net Sun Mar 3 06:11:56 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 02 Mar 2002 22:11:56 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.21,1.22 test_datetime.py,1.12,1.13 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv5735 Modified Files: datetime.py test_datetime.py Log Message: Get a start on a struct tm kinda-workalike that does principled, x-platform normalization; doesn't have year 1970-2038 restrictions; and can construct Unixish timestamps (floating seconds since 1970) for years before 1970 too. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** datetime.py 3 Mar 2002 04:03:22 -0000 1.21 --- datetime.py 3 Mar 2002 06:11:54 -0000 1.22 *************** *** 92,95 **** --- 92,151 ---- return year, month, n-dbm + # This is a start at a struct tm workalike. Goals: + # + # + Works the same way across platforms. + # + Handles all the fields datetime needs handled, without 1970-2038 glitches. + # + # Note: I suspect it's best if this flavor of tm does *not* try to + # second-guess timezones or DST. Instead fold whatever adjustments you want + # into the minutes argument (and the constructor will normalize). + + _ORD1970 = _ymd2ord(1970, 1, 1) # base ordinal for UNIX epoch + + class tmxxx: + + ordinal = None + + def __init__(self, year, month, day, hour=0, minute=0, second=0, + microsecond=0): + # Normalize all the inputs, and store the normalized values. + carry, microsecond = divmod(microsecond, 1000000) + second += carry + carry, second = divmod(second, 60) + minute += carry + carry, minute = divmod(minute, 60) + hour += carry + carry, hour = divmod(hour, 24) + day += carry + # That was easy. Now it gets muddy: the proper range for day + # can't be determined without knowing the correct month and year, + # but if day is, e.g., plus or minus a million, the current month + # and year values make no sense (and may also be out of bounds + # themselves). + # Saying 12 months == 1 year should be non-controversial. + carry, month = divmod(month-1, 12) + year += carry + month += 1 + assert 1 <= month <= 12 + # Now only day can be out of bounds. If it is, what to do is arguable, + # but at least the method here is principled and explainable. + if not 1 <= day <= _days_in_month(month, year): + # Note that the "if" test is for efficiency, not correctness: + # there's simply no need to do this dance if day is already in + # range, and it's an expensive dance. + self.ordinal = _ymd2ord(year, month, 1) + (day - 1) + year, month, day = _ord2ymd(self.ordinal) + self.year, self.month, self.day = year, month, day + self.hour, self.minute, self.second = hour, minute, second + self.microsecond = microsecond + + def time(self): + "Return Unixish timestamp, as a float." + if self.ordinal is None: + self.ordinal = _ymd2ord(self.year, self.month, self.day) + days = self.ordinal - _ORD1970 # convert to UNIX epoch + seconds = ((days * 24. + self.hour)*60. + self.minute)*60. + return seconds + self.second + self.microsecond / 1e6 + class basetime(object): """Abstract date/time type. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** test_datetime.py 3 Mar 2002 02:50:52 -0000 1.12 --- test_datetime.py 3 Mar 2002 06:11:54 -0000 1.13 *************** *** 222,247 **** # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm ISO_LONG_YEARS_TABLE = """ ! 4 32 60 88 ! 9 37 65 93 ! 15 43 71 99 ! 20 48 76 26 54 82 ! 105 133 161 189 ! 111 139 167 195 ! 116 144 172 ! 122 150 178 128 156 184 ! 201 229 257 285 ! 207 235 263 291 ! 212 240 268 296 ! 218 246 274 224 252 280 ! 303 331 359 387 ! 308 336 364 392 ! 314 342 370 398 ! 320 348 376 325 353 381 """ --- 222,247 ---- # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm ISO_LONG_YEARS_TABLE = """ ! 4 32 60 88 ! 9 37 65 93 ! 15 43 71 99 ! 20 48 76 26 54 82 ! 105 133 161 189 ! 111 139 167 195 ! 116 144 172 ! 122 150 178 128 156 184 ! 201 229 257 285 ! 207 235 263 291 ! 212 240 268 296 ! 218 246 274 224 252 280 ! 303 331 359 387 ! 308 336 364 392 ! 314 342 370 398 ! 320 348 376 325 353 381 """ *************** *** 257,260 **** --- 257,273 ---- self.assertEqual(L, iso_long_years) + def test_tmxxx(self): + from datetime import tmxxx + for timestamp in 123456789.0, 987654321.0: + dt = datetime.utcfromtimestamp(timestamp) + # Mange the fields, but in such a way that normalization should + # restore them to dt's values. + tm = tmxxx(dt.year - 1, dt.month + 12, dt.day + 100, + dt.hour - 24*100, dt.minute - 3, dt.second + 12, + (3*60 - 12) * 1000000) + dt2 = datetime.new(tm.year, tm.month, tm.day, tm.hour, tm.minute, + tm.second, tm.microsecond, tzoffset=0) + self.assertEqual(dt, dt2) + self.assertEqual(timestamp, tm.time()) def test_suite(): From nnorwitz@users.sourceforge.net Sun Mar 3 15:11:19 2002 From: nnorwitz@users.sourceforge.net (Neal Norwitz) Date: Sun, 03 Mar 2002 07:11:19 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python sysmodule.c,2.100,2.101 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv6411/Python Modified Files: sysmodule.c Log Message: SF #506611, fix sys.setprofile(), sys.settrace() core dumps when no arguments are passed Index: sysmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/sysmodule.c,v retrieving revision 2.100 retrieving revision 2.101 diff -C2 -d -r2.100 -r2.101 *** sysmodule.c 29 Jan 2002 00:53:41 -0000 2.100 --- sysmodule.c 3 Mar 2002 15:11:17 -0000 2.101 *************** *** 565,572 **** setdlopenflags_doc}, #endif ! {"setprofile", sys_setprofile, METH_OLDARGS, setprofile_doc}, {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, setrecursionlimit_doc}, ! {"settrace", sys_settrace, METH_OLDARGS, settrace_doc}, {NULL, NULL} /* sentinel */ }; --- 565,572 ---- setdlopenflags_doc}, #endif ! {"setprofile", sys_setprofile, METH_O, setprofile_doc}, {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, setrecursionlimit_doc}, ! {"settrace", sys_settrace, METH_O, settrace_doc}, {NULL, NULL} /* sentinel */ }; From nnorwitz@users.sourceforge.net Sun Mar 3 15:11:20 2002 From: nnorwitz@users.sourceforge.net (Neal Norwitz) Date: Sun, 03 Mar 2002 07:11:20 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_profilehooks.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv6411/Lib/test Modified Files: test_profilehooks.py Log Message: SF #506611, fix sys.setprofile(), sys.settrace() core dumps when no arguments are passed Index: test_profilehooks.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_profilehooks.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** test_profilehooks.py 4 Oct 2001 14:49:46 -0000 1.6 --- test_profilehooks.py 3 Mar 2002 15:11:17 -0000 1.7 *************** *** 1,4 **** --- 1,6 ---- from __future__ import generators + from test_support import TestFailed + import pprint import sys *************** *** 330,333 **** --- 332,339 ---- def capture_events(callable, p=None): + try: sys.setprofile() + except TypeError: pass + else: raise TestFailed, 'sys.setprofile() did not raise TypeError' + if p is None: p = HookWatcher() From nnorwitz@users.sourceforge.net Sun Mar 3 15:13:00 2002 From: nnorwitz@users.sourceforge.net (Neal Norwitz) Date: Sun, 03 Mar 2002 07:13:00 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_scope.py,1.24,1.25 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv7127/Lib/test Modified Files: test_scope.py Log Message: SF #506611, fix sys.setprofile(), sys.settrace() core dumps when no arguments are passed Index: test_scope.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_scope.py,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** test_scope.py 15 Dec 2001 18:04:10 -0000 1.24 --- test_scope.py 3 Mar 2002 15:12:58 -0000 1.25 *************** *** 472,475 **** --- 472,479 ---- sys.settrace(None) + try: sys.settrace() + except TypeError: pass + else: raise TestFailed, 'sys.settrace() did not raise TypeError' + print "20. eval and exec with free variables" From nnorwitz@users.sourceforge.net Sun Mar 3 15:17:09 2002 From: nnorwitz@users.sourceforge.net (Neal Norwitz) Date: Sun, 03 Mar 2002 07:17:09 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_profilehooks.py,1.6,1.6.10.1 test_scope.py,1.24,1.24.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv8134/Lib/test Modified Files: Tag: release22-maint test_profilehooks.py test_scope.py Log Message: SF #506611, fix sys.setprofile(), sys.settrace() core dumps when no arguments are passed Index: test_profilehooks.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_profilehooks.py,v retrieving revision 1.6 retrieving revision 1.6.10.1 diff -C2 -d -r1.6 -r1.6.10.1 *** test_profilehooks.py 4 Oct 2001 14:49:46 -0000 1.6 --- test_profilehooks.py 3 Mar 2002 15:17:07 -0000 1.6.10.1 *************** *** 1,4 **** --- 1,6 ---- from __future__ import generators + from test_support import TestFailed + import pprint import sys *************** *** 330,333 **** --- 332,339 ---- def capture_events(callable, p=None): + try: sys.setprofile() + except TypeError: pass + else: raise TestFailed, 'sys.setprofile() did not raise TypeError' + if p is None: p = HookWatcher() Index: test_scope.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_scope.py,v retrieving revision 1.24 retrieving revision 1.24.4.1 diff -C2 -d -r1.24 -r1.24.4.1 *** test_scope.py 15 Dec 2001 18:04:10 -0000 1.24 --- test_scope.py 3 Mar 2002 15:17:07 -0000 1.24.4.1 *************** *** 472,475 **** --- 472,479 ---- sys.settrace(None) + try: sys.settrace() + except TypeError: pass + else: raise TestFailed, 'sys.settrace() did not raise TypeError' + print "20. eval and exec with free variables" From nnorwitz@users.sourceforge.net Sun Mar 3 15:17:09 2002 From: nnorwitz@users.sourceforge.net (Neal Norwitz) Date: Sun, 03 Mar 2002 07:17:09 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python sysmodule.c,2.98.6.2,2.98.6.3 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv8134/Python Modified Files: Tag: release22-maint sysmodule.c Log Message: SF #506611, fix sys.setprofile(), sys.settrace() core dumps when no arguments are passed Index: sysmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/sysmodule.c,v retrieving revision 2.98.6.2 retrieving revision 2.98.6.3 diff -C2 -d -r2.98.6.2 -r2.98.6.3 *** sysmodule.c 6 Feb 2002 17:06:03 -0000 2.98.6.2 --- sysmodule.c 3 Mar 2002 15:17:07 -0000 2.98.6.3 *************** *** 565,572 **** setdlopenflags_doc}, #endif ! {"setprofile", sys_setprofile, METH_OLDARGS, setprofile_doc}, {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, setrecursionlimit_doc}, ! {"settrace", sys_settrace, METH_OLDARGS, settrace_doc}, {NULL, NULL} /* sentinel */ }; --- 565,572 ---- setdlopenflags_doc}, #endif ! {"setprofile", sys_setprofile, METH_O, setprofile_doc}, {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, setrecursionlimit_doc}, ! {"settrace", sys_settrace, METH_O, settrace_doc}, {NULL, NULL} /* sentinel */ }; From gvanrossum@users.sourceforge.net Sun Mar 3 19:58:43 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 03 Mar 2002 11:58:43 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.22,1.23 test_datetime.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv24418 Modified Files: datetime.py test_datetime.py Log Message: - Add isoweekday(), which has Monday-Sunday == 1-7. - Fix timedelta.__div__, and add testcases for it. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** datetime.py 3 Mar 2002 06:11:54 -0000 1.22 --- datetime.py 3 Mar 2002 19:58:41 -0000 1.23 *************** *** 273,281 **** def __div__(self, other): if isinstance(other, (int, long)): ! # XXX If, e.g., this is a delta of 1 day, dividing by 2 and ! # XXX getting back 0 is pretty surprising. ! return timedelta(self.__days // other, ! self.__seconds // other, ! self.__microseconds // other) return NotImplemented --- 273,279 ---- def __div__(self, other): if isinstance(other, (int, long)): ! usec = ((self.__days * (24*3600L) + self.__seconds) * 1000000 + ! self.__microseconds) ! return timedelta(0, 0, usec // other) return NotImplemented *************** *** 615,625 **** def weekday(self): ! "Return day of the week, where Monday == 0 (according to ISO)." ! # The constant 6 was obtained experimentally :-) ! # XXX I (tim) believe this is incorrect: ISO defines day ordinals ! # XXX as ranging from 1 (Monday) through 7 (Sunday). The next line ! # XXX (commented out) implements that: ! # return self.toordinal() % 7 or 7 ! return (_ymd2ord(self.__year, self.__month, self.__day) + 6) % 7 def isocalendar(self): --- 613,623 ---- def weekday(self): ! "Return day of the week, where Monday == 0 ... Sunday == 6." ! return (self.toordinal() + 6) % 7 ! ! def isoweekday(self): ! "Return day of the week, where Monday == 1 ... Sunday == 7." ! # 1-Jan-0001 is a Monday ! return self.toordinal() % 7 or 7 def isocalendar(self): Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** test_datetime.py 3 Mar 2002 06:11:54 -0000 1.13 --- test_datetime.py 3 Mar 2002 19:58:41 -0000 1.14 *************** *** 145,148 **** --- 145,153 ---- self.assertEqual(c*1000, timedelta(0, 1)) self.assertEqual(1000*c, timedelta(0, 1)) + self.assertEqual(a//7, timedelta(1)) + self.assertEqual(b//10, timedelta(0, 6)) + self.assertEqual(c//1000, timedelta(0, 0, 1)) + self.assertEqual(a//10, timedelta(0, 7*24*360)) + self.assertEqual(a//3600000, timedelta(0, 0, 7*24*1000)) def test_computations(self): *************** *** 198,203 **** --- 203,210 ---- # March 4, 2002 is a Monday self.assertEqual(datetime(2002, 3, 4+i).weekday(), i) + self.assertEqual(datetime(2002, 3, 4+i).isoweekday(), i+1) # January 2, 1956 is a Monday self.assertEqual(datetime(1956, 1, 2+i).weekday(), i) + self.assertEqual(datetime(1956, 1, 2+i).isoweekday(), i+1) def test_isocalendar(self): From gvanrossum@users.sourceforge.net Sun Mar 3 20:24:09 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 03 Mar 2002 12:24:09 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.23,1.24 test_datetime.py,1.14,1.15 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv2478 Modified Files: datetime.py test_datetime.py Log Message: As suggested by Neal Norwitz, support add/sub int/long/float to datetime and timedelta, interpreting as seconds. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** datetime.py 3 Mar 2002 19:58:41 -0000 1.23 --- datetime.py 3 Mar 2002 20:24:06 -0000 1.24 *************** *** 236,239 **** --- 236,249 ---- self.__seconds + other.__seconds, self.__microseconds + other.__microseconds) + if isinstance(other, (int, long)): + return timedelta(self.__days, + self.__seconds + other, + self.__microseconds) + if isinstance(other, float): + ss, us = divmod(other*1e6, 1e6) + d, ss = divmod(ss, 24*3600) + return timedelta(self.__days + int(d), + self.__seconds + int(ss), + self.__microseconds + int(round(us))) return NotImplemented *************** *** 241,245 **** def __sub__(self, other): ! if isinstance(other, timedelta): return self + -other return NotImplemented --- 251,255 ---- def __sub__(self, other): ! if isinstance(other, (timedelta, int, long, float)): return self + -other return NotImplemented *************** *** 306,310 **** __repr__, __str__ __cmp__, __hash__ ! __add__, __radd__, __sub__ (add/radd only with timedelta other arg) Methods: --- 316,320 ---- __repr__, __str__ __cmp__, __hash__ ! __add__, __radd__, __sub__ (add/radd only with timedelta or numeric arg) Methods: *************** *** 572,576 **** def __add__(self, other): ! "Add a datetime to a timedelta." if isinstance(other, timedelta): hh, mm, ss, us = (self.__hour, --- 582,589 ---- def __add__(self, other): ! """Add a datetime to a timedelta. ! ! An int/long/float argument is also allowed, interpreted as seconds. ! """ if isinstance(other, timedelta): hh, mm, ss, us = (self.__hour, *************** *** 589,592 **** --- 602,611 ---- result.__tzoffset = self.__tzoffset return result + elif isinstance(other, (int, long)): + return self + timedelta(0, other) + elif isinstance(other, float): + ss, us = divmod(other*1e6, 1e6) + d, ss = divmod(ss, 24*3600) + return self + timedelta(int(d), int(ss), int(round(us))) return NotImplemented *************** *** 594,599 **** def __sub__(self, other): ! "Subtract two datetimes, or a datetime and a timedelta." ! if isinstance(other, timedelta): return self + -other if isinstance(other, datetime): --- 613,621 ---- def __sub__(self, other): ! """Subtract two datetimes, or a datetime and a timedelta. ! ! An int/long/float argument is also allowed, interpreted as seconds. ! """ ! if isinstance(other, (timedelta, int, long, float)): return self + -other if isinstance(other, datetime): Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** test_datetime.py 3 Mar 2002 19:58:41 -0000 1.14 --- test_datetime.py 3 Mar 2002 20:24:06 -0000 1.15 *************** *** 150,153 **** --- 150,166 ---- self.assertEqual(a//10, timedelta(0, 7*24*360)) self.assertEqual(a//3600000, timedelta(0, 0, 7*24*1000)) + # Add/sub ints, longs, floats + self.assertEqual(a + 7*24*3600, timedelta(14)) + self.assertEqual(a - 24*3600, timedelta(6)) + self.assertEqual(a + 100, timedelta(7, 100)) + self.assertEqual(a - 100, timedelta(6, 24*3600-100)) + self.assertEqual(a + 7*24*3600L, timedelta(14)) + self.assertEqual(a - 24*3600L, timedelta(6)) + self.assertEqual(a + 100L, timedelta(7, 100)) + self.assertEqual(a - 100L, timedelta(6, 24*3600-100)) + self.assertEqual(c + 0.001, timedelta(0, 0, 2000)) + self.assertEqual(c - 0.0001, timedelta(0, 0, 900)) + self.assertEqual(b + 1.1, timedelta(0, 61, 100000)) + self.assertEqual(b - 1.1, timedelta(0, 58, 900000)) def test_computations(self): *************** *** 198,201 **** --- 211,221 ---- self.assertEqual(a - (week + day + hour + millisec), (((a - week) - day) - hour) - millisec) + # Add/sub ints, longs, floats + self.assertEqual(a + 12, a + timedelta(0, 12)) + self.assertEqual(a - 12, a - timedelta(0, 12)) + self.assertEqual(a + 12L, a + timedelta(0, 12)) + self.assertEqual(a - 12L, a - timedelta(0, 12)) + self.assertEqual(a + 0.001, a + timedelta(0, 0, 1000)) + self.assertEqual(a - 0.001, a - timedelta(0, 0, 1000)) def test_weekday(self): From gvanrossum@users.sourceforge.net Sun Mar 3 20:43:52 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 03 Mar 2002 12:43:52 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.24,1.25 test_datetime.py,1.15,1.16 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv7507 Modified Files: datetime.py test_datetime.py Log Message: Add proper tests for __radd__, __rsub__ of timedelta; fix bug thus found. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** datetime.py 3 Mar 2002 20:24:06 -0000 1.24 --- datetime.py 3 Mar 2002 20:43:49 -0000 1.25 *************** *** 256,260 **** def __rsub__(self, other): ! if isinstance(other, timedelta): return -self + other return NotImplemented --- 256,260 ---- def __rsub__(self, other): ! if isinstance(other, (timedelta, int, long, float)): return -self + other return NotImplemented Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** test_datetime.py 3 Mar 2002 20:24:06 -0000 1.15 --- test_datetime.py 3 Mar 2002 20:43:49 -0000 1.16 *************** *** 155,166 **** --- 155,174 ---- self.assertEqual(a + 100, timedelta(7, 100)) self.assertEqual(a - 100, timedelta(6, 24*3600-100)) + self.assertEqual(100 + a, a + 100) + self.assertEqual(100 - a, 100 + -a) self.assertEqual(a + 7*24*3600L, timedelta(14)) self.assertEqual(a - 24*3600L, timedelta(6)) self.assertEqual(a + 100L, timedelta(7, 100)) self.assertEqual(a - 100L, timedelta(6, 24*3600-100)) + self.assertEqual(100L + a, a + 100L) + self.assertEqual(100L - a, 100L + -a) self.assertEqual(c + 0.001, timedelta(0, 0, 2000)) self.assertEqual(c - 0.0001, timedelta(0, 0, 900)) self.assertEqual(b + 1.1, timedelta(0, 61, 100000)) self.assertEqual(b - 1.1, timedelta(0, 58, 900000)) + self.assertEqual(a + 1e6 + 1e-6, timedelta(7, 1000000, 1)) + self.assertEqual(a - 1e6 - 1e-6, timedelta(7, -1000000, -1)) + self.assertEqual(1.1 + a, a + 1.1) + self.assertEqual(1.1 - a, 1.1 + -a) def test_computations(self): *************** *** 214,221 **** --- 222,232 ---- self.assertEqual(a + 12, a + timedelta(0, 12)) self.assertEqual(a - 12, a - timedelta(0, 12)) + self.assertEqual(100 + a, a + 100) self.assertEqual(a + 12L, a + timedelta(0, 12)) self.assertEqual(a - 12L, a - timedelta(0, 12)) + self.assertEqual(100L + a, a + 100L) self.assertEqual(a + 0.001, a + timedelta(0, 0, 1000)) self.assertEqual(a - 0.001, a - timedelta(0, 0, 1000)) + self.assertEqual(0.1 + a, a + 0.1) def test_weekday(self): From gvanrossum@users.sourceforge.net Sun Mar 3 20:45:14 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 03 Mar 2002 12:45:14 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.16,1.17 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv7860 Modified Files: test_datetime.py Log Message: Make one float test tougher. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** test_datetime.py 3 Mar 2002 20:43:49 -0000 1.16 --- test_datetime.py 3 Mar 2002 20:45:12 -0000 1.17 *************** *** 167,172 **** self.assertEqual(b + 1.1, timedelta(0, 61, 100000)) self.assertEqual(b - 1.1, timedelta(0, 58, 900000)) ! self.assertEqual(a + 1e6 + 1e-6, timedelta(7, 1000000, 1)) ! self.assertEqual(a - 1e6 - 1e-6, timedelta(7, -1000000, -1)) self.assertEqual(1.1 + a, a + 1.1) self.assertEqual(1.1 - a, 1.1 + -a) --- 167,172 ---- self.assertEqual(b + 1.1, timedelta(0, 61, 100000)) self.assertEqual(b - 1.1, timedelta(0, 58, 900000)) ! self.assertEqual(a + (1e6 + 1e-6), timedelta(7, 1000000, 1)) ! self.assertEqual(a - (1e6 + 1e-6), timedelta(7, -1000000, -1)) self.assertEqual(1.1 + a, a + 1.1) self.assertEqual(1.1 - a, 1.1 + -a) From gvanrossum@users.sourceforge.net Sun Mar 3 20:52:31 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 03 Mar 2002 12:52:31 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.25,1.26 test_datetime.py,1.17,1.18 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv9873 Modified Files: datetime.py test_datetime.py Log Message: Of course, isocalendar() should return 1-7 for the weekday too. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** datetime.py 3 Mar 2002 20:43:49 -0000 1.25 --- datetime.py 3 Mar 2002 20:52:29 -0000 1.26 *************** *** 650,654 **** from that. ! Note that the first week is 1, but Monday is 0. ISO calendar algorithm taken from --- 650,654 ---- from that. ! The first week is 1; Monday is 1 ... Sunday is 7. ISO calendar algorithm taken from *************** *** 668,672 **** year += 1 week = 0 ! return year, week+1, day --- 668,672 ---- year += 1 week = 0 ! return year, week+1, day+1 Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** test_datetime.py 3 Mar 2002 20:45:12 -0000 1.17 --- test_datetime.py 3 Mar 2002 20:52:29 -0000 1.18 *************** *** 244,258 **** for i in range(7): d = datetime(2003, 12, 22+i) ! self.assertEqual(d.isocalendar(), (2003, 52, i)) d = datetime(2003, 12, 29) + timedelta(i) ! self.assertEqual(d.isocalendar(), (2004, 1, i)) d = datetime(2004, 1, 5+i) ! self.assertEqual(d.isocalendar(), (2004, 2, i)) d = datetime(2009, 12, 21+i) ! self.assertEqual(d.isocalendar(), (2009, 52, i)) d = datetime(2009, 12, 28) + timedelta(i) ! self.assertEqual(d.isocalendar(), (2009, 53, i)) d = datetime(2010, 1, 4+i) ! self.assertEqual(d.isocalendar(), (2010, 1, i)) def test_iso_long_years(self): --- 244,258 ---- for i in range(7): d = datetime(2003, 12, 22+i) ! self.assertEqual(d.isocalendar(), (2003, 52, i+1)) d = datetime(2003, 12, 29) + timedelta(i) ! self.assertEqual(d.isocalendar(), (2004, 1, i+1)) d = datetime(2004, 1, 5+i) ! self.assertEqual(d.isocalendar(), (2004, 2, i+1)) d = datetime(2009, 12, 21+i) ! self.assertEqual(d.isocalendar(), (2009, 52, i+1)) d = datetime(2009, 12, 28) + timedelta(i) ! self.assertEqual(d.isocalendar(), (2009, 53, i+1)) d = datetime(2010, 1, 4+i) ! self.assertEqual(d.isocalendar(), (2010, 1, i+1)) def test_iso_long_years(self): From gvanrossum@users.sourceforge.net Sun Mar 3 21:24:35 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 03 Mar 2002 13:24:35 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.26,1.27 test_datetime.py,1.18,1.19 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv20056 Modified Files: datetime.py test_datetime.py Log Message: - Add isoformat() and utcisoformat(), returning ISO style timestamps. - Use isoformat(' ') in __str__. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** datetime.py 3 Mar 2002 20:52:29 -0000 1.26 --- datetime.py 3 Mar 2002 21:24:33 -0000 1.27 *************** *** 324,327 **** --- 324,329 ---- strftime(), utcstrftime() toordinal() + weekday(), isoweekday(), isocalendar() + isoformat(), utcisoformat() Properties (readonly): *************** *** 438,450 **** def __str__(self): "Convert to pretty string, for str()." ! if self.__tzoffset == 0: ! return self.ctime() + " UTC" ! if self.__tzoffset > 0: ! h, m = divmod(self.__tzoffset, 60) ! else: ! h, m = divmod(-self.__tzoffset, 60) ! h = -h ! # XXX This is broken! ctime() renormalizes to local time. :-( ! return self.ctime() + " %+03d:%02d" % (h, m) # Read-only field accessors --- 440,444 ---- def __str__(self): "Convert to pretty string, for str()." ! return self.isoformat(sep=' ') # Read-only field accessors *************** *** 669,672 **** --- 663,701 ---- week = 0 return year, week+1, day+1 + + def isoformat(self, sep='T'): + """Return the time formatted according to ISO. + + This is 'YYYY-MM-DD HH:MM:SS.mmmmmm-xx:yy' + where -xx:yy is the timezone offset. + + Optional argument sep specifies the separator between date and + time, default 'T'. + + This method does not convert to local time. + """ + if self.__tzoffset >= 0: + h, m = divmod(self.__tzoffset, 60) + else: + h, m = divmod(-self.__tzoffset, 60) + h = -h + return "%04d-%02d-%02d%c%02d:%02d:%02d.%06d%+03d:%02d" % ( + self.__year, self.__month, self.__day, + sep, + self.__hour, self.__minute, self.__second, + self.__microsecond, + h, m) + + def utcisoformat(self, sep='T'): + """Return the time as UTC formatted according to ISO. + + This is 'YYYY-MM-DD HH:MM:SS.mmmmmmZ'. + + Optional argument sep specifies the separator between date and + time, default 'T'. + """ + y, m, d, hh, mm = self._utc_ymdHM() + return "%04d-%02d-%02d%c%02d:%02d:%02d.%06dZ" % ( + y, m, d, sep, hh, mm, self.__second, self.__microsecond) Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** test_datetime.py 3 Mar 2002 20:52:29 -0000 1.18 --- test_datetime.py 3 Mar 2002 21:24:33 -0000 1.19 *************** *** 295,298 **** --- 295,305 ---- self.assertEqual(L, iso_long_years) + def test_isoformat(self): + t = datetime(2, 3, 2, 4, 5, 1, 123, tzoffset=-120) + self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123-02:00") + self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123-02:00") + self.assertEqual(t.utcisoformat(), "0002-03-02T06:05:01.000123Z") + self.assertEqual(t.utcisoformat(' '), "0002-03-02 06:05:01.000123Z") + def test_tmxxx(self): from datetime import tmxxx From loewis@users.sourceforge.net Sun Mar 3 21:30:29 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 03 Mar 2002 13:30:29 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.359,1.360 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv20927/Misc Modified Files: NEWS Log Message: Patch #50002: Display line information for bad \x escapes: - recognize "SyntaxError"s by the print_file_and_line attribute. - add the syntaxerror attributes to all exceptions in compile.c. Fixes #221791 Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.359 retrieving revision 1.360 diff -C2 -d -r1.359 -r1.360 *** NEWS 1 Mar 2002 10:47:37 -0000 1.359 --- NEWS 3 Mar 2002 21:30:27 -0000 1.360 *************** *** 7,10 **** --- 7,13 ---- Core and builtins + - PyErr_Display will provide file and line information for all exceptions + that have an attribute print_file_and_line, not just SyntaxErrors. + - The UTF-8 codec will now encode and decode Unicode surrogates correctly and without raising exceptions for unpaired ones. From loewis@users.sourceforge.net Sun Mar 3 21:30:29 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 03 Mar 2002 13:30:29 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python compile.c,2.238,2.239 errors.c,2.66,2.67 exceptions.c,1.28,1.29 pythonrun.c,2.154,2.155 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv20927/Python Modified Files: compile.c errors.c exceptions.c pythonrun.c Log Message: Patch #50002: Display line information for bad \x escapes: - recognize "SyntaxError"s by the print_file_and_line attribute. - add the syntaxerror attributes to all exceptions in compile.c. Fixes #221791 Index: compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.238 retrieving revision 2.239 diff -C2 -d -r2.238 -r2.239 *** compile.c 29 Jan 2002 00:56:37 -0000 2.238 --- compile.c 3 Mar 2002 21:30:27 -0000 2.239 *************** *** 466,477 **** line = Py_None; } ! t = Py_BuildValue("(ziOO)", c->c_filename, c->c_lineno, ! Py_None, line); ! if (t == NULL) ! goto exit; ! w = Py_BuildValue("(OO)", v, t); ! if (w == NULL) ! goto exit; ! PyErr_SetObject(exc, w); exit: Py_XDECREF(t); --- 466,484 ---- line = Py_None; } ! if (exc == PyExc_SyntaxError) { ! t = Py_BuildValue("(ziOO)", c->c_filename, c->c_lineno, ! Py_None, line); ! if (t == NULL) ! goto exit; ! w = Py_BuildValue("(OO)", v, t); ! if (w == NULL) ! goto exit; ! PyErr_SetObject(exc, w); ! } else { ! /* Make sure additional exceptions are printed with ! file and line, also. */ ! PyErr_SetObject(exc, v); ! PyErr_SyntaxLocation(c->c_filename, c->c_lineno); ! } exit: Py_XDECREF(t); *************** *** 1154,1158 **** len = strlen(s); if (len > INT_MAX) { ! PyErr_SetString(PyExc_OverflowError, "string to parse is too long"); return NULL; } --- 1161,1166 ---- len = strlen(s); if (len > INT_MAX) { ! com_error(com, PyExc_OverflowError, ! "string to parse is too long"); return NULL; } *************** *** 1172,1180 **** if (unicode || Py_UnicodeFlag) { if (rawmode) ! return PyUnicode_DecodeRawUnicodeEscape( ! s, len, NULL); else ! return PyUnicode_DecodeUnicodeEscape( s, len, NULL); } #endif --- 1180,1192 ---- if (unicode || Py_UnicodeFlag) { if (rawmode) ! v = PyUnicode_DecodeRawUnicodeEscape( ! s, len, NULL); else ! v = PyUnicode_DecodeUnicodeEscape( s, len, NULL); + if (v == NULL) + PyErr_SyntaxLocation(com->c_filename, com->c_lineno); + return v; + } #endif *************** *** 1239,1245 **** break; } - PyErr_SetString(PyExc_ValueError, - "invalid \\x escape"); Py_DECREF(v); return NULL; default: --- 1251,1257 ---- break; } Py_DECREF(v); + com_error(com, PyExc_ValueError, + "invalid \\x escape"); return NULL; default: Index: errors.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v retrieving revision 2.66 retrieving revision 2.67 diff -C2 -d -r2.66 -r2.67 *** errors.c 2 Oct 2001 21:32:07 -0000 2.66 --- errors.c 3 Mar 2002 21:30:27 -0000 2.67 *************** *** 562,566 **** ! /* XXX There's a comment missing here */ void --- 562,568 ---- ! /* Set file and line information for the current exception. ! If the exception is not a SyntaxError, also sets additional attributes ! to make printing of exceptions believe it is a syntax error. */ void *************** *** 595,598 **** --- 597,620 ---- PyObject_SetAttrString(v, "text", tmp); Py_DECREF(tmp); + } + } + if (PyObject_SetAttrString(v, "offset", Py_None)) { + PyErr_Clear(); + } + if (exc != PyExc_SyntaxError) { + if (!PyObject_HasAttrString(v, "msg")) { + tmp = PyObject_Str(v); + if (tmp) { + if (PyObject_SetAttrString(v, "msg", tmp)) + PyErr_Clear(); + Py_DECREF(tmp); + } else { + PyErr_Clear(); + } + } + if (!PyObject_HasAttrString(v, "print_file_and_line")) { + if (PyObject_SetAttrString(v, "print_file_and_line", + Py_None)) + PyErr_Clear(); } } Index: exceptions.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/exceptions.c,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** exceptions.c 28 Nov 2001 20:24:33 -0000 1.28 --- exceptions.c 3 Mar 2002 21:30:27 -0000 1.29 *************** *** 671,675 **** PyObject_SetAttrString(klass, "lineno", Py_None) || PyObject_SetAttrString(klass, "offset", Py_None) || ! PyObject_SetAttrString(klass, "text", Py_None)) { retval = -1; --- 671,676 ---- PyObject_SetAttrString(klass, "lineno", Py_None) || PyObject_SetAttrString(klass, "offset", Py_None) || ! PyObject_SetAttrString(klass, "text", Py_None) || ! PyObject_SetAttrString(klass, "print_file_and_line", Py_None)) { retval = -1; Index: pythonrun.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v retrieving revision 2.154 retrieving revision 2.155 diff -C2 -d -r2.154 -r2.155 *** pythonrun.c 12 Jan 2002 11:05:11 -0000 2.154 --- pythonrun.c 3 Mar 2002 21:30:27 -0000 2.155 *************** *** 921,925 **** err = PyTraceBack_Print(tb, f); if (err == 0 && ! PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { PyObject *message; --- 921,925 ---- err = PyTraceBack_Print(tb, f); if (err == 0 && ! PyObject_HasAttrString(v, "print_file_and_line")) { PyObject *message; From loewis@users.sourceforge.net Sun Mar 3 21:32:03 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 03 Mar 2002 13:32:03 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python compile.c,2.234.4.2,2.234.4.3 errors.c,2.66,2.66.10.1 exceptions.c,1.28,1.28.6.1 pythonrun.c,2.153.6.1,2.153.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv22284/Python Modified Files: Tag: release22-maint compile.c errors.c exceptions.c pythonrun.c Log Message: Patch #50002: Display line information for bad \x escapes: - recognize "SyntaxError"s by the print_file_and_line attribute. - add the syntaxerror attributes to all exceptions in compile.c. Fixes #221791 Index: compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.234.4.2 retrieving revision 2.234.4.3 diff -C2 -d -r2.234.4.2 -r2.234.4.3 *** compile.c 6 Feb 2002 17:06:02 -0000 2.234.4.2 --- compile.c 3 Mar 2002 21:32:00 -0000 2.234.4.3 *************** *** 466,477 **** line = Py_None; } ! t = Py_BuildValue("(ziOO)", c->c_filename, c->c_lineno, ! Py_None, line); ! if (t == NULL) ! goto exit; ! w = Py_BuildValue("(OO)", v, t); ! if (w == NULL) ! goto exit; ! PyErr_SetObject(exc, w); exit: Py_XDECREF(t); --- 466,484 ---- line = Py_None; } ! if (exc == PyExc_SyntaxError) { ! t = Py_BuildValue("(ziOO)", c->c_filename, c->c_lineno, ! Py_None, line); ! if (t == NULL) ! goto exit; ! w = Py_BuildValue("(OO)", v, t); ! if (w == NULL) ! goto exit; ! PyErr_SetObject(exc, w); ! } else { ! /* Make sure additional exceptions are printed with ! file and line, also. */ ! PyErr_SetObject(exc, v); ! PyErr_SyntaxLocation(c->c_filename, c->c_lineno); ! } exit: Py_XDECREF(t); *************** *** 1154,1158 **** len = strlen(s); if (len > INT_MAX) { ! PyErr_SetString(PyExc_OverflowError, "string to parse is too long"); return NULL; } --- 1161,1166 ---- len = strlen(s); if (len > INT_MAX) { ! com_error(com, PyExc_OverflowError, ! "string to parse is too long"); return NULL; } *************** *** 1172,1180 **** if (unicode || Py_UnicodeFlag) { if (rawmode) ! return PyUnicode_DecodeRawUnicodeEscape( ! s, len, NULL); else ! return PyUnicode_DecodeUnicodeEscape( s, len, NULL); } #endif --- 1180,1192 ---- if (unicode || Py_UnicodeFlag) { if (rawmode) ! v = PyUnicode_DecodeRawUnicodeEscape( ! s, len, NULL); else ! v = PyUnicode_DecodeUnicodeEscape( s, len, NULL); + if (v == NULL) + PyErr_SyntaxLocation(com->c_filename, com->c_lineno); + return v; + } #endif *************** *** 1239,1245 **** break; } - PyErr_SetString(PyExc_ValueError, - "invalid \\x escape"); Py_DECREF(v); return NULL; default: --- 1251,1257 ---- break; } Py_DECREF(v); + com_error(com, PyExc_ValueError, + "invalid \\x escape"); return NULL; default: Index: errors.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v retrieving revision 2.66 retrieving revision 2.66.10.1 diff -C2 -d -r2.66 -r2.66.10.1 *** errors.c 2 Oct 2001 21:32:07 -0000 2.66 --- errors.c 3 Mar 2002 21:32:01 -0000 2.66.10.1 *************** *** 562,566 **** ! /* XXX There's a comment missing here */ void --- 562,568 ---- ! /* Set file and line information for the current exception. ! If the exception is not a SyntaxError, also sets additional attributes ! to make printing of exceptions believe it is a syntax error. */ void *************** *** 595,598 **** --- 597,620 ---- PyObject_SetAttrString(v, "text", tmp); Py_DECREF(tmp); + } + } + if (PyObject_SetAttrString(v, "offset", Py_None)) { + PyErr_Clear(); + } + if (exc != PyExc_SyntaxError) { + if (!PyObject_HasAttrString(v, "msg")) { + tmp = PyObject_Str(v); + if (tmp) { + if (PyObject_SetAttrString(v, "msg", tmp)) + PyErr_Clear(); + Py_DECREF(tmp); + } else { + PyErr_Clear(); + } + } + if (!PyObject_HasAttrString(v, "print_file_and_line")) { + if (PyObject_SetAttrString(v, "print_file_and_line", + Py_None)) + PyErr_Clear(); } } Index: exceptions.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/exceptions.c,v retrieving revision 1.28 retrieving revision 1.28.6.1 diff -C2 -d -r1.28 -r1.28.6.1 *** exceptions.c 28 Nov 2001 20:24:33 -0000 1.28 --- exceptions.c 3 Mar 2002 21:32:01 -0000 1.28.6.1 *************** *** 671,675 **** PyObject_SetAttrString(klass, "lineno", Py_None) || PyObject_SetAttrString(klass, "offset", Py_None) || ! PyObject_SetAttrString(klass, "text", Py_None)) { retval = -1; --- 671,676 ---- PyObject_SetAttrString(klass, "lineno", Py_None) || PyObject_SetAttrString(klass, "offset", Py_None) || ! PyObject_SetAttrString(klass, "text", Py_None) || ! PyObject_SetAttrString(klass, "print_file_and_line", Py_None)) { retval = -1; Index: pythonrun.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v retrieving revision 2.153.6.1 retrieving revision 2.153.6.2 diff -C2 -d -r2.153.6.1 -r2.153.6.2 *** pythonrun.c 12 Jan 2002 11:13:24 -0000 2.153.6.1 --- pythonrun.c 3 Mar 2002 21:32:01 -0000 2.153.6.2 *************** *** 921,925 **** err = PyTraceBack_Print(tb, f); if (err == 0 && ! PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { PyObject *message; --- 921,925 ---- err = PyTraceBack_Print(tb, f); if (err == 0 && ! PyObject_HasAttrString(v, "print_file_and_line")) { PyObject *message; From loewis@users.sourceforge.net Sun Mar 3 21:32:03 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 03 Mar 2002 13:32:03 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.337.2.4.2.1,1.337.2.4.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv22284/Misc Modified Files: Tag: release22-maint NEWS Log Message: Patch #50002: Display line information for bad \x escapes: - recognize "SyntaxError"s by the print_file_and_line attribute. - add the syntaxerror attributes to all exceptions in compile.c. Fixes #221791 Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.337.2.4.2.1 retrieving revision 1.337.2.4.2.2 diff -C2 -d -r1.337.2.4.2.1 -r1.337.2.4.2.2 *** NEWS 10 Jan 2002 13:51:05 -0000 1.337.2.4.2.1 --- NEWS 3 Mar 2002 21:32:00 -0000 1.337.2.4.2.2 *************** *** 3,6 **** --- 3,12 ---- =============================== + Core and builtins + + - PyErr_Display will provide file and line information for all exceptions + that have an attribute print_file_and_line, not just SyntaxErrors. This + fixes the bug that no proper line number is given for bad \x escapes. + Library From bwarsaw@users.sourceforge.net Sun Mar 3 22:46:48 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Sun, 03 Mar 2002 14:46:48 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/email Generator.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/email In directory usw-pr-cvs1:/tmp/cvs-serv14468 Modified Files: Generator.py Log Message: Removed two unused imports. Closes patch #525225. 2.2.1 candidate (but not terribly important). Index: Generator.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/email/Generator.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Generator.py 19 Oct 2001 04:06:39 -0000 1.6 --- Generator.py 3 Mar 2002 22:46:46 -0000 1.7 *************** *** 12,19 **** from cStringIO import StringIO - # Intrapackage imports - import Message - import Errors - EMPTYSTRING = '' SEMISPACE = '; ' --- 12,15 ---- From gvanrossum@users.sourceforge.net Sun Mar 3 23:16:23 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 03 Mar 2002 15:16:23 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.27,1.28 test_datetime.py,1.19,1.20 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv22462 Modified Files: datetime.py test_datetime.py Log Message: Attempt to fix ctime() to avoid dependence on time.localtime(). XXX This probably breaks when the time module's epoch isn't 1/1/1970! - Add global arrays _MONTHNAMES and _DAYNAMES - Augment class tmxxx: - Note in time() docstring that it assumes UTC - Add ctime() method - Add _localtzoffset() function which attempts to calculate the tzoffset for a given local time. It asks localtime() if possible, but if that fails just assumes time.timezone. - Use _localtzoffset() to calculate the default tzoffset; correct, but even slower than before - Change _mktime() to use tmxxx() instead of the time module - Change _utc_ymdHM() to use tmxxx() instead of repeating the work - Change ctime() and utcctime() to do the right thing, using tmxxx (mostly; there's some stuff with renormalizing for the local time zone that I've probably gotten wrong) - Fix a comment or two Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** datetime.py 3 Mar 2002 21:24:33 -0000 1.27 --- datetime.py 3 Mar 2002 23:16:21 -0000 1.28 *************** *** 92,95 **** --- 92,100 ---- return year, month, n-dbm + # Month and day names. For localized versions, see the calendar module. + _MONTHNAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + _DAYNAMES = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] + # This is a start at a struct tm workalike. Goals: # *************** *** 141,145 **** def time(self): ! "Return Unixish timestamp, as a float." if self.ordinal is None: self.ordinal = _ymd2ord(self.year, self.month, self.day) --- 146,150 ---- def time(self): ! "Return Unixish timestamp, as a float (assuming UTC)." if self.ordinal is None: self.ordinal = _ymd2ord(self.year, self.month, self.day) *************** *** 148,151 **** --- 153,183 ---- return seconds + self.second + self.microsecond / 1e6 + def ctime(self): + "Return ctime() style string." + if self.ordinal is None: + self.ordinal = _ymd2ord(self.year, self.month, self.day) + weekday = self.ordinal % 7 or 7 + return "%s %s %2d %02d:%02d:%02d %04d" % ( + _DAYNAMES[weekday - 1], + _MONTHNAMES[self.month - 1], + self.day, + self.hour, self.minute, self.second, + self.year) + + + def _localtzoffset(year, month, day, hour, minute): + "Return tzoffset for local time corresponding to given date/time." + try: + t = _time.mktime((year, month, day, hour, minute, 0, -1, -1, -1)) + tm = _time.localtime(t) + if tm.tm_isdst > 0: + return - (_time.altzone // 60) + else: + return - (_time.timezone // 60) + except (ValueError, OverflowError): + # XXX Dates out of range for mktime() never see DST + return - (_time.timezone // 60) + + class basetime(object): """Abstract date/time type. *************** *** 331,336 **** """ - __isdst = None - def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzoffset=None): --- 363,366 ---- *************** *** 361,372 **** raise ValueError('microsecond must be in 0..999999', microsecond) if tzoffset is None: ! # XXX This decides whether local time is DST or not once, ! # and never changes its mind, regardless how long we run ! if datetime.__isdst is None: ! datetime.__isdst = _time.localtime()[-1] ! if datetime.__isdst > 0: ! tzoffset = -(_time.altzone // 60) ! else: ! tzoffset = -(_time.timezone // 60) if not -1439 <= tzoffset <= 1439: raise ValueError('tzoffset must be in -1439..1439', tzoffset) --- 391,396 ---- raise ValueError('microsecond must be in 0..999999', microsecond) if tzoffset is None: ! # XXX Correct, but expensive ! tzoffset = _localtzoffset(year, month, day, hour, minute) if not -1439 <= tzoffset <= 1439: raise ValueError('tzoffset must be in -1439..1439', tzoffset) *************** *** 457,467 **** # Standard conversions, __cmp__, __hash__ (and helpers) def _mktime(self): ! # Helper to call time.mktime() ! y, m, d = self.__year, self.__month, self.__day ! hh, mm, ss = self.__hour, self.__minute, self.__second ! mm -= self.__tzoffset # tzoffset is negative in the US ! ss -= _time.timezone # but time.timezone has the opposite sign! ! return _time.mktime((y, m, d, hh, mm, ss, -1, -1, -1)) def _timestamp(self): --- 481,491 ---- # Standard conversions, __cmp__, __hash__ (and helpers) + # XXX These should be done without reference to the time module + def _mktime(self): ! # Helper to return a POSIX-ish timestamp ! t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute - self.__tzoffset, self.__second) ! return t.time() + self.__microsecond / 1e6 def _timestamp(self): *************** *** 505,539 **** def _utc_ymdHM(self): # Helper to return (year, month, day, hour, minute) in UTC equivalent ! y, m, d = self.__year, self.__month, self.__day ! H, M = self.__hour, self.__minute ! if self.__tzoffset: ! M -= self.__tzoffset ! if not 0 <= M <= 59: ! carry, M = divmod(M, 60) ! H += carry ! if not 0 <= H <= 23: ! carry, H = divmod(H, 24) ! # tzoffset is less than a day, so carry is no more than 1. ! if carry > 0: ! assert carry == 1 ! d += 1 ! if d > _days_in_month(m, y): ! d = 1 ! m += 1 ! if m > 12: ! m = 1 ! y += 1 ! else: ! assert carry == -1 ! d -= 1 ! if d == 0: ! m -= 1 ! if m > 0: ! d = _days_in_month(m, y) ! else: ! d = 31 ! m = 12 ! y -= 1 ! return y, m, d, H, M def __hash__(self): --- 529,535 ---- def _utc_ymdHM(self): # Helper to return (year, month, day, hour, minute) in UTC equivalent ! t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute - self.__tzoffset) ! return t.year, t.month, t.day, t.hour, t.minute def __hash__(self): *************** *** 559,563 **** def ctime(self): "Format a la ctime() in local time." ! return _time.strftime("%c", _time.localtime(self._mktime())) def strftime(self, fmt): --- 555,568 ---- def ctime(self): "Format a la ctime() in local time." ! tzoffset = _localtzoffset(self.__year, self.__month, self.__day, 0, 0) ! t = tmxxx(self.__year, self.__month, self.__day, self.__hour, ! self.__minute - self.__tzoffset + tzoffset, self.__second) ! tzoffset1 = _localtzoffset(t.year, t.month, t.day, t.hour, t.minute) ! if tzoffset1 != tzoffset: ! t = tmxxx(t.year, t.month, t.day, t.hour, ! t.minute - tzoffset + tzoffset1, self.__second) ! tzoffset2 = _localtzoffset(t.year, t.month, t.day, t.hour, t.minute) ! assert tzoffset2 == tzoffset1 # XXX Hah! ! return t.ctime() def strftime(self, fmt): *************** *** 567,571 **** def utcctime(self): "Format a la ctime() in UTC." ! return _time.strftime("%c", _time.gmtime(self._mktime())) def utcstrftime(self, fmt): --- 572,578 ---- def utcctime(self): "Format a la ctime() in UTC." ! t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute - self.__tzoffset, self.__second) ! return t.ctime() def utcstrftime(self, fmt): *************** *** 652,656 **** week1monday = _isoweek1monday(year) today = _ymd2ord(self.__year, self.__month, self.__day) ! # Internally, week has origin 0 week, day = divmod(today - week1monday, 7) if week < 0: --- 659,663 ---- week1monday = _isoweek1monday(year) today = _ymd2ord(self.__year, self.__month, self.__day) ! # Internally, week and day have origin 0 week, day = divmod(today - week1monday, 7) if week < 0: Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** test_datetime.py 3 Mar 2002 21:24:33 -0000 1.19 --- test_datetime.py 3 Mar 2002 23:16:21 -0000 1.20 *************** *** 316,319 **** --- 316,334 ---- self.assertEqual(timestamp, tm.time()) + def test_ctime(self): + t = datetime(2002, 3, 2, 18, 3, 5, 123) + self.assertEqual(t.ctime(), "Sat Mar 2 18:03:05 2002") + # XXX Can only test utcctime() in known timezone :-( + # XXX What about the southern hemisphere, where this is DST? + import time + if time.timezone == 5*3600: + self.assertEqual(t.utcctime(), "Sat Mar 2 23:03:05 2002") + elif time.timezone == 0: + self.assertEqual(t.utcctime(), "Sat Mar 2 18:03:05 2002") + elif time.timezone == 3600: + self.assertEqual(t.utcctime(), "Sat Mar 2 17:03:05 2002") + else: + self.fail("Can't test utcctime()") + def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') From tim_one@users.sourceforge.net Sun Mar 3 23:17:04 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 15:17:04 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.223,2.224 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv23112/python/Modules Modified Files: posixmodule.c Log Message: Python no longer compiled on Windows, due to #include file confusion over SEP, ALTSEP and MAXPATHLEN. Patched up posixmodule.c for MSVC, but unsure what the story is now on other non-Unixish platforms -- the preprocessor maze has no exit . Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.223 retrieving revision 2.224 diff -C2 -d -r2.223 -r2.224 *** posixmodule.c 3 Mar 2002 03:07:07 -0000 2.223 --- posixmodule.c 3 Mar 2002 23:17:02 -0000 2.224 *************** *** 194,201 **** #endif /* HAVE_SYS_UTSNAME_H */ - #ifndef MAXPATHLEN - #define MAXPATHLEN 1024 - #endif /* MAXPATHLEN */ - #ifdef HAVE_DIRENT_H #include --- 194,197 ---- *************** *** 224,227 **** --- 220,224 ---- #include #include + #include "osdefs.h" #define WINDOWS_LEAN_AND_MEAN #include *************** *** 238,241 **** --- 235,242 ---- #include #endif /* OS2 */ + + #ifndef MAXPATHLEN + #define MAXPATHLEN 1024 + #endif /* MAXPATHLEN */ #ifdef UNION_WAIT From tim_one@users.sourceforge.net Mon Mar 4 00:14:56 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 16:14:56 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.28,1.29 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv10857 Modified Files: datetime.py Log Message: _ord2ymd(): Deal with the switch to year-one based computation more gracefully, and add extensive explanation. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** datetime.py 3 Mar 2002 23:16:21 -0000 1.28 --- datetime.py 4 Mar 2002 00:14:54 -0000 1.29 *************** *** 71,94 **** "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1." ! n400 = (n-1) // _DI400Y # number of 400-year blocks preceding ! year = n400 * 400 + 1 ! n -= n400 * _DI400Y ! more = n // 365 ! dby = _days_before_year(more + 1) ! if dby >= n: ! dby -= _days_in_year(more) ! more -= 1 ! year += more ! assert n > dby ! n -= dby month = min(n//29 + 1, 12) ! dbm = _days_before_month(month, year) ! if dbm >= n: month -= 1 ! dbm -= _days_in_month(month, year) ! assert n > dbm ! return year, month, n-dbm # Month and day names. For localized versions, see the calendar module. --- 71,126 ---- "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1." ! # n is a 1-based index, starting at 1-Jan-1. The pattern of leap years ! # repeats exactly every 400 years. The basic strategy is to find the ! # closest 400-year boundary at or before n, then work with the offset ! # from that boundary to n. Life is much clearer if we subtract 1 from ! # n first -- then the values of n at 400-year boundaries are exactly ! # those divisible by _DI400Y: ! # ! # D M Y n n-1 ! # -- --- ---- ---------- ---------------- ! # 31 Dec -400 -_DI400Y -_DI400Y -1 ! # 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary ! # ... ! # 30 Dec 000 -1 -2 ! # 31 Dec 000 0 -1 ! # 1 Jan 001 1 0 400-year boundary ! # 2 Jan 001 2 1 ! # 3 Jan 001 3 2 ! # ... ! # 31 Dec 400 _DI400Y _DI400Y -1 ! # 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary ! n -= 1 ! n400, n = divmod(n, _DI400Y) ! year = n400 * 400 + 1 # ..., -399, 1, 401, ... ! # Now n is the (non-negative) offset, in days, from January 1 of year, to ! # the desired date. First compute how many whole years precede the ! # desired date. Dividing by 365 gives an upper bound quickly, and it's ! # easy to show that it's either exact or one too large (note that this ! # relies on that n < _DI400Y; if we did this before factoring out a close ! # 400-year boundary, there's no bound on how far off n//365 could be). ! whole_years_preceding = n // 365 ! exact_days = _days_before_year(whole_years_preceding + 1) ! if exact_days > n: # estimate is too large ! exact_days -= _days_in_year(whole_years_preceding) ! whole_years_preceding -= 1 ! assert 0 <= exact_days <= n ! year += whole_years_preceding ! n -= exact_days + # Now the year is correct, and n is the offset from January 1. We find + # the month via another estimate that's either exact or one too large. month = min(n//29 + 1, 12) ! exact_days = _days_before_month(month, year) ! if exact_days > n: # estimate is too large month -= 1 ! exact_days -= _days_in_month(month, year) ! assert 0 <= exact_days <= n ! n -= exact_days ! ! # Now the year and month are correct, and n is the offset from the ! # start of that month: we're done! ! return year, month, n+1 # Month and day names. For localized versions, see the calendar module. From tim_one@users.sourceforge.net Mon Mar 4 00:53:03 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 16:53:03 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.29,1.30 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv22303 Modified Files: datetime.py Log Message: tmxxx.__init__(): Optimize for common cases. This got more important when __hash__ started using tmxxx. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.29 retrieving revision 1.30 diff -C2 -d -r1.29 -r1.30 *** datetime.py 4 Mar 2002 00:14:54 -0000 1.29 --- datetime.py 4 Mar 2002 00:53:01 -0000 1.30 *************** *** 147,158 **** microsecond=0): # Normalize all the inputs, and store the normalized values. ! carry, microsecond = divmod(microsecond, 1000000) ! second += carry ! carry, second = divmod(second, 60) ! minute += carry ! carry, minute = divmod(minute, 60) ! hour += carry ! carry, hour = divmod(hour, 24) ! day += carry # That was easy. Now it gets muddy: the proper range for day # can't be determined without knowing the correct month and year, --- 147,163 ---- microsecond=0): # Normalize all the inputs, and store the normalized values. ! if not 0 <= microsecond <= 999999: ! carry, microsecond = divmod(microsecond, 1000000) ! second += carry ! if not 0 <= second <= 59: ! carry, second = divmod(second, 60) ! minute += carry ! if not 0 <= minute <= 59: ! carry, minute = divmod(minute, 60) ! hour += carry ! if not 0 <= hour <= 23: ! carry, hour = divmod(hour, 24) ! day += carry ! # That was easy. Now it gets muddy: the proper range for day # can't be determined without knowing the correct month and year, *************** *** 161,176 **** # themselves). # Saying 12 months == 1 year should be non-controversial. ! carry, month = divmod(month-1, 12) ! year += carry ! month += 1 ! assert 1 <= month <= 12 ! # Now only day can be out of bounds. If it is, what to do is arguable, ! # but at least the method here is principled and explainable. ! if not 1 <= day <= _days_in_month(month, year): ! # Note that the "if" test is for efficiency, not correctness: ! # there's simply no need to do this dance if day is already in ! # range, and it's an expensive dance. ! self.ordinal = _ymd2ord(year, month, 1) + (day - 1) ! year, month, day = _ord2ymd(self.ordinal) self.year, self.month, self.day = year, month, day self.hour, self.minute, self.second = hour, minute, second --- 166,200 ---- # themselves). # Saying 12 months == 1 year should be non-controversial. ! if not 1 <= month <= 12: ! carry, month = divmod(month-1, 12) ! year += carry ! month += 1 ! assert 1 <= month <= 12 ! ! # Now only day can be out of bounds (year may also be out of bounds ! # for a datetime object, but we don't care about that here). ! # If day is out of bounds, what to do is arguable, but at least the ! # method here is principled and explainable. ! dim = _days_in_month(month, year) ! if not 1 <= day <= dim: ! # Move day-1 days from the first of the month. First try to ! # get off cheap if we're only one day out of range (adjustments ! # for timezone alone can't be worse than that). ! if day == 0: # move back a day ! month -= 1 ! if month > 0: ! day = _days_in_month(month, year) ! else: ! year, month, day = year-1, 12, 31 ! elif day == dim + 1: # move forward a day ! month += 1 ! day = 1 ! if month > 12: ! month = 1 ! year += 1 ! else: ! self.ordinal = _ymd2ord(year, month, 1) + (day - 1) ! year, month, day = _ord2ymd(self.ordinal) ! self.year, self.month, self.day = year, month, day self.hour, self.minute, self.second = hour, minute, second From tim_one@users.sourceforge.net Mon Mar 4 01:03:16 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 17:03:16 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.30,1.31 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv25440 Modified Files: datetime.py Log Message: Give tmxxx a toordinal() method, and use it (squash code duplication). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -d -r1.30 -r1.31 *** datetime.py 4 Mar 2002 00:53:01 -0000 1.30 --- datetime.py 4 Mar 2002 01:03:14 -0000 1.31 *************** *** 201,209 **** self.microsecond = microsecond ! def time(self): ! "Return Unixish timestamp, as a float (assuming UTC)." if self.ordinal is None: self.ordinal = _ymd2ord(self.year, self.month, self.day) ! days = self.ordinal - _ORD1970 # convert to UNIX epoch seconds = ((days * 24. + self.hour)*60. + self.minute)*60. return seconds + self.second + self.microsecond / 1e6 --- 201,217 ---- self.microsecond = microsecond ! def toordinal(self): ! """Return proleptic Gregorian ordinal for the year, month and day. ! ! January 1 of year 1 is day 1. Only the year, month and day values ! contribute to the result. ! """ if self.ordinal is None: self.ordinal = _ymd2ord(self.year, self.month, self.day) ! return self.ordinal ! ! def time(self): ! "Return Unixish timestamp, as a float (assuming UTC)." ! days = self.toordinal() - _ORD1970 # convert to UNIX epoch seconds = ((days * 24. + self.hour)*60. + self.minute)*60. return seconds + self.second + self.microsecond / 1e6 *************** *** 211,217 **** def ctime(self): "Return ctime() style string." ! if self.ordinal is None: ! self.ordinal = _ymd2ord(self.year, self.month, self.day) ! weekday = self.ordinal % 7 or 7 return "%s %s %2d %02d:%02d:%02d %04d" % ( _DAYNAMES[weekday - 1], --- 219,223 ---- def ctime(self): "Return ctime() style string." ! weekday = self.toordinal() % 7 or 7 return "%s %s %2d %02d:%02d:%02d %04d" % ( _DAYNAMES[weekday - 1], From tim_one@users.sourceforge.net Mon Mar 4 01:15:01 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 17:15:01 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.20,1.21 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv28300 Modified Files: test_datetime.py Log Message: test_ordinal_conversions(): Exhaustively test ordinal<->date for every day in a leap year, and in a non leap year. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** test_datetime.py 3 Mar 2002 23:16:21 -0000 1.20 --- test_datetime.py 4 Mar 2002 01:14:59 -0000 1.21 *************** *** 64,67 **** --- 64,79 ---- self.assertEqual(_ymd2ord(year-1, 12, 31), n-1) + # Test every day in a leap-year and a non-leap year. + dim = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + for year, isleap in (2000, 1), (2002, 0): + n = _ymd2ord(year, 1, 1) + for month, maxday in zip(range(1, 13), dim): + if month == 2 and isleap: + maxday += 1 + for day in range(1, maxday+1): + self.assertEqual((year, month, day), _ord2ymd(n)) + self.assertEqual(n, _ymd2ord(year, month, day)) + n += 1 + def test_bad_constructor_arguments(self): from datetime import MINYEAR, MAXYEAR From tim_one@users.sourceforge.net Mon Mar 4 01:18:14 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 17:18:14 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.21,1.22 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv29431 Modified Files: test_datetime.py Log Message: test_basic_attributes(): Verify that microsecond defaulted to 0. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** test_datetime.py 4 Mar 2002 01:14:59 -0000 1.21 --- test_datetime.py 4 Mar 2002 01:18:12 -0000 1.22 *************** *** 19,22 **** --- 19,23 ---- self.assertEqual(dt.minute, 0) self.assertEqual(dt.second, 0) + self.assertEqual(dt.microsecond, 0) def test_roundtrip(self): From tim_one@users.sourceforge.net Mon Mar 4 01:24:52 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 17:24:52 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.22,1.23 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv31092 Modified Files: test_datetime.py Log Message: test_bad_constructor_arguments(): add tests for bad microsecond and tzoffset arguments. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** test_datetime.py 4 Mar 2002 01:18:12 -0000 1.22 --- test_datetime.py 4 Mar 2002 01:24:50 -0000 1.23 *************** *** 114,117 **** --- 114,128 ---- self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, -1) self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 60) + # bad microseconds + datetime(2000, 1, 31, 23, 59, 59, 0) # no exception + datetime(2000, 1, 31, 23, 59, 59, 999999) # no exception + self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 59, -1) + self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 59, + 1000000) + # bad tzoffet + datetime(2, 1, 1, 0, 0, 0, 0, -1439) # no exception + datetime(2, 1, 1, 0, 0, 0, 0, 1439) # no exception + self.assertRaises(ValueError, datetime, 2, 1, 1, 0, 0, 0, 0, -1440) + self.assertRaises(ValueError, datetime, 2, 1, 1, 0, 0, 0, 0, 1440) def test_hash_equality(self): From tim_one@users.sourceforge.net Mon Mar 4 01:39:55 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 17:39:55 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.31,1.32 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv1894 Modified Files: datetime.py Log Message: Removed datetime._timestamp(): it called datetime._mktime(), then added in microseconds. But datetime._mktime() already adds in microseconds, so _timestamp() was just a buggy synonyn. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** datetime.py 4 Mar 2002 01:03:14 -0000 1.31 --- datetime.py 4 Mar 2002 01:39:53 -0000 1.32 *************** *** 551,558 **** return t.time() + self.__microsecond / 1e6 - def _timestamp(self): - # Helper like _mktime() that adds microseconds - return self._mktime() + self.__microsecond / 1e6 - def timetuple(self): "Return local time tuple compatible with time.localtime()." --- 551,554 ---- *************** *** 584,588 **** (y2, m2, d2, hh2, mm2, ss2, tz2)) else: ! return cmp(self._timestamp(), other._timestamp()) else: raise TypeError, ("can't compare datetime to %s instance" % --- 580,584 ---- (y2, m2, d2, hh2, mm2, ss2, tz2)) else: ! return cmp(self._mktime(), other._mktime()) else: raise TypeError, ("can't compare datetime to %s instance" % From tim_one@users.sourceforge.net Mon Mar 4 01:42:05 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 17:42:05 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.32,1.33 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv3729 Modified Files: datetime.py Log Message: datetime._mktime(): defer entirely to tmxxx.time(). The latter already knows how to-- and is --adding in microseconds. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** datetime.py 4 Mar 2002 01:39:53 -0000 1.32 --- datetime.py 4 Mar 2002 01:42:03 -0000 1.33 *************** *** 548,553 **** # Helper to return a POSIX-ish timestamp t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute - self.__tzoffset, self.__second) ! return t.time() + self.__microsecond / 1e6 def timetuple(self): --- 548,554 ---- # Helper to return a POSIX-ish timestamp t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute - self.__tzoffset, self.__second, ! self.__microsecond) ! return t.time() def timetuple(self): From tim_one@users.sourceforge.net Mon Mar 4 02:23:28 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 18:23:28 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.33,1.34 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv13979 Modified Files: datetime.py Log Message: timedelta.__add__(): Improve floating-point accuracy. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -d -r1.33 -r1.34 *** datetime.py 4 Mar 2002 01:42:03 -0000 1.33 --- datetime.py 4 Mar 2002 02:23:26 -0000 1.34 *************** *** 7,10 **** --- 7,11 ---- import time as _time + import math as _math MINYEAR = 1 # XXX The design doc says 0 *************** *** 335,343 **** self.__microseconds) if isinstance(other, float): ! ss, us = divmod(other*1e6, 1e6) ! d, ss = divmod(ss, 24*3600) ! return timedelta(self.__days + int(d), ! self.__seconds + int(ss), ! self.__microseconds + int(round(us))) return NotImplemented --- 336,349 ---- self.__microseconds) if isinstance(other, float): ! sign = 1 ! if other < 0: ! sign, other = -1, -other ! frac, whole = _math.modf(other) ! us = int(frac * 1e6 + 0.5) ! assert 0 <= us <= 1000000 # if 1e6, constructor will normalize ! days, seconds = divmod(whole, 24*3600) ! return timedelta(self.__days + sign * int(days), ! self.__seconds + sign * int(seconds), ! self.__microseconds + sign * us) return NotImplemented From tim_one@users.sourceforge.net Mon Mar 4 02:25:30 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 18:25:30 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.34,1.35 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv15437 Modified Files: datetime.py Log Message: timedelta docstring: document that int/long/float seconds work w/ + and -. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** datetime.py 4 Mar 2002 02:23:26 -0000 1.34 --- datetime.py 4 Mar 2002 02:25:28 -0000 1.35 *************** *** 270,273 **** --- 270,274 ---- - add, subtract timedelta + - add, subtract int/long/float seconds - unary plus, minus, abs - compare to timedelta From tim_one@users.sourceforge.net Mon Mar 4 02:43:58 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 18:43:58 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.35,1.36 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv18830 Modified Files: datetime.py Log Message: datetime.__add__(): When adding a float, let the careful fp code in timedelta.__add__ handle it instead. Since floating-point code is always wrong <0.5 wink>, duplication of fp code should be avoided at almost any cost. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.35 retrieving revision 1.36 diff -C2 -d -r1.35 -r1.36 *** datetime.py 4 Mar 2002 02:25:28 -0000 1.35 --- datetime.py 4 Mar 2002 02:43:56 -0000 1.36 *************** *** 672,678 **** return self + timedelta(0, other) elif isinstance(other, float): ! ss, us = divmod(other*1e6, 1e6) ! d, ss = divmod(ss, 24*3600) ! return self + timedelta(int(d), int(ss), int(round(us))) return NotImplemented --- 672,676 ---- return self + timedelta(0, other) elif isinstance(other, float): ! return self + (timedelta(0) + other) return NotImplemented From tim_one@users.sourceforge.net Mon Mar 4 03:01:17 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 19:01:17 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.36,1.37 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv23783 Modified Files: datetime.py Log Message: datetime.__add__(): when adding a timedelta, let tmxxx handle the normalization (Guido remarked on the Wiki that this is what he wanted normalization for -- finally got around to it ). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.36 retrieving revision 1.37 diff -C2 -d -r1.36 -r1.37 *** datetime.py 4 Mar 2002 02:43:56 -0000 1.36 --- datetime.py 4 Mar 2002 03:01:14 -0000 1.37 *************** *** 654,671 **** """ if isinstance(other, timedelta): ! hh, mm, ss, us = (self.__hour, ! self.__minute, ! self.__second + other.seconds, ! self.__microsecond + other.microseconds) ! carry_ss, us = divmod(us, 1000000) ! carry_mm, ss = divmod(ss+carry_ss, 60) ! carry_hh, mm = divmod(mm+carry_mm, 60) ! days, hh = divmod(hh+carry_hh, 24) ! result = datetime.fromordinal(days + other.days + self.toordinal()) ! result.__hour = hh ! result.__minute = mm ! result.__second = ss ! result.__microsecond = us ! result.__tzoffset = self.__tzoffset return result elif isinstance(other, (int, long)): --- 654,667 ---- """ if isinstance(other, timedelta): ! t = tmxxx(self.__year, ! self.__month, ! self.__day + other.days, ! self.__hour, ! self.__minute, ! self.__second + other.seconds, ! self.__microsecond + other.microseconds) ! result = datetime.new(t.year, t.month, t.day, ! t.hour, t.minute, t.second, ! t.microsecond, self.__tzoffset) return result elif isinstance(other, (int, long)): From tim_one@users.sourceforge.net Mon Mar 4 06:10:17 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 03 Mar 2002 22:10:17 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.37,1.38 test_datetime.py,1.23,1.24 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv26196 Modified Files: datetime.py test_datetime.py Log Message: Fixed two bugs in datetime.__cmp__: 1. Shallow. When the tzoffsets matched, it forgot to compare microseconds. 2. Not so shallow. When the tzoffsets didn't match, it reverted to comparing timestamps, but an IEEE double doesn't have enough precision to avoid mapping distinct datetimes onto the same timestamp. It takes about 38 bits to distinguish the individual seconds across 10000 years, leaving only about 53-38 = 15 bits to distinguish the microseconds. As a result, non-equal datetimes could compare equal, especially for years near MAXYEAR. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.37 retrieving revision 1.38 diff -C2 -d -r1.37 -r1.38 *** datetime.py 4 Mar 2002 03:01:14 -0000 1.37 --- datetime.py 4 Mar 2002 06:10:15 -0000 1.38 *************** *** 578,592 **** "Three-way comparison." if isinstance(other, datetime): ! if other.__tzoffset == self.__tzoffset: y, m, d = self.__year, self.__month, self.__day ! hh, mm, ss = self.__hour, self.__minute, self.__second ! tz = self.__tzoffset y2, m2, d2 = other.__year, other.__month, other.__day ! hh2, mm2, ss2 = other.__hour, other.__minute, other.__second ! tz2 = other.__tzoffset ! return cmp((y, m, d, hh, mm, ss, tz), ! (y2, m2, d2, hh2, mm2, ss2, tz2)) else: ! return cmp(self._mktime(), other._mktime()) else: raise TypeError, ("can't compare datetime to %s instance" % --- 578,593 ---- "Three-way comparison." if isinstance(other, datetime): ! if self.__tzoffset == other.__tzoffset: y, m, d = self.__year, self.__month, self.__day ! H, M = self.__hour, self.__minute y2, m2, d2 = other.__year, other.__month, other.__day ! H2, M2 = other.__hour, other.__minute else: ! y, m, d, H, M = self._utc_ymdHM() ! y2, m2, d2, H2, M2 = other._utc_ymdHM() ! return cmp((y, m, d, H, M, ! self.__second, self.__microsecond), ! (y2, m2, d2, H2, M2, ! other.__second, other.__microsecond)) else: raise TypeError, ("can't compare datetime to %s instance" % Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** test_datetime.py 4 Mar 2002 01:24:50 -0000 1.23 --- test_datetime.py 4 Mar 2002 06:10:15 -0000 1.24 *************** *** 7,11 **** import unittest ! from datetime import datetime, timedelta class TestDateTime(unittest.TestCase): --- 7,11 ---- import unittest ! from datetime import datetime, timedelta, MINYEAR, MAXYEAR class TestDateTime(unittest.TestCase): *************** *** 42,47 **** self.assert_(dt2 > dt3) def test_ordinal_conversions(self): ! from datetime import _ymd2ord, _ord2ymd, MINYEAR, MAXYEAR # Check some fixed values. --- 42,66 ---- self.assert_(dt2 > dt3) + # Make sure comparison doesn't forget microseconds, and isn't done + # via comparing a float timestamp (an IEEE double doesn't have enough + # precision to span microsecond resolution across years 1 thru 9999, + # so comparing via timestamp necessarily calls some distinct values + # equal). + dt1 = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) + us = timedelta(microseconds=1) + dt2 = dt1 + us + self.assertEqual(dt2 - dt1, us) + self.assert_(dt1 < dt2) + + # Again, but mix timezones. + dt1 = datetime.new(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60) + dt2 = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) + self.assert_(dt1 == dt2) + dt2 += us + self.assertEqual(dt2 - dt1, us) + self.assert_(dt1 < dt2) + def test_ordinal_conversions(self): ! from datetime import _ymd2ord, _ord2ymd # Check some fixed values. *************** *** 78,82 **** def test_bad_constructor_arguments(self): - from datetime import MINYEAR, MAXYEAR # bad years datetime(MINYEAR, 1, 1) # no exception --- 97,100 ---- From mal@lemburg.com Mon Mar 4 09:13:29 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Mon, 04 Mar 2002 10:13:29 +0100 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.37,1.38 test_datetime.py,1.23,1.24 References: Message-ID: <3C833AB9.788CFE20@lemburg.com> Tim Peters wrote: > > Update of /cvsroot/python/python/nondist/sandbox/datetime > > 2. Not so shallow. When the tzoffsets didn't match, it reverted to > comparing timestamps, but an IEEE double doesn't have enough > precision to avoid mapping distinct datetimes onto the same timestamp. > It takes about 38 bits to distinguish the individual seconds across > 10000 years, leaving only about 53-38 = 15 bits to distinguish the > microseconds. As a result, non-equal datetimes could compare equal, > especially for years near MAXYEAR. Funny, how you guys run into the same problems I had at the time ;-) -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From loewis@users.sourceforge.net Mon Mar 4 09:38:55 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Mon, 04 Mar 2002 01:38:55 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules arraymodule.c,2.67,2.68 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv26372 Modified Files: arraymodule.c Log Message: Remove tp_print. Index: arraymodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/arraymodule.c,v retrieving revision 2.67 retrieving revision 2.68 diff -C2 -d -r2.67 -r2.68 *** arraymodule.c 1 Mar 2002 10:27:01 -0000 2.67 --- arraymodule.c 4 Mar 2002 09:38:52 -0000 2.68 *************** *** 1428,1464 **** }; - static int - array_print(arrayobject *a, FILE *fp, int flags) - { - int ok = 0; - int i, len; - PyObject *v; - len = a->ob_size; - if (len == 0) { - fprintf(fp, "array('%c')", a->ob_descr->typecode); - return ok; - } - if (a->ob_descr->typecode == 'c') { - PyObject *t_empty = PyTuple_New(0); - fprintf(fp, "array('c', "); - v = array_tostring(a, t_empty); - Py_DECREF(t_empty); - ok = PyObject_Print(v, fp, 0); - Py_XDECREF(v); - fprintf(fp, ")"); - return ok; - } - fprintf(fp, "array('%c', [", a->ob_descr->typecode); - for (i = 0; i < len && ok == 0; i++) { - if (i > 0) - fprintf(fp, ", "); - v = (a->ob_descr->getitem)(a, i); - ok = PyObject_Print(v, fp, 0); - Py_XDECREF(v); - } - fprintf(fp, "])"); - return ok; - } - static PyObject * array_repr(arrayobject *a) --- 1428,1431 ---- *************** *** 1720,1724 **** 0, (destructor)array_dealloc, /* tp_dealloc */ ! (printfunc)array_print, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ --- 1687,1691 ---- 0, (destructor)array_dealloc, /* tp_dealloc */ ! 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ From mal@lemburg.com Mon Mar 4 09:54:31 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Mon, 04 Mar 2002 10:54:31 +0100 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.28,1.29 References: Message-ID: <3C834457.ECC484F2@lemburg.com> Tim Peters wrote: > > Index: datetime.py > =================================================================== > RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v > retrieving revision 1.28 > retrieving revision 1.29 > diff -C2 -d -r1.28 -r1.29 > *** datetime.py 3 Mar 2002 23:16:21 -0000 1.28 > --- datetime.py 4 Mar 2002 00:14:54 -0000 1.29 > *************** > *** 71,94 **** > "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1." > > ! n400 = (n-1) // _DI400Y # number of 400-year blocks preceding > ! year = n400 * 400 + 1 > ! n -= n400 * _DI400Y > > ! more = n // 365 > ! dby = _days_before_year(more + 1) > ! if dby >= n: > ! dby -= _days_in_year(more) > ! more -= 1 > ! year += more > ! assert n > dby > ! n -= dby > > month = min(n//29 + 1, 12) > ! dbm = _days_before_month(month, year) > ! if dbm >= n: > month -= 1 > ! dbm -= _days_in_month(month, year) > ! assert n > dbm > ! return year, month, n-dbm > > # Month and day names. For localized versions, see the calendar module. > --- 71,126 ---- > "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1." > > ! # n is a 1-based index, starting at 1-Jan-1. The pattern of leap years > ! # repeats exactly every 400 years. The basic strategy is to find the > ! # closest 400-year boundary at or before n, then work with the offset > ! # from that boundary to n. Life is much clearer if we subtract 1 from > ! # n first -- then the values of n at 400-year boundaries are exactly > ! # those divisible by _DI400Y: > ! # > ! # D M Y n n-1 > ! # -- --- ---- ---------- ---------------- > ! # 31 Dec -400 -_DI400Y -_DI400Y -1 > ! # 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary > ! # ... > ! # 30 Dec 000 -1 -2 > ! # 31 Dec 000 0 -1 > ! # 1 Jan 001 1 0 400-year boundary > ! # 2 Jan 001 2 1 > ! # 3 Jan 001 3 2 > ! # ... > ! # 31 Dec 400 _DI400Y _DI400Y -1 > ! # 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary > ! n -= 1 > ! n400, n = divmod(n, _DI400Y) > ! year = n400 * 400 + 1 # ..., -399, 1, 401, ... > > ! # Now n is the (non-negative) offset, in days, from January 1 of year, to > ! # the desired date. First compute how many whole years precede the > ! # desired date. Dividing by 365 gives an upper bound quickly, and it's > ! # easy to show that it's either exact or one too large (note that this > ! # relies on that n < _DI400Y; if we did this before factoring out a close > ! # 400-year boundary, there's no bound on how far off n//365 could be). > ! whole_years_preceding = n // 365 > ! exact_days = _days_before_year(whole_years_preceding + 1) > ! if exact_days > n: # estimate is too large > ! exact_days -= _days_in_year(whole_years_preceding) > ! whole_years_preceding -= 1 > ! assert 0 <= exact_days <= n > ! year += whole_years_preceding > ! n -= exact_days > > + # Now the year is correct, and n is the offset from January 1. We find > + # the month via another estimate that's either exact or one too large. > month = min(n//29 + 1, 12) > ! exact_days = _days_before_month(month, year) > ! if exact_days > n: # estimate is too large > month -= 1 > ! exact_days -= _days_in_month(month, year) > ! assert 0 <= exact_days <= n > ! n -= exact_days > ! > ! # Now the year and month are correct, and n is the offset from the > ! # start of that month: we're done! > ! return year, month, n+1 Looks a lot like what I do in mxDateTime.c :-) -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From tim_one@users.sourceforge.net Mon Mar 4 10:17:43 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 02:17:43 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.38,1.39 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv2933 Modified Files: datetime.py Log Message: _ord2ymd(): Speedups, especially with an eye toward C reimplementation. This no longer makes any external calls. The computation of the year is now a mirror of that in "Calendrical Calculations", but the latter's computation of month and day is woefully inefficient. Curiously, they didn't seem to realize that leap-year determination comes almost for free from the intermediates left behind from computing the year number. Also added dummy None initial entries to the arrays indexed by month ordinal, to avoid the "-1" adjustment when subscripting. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -d -r1.38 -r1.39 *** datetime.py 4 Mar 2002 06:10:15 -0000 1.38 --- datetime.py 4 Mar 2002 10:17:41 -0000 1.39 *************** *** 21,31 **** # proleptic Gregorian ordinals and many other calendar systems. ! _DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] ! _DAYS_BEFORE_MONTH = [] dbm = 0 ! for dim in _DAYS_IN_MONTH: _DAYS_BEFORE_MONTH.append(dbm) ! dbm = dbm + dim del dbm, dim --- 21,31 ---- # proleptic Gregorian ordinals and many other calendar systems. ! _DAYS_IN_MONTH = [None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] ! _DAYS_BEFORE_MONTH = [None] dbm = 0 ! for dim in _DAYS_IN_MONTH[1:]: _DAYS_BEFORE_MONTH.append(dbm) ! dbm += dim del dbm, dim *************** *** 48,52 **** if month == 2 and _is_leap(year): return 29 ! return _DAYS_IN_MONTH[month-1] def _days_before_month(month, year): --- 48,52 ---- if month == 2 and _is_leap(year): return 29 ! return _DAYS_IN_MONTH[month] def _days_before_month(month, year): *************** *** 54,58 **** if not 1 <= month <= 12: raise ValueError('month must be in 1..12', month) ! return _DAYS_BEFORE_MONTH[month-1] + (month > 2 and _is_leap(year)) def _ymd2ord(year, month, day): --- 54,58 ---- if not 1 <= month <= 12: raise ValueError('month must be in 1..12', month) ! return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year)) def _ymd2ord(year, month, day): *************** *** 68,71 **** --- 68,85 ---- _DI400Y = _days_before_year(401) # number of days in 400 years + _DI100Y = _days_before_year(101) # " " " " 100 " + _DI4Y = _days_before_year(5) # " " " " 4 " + + # A 4-year cycle has an extra leap day over what we'd get from pasting + # together 4 single years. + assert _DI4Y == 4 * 365 + 1 + + # Similarly, a 400-year cycle has an extra leap day over what we'd get from + # pasting together 4 100-year cycles. + assert _DI400Y == 4 * _DI100Y + 1 + + # OTOH, a 100-year cycle has one fewer leap day than we'd get from + # pasting together 25 4-year cycles. + assert _DI100Y == 25 * _DI4Y - 1 def _ord2ymd(n): *************** *** 97,123 **** # Now n is the (non-negative) offset, in days, from January 1 of year, to ! # the desired date. First compute how many whole years precede the ! # desired date. Dividing by 365 gives an upper bound quickly, and it's ! # easy to show that it's either exact or one too large (note that this ! # relies on that n < _DI400Y; if we did this before factoring out a close ! # 400-year boundary, there's no bound on how far off n//365 could be). ! whole_years_preceding = n // 365 ! exact_days = _days_before_year(whole_years_preceding + 1) ! if exact_days > n: # estimate is too large ! exact_days -= _days_in_year(whole_years_preceding) ! whole_years_preceding -= 1 ! assert 0 <= exact_days <= n ! year += whole_years_preceding ! n -= exact_days # Now the year is correct, and n is the offset from January 1. We find ! # the month via another estimate that's either exact or one too large. month = min(n//29 + 1, 12) ! exact_days = _days_before_month(month, year) ! if exact_days > n: # estimate is too large month -= 1 ! exact_days -= _days_in_month(month, year) ! assert 0 <= exact_days <= n ! n -= exact_days # Now the year and month are correct, and n is the offset from the --- 111,143 ---- # Now n is the (non-negative) offset, in days, from January 1 of year, to ! # the desired date. Now compute how many 100-year cycles precede n. ! # Note that it's possible for n100 to equal 4! In that case 4 full ! # 100-year cycles precede the desired day, which implies the desired ! # day is December 31 at the end of a 400-year cycle. ! n100, n = divmod(n, _DI100Y) ! ! # Now compute how many 4-year cycles precede it. ! n4, n = divmod(n, _DI4Y) ! ! # And now how many single years. Again n1 can be 4, and again meaning ! # that the desired day is December 31 at the end of the 4-year cycle. ! n1, n = divmod(n, 365) ! ! year += n100 * 100 + n4 * 4 + n1 ! if n1 == 4 or n100 == 4: ! assert n == 0 ! return year-1, 12, 31 # Now the year is correct, and n is the offset from January 1. We find ! # the month via an estimate that's either exact or one too large. ! leapyear = n1 == 3 and (n4 != 24 or n100 == 3) ! assert leapyear == _is_leap(year) month = min(n//29 + 1, 12) ! preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear) ! if preceding > n: # estimate is too large month -= 1 ! preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear) ! assert 0 <= preceding <= n ! n -= preceding # Now the year and month are correct, and n is the offset from the From jvr@users.sourceforge.net Mon Mar 4 10:31:35 2002 From: jvr@users.sourceforge.net (Just van Rossum) Date: Mon, 04 Mar 2002 02:31:35 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/cg CGStubLib,1.2,1.3 CGStubLib.exp,1.2,1.3 _CGmodule.c,1.4,1.5 cgsupport.py,1.3,1.4 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cg In directory usw-pr-cvs1:/tmp/cvs-serv7812 Modified Files: CGStubLib CGStubLib.exp _CGmodule.c cgsupport.py Log Message: Added ClipCGContextToRegion() from Quickdraw.h. Index: CGStubLib =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/CGStubLib,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 Binary files /tmp/cvsIKKY4o and /tmp/cvs6JauSD differ Index: CGStubLib.exp =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/CGStubLib.exp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** CGStubLib.exp 2 Mar 2002 10:20:44 -0000 1.2 --- CGStubLib.exp 4 Mar 2002 10:31:32 -0000 1.3 *************** *** 58,59 **** --- 58,60 ---- CreateCGContextForPort SyncCGContextOriginWithPort + ClipCGContextToRegion Index: _CGmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/_CGmodule.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** _CGmodule.c 2 Mar 2002 10:20:44 -0000 1.4 --- _CGmodule.c 4 Mar 2002 10:31:32 -0000 1.5 *************** *** 1130,1133 **** --- 1130,1150 ---- } + static PyObject *CGContextRefObj_ClipCGContextToRegion(CGContextRefObject *_self, PyObject *_args) + { + PyObject *_res = NULL; + Rect portRect; + RgnHandle region; + if (!PyArg_ParseTuple(_args, "O&O&", + PyMac_GetRect, &portRect, + ResObj_Convert, ®ion)) + return NULL; + ClipCGContextToRegion(_self->ob_itself, + &portRect, + region); + Py_INCREF(Py_None); + _res = Py_None; + return _res; + } + static PyMethodDef CGContextRefObj_methods[] = { {"CGContextSaveGState", (PyCFunction)CGContextRefObj_CGContextSaveGState, 1, *************** *** 1245,1248 **** --- 1262,1267 ---- {"SyncCGContextOriginWithPort", (PyCFunction)CGContextRefObj_SyncCGContextOriginWithPort, 1, "(CGrafPtr port) -> None"}, + {"ClipCGContextToRegion", (PyCFunction)CGContextRefObj_ClipCGContextToRegion, 1, + "(Rect portRect, RgnHandle region) -> None"}, {NULL, NULL, 0} }; Index: cgsupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/cgsupport.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** cgsupport.py 2 Mar 2002 10:20:44 -0000 1.3 --- cgsupport.py 4 Mar 2002 10:31:32 -0000 1.4 *************** *** 19,22 **** --- 19,23 ---- CGrafPtr = OpaqueByValueType("CGrafPtr", "GrafObj") + RgnHandle = OpaqueByValueType("RgnHandle", "ResObj") # Create the type objects *************** *** 283,286 **** --- 284,296 ---- ) CGContextRef_methods.append(f) + + # manual method, lives in Quickdraw.h + f = Method(void, 'ClipCGContextToRegion', + (CGContextRef, 'ctx', InMode), + (Rect, 'portRect', InMode), + (RgnHandle, 'region', InMode), + ) + CGContextRef_methods.append(f) + CreateCGContextForPort_body = """\ From tim.one@comcast.net Mon Mar 4 10:36:51 2002 From: tim.one@comcast.net (Tim Peters) Date: Mon, 04 Mar 2002 05:36:51 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.28,1.29 In-Reply-To: <3C834457.ECC484F2@lemburg.com> Message-ID: [M.-A. Lemburg] > Looks a lot like what I do in mxDateTime.c :-) The key difference is that the Dates.py Gregorian algorithms were loop-free, no matter how large or small the year, even if the year requires a million bits to express (although not even Guido may live long enough to verify that in person ). From mal@lemburg.com Mon Mar 4 11:07:46 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Mon, 04 Mar 2002 12:07:46 +0100 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetimedatetime.py,1.28,1.29 References: Message-ID: <3C835582.23FE9B1A@lemburg.com> Tim Peters wrote: > > [M.-A. Lemburg] > > Looks a lot like what I do in mxDateTime.c :-) > > The key difference is that the Dates.py Gregorian algorithms were loop-free, > no matter how large or small the year, even if the year requires a million > bits to express (although not even Guido may live long enough to verify that > in person ). Oh, the mxDateTime algorithm is loop-free in a sense as well: the correction does at most 3 iterations, the month finder at most 12 iterations. I'll have a look at yours, though. Perhaps I can make the algorithms a bit faster ;-) (oh, I like competition). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From bwarsaw@users.sourceforge.net Mon Mar 4 13:20:04 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 04 Mar 2002 05:20:04 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0279.txt,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv16151 Modified Files: pep-0279.txt Log Message: Latest update from Raymond D. Hettinger. Spell checking applied. Made code samples self-consistent, and also consistent with Python style guide w.r.t. spaces around function arguments. Index: pep-0279.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0279.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** pep-0279.txt 7 Feb 2002 12:08:12 -0000 1.4 --- pep-0279.txt 4 Mar 2002 13:20:02 -0000 1.5 *************** *** 3,7 **** Version: $Revision$ Last-Modified: $Date$ ! Author: othello@javanet.com (Raymond D. Hettinger) Status: Draft Type: Standards Track --- 3,7 ---- Version: $Revision$ Last-Modified: $Date$ ! Author: python@rcn.com (Raymond D. Hettinger) Status: Draft Type: Standards Track *************** *** 14,19 **** This PEP introduces four orthogonal (not mutually exclusive) ideas ! for enhancing the generators as introduced in Python version 2.2 ! [1]. The goal is to increase the convenience, utility, and power of generators. --- 14,19 ---- This PEP introduces four orthogonal (not mutually exclusive) ideas ! for enhancing the generators introduced in Python version 2.2 [1]. ! The goal is to increase the convenience, utility, and power of generators. *************** *** 33,37 **** establishing a common iterable interface for mappings, sequences, and file objects. In the case of mappings and file objects, lazy ! evaluation was made available. The next steps in the evolution of generators are: --- 33,37 ---- establishing a common iterable interface for mappings, sequences, and file objects. In the case of mappings and file objects, lazy ! evaluation became the norm. The next steps in the evolution of generators are: *************** *** 53,57 **** 4. Add a generator method to enable exceptions to be passed to a generator. Currently, there is no clean method for triggering ! exceptions from outside the generator. All of the suggestions are designed to take advantage of the --- 53,58 ---- 4. Add a generator method to enable exceptions to be passed to a generator. Currently, there is no clean method for triggering ! exceptions from outside the generator. Also, generator exception ! passing helps mitigate the try/finally prohibition for generators. All of the suggestions are designed to take advantage of the *************** *** 61,73 **** generators become final and are not imported from __future__. ! SourceForge contains a working, pure Python simulation of every ! feature proposed in this PEP [8]. SourceForge also has a separate ! file with a simulation test suite and working source code for the ! examples listed used in this PEP [9]. Specification for new built-ins: ! def xfilter( pred, gen ): ''' xfilter(...) --- 62,83 ---- generators become final and are not imported from __future__. ! ! ! Reference Implementation ! ! There is not currently a CPython implementation; however, a simulation ! module written in pure Python is available on SourceForge [8]. The ! simulation covers every feature proposed in this PEP and is meant ! to allow direct experimentation with the proposals. ! ! There is also a module [9] with working source code for all of the ! examples used in this PEP. It serves as a test suite for the simulator ! and it documents how each of the new features works in practice. ! Specification for new built-ins: ! def xfilter(pred, gen): ''' xfilter(...) *************** *** 87,91 **** yield i ! def xmap( fun, *collections ): ''' xmap(...) --- 97,101 ---- yield i ! def xmap(fun, *collections): ### Code from Python Cookbook [6] ''' xmap(...) *************** *** 97,109 **** corresponding item of each collection, substituting None for missing values when not all collections have the same length. ! If the function is None, return a list of the items of the ! collection (or a list of tuples if more than one collection). ''' gens = map(iter, collections) values_left = [1] def values(): ! # Emulate map behaviour, i.e. shorter ! # sequences are padded with None when ! # they run out of values. values_left[0] = 0 for i in range(len(gens)): --- 107,118 ---- corresponding item of each collection, substituting None for missing values when not all collections have the same length. ! If the function is None, return an iterator of the items of the ! collection (or an iterator of tuples if more than one collection). ''' gens = map(iter, collections) values_left = [1] def values(): ! # Emulate map behavior by padding sequences with None ! # when they run out of values. values_left[0] = 0 for i in range(len(gens)): *************** *** 124,128 **** yield fun(*args) ! def xzip( *collections ): ### Code from Python Cookbook [6] ''' xzip(...) --- 133,137 ---- yield fun(*args) ! def xzip(*collections): ''' xzip(...) *************** *** 136,142 **** gens = map(iter, collections) while 1: ! yield tuple( [g.next() for g in gens] ) ! def indexed( collection, cnt=0, limit=None ): 'Generates an indexed series: (0,seqn[0]), (1,seqn[1]) ...' gen = iter(collection) --- 145,151 ---- gens = map(iter, collections) while 1: ! yield tuple([g.next() for g in gens]) ! def indexed(collection, cnt=0, limit=None): 'Generates an indexed series: (0,seqn[0]), (1,seqn[1]) ...' gen = iter(collection) *************** *** 145,148 **** --- 154,158 ---- cnt += 1 + Note A: PEP 212 Loop Counter Iteration [2] discussed several proposals for achieving indexing. Some of the proposals only work *************** *** 150,161 **** xrange, sequence, or iterable object. Also, those proposals were presented and evaluated in the world prior to Python 2.2 which did ! not include generators. - Note B: An alternate, simplified definition of indexed was proposed: ! def indexed( collection, cnt=0, limit=sys.maxint ): ! 'Generates an indexed series: (0,seqn[0]), (1,seqn[1]) ...' ! return xzip( xrange(cnt,limit), collection ) Specification for Generator Comprehensions: --- 160,199 ---- xrange, sequence, or iterable object. Also, those proposals were presented and evaluated in the world prior to Python 2.2 which did ! not include generators. As a result, the generator-less version in ! PEP 212 had the disadvantage of consuming memory with a giant list ! of tuples. The generator version presented here is fast and light, ! works with all iterables, and allows users to abandon the sequence ! in mid-stream. ! Note B: An alternate, simplified definition of indexed is: + def indexed(collection, cnt=0, limit=sys.maxint): + 'Generates an indexed series: (0,seqn[0]), (1,seqn[1]) ...' + return xzip( xrange(cnt,limit), collection ) + + + Note C: As it stands, the Python code for xmap is slow. The actual + implementation of the functions should be written in C for speed. + The pure Python code listed above is meant only to specify how the + functions would behave, in particular that they should as closely as + possible emulate their non-lazy counterparts. + + + Note D: Almost all of the PEP reviewers welcomed these functions but were + divided as to whether they should be built-ins or in a separate module. + The main argument for a separate module was to slow the rate of language + inflation. The main argument for built-ins was that these functions are + destined to be part of a core programming style, applicable to any object + with an iterable interface. Just as zip() solves the problem of looping + over multiple sequences, the indexed() function solves the loop counter + problem. Likewise, the x-functions solve the problem of applying + functional constructs without forcing the evaluation of an entire sequence. + + If only one built-in were allowed, then indexed() is the most important + general purpose tool, solving the broadest class of problems while + improving program brevity, clarity and reliability. + + Specification for Generator Comprehensions: *************** *** 165,179 **** g = [yield (len(line),line) for line in file if len(line)>5] This would be implemented as if it had been written: ! class __Temp: ! def __iter__(self): ! for line in file: ! if len(line) > 5: ! yield (len(line), line) ! g = __Temp() ! Note A: There is some debate about whether the enclosing brackets should be part of the syntax for generator comprehensions. On the plus side, it neatly parallels list comprehensions and would be --- 203,218 ---- g = [yield (len(line),line) for line in file if len(line)>5] + print g.next() This would be implemented as if it had been written: ! def __temp(self): ! for line in file: ! if len(line) > 5: ! yield (len(line), line) ! g = __temp() ! print g.next() ! Note A: There is some discussion about whether the enclosing brackets should be part of the syntax for generator comprehensions. On the plus side, it neatly parallels list comprehensions and would be *************** *** 186,204 **** minus side, the brackets may falsely suggest that the whole expression returns a list. Most of the feedback received to date ! indicates that brackets do not make a false suggestion and are ! in fact helpful. ! ! Note B: An iterable instance is returned by the above code. The ! purpose is to allow the object to be re-started and looped-over ! multiple times. This accurately mimics the behavior of list ! comprehensions. As a result, the following code (provided by Oren ! Tirosh) works equally well with or without 'yield': ! ! letters = [yield chr(i) for i in xrange(ord('a'),ord('z')+1)] ! digits = [yield str(i) for i in xrange(10)] ! letdig = [yield l+d for l in letters for d in digits] ! Note C: List comprehensions expose their looping variable and ! leave the variable in the enclosing scope. The code, [str(i) for i in range(8)] leaves 'i' set to 7 in the scope where the comprehension appears. This behavior is by design and reflects an --- 225,232 ---- minus side, the brackets may falsely suggest that the whole expression returns a list. Most of the feedback received to date ! indicates that brackets are helpful and not misleading. ! Note B: List comprehensions expose their looping variable and ! leave that variable in the enclosing scope. The code, [str(i) for i in range(8)] leaves 'i' set to 7 in the scope where the comprehension appears. This behavior is by design and reflects an *************** *** 216,222 **** is not in a defined state on the line immediately following the list comprehension. It does not come into existence until ! iteration starts. Since several generators may be running at ! once, there are potentially multiple, unequal instances of 'i' at ! any one time. --- 244,249 ---- is not in a defined state on the line immediately following the list comprehension. It does not come into existence until ! iteration starts (possibly never). ! *************** *** 230,234 **** print x ! 2. Let the .next() method take a value to pass to generator as in: g = mygen() --- 257,261 ---- print x ! 2. Let the .next() method take a value to pass to the generator as in: g = mygen() *************** *** 237,245 **** g.next(2) # '2' is bound to 'x' in mygen(), then printed ! The control flow is unchanged by this proposal. The only change ! is that a value can be sent into the generator. By analogy, ! consider the quality improvement from GOSUB (which had no argument ! passing mechanism) to modern procedure calls (which can pass in ! arguments and return values). Most of the underlying machinery is already in place, only the --- 264,272 ---- g.next(2) # '2' is bound to 'x' in mygen(), then printed ! The control flow of 'yield' and 'next' is unchanged by this proposal. ! The only change is that a value can be sent into the generator. ! By analogy, consider the quality improvement from GOSUB (which had ! no argument passing mechanism) to modern procedure calls (which can ! pass in arguments and return values). Most of the underlying machinery is already in place, only the *************** *** 264,273 **** threading module with its attendant mutexes, semaphores, and data queues. A class-based approach competes well when there are no ! complex execution states or variable states. When the complexity ! increases, generators with parameter passing are much simpler because they automatically save state (unlike classes which must ! explicitly save the variable and execution state in instance ! variables). Example of a Complex Consumer --- 291,302 ---- threading module with its attendant mutexes, semaphores, and data queues. A class-based approach competes well when there are no ! complex execution states or variable states. However, when the ! complexity increases, generators with parameter passing are much simpler because they automatically save state (unlike classes which must ! explicitly save the variable and execution state in instance variables). + Note A: This proposal changes 'yield' from a statement to an + expression with binding and precedence similar to lambda. + Example of a Complex Consumer *************** *** 285,289 **** cum = [] if appendOrOverwrite == 'w+': ! cum.extend( packages[packagename] ) try: while 1: --- 314,318 ---- cum = [] if appendOrOverwrite == 'w+': ! cum.extend(packages[packagename]) try: while 1: *************** *** 292,300 **** except FlushStream: packages[packagename] = cum ostream = filelike('mydest','w') # Analogous to file.open(name,flag) ostream.next() # Advance to the first yield ostream.next(firstdat) # Analogous to file.write(dat) ostream.next(seconddat) ! ostream.throw( FlushStream ) # This feature proposed below --- 321,330 ---- except FlushStream: packages[packagename] = cum + ostream = filelike('mydest','w') # Analogous to file.open(name,flag) ostream.next() # Advance to the first yield ostream.next(firstdat) # Analogous to file.write(dat) ostream.next(seconddat) ! ostream.throw(FlushStream) # This feature proposed below *************** *** 302,309 **** Loop over the picture files in a directory, shrink them ! one-at-a-time to thumbnail size using PIL [7], and send them to a lazy consumer. That consumer is responsible for creating a large ! blank image, accepting thumbnails one-at-a-time and placing them ! in a 5x3 grid format onto the blank image. Whenever the grid is full, it writes-out the large image as an index print. A FlushStream exception indicates that no more thumbnails are --- 332,339 ---- Loop over the picture files in a directory, shrink them ! one at a time to thumbnail size using PIL [7], and send them to a lazy consumer. That consumer is responsible for creating a large ! blank image, accepting thumbnails one at a time and placing them ! in a 5 by 3 grid format onto the blank image. Whenever the grid is full, it writes-out the large image as an index print. A FlushStream exception indicates that no more thumbnails are *************** *** 312,327 **** ! Example of a Producer and Consumer Used Together in a Pipelike Fashion ! 'Analogy to: source | upper | sink' sink = sinkgen() sink.next() for word in source(): ! sink.next( word.upper() ) Specification for Generator Exception Passing: ! Add a .throw(exception) method to the resulting generator as in: def mygen(): --- 342,358 ---- ! Example of a Producer and Consumer Used Together in a Pipe-like Fashion ! 'Analogy to Linux style pipes: source | upper | sink' sink = sinkgen() sink.next() for word in source(): ! sink.next(word.upper()) ! Specification for Generator Exception Passing: ! Add a .throw(exception) method to the generator interface: def mygen(): *************** *** 337,346 **** g.throw(FlushStream) ! There is no existing work around for triggering an exception inside a generator. This is a true deficiency. It is the only ! case in Python where active code cannot be excepted to or through. Even if the .next(arg) proposal is not adopted, we should add the .throw() method. Note A: The name of the throw method was selected for several reasons. Raise is a keyword and so cannot be used as a method --- 368,383 ---- g.throw(FlushStream) ! There is no existing work-around for triggering an exception inside a generator. This is a true deficiency. It is the only ! case in Python where active code cannot be excepted to or through. Even if the .next(arg) proposal is not adopted, we should add the .throw() method. + Generator exception passing also helps address an intrinsic limitation + on generators, the prohibition against their using try/finally to + trigger clean-up code [1]. Without .throw(), the current work-around + forces the resolution or clean-up code to be moved outside the generator. + + Note A: The name of the throw method was selected for several reasons. Raise is a keyword and so cannot be used as a method *************** *** 351,360 **** already associated with exceptions in other languages. ! Note B: The throw syntax should exactly match raise's syntax including: ! raise string g.throw(string) ! raise string, data g.throw(string,data) ! raise class, instance g.throw(class,instance) ! raise instance g.throw(instance) ! raise g.throw() --- 388,461 ---- already associated with exceptions in other languages. ! Alternative method names were considered: resolve(), signal(), ! genraise(), raiseinto(), and flush(). None of these seem to fit ! as well as throw(). ! ! ! Note B: The throw syntax should exactly match raise's syntax: ! ! throw([expression, [expression, [expression]]]) ! ! Accordingly, it should be implemented to handle all of the following: ! ! raise string g.throw(string) ! raise string, data g.throw(string,data) ! raise class, instance g.throw(class,instance) ! raise instance g.throw(instance) ! raise g.throw() ! ! ! Discussion of Restartability: ! ! Inside for-loops, generators are not substitutable for lists unless they ! are accessed only once. A second access only works for restartable ! objects like lists, dicts, objects defined with __getitem__, and ! xrange objects. Generators are not the only objects which are not ! restartable. Other examples of non-restartable sequences include file ! objects, xreadlines objects, and the result of iter(callable,sentinel). ! ! Since the proposed built-in functions return generators, they are also ! non-restartable. As a result, 'xmap' is not substitutable for 'map' in ! the following example: ! ! alphabet = map(chr, xrange(ord('a'), ord('z')+1)) ! twoletterwords = [a+b for a in alphabet for b in alphabet] ! ! Since generator comprehensions also return generators, they are not ! restartable. Consequently, they are not substitutable for list ! comprehensions in the following example: ! ! digits = [str(i) for i in xrange(10)] ! alphadig = [a+d for a in 'abcdefg' for d in digits] ! ! To achieve substitutabity, generator comprehensions and x-functions ! can be implemented in a way that supports restarts. PEP 234 [4] ! explicitly states that restarts are to be supported through repeated ! calls to iter(). With that guidance, it is easy to add restartability ! to generator comprehensions using a simple wrapper class around the ! generator function and modifying the implementation above to return: ! ! g = Restartable(__temp) # instead of g = __temp() ! ! Restartable is a simple (12 line) class which calls the generator function ! to create a new, re-wound generator whenever iter() requests a restart. ! Calls to .next() are simply forwarded to the generator. The Python source ! code for the Restartable class can found in the PEP 279 simulator [8]. ! An actual implementation in C can achieve re-startability directly and ! would not need the slow class wrapper used in the pure Python simulation. ! ! The XLazy library [10] shows how restarts can be implemented for xmap, ! xfilter, and xzip. ! ! The upside of adding restart capability is that more list comprehensions ! can be made lazy and save memory by adding 'yield'. Likewise, ! more expressions that use map, filter, and zip can be made lazy just by ! adding 'x'. ! ! A possible downside is that x-functions have no control over whether their ! inputs are themselves restartable. With non-restartable inputs like ! generators or files, an x-function restart will not produce a meaningful ! result. ! *************** *** 370,390 **** http://python.sourceforge.net/peps/pep-0202.html ! [4] There have been several discussion on comp.lang.python which helped ! tease out these proposals: ! ! Indexed Function ! http://groups.google.com/groups?hl=en&th=33f778d92dd5720a ! ! Xmap, Xfilter, Xzip and Two-way Generator Communication ! http://groups.google.com/groups?hl=en&th=b5e576b02894bb04&rnum=1 ! ! Two-way Generator Communication -- Revised Version ! http://groups.google.com/groups?hl=en&th=cb1d86e68850c592&rnum=1 ! ! Generator Comprehensions ! http://groups.google.com/groups?hl=en&th=215e6e5a7bfd526&rnum=2 ! ! Discussion Draft of this PEP ! http://groups.google.com/groups?hl=en&th=df8b5e7709957eb7 [5] Dr. David Mertz's draft column for Charming Python. --- 471,476 ---- http://python.sourceforge.net/peps/pep-0202.html ! [4] PEP 234 Iterators ! http://python.sourceforge.net/peps/pep-0234.html [5] Dr. David Mertz's draft column for Charming Python. *************** *** 404,407 **** --- 490,496 ---- http://sourceforge.net/tracker/download.php?group_id=5470&atid=305470&file_id=17412&aid=513756 + [10] Oren Tirosh's XLazy library with re-startable x-functions is at: + http://www.tothink.com/python/dataflow/ + Copyright From fdrake@users.sourceforge.net Mon Mar 4 14:36:18 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 06:36:18 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime .cvsignore,NONE,1.1 Makefile,NONE,1.1 datetime.c,NONE,1.1 setup.py,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv7708 Added Files: .cvsignore Makefile datetime.c setup.py Log Message: Tell CVS to ignore the build/ directory created by distutils. --- NEW FILE: .cvsignore --- build --- NEW FILE: Makefile --- PYTHON=python2.2 default: check all: _datetime.so _datetime.so: datetime.c $(PYTHON) setup.py build_ext -i check: _datetime.so $(PYTHON) test_datetime.py test: check --- NEW FILE: datetime.c --- /* C implementation for the date/time type documented at * */ #include "Python.h" #include "modsupport.h" static PyMethodDef functions[] = { {NULL, NULL, 0, NULL} }; void init_datetime(void) { PyObject *m = Py_InitModule3("_datetime", functions, "Fast implementation of the datetime type."); PyModule_AddIntConstant(m, "MINYEAR", 1); PyModule_AddIntConstant(m, "MAXYEAR", 9999); } --- NEW FILE: setup.py --- from distutils.core import setup, Extension setup(name="datetime", version = "0.1", ext_modules=[Extension("_datetime", ["datetime.c"])]) From gvanrossum@users.sourceforge.net Mon Mar 4 15:34:31 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Mar 2002 07:34:31 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.39,1.40 test_datetime.py,1.24,1.25 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv32033 Modified Files: datetime.py test_datetime.py Log Message: Disallow adding or sutracting plain numbers; there's no agreement whether the number should be interpreted as days or seconds. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.39 retrieving revision 1.40 diff -C2 -d -r1.39 -r1.40 *** datetime.py 4 Mar 2002 10:17:41 -0000 1.39 --- datetime.py 4 Mar 2002 15:34:29 -0000 1.40 *************** *** 352,381 **** self.__seconds + other.__seconds, self.__microseconds + other.__microseconds) ! if isinstance(other, (int, long)): ! return timedelta(self.__days, ! self.__seconds + other, ! self.__microseconds) ! if isinstance(other, float): ! sign = 1 ! if other < 0: ! sign, other = -1, -other ! frac, whole = _math.modf(other) ! us = int(frac * 1e6 + 0.5) ! assert 0 <= us <= 1000000 # if 1e6, constructor will normalize ! days, seconds = divmod(whole, 24*3600) ! return timedelta(self.__days + sign * int(days), ! self.__seconds + sign * int(seconds), ! self.__microseconds + sign * us) ! return NotImplemented __radd__ = __add__ def __sub__(self, other): ! if isinstance(other, (timedelta, int, long, float)): return self + -other return NotImplemented def __rsub__(self, other): ! if isinstance(other, (timedelta, int, long, float)): return -self + other return NotImplemented --- 352,367 ---- self.__seconds + other.__seconds, self.__microseconds + other.__microseconds) ! raise TypeError ! # XXX Should be 'return NotImplemented', but there's a bug in 2.2... __radd__ = __add__ def __sub__(self, other): ! if isinstance(other, timedelta): return self + -other return NotImplemented def __rsub__(self, other): ! if isinstance(other, timedelta): return -self + other return NotImplemented *************** *** 437,441 **** __repr__, __str__ __cmp__, __hash__ ! __add__, __radd__, __sub__ (add/radd only with timedelta or numeric arg) Methods: --- 423,427 ---- __repr__, __str__ __cmp__, __hash__ ! __add__, __radd__, __sub__ (add/radd only with timedelta arg) Methods: *************** *** 670,677 **** def __add__(self, other): ! """Add a datetime to a timedelta. ! ! An int/long/float argument is also allowed, interpreted as seconds. ! """ if isinstance(other, timedelta): t = tmxxx(self.__year, --- 656,660 ---- def __add__(self, other): ! "Add a datetime to a timedelta." if isinstance(other, timedelta): t = tmxxx(self.__year, *************** *** 686,694 **** t.microsecond, self.__tzoffset) return result ! elif isinstance(other, (int, long)): ! return self + timedelta(0, other) ! elif isinstance(other, float): ! return self + (timedelta(0) + other) ! return NotImplemented __radd__ = __add__ --- 669,674 ---- t.microsecond, self.__tzoffset) return result ! raise TypeError ! # XXX Should be 'return NotImplemented', but there's a bug in 2.2... __radd__ = __add__ *************** *** 699,703 **** An int/long/float argument is also allowed, interpreted as seconds. """ ! if isinstance(other, (timedelta, int, long, float)): return self + -other if isinstance(other, datetime): --- 679,683 ---- An int/long/float argument is also allowed, interpreted as seconds. """ ! if isinstance(other, timedelta): return self + -other if isinstance(other, datetime): Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.24 retrieving revision 1.25 diff -C2 -d -r1.24 -r1.25 *** test_datetime.py 4 Mar 2002 06:10:15 -0000 1.24 --- test_datetime.py 4 Mar 2002 15:34:29 -0000 1.25 *************** *** 192,216 **** self.assertEqual(a//10, timedelta(0, 7*24*360)) self.assertEqual(a//3600000, timedelta(0, 0, 7*24*1000)) ! # Add/sub ints, longs, floats ! self.assertEqual(a + 7*24*3600, timedelta(14)) ! self.assertEqual(a - 24*3600, timedelta(6)) ! self.assertEqual(a + 100, timedelta(7, 100)) ! self.assertEqual(a - 100, timedelta(6, 24*3600-100)) ! self.assertEqual(100 + a, a + 100) ! self.assertEqual(100 - a, 100 + -a) ! self.assertEqual(a + 7*24*3600L, timedelta(14)) ! self.assertEqual(a - 24*3600L, timedelta(6)) ! self.assertEqual(a + 100L, timedelta(7, 100)) ! self.assertEqual(a - 100L, timedelta(6, 24*3600-100)) ! self.assertEqual(100L + a, a + 100L) ! self.assertEqual(100L - a, 100L + -a) ! self.assertEqual(c + 0.001, timedelta(0, 0, 2000)) ! self.assertEqual(c - 0.0001, timedelta(0, 0, 900)) ! self.assertEqual(b + 1.1, timedelta(0, 61, 100000)) ! self.assertEqual(b - 1.1, timedelta(0, 58, 900000)) ! self.assertEqual(a + (1e6 + 1e-6), timedelta(7, 1000000, 1)) ! self.assertEqual(a - (1e6 + 1e-6), timedelta(7, -1000000, -1)) ! self.assertEqual(1.1 + a, a + 1.1) ! self.assertEqual(1.1 - a, 1.1 + -a) def test_computations(self): --- 192,201 ---- self.assertEqual(a//10, timedelta(0, 7*24*360)) self.assertEqual(a//3600000, timedelta(0, 0, 7*24*1000)) ! # Add/sub ints, longs, floats should be illegal ! for i in 1, 1L, 1.0: ! self.assertRaises(TypeError, lambda: a+i) ! self.assertRaises(TypeError, lambda: a-i) ! self.assertRaises(TypeError, lambda: i+a) ! self.assertRaises(TypeError, lambda: i-a) def test_computations(self): *************** *** 261,274 **** self.assertEqual(a - (week + day + hour + millisec), (((a - week) - day) - hour) - millisec) ! # Add/sub ints, longs, floats ! self.assertEqual(a + 12, a + timedelta(0, 12)) ! self.assertEqual(a - 12, a - timedelta(0, 12)) ! self.assertEqual(100 + a, a + 100) ! self.assertEqual(a + 12L, a + timedelta(0, 12)) ! self.assertEqual(a - 12L, a - timedelta(0, 12)) ! self.assertEqual(100L + a, a + 100L) ! self.assertEqual(a + 0.001, a + timedelta(0, 0, 1000)) ! self.assertEqual(a - 0.001, a - timedelta(0, 0, 1000)) ! self.assertEqual(0.1 + a, a + 0.1) def test_weekday(self): --- 246,255 ---- self.assertEqual(a - (week + day + hour + millisec), (((a - week) - day) - hour) - millisec) ! # Add/sub ints, longs, floats should be illegal ! for i in 1, 1L, 1.0: ! self.assertRaises(TypeError, lambda: a+i) ! self.assertRaises(TypeError, lambda: a-i) ! self.assertRaises(TypeError, lambda: i+a) ! self.assertRaises(TypeError, lambda: i-a) def test_weekday(self): From tim_one@users.sourceforge.net Mon Mar 4 18:32:10 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 10:32:10 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.25,1.26 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv25314 Modified Files: test_datetime.py Log Message: test_tz_independent_comparing(): Change assert_(x==y) to assertEqual(). Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** test_datetime.py 4 Mar 2002 15:34:29 -0000 1.25 --- test_datetime.py 4 Mar 2002 18:32:07 -0000 1.26 *************** *** 56,60 **** dt1 = datetime.new(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60) dt2 = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) ! self.assert_(dt1 == dt2) dt2 += us self.assertEqual(dt2 - dt1, us) --- 56,60 ---- dt1 = datetime.new(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60) dt2 = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) ! self.assertEqual(dt1, dt2) dt2 += us self.assertEqual(dt2 - dt1, us) From tim_one@users.sourceforge.net Mon Mar 4 18:49:10 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 10:49:10 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.40,1.41 test_datetime.py,1.26,1.27 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv29066 Modified Files: datetime.py test_datetime.py Log Message: datetime.__add__: raise OverflowError if result out of range, meaning specifcally that the result year is out of range. New test test_overflow. Note: tmxxx intentionally ignores year out of range, and should ignore it. Else, e.g., timezone adjustments done for internal datetime purposes of hashing or comparing could raise bogus OverflowErrors at the boundaries: some legit datetime objects can't be converted to legit UTC datetimes. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.40 retrieving revision 1.41 diff -C2 -d -r1.40 -r1.41 *** datetime.py 4 Mar 2002 15:34:29 -0000 1.40 --- datetime.py 4 Mar 2002 18:49:07 -0000 1.41 *************** *** 655,658 **** --- 655,663 ---- # Computations + def _checkOverflow(self, year): + if not MINYEAR <= year <= MAXYEAR: + raise OverflowError("datetime +/-: result year %d not in %d..%d" % + (year, MINYEAR, MAXYEAR)) + def __add__(self, other): "Add a datetime to a timedelta." *************** *** 665,668 **** --- 670,674 ---- self.__second + other.seconds, self.__microsecond + other.microseconds) + self._checkOverflow(t.year) result = datetime.new(t.year, t.month, t.day, t.hour, t.minute, t.second, Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** test_datetime.py 4 Mar 2002 18:32:07 -0000 1.26 --- test_datetime.py 4 Mar 2002 18:49:07 -0000 1.27 *************** *** 253,256 **** --- 253,271 ---- self.assertRaises(TypeError, lambda: i-a) + def test_overflow(self): + us = timedelta(microseconds=1) + mus = - us + + dt = datetime.new(MINYEAR, 1, 1, microsecond=1) + dt -= us # no problem + self.assertRaises(OverflowError, dt.__sub__, us) + self.assertRaises(OverflowError, dt.__add__, mus) + + dt = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998) + dt += us # no problem + self.assertRaises(OverflowError, dt.__add__, us) + self.assertRaises(OverflowError, dt.__sub__, mus) + + def test_weekday(self): for i in range(7): From tim_one@users.sourceforge.net Mon Mar 4 18:52:59 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 10:52:59 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.27,1.28 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv32541 Modified Files: test_datetime.py Log Message: I don't believe it: I checked in a file with trailing whitespace . Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** test_datetime.py 4 Mar 2002 18:49:07 -0000 1.27 --- test_datetime.py 4 Mar 2002 18:52:57 -0000 1.28 *************** *** 267,271 **** self.assertRaises(OverflowError, dt.__sub__, mus) - def test_weekday(self): for i in range(7): --- 267,270 ---- From gvanrossum@users.sourceforge.net Mon Mar 4 18:56:12 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Mar 2002 10:56:12 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.41,1.42 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv1528 Modified Files: datetime.py Log Message: Changes to timedelta() constructor: - allow floats - add keyword arguments milliseconds, minutes, hours, and weeks Also remove an outdated item from a comment Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.41 retrieving revision 1.42 diff -C2 -d -r1.41 -r1.42 *** datetime.py 4 Mar 2002 18:49:07 -0000 1.41 --- datetime.py 4 Mar 2002 18:56:10 -0000 1.42 *************** *** 290,297 **** - add, subtract timedelta - - add, subtract int/long/float seconds - unary plus, minus, abs - compare to timedelta ! - multiply, divide by int/long In addition, datetime supports subtraction of two datetime objects --- 290,296 ---- - add, subtract timedelta - unary plus, minus, abs - compare to timedelta ! - multiply, divide by int/long/float In addition, datetime supports subtraction of two datetime objects *************** *** 303,307 **** """ ! def __init__(self, days=0, seconds=0, microseconds=0): s, us = divmod(microseconds, 1000000) assert us >= 0 --- 302,323 ---- """ ! def __init__(self, days=0, seconds=0, microseconds=0, ! # XXX The following should only be used as keyword args: ! milliseconds=0, minutes=0, hours=0, weeks=0): ! # Normalize everything to days, seconds, microseconds ! days += weeks*7 ! seconds += minutes*60 + hours*3600 ! microseconds += milliseconds*1000 ! # Deal with floats ! # XXX Tim may rewrite this for accuracy :-) ! if isinstance(days, float): ! days, fraction = divmod(days, 1.0) ! if fraction: ! seconds += fraction*(24*3600) ! if isinstance(seconds, float): ! seconds, fraction = divmod(seconds, 1.0) ! if fraction: ! microseconds += fraction*1e6 ! # Propagate carry from us to s, from s to d s, us = divmod(microseconds, 1000000) assert us >= 0 *************** *** 310,320 **** d += days # d may be < 0 ! self.__days = d ! self.__seconds = s ! self.__microseconds = us def __repr__(self): if self.__microseconds: ! return "timedelta(%d, %d, %d)" % (self.__days, self.__seconds, self.__microseconds) --- 326,336 ---- d += days # d may be < 0 ! self.__days = int(d) ! self.__seconds = int(s) ! self.__microseconds = int(round(us)) def __repr__(self): if self.__microseconds: ! return "timedelta(days=%d, %d, %d)" % (self.__days, self.__seconds, self.__microseconds) From gvanrossum@users.sourceforge.net Mon Mar 4 19:09:15 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Mar 2002 11:09:15 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.28,1.29 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv5667 Modified Files: test_datetime.py Log Message: Add tests for: - keyword args to timedelta constructor - float args to timedelta constructor Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** test_datetime.py 4 Mar 2002 18:52:57 -0000 1.28 --- test_datetime.py 4 Mar 2002 19:09:12 -0000 1.29 *************** *** 198,201 **** --- 198,220 ---- self.assertRaises(TypeError, lambda: i+a) self.assertRaises(TypeError, lambda: i-a) + # Check keyword args to constructor + eq = self.assertEqual + td = timedelta + eq(td(1), td(days=1)) + eq(td(0, 1), td(seconds=1)) + eq(td(0, 0, 1), td(microseconds=1)) + eq(td(weeks=1), td(days=7)) + eq(td(days=1), td(hours=24)) + eq(td(hours=1), td(minutes=60)) + eq(td(minutes=1), td(seconds=60)) + eq(td(seconds=1), td(milliseconds=1000)) + eq(td(milliseconds=1), td(microseconds=1000)) + # Check float args to constructor + eq(td(weeks=1.0/7), td(days=1)) + eq(td(days=1.0/24), td(hours=1)) + eq(td(hours=1.0/60), td(minutes=1)) + eq(td(minutes=1.0/60), td(seconds=1)) + eq(td(seconds=0.001), td(milliseconds=1)) + eq(td(milliseconds=0.001), td(microseconds=1)) def test_computations(self): From gvanrossum@users.sourceforge.net Mon Mar 4 19:39:40 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Mar 2002 11:39:40 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.42,1.43 test_datetime.py,1.29,1.30 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv16311 Modified Files: datetime.py test_datetime.py Log Message: Add min, max and resolution to datetime class. This was proposed by s.keim in the Wiki. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.42 retrieving revision 1.43 diff -C2 -d -r1.42 -r1.43 *** datetime.py 4 Mar 2002 18:56:10 -0000 1.42 --- datetime.py 4 Mar 2002 19:39:38 -0000 1.43 *************** *** 790,793 **** --- 790,798 ---- + datetime.min = datetime(1, 1, 1, tzoffset=0) + datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999, tzoffset=0) + datetime.resolution = timedelta(microseconds=1) + + def _isoweek1monday(year): # Helper to calculate the day number of the Monday starting week 1 Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.29 retrieving revision 1.30 diff -C2 -d -r1.29 -r1.30 *** test_datetime.py 4 Mar 2002 19:09:12 -0000 1.29 --- test_datetime.py 4 Mar 2002 19:39:38 -0000 1.30 *************** *** 387,390 **** --- 387,396 ---- self.fail("Can't test utcctime()") + def test_resolution_info(self): + self.assert_(isinstance(datetime.min, datetime)) + self.assert_(isinstance(datetime.max, datetime)) + self.assert_(isinstance(datetime.resolution, timedelta)) + self.assert_(datetime.max > datetime.min) + def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') From tim_one@users.sourceforge.net Mon Mar 4 19:51:35 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 11:51:35 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.43,1.44 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv19454 Modified Files: datetime.py Log Message: timedelta.__init__(): Extensive rework for fp accuracy, and to ease the overflow-checking burdens when recoded in C. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.43 retrieving revision 1.44 diff -C2 -d -r1.43 -r1.44 *** datetime.py 4 Mar 2002 19:39:38 -0000 1.43 --- datetime.py 4 Mar 2002 19:51:32 -0000 1.44 *************** *** 305,332 **** # XXX The following should only be used as keyword args: milliseconds=0, minutes=0, hours=0, weeks=0): ! # Normalize everything to days, seconds, microseconds ! days += weeks*7 ! seconds += minutes*60 + hours*3600 ! microseconds += milliseconds*1000 ! # Deal with floats ! # XXX Tim may rewrite this for accuracy :-) ! if isinstance(days, float): ! days, fraction = divmod(days, 1.0) ! if fraction: ! seconds += fraction*(24*3600) ! if isinstance(seconds, float): ! seconds, fraction = divmod(seconds, 1.0) ! if fraction: ! microseconds += fraction*1e6 # Propagate carry from us to s, from s to d s, us = divmod(microseconds, 1000000) ! assert us >= 0 d, s = divmod(s + seconds, 24*3600) ! assert s >= 0 d += days # d may be < 0 self.__days = int(d) self.__seconds = int(s) ! self.__microseconds = int(round(us)) def __repr__(self): --- 305,336 ---- # XXX The following should only be used as keyword args: milliseconds=0, minutes=0, hours=0, weeks=0): ! # Normalize everything to days, seconds, microseconds. ! # Convert everything to float first, else overflow-checking in C ! # is going to be a nightmare. ! days += weeks*7. ! seconds += minutes*60. + hours*3600. ! microseconds += milliseconds*1000. ! # Get rid of all fractions. ! dayfrac, days = _math.modf(days) ! daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.)) ! secondsfrac, seconds = _math.modf(seconds) ! seconds += daysecondswhole ! secondsfrac += daysecondsfrac ! microseconds += secondsfrac*1e6 ! microseconds = round(microseconds) ! assert _math.modf(days)[0] == 0.0 ! assert _math.modf(seconds)[0] == 0.0 ! assert _math.modf(microseconds)[0] == 0.0 # Propagate carry from us to s, from s to d s, us = divmod(microseconds, 1000000) ! assert us == int(us) and 0 <= us < 1000000 d, s = divmod(s + seconds, 24*3600) ! assert s == int(s) and 0 <= s < 24*3600 d += days + assert d == long(d) # d may be < 0 self.__days = int(d) self.__seconds = int(s) ! self.__microseconds = int(us) def __repr__(self): From tim.one@comcast.net Mon Mar 4 20:09:00 2002 From: tim.one@comcast.net (Tim Peters) Date: Mon, 04 Mar 2002 15:09:00 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetimedatetime.py,1.28,1.29 In-Reply-To: <3C835582.23FE9B1A@lemburg.com> Message-ID: [MAL] > Oh, the mxDateTime algorithm is loop-free in a sense as well: > the correction does at most 3 iterations, the month finder > at most 12 iterations. "iterations" sounds like "loops" to me, and so do the "while() {}" blocks in the code . > I'll have a look at yours, though. Perhaps I can make the > algorithms a bit faster ;-) (oh, I like competition). Speed here is much more important for us, because we store dates in broken-down form -- we may need to do ordinal->date on every add and subtract. By the time this gets recoded in C, I expect most divmods() will get converted to floating-point multiplies by provably-good-enough reciprocal approximations. From gvanrossum@users.sourceforge.net Mon Mar 4 20:21:20 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Mar 2002 12:21:20 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.30,1.31 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv30550 Modified Files: test_datetime.py Log Message: Changed all occurrences of datetime.new(args) to datetime(args). Why were we using datetime.new(args) to create instances? datetime(args) works just as well, and is more familiar -- after all, datetime (as imported here) is the class, not the module. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -d -r1.30 -r1.31 *** test_datetime.py 4 Mar 2002 19:39:38 -0000 1.30 --- test_datetime.py 4 Mar 2002 20:21:18 -0000 1.31 *************** *** 12,16 **** def test_basic_attributes(self): ! dt = datetime.new(2002, 3, 1, 12, 0, 0) self.assertEqual(dt.year, 2002) self.assertEqual(dt.month, 3) --- 12,16 ---- def test_basic_attributes(self): ! dt = datetime(2002, 3, 1, 12, 0, 0) self.assertEqual(dt.year, 2002) self.assertEqual(dt.month, 3) *************** *** 22,26 **** def test_roundtrip(self): ! for dt in (datetime.new(1, 2, 3, 4, 5, 6, 7, 8), datetime.now()): # Verify dt -> string -> datetime identity. --- 22,26 ---- def test_roundtrip(self): ! for dt in (datetime(1, 2, 3, 4, 5, 6, 7, 8), datetime.now()): # Verify dt -> string -> datetime identity. *************** *** 30,42 **** # Verify identity via reconstructing from pieces. ! dt2 = datetime.new(dt.year, dt.month, dt.day, ! dt.hour, dt.minute, dt.second, ! dt.microsecond, dt.tzoffset) self.assertEqual(dt, dt2) def test_tz_independent_comparing(self): ! dt1 = datetime.new(2002, 3, 1, 9, 0, 0, tzoffset=-60) ! dt2 = datetime.new(2002, 3, 1, 10, 0, 0, tzoffset=-60) ! dt3 = datetime.new(2002, 3, 1, 10, 0, 0, tzoffset=0) self.assertEqual(dt1, dt3) self.assert_(dt2 > dt3) --- 30,42 ---- # Verify identity via reconstructing from pieces. ! dt2 = datetime(dt.year, dt.month, dt.day, ! dt.hour, dt.minute, dt.second, ! dt.microsecond, dt.tzoffset) self.assertEqual(dt, dt2) def test_tz_independent_comparing(self): ! dt1 = datetime(2002, 3, 1, 9, 0, 0, tzoffset=-60) ! dt2 = datetime(2002, 3, 1, 10, 0, 0, tzoffset=-60) ! dt3 = datetime(2002, 3, 1, 10, 0, 0, tzoffset=0) self.assertEqual(dt1, dt3) self.assert_(dt2 > dt3) *************** *** 47,51 **** # so comparing via timestamp necessarily calls some distinct values # equal). ! dt1 = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) us = timedelta(microseconds=1) dt2 = dt1 + us --- 47,51 ---- # so comparing via timestamp necessarily calls some distinct values # equal). ! dt1 = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) us = timedelta(microseconds=1) dt2 = dt1 + us *************** *** 54,59 **** # Again, but mix timezones. ! dt1 = datetime.new(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60) ! dt2 = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) self.assertEqual(dt1, dt2) dt2 += us --- 54,59 ---- # Again, but mix timezones. ! dt1 = datetime(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60) ! dt2 = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) self.assertEqual(dt1, dt2) dt2 += us *************** *** 276,285 **** mus = - us ! dt = datetime.new(MINYEAR, 1, 1, microsecond=1) dt -= us # no problem self.assertRaises(OverflowError, dt.__sub__, us) self.assertRaises(OverflowError, dt.__add__, mus) ! dt = datetime.new(MAXYEAR, 12, 31, 23, 59, 59, 999998) dt += us # no problem self.assertRaises(OverflowError, dt.__add__, us) --- 276,285 ---- mus = - us ! dt = datetime(MINYEAR, 1, 1, microsecond=1) dt -= us # no problem self.assertRaises(OverflowError, dt.__sub__, us) self.assertRaises(OverflowError, dt.__add__, mus) ! dt = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999998) dt += us # no problem self.assertRaises(OverflowError, dt.__add__, us) *************** *** 367,372 **** dt.hour - 24*100, dt.minute - 3, dt.second + 12, (3*60 - 12) * 1000000) ! dt2 = datetime.new(tm.year, tm.month, tm.day, tm.hour, tm.minute, ! tm.second, tm.microsecond, tzoffset=0) self.assertEqual(dt, dt2) self.assertEqual(timestamp, tm.time()) --- 367,372 ---- dt.hour - 24*100, dt.minute - 3, dt.second + 12, (3*60 - 12) * 1000000) ! dt2 = datetime(tm.year, tm.month, tm.day, tm.hour, tm.minute, ! tm.second, tm.microsecond, tzoffset=0) self.assertEqual(dt, dt2) self.assertEqual(timestamp, tm.time()) From gvanrossum@users.sourceforge.net Mon Mar 4 20:24:14 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Mar 2002 12:24:14 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.44,1.45 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv31666 Modified Files: datetime.py Log Message: Get rid of datetime.new() as an alias for datetime(). YAGNI. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.44 retrieving revision 1.45 diff -C2 -d -r1.44 -r1.45 *** datetime.py 4 Mar 2002 19:51:32 -0000 1.44 --- datetime.py 4 Mar 2002 20:24:12 -0000 1.45 *************** *** 434,438 **** Constructors: ! __init__() == new() now(), utcnow() fromtimestamp(), utcfromtimestamp() --- 434,438 ---- Constructors: ! __init__() now(), utcnow() fromtimestamp(), utcfromtimestamp() *************** *** 501,509 **** # Additional constructors - def new(cls, *args, **kwds): - "Constructor. Same arguments as __init__." - return cls(*args, **kwds) - new = classmethod(new) - def fromtimestamp(cls, t): "Construct a datetime from a POSIX timestamp (like time.time())." --- 501,504 ---- *************** *** 691,697 **** self.__microsecond + other.microseconds) self._checkOverflow(t.year) ! result = datetime.new(t.year, t.month, t.day, ! t.hour, t.minute, t.second, ! t.microsecond, self.__tzoffset) return result raise TypeError --- 686,692 ---- self.__microsecond + other.microseconds) self._checkOverflow(t.year) ! result = datetime(t.year, t.month, t.day, ! t.hour, t.minute, t.second, ! t.microsecond, self.__tzoffset) return result raise TypeError From gvanrossum@users.sourceforge.net Mon Mar 4 20:26:56 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Mar 2002 12:26:56 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.31,1.32 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv32605 Modified Files: test_datetime.py Log Message: Add a test that fails for the current constructor of timedelta(), because a double doesn't have enough resolution (or is that precision) to express 10000 years in microseconds. Tim will fix it. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** test_datetime.py 4 Mar 2002 20:21:18 -0000 1.31 --- test_datetime.py 4 Mar 2002 20:26:54 -0000 1.32 *************** *** 393,396 **** --- 393,402 ---- self.assert_(datetime.max > datetime.min) + def test_extreme_timedelta(self): + big = datetime.max - datetime.min + n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds + justasbig = timedelta(0, 0, n) + self.assertEqual(big, justasbig) + def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') From tim.one@comcast.net Mon Mar 4 20:29:43 2002 From: tim.one@comcast.net (Tim Peters) Date: Mon, 04 Mar 2002 15:29:43 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.30,1.31 In-Reply-To: Message-ID: [Guido] > Why were we using datetime.new(args) to create instances? I have no idea: I did it because the rest of the test file did, and I confess I even went back and changed some of my plain "datetime(...)"s into "datetime.new(...)"s! I figure we figured this was really a Smalltalk class . From guido@python.org Mon Mar 4 20:35:13 2002 From: guido@python.org (Guido van Rossum) Date: Mon, 04 Mar 2002 15:35:13 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.30,1.31 In-Reply-To: Your message of "Mon, 04 Mar 2002 15:29:43 EST." References: Message-ID: <200203042035.g24KZDH29021@pcp742651pcs.reston01.va.comcast.net> > [Guido] > > Why were we using datetime.new(args) to create instances? > > I have no idea: I did it because the rest of the test file did, and > I confess I even went back and changed some of my plain > "datetime(...)"s into "datetime.new(...)"s! I figure we figured > this was really a Smalltalk class . Fred seems to have started it by accident. His first testcase called datetime.new(...) as the constructor, but that was because in his mind 'datetime' was the module, not the class. I'll fix the TestCases page in the Wiki to avoid more confusion. --Guido van Rossum (home page: http://www.python.org/~guido/) From fdrake@users.sourceforge.net Mon Mar 4 20:41:26 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 12:41:26 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.h,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv5607 Added Files: datetime.h Log Message: Preliminary header for the C implementation of the date/time type. --- NEW FILE: datetime.h --- /* datetime.h */ #ifndef DATETIME_H #define DATETIME_H #define _PyDateTime_DATA_SIZE 12 typedef struct { PyObject_HEAD; unsigned char data[_PyDateTime_DATA_SIZE]; } PyDateTime_Object; extern DL_IMPORT(PyTypeObject) PyDateTime_Type; #define PyDateTime_GET_YEAR(o) (((PyDateTime_Object*)o)->data[0] << 8 \ | ((PyDateTime_Object*)o)->data[1]) #define PyDateTime_GET_MONTH(o) (((PyDateTime_Object*)o)->data[2]) #define PyDateTime_GET_DAY(o) (((PyDateTime_Object*)o)->data[3]) #define PyDateTime_GET_HOUR(o) (((PyDateTime_Object*)o)->data[4]) #define PyDateTime_GET_MINUTE(o) (((PyDateTime_Object*)o)->data[5]) #define PyDateTime_GET_SECOND(o) (((PyDateTime_Object*)o)->data[6]) #define PyDateTime_GET_MICROSECOND(o) (((PyDateTime_Object*)o)->data[7] << 16 \ | ((PyDateTime_Object*)o)->data[8] << 8\ | ((PyDateTime_Object*)o)->data[9]) #define PyDateTime_GET_TZOFFSET(o) ((signed int) \ (((PyDateTime_Object*)o)->data[10] << 8\ | ((PyDateTime_Object*)o)->data[11])) #endif From fdrake@users.sourceforge.net Mon Mar 4 20:43:18 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 12:43:18 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.c,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv6488 Modified Files: datetime.c Log Message: Added constructor & basic attributes (+ required type object). Several slots have handlers that are dummied in. Index: datetime.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** datetime.c 4 Mar 2002 14:36:16 -0000 1.1 --- datetime.c 4 Mar 2002 20:43:16 -0000 1.2 *************** *** 1,4 **** /* C implementation for the date/time type documented at ! * */ --- 1,4 ---- /* C implementation for the date/time type documented at ! * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage */ *************** *** 6,9 **** --- 6,271 ---- #include "modsupport.h" + #include "datetime.h" + + #define MINYEAR 1 + #define MAXYEAR 9999 + + /* Rename the long macros in datetime.h to more reasonable short names. */ + #define GET_YEAR(o) PyDateTime_GET_YEAR(o) + #define GET_MONTH(o) PyDateTime_GET_MONTH(o) + #define GET_DAY(o) PyDateTime_GET_DAY(o) + #define GET_HOUR(o) PyDateTime_GET_HOUR(o) + #define GET_MINUTE(o) PyDateTime_GET_MINUTE(o) + #define GET_SECOND(o) PyDateTime_GET_SECOND(o) + #define GET_MICROSECOND(o) PyDateTime_GET_MICROSECOND(o) + #define GET_TZOFFSET(o) PyDateTime_GET_TZOFFSET(o) + + /* Set accessors. */ + #define SET_YEAR(o, v) (((o)->data[0] = ((v) & 0xff00) >> 8), \ + ((o)->data[1] = ((v) & 0x00ff))) + #define SET_MONTH(o, v) (PyDateTime_GET_MONTH(o) = (v)) + #define SET_DAY(o, v) (PyDateTime_GET_DAY(o) = (v)) + #define SET_HOUR(o, v) (PyDateTime_GET_HOUR(o) = (v)) + #define SET_MINUTE(o, v) (PyDateTime_GET_MINUTE(o) = (v)) + #define SET_SECOND(o, v) (PyDateTime_GET_SECOND(o) = (v)) + #define SET_MICROSECOND(o, v) (((o)->data[7] = ((v) & 0xff0000) >> 16), \ + ((o)->data[8] = ((v) & 0x00ff00) >> 0), \ + ((o)->data[9] = ((v) & 0x00ff00))) + #define SET_TZOFFSET(o, v) (((o)->data[10] = ((v) & 0xff00) >> 8), \ + ((o)->data[11] = ((v) & 0x00ff))) + + static PyObject * + datetime_compare(PyDateTime_Object *self, PyObject *other) + { + PyErr_SetString(PyExc_NotImplementedError, + "not yet implemented"); + return NULL; + } + + static PyObject * + datetime_repr(PyDateTime_Object *self) + { + return PyString_FromString(""); + } + + static PyObject * + datetime_str(PyDateTime_Object *self) + { + return datetime_repr(self); + } + + static int + datetime_hash(PyDateTime_Object *self) + { + return -2; + } + + static int + is_leap(int year) + { + return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); + } + + static int + days_in_month(int year, int month) + { + static int _days_in_month[] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + + assert(month >= 1); + assert(month <= 12); + if (month == 2 && is_leap(year)) + return 29; + else + return _days_in_month[month]; + } + + static PyObject * + datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw) + { + PyDateTime_Object *self = NULL; + long int year, month, day, hour = 0, minute = 0, second = 0, usecond = 0; + long int tzoffset; + PyObject *tzoffset_object = Py_None; + + static char * keywords[] = { + "year", "month", "day", "hour", "minute", "second", "microsecond", + "tzoffset", NULL + }; + + if (PyArg_ParseTupleAndKeywords(args, kw, "lll|llllO", keywords, + &year, &month, &day, &hour, &minute, + &second, &usecond, &tzoffset_object)) { + if (year < MINYEAR || year > MAXYEAR) { + PyErr_SetString(PyExc_ValueError, "year is out of range"); + return NULL; + } + if (month < 1 || month > 12) { + PyErr_SetString(PyExc_ValueError, "month must be in 1..12"); + return NULL; + } + if (day < 1 || day > days_in_month(year, month)) { + PyErr_SetString(PyExc_ValueError, "day is out of range for month"); + return NULL; + } + if (hour < 0 || hour > 23) { + PyErr_SetString(PyExc_ValueError, "hour must be in 0..23"); + return NULL; + } + if (minute < 0 || minute > 59) { + PyErr_SetString(PyExc_ValueError, "minute must be in 0..59"); + return NULL; + } + if (second < 0 || second > 59) { + PyErr_SetString(PyExc_ValueError, "second must be in 0..59"); + return NULL; + } + if (usecond < 0 || usecond > 999999) { + PyErr_SetString(PyExc_ValueError, + "microsecond must be in 0..999999"); + return NULL; + } + if (tzoffset_object == Py_None) { + /* tzoffset == None not yet implemented */ + tzoffset = 0; + } + else { + tzoffset_object = PyNumber_Int(tzoffset_object); + if (tzoffset_object == NULL) + return NULL; + tzoffset = PyInt_AS_LONG(tzoffset_object); + Py_DECREF(tzoffset_object); + if (tzoffset < -1439 || tzoffset > 1439) { + PyErr_SetString(PyExc_ValueError, + "tzoffset must be in -1439..1439"); + return NULL; + } + tzoffset_object = NULL; + } + self = PyObject_New(PyDateTime_Object, &PyDateTime_Type); + if (self != NULL) { + SET_YEAR(self, year); + SET_MONTH(self, month); + SET_DAY(self, day); + SET_HOUR(self, hour); + SET_MINUTE(self, minute); + SET_SECOND(self, second); + SET_MICROSECOND(self, usecond); + SET_TZOFFSET(self, tzoffset); + } + } + return (PyObject *) self; + } + + + static PyObject * + datetime_year(PyDateTime_Object *self, void *unused) + { + return (PyInt_FromLong(GET_YEAR(self))); + } + + static PyObject * + datetime_month(PyDateTime_Object *self, void *unused) + { + return (PyInt_FromLong(GET_MONTH(self))); + } + + static PyObject * + datetime_day(PyDateTime_Object *self, void *unused) + { + return (PyInt_FromLong(GET_DAY(self))); + } + + static PyObject * + datetime_hour(PyDateTime_Object *self, void *unused) + { + return (PyInt_FromLong(GET_HOUR(self))); + } + + static PyObject * + datetime_minute(PyDateTime_Object *self, void *unused) + { + return (PyInt_FromLong(GET_MINUTE(self))); + } + + static PyObject * + datetime_second(PyDateTime_Object *self, void *unused) + { + return (PyInt_FromLong(GET_SECOND(self))); + } + + static PyObject * + datetime_microsecond(PyDateTime_Object *self, void *unused) + { + return (PyInt_FromLong(GET_MICROSECOND(self))); + } + + static PyObject * + datetime_tzoffset(PyDateTime_Object *self, void *unused) + { + return (PyInt_FromLong(GET_TZOFFSET(self))); + } + + static PyGetSetDef datetime_getset[] = { + {"year",(getter)datetime_year}, + {"month", (getter)datetime_month}, + {"day", (getter)datetime_day}, + {"hour", (getter)datetime_hour}, + {"minute", (getter)datetime_minute}, + {"second", (getter)datetime_second}, + {"microsecond", (getter)datetime_microsecond}, + {"tzoffset", (getter)datetime_tzoffset}, + {NULL} + }; + + static char datetime_doc[] = + "Basic date/time type."; + + + PyTypeObject PyDateTime_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "datetime.datetime", /* tp_name */ + sizeof(PyDateTime_Object), /* tp_basicsize */ + 0, /* tp_itemsize */ + _PyObject_Del, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + (cmpfunc)datetime_compare, /* tp_compare */ + (reprfunc)datetime_repr, /* tp_repr */ + 0, /* tp_as_number */ + /*&datetime_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)datetime_hash, /* tp_hash */ + 0, /* tp_call */ + (reprfunc)datetime_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + datetime_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + datetime_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + datetime_new, /* tp_new */ + _PyObject_Del, /* tp_free */ + }; *************** *** 17,23 **** init_datetime(void) { ! PyObject *m = Py_InitModule3("_datetime", functions, ! "Fast implementation of the datetime type."); PyModule_AddIntConstant(m, "MINYEAR", 1); PyModule_AddIntConstant(m, "MAXYEAR", 9999); } --- 279,292 ---- init_datetime(void) { ! PyObject *m; ! ! if (PyType_Ready(&PyDateTime_Type) < 0) ! return; ! ! m = Py_InitModule3("_datetime", functions, ! "Fast implementation of the datetime type."); PyModule_AddIntConstant(m, "MINYEAR", 1); PyModule_AddIntConstant(m, "MAXYEAR", 9999); + Py_INCREF(&PyDateTime_Type); + PyModule_AddObject(m, "datetime", (PyObject *) &PyDateTime_Type); } From fdrake@users.sourceforge.net Mon Mar 4 20:44:21 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 12:44:21 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_cdatetime.py,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv6906 Added Files: test_cdatetime.py Log Message: Tests that the C implementation passes. This will eventually be stubbed to use test_datetime or be removed. --- NEW FILE: test_cdatetime.py --- """Test date/time type. See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases """ import sys import unittest from _datetime import datetime, MINYEAR, MAXYEAR class TestDateTime(unittest.TestCase): def test_basic_attributes(self): dt = datetime(2002, 3, 1, 12, 0, 0) self.assertEqual(dt.year, 2002) self.assertEqual(dt.month, 3) self.assertEqual(dt.day, 1) self.assertEqual(dt.hour, 12) self.assertEqual(dt.minute, 0) self.assertEqual(dt.second, 0) self.assertEqual(dt.microsecond, 0) def test_suite(): s1 = unittest.makeSuite(TestDateTime, 'test') return unittest.TestSuite([s1]) def test_main(): r = unittest.TextTestRunner(stream=sys.stdout, verbosity=2) s = test_suite() r.run(s) if __name__ == "__main__": test_main() From fdrake@users.sourceforge.net Mon Mar 4 20:44:51 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 12:44:51 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime Makefile,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv7118 Modified Files: Makefile Log Message: Run the tests for the C date/time as well. Index: Makefile =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Makefile 4 Mar 2002 14:36:16 -0000 1.1 --- Makefile 4 Mar 2002 20:44:49 -0000 1.2 *************** *** 9,12 **** --- 9,13 ---- check: _datetime.so $(PYTHON) test_datetime.py + $(PYTHON) test_cdatetime.py test: check From fdrake@acm.org Mon Mar 4 21:08:14 2002 From: fdrake@acm.org (Fred L. Drake, Jr.) Date: Mon, 4 Mar 2002 16:08:14 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.30,1.31 In-Reply-To: <200203042035.g24KZDH29021@pcp742651pcs.reston01.va.comcast.net> References: <200203042035.g24KZDH29021@pcp742651pcs.reston01.va.comcast.net> Message-ID: <15491.57918.40857.545634@grendel.zope.com> Guido van Rossum writes: > Fred seems to have started it by accident. His first testcase called > datetime.new(...) as the constructor, but that was because in his mind > 'datetime' was the module, not the class. I'll fix the TestCases page At the time, none of the code existed, and it seemed a reasonable name for it. Not being a Smalltalk programmer, I never guessed that datetime.new() would be interpreted as a classmethod on a class. ;-) -Fred -- Fred L. Drake, Jr. PythonLabs at Zope Corporation From fdrake@users.sourceforge.net Mon Mar 4 21:20:56 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 13:20:56 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.c,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv20985 Modified Files: datetime.c Log Message: Use indentation more consistently. Index: datetime.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** datetime.c 4 Mar 2002 20:43:16 -0000 1.2 --- datetime.c 4 Mar 2002 21:20:54 -0000 1.3 *************** *** 225,270 **** PyTypeObject PyDateTime_Type = { ! PyObject_HEAD_INIT(&PyType_Type) ! 0, /* ob_size */ ! "datetime.datetime", /* tp_name */ ! sizeof(PyDateTime_Object), /* tp_basicsize */ ! 0, /* tp_itemsize */ ! _PyObject_Del, /* tp_dealloc */ ! 0, /* tp_print */ ! 0, /* tp_getattr */ ! 0, /* tp_setattr */ ! (cmpfunc)datetime_compare, /* tp_compare */ ! (reprfunc)datetime_repr, /* tp_repr */ ! 0, /* tp_as_number */ ! /*&datetime_as_number, /* tp_as_number */ ! 0, /* tp_as_sequence */ ! 0, /* tp_as_mapping */ ! (hashfunc)datetime_hash, /* tp_hash */ ! 0, /* tp_call */ ! (reprfunc)datetime_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ ! 0, /* tp_setattro */ ! 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | ! Py_TPFLAGS_BASETYPE, /* tp_flags */ ! datetime_doc, /* tp_doc */ ! 0, /* tp_traverse */ ! 0, /* tp_clear */ ! 0, /* tp_richcompare */ ! 0, /* tp_weaklistoffset */ ! 0, /* tp_iter */ ! 0, /* tp_iternext */ ! 0, /* tp_methods */ ! 0, /* tp_members */ ! datetime_getset, /* tp_getset */ ! 0, /* tp_base */ ! 0, /* tp_dict */ ! 0, /* tp_descr_get */ ! 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! 0, /* tp_init */ ! 0, /* tp_alloc */ ! datetime_new, /* tp_new */ ! _PyObject_Del, /* tp_free */ }; --- 225,269 ---- PyTypeObject PyDateTime_Type = { ! PyObject_HEAD_INIT(&PyType_Type) ! 0, /* ob_size */ ! "datetime.datetime", /* tp_name */ ! sizeof(PyDateTime_Object), /* tp_basicsize */ ! 0, /* tp_itemsize */ ! _PyObject_Del, /* tp_dealloc */ ! 0, /* tp_print */ ! 0, /* tp_getattr */ ! 0, /* tp_setattr */ ! (cmpfunc)datetime_compare, /* tp_compare */ ! (reprfunc)datetime_repr, /* tp_repr */ ! 0, /* tp_as_number */ ! 0, /* tp_as_sequence */ ! 0, /* tp_as_mapping */ ! (hashfunc)datetime_hash, /* tp_hash */ ! 0, /* tp_call */ ! (reprfunc)datetime_str, /* tp_str */ ! PyObject_GenericGetAttr, /* tp_getattro */ ! 0, /* tp_setattro */ ! 0, /* tp_as_buffer */ ! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES | ! Py_TPFLAGS_BASETYPE, /* tp_flags */ ! datetime_doc, /* tp_doc */ ! 0, /* tp_traverse */ ! 0, /* tp_clear */ ! 0, /* tp_richcompare */ ! 0, /* tp_weaklistoffset */ ! 0, /* tp_iter */ ! 0, /* tp_iternext */ ! 0, /* tp_methods */ ! 0, /* tp_members */ ! datetime_getset, /* tp_getset */ ! 0, /* tp_base */ ! 0, /* tp_dict */ ! 0, /* tp_descr_get */ ! 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! 0, /* tp_init */ ! 0, /* tp_alloc */ ! datetime_new, /* tp_new */ ! _PyObject_Del, /* tp_free */ }; From tim_one@users.sourceforge.net Mon Mar 4 22:52:09 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 14:52:09 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.45,1.46 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv23648 Modified Files: datetime.py Log Message: timedelta.__init__(): Massive rewrite to deal correctly with both the huge dynamic range of floats and the unbounded precision of longs, while also isolating the subcomputations that can be reliably done with 32-bit ints (and asserting that those won't overflow when redone in C -- but assuming Python ints are 32 bits, for sanity's sake). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.45 retrieving revision 1.46 diff -C2 -d -r1.45 -r1.46 *** datetime.py 4 Mar 2002 20:24:12 -0000 1.45 --- datetime.py 4 Mar 2002 22:52:07 -0000 1.46 *************** *** 305,336 **** # XXX The following should only be used as keyword args: milliseconds=0, minutes=0, hours=0, weeks=0): # Normalize everything to days, seconds, microseconds. ! # Convert everything to float first, else overflow-checking in C ! # is going to be a nightmare. ! days += weeks*7. ! seconds += minutes*60. + hours*3600. ! microseconds += milliseconds*1000. ! # Get rid of all fractions. ! dayfrac, days = _math.modf(days) ! daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.)) ! secondsfrac, seconds = _math.modf(seconds) ! seconds += daysecondswhole secondsfrac += daysecondsfrac ! microseconds += secondsfrac*1e6 ! microseconds = round(microseconds) ! assert _math.modf(days)[0] == 0.0 ! assert _math.modf(seconds)[0] == 0.0 ! assert _math.modf(microseconds)[0] == 0.0 ! # Propagate carry from us to s, from s to d ! s, us = divmod(microseconds, 1000000) ! assert us == int(us) and 0 <= us < 1000000 ! d, s = divmod(s + seconds, 24*3600) ! assert s == int(s) and 0 <= s < 24*3600 d += days ! assert d == long(d) ! # d may be < 0 ! self.__days = int(d) ! self.__seconds = int(s) ! self.__microseconds = int(us) def __repr__(self): --- 305,406 ---- # XXX The following should only be used as keyword args: milliseconds=0, minutes=0, hours=0, weeks=0): + # Doing this efficiently and accurately in C is going to be difficult + # and error-prone, due to ubiquitous overflow possibilities, and that + # C double doesn't have enough bits of precision to represent + # microseconds over 10K years faithfully. The code here tries to make + # explicit where go-fast assumptions can be relied on, in order to + # guide the C implementation; it's way more convoluted than speed- + # ignoring auto-overflow-to-long idiomatic Python could be. + + # XXX Check that all inputs are ints, longs or floats. + + # Final values, all integer. + # s and us fit in 32-bit signed ints; d isn't bounded. + d = s = us = 0 + # Normalize everything to days, seconds, microseconds. ! days += weeks*7 ! seconds += minutes*60 + hours*3600 ! microseconds += milliseconds*1000 ! ! # Get rid of all fractions, and normalize s and us. ! # Take a deep breath . ! if isinstance(days, float): ! dayfrac, days = _math.modf(days) ! daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.)) ! assert daysecondswhole == int(daysecondswhole) # can't overflow ! daysecondswhole = int(daysecondswhole) ! assert days == long(days) ! d = long(days) ! else: ! daysecondsfrac, daysecondswhole = 0.0, 0 ! d = days ! assert isinstance(daysecondsfrac, float) ! assert isinstance(daysecondswhole, int) ! assert 0 <= daysecondswhole < 24*3600 ! assert isinstance(d, (int, long)) ! # days isn't referenced again before redefinition ! ! if isinstance(seconds, float): ! secondsfrac, seconds = _math.modf(seconds) ! assert seconds == long(seconds) ! seconds = long(seconds) ! else: ! secondsfrac = 0.0 ! assert isinstance(secondsfrac, float) ! assert isinstance(seconds, (int, long)) ! days, seconds = divmod(seconds, 24*3600) ! d += days ! s = int(seconds) # can't overflow ! s += daysecondswhole # can't overflow ! assert isinstance(s, int) ! assert 0 <= s < 2*24*3600 ! # seconds isn't referenced again before redefinition ! secondsfrac += daysecondsfrac ! assert -2.0 <= secondsfrac <= 2.0 ! usdouble = secondsfrac * 1e6 ! assert -2.1e6 < usdouble < 2.1e6 # exact value not critical ! # secondsfrac & daysecondsfrac aren't referenced again ! ! if isinstance(microseconds, float): ! microseconds += usdouble ! microseconds = round(microseconds) ! seconds, microseconds = divmod(microseconds, 1e6) ! assert microseconds == int(microseconds) ! assert seconds == long(seconds) ! days, seconds = divmod(seconds, 24.*3600.) ! assert days == long(days) ! assert seconds == int(seconds) ! d += long(days) ! s += int(seconds) # can't overflow ! assert isinstance(s, int) ! else: ! seconds, microseconds = divmod(microseconds, 1000000) ! days, seconds = divmod(seconds, 24*3600) ! d += days ! s += int(seconds) # can't overflow ! assert isinstance(s, int) ! microseconds = float(microseconds) ! microseconds += usdouble ! microseconds = round(microseconds) ! ! # Just a little bit of carrying possible for microseconds and seconds. ! assert isinstance(microseconds, float) ! assert 0 <= microseconds <= 3.1e6 ! assert int(microseconds) == microseconds ! us = int(microseconds) ! seconds, us = divmod(us, 1000000) ! s += seconds # cant't overflow ! assert isinstance(s, int) ! days, s = divmod(s, 24*3600) d += days ! ! assert isinstance(d, (int, long)) ! assert isinstance(s, int) and 0 <= s < 24*3600 ! assert isinstance(us, int) and 0 <= us < 1000000 ! self.__days = d ! self.__seconds = s ! self.__microseconds = us def __repr__(self): From montanaro@users.sourceforge.net Mon Mar 4 23:08:30 2002 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Mon, 04 Mar 2002 15:08:30 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libre.tex,1.75,1.76 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv30742 Modified Files: libre.tex Log Message: add simple example of avoiding backtracking Index: libre.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libre.tex,v retrieving revision 1.75 retrieving revision 1.76 diff -C2 -d -r1.75 -r1.76 *** libre.tex 25 Feb 2002 18:56:45 -0000 1.75 --- libre.tex 4 Mar 2002 23:08:28 -0000 1.76 *************** *** 803,810 **** \subsection{Examples} - %\begin{list}{}{\leftmargin 0.7in \labelwidth 0.65in} - - %\item[Simulating scanf] - \leftline{\strong{Simulating \cfunction{scanf()}}} --- 803,806 ---- *************** *** 852,857 **** \begin{verbatim} ! ([^\s]+) - (\d+) errors, (\d+) warnings \end{verbatim} ! %\end{list} --- 848,873 ---- \begin{verbatim} ! (\S+) - (\d+) errors, (\d+) warnings \end{verbatim} ! \leftline{\strong{Avoiding backtracking}} ! ! If you create regular expressions that require the engine to perform a lot ! of backtracking, you may encounter a RuntimeError exception with the message ! \code{maximum recursion limit exceeded}. For example, ! ! \begin{verbatim} ! >>> s = "<" + "that's a very big string!"*1000 + ">" ! >>> re.match('<.*?>', s) ! Traceback (most recent call last): ! File "", line 1, in ? ! File "/usr/local/lib/python2.3/sre.py", line 132, in match ! return _compile(pattern, flags).match(string) ! RuntimeError: maximum recursion limit exceeded ! \end{verbatim} ! ! You can often restructure your regular expression to avoid backtracking. ! The above regular expression can be recast as \regexp{\textless ! [\textasciicircum \textgreater]*\textgreater}. As a further ! benefit, such regular expressions will run faster than their backtracking ! equivalents. From gvanrossum@users.sourceforge.net Tue Mar 5 03:23:23 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 04 Mar 2002 19:23:23 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.46,1.47 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv18346 Modified Files: datetime.py Log Message: Small stuff: - Make _MONTHNAMES and _DAYNAMES 1-indexed arrays by inserting a None (matching _DAYS_IN_MONTH etc.) - Change timedelta.__repr__ to return self.__class__.__name__ (but not the full module name) - Change various operations to use self.__class__ rather than timedelta or datetime, to support subclasses - In datetime, add a class variable timedelta_class which is used for the return type of __sub__, so a subclass can override the class to be used for deltas There are no tests for these behaviors yet. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.46 retrieving revision 1.47 diff -C2 -d -r1.46 -r1.47 *** datetime.py 4 Mar 2002 22:52:07 -0000 1.46 --- datetime.py 5 Mar 2002 03:23:21 -0000 1.47 *************** *** 146,152 **** # Month and day names. For localized versions, see the calendar module. ! _MONTHNAMES = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", ! "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] ! _DAYNAMES = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] # This is a start at a struct tm workalike. Goals: --- 146,152 ---- # Month and day names. For localized versions, see the calendar module. ! _MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", ! "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] ! _DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] # This is a start at a struct tm workalike. Goals: *************** *** 242,247 **** weekday = self.toordinal() % 7 or 7 return "%s %s %2d %02d:%02d:%02d %04d" % ( ! _DAYNAMES[weekday - 1], ! _MONTHNAMES[self.month - 1], self.day, self.hour, self.minute, self.second, --- 242,247 ---- weekday = self.toordinal() % 7 or 7 return "%s %s %2d %02d:%02d:%02d %04d" % ( ! _DAYNAMES[weekday], ! _MONTHNAMES[self.month], self.day, self.hour, self.minute, self.second, *************** *** 406,415 **** def __repr__(self): if self.__microseconds: ! return "timedelta(days=%d, %d, %d)" % (self.__days, ! self.__seconds, ! self.__microseconds) if self.__seconds: ! return "timedelta(%d, %d)" % (self.__days, self.__seconds) ! return "timedelta(%d)" % self.__days def __str__(self): --- 406,418 ---- def __repr__(self): if self.__microseconds: ! return "%s(days=%d, %d, %d)" % (self.__class__.__name__, ! self.__days, ! self.__seconds, ! self.__microseconds) if self.__seconds: ! return "%s(%d, %d)" % (self.__class__.__name__, ! self.__days, ! self.__seconds) ! return "%s(%d)" % (self.__class__.__name__, self.__days) def __str__(self): *************** *** 439,445 **** def __add__(self, other): if isinstance(other, timedelta): ! return timedelta(self.__days + other.__days, ! self.__seconds + other.__seconds, ! self.__microseconds + other.__microseconds) raise TypeError # XXX Should be 'return NotImplemented', but there's a bug in 2.2... --- 442,448 ---- def __add__(self, other): if isinstance(other, timedelta): ! return self.__class__(self.__days + other.__days, ! self.__seconds + other.__seconds, ! self.__microseconds + other.__microseconds) raise TypeError # XXX Should be 'return NotImplemented', but there's a bug in 2.2... *************** *** 458,462 **** def __neg__(self): ! return timedelta(-self.__days, -self.__seconds, -self.__microseconds) def __pos__(self): --- 461,467 ---- def __neg__(self): ! return self.__class__(-self.__days, ! -self.__seconds, ! -self.__microseconds) def __pos__(self): *************** *** 471,477 **** def __mul__(self, other): if isinstance(other, (int, long)): ! return timedelta(self.__days * other, ! self.__seconds * other, ! self.__microseconds * other) return NotImplemented --- 476,482 ---- def __mul__(self, other): if isinstance(other, (int, long)): ! return self.__class__(self.__days * other, ! self.__seconds * other, ! self.__microseconds * other) return NotImplemented *************** *** 482,486 **** usec = ((self.__days * (24*3600L) + self.__seconds) * 1000000 + self.__microseconds) ! return timedelta(0, 0, usec // other) return NotImplemented --- 487,491 ---- usec = ((self.__days * (24*3600L) + self.__seconds) * 1000000 + self.__microseconds) ! return self.__class__(0, 0, usec // other) return NotImplemented *************** *** 756,762 **** self.__microsecond + other.microseconds) self._checkOverflow(t.year) ! result = datetime(t.year, t.month, t.day, ! t.hour, t.minute, t.second, ! t.microsecond, self.__tzoffset) return result raise TypeError --- 761,767 ---- self.__microsecond + other.microseconds) self._checkOverflow(t.year) ! result = self.__class__(t.year, t.month, t.day, ! t.hour, t.minute, t.second, ! t.microsecond, self.__tzoffset) return result raise TypeError *************** *** 765,768 **** --- 770,775 ---- __radd__ = __add__ + timedelta_class = timedelta # Allows a subclass to override + def __sub__(self, other): """Subtract two datetimes, or a datetime and a timedelta. *************** *** 781,786 **** (other.__minute - other.__tzoffset) * 60 + other.__hour * 3600) ! return timedelta(days1 - days2, secs1 - secs2, ! self.__microsecond - other.__microsecond) return NotImplemented --- 788,795 ---- (other.__minute - other.__tzoffset) * 60 + other.__hour * 3600) ! return self.timedelta_class( ! days1 - days2, ! secs1 - secs2, ! self.__microsecond - other.__microsecond) return NotImplemented From tim_one@users.sourceforge.net Tue Mar 5 03:55:37 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 19:55:37 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.h,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv25638 Modified Files: datetime.h Log Message: PyObject_HEAD already contains a semicolon, and MSVC can't tolerate putting another semicolon after it. Getting rid of the semicolon clears up oodles of bogus errors. Still doesn't compile on Windows, though: datetime.c(226) : warning C4273: 'PyDateTime_Type' : inconsistent dll linkage. dllexport assumed. datetime.c(227) : error C2099: initializer is not a constant plus lots of warnings, some of which look serious. Index: datetime.h =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** datetime.h 4 Mar 2002 20:41:24 -0000 1.1 --- datetime.h 5 Mar 2002 03:55:35 -0000 1.2 *************** *** 9,13 **** typedef struct { ! PyObject_HEAD; unsigned char data[_PyDateTime_DATA_SIZE]; } PyDateTime_Object; --- 9,13 ---- typedef struct { ! PyObject_HEAD unsigned char data[_PyDateTime_DATA_SIZE]; } PyDateTime_Object; From fdrake@users.sourceforge.net Tue Mar 5 04:02:41 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 20:02:41 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libre.tex,1.76,1.77 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv28790/lib Modified Files: libre.tex Log Message: Remove extra indenatation from sample interpreter session. Remove whitespace from the middle of an inline RE example; it was OK for the typeset formats, but LaTeX2HTML is more touchy about this. Index: libre.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libre.tex,v retrieving revision 1.76 retrieving revision 1.77 diff -C2 -d -r1.76 -r1.77 *** libre.tex 4 Mar 2002 23:08:28 -0000 1.76 --- libre.tex 5 Mar 2002 04:02:39 -0000 1.77 *************** *** 858,873 **** \begin{verbatim} ! >>> s = "<" + "that's a very big string!"*1000 + ">" ! >>> re.match('<.*?>', s) ! Traceback (most recent call last): ! File "", line 1, in ? ! File "/usr/local/lib/python2.3/sre.py", line 132, in match ! return _compile(pattern, flags).match(string) ! RuntimeError: maximum recursion limit exceeded \end{verbatim} You can often restructure your regular expression to avoid backtracking. ! The above regular expression can be recast as \regexp{\textless ! [\textasciicircum \textgreater]*\textgreater}. As a further ! benefit, such regular expressions will run faster than their backtracking ! equivalents. --- 858,873 ---- \begin{verbatim} ! >>> s = "<" + "that's a very big string!"*1000 + ">" ! >>> re.match('<.*?>', s) ! Traceback (most recent call last): ! File "", line 1, in ? ! File "/usr/local/lib/python2.3/sre.py", line 132, in match ! return _compile(pattern, flags).match(string) ! RuntimeError: maximum recursion limit exceeded \end{verbatim} You can often restructure your regular expression to avoid backtracking. ! The above regular expression can be recast as ! \regexp{\textless[\textasciicircum \textgreater]*\textgreater}. As a ! further benefit, such regular expressions will run faster than their ! backtracking equivalents. From fdrake@users.sourceforge.net Tue Mar 5 04:04:08 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 20:04:08 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/perl python.perl,1.116,1.117 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/perl In directory usw-pr-cvs1:/tmp/cvs-serv29139/perl Modified Files: python.perl Log Message: Add implementations for \textgreater and \textless, defined in (relatively) recent versions of LaTeX2e but not support in LaTeX2HTML. Index: python.perl =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/perl/python.perl,v retrieving revision 1.116 retrieving revision 1.117 diff -C2 -d -r1.116 -r1.117 *** python.perl 14 Dec 2001 22:50:05 -0000 1.116 --- python.perl 5 Mar 2002 04:04:06 -0000 1.117 *************** *** 89,92 **** --- 89,94 ---- sub do_cmd_textasciicircum{ '^' . @_[0]; } sub do_cmd_textbar{ '|' . @_[0]; } + sub do_cmd_textgreater{ '>' . @_[0]; } + sub do_cmd_textless{ '<' . @_[0]; } sub do_cmd_infinity{ '∞' . @_[0]; } sub do_cmd_plusminus{ '±' . @_[0]; } From tim_one@users.sourceforge.net Tue Mar 5 04:15:56 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 20:15:56 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.47,1.48 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv31117 Modified Files: datetime.py Log Message: timedelta.__init__(): Small simplification to handling of seconds; repaired some incorrect asserts not triggered by the tests. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.47 retrieving revision 1.48 diff -C2 -d -r1.47 -r1.48 *** datetime.py 5 Mar 2002 03:23:21 -0000 1.47 --- datetime.py 5 Mar 2002 04:15:53 -0000 1.48 *************** *** 330,343 **** daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.)) assert daysecondswhole == int(daysecondswhole) # can't overflow ! daysecondswhole = int(daysecondswhole) assert days == long(days) d = long(days) else: ! daysecondsfrac, daysecondswhole = 0.0, 0 d = days assert isinstance(daysecondsfrac, float) - assert isinstance(daysecondswhole, int) - assert 0 <= daysecondswhole < 24*3600 assert isinstance(d, (int, long)) # days isn't referenced again before redefinition --- 330,342 ---- daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.)) assert daysecondswhole == int(daysecondswhole) # can't overflow ! s = int(daysecondswhole) assert days == long(days) d = long(days) else: ! daysecondsfrac = 0.0 d = days assert isinstance(daysecondsfrac, float) assert isinstance(d, (int, long)) + assert abs(s) <= 24 * 3600 # days isn't referenced again before redefinition *************** *** 352,359 **** days, seconds = divmod(seconds, 24*3600) d += days ! s = int(seconds) # can't overflow ! s += daysecondswhole # can't overflow assert isinstance(s, int) ! assert 0 <= s < 2*24*3600 # seconds isn't referenced again before redefinition --- 351,357 ---- days, seconds = divmod(seconds, 24*3600) d += days ! s += int(seconds) # can't overflow assert isinstance(s, int) ! assert abs(s) <= 2 * 24 * 3600 # seconds isn't referenced again before redefinition *************** *** 376,379 **** --- 374,378 ---- s += int(seconds) # can't overflow assert isinstance(s, int) + assert abs(s) <= 3 * 24 * 3600 else: seconds, microseconds = divmod(microseconds, 1000000) *************** *** 382,392 **** s += int(seconds) # can't overflow assert isinstance(s, int) microseconds = float(microseconds) microseconds += usdouble microseconds = round(microseconds) # Just a little bit of carrying possible for microseconds and seconds. assert isinstance(microseconds, float) - assert 0 <= microseconds <= 3.1e6 assert int(microseconds) == microseconds us = int(microseconds) --- 381,393 ---- s += int(seconds) # can't overflow assert isinstance(s, int) + assert abs(s) <= 3 * 24 * 3600 microseconds = float(microseconds) microseconds += usdouble microseconds = round(microseconds) + assert abs(s) <= 3 * 24 * 3600 + assert abs(microseconds) <= 3.1e6 # Just a little bit of carrying possible for microseconds and seconds. assert isinstance(microseconds, float) assert int(microseconds) == microseconds us = int(microseconds) From tim_one@users.sourceforge.net Tue Mar 5 04:19:06 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 20:19:06 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.32,1.33 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv31542 Modified Files: test_datetime.py Log Message: test_hash_equality(): Use the datetime objects constructed for hash- equality tests as dict keys, and make sure equal keys "work" in context. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.32 retrieving revision 1.33 diff -C2 -d -r1.32 -r1.33 *** test_datetime.py 4 Mar 2002 20:26:54 -0000 1.32 --- test_datetime.py 5 Mar 2002 04:19:03 -0000 1.33 *************** *** 151,154 **** --- 151,160 ---- self.assertEqual(hash(d), hash(e)) + dic = {d: 1} + dic[e] = 2 + self.assertEqual(len(dic), 1) + self.assertEqual(dic[d], 2) + self.assertEqual(dic[e], 2) + d = datetime(2001, 1, 1, 0, 5, 17, tzoffset=35) # same thing in UTC. *************** *** 156,159 **** --- 162,171 ---- self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) + + dic = {d: 1} + dic[e] = 2 + self.assertEqual(len(dic), 1) + self.assertEqual(dic[d], 2) + self.assertEqual(dic[e], 2) def test_timedelta(self): From fdrake@users.sourceforge.net Tue Mar 5 06:44:51 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 04 Mar 2002 22:44:51 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime Makefile,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv24440 Modified Files: Makefile Log Message: Add dependency on the header file. Index: Makefile =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Makefile 4 Mar 2002 20:44:49 -0000 1.2 --- Makefile 5 Mar 2002 06:44:49 -0000 1.3 *************** *** 4,8 **** all: _datetime.so ! _datetime.so: datetime.c $(PYTHON) setup.py build_ext -i --- 4,8 ---- all: _datetime.so ! _datetime.so: datetime.c datetime.h $(PYTHON) setup.py build_ext -i From tim_one@users.sourceforge.net Tue Mar 5 07:59:14 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 04 Mar 2002 23:59:14 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.33,1.34 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv7224 Modified Files: test_datetime.py Log Message: test_overflow(): use datetime.{min, max, resolution} instead of hardcoded constants. Plus assorted minor fiddling. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -d -r1.33 -r1.34 *** test_datetime.py 5 Mar 2002 04:19:03 -0000 1.33 --- test_datetime.py 5 Mar 2002 07:59:12 -0000 1.34 *************** *** 285,300 **** def test_overflow(self): ! us = timedelta(microseconds=1) ! mus = - us ! dt = datetime(MINYEAR, 1, 1, microsecond=1) ! dt -= us # no problem ! self.assertRaises(OverflowError, dt.__sub__, us) ! self.assertRaises(OverflowError, dt.__add__, mus) ! dt = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999998) ! dt += us # no problem ! self.assertRaises(OverflowError, dt.__add__, us) ! self.assertRaises(OverflowError, dt.__sub__, mus) def test_weekday(self): --- 285,299 ---- def test_overflow(self): ! tiny = datetime.resolution ! dt = datetime.min + tiny ! dt -= tiny # no problem ! self.assertRaises(OverflowError, dt.__sub__, tiny) ! self.assertRaises(OverflowError, dt.__add__, -tiny) ! dt = datetime.max - tiny ! dt += tiny # no problem ! self.assertRaises(OverflowError, dt.__add__, tiny) ! self.assertRaises(OverflowError, dt.__sub__, -tiny) def test_weekday(self): *************** *** 374,378 **** for timestamp in 123456789.0, 987654321.0: dt = datetime.utcfromtimestamp(timestamp) ! # Mange the fields, but in such a way that normalization should # restore them to dt's values. tm = tmxxx(dt.year - 1, dt.month + 12, dt.day + 100, --- 373,377 ---- for timestamp in 123456789.0, 987654321.0: dt = datetime.utcfromtimestamp(timestamp) ! # Manglee the fields, but in such a way that normalization should # restore them to dt's values. tm = tmxxx(dt.year - 1, dt.month + 12, dt.day + 100, *************** *** 407,413 **** --- 406,416 ---- def test_extreme_timedelta(self): big = datetime.max - datetime.min + # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds + # n = 315537897599999999 justasbig = timedelta(0, 0, n) self.assertEqual(big, justasbig) + self.assertEqual(datetime.min + big, datetime.max) + self.assertEqual(datetime.max - big, datetime.min) def test_suite(): From tim_one@users.sourceforge.net Tue Mar 5 08:00:43 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 05 Mar 2002 00:00:43 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.34,1.35 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv7779 Modified Files: test_datetime.py Log Message: Finished a new comment. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** test_datetime.py 5 Mar 2002 07:59:12 -0000 1.34 --- test_datetime.py 5 Mar 2002 08:00:41 -0000 1.35 *************** *** 408,412 **** # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds ! # n = 315537897599999999 justasbig = timedelta(0, 0, n) self.assertEqual(big, justasbig) --- 408,412 ---- # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds ! # n = 315537897599999999 ~= 2**58.13 justasbig = timedelta(0, 0, n) self.assertEqual(big, justasbig) From tim_one@users.sourceforge.net Tue Mar 5 08:30:33 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 05 Mar 2002 00:30:33 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.48,1.49 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv14634 Modified Files: datetime.py Log Message: _ord2ymd(): Cheaper way to estimate the month, with an addition and a shift, replacing an addition, a division, and a min(). Amazingly, in both leap and non-leap years, this needs to take the "if" (correction) branch exactly as many times as the more expensive method (across all possible values for n). Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.48 retrieving revision 1.49 diff -C2 -d -r1.48 -r1.49 *** datetime.py 5 Mar 2002 04:15:53 -0000 1.48 --- datetime.py 5 Mar 2002 08:30:31 -0000 1.49 *************** *** 133,137 **** leapyear = n1 == 3 and (n4 != 24 or n100 == 3) assert leapyear == _is_leap(year) ! month = min(n//29 + 1, 12) preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear) if preceding > n: # estimate is too large --- 133,137 ---- leapyear = n1 == 3 and (n4 != 24 or n100 == 3) assert leapyear == _is_leap(year) ! month = (n + 50) >> 5 preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear) if preceding > n: # estimate is too large From tim_one@users.sourceforge.net Tue Mar 5 08:39:15 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 05 Mar 2002 00:39:15 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.49,1.50 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv18115 Modified Files: datetime.py Log Message: _ord2ymd(): Strengthened a crucial assertion. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.49 retrieving revision 1.50 diff -C2 -d -r1.49 -r1.50 *** datetime.py 5 Mar 2002 08:30:31 -0000 1.49 --- datetime.py 5 Mar 2002 08:39:13 -0000 1.50 *************** *** 138,143 **** month -= 1 preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear) - assert 0 <= preceding <= n n -= preceding # Now the year and month are correct, and n is the offset from the --- 138,143 ---- month -= 1 preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear) n -= preceding + assert 0 <= n < _days_in_month(month, year) # Now the year and month are correct, and n is the offset from the From tim_one@users.sourceforge.net Tue Mar 5 08:53:35 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 05 Mar 2002 00:53:35 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.35,1.36 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv21491 Modified Files: test_datetime.py Log Message: Typo in comment. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.35 retrieving revision 1.36 diff -C2 -d -r1.35 -r1.36 *** test_datetime.py 5 Mar 2002 08:00:41 -0000 1.35 --- test_datetime.py 5 Mar 2002 08:53:33 -0000 1.36 *************** *** 373,377 **** for timestamp in 123456789.0, 987654321.0: dt = datetime.utcfromtimestamp(timestamp) ! # Manglee the fields, but in such a way that normalization should # restore them to dt's values. tm = tmxxx(dt.year - 1, dt.month + 12, dt.day + 100, --- 373,377 ---- for timestamp in 123456789.0, 987654321.0: dt = datetime.utcfromtimestamp(timestamp) ! # Mangles the fields, but in such a way that normalization should # restore them to dt's values. tm = tmxxx(dt.year - 1, dt.month + 12, dt.day + 100, From tim_one@users.sourceforge.net Tue Mar 5 09:12:46 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 05 Mar 2002 01:12:46 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.50,1.51 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv25482 Modified Files: datetime.py Log Message: _localtzoffset(): If the given date is out of platform mktime()'s range, feed mktime() the same values except for a year that is in its range, and with the same leap-year-ness as the given year. In effect, this imposes a "proleptic" DST determination for years outside the platform range. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.50 retrieving revision 1.51 diff -C2 -d -r1.50 -r1.51 *** datetime.py 5 Mar 2002 08:39:13 -0000 1.50 --- datetime.py 5 Mar 2002 09:12:44 -0000 1.51 *************** *** 259,265 **** return - (_time.timezone // 60) except (ValueError, OverflowError): ! # XXX Dates out of range for mktime() never see DST ! return - (_time.timezone // 60) ! class basetime(object): --- 259,266 ---- return - (_time.timezone // 60) except (ValueError, OverflowError): ! # Dates out of range for mktime() never see DST. ! # As a reasonable guess, though, we can try a year in mktime()'s range ! # with the same leap-year-ness as the given year. ! return _localtzoffset(2003 + _is_leap(year), month, day, hour, minute) class basetime(object): From mal@lemburg.com Tue Mar 5 09:42:37 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Tue, 05 Mar 2002 10:42:37 +0100 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.50,1.51 References: Message-ID: <3C84930D.2E0B0E97@lemburg.com> Tim Peters wrote: > > Update of /cvsroot/python/python/nondist/sandbox/datetime > In directory usw-pr-cvs1:/tmp/cvs-serv25482 > > Modified Files: > datetime.py > Log Message: > _localtzoffset(): If the given date is out of platform mktime()'s range, > feed mktime() the same values except for a year that is in its range, and > with the same leap-year-ness as the given year. In effect, this imposes > a "proleptic" DST determination for years outside the platform range. This fails badly. DST rules change every year and historic DST switch times as well as future ones are not necessarily reliable. Have a look at the TZ package at ftp://elsie.nci.nih.gov/pub/ for some fun with DST. They update those files many times a year. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From tim@zope.com Tue Mar 5 10:16:16 2002 From: tim@zope.com (Tim Peters) Date: Tue, 5 Mar 2002 05:16:16 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.50,1.51 In-Reply-To: <3C84930D.2E0B0E97@lemburg.com> Message-ID: >> _localtzoffset(): If the given date is out of platform >> mktime()'s range, feed mktime() the same values except for a year >> that is in its range, and with the same leap-year-ness as the given >> year. In effect, this imposes a "proleptic" DST determination for >> years outside the platform range. [M.-A. Lemburg] > This fails badly. Oh, fiddlesticks. By construction, the platform C library knows nothing whatsoever about DST in such cases. We're not trying to do substantially better than it can, we're just trying to return an explainable result that's better than random. ECMAScript goes on to substitute a year that also begins with the same weekday, and I'm happy to do that too, but not more than that. The implementation of ECMAScript should not try to determine whether the exact time was subject to daylight saving time, but just whether daylight saving time would have been in effect if the current daylight saving time algorithm had been used at the time. > DST rules change every year and historic DST switch times as well as > future ones are not necessarily reliable. Of course. Ignoring reality in favor of something uniform is what "proleptic" means in this context, in the same way that the "proleptic Gregorian" calendar ignores messy date realities (about real-life discontinuous year numbering, varying dates of adoption across a gazillion principalities, leap seconds changing the lengths of days, and so on). > Have a look at the TZ package at ftp://elsie.nci.nih.gov/pub/ > for some fun with DST. They update those files many times a > year. Actually, we figured we'd leave the 12MB-of-compressed-DST-tables market to eGenix . From mal@lemburg.com Tue Mar 5 10:42:16 2002 From: mal@lemburg.com (M.-A. Lemburg) Date: Tue, 05 Mar 2002 11:42:16 +0100 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.50,1.51 References: Message-ID: <3C84A108.497B534D@lemburg.com> Tim Peters wrote: > > >> _localtzoffset(): If the given date is out of platform > >> mktime()'s range, feed mktime() the same values except for a year > >> that is in its range, and with the same leap-year-ness as the given > >> year. In effect, this imposes a "proleptic" DST determination for > >> years outside the platform range. > > [M.-A. Lemburg] > > This fails badly. > > Oh, fiddlesticks. By construction, the platform C library knows nothing > whatsoever about DST in such cases. We're not trying to do substantially > better than it can, we're just trying to return an explainable result that's > better than random. ECMAScript goes on to substitute a year that also > begins with the same weekday, and I'm happy to do that too, but not more > than that. > > The implementation of ECMAScript should not try to determine > whether the exact time was subject to daylight saving time, but just > whether daylight saving time would have been in effect if the current > daylight saving time algorithm had been used at the time. My point was to not fiddle with the date at all: raise an exception and that's it. > > DST rules change every year and historic DST switch times as well as > > future ones are not necessarily reliable. > > Of course. Ignoring reality in favor of something uniform is what > "proleptic" means in this context, in the same way that the "proleptic > Gregorian" calendar ignores messy date realities (about real-life > discontinuous year numbering, varying dates of adoption across a gazillion > principalities, leap seconds changing the lengths of days, and so on). > > > Have a look at the TZ package at ftp://elsie.nci.nih.gov/pub/ > > for some fun with DST. They update those files many times a > > year. > > Actually, we figured we'd leave the 12MB-of-compressed-DST-tables market to > eGenix . Gee, thanks :-) I'll rather leave that market to the C lib vendors. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH ______________________________________________________________________ Company & Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mwh@users.sourceforge.net Tue Mar 5 13:28:00 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 05:28:00 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects structseq.c,1.3,1.4 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv27068/Objects Modified Files: structseq.c Log Message: A fix & test for [ 496873 ] structseqs unpicklable by adding a __reduce__ method to structseqs. Will also commit this to the 2.2.1 branch momentarily. Index: structseq.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** structseq.c 28 Nov 2001 20:56:44 -0000 1.3 --- structseq.c 5 Mar 2002 13:27:57 -0000 1.4 *************** *** 189,192 **** --- 189,213 ---- } + static PyObject * + structseq_reduce(PyStructSequence* self) + { + PyObject* tup; + long n_fields; + int i; + + n_fields = REAL_SIZE(self); + tup = PyTuple_New(n_fields); + if (!tup) { + return NULL; + } + + for (i = 0; i < n_fields; i++) { + Py_INCREF(self->ob_item[i]); + PyTuple_SET_ITEM(tup, i, self->ob_item[i]); + } + + return Py_BuildValue("(O(O))", self->ob_type, tup); + } + static PySequenceMethods structseq_as_sequence = { (inquiry)structseq_length, *************** *** 200,203 **** --- 221,230 ---- }; + static PyMethodDef structseq_methods[] = { + {"__reduce__", (PyCFunction)structseq_reduce, + METH_NOARGS, NULL}, + {NULL, NULL} + }; + static PyTypeObject _struct_sequence_template = { PyObject_HEAD_INIT(&PyType_Type) *************** *** 229,233 **** 0, /* tp_iter */ 0, /* tp_iternext */ ! 0, /* tp_methods */ NULL, /* tp_members */ 0, /* tp_getset */ --- 256,260 ---- 0, /* tp_iter */ 0, /* tp_iternext */ ! structseq_methods, /* tp_methods */ NULL, /* tp_members */ 0, /* tp_getset */ *************** *** 283,285 **** --- 310,314 ---- PyDict_SetItemString(dict, real_length_key, PyInt_FromLong((long) n_members)); + PyDict_SetItemString(dict, "__safe_for_unpickling__", + PyInt_FromLong(1)); } From mwh@users.sourceforge.net Tue Mar 5 13:28:00 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 05:28:00 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test pickletester.py,1.12,1.13 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv27068/Lib/test Modified Files: pickletester.py Log Message: A fix & test for [ 496873 ] structseqs unpicklable by adding a __reduce__ method to structseqs. Will also commit this to the 2.2.1 branch momentarily. Index: pickletester.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/pickletester.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** pickletester.py 19 Dec 2001 16:58:54 -0000 1.12 --- pickletester.py 5 Mar 2002 13:27:58 -0000 1.13 *************** *** 249,252 **** --- 249,259 ---- self.assertEqual(a.__class__, b.__class__) + def test_structseq(self): + import time + t = time.localtime() + s = self.dumps(t) + u = self.loads(s) + self.assertEqual(t, u) + class AbstractPickleModuleTests(unittest.TestCase): From mwh@users.sourceforge.net Tue Mar 5 13:52:31 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 05:52:31 -0800 Subject: [Python-checkins] CVS: python/dist/src Makefile.pre.in,1.73.4.1,1.73.4.2 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv16469 Modified Files: Tag: release22-maint Makefile.pre.in Log Message: backport gvanrossum's checkin of revision 1.76 of Makefile.pre.in SF patch #524005 by Paul Eggert. Use posixly correct sort args. Bugfix candidate. Index: Makefile.pre.in =================================================================== RCS file: /cvsroot/python/python/dist/src/Makefile.pre.in,v retrieving revision 1.73.4.1 retrieving revision 1.73.4.2 diff -C2 -d -r1.73.4.1 -r1.73.4.2 *** Makefile.pre.in 28 Jan 2002 15:07:45 -0000 1.73.4.1 --- Makefile.pre.in 5 Mar 2002 13:52:29 -0000 1.73.4.2 *************** *** 828,832 **** for i in $(SRCDIRS); do ctags -w -t -a $$i/*.[ch]; \ done; \ ! sort tags -o tags # Create a tags file for GNU Emacs --- 828,832 ---- for i in $(SRCDIRS); do ctags -w -t -a $$i/*.[ch]; \ done; \ ! sort -o tags tags # Create a tags file for GNU Emacs From mwh@users.sourceforge.net Tue Mar 5 13:56:26 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 05:56:26 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python thread_nt.h,2.20,2.20.10.1 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv19738 Modified Files: Tag: release22-maint thread_nt.h Log Message: backport tim_one's checkin of revision 2.22 of thread_nt.h SF patch 522961: Leak in Python/thread_nt.h, from Gerald S. Williams. A file-static "threads" dict mapped thread IDs to Windows handles, but was never referenced, and entries never got removed. This gets rid of the YAGNI-dict entirely. Bugfix candidate. Index: thread_nt.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/thread_nt.h,v retrieving revision 2.20 retrieving revision 2.20.10.1 diff -C2 -d -r2.20 -r2.20.10.1 *** thread_nt.h 16 Oct 2001 21:50:04 -0000 2.20 --- thread_nt.h 5 Mar 2002 13:56:23 -0000 2.20.10.1 *************** *** 2,10 **** /* This code implemented by Dag.Gruneau@elsa.preseco.comm.se */ /* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch@iso.ru */ #include #include #include - #include typedef struct NRMUTEX { --- 2,10 ---- /* This code implemented by Dag.Gruneau@elsa.preseco.comm.se */ /* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch@iso.ru */ + /* Eliminated some memory leaks, gsw@agere.com */ #include #include #include typedef struct NRMUTEX { *************** *** 14,20 **** } NRMUTEX, *PNRMUTEX ; - /* dictionary to correlate thread ids with the handle needed to terminate them*/ - static PyObject *threads = NULL; - typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ; --- 14,17 ---- *************** *** 140,153 **** /* - * Change all headers to pure ANSI as no one will use K&R style on an - * NT - */ - - /* * Initialization of the C package, should not be needed. */ static void PyThread__init_thread(void) { - threads = PyDict_New(); } --- 137,144 ---- *************** *** 183,187 **** callobj *obj; int id; - PyObject *key, *val; dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident())); --- 174,177 ---- *************** *** 204,210 **** WaitForSingleObject(obj->done, 5000); /* maybe INFINITE instead of 5000? */ CloseHandle((HANDLE)obj->done); - key = PyLong_FromLong(obj->id); - val = PyLong_FromLong((long)rv); - PyDict_SetItem(threads, key, val); id = obj->id; free(obj); --- 194,197 ---- From mwh@users.sourceforge.net Tue Mar 5 13:58:16 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 05:58:16 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc ACKS,1.149.4.2,1.149.4.3 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv21380 Modified Files: Tag: release22-maint ACKS Log Message: backport gvanrossum's checkin of revision 1.161 of ACKS SF patch 518765 (Derek Harland): Bug in copy.py when used through rexec. When using a restricted environment, imports of copy will fail with an AttributeError when trying to access types.CodeType. Bugfix candidate (all the way back to 1.5.3, but at least 2.1.3 and 2.2.1). Index: ACKS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/ACKS,v retrieving revision 1.149.4.2 retrieving revision 1.149.4.3 diff -C2 -d -r1.149.4.2 -r1.149.4.3 *** ACKS 28 Feb 2002 10:13:04 -0000 1.149.4.2 --- ACKS 5 Mar 2002 13:58:13 -0000 1.149.4.3 *************** *** 175,178 **** --- 175,179 ---- Barry Hantman Lynda Hardman + Derek Harland Jason Harper Gerhard Häring From mwh@users.sourceforge.net Tue Mar 5 13:58:45 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 05:58:45 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib copy.py,1.22.10.1,1.22.10.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv21762 Modified Files: Tag: release22-maint copy.py Log Message: backport gvanrossum's checkin of revision 1.24 of copy.py SF patch 518765 (Derek Harland): Bug in copy.py when used through rexec. When using a restricted environment, imports of copy will fail with an AttributeError when trying to access types.CodeType. Bugfix candidate (all the way back to 1.5.3, but at least 2.1.3 and 2.2.1). Index: copy.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/copy.py,v retrieving revision 1.22.10.1 retrieving revision 1.22.10.2 diff -C2 -d -r1.22.10.1 -r1.22.10.2 *** copy.py 4 Jan 2002 12:28:43 -0000 1.22.10.1 --- copy.py 5 Mar 2002 13:58:42 -0000 1.22.10.2 *************** *** 198,202 **** except AttributeError: pass ! d[types.CodeType] = _deepcopy_atomic d[types.TypeType] = _deepcopy_atomic d[types.XRangeType] = _deepcopy_atomic --- 198,205 ---- except AttributeError: pass ! try: ! d[types.CodeType] = _deepcopy_atomic ! except AttributeError: ! pass d[types.TypeType] = _deepcopy_atomic d[types.XRangeType] = _deepcopy_atomic From mwh@users.sourceforge.net Tue Mar 5 14:01:31 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 06:01:31 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test pickletester.py,1.12,1.12.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv24336 Modified Files: Tag: release22-maint pickletester.py Log Message: backport my checkin of revision 1.13 of pickletester.py A fix & test for [ 496873 ] structseqs unpicklable by adding a __reduce__ method to structseqs. Will also commit this to the 2.2.1 branch momentarily. Index: pickletester.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/pickletester.py,v retrieving revision 1.12 retrieving revision 1.12.4.1 diff -C2 -d -r1.12 -r1.12.4.1 *** pickletester.py 19 Dec 2001 16:58:54 -0000 1.12 --- pickletester.py 5 Mar 2002 14:01:28 -0000 1.12.4.1 *************** *** 249,252 **** --- 249,259 ---- self.assertEqual(a.__class__, b.__class__) + def test_structseq(self): + import time + t = time.localtime() + s = self.dumps(t) + u = self.loads(s) + self.assertEqual(t, u) + class AbstractPickleModuleTests(unittest.TestCase): From mwh@users.sourceforge.net Tue Mar 5 14:00:56 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 06:00:56 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects structseq.c,1.3,1.3.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv23684 Modified Files: Tag: release22-maint structseq.c Log Message: backport my checkin of revision 1.4 of structseq.c A fix & test for [ 496873 ] structseqs unpicklable by adding a __reduce__ method to structseqs. Will also commit this to the 2.2.1 branch momentarily. Index: structseq.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v retrieving revision 1.3 retrieving revision 1.3.6.1 diff -C2 -d -r1.3 -r1.3.6.1 *** structseq.c 28 Nov 2001 20:56:44 -0000 1.3 --- structseq.c 5 Mar 2002 14:00:52 -0000 1.3.6.1 *************** *** 189,192 **** --- 189,213 ---- } + static PyObject * + structseq_reduce(PyStructSequence* self) + { + PyObject* tup; + long n_fields; + int i; + + n_fields = REAL_SIZE(self); + tup = PyTuple_New(n_fields); + if (!tup) { + return NULL; + } + + for (i = 0; i < n_fields; i++) { + Py_INCREF(self->ob_item[i]); + PyTuple_SET_ITEM(tup, i, self->ob_item[i]); + } + + return Py_BuildValue("(O(O))", self->ob_type, tup); + } + static PySequenceMethods structseq_as_sequence = { (inquiry)structseq_length, *************** *** 200,203 **** --- 221,230 ---- }; + static PyMethodDef structseq_methods[] = { + {"__reduce__", (PyCFunction)structseq_reduce, + METH_NOARGS, NULL}, + {NULL, NULL} + }; + static PyTypeObject _struct_sequence_template = { PyObject_HEAD_INIT(&PyType_Type) *************** *** 229,233 **** 0, /* tp_iter */ 0, /* tp_iternext */ ! 0, /* tp_methods */ NULL, /* tp_members */ 0, /* tp_getset */ --- 256,260 ---- 0, /* tp_iter */ 0, /* tp_iternext */ ! structseq_methods, /* tp_methods */ NULL, /* tp_members */ 0, /* tp_getset */ *************** *** 283,285 **** --- 310,314 ---- PyDict_SetItemString(dict, real_length_key, PyInt_FromLong((long) n_members)); + PyDict_SetItemString(dict, "__safe_for_unpickling__", + PyInt_FromLong(1)); } From mwh@users.sourceforge.net Tue Mar 5 14:00:19 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 06:00:19 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib mailbox.py,1.33,1.33.12.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv22981 Modified Files: Tag: release22-maint mailbox.py Log Message: backport bwarsaw's checkin of revision 1.34 of mailbox.py Added PortableUnixMailbox to the __all__ variable, and in the __main__ section use this class instead of UnixMailbox as per the comments in the latter's class. Bug fix candidate for 2.2.1. Index: mailbox.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/mailbox.py,v retrieving revision 1.33 retrieving revision 1.33.12.1 diff -C2 -d -r1.33 -r1.33.12.1 *** mailbox.py 13 Sep 2001 01:29:13 -0000 1.33 --- mailbox.py 5 Mar 2002 14:00:16 -0000 1.33.12.1 *************** *** 7,11 **** import os ! __all__ = ["UnixMailbox","MmdfMailbox","MHMailbox","Maildir","BabylMailbox"] class _Mailbox: --- 7,12 ---- import os ! __all__ = ["UnixMailbox","MmdfMailbox","MHMailbox","Maildir","BabylMailbox", ! "PortableUnixMailbox"] class _Mailbox: *************** *** 92,95 **** --- 93,97 ---- + # Recommended to use PortableUnixMailbox instead! class UnixMailbox(_Mailbox): def _search_start(self): *************** *** 283,287 **** else: fp = open(mbox, 'r') ! mb = UnixMailbox(fp) msgs = [] --- 285,289 ---- else: fp = open(mbox, 'r') ! mb = PortableUnixMailbox(fp) msgs = [] From gvanrossum@users.sourceforge.net Tue Mar 5 14:14:50 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Mar 2002 06:14:50 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.51,1.52 test_datetime.py,1.36,1.37 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv32276 Modified Files: datetime.py test_datetime.py Log Message: A somewhat yucky but I think necessary change: introduce a separate date class. This implements all the date shuffling; the datetime class then subclasses this and adds more precision and tzoffset fiddling. It's yucky because there's a fair amount of code duplication, alas -- this can probably be reduced by thinking more about which interfaces are needed. It's also necessary because the more I think about it, the more we need a succession of types: - date -- for calendrical computations - xxxx -- for date+time computations without timezone awareness - yyyy -- local-timezone-and-DST-aware date+time computations - zzzz -- UTC date+time computations - datetime -- generalized timezone-and-DST-aware date+time computations I'll try to clean this up some more after my shower. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.51 retrieving revision 1.52 diff -C2 -d -r1.51 -r1.52 *** datetime.py 5 Mar 2002 09:12:44 -0000 1.51 --- datetime.py 5 Mar 2002 14:14:48 -0000 1.52 *************** *** 1,3 **** ! """Concrete date/time type -- prototype implemented in Python. See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage --- 1,3 ---- ! """Concrete date/time and related types -- prototype implemented in Python. See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage *************** *** 506,511 **** ! class datetime(basetime): ! """Concrete date/time type. Constructors: --- 506,751 ---- ! class date(basetime): ! """Concrete date type. ! ! Constructors: ! ! __init__() ! today() ! fromordinal() ! ! Operators: ! ! __repr__, __str__ ! __cmp__, __hash__ ! __add__, __radd__, __sub__ (add/radd only with timedelta arg) ! ! Methods: ! ! timetuple(), utctimetuple() ! toordinal() ! weekday(), isoweekday(), isocalendar() ! isoformat() ! ! Properties (readonly): ! year, month, day ! """ ! ! def __init__(self, year, month, day): ! """Constructor. ! ! Arguments: ! ! year, month, day (required, base 1) ! """ ! if not MINYEAR <= year <= MAXYEAR: ! raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), ! year) ! if not 1 <= month <= 12: ! raise ValueError('month must be in 1..12', month) ! dim = _days_in_month(month, year) ! if not 1 <= day <= dim: ! raise ValueError('day must be in 1..%d' % dim, day) ! self.__year = year ! self.__month = month ! self.__day = day ! ! # Additional constructors ! ! def fromtimestamp(cls, t): ! "Construct a date from a POSIX timestamp (like time.time())." ! y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t) ! us = int((t % 1.0) * 1000000) ! if dst > 0: ! tz = -(_time.altzone // 60) ! else: ! tz = -(_time.timezone // 60) ! return cls(y, m, d) ! fromtimestamp = classmethod(fromtimestamp) ! ! def today(cls): ! "Construct a date from time.time()." ! t = _time.time() ! return cls.fromtimestamp(t) ! today = classmethod(today) ! ! def fromordinal(cls, n): ! """Contruct a date from a proleptic Gregorian ordinal. ! ! January 1 of year 1 is day 1. Only the year, month and day are ! non-zero in the result. ! """ ! y, m, d = _ord2ymd(n) ! return cls(y, m, d) ! fromordinal = classmethod(fromordinal) ! ! # Conversions to string ! ! def __repr__(self): ! "Convert to formal string, for repr()." ! return "%s(%d, %d, %d)" % (self.__class__.__name__, ! self.__year, ! self.__month, ! self.__day) ! ! def __str__(self): ! "Convert to pretty string, for str()." ! return self.isoformat() ! ! # Read-only field accessors ! year = property(lambda self: self.__year, ! doc="year (%d-%d)" % (MINYEAR, MAXYEAR)) ! month = property(lambda self: self.__month, doc="month (1-12)") ! day = property(lambda self: self.__day, doc="day (1-31)") ! ! # Standard conversions, __cmp__, __hash__ (and helpers) ! ! # XXX These should be done without reference to the time module ! ! def _mktime(self): ! # Helper to return a POSIX-ish timestamp ! t = tmxxx(self.__year, self.__month, self.__day) ! return t.time() ! ! def timetuple(self): ! "Return local time tuple compatible with time.localtime()." ! return _time.localtime(self._mktime()) ! ! def toordinal(self): ! """Return proleptic Gregorian ordinal for the year, month and day. ! ! January 1 of year 1 is day 1. Only the year, month and day values ! contribute to the result. ! """ ! return _ymd2ord(self.__year, self.__month, self.__day) ! ! def __cmp__(self, other): ! "Three-way comparison." ! if isinstance(other, date): ! y, m, d = self.__year, self.__month, self.__day ! y2, m2, d2 = other.__year, other.__month, other.__day ! return cmp((y, m, d), (y2, m2, d2)) ! else: ! raise TypeError, ("can't compare date to %s instance" % ! type(other).__name__) ! ! def __hash__(self): ! "Hash." ! # Caution: objects that compare equal must have equal hashcodes, ! # and two dates can be equal even if their fields aren't ! # (due to tzoffset). So we have to compute a UTC-normalized hash. ! return hash((self.__year, self.__month, self.__day)) ! ! # Formatting methods ! ! # XXX These shouldn't depend on time.localtime(), because that ! # clips the usable dates to [1970 .. 2038). At least ctime() is ! # easily done without using strftime() -- that's better too because ! # strftime("%c", ...) is locale specific. ! ! # XXX An additional question is whether ctime() should renormalize ! # to local time, or display the time as entered (which may be ! # confusing since it doesn't show the timezone). ! ! def ctime(self): ! "Format a la ctime() in local time." ! t = tmxxx(self.__year, self.__month, self.__day) ! return t.ctime() ! ! def strftime(self, fmt): ! "Format using strftime() in local time." ! return _time.strftime(fmt, _time.localtime(self._mktime())) ! ! # Computations ! ! def _checkOverflow(self, year): ! if not MINYEAR <= year <= MAXYEAR: ! raise OverflowError("date +/-: result year %d not in %d..%d" % ! (year, MINYEAR, MAXYEAR)) ! ! def __add__(self, other): ! "Add a date to a timedelta." ! if isinstance(other, timedelta): ! t = tmxxx(self.__year, ! self.__month, ! self.__day + other.days) ! self._checkOverflow(t.year) ! result = self.__class__(t.year, t.month, t.day) ! return result ! raise TypeError ! # XXX Should be 'return NotImplemented', but there's a bug in 2.2... ! ! __radd__ = __add__ ! ! timedelta_class = timedelta # Allows a subclass to override ! ! def __sub__(self, other): ! """Subtract two dates, or a date and a timedelta. ! ! An int/long/float argument is also allowed, interpreted as seconds. ! """ ! if isinstance(other, timedelta): ! return self + -other ! if isinstance(other, date): ! days1 = self.toordinal() ! days2 = other.toordinal() ! return self.timedelta_class(days1 - days2) ! return NotImplemented ! ! # Day-of-the-week and week-of-the-year, according to ISO ! ! def weekday(self): ! "Return day of the week, where Monday == 0 ... Sunday == 6." ! return (self.toordinal() + 6) % 7 ! ! def isoweekday(self): ! "Return day of the week, where Monday == 1 ... Sunday == 7." ! # 1-Jan-0001 is a Monday ! return self.toordinal() % 7 or 7 ! ! def isocalendar(self): ! """Return a 3-tuple containing ISO year, week number, and weekday. ! ! The first ISO week of the year is the (Mon-Sun) week ! containing the year's first Thursday; everything rest derives ! from that. ! ! The first week is 1; Monday is 1 ... Sunday is 7. ! ! ISO calendar algorithm taken from ! http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm ! """ ! year = self.__year ! week1monday = _isoweek1monday(year) ! today = _ymd2ord(self.__year, self.__month, self.__day) ! # Internally, week and day have origin 0 ! week, day = divmod(today - week1monday, 7) ! if week < 0: ! year -= 1 ! week1monday = _isoweek1monday(year) ! week, day = divmod(today - week1monday, 7) ! elif week >= 52: ! if today >= _isoweek1monday(year+1): ! year += 1 ! week = 0 ! return year, week+1, day+1 ! ! def isoformat(self): ! """Return the time formatted according to ISO. ! ! This is 'YYYY-MM-DD'. ! ! Optional argument sep specifies the separator between date and ! time, default 'T'. ! """ ! return "%04d-%02d-%02d" % (self.__year, self.__month, self.__day) ! ! date.min = date(1, 1, 1) ! date.max = date(9999, 12, 31) ! date.resolution = timedelta(days=1) ! ! ! class datetime(date): ! """Concrete date/time type, inheriting from date. Constructors: *************** *** 546,557 **** """ ! if not MINYEAR <= year <= MAXYEAR: ! raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), ! year) ! if not 1 <= month <= 12: ! raise ValueError('month must be in 1..12', month) ! dim = _days_in_month(month, year) ! if not 1 <= day <= dim: ! raise ValueError('day must be in 1..%d' % dim, day) if not 0 <= hour <= 23: raise ValueError('hour must be in 0..23', hour) --- 786,790 ---- """ ! super(datetime, self).__init__(year, month, day) if not 0 <= hour <= 23: raise ValueError('hour must be in 0..23', hour) *************** *** 567,570 **** --- 800,804 ---- if not -1439 <= tzoffset <= 1439: raise ValueError('tzoffset must be in -1439..1439', tzoffset) + # XXX This duplicates __year, __month, __day for convenience :-( self.__year = year self.__month = month *************** *** 608,621 **** utcnow = classmethod(utcnow) - def fromordinal(cls, n): - """Contruct a datetime from a proleptic Gregorian ordinal. - - January 1 of year 1 is day 1. Only the year, month and day are - non-zero in the result. - """ - y, m, d = _ord2ymd(n) - return cls(y, m, d) - fromordinal = classmethod(fromordinal) - # Conversions to string --- 842,845 ---- *************** *** 627,631 **** del L[-1] s = ", ".join(map(str, L)) ! return "datetime(%s, tzoffset=%d)" % (s, self.__tzoffset) def __str__(self): --- 851,857 ---- del L[-1] s = ", ".join(map(str, L)) ! return "%s(%s, tzoffset=%d)" % (self.__class__.__name__, ! s, ! self.__tzoffset) def __str__(self): *************** *** 634,641 **** # Read-only field accessors - year = property(lambda self: self.__year, - doc="year (%d-%d)" % (MINYEAR, MAXYEAR)) - month = property(lambda self: self.__month, doc="month (1-12)") - day = property(lambda self: self.__day, doc="day (1-31)") hour = property(lambda self: self.__hour, doc="hour (0-23)") minute = property(lambda self: self.__minute, doc="minute (0-59)") --- 860,863 ---- *************** *** 657,676 **** return t.time() - def timetuple(self): - "Return local time tuple compatible with time.localtime()." - return _time.localtime(self._mktime()) - def utctimetuple(self): "Return UTC time tuple compatible with time.gmtime()." return _time.gmtime(self._mktime()) - def toordinal(self): - """Return proleptic Gregorian ordinal for the year, month and day. - - January 1 of year 1 is day 1. Only the year, month and day values - contribute to the result. - """ - return _ymd2ord(self.__year, self.__month, self.__day) - def __cmp__(self, other): "Three-way comparison." --- 879,886 ---- *************** *** 727,738 **** t = tmxxx(t.year, t.month, t.day, t.hour, t.minute - tzoffset + tzoffset1, self.__second) ! tzoffset2 = _localtzoffset(t.year, t.month, t.day, t.hour, t.minute) assert tzoffset2 == tzoffset1 # XXX Hah! return t.ctime() - def strftime(self, fmt): - "Format using strftime() in local time." - return _time.strftime(fmt, _time.localtime(self._mktime())) - def utcctime(self): "Format a la ctime() in UTC." --- 937,945 ---- t = tmxxx(t.year, t.month, t.day, t.hour, t.minute - tzoffset + tzoffset1, self.__second) ! tzoffset2 = _localtzoffset(t.year, t.month, t.day, ! t.hour, t.minute) assert tzoffset2 == tzoffset1 # XXX Hah! return t.ctime() def utcctime(self): "Format a la ctime() in UTC." *************** *** 747,755 **** # Computations - def _checkOverflow(self, year): - if not MINYEAR <= year <= MAXYEAR: - raise OverflowError("datetime +/-: result year %d not in %d..%d" % - (year, MINYEAR, MAXYEAR)) - def __add__(self, other): "Add a datetime to a timedelta." --- 954,957 ---- *************** *** 772,777 **** __radd__ = __add__ - timedelta_class = timedelta # Allows a subclass to override - def __sub__(self, other): """Subtract two datetimes, or a datetime and a timedelta. --- 974,977 ---- *************** *** 796,836 **** return NotImplemented ! # Day-of-the-week and week-of-the-year, according to ISO ! ! def weekday(self): ! "Return day of the week, where Monday == 0 ... Sunday == 6." ! return (self.toordinal() + 6) % 7 ! ! def isoweekday(self): ! "Return day of the week, where Monday == 1 ... Sunday == 7." ! # 1-Jan-0001 is a Monday ! return self.toordinal() % 7 or 7 ! ! def isocalendar(self): ! """Return a 3-tuple containing ISO year, week number, and weekday. ! ! The first ISO week of the year is the (Mon-Sun) week ! containing the year's first Thursday; everything rest derives ! from that. ! ! The first week is 1; Monday is 1 ... Sunday is 7. ! ! ISO calendar algorithm taken from ! http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm ! """ ! year = self.__year ! week1monday = _isoweek1monday(year) ! today = _ymd2ord(self.__year, self.__month, self.__day) ! # Internally, week and day have origin 0 ! week, day = divmod(today - week1monday, 7) ! if week < 0: ! year -= 1 ! week1monday = _isoweek1monday(year) ! week, day = divmod(today - week1monday, 7) ! elif week >= 52: ! if today >= _isoweek1monday(year+1): ! year += 1 ! week = 0 ! return year, week+1, day+1 def isoformat(self, sep='T'): --- 996,1000 ---- return NotImplemented ! # ISO formats including time and tzoffset def isoformat(self, sep='T'): Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.36 retrieving revision 1.37 diff -C2 -d -r1.36 -r1.37 *** test_datetime.py 5 Mar 2002 08:53:33 -0000 1.36 --- test_datetime.py 5 Mar 2002 14:14:48 -0000 1.37 *************** *** 7,28 **** import unittest ! from datetime import datetime, timedelta, MINYEAR, MAXYEAR ! class TestDateTime(unittest.TestCase): def test_basic_attributes(self): ! dt = datetime(2002, 3, 1, 12, 0, 0) self.assertEqual(dt.year, 2002) self.assertEqual(dt.month, 3) self.assertEqual(dt.day, 1) - self.assertEqual(dt.hour, 12) - self.assertEqual(dt.minute, 0) - self.assertEqual(dt.second, 0) - self.assertEqual(dt.microsecond, 0) def test_roundtrip(self): ! for dt in (datetime(1, 2, 3, 4, 5, 6, 7, 8), ! datetime.now()): ! # Verify dt -> string -> datetime identity. s = repr(dt) dt2 = eval(s) --- 7,91 ---- import unittest ! from datetime import date, datetime, timedelta, MINYEAR, MAXYEAR ! ! class TestTimeDelta(unittest.TestCase): ! ! def test_timedelta(self): ! a = timedelta(7) # One week ! b = timedelta(0, 60) # One minute ! c = timedelta(0, 0, 1000) # One millisecond ! self.assertEqual(a+b+c, timedelta(7, 60, 1000)) ! self.assertEqual(a-b, timedelta(6, 24*3600 - 60)) ! self.assertEqual(-a, timedelta(-7)) ! self.assertEqual(+a, timedelta(7)) ! self.assertEqual(-b, timedelta(-1, 24*3600 - 60)) ! self.assertEqual(-c, timedelta(-1, 24*3600 - 1, 999000)) ! self.assertEqual(abs(a), a) ! self.assertEqual(abs(-a), a) ! self.assertEqual(timedelta(6, 24*3600), a) ! self.assertEqual(timedelta(0, 0, 60*1000000), b) ! self.assertEqual(a*10, timedelta(70)) ! self.assertEqual(a*10, 10*a) ! self.assertEqual(a*10L, 10*a) ! self.assertEqual(b*10, timedelta(0, 600)) ! self.assertEqual(10*b, timedelta(0, 600)) ! self.assertEqual(b*10L, timedelta(0, 600)) ! self.assertEqual(c*10, timedelta(0, 0, 10000)) ! self.assertEqual(10*c, timedelta(0, 0, 10000)) ! self.assertEqual(c*10L, timedelta(0, 0, 10000)) ! self.assertEqual(a*-1, -a) ! self.assertEqual(b*-2, -b-b) ! self.assertEqual(c*-2, -c+-c) ! self.assertEqual(b*(60*24), (b*60)*24) ! self.assertEqual(b*(60*24), (60*b)*24) ! self.assertEqual(c*1000, timedelta(0, 1)) ! self.assertEqual(1000*c, timedelta(0, 1)) ! self.assertEqual(a//7, timedelta(1)) ! self.assertEqual(b//10, timedelta(0, 6)) ! self.assertEqual(c//1000, timedelta(0, 0, 1)) ! self.assertEqual(a//10, timedelta(0, 7*24*360)) ! self.assertEqual(a//3600000, timedelta(0, 0, 7*24*1000)) ! # Add/sub ints, longs, floats should be illegal ! for i in 1, 1L, 1.0: ! self.assertRaises(TypeError, lambda: a+i) ! self.assertRaises(TypeError, lambda: a-i) ! self.assertRaises(TypeError, lambda: i+a) ! self.assertRaises(TypeError, lambda: i-a) ! # Check keyword args to constructor ! eq = self.assertEqual ! td = timedelta ! eq(td(1), td(days=1)) ! eq(td(0, 1), td(seconds=1)) ! eq(td(0, 0, 1), td(microseconds=1)) ! eq(td(weeks=1), td(days=7)) ! eq(td(days=1), td(hours=24)) ! eq(td(hours=1), td(minutes=60)) ! eq(td(minutes=1), td(seconds=60)) ! eq(td(seconds=1), td(milliseconds=1000)) ! eq(td(milliseconds=1), td(microseconds=1000)) ! # Check float args to constructor ! eq(td(weeks=1.0/7), td(days=1)) ! eq(td(days=1.0/24), td(hours=1)) ! eq(td(hours=1.0/60), td(minutes=1)) ! eq(td(minutes=1.0/60), td(seconds=1)) ! eq(td(seconds=0.001), td(milliseconds=1)) ! eq(td(milliseconds=0.001), td(microseconds=1)) ! ! ! class TestDate(unittest.TestCase): ! ! theclass = date def test_basic_attributes(self): ! dt = self.theclass(2002, 3, 1) self.assertEqual(dt.year, 2002) self.assertEqual(dt.month, 3) self.assertEqual(dt.day, 1) def test_roundtrip(self): ! for dt in (self.theclass(1, 2, 3), ! self.theclass.today()): ! # Verify dt -> string -> date identity. s = repr(dt) dt2 = eval(s) *************** *** 30,64 **** # Verify identity via reconstructing from pieces. ! dt2 = datetime(dt.year, dt.month, dt.day, ! dt.hour, dt.minute, dt.second, ! dt.microsecond, dt.tzoffset) self.assertEqual(dt, dt2) - def test_tz_independent_comparing(self): - dt1 = datetime(2002, 3, 1, 9, 0, 0, tzoffset=-60) - dt2 = datetime(2002, 3, 1, 10, 0, 0, tzoffset=-60) - dt3 = datetime(2002, 3, 1, 10, 0, 0, tzoffset=0) - self.assertEqual(dt1, dt3) - self.assert_(dt2 > dt3) - - # Make sure comparison doesn't forget microseconds, and isn't done - # via comparing a float timestamp (an IEEE double doesn't have enough - # precision to span microsecond resolution across years 1 thru 9999, - # so comparing via timestamp necessarily calls some distinct values - # equal). - dt1 = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) - us = timedelta(microseconds=1) - dt2 = dt1 + us - self.assertEqual(dt2 - dt1, us) - self.assert_(dt1 < dt2) - - # Again, but mix timezones. - dt1 = datetime(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60) - dt2 = datetime(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) - self.assertEqual(dt1, dt2) - dt2 += us - self.assertEqual(dt2 - dt1, us) - self.assert_(dt1 < dt2) - def test_ordinal_conversions(self): from datetime import _ymd2ord, _ord2ymd --- 93,99 ---- # Verify identity via reconstructing from pieces. ! dt2 = self.theclass(dt.year, dt.month, dt.day) self.assertEqual(dt, dt2) def test_ordinal_conversions(self): from datetime import _ymd2ord, _ord2ymd *************** *** 98,151 **** def test_bad_constructor_arguments(self): # bad years ! datetime(MINYEAR, 1, 1) # no exception ! datetime(MAXYEAR, 1, 1) # no exception ! self.assertRaises(ValueError, datetime, MINYEAR-1, 1, 1) ! self.assertRaises(ValueError, datetime, MAXYEAR+1, 1, 1) # bad months ! datetime(2000, 1, 1) # no exception ! datetime(2000, 12, 1) # no exception ! self.assertRaises(ValueError, datetime, 2000, 0, 1) ! self.assertRaises(ValueError, datetime, 2000, 13, 1) # bad days ! datetime(2000, 2, 29) # no exception ! datetime(2004, 2, 29) # no exception ! datetime(2400, 2, 29) # no exception ! self.assertRaises(ValueError, datetime, 2000, 2, 30) ! self.assertRaises(ValueError, datetime, 2001, 2, 29) ! self.assertRaises(ValueError, datetime, 2100, 2, 29) ! self.assertRaises(ValueError, datetime, 1900, 2, 29) ! self.assertRaises(ValueError, datetime, 2000, 1, 0) ! self.assertRaises(ValueError, datetime, 2000, 1, 32) ! # bad hours ! datetime(2000, 1, 31, 0) # no exception ! datetime(2000, 1, 31, 23) # no exception ! self.assertRaises(ValueError, datetime, 2000, 1, 31, -1) ! self.assertRaises(ValueError, datetime, 2000, 1, 31, 24) ! # bad minutes ! datetime(2000, 1, 31, 23, 0) # no exception ! datetime(2000, 1, 31, 23, 59) # no exception ! self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, -1) ! self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 60) ! # bad seconds ! datetime(2000, 1, 31, 23, 59, 0) # no exception ! datetime(2000, 1, 31, 23, 59, 59) # no exception ! self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, -1) ! self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 60) ! # bad microseconds ! datetime(2000, 1, 31, 23, 59, 59, 0) # no exception ! datetime(2000, 1, 31, 23, 59, 59, 999999) # no exception ! self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 59, -1) ! self.assertRaises(ValueError, datetime, 2000, 1, 31, 23, 59, 59, ! 1000000) ! # bad tzoffet ! datetime(2, 1, 1, 0, 0, 0, 0, -1439) # no exception ! datetime(2, 1, 1, 0, 0, 0, 0, 1439) # no exception ! self.assertRaises(ValueError, datetime, 2, 1, 1, 0, 0, 0, 0, -1440) ! self.assertRaises(ValueError, datetime, 2, 1, 1, 0, 0, 0, 0, 1440) def test_hash_equality(self): ! d = datetime(2000, 12, 31, 23, 30, 17, tzoffset=-35) ! # same thing in UTC. ! e = datetime(2001, 1, 1, 0, 5, 17, tzoffset=0) self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) --- 133,160 ---- def test_bad_constructor_arguments(self): # bad years ! self.theclass(MINYEAR, 1, 1) # no exception ! self.theclass(MAXYEAR, 1, 1) # no exception ! self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1) ! self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1) # bad months ! self.theclass(2000, 1, 1) # no exception ! self.theclass(2000, 12, 1) # no exception ! self.assertRaises(ValueError, self.theclass, 2000, 0, 1) ! self.assertRaises(ValueError, self.theclass, 2000, 13, 1) # bad days ! self.theclass(2000, 2, 29) # no exception ! self.theclass(2004, 2, 29) # no exception ! self.theclass(2400, 2, 29) # no exception ! self.assertRaises(ValueError, self.theclass, 2000, 2, 30) ! self.assertRaises(ValueError, self.theclass, 2001, 2, 29) ! self.assertRaises(ValueError, self.theclass, 2100, 2, 29) ! self.assertRaises(ValueError, self.theclass, 1900, 2, 29) ! self.assertRaises(ValueError, self.theclass, 2000, 1, 0) ! self.assertRaises(ValueError, self.theclass, 2000, 1, 32) def test_hash_equality(self): ! d = self.theclass(2000, 12, 31) ! # same thing ! e = self.theclass(2000, 12, 31) self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) *************** *** 157,163 **** self.assertEqual(dic[e], 2) ! d = datetime(2001, 1, 1, 0, 5, 17, tzoffset=35) ! # same thing in UTC. ! e = datetime(2000, 12, 31, 23, 30, 17, tzoffset=0) self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) --- 166,172 ---- self.assertEqual(dic[e], 2) ! d = self.theclass(2001, 1, 1) ! # same thing ! e = self.theclass(2001, 1, 1) self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) *************** *** 169,280 **** self.assertEqual(dic[e], 2) - def test_timedelta(self): - a = timedelta(7) # One week - b = timedelta(0, 60) # One minute - c = timedelta(0, 0, 1000) # One millisecond - self.assertEqual(a+b+c, timedelta(7, 60, 1000)) - self.assertEqual(a-b, timedelta(6, 24*3600 - 60)) - self.assertEqual(-a, timedelta(-7)) - self.assertEqual(+a, timedelta(7)) - self.assertEqual(-b, timedelta(-1, 24*3600 - 60)) - self.assertEqual(-c, timedelta(-1, 24*3600 - 1, 999000)) - self.assertEqual(abs(a), a) - self.assertEqual(abs(-a), a) - self.assertEqual(timedelta(6, 24*3600), a) - self.assertEqual(timedelta(0, 0, 60*1000000), b) - self.assertEqual(a*10, timedelta(70)) - self.assertEqual(a*10, 10*a) - self.assertEqual(a*10L, 10*a) - self.assertEqual(b*10, timedelta(0, 600)) - self.assertEqual(10*b, timedelta(0, 600)) - self.assertEqual(b*10L, timedelta(0, 600)) - self.assertEqual(c*10, timedelta(0, 0, 10000)) - self.assertEqual(10*c, timedelta(0, 0, 10000)) - self.assertEqual(c*10L, timedelta(0, 0, 10000)) - self.assertEqual(a*-1, -a) - self.assertEqual(b*-2, -b-b) - self.assertEqual(c*-2, -c+-c) - self.assertEqual(b*(60*24), (b*60)*24) - self.assertEqual(b*(60*24), (60*b)*24) - self.assertEqual(c*1000, timedelta(0, 1)) - self.assertEqual(1000*c, timedelta(0, 1)) - self.assertEqual(a//7, timedelta(1)) - self.assertEqual(b//10, timedelta(0, 6)) - self.assertEqual(c//1000, timedelta(0, 0, 1)) - self.assertEqual(a//10, timedelta(0, 7*24*360)) - self.assertEqual(a//3600000, timedelta(0, 0, 7*24*1000)) - # Add/sub ints, longs, floats should be illegal - for i in 1, 1L, 1.0: - self.assertRaises(TypeError, lambda: a+i) - self.assertRaises(TypeError, lambda: a-i) - self.assertRaises(TypeError, lambda: i+a) - self.assertRaises(TypeError, lambda: i-a) - # Check keyword args to constructor - eq = self.assertEqual - td = timedelta - eq(td(1), td(days=1)) - eq(td(0, 1), td(seconds=1)) - eq(td(0, 0, 1), td(microseconds=1)) - eq(td(weeks=1), td(days=7)) - eq(td(days=1), td(hours=24)) - eq(td(hours=1), td(minutes=60)) - eq(td(minutes=1), td(seconds=60)) - eq(td(seconds=1), td(milliseconds=1000)) - eq(td(milliseconds=1), td(microseconds=1000)) - # Check float args to constructor - eq(td(weeks=1.0/7), td(days=1)) - eq(td(days=1.0/24), td(hours=1)) - eq(td(hours=1.0/60), td(minutes=1)) - eq(td(minutes=1.0/60), td(seconds=1)) - eq(td(seconds=0.001), td(milliseconds=1)) - eq(td(milliseconds=0.001), td(microseconds=1)) - def test_computations(self): ! a = datetime(2002, 1, 31) ! b = datetime(1956, 1, 31) diff = a-b self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) self.assertEqual(diff.seconds, 0) self.assertEqual(diff.microseconds, 0) - a = datetime(2002, 3, 2, 17, 6) - millisec = timedelta(0, 0, 1000) - hour = timedelta(0, 3600) day = timedelta(1) week = timedelta(7) ! self.assertEqual(a + hour, datetime(2002, 3, 2, 18, 6)) ! self.assertEqual(a + 10*hour, datetime(2002, 3, 3, 3, 6)) ! self.assertEqual(a - hour, datetime(2002, 3, 2, 16, 6)) ! self.assertEqual(a - hour, a + -hour) ! self.assertEqual(a - 20*hour, datetime(2002, 3, 1, 21, 6)) ! self.assertEqual(a + day, datetime(2002, 3, 3, 17, 6)) ! self.assertEqual(a - day, datetime(2002, 3, 1, 17, 6)) ! self.assertEqual(a + week, datetime(2002, 3, 9, 17, 6)) ! self.assertEqual(a - week, datetime(2002, 2, 23, 17, 6)) ! self.assertEqual(a + 52*week, datetime(2003, 3, 1, 17, 6)) ! self.assertEqual(a - 52*week, datetime(2001, 3, 3, 17, 6)) self.assertEqual((a + week) - a, week) self.assertEqual((a + day) - a, day) - self.assertEqual((a + hour) - a, hour) - self.assertEqual((a + millisec) - a, millisec) self.assertEqual((a - week) - a, -week) self.assertEqual((a - day) - a, -day) - self.assertEqual((a - hour) - a, -hour) - self.assertEqual((a - millisec) - a, -millisec) self.assertEqual(a - (a + week), -week) self.assertEqual(a - (a + day), -day) - self.assertEqual(a - (a + hour), -hour) - self.assertEqual(a - (a + millisec), -millisec) self.assertEqual(a - (a - week), week) self.assertEqual(a - (a - day), day) - self.assertEqual(a - (a - hour), hour) - self.assertEqual(a - (a - millisec), millisec) - self.assertEqual(a + (week + day + hour + millisec), - datetime(2002, 3, 10, 18, 6, 0, 1000)) - self.assertEqual(a + (week + day + hour + millisec), - (((a + week) + day) + hour) + millisec) - self.assertEqual(a - (week + day + hour + millisec), - datetime(2002, 2, 22, 16, 5, 59, 999000)) - self.assertEqual(a - (week + day + hour + millisec), - (((a - week) - day) - hour) - millisec) # Add/sub ints, longs, floats should be illegal for i in 1, 1L, 1.0: --- 178,205 ---- self.assertEqual(dic[e], 2) def test_computations(self): ! a = self.theclass(2002, 1, 31) ! b = self.theclass(1956, 1, 31) diff = a-b self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) self.assertEqual(diff.seconds, 0) self.assertEqual(diff.microseconds, 0) day = timedelta(1) week = timedelta(7) ! a = self.theclass(2002, 3, 2) ! self.assertEqual(a + day, self.theclass(2002, 3, 3)) ! self.assertEqual(a - day, self.theclass(2002, 3, 1)) ! self.assertEqual(a + week, self.theclass(2002, 3, 9)) ! self.assertEqual(a - week, self.theclass(2002, 2, 23)) ! self.assertEqual(a + 52*week, self.theclass(2003, 3, 1)) ! self.assertEqual(a - 52*week, self.theclass(2001, 3, 3)) self.assertEqual((a + week) - a, week) self.assertEqual((a + day) - a, day) self.assertEqual((a - week) - a, -week) self.assertEqual((a - day) - a, -day) self.assertEqual(a - (a + week), -week) self.assertEqual(a - (a + day), -day) self.assertEqual(a - (a - week), week) self.assertEqual(a - (a - day), day) # Add/sub ints, longs, floats should be illegal for i in 1, 1L, 1.0: *************** *** 285,296 **** def test_overflow(self): ! tiny = datetime.resolution ! dt = datetime.min + tiny dt -= tiny # no problem self.assertRaises(OverflowError, dt.__sub__, tiny) self.assertRaises(OverflowError, dt.__add__, -tiny) ! dt = datetime.max - tiny dt += tiny # no problem self.assertRaises(OverflowError, dt.__add__, tiny) --- 210,221 ---- def test_overflow(self): ! tiny = self.theclass.resolution ! dt = self.theclass.min + tiny dt -= tiny # no problem self.assertRaises(OverflowError, dt.__sub__, tiny) self.assertRaises(OverflowError, dt.__add__, -tiny) ! dt = self.theclass.max - tiny dt += tiny # no problem self.assertRaises(OverflowError, dt.__add__, tiny) *************** *** 300,308 **** for i in range(7): # March 4, 2002 is a Monday ! self.assertEqual(datetime(2002, 3, 4+i).weekday(), i) ! self.assertEqual(datetime(2002, 3, 4+i).isoweekday(), i+1) # January 2, 1956 is a Monday ! self.assertEqual(datetime(1956, 1, 2+i).weekday(), i) ! self.assertEqual(datetime(1956, 1, 2+i).isoweekday(), i+1) def test_isocalendar(self): --- 225,233 ---- for i in range(7): # March 4, 2002 is a Monday ! self.assertEqual(self.theclass(2002, 3, 4+i).weekday(), i) ! self.assertEqual(self.theclass(2002, 3, 4+i).isoweekday(), i+1) # January 2, 1956 is a Monday ! self.assertEqual(self.theclass(1956, 1, 2+i).weekday(), i) ! self.assertEqual(self.theclass(1956, 1, 2+i).isoweekday(), i+1) def test_isocalendar(self): *************** *** 310,324 **** # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for i in range(7): ! d = datetime(2003, 12, 22+i) self.assertEqual(d.isocalendar(), (2003, 52, i+1)) ! d = datetime(2003, 12, 29) + timedelta(i) self.assertEqual(d.isocalendar(), (2004, 1, i+1)) ! d = datetime(2004, 1, 5+i) self.assertEqual(d.isocalendar(), (2004, 2, i+1)) ! d = datetime(2009, 12, 21+i) self.assertEqual(d.isocalendar(), (2009, 52, i+1)) ! d = datetime(2009, 12, 28) + timedelta(i) self.assertEqual(d.isocalendar(), (2009, 53, i+1)) ! d = datetime(2010, 1, 4+i) self.assertEqual(d.isocalendar(), (2010, 1, i+1)) --- 235,249 ---- # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm for i in range(7): ! d = self.theclass(2003, 12, 22+i) self.assertEqual(d.isocalendar(), (2003, 52, i+1)) ! d = self.theclass(2003, 12, 29) + timedelta(i) self.assertEqual(d.isocalendar(), (2004, 1, i+1)) ! d = self.theclass(2004, 1, 5+i) self.assertEqual(d.isocalendar(), (2004, 2, i+1)) ! d = self.theclass(2009, 12, 21+i) self.assertEqual(d.isocalendar(), (2009, 52, i+1)) ! d = self.theclass(2009, 12, 28) + timedelta(i) self.assertEqual(d.isocalendar(), (2009, 53, i+1)) ! d = self.theclass(2010, 1, 4+i) self.assertEqual(d.isocalendar(), (2010, 1, i+1)) *************** *** 355,360 **** L = [] for i in range(400): ! d = datetime(2000+i, 12, 31) ! d1 = datetime(1600+i, 12, 31) self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:]) if d.isocalendar()[1] == 53: --- 280,285 ---- L = [] for i in range(400): ! d = self.theclass(2000+i, 12, 31) ! d1 = self.theclass(1600+i, 12, 31) self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:]) if d.isocalendar()[1] == 53: *************** *** 363,367 **** def test_isoformat(self): ! t = datetime(2, 3, 2, 4, 5, 1, 123, tzoffset=-120) self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123-02:00") self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123-02:00") --- 288,502 ---- def test_isoformat(self): ! t = self.theclass(2, 3, 2) ! self.assertEqual(t.isoformat(), "0002-03-02") ! ! def test_ctime(self): ! t = self.theclass(2002, 3, 2) ! self.assertEqual(t.ctime(), "Sat Mar 2 00:00:00 2002") ! ! def test_resolution_info(self): ! self.assert_(isinstance(self.theclass.min, self.theclass)) ! self.assert_(isinstance(self.theclass.max, self.theclass)) ! self.assert_(isinstance(self.theclass.resolution, timedelta)) ! self.assert_(self.theclass.max > self.theclass.min) ! ! def test_extreme_timedelta(self): ! big = self.theclass.max - self.theclass.min ! # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds ! n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds ! # n = 315537897599999999 ~= 2**58.13 ! justasbig = timedelta(0, 0, n) ! self.assertEqual(big, justasbig) ! self.assertEqual(self.theclass.min + big, self.theclass.max) ! self.assertEqual(self.theclass.max - big, self.theclass.min) ! ! ! class TestDateTime(TestDate): ! ! theclass = datetime ! ! def test_basic_attributes(self): ! dt = self.theclass(2002, 3, 1, 12, 0, 0) ! self.assertEqual(dt.year, 2002) ! self.assertEqual(dt.month, 3) ! self.assertEqual(dt.day, 1) ! self.assertEqual(dt.hour, 12) ! self.assertEqual(dt.minute, 0) ! self.assertEqual(dt.second, 0) ! self.assertEqual(dt.microsecond, 0) ! ! def test_roundtrip(self): ! for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7, 8), ! self.theclass.now()): ! # Verify dt -> string -> datetime identity. ! s = repr(dt) ! dt2 = eval(s) ! self.assertEqual(dt, dt2) ! ! # Verify identity via reconstructing from pieces. ! dt2 = self.theclass(dt.year, dt.month, dt.day, ! dt.hour, dt.minute, dt.second, ! dt.microsecond, dt.tzoffset) ! self.assertEqual(dt, dt2) ! ! def test_tz_independent_comparing(self): ! dt1 = self.theclass(2002, 3, 1, 9, 0, 0, tzoffset=-60) ! dt2 = self.theclass(2002, 3, 1, 10, 0, 0, tzoffset=-60) ! dt3 = self.theclass(2002, 3, 1, 10, 0, 0, tzoffset=0) ! self.assertEqual(dt1, dt3) ! self.assert_(dt2 > dt3) ! ! # Make sure comparison doesn't forget microseconds, and isn't done ! # via comparing a float timestamp (an IEEE double doesn't have enough ! # precision to span microsecond resolution across years 1 thru 9999, ! # so comparing via timestamp necessarily calls some distinct values ! # equal). ! dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) ! us = timedelta(microseconds=1) ! dt2 = dt1 + us ! self.assertEqual(dt2 - dt1, us) ! self.assert_(dt1 < dt2) ! ! # Again, but mix timezones. ! dt1 = self.theclass(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60) ! dt2 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) ! self.assertEqual(dt1, dt2) ! dt2 += us ! self.assertEqual(dt2 - dt1, us) ! self.assert_(dt1 < dt2) ! ! def test_bad_constructor_arguments(self): ! # bad years ! self.theclass(MINYEAR, 1, 1) # no exception ! self.theclass(MAXYEAR, 1, 1) # no exception ! self.assertRaises(ValueError, self.theclass, MINYEAR-1, 1, 1) ! self.assertRaises(ValueError, self.theclass, MAXYEAR+1, 1, 1) ! # bad months ! self.theclass(2000, 1, 1) # no exception ! self.theclass(2000, 12, 1) # no exception ! self.assertRaises(ValueError, self.theclass, 2000, 0, 1) ! self.assertRaises(ValueError, self.theclass, 2000, 13, 1) ! # bad days ! self.theclass(2000, 2, 29) # no exception ! self.theclass(2004, 2, 29) # no exception ! self.theclass(2400, 2, 29) # no exception ! self.assertRaises(ValueError, self.theclass, 2000, 2, 30) ! self.assertRaises(ValueError, self.theclass, 2001, 2, 29) ! self.assertRaises(ValueError, self.theclass, 2100, 2, 29) ! self.assertRaises(ValueError, self.theclass, 1900, 2, 29) ! self.assertRaises(ValueError, self.theclass, 2000, 1, 0) ! self.assertRaises(ValueError, self.theclass, 2000, 1, 32) ! # bad hours ! self.theclass(2000, 1, 31, 0) # no exception ! self.theclass(2000, 1, 31, 23) # no exception ! self.assertRaises(ValueError, self.theclass, 2000, 1, 31, -1) ! self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 24) ! # bad minutes ! self.theclass(2000, 1, 31, 23, 0) # no exception ! self.theclass(2000, 1, 31, 23, 59) # no exception ! self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, -1) ! self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 60) ! # bad seconds ! self.theclass(2000, 1, 31, 23, 59, 0) # no exception ! self.theclass(2000, 1, 31, 23, 59, 59) # no exception ! self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, -1) ! self.assertRaises(ValueError, self.theclass, 2000, 1, 31, 23, 59, 60) ! # bad microseconds ! self.theclass(2000, 1, 31, 23, 59, 59, 0) # no exception ! self.theclass(2000, 1, 31, 23, 59, 59, 999999) # no exception ! self.assertRaises(ValueError, self.theclass, ! 2000, 1, 31, 23, 59, 59, -1) ! self.assertRaises(ValueError, self.theclass, ! 2000, 1, 31, 23, 59, 59, ! 1000000) ! # bad tzoffet ! self.theclass(2, 1, 1, 0, 0, 0, 0, -1439) # no exception ! self.theclass(2, 1, 1, 0, 0, 0, 0, 1439) # no exception ! self.assertRaises(ValueError, self.theclass, ! 2, 1, 1, 0, 0, 0, 0, -1440) ! self.assertRaises(ValueError, self.theclass, ! 2, 1, 1, 0, 0, 0, 0, 1440) ! ! def test_hash_equality(self): ! d = self.theclass(2000, 12, 31, 23, 30, 17, tzoffset=-35) ! # same thing in UTC. ! e = self.theclass(2001, 1, 1, 0, 5, 17, tzoffset=0) ! self.assertEqual(d, e) ! self.assertEqual(hash(d), hash(e)) ! ! dic = {d: 1} ! dic[e] = 2 ! self.assertEqual(len(dic), 1) ! self.assertEqual(dic[d], 2) ! self.assertEqual(dic[e], 2) ! ! d = self.theclass(2001, 1, 1, 0, 5, 17, tzoffset=35) ! # same thing in UTC. ! e = self.theclass(2000, 12, 31, 23, 30, 17, tzoffset=0) ! self.assertEqual(d, e) ! self.assertEqual(hash(d), hash(e)) ! ! dic = {d: 1} ! dic[e] = 2 ! self.assertEqual(len(dic), 1) ! self.assertEqual(dic[d], 2) ! self.assertEqual(dic[e], 2) ! ! def test_computations(self): ! a = self.theclass(2002, 1, 31) ! b = self.theclass(1956, 1, 31) ! diff = a-b ! self.assertEqual(diff.days, 46*365 + len(range(1956, 2002, 4))) ! self.assertEqual(diff.seconds, 0) ! self.assertEqual(diff.microseconds, 0) ! a = self.theclass(2002, 3, 2, 17, 6) ! millisec = timedelta(0, 0, 1000) ! hour = timedelta(0, 3600) ! day = timedelta(1) ! week = timedelta(7) ! self.assertEqual(a + hour, self.theclass(2002, 3, 2, 18, 6)) ! self.assertEqual(a + 10*hour, self.theclass(2002, 3, 3, 3, 6)) ! self.assertEqual(a - hour, self.theclass(2002, 3, 2, 16, 6)) ! self.assertEqual(a - hour, a + -hour) ! self.assertEqual(a - 20*hour, self.theclass(2002, 3, 1, 21, 6)) ! self.assertEqual(a + day, self.theclass(2002, 3, 3, 17, 6)) ! self.assertEqual(a - day, self.theclass(2002, 3, 1, 17, 6)) ! self.assertEqual(a + week, self.theclass(2002, 3, 9, 17, 6)) ! self.assertEqual(a - week, self.theclass(2002, 2, 23, 17, 6)) ! self.assertEqual(a + 52*week, self.theclass(2003, 3, 1, 17, 6)) ! self.assertEqual(a - 52*week, self.theclass(2001, 3, 3, 17, 6)) ! self.assertEqual((a + week) - a, week) ! self.assertEqual((a + day) - a, day) ! self.assertEqual((a + hour) - a, hour) ! self.assertEqual((a + millisec) - a, millisec) ! self.assertEqual((a - week) - a, -week) ! self.assertEqual((a - day) - a, -day) ! self.assertEqual((a - hour) - a, -hour) ! self.assertEqual((a - millisec) - a, -millisec) ! self.assertEqual(a - (a + week), -week) ! self.assertEqual(a - (a + day), -day) ! self.assertEqual(a - (a + hour), -hour) ! self.assertEqual(a - (a + millisec), -millisec) ! self.assertEqual(a - (a - week), week) ! self.assertEqual(a - (a - day), day) ! self.assertEqual(a - (a - hour), hour) ! self.assertEqual(a - (a - millisec), millisec) ! self.assertEqual(a + (week + day + hour + millisec), ! self.theclass(2002, 3, 10, 18, 6, 0, 1000)) ! self.assertEqual(a + (week + day + hour + millisec), ! (((a + week) + day) + hour) + millisec) ! self.assertEqual(a - (week + day + hour + millisec), ! self.theclass(2002, 2, 22, 16, 5, 59, 999000)) ! self.assertEqual(a - (week + day + hour + millisec), ! (((a - week) - day) - hour) - millisec) ! # Add/sub ints, longs, floats should be illegal ! for i in 1, 1L, 1.0: ! self.assertRaises(TypeError, lambda: a+i) ! self.assertRaises(TypeError, lambda: a-i) ! self.assertRaises(TypeError, lambda: i+a) ! self.assertRaises(TypeError, lambda: i-a) ! ! def test_isoformat(self): ! t = self.theclass(2, 3, 2, 4, 5, 1, 123, tzoffset=-120) self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123-02:00") self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123-02:00") *************** *** 372,376 **** from datetime import tmxxx for timestamp in 123456789.0, 987654321.0: ! dt = datetime.utcfromtimestamp(timestamp) # Mangles the fields, but in such a way that normalization should # restore them to dt's values. --- 507,511 ---- from datetime import tmxxx for timestamp in 123456789.0, 987654321.0: ! dt = self.theclass.utcfromtimestamp(timestamp) # Mangles the fields, but in such a way that normalization should # restore them to dt's values. *************** *** 378,388 **** dt.hour - 24*100, dt.minute - 3, dt.second + 12, (3*60 - 12) * 1000000) ! dt2 = datetime(tm.year, tm.month, tm.day, tm.hour, tm.minute, ! tm.second, tm.microsecond, tzoffset=0) self.assertEqual(dt, dt2) self.assertEqual(timestamp, tm.time()) def test_ctime(self): ! t = datetime(2002, 3, 2, 18, 3, 5, 123) self.assertEqual(t.ctime(), "Sat Mar 2 18:03:05 2002") # XXX Can only test utcctime() in known timezone :-( --- 513,523 ---- dt.hour - 24*100, dt.minute - 3, dt.second + 12, (3*60 - 12) * 1000000) ! dt2 = self.theclass(tm.year, tm.month, tm.day, tm.hour, tm.minute, ! tm.second, tm.microsecond, tzoffset=0) self.assertEqual(dt, dt2) self.assertEqual(timestamp, tm.time()) def test_ctime(self): ! t = self.theclass(2002, 3, 2, 18, 3, 5, 123) self.assertEqual(t.ctime(), "Sat Mar 2 18:03:05 2002") # XXX Can only test utcctime() in known timezone :-( *************** *** 398,420 **** self.fail("Can't test utcctime()") - def test_resolution_info(self): - self.assert_(isinstance(datetime.min, datetime)) - self.assert_(isinstance(datetime.max, datetime)) - self.assert_(isinstance(datetime.resolution, timedelta)) - self.assert_(datetime.max > datetime.min) - - def test_extreme_timedelta(self): - big = datetime.max - datetime.min - # 3652058 days, 23 hours, 59 minutes, 59 seconds, 999999 microseconds - n = (big.days*24*3600 + big.seconds)*1000000 + big.microseconds - # n = 315537897599999999 ~= 2**58.13 - justasbig = timedelta(0, 0, n) - self.assertEqual(big, justasbig) - self.assertEqual(datetime.min + big, datetime.max) - self.assertEqual(datetime.max - big, datetime.min) def test_suite(): ! s1 = unittest.makeSuite(TestDateTime, 'test') ! return unittest.TestSuite([s1]) def test_main(): --- 533,542 ---- self.fail("Can't test utcctime()") def test_suite(): ! s1 = unittest.makeSuite(TestTimeDelta, 'test') ! s2 = unittest.makeSuite(TestDate, 'test') ! s3 = unittest.makeSuite(TestDateTime, 'test') ! return unittest.TestSuite([s1, s2, s3]) def test_main(): From mwh@users.sourceforge.net Tue Mar 5 14:20:34 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 06:20:34 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules mpzmodule.c,2.38,2.38.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv8376 Modified Files: Tag: release22-maint mpzmodule.c Log Message: backport gvanrossum's checkin of revision 2.40 of mpzmodule.c SF patch 517245 by Marc Recht. Support GMP version >= 2. Bugfix candidate. Index: mpzmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/mpzmodule.c,v retrieving revision 2.38 retrieving revision 2.38.6.1 diff -C2 -d -r2.38 -r2.38.6.1 *** mpzmodule.c 8 Dec 2001 18:02:57 -0000 2.38 --- mpzmodule.c 5 Mar 2002 14:20:32 -0000 2.38.6.1 *************** *** 63,67 **** #include "gmp.h" ! #if __GNU_MP__ + 0 == 2 #define GMP2 #define BITS_PER_MP_LIMB mp_bits_per_limb --- 63,67 ---- #include "gmp.h" ! #if __GNU_MP__ + 0 >= 2 #define GMP2 #define BITS_PER_MP_LIMB mp_bits_per_limb From mwh@users.sourceforge.net Tue Mar 5 14:20:53 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 06:20:53 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc ACKS,1.149.4.3,1.149.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv8676 Modified Files: Tag: release22-maint ACKS Log Message: backport gvanrossum's checkin of revision 1.162 of ACKS SF patch 517245 by Marc Recht. Support GMP version >= 2. Bugfix candidate. Index: ACKS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/ACKS,v retrieving revision 1.149.4.3 retrieving revision 1.149.4.4 diff -C2 -d -r1.149.4.3 -r1.149.4.4 *** ACKS 5 Mar 2002 13:58:13 -0000 1.149.4.3 --- ACKS 5 Mar 2002 14:20:51 -0000 1.149.4.4 *************** *** 349,352 **** --- 349,353 ---- Eric Raymond Edward K. Ream + Marc Recht John Redford Terry Reedy From mwh@users.sourceforge.net Tue Mar 5 14:23:58 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 06:23:58 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects object.c,2.162,2.162.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv11399 Modified Files: Tag: release22-maint object.c Log Message: backport tim_one's checkin of revision 2.164 of object.c Whether platform malloc(0) returns NULL has nothing to do with whether platform realloc(p, 0) returns NULL, so MALLOC_ZERO_RETURNS_NULL can be correctly undefined yet realloc(p, 0) can return NULL anyway. Prevent realloc(p, 0) doing free(p) and returning NULL via a different hack. Would probably be better to get rid of MALLOC_ZERO_RETURNS_NULL entirely. Bugfix candidate. Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.162 retrieving revision 2.162.6.1 diff -C2 -d -r2.162 -r2.162.6.1 *** object.c 4 Dec 2001 15:54:53 -0000 2.162 --- object.c 5 Mar 2002 14:23:56 -0000 2.162.6.1 *************** *** 1889,1897 **** PyMem_Realloc(void *p, size_t nbytes) { ! #if _PyMem_EXTRA > 0 ! if (nbytes == 0) ! nbytes = _PyMem_EXTRA; ! #endif ! return PyMem_REALLOC(p, nbytes); } --- 1889,1894 ---- PyMem_Realloc(void *p, size_t nbytes) { ! /* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */ ! return PyMem_REALLOC(p, nbytes ? nbytes : 1); } From mwh@users.sourceforge.net Tue Mar 5 14:24:47 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 06:24:47 -0800 Subject: [Python-checkins] CVS: python/dist/src/Include pymem.h,2.4,2.4.16.1 pyport.h,2.40,2.40.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv12181 Modified Files: Tag: release22-maint pymem.h pyport.h Log Message: backport tim_one's checkin of revision 2.5 of pymem.h revision 2.44 of pyport.h Whether platform malloc(0) returns NULL has nothing to do with whether platform realloc(p, 0) returns NULL, so MALLOC_ZERO_RETURNS_NULL can be correctly undefined yet realloc(p, 0) can return NULL anyway. Prevent realloc(p, 0) doing free(p) and returning NULL via a different hack. Would probably be better to get rid of MALLOC_ZERO_RETURNS_NULL entirely. Bugfix candidate. Index: pymem.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pymem.h,v retrieving revision 2.4 retrieving revision 2.4.16.1 diff -C2 -d -r2.4 -r2.4.16.1 *** pymem.h 26 Jul 2001 21:34:59 -0000 2.4 --- pymem.h 5 Mar 2002 14:24:45 -0000 2.4.16.1 *************** *** 112,122 **** #define PyMem_NEW(type, n) \ ( (type *) PyMem_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)) ) ! #define PyMem_RESIZE(p, type, n) \ ! if ((p) == NULL) \ ! (p) = (type *)(PyMem_MALLOC( \ ! _PyMem_EXTRA + (n) * sizeof(type))); \ ! else \ ! (p) = (type *)(PyMem_REALLOC((p), \ ! _PyMem_EXTRA + (n) * sizeof(type))) #define PyMem_DEL(p) PyMem_FREE(p) --- 112,127 ---- #define PyMem_NEW(type, n) \ ( (type *) PyMem_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)) ) ! ! /* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */ ! #define PyMem_RESIZE(p, type, n) \ ! do { \ ! size_t _sum = (n) * sizeof(type); \ ! if (!_sum) \ ! _sum = 1; \ ! (p) = (type *)((p) ? \ ! PyMem_REALLOC(p, _sum) : \ ! PyMem_MALLOC(_sum)); \ ! } while (0) ! #define PyMem_DEL(p) PyMem_FREE(p) Index: pyport.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pyport.h,v retrieving revision 2.40 retrieving revision 2.40.8.1 diff -C2 -d -r2.40 -r2.40.8.1 *** pyport.h 27 Oct 2001 21:16:16 -0000 2.40 --- pyport.h 5 Mar 2002 14:24:45 -0000 2.40.8.1 *************** *** 365,370 **** #ifdef MALLOC_ZERO_RETURNS_NULL ! /* XXX Always allocate one extra byte, since some malloc's return NULL ! XXX for malloc(0) or realloc(p, 0). */ #define _PyMem_EXTRA 1 #else --- 365,378 ---- #ifdef MALLOC_ZERO_RETURNS_NULL ! /* Allocate an extra byte if the platform malloc(0) returns NULL. ! Caution: this bears no relation to whether realloc(p, 0) returns NULL ! when p != NULL. Even on platforms where malloc(0) does not return NULL, ! realloc(p, 0) may act like free(p) and return NULL. Examples include ! Windows, and Python's own obmalloc.c (as of 2-Mar-2002). For whatever ! reason, our docs promise that PyMem_Realloc(p, 0) won't act like ! free(p) or return NULL, so realloc() calls may have to be hacked ! too, but MALLOC_ZERO_RETURNS_NULL's state is irrelevant to realloc (it ! needs a different hack). ! */ #define _PyMem_EXTRA 1 #else From mwh@users.sourceforge.net Tue Mar 5 15:37:21 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 07:37:21 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.113.4.1,1.113.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv15359 Modified Files: Tag: release22-maint test_descr.py Log Message: backport gvanrossum's checkin of revision 1.115 of test_descr.py SF patch 514641 (Naofumi Honda) - Negative ob_size of LongObjects Due to the bizarre definition of _PyLong_Copy(), creating an instance of a subclass of long with a negative value could cause core dumps later on. Unfortunately it looks like the behavior of _PyLong_Copy() is quite intentional, so the fix is more work than feels comfortable. This fix is almost, but not quite, the code that Naofumi Honda added; in addition, I added a test case. I haven't quite worked out how to port the fix yet, but the test cases can go straight over. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.113.4.1 retrieving revision 1.113.4.2 diff -C2 -d -r1.113.4.1 -r1.113.4.2 *** test_descr.py 4 Jan 2002 12:28:43 -0000 1.113.4.1 --- test_descr.py 5 Mar 2002 15:37:18 -0000 1.113.4.2 *************** *** 1749,1752 **** --- 1749,1756 ---- verify((0 + a).__class__ is long) + # Check that negative clones don't segfault + a = longclone(-1) + vereq(a.__dict__, {}) + class precfloat(float): __slots__ = ['prec'] From mwh@users.sourceforge.net Tue Mar 5 15:37:48 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 07:37:48 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc ACKS,1.149.4.4,1.149.4.5 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv15502 Modified Files: Tag: release22-maint ACKS Log Message: backport gvanrossum's checkin of revision 1.163 of ACKS Index: ACKS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/ACKS,v retrieving revision 1.149.4.4 retrieving revision 1.149.4.5 diff -C2 -d -r1.149.4.4 -r1.149.4.5 *** ACKS 5 Mar 2002 14:20:51 -0000 1.149.4.4 --- ACKS 5 Mar 2002 15:37:46 -0000 1.149.4.5 *************** *** 202,205 **** --- 202,206 ---- Gerrit Holl Philip Homburg + Naofumi Honda Jeffrey Honig Rob Hooft From mwh@users.sourceforge.net Tue Mar 5 15:38:45 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 07:38:45 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.113.4.2,1.113.4.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv15943 Modified Files: Tag: release22-maint test_descr.py Log Message: backport tim_one's checkin of revision 1.116 of test_descr.py _PyLong_Copy(): was creating a copy of the absolute value, but should copy the sign too. Added a test to test_descr to ensure that it does. Bugfix candidate. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.113.4.2 retrieving revision 1.113.4.3 diff -C2 -d -r1.113.4.2 -r1.113.4.3 *** test_descr.py 5 Mar 2002 15:37:18 -0000 1.113.4.2 --- test_descr.py 5 Mar 2002 15:38:43 -0000 1.113.4.3 *************** *** 1752,1755 **** --- 1752,1756 ---- a = longclone(-1) vereq(a.__dict__, {}) + vereq(long(a), -1) # verify PyNumber_Long() copies the sign bit class precfloat(float): From mwh@users.sourceforge.net Tue Mar 5 15:41:42 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 07:41:42 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects object.c,2.162.6.1,2.162.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv16797 Modified Files: Tag: release22-maint object.c Log Message: Backport the bits of Guido's fix for SF patch 514641 (Naofumi Honda) - Negative ob_size of LongObjects that Tim didn't later back out. Index: object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.162.6.1 retrieving revision 2.162.6.2 diff -C2 -d -r2.162.6.1 -r2.162.6.2 *** object.c 5 Mar 2002 14:23:56 -0000 2.162.6.1 --- object.c 5 Mar 2002 15:41:40 -0000 2.162.6.2 *************** *** 1192,1197 **** return NULL; if (dictoffset < 0) { ! const size_t size = _PyObject_VAR_SIZE(tp, ! ((PyVarObject *)obj)->ob_size); dictoffset += (long)size; assert(dictoffset > 0); --- 1192,1203 ---- return NULL; if (dictoffset < 0) { ! int tsize; ! size_t size; ! ! tsize = ((PyVarObject *)obj)->ob_size; ! if (tsize < 0) ! tsize = -tsize; ! size = _PyObject_VAR_SIZE(tp, tsize); ! dictoffset += (long)size; assert(dictoffset > 0); From mwh@users.sourceforge.net Tue Mar 5 15:42:50 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 07:42:50 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.112.8.1,1.112.8.2 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv17502 Modified Files: Tag: release22-maint longobject.c Log Message: backport tim_one's checkin of revision 1.114 of longobject.c _PyLong_Copy(): was creating a copy of the absolute value, but should copy the sign too. Added a test to test_descr to ensure that it does. Bugfix candidate. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.112.8.1 retrieving revision 1.112.8.2 diff -C2 -d -r1.112.8.1 -r1.112.8.2 *** longobject.c 16 Feb 2002 23:41:39 -0000 1.112.8.1 --- longobject.c 5 Mar 2002 15:42:48 -0000 1.112.8.2 *************** *** 64,68 **** result = _PyLong_New(i); if (result != NULL) { ! result->ob_size = i; while (--i >= 0) result->ob_digit[i] = src->ob_digit[i]; --- 64,68 ---- result = _PyLong_New(i); if (result != NULL) { ! result->ob_size = src->ob_size; while (--i >= 0) result->ob_digit[i] = src->ob_digit[i]; From loewis@users.sourceforge.net Tue Mar 5 15:46:40 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Tue, 05 Mar 2002 07:46:40 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib codecs.py,1.23,1.24 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv18567 Modified Files: codecs.py Log Message: Set default value for readlines.sizehint to None. Change needed for 2.2.1 as well. Index: codecs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/codecs.py,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** codecs.py 19 Sep 2001 11:24:48 -0000 1.23 --- codecs.py 5 Mar 2002 15:46:38 -0000 1.24 *************** *** 253,257 **** ! def readlines(self, sizehint=0): """ Read all lines available on the input stream --- 253,257 ---- ! def readlines(self, sizehint=None): """ Read all lines available on the input stream From mwh@users.sourceforge.net Tue Mar 5 15:55:27 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Tue, 05 Mar 2002 07:55:27 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib codecs.py,1.23,1.23.12.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv22140 Modified Files: Tag: release22-maint codecs.py Log Message: backport loewis' checkin of revision 1.24 of codecs.py Set default value for readlines.sizehint to None. Change needed for 2.2.1 as well. Index: codecs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/codecs.py,v retrieving revision 1.23 retrieving revision 1.23.12.1 diff -C2 -d -r1.23 -r1.23.12.1 *** codecs.py 19 Sep 2001 11:24:48 -0000 1.23 --- codecs.py 5 Mar 2002 15:55:25 -0000 1.23.12.1 *************** *** 253,257 **** ! def readlines(self, sizehint=0): """ Read all lines available on the input stream --- 253,257 ---- ! def readlines(self, sizehint=None): """ Read all lines available on the input stream From andymac@bullseye.apana.org.au Tue Mar 5 10:17:33 2002 From: andymac@bullseye.apana.org.au (Andrew MacIntyre) Date: Tue, 5 Mar 2002 21:17:33 +1100 (EDT) Subject: [Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.223,2.224 In-Reply-To: Message-ID: On Sun, 3 Mar 2002, Tim Peters wrote: > Update of /cvsroot/python/python/dist/src/Modules > In directory usw-pr-cvs1:/tmp/cvs-serv23112/python/Modules > > Modified Files: > posixmodule.c > Log Message: > Python no longer compiled on Windows, due to #include file confusion > over SEP, ALTSEP and MAXPATHLEN. > Patched up posixmodule.c for MSVC, but unsure what the story is now on > other non-Unixish platforms -- the preprocessor maze has no exit . I presume this was as a result of my large commit :-( Sorry. It has occurred to me that posixmodule.c is nearly a candidate for the approach applied to threads and dynamic loading.... -- Andrew I MacIntyre "These thoughts are mine alone..." E-mail: andymac@bullseye.apana.org.au | Snail: PO Box 370 andymac@pcug.org.au | Belconnen ACT 2616 Web: http://www.andymac.org/ | Australia From tim_one@users.sourceforge.net Tue Mar 5 19:11:45 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Tue, 05 Mar 2002 11:11:45 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.52,1.53 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv24539 Modified Files: datetime.py Log Message: Hmm. Either some fiddling to timedelta.__init__ got lost via another checkin, or I forgot to check it in to begin with. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.52 retrieving revision 1.53 diff -C2 -d -r1.52 -r1.53 *** datetime.py 5 Mar 2002 14:14:48 -0000 1.52 --- datetime.py 5 Mar 2002 19:11:43 -0000 1.53 *************** *** 338,341 **** --- 338,342 ---- d = days assert isinstance(daysecondsfrac, float) + assert abs(daysecondsfrac) <= 1.0 assert isinstance(d, (int, long)) assert abs(s) <= 24 * 3600 *************** *** 346,352 **** assert seconds == long(seconds) seconds = long(seconds) else: ! secondsfrac = 0.0 assert isinstance(secondsfrac, float) assert isinstance(seconds, (int, long)) days, seconds = divmod(seconds, 24*3600) --- 347,358 ---- assert seconds == long(seconds) seconds = long(seconds) + secondsfrac += daysecondsfrac + assert abs(secondsfrac) <= 2.0 else: ! secondsfrac = daysecondsfrac ! # daysecondsfrac isn't referenced again assert isinstance(secondsfrac, float) + assert abs(secondsfrac) <= 2.0 + assert isinstance(seconds, (int, long)) days, seconds = divmod(seconds, 24*3600) *************** *** 357,365 **** # seconds isn't referenced again before redefinition - secondsfrac += daysecondsfrac - assert -2.0 <= secondsfrac <= 2.0 usdouble = secondsfrac * 1e6 ! assert -2.1e6 < usdouble < 2.1e6 # exact value not critical ! # secondsfrac & daysecondsfrac aren't referenced again if isinstance(microseconds, float): --- 363,369 ---- # seconds isn't referenced again before redefinition usdouble = secondsfrac * 1e6 ! assert abs(usdouble) < 2.1e6 # exact value not critical ! # secondsfrac isn't referenced again if isinstance(microseconds, float): *************** *** 387,391 **** microseconds = round(microseconds) assert abs(s) <= 3 * 24 * 3600 ! assert abs(microseconds) <= 3.1e6 # Just a little bit of carrying possible for microseconds and seconds. --- 391,395 ---- microseconds = round(microseconds) assert abs(s) <= 3 * 24 * 3600 ! assert abs(microseconds) < 3.1e6 # Just a little bit of carrying possible for microseconds and seconds. From jackjansen@users.sourceforge.net Tue Mar 5 22:43:52 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Tue, 05 Mar 2002 14:43:52 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Build _CG.carbon.mcp,1.2,1.3 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Build In directory usw-pr-cvs1:/tmp/cvs-serv27624/Python/Mac/Build Modified Files: _CG.carbon.mcp Log Message: CGStubLib wasn't weak-linked, fixed. 221 candidate. Index: _CG.carbon.mcp =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Build/_CG.carbon.mcp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 Binary files /tmp/cvsjhXD1M and /tmp/cvsmTDt2r differ From tim.one@comcast.net Tue Mar 5 22:52:55 2002 From: tim.one@comcast.net (Tim Peters) Date: Tue, 05 Mar 2002 17:52:55 -0500 Subject: [Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.223,2.224 In-Reply-To: Message-ID: [Tim] > Modified Files: > posixmodule.c > Log Message: > Python no longer compiled on Windows, due to #include file confusion > over SEP, ALTSEP and MAXPATHLEN. > ... [Andrew MacIntyre] > I presume this was as a result of my large commit :-( Sorry. Probably, but don't worry about it. Historically, the Windows build breaks about once per week, and it's my stated policy that I'd much rather fix it after the fact then pee away time applying patches in advance. One reason for that is, if I wait until after the build is broken, it's much easier to shame the committer into making fixes an urgent priority . > It has occurred to me that posixmodule.c is nearly a candidate for the > approach applied to threads and dynamic loading.... I don't expect it would really help, for much the same reason thread_pthread.h alone has a mass of inscructable #ifdefs at its start, yet keeps breaking on pthreads platforms anyway: outside the 300-line preprocessor maze at the start of posixmodule.c, most of the #ifdef hair in the remaining 6400 lines has to do with untangling Unix variations. From gvanrossum@users.sourceforge.net Wed Mar 6 01:25:18 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 05 Mar 2002 17:25:18 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.53,1.54 test_datetime.py,1.37,1.38 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv5073 Modified Files: datetime.py test_datetime.py Log Message: Eradicate all references to time zone offset. This implements naive time'' as I described on python-dev. Some cleanup remains to be done... Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.53 retrieving revision 1.54 diff -C2 -d -r1.53 -r1.54 *** datetime.py 5 Mar 2002 19:11:43 -0000 1.53 --- datetime.py 6 Mar 2002 01:25:13 -0000 1.54 *************** *** 249,267 **** - def _localtzoffset(year, month, day, hour, minute): - "Return tzoffset for local time corresponding to given date/time." - try: - t = _time.mktime((year, month, day, hour, minute, 0, -1, -1, -1)) - tm = _time.localtime(t) - if tm.tm_isdst > 0: - return - (_time.altzone // 60) - else: - return - (_time.timezone // 60) - except (ValueError, OverflowError): - # Dates out of range for mktime() never see DST. - # As a reasonable guess, though, we can try a year in mktime()'s range - # with the same leap-year-ness as the given year. - return _localtzoffset(2003 + _is_leap(year), month, day, hour, minute) - class basetime(object): """Abstract date/time type. --- 249,252 ---- *************** *** 423,443 **** def __str__(self): ! def plural(n): ! return n, n != 1 and "s" or "" ! L = [] if self.__days: ! L.append("%d day%s" % plural(self.__days)) ! if self.__seconds: ! mm, ss = divmod(self.__seconds, 60) ! hh, mm = divmod(mm, 60) ! if hh: ! L.append("%d hour%s" % plural(hh)) ! if mm: ! L.append("%d minute%s" % plural(mm)) ! if ss: ! L.append("%d second%s" % plural(ss)) if self.__microseconds: ! L.append("%d microsecond%s" % plural(self.__microseconds)) ! return ", ".join(L) days = property(lambda self: self.__days, doc="days") --- 408,421 ---- def __str__(self): ! mm, ss = divmod(self.__seconds, 60) ! hh, mm = divmod(mm, 60) ! s = "%d:%02d:%02d" % (hh, mm, ss) if self.__days: ! def plural(n): ! return n, n != 1 and "s" or "" ! s = ("%d day%s, " % plural(self.__days)) + s if self.__microseconds: ! s = s + ".%06d" % self.__microseconds ! return s days = property(lambda self: self.__days, doc="days") *************** *** 560,568 **** "Construct a date from a POSIX timestamp (like time.time())." y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t) - us = int((t % 1.0) * 1000000) - if dst > 0: - tz = -(_time.altzone // 60) - else: - tz = -(_time.timezone // 60) return cls(y, m, d) fromtimestamp = classmethod(fromtimestamp) --- 538,541 ---- *************** *** 636,642 **** def __hash__(self): "Hash." - # Caution: objects that compare equal must have equal hashcodes, - # and two dates can be equal even if their fields aren't - # (due to tzoffset). So we have to compute a UTC-normalized hash. return hash((self.__year, self.__month, self.__day)) --- 609,612 ---- *************** *** 648,662 **** # strftime("%c", ...) is locale specific. - # XXX An additional question is whether ctime() should renormalize - # to local time, or display the time as entered (which may be - # confusing since it doesn't show the timezone). - def ctime(self): ! "Format a la ctime() in local time." ! t = tmxxx(self.__year, self.__month, self.__day) ! return t.ctime() def strftime(self, fmt): ! "Format using strftime() in local time." return _time.strftime(fmt, _time.localtime(self._mktime())) --- 618,627 ---- # strftime("%c", ...) is locale specific. def ctime(self): ! "Format a la ctime()." ! return tmxxx(self.__year, self.__month, self.__day).ctime() def strftime(self, fmt): ! "Format using strftime()." return _time.strftime(fmt, _time.localtime(self._mktime())) *************** *** 776,784 **** Properties (readonly): ! year, month, day, hour, minute, second, microsecond, tzoffset """ def __init__(self, year, month, day, hour=0, minute=0, second=0, ! microsecond=0, tzoffset=None): """Constructor. --- 741,749 ---- Properties (readonly): ! year, month, day, hour, minute, second, microsecond """ def __init__(self, year, month, day, hour=0, minute=0, second=0, ! microsecond=0): """Constructor. *************** *** 787,792 **** year, month, day (required, base 1) hour, minute, second, microsecond (default to zero) - tzoffset (minutes east of UTC; defaults to local time) - """ super(datetime, self).__init__(year, month, day) --- 752,755 ---- *************** *** 799,807 **** if not 0 <= microsecond <= 999999: raise ValueError('microsecond must be in 0..999999', microsecond) - if tzoffset is None: - # XXX Correct, but expensive - tzoffset = _localtzoffset(year, month, day, hour, minute) - if not -1439 <= tzoffset <= 1439: - raise ValueError('tzoffset must be in -1439..1439', tzoffset) # XXX This duplicates __year, __month, __day for convenience :-( self.__year = year --- 762,765 ---- *************** *** 812,816 **** self.__second = second self.__microsecond = microsecond - self.__tzoffset = tzoffset # minutes east of UTC # Additional constructors --- 770,773 ---- *************** *** 820,828 **** y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t) us = int((t % 1.0) * 1000000) ! if dst > 0: ! tz = -(_time.altzone // 60) ! else: ! tz = -(_time.timezone // 60) ! return cls(y, m, d, hh, mm, ss, us, tz) fromtimestamp = classmethod(fromtimestamp) --- 777,781 ---- y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t) us = int((t % 1.0) * 1000000) ! return cls(y, m, d, hh, mm, ss, us) fromtimestamp = classmethod(fromtimestamp) *************** *** 837,841 **** y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t) us = int((t % 1.0) * 1000000) ! return cls(y, m, d, hh, mm, ss, us, 0) utcfromtimestamp = classmethod(utcfromtimestamp) --- 790,794 ---- y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t) us = int((t % 1.0) * 1000000) ! return cls(y, m, d, hh, mm, ss, us) utcfromtimestamp = classmethod(utcfromtimestamp) *************** *** 855,861 **** del L[-1] s = ", ".join(map(str, L)) ! return "%s(%s, tzoffset=%d)" % (self.__class__.__name__, ! s, ! self.__tzoffset) def __str__(self): --- 808,812 ---- del L[-1] s = ", ".join(map(str, L)) ! return "%s(%s)" % (self.__class__.__name__, s) def __str__(self): *************** *** 869,874 **** microsecond = property(lambda self: self.__microsecond, doc="microsecond (0-999999)") - tzoffset = property(lambda self: self.__tzoffset, - doc="time zone offset in minutes east of UTC") # Standard conversions, __cmp__, __hash__ (and helpers) --- 820,823 ---- *************** *** 879,883 **** # Helper to return a POSIX-ish timestamp t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute - self.__tzoffset, self.__second, self.__microsecond) return t.time() --- 828,832 ---- # Helper to return a POSIX-ish timestamp t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute, self.__second, self.__microsecond) return t.time() *************** *** 890,923 **** "Three-way comparison." if isinstance(other, datetime): ! if self.__tzoffset == other.__tzoffset: ! y, m, d = self.__year, self.__month, self.__day ! H, M = self.__hour, self.__minute ! y2, m2, d2 = other.__year, other.__month, other.__day ! H2, M2 = other.__hour, other.__minute ! else: ! y, m, d, H, M = self._utc_ymdHM() ! y2, m2, d2, H2, M2 = other._utc_ymdHM() ! return cmp((y, m, d, H, M, ! self.__second, self.__microsecond), ! (y2, m2, d2, H2, M2, ! other.__second, other.__microsecond)) ! else: ! raise TypeError, ("can't compare datetime to %s instance" % ! type(other).__name__) ! ! def _utc_ymdHM(self): ! # Helper to return (year, month, day, hour, minute) in UTC equivalent ! t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute - self.__tzoffset) ! return t.year, t.month, t.day, t.hour, t.minute def __hash__(self): "Hash." ! # Caution: objects that compare equal must have equal hashcodes, ! # and two datetimes can be equal even if their fields aren't ! # (due to tzoffset). So we have to compute a UTC-normalized hash. ! # XXX _utc_ymdHM can be expensive; dream up a quicker correct way. ! y, m, d, H, M = self._utc_ymdHM() ! return hash((y, m, d, H, M, self.__second, self.__microsecond)) # Formatting methods --- 839,856 ---- "Three-way comparison." if isinstance(other, datetime): ! return cmp((self.__year, self.__month, self.__day, ! self.__hour, self.__minute, self.__second, ! self.__microsecond), ! (other.__year, other.__month, other.__day, ! other.__hour, other.__minute, other.__second, ! other.__microsecond)) ! raise TypeError, ("can't compare datetime to %s instance" % ! type(other).__name__) def __hash__(self): "Hash." ! return hash((self.__year, self.__month, self.__day, ! self.__hour, self.__minute, self.__second, ! self.__microsecond)) # Formatting methods *************** *** 933,959 **** def ctime(self): ! "Format a la ctime() in local time." ! tzoffset = _localtzoffset(self.__year, self.__month, self.__day, 0, 0) t = tmxxx(self.__year, self.__month, self.__day, self.__hour, ! self.__minute - self.__tzoffset + tzoffset, self.__second) ! tzoffset1 = _localtzoffset(t.year, t.month, t.day, t.hour, t.minute) ! if tzoffset1 != tzoffset: ! t = tmxxx(t.year, t.month, t.day, t.hour, ! t.minute - tzoffset + tzoffset1, self.__second) ! tzoffset2 = _localtzoffset(t.year, t.month, t.day, ! t.hour, t.minute) ! assert tzoffset2 == tzoffset1 # XXX Hah! ! return t.ctime() ! ! def utcctime(self): ! "Format a la ctime() in UTC." ! t = tmxxx(self.__year, self.__month, self.__day, ! self.__hour, self.__minute - self.__tzoffset, self.__second) return t.ctime() - def utcstrftime(self, fmt): - "Format using strftime() in UTC." - return _time.strftime(fmt, _time.gmtime(self._mktime())) - # Computations --- 866,874 ---- def ctime(self): ! "Format a la ctime()." t = tmxxx(self.__year, self.__month, self.__day, self.__hour, ! self.__minute, self.__second) return t.ctime() # Computations *************** *** 971,975 **** result = self.__class__(t.year, t.month, t.day, t.hour, t.minute, t.second, ! t.microsecond, self.__tzoffset) return result raise TypeError --- 886,890 ---- result = self.__class__(t.year, t.month, t.day, t.hour, t.minute, t.second, ! t.microsecond) return result raise TypeError *************** *** 988,996 **** days1 = self.toordinal() days2 = other.toordinal() ! secs1 = (self.__second + ! (self.__minute - self.__tzoffset) * 60 + ! self.__hour * 3600) secs2 = (other.__second + ! (other.__minute - other.__tzoffset) * 60 + other.__hour * 3600) return self.timedelta_class( --- 903,909 ---- days1 = self.toordinal() days2 = other.toordinal() ! secs1 = (self.__second + self.__minute * 60 + self.__hour * 3600) secs2 = (other.__second + ! (other.__minute) * 60 + other.__hour * 3600) return self.timedelta_class( *************** *** 1000,1004 **** return NotImplemented ! # ISO formats including time and tzoffset def isoformat(self, sep='T'): --- 913,917 ---- return NotImplemented ! # ISO formats including time def isoformat(self, sep='T'): *************** *** 1010,1043 **** Optional argument sep specifies the separator between date and time, default 'T'. - - This method does not convert to local time. """ ! if self.__tzoffset >= 0: ! h, m = divmod(self.__tzoffset, 60) ! else: ! h, m = divmod(-self.__tzoffset, 60) ! h = -h ! return "%04d-%02d-%02d%c%02d:%02d:%02d.%06d%+03d:%02d" % ( self.__year, self.__month, self.__day, sep, self.__hour, self.__minute, self.__second, ! self.__microsecond, ! h, m) ! ! def utcisoformat(self, sep='T'): ! """Return the time as UTC formatted according to ISO. ! ! This is 'YYYY-MM-DD HH:MM:SS.mmmmmmZ'. ! ! Optional argument sep specifies the separator between date and ! time, default 'T'. ! """ ! y, m, d, hh, mm = self._utc_ymdHM() ! return "%04d-%02d-%02d%c%02d:%02d:%02d.%06dZ" % ( ! y, m, d, sep, hh, mm, self.__second, self.__microsecond) ! datetime.min = datetime(1, 1, 1, tzoffset=0) ! datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999, tzoffset=0) datetime.resolution = timedelta(microseconds=1) --- 923,936 ---- Optional argument sep specifies the separator between date and time, default 'T'. """ ! return "%04d-%02d-%02d%c%02d:%02d:%02d.%06d" % ( self.__year, self.__month, self.__day, sep, self.__hour, self.__minute, self.__second, ! self.__microsecond) ! datetime.min = datetime(1, 1, 1) ! datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999) datetime.resolution = timedelta(microseconds=1) Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.37 retrieving revision 1.38 diff -C2 -d -r1.37 -r1.38 *** test_datetime.py 5 Mar 2002 14:14:48 -0000 1.37 --- test_datetime.py 6 Mar 2002 01:25:15 -0000 1.38 *************** *** 327,331 **** def test_roundtrip(self): ! for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7, 8), self.theclass.now()): # Verify dt -> string -> datetime identity. --- 327,331 ---- def test_roundtrip(self): ! for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7), self.theclass.now()): # Verify dt -> string -> datetime identity. *************** *** 337,347 **** dt2 = self.theclass(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ! dt.microsecond, dt.tzoffset) self.assertEqual(dt, dt2) def test_tz_independent_comparing(self): ! dt1 = self.theclass(2002, 3, 1, 9, 0, 0, tzoffset=-60) ! dt2 = self.theclass(2002, 3, 1, 10, 0, 0, tzoffset=-60) ! dt3 = self.theclass(2002, 3, 1, 10, 0, 0, tzoffset=0) self.assertEqual(dt1, dt3) self.assert_(dt2 > dt3) --- 337,347 ---- dt2 = self.theclass(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ! dt.microsecond) self.assertEqual(dt, dt2) def test_tz_independent_comparing(self): ! dt1 = self.theclass(2002, 3, 1, 9, 0, 0) ! dt2 = self.theclass(2002, 3, 1, 10, 0, 0) ! dt3 = self.theclass(2002, 3, 1, 9, 0, 0) self.assertEqual(dt1, dt3) self.assert_(dt2 > dt3) *************** *** 352,356 **** # so comparing via timestamp necessarily calls some distinct values # equal). ! dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) us = timedelta(microseconds=1) dt2 = dt1 + us --- 352,356 ---- # so comparing via timestamp necessarily calls some distinct values # equal). ! dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998) us = timedelta(microseconds=1) dt2 = dt1 + us *************** *** 358,369 **** self.assert_(dt1 < dt2) - # Again, but mix timezones. - dt1 = self.theclass(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60) - dt2 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0) - self.assertEqual(dt1, dt2) - dt2 += us - self.assertEqual(dt2 - dt1, us) - self.assert_(dt1 < dt2) - def test_bad_constructor_arguments(self): # bad years --- 358,361 ---- *************** *** 410,425 **** 2000, 1, 31, 23, 59, 59, 1000000) - # bad tzoffet - self.theclass(2, 1, 1, 0, 0, 0, 0, -1439) # no exception - self.theclass(2, 1, 1, 0, 0, 0, 0, 1439) # no exception - self.assertRaises(ValueError, self.theclass, - 2, 1, 1, 0, 0, 0, 0, -1440) - self.assertRaises(ValueError, self.theclass, - 2, 1, 1, 0, 0, 0, 0, 1440) def test_hash_equality(self): ! d = self.theclass(2000, 12, 31, 23, 30, 17, tzoffset=-35) ! # same thing in UTC. ! e = self.theclass(2001, 1, 1, 0, 5, 17, tzoffset=0) self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) --- 402,409 ---- 2000, 1, 31, 23, 59, 59, 1000000) def test_hash_equality(self): ! d = self.theclass(2000, 12, 31, 23, 30, 17) ! e = self.theclass(2000, 12, 31, 23, 30, 17) self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) *************** *** 431,437 **** self.assertEqual(dic[e], 2) ! d = self.theclass(2001, 1, 1, 0, 5, 17, tzoffset=35) ! # same thing in UTC. ! e = self.theclass(2000, 12, 31, 23, 30, 17, tzoffset=0) self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) --- 415,420 ---- self.assertEqual(dic[e], 2) ! d = self.theclass(2001, 1, 1, 0, 5, 17) ! e = self.theclass(2001, 1, 1, 0, 5, 17) self.assertEqual(d, e) self.assertEqual(hash(d), hash(e)) *************** *** 498,506 **** def test_isoformat(self): ! t = self.theclass(2, 3, 2, 4, 5, 1, 123, tzoffset=-120) ! self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123-02:00") ! self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123-02:00") ! self.assertEqual(t.utcisoformat(), "0002-03-02T06:05:01.000123Z") ! self.assertEqual(t.utcisoformat(' '), "0002-03-02 06:05:01.000123Z") def test_tmxxx(self): --- 481,488 ---- def test_isoformat(self): ! t = self.theclass(2, 3, 2, 4, 5, 1, 123) ! self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123") ! self.assertEqual(t.isoformat('T'), "0002-03-02T04:05:01.000123") ! self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123") def test_tmxxx(self): *************** *** 514,518 **** (3*60 - 12) * 1000000) dt2 = self.theclass(tm.year, tm.month, tm.day, tm.hour, tm.minute, ! tm.second, tm.microsecond, tzoffset=0) self.assertEqual(dt, dt2) self.assertEqual(timestamp, tm.time()) --- 496,500 ---- (3*60 - 12) * 1000000) dt2 = self.theclass(tm.year, tm.month, tm.day, tm.hour, tm.minute, ! tm.second, tm.microsecond) self.assertEqual(dt, dt2) self.assertEqual(timestamp, tm.time()) *************** *** 521,535 **** t = self.theclass(2002, 3, 2, 18, 3, 5, 123) self.assertEqual(t.ctime(), "Sat Mar 2 18:03:05 2002") - # XXX Can only test utcctime() in known timezone :-( - # XXX What about the southern hemisphere, where this is DST? - import time - if time.timezone == 5*3600: - self.assertEqual(t.utcctime(), "Sat Mar 2 23:03:05 2002") - elif time.timezone == 0: - self.assertEqual(t.utcctime(), "Sat Mar 2 18:03:05 2002") - elif time.timezone == 3600: - self.assertEqual(t.utcctime(), "Sat Mar 2 17:03:05 2002") - else: - self.fail("Can't test utcctime()") --- 503,506 ---- From fdrake@users.sourceforge.net Wed Mar 6 02:29:33 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 18:29:33 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libfuncs.tex,1.101,1.102 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv16956/lib Modified Files: libfuncs.tex Log Message: Added missing version annotation for dict(). Index: libfuncs.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfuncs.tex,v retrieving revision 1.101 retrieving revision 1.102 diff -C2 -d -r1.101 -r1.102 *** libfuncs.tex 23 Feb 2002 04:40:15 -0000 1.101 --- libfuncs.tex 6 Mar 2002 02:29:30 -0000 1.102 *************** *** 202,205 **** --- 202,207 ---- \item \code{dict([(i-1, i) for i in (2, 3)])} \end{itemize} + + \versionadded{2.2} \end{funcdesc} From fdrake@users.sourceforge.net Wed Mar 6 02:29:52 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 18:29:52 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libfuncs.tex,1.100.4.1,1.100.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv17016/lib Modified Files: Tag: release22-maint libfuncs.tex Log Message: Added missing version annotation for dict(). Index: libfuncs.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfuncs.tex,v retrieving revision 1.100.4.1 retrieving revision 1.100.4.2 diff -C2 -d -r1.100.4.1 -r1.100.4.2 *** libfuncs.tex 23 Feb 2002 08:31:37 -0000 1.100.4.1 --- libfuncs.tex 6 Mar 2002 02:29:50 -0000 1.100.4.2 *************** *** 202,205 **** --- 202,207 ---- \item \code{dict([(i-1, i) for i in (2, 3)])} \end{itemize} + + \versionadded{2.2} \end{funcdesc} From fdrake@users.sourceforge.net Wed Mar 6 04:06:01 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 20:06:01 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.c,1.3,1.4 datetime.h,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv2001 Modified Files: datetime.c datetime.h Log Message: Make the corresponding changes to remove tzoffset support from the datetime type. Guido made the changes to the Python implementation earlier. Index: datetime.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** datetime.c 4 Mar 2002 21:20:54 -0000 1.3 --- datetime.c 6 Mar 2002 04:05:59 -0000 1.4 *************** *** 19,23 **** #define GET_SECOND(o) PyDateTime_GET_SECOND(o) #define GET_MICROSECOND(o) PyDateTime_GET_MICROSECOND(o) - #define GET_TZOFFSET(o) PyDateTime_GET_TZOFFSET(o) /* Set accessors. */ --- 19,22 ---- *************** *** 32,37 **** ((o)->data[8] = ((v) & 0x00ff00) >> 0), \ ((o)->data[9] = ((v) & 0x00ff00))) - #define SET_TZOFFSET(o, v) (((o)->data[10] = ((v) & 0xff00) >> 8), \ - ((o)->data[11] = ((v) & 0x00ff))) static PyObject * --- 31,34 ---- *************** *** 87,101 **** PyDateTime_Object *self = NULL; long int year, month, day, hour = 0, minute = 0, second = 0, usecond = 0; - long int tzoffset; - PyObject *tzoffset_object = Py_None; static char * keywords[] = { ! "year", "month", "day", "hour", "minute", "second", "microsecond", ! "tzoffset", NULL }; ! if (PyArg_ParseTupleAndKeywords(args, kw, "lll|llllO", keywords, &year, &month, &day, &hour, &minute, ! &second, &usecond, &tzoffset_object)) { if (year < MINYEAR || year > MAXYEAR) { PyErr_SetString(PyExc_ValueError, "year is out of range"); --- 84,95 ---- PyDateTime_Object *self = NULL; long int year, month, day, hour = 0, minute = 0, second = 0, usecond = 0; static char * keywords[] = { ! "year", "month", "day", "hour", "minute", "second", "microsecond", NULL }; ! if (PyArg_ParseTupleAndKeywords(args, kw, "lll|llll", keywords, &year, &month, &day, &hour, &minute, ! &second, &usecond)) { if (year < MINYEAR || year > MAXYEAR) { PyErr_SetString(PyExc_ValueError, "year is out of range"); *************** *** 127,147 **** return NULL; } - if (tzoffset_object == Py_None) { - /* tzoffset == None not yet implemented */ - tzoffset = 0; - } - else { - tzoffset_object = PyNumber_Int(tzoffset_object); - if (tzoffset_object == NULL) - return NULL; - tzoffset = PyInt_AS_LONG(tzoffset_object); - Py_DECREF(tzoffset_object); - if (tzoffset < -1439 || tzoffset > 1439) { - PyErr_SetString(PyExc_ValueError, - "tzoffset must be in -1439..1439"); - return NULL; - } - tzoffset_object = NULL; - } self = PyObject_New(PyDateTime_Object, &PyDateTime_Type); if (self != NULL) { --- 121,124 ---- *************** *** 153,157 **** SET_SECOND(self, second); SET_MICROSECOND(self, usecond); - SET_TZOFFSET(self, tzoffset); } } --- 130,133 ---- *************** *** 202,211 **** } - static PyObject * - datetime_tzoffset(PyDateTime_Object *self, void *unused) - { - return (PyInt_FromLong(GET_TZOFFSET(self))); - } - static PyGetSetDef datetime_getset[] = { {"year",(getter)datetime_year}, --- 178,181 ---- *************** *** 216,220 **** {"second", (getter)datetime_second}, {"microsecond", (getter)datetime_microsecond}, - {"tzoffset", (getter)datetime_tzoffset}, {NULL} }; --- 186,189 ---- Index: datetime.h =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** datetime.h 5 Mar 2002 03:55:35 -0000 1.2 --- datetime.h 6 Mar 2002 04:05:59 -0000 1.3 *************** *** 5,9 **** #define DATETIME_H ! #define _PyDateTime_DATA_SIZE 12 typedef struct --- 5,9 ---- #define DATETIME_H ! #define _PyDateTime_DATA_SIZE 10 typedef struct *************** *** 27,33 **** | ((PyDateTime_Object*)o)->data[8] << 8\ | ((PyDateTime_Object*)o)->data[9]) - #define PyDateTime_GET_TZOFFSET(o) ((signed int) \ - (((PyDateTime_Object*)o)->data[10] << 8\ - | ((PyDateTime_Object*)o)->data[11])) #endif --- 27,30 ---- From fdrake@users.sourceforge.net Wed Mar 6 04:10:39 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 20:10:39 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.54,1.55 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv2888 Modified Files: datetime.py Log Message: Fix up a docstring. Index: datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v retrieving revision 1.54 retrieving revision 1.55 diff -C2 -d -r1.54 -r1.55 *** datetime.py 6 Mar 2002 01:25:13 -0000 1.54 --- datetime.py 6 Mar 2002 04:10:37 -0000 1.55 *************** *** 701,710 **** def isoformat(self): ! """Return the time formatted according to ISO. This is 'YYYY-MM-DD'. - - Optional argument sep specifies the separator between date and - time, default 'T'. """ return "%04d-%02d-%02d" % (self.__year, self.__month, self.__day) --- 701,707 ---- def isoformat(self): ! """Return the date formatted according to ISO. This is 'YYYY-MM-DD'. """ return "%04d-%02d-%02d" % (self.__year, self.__month, self.__day) From fdrake@users.sourceforge.net Wed Mar 6 04:30:53 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 20:30:53 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.c,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv5658 Modified Files: datetime.c Log Message: Fix SET_MICROSECOND() macro to actually store the value correctly. Add support for isoformat(), isoweekday(), weekday(). Added class attributes min, max. Moved instance creation to a separate function from the tp_new handler; this makes it easier to create instances using alternate constructors, or just in C code. Index: datetime.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** datetime.c 6 Mar 2002 04:05:59 -0000 1.4 --- datetime.c 6 Mar 2002 04:30:51 -0000 1.5 *************** *** 29,34 **** #define SET_SECOND(o, v) (PyDateTime_GET_SECOND(o) = (v)) #define SET_MICROSECOND(o, v) (((o)->data[7] = ((v) & 0xff0000) >> 16), \ ! ((o)->data[8] = ((v) & 0x00ff00) >> 0), \ ! ((o)->data[9] = ((v) & 0x00ff00))) static PyObject * --- 29,103 ---- #define SET_SECOND(o, v) (PyDateTime_GET_SECOND(o) = (v)) #define SET_MICROSECOND(o, v) (((o)->data[7] = ((v) & 0xff0000) >> 16), \ ! ((o)->data[8] = ((v) & 0x00ff00) >> 8), \ ! ((o)->data[9] = ((v) & 0x0000ff))) ! ! /* ! * General calendrical helper functions ! */ ! ! static int ! is_leap(int year) ! { ! return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); ! } ! ! static int ! days_in_month(int year, int month) ! { ! static int _days_in_month[] = { ! 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ! }; ! ! assert(month >= 1); ! assert(month <= 12); ! if (month == 2 && is_leap(year)) ! return 29; ! else ! return _days_in_month[month]; ! } ! ! static long ! days_before_year(int year) ! { ! int y = year - 1; ! return y*365 + y/4 - y/100 + y/400; ! } ! ! /* Each entry at index 1..12 gives the number of days before each ! * month on non-leap years. ! */ ! static int _days_before_month[] = { ! 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ! }; ! ! static int ! days_before_month(int year, int month) ! { ! int days; ! ! assert(month >= 1); ! assert(month <= 12); ! days = _days_before_month[month]; ! if (month > 2 && is_leap(year)) ! ++days; ! return days; ! } ! ! static long ! ymd_to_ord(int year, int month, int day) ! { ! return days_before_year(year) + days_before_month(year, month) + day; ! } ! ! static int ! weekday(int year, int month, int day) ! { ! return (ymd_to_ord(year, month, day) + 6) % 7; ! } ! ! ! /* ! * PyDateTime_Object implementation ! */ static PyObject * *************** *** 58,80 **** } ! static int ! is_leap(int year) ! { ! return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); ! } ! ! static int ! days_in_month(int year, int month) { ! static int _days_in_month[] = { ! 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ! }; ! assert(month >= 1); ! assert(month <= 12); ! if (month == 2 && is_leap(year)) ! return 29; ! else ! return _days_in_month[month]; } --- 127,148 ---- } ! /* Create a datetime instance with no range checking. */ ! static PyObject * ! new_datetime(int year, int month, int day, int hour, int minute, ! int second, int usecond) { ! PyDateTime_Object *self; ! self = PyObject_New(PyDateTime_Object, &PyDateTime_Type); ! if (self != NULL) { ! SET_YEAR(self, year); ! SET_MONTH(self, month); ! SET_DAY(self, day); ! SET_HOUR(self, hour); ! SET_MINUTE(self, minute); ! SET_SECOND(self, second); ! SET_MICROSECOND(self, usecond); ! } ! return (PyObject *) self; } *************** *** 82,89 **** datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw) { ! PyDateTime_Object *self = NULL; long int year, month, day, hour = 0, minute = 0, second = 0, usecond = 0; ! static char * keywords[] = { "year", "month", "day", "hour", "minute", "second", "microsecond", NULL }; --- 150,157 ---- datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw) { ! PyObject *self = NULL; long int year, month, day, hour = 0, minute = 0, second = 0, usecond = 0; ! static char *keywords[] = { "year", "month", "day", "hour", "minute", "second", "microsecond", NULL }; *************** *** 121,136 **** return NULL; } ! self = PyObject_New(PyDateTime_Object, &PyDateTime_Type); ! if (self != NULL) { ! SET_YEAR(self, year); ! SET_MONTH(self, month); ! SET_DAY(self, day); ! SET_HOUR(self, hour); ! SET_MINUTE(self, minute); ! SET_SECOND(self, second); ! SET_MICROSECOND(self, usecond); ! } } ! return (PyObject *) self; } --- 189,195 ---- return NULL; } ! self = new_datetime(year, month, day, hour, minute, second, usecond); } ! return self; } *************** *** 189,192 **** --- 248,300 ---- }; + static PyObject * + datetime_isoformat(PyDateTime_Object *self, PyObject *args, PyObject *kw) + { + char buffer[128]; + char sep = 'T'; + + static char *keywords[] = {"sep", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords, &sep)) + return NULL; + + PyOS_snprintf(buffer, sizeof(buffer), + "%04d-%02d-%02d%c%02d:%02d:%02d.%06d", + GET_YEAR(self), GET_MONTH(self), GET_DAY(self), + sep, + GET_HOUR(self), GET_MINUTE(self), GET_SECOND(self), + GET_MICROSECOND(self)); + return PyString_FromString(buffer); + } + + static PyObject * + datetime_isoweekday(PyDateTime_Object *self) + { + int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); + + return PyInt_FromLong(dow + 1); + } + + static PyObject * + datetime_weekday(PyDateTime_Object *self) + { + int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); + + return PyInt_FromLong(dow); + } + + static PyMethodDef datetime_methods[] = { + {"isoformat", (PyCFunction)datetime_isoformat, METH_VARARGS|METH_KEYWORDS, + "Return the day of the week represented by the datetime.\n" + "Monday == 1 ... Sunday == 7"}, + {"isoweekday", (PyCFunction)datetime_isoweekday, METH_NOARGS, + "Return the day of the week represented by the datetime.\n" + "Monday == 1 ... Sunday == 7"}, + {"weekday", (PyCFunction)datetime_weekday, METH_NOARGS, + "Return the day of the week represented by the datetime.\n" + "Monday == 0 ... Sunday == 6"}, + {NULL} + }; + static char datetime_doc[] = "Basic date/time type."; *************** *** 223,227 **** 0, /* tp_iter */ 0, /* tp_iternext */ ! 0, /* tp_methods */ 0, /* tp_members */ datetime_getset, /* tp_getset */ --- 331,335 ---- 0, /* tp_iter */ 0, /* tp_iternext */ ! datetime_methods, /* tp_methods */ 0, /* tp_members */ datetime_getset, /* tp_getset */ *************** *** 242,246 **** {NULL, NULL, 0, NULL} }; ! void --- 350,354 ---- {NULL, NULL, 0, NULL} }; ! void *************** *** 248,254 **** --- 356,373 ---- { PyObject *m; + PyObject *d, *dt; if (PyType_Ready(&PyDateTime_Type) < 0) return; + + d = PyDateTime_Type.tp_dict; + dt = new_datetime(1, 1, 1, 0, 0, 0, 0); + if (dt == NULL || PyDict_SetItemString(d, "min", dt) < 0) + return; + Py_DECREF(dt); + dt = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999); + if (dt == NULL || PyDict_SetItemString(d, "max", dt) < 0) + return; + Py_DECREF(dt); m = Py_InitModule3("_datetime", functions, From fdrake@users.sourceforge.net Wed Mar 6 04:36:29 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 20:36:29 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_cdatetime.py,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv6342 Modified Files: test_cdatetime.py Log Message: Add test that retrieves the basic attributes from the datetime instance which actually checks that the bit-shifting accessors do the right thing. Add the test of the isoformat() method now that we have it. Index: test_cdatetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_cdatetime.py,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** test_cdatetime.py 4 Mar 2002 20:44:19 -0000 1.1 --- test_cdatetime.py 6 Mar 2002 04:36:26 -0000 1.2 *************** *** 11,16 **** class TestDateTime(unittest.TestCase): def test_basic_attributes(self): ! dt = datetime(2002, 3, 1, 12, 0, 0) self.assertEqual(dt.year, 2002) self.assertEqual(dt.month, 3) --- 11,18 ---- class TestDateTime(unittest.TestCase): + theclass = datetime + def test_basic_attributes(self): ! dt = self.theclass(2002, 3, 1, 12, 0) self.assertEqual(dt.year, 2002) self.assertEqual(dt.month, 3) *************** *** 20,23 **** --- 22,44 ---- self.assertEqual(dt.second, 0) self.assertEqual(dt.microsecond, 0) + + def test_basic_attributes_nonzero(self): + # Make sure all attributes are non-zero so bugs in + # bit-shifting access show up. + dt = self.theclass(2002, 3, 1, 12, 59, 59, 8000) + self.assertEqual(dt.year, 2002) + self.assertEqual(dt.month, 3) + self.assertEqual(dt.day, 1) + self.assertEqual(dt.hour, 12) + self.assertEqual(dt.minute, 59) + self.assertEqual(dt.second, 59) + self.assertEqual(dt.microsecond, 8000) + + def test_isoformat(self): + t = self.theclass(2, 3, 2, 4, 5, 1, 123) + self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123") + self.assertEqual(t.isoformat('T'), "0002-03-02T04:05:01.000123") + self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123") + def test_suite(): From fdrake@users.sourceforge.net Wed Mar 6 04:37:32 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 20:37:32 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_datetime.py,1.38,1.39 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv6487 Modified Files: test_datetime.py Log Message: Add the test for the bit-shifting accessors here as well, just to be sure we run all the tests the C implementation needs are also supported by the Python implementation. Index: test_datetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -d -r1.38 -r1.39 *** test_datetime.py 6 Mar 2002 01:25:15 -0000 1.38 --- test_datetime.py 6 Mar 2002 04:37:30 -0000 1.39 *************** *** 326,329 **** --- 326,341 ---- self.assertEqual(dt.microsecond, 0) + def test_basic_attributes_nonzero(self): + # Make sure all attributes are non-zero so bugs in + # bit-shifting access show up. + dt = self.theclass(2002, 3, 1, 12, 59, 59, 8000) + self.assertEqual(dt.year, 2002) + self.assertEqual(dt.month, 3) + self.assertEqual(dt.day, 1) + self.assertEqual(dt.hour, 12) + self.assertEqual(dt.minute, 59) + self.assertEqual(dt.second, 59) + self.assertEqual(dt.microsecond, 8000) + def test_roundtrip(self): for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7), From fdrake@users.sourceforge.net Wed Mar 6 05:53:36 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 21:53:36 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime datetime.c,1.5,1.6 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv15873 Modified Files: datetime.c Log Message: Added implementation of isocalendar(). Index: datetime.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** datetime.c 6 Mar 2002 04:30:51 -0000 1.5 --- datetime.c 6 Mar 2002 05:53:34 -0000 1.6 *************** *** 96,99 **** --- 96,113 ---- } + static int + iso_week1_monday(int year) + { + int first_day = ymd_to_ord(year, 1, 1); + int first_weekday = (first_day + 6) % 7; + int week1_monday = first_day - first_weekday; + + #define THURSDAY 3 + if (first_weekday > THURSDAY) + week1_monday += 7; + #undef THURSDAY + return week1_monday; + } + /* *************** *** 249,252 **** --- 263,290 ---- static PyObject * + datetime_isocalendar(PyDateTime_Object *self) + { + int year = GET_YEAR(self); + int week1_monday = iso_week1_monday(year); + long today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self)); + int week = (today - week1_monday) / 7; + int day = (today - week1_monday) % 7; + + if (week < 0) { + --year; + week1_monday = iso_week1_monday(year); + week = (today - week1_monday) / 7; + day = (today - week1_monday) % 7; + } + else if (week >= 52 && + today >= iso_week1_monday(year + 1)) { + ++year; + week = 0; + } + return Py_BuildValue("iii", year, week + 1, day + 1); + } + + + static PyObject * datetime_isoformat(PyDateTime_Object *self, PyObject *args, PyObject *kw) { *************** *** 285,295 **** static PyMethodDef datetime_methods[] = { ! {"isoformat", (PyCFunction)datetime_isoformat, METH_VARARGS|METH_KEYWORDS, "Return the day of the week represented by the datetime.\n" "Monday == 1 ... Sunday == 7"}, ! {"isoweekday", (PyCFunction)datetime_isoweekday, METH_NOARGS, "Return the day of the week represented by the datetime.\n" "Monday == 1 ... Sunday == 7"}, ! {"weekday", (PyCFunction)datetime_weekday, METH_NOARGS, "Return the day of the week represented by the datetime.\n" "Monday == 0 ... Sunday == 6"}, --- 323,337 ---- static PyMethodDef datetime_methods[] = { ! {"isocalendar", (PyCFunction)datetime_isocalendar, METH_NOARGS, ! "Return a 3-tuple containing ISO year, week number, and weekday.\n\n" ! "The first ISO week of the year is the (Mon-Sun) week containing the\n" ! "year's first Thursday; everything rest derives from that."}, ! {"isoformat", (PyCFunction)datetime_isoformat, METH_VARARGS|METH_KEYWORDS, "Return the day of the week represented by the datetime.\n" "Monday == 1 ... Sunday == 7"}, ! {"isoweekday", (PyCFunction)datetime_isoweekday, METH_NOARGS, "Return the day of the week represented by the datetime.\n" "Monday == 1 ... Sunday == 7"}, ! {"weekday", (PyCFunction)datetime_weekday, METH_NOARGS, "Return the day of the week represented by the datetime.\n" "Monday == 0 ... Sunday == 6"}, From fdrake@users.sourceforge.net Wed Mar 6 05:55:02 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 05 Mar 2002 21:55:02 -0800 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_cdatetime.py,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/datetime In directory usw-pr-cvs1:/tmp/cvs-serv15991 Modified Files: test_cdatetime.py Log Message: Add the tests for isocalendar(), isoformat(), isoweekday(), and weekday(), but comment out the parts that use a timedelta object since that doesnt Index: test_cdatetime.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_cdatetime.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** test_cdatetime.py 6 Mar 2002 04:36:26 -0000 1.2 --- test_cdatetime.py 6 Mar 2002 05:55:00 -0000 1.3 *************** *** 35,38 **** --- 35,94 ---- self.assertEqual(dt.microsecond, 8000) + def test_isocalendar(self): + # Check examples from + # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm + for i in range(7): + d = self.theclass(2003, 12, 22+i) + self.assertEqual(d.isocalendar(), (2003, 52, i+1)) + ## d = self.theclass(2003, 12, 29) + timedelta(i) + ## self.assertEqual(d.isocalendar(), (2004, 1, i+1)) + d = self.theclass(2004, 1, 5+i) + self.assertEqual(d.isocalendar(), (2004, 2, i+1)) + d = self.theclass(2009, 12, 21+i) + self.assertEqual(d.isocalendar(), (2009, 52, i+1)) + ## d = self.theclass(2009, 12, 28) + timedelta(i) + ## self.assertEqual(d.isocalendar(), (2009, 53, i+1)) + d = self.theclass(2010, 1, 4+i) + self.assertEqual(d.isocalendar(), (2010, 1, i+1)) + + def test_iso_long_years(self): + # Calculate long ISO years and compare to table from + # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm + ISO_LONG_YEARS_TABLE = """ + 4 32 60 88 + 9 37 65 93 + 15 43 71 99 + 20 48 76 + 26 54 82 + + 105 133 161 189 + 111 139 167 195 + 116 144 172 + 122 150 178 + 128 156 184 + + 201 229 257 285 + 207 235 263 291 + 212 240 268 296 + 218 246 274 + 224 252 280 + + 303 331 359 387 + 308 336 364 392 + 314 342 370 398 + 320 348 376 + 325 353 381 + """ + iso_long_years = map(int, ISO_LONG_YEARS_TABLE.split()) + iso_long_years.sort() + L = [] + for i in range(400): + d = self.theclass(2000+i, 12, 31) + d1 = self.theclass(1600+i, 12, 31) + self.assertEqual(d.isocalendar()[1:], d1.isocalendar()[1:]) + if d.isocalendar()[1] == 53: + L.append(i) + self.assertEqual(L, iso_long_years) + def test_isoformat(self): t = self.theclass(2, 3, 2, 4, 5, 1, 123) *************** *** 40,43 **** --- 96,108 ---- self.assertEqual(t.isoformat('T'), "0002-03-02T04:05:01.000123") self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123") + + def test_weekday(self): + for i in range(7): + # March 4, 2002 is a Monday + self.assertEqual(self.theclass(2002, 3, 4+i).weekday(), i) + self.assertEqual(self.theclass(2002, 3, 4+i).isoweekday(), i+1) + # January 2, 1956 is a Monday + self.assertEqual(self.theclass(1956, 1, 2+i).weekday(), i) + self.assertEqual(self.theclass(1956, 1, 2+i).isoweekday(), i+1) From fdrake@acm.org Wed Mar 6 05:59:08 2002 From: fdrake@acm.org (Fred Drake) Date: Wed, 06 Mar 2002 00:59:08 -0500 Subject: [Python-checkins] CVS: python/nondist/sandbox/datetime test_cdatetime.py,1.2,1.3 In-Reply-To: Message-ID: On Tue, 05 Mar 2002 21:55:02 -0800 "Fred L. Drake" wrote: > but comment out the parts that use a timedelta object > since that doesnt Ooops! That was supposed to be "... doesn't exist yet in the C implementation." -Fred -- Fred L. Drake, Jr. PythonLabs at Zope Corporation From bwarsaw@users.sourceforge.net Wed Mar 6 13:16:10 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Wed, 06 Mar 2002 05:16:10 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0284.txt,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv28216 Added Files: pep-0284.txt Log Message: PEP 284, Integer for-loops, Eppstein & Ewing --- NEW FILE: pep-0284.txt --- PEP: 284 Title: Integer for-loops Version: $Revision: 1.1 $ Last-Modified: $Date: 2002/03/06 13:16:08 $ Author: eppstein@ics.uci.edu (David Eppstein), greg@cosc.canterbury.ac.nz (Greg Ewing) Status: Draft Type: Standards Track Created: 1-Mar-2002 Python-Version: 2.3 Post-History: Abstract This PEP proposes to simplify iteration over intervals of integers, by extending the range of expressions allowed after a "for" keyword to allow three-way comparisons such as for lower <= var < upper: in place of the current for item in list: syntax. The resulting loop or list iteration will loop over all values of var that make the comparison true, starting from the left endpoint of the given interval. Rationale One of the most common uses of for-loops in Python is to iterate over an interval of integers. Python provides functions range() and xrange() to generate lists and iterators for such intervals, which work best for the most frequent case: half-open intervals increasing from zero. However, the range() syntax is more awkward for open or closed intervals, and lacks symmetry when reversing the order of iteration. In addition, the call to an unfamiliar function makes it difficult for newcomers to Python to understand code that uses range() or xrange(). The perceived lack of a natural, intuitive integer iteration syntax has led to heated debate on python-list, and spawned at least four PEPs before this one. PEP 204 [1] (rejected) proposed to re-use Python's slice syntax for integer ranges, leading to a terser syntax but not solving the readability problem of multi-argument range(). PEP 212 [2] (deferred) proposed several syntaxes for directly converting a list to a sequence of integer indices, in place of the current idiom range(len(list)) for such conversion, and PEP 281 [3] proposes to simplify the same idiom by allowing it to be written as range(list). PEP 276 [4] proposes to allow automatic conversion of integers to iterators, simplifying the most common half-open case but not addressing the complexities of other types of interval. Additional alternatives have been discussed on python-list. The solution described here is to allow a three-way comparison after a "for" keyword, both in the context of a for-loop and of a list comprehension: for lower <= var < upper: This would cause iteration over an interval of consecutive integers, beginning at the left bound in the comparison and ending at the right bound. The exact comparison operations used would determine whether the interval is open or closed at either end and whether the integers are considered in ascending or descending order. This syntax closely matches standard mathematical notation, so is likely to be more familiar to Python novices than the current range() syntax. Open and closed interval endpoints are equally easy to express, and the reversal of an integer interval can be formed simply by swapping the two endpoints and reversing the comparisons. In addition, the semantics of such a loop would closely resemble one way of interpreting the existing Python for-loops: for item in list iterates over exactly those values of item that cause the expression item in list to be true. Similarly, the new format for lower <= var < upper: would iterate over exactly those integer values of var that cause the expression lower <= var < upper to be true. Specification We propose to extend the syntax of a for statement, currently for_stmt: "for" target_list "in" expression_list ":" suite ["else" ":" suite] as described below: for_stmt: "for" for_test ":" suite ["else" ":" suite] for_test: target_list "in" expression_list | or_expr less_comp or_expr less_comp or_expr | or_expr greater_comp identifier greater_comp or_expr less_comp: "<" | "<=" greater_comp: ">" | ">=" Similarly, we propose to extend the syntax of list comprehensions, currently list_for: "for" expression_list "in" testlist [list_iter] by replacing it with: list_for: "for" for_test [list_iter] In all cases the expression formed by for_test would be subject to the same precedence rules as comparisons in expressions. The two comp_operators in a for_test must be required to be both of similar types, unlike chained comparisons in expressions which do not have such a restriction. We refer to the two or_expr's occurring on the left and right sides of the for-loop syntax as the bounds of the loop, and the middle or_expr as the variable of the loop. When a for-loop using the new syntax is executed, the expressions for both bounds will be evaluated, and an iterator object created that iterates through all integers between the two bounds according to the comparison operations used. The iterator will begin with an integer equal or near to the left bound, and then step through the remaining integers with a step size of +1 or -1 if the comparison operation is in the set described by less_comp or greater_comp respectively. The execution will then proceed as if the expression had been for variable in iterator where "variable" refers to the variable of the loop and "iterator" refers to the iterator created for the given integer interval. The values taken by the loop variable in an integer for-loop may be either plain integers or long integers, according to the magnitude of the bounds. Both bounds of an integer for-loop must evaluate to a real numeric type (integer, long, or float). Any other value will cause the for-loop statement to raise a TypeError exception. Issues The following issues were raised in discussion of this and related proposals on the Python list. - Should the right bound be evaluated once, or every time through the loop? Clearly, it only makes sense to evaluate the left bound once. For reasons of consistency and efficiency, we have chosen the same convention for the right bound. - Although the new syntax considerably simplifies integer for-loops, list comprehensions using the new syntax are not as simple. We feel that this is appropriate since for-loops are more frequent than comprehensions. - The proposal does not allow access to integer iterator objects such as would be created by xrange. True, but we see this as a shortcoming in the general list-comprehension syntax, beyond the scope of this proposal. In addition, xrange() will still be available. - The proposal does not allow increments other than 1 and -1. More general arithmetic progressions would need to be created by range() or xrange(), or by a list comprehension syntax such as [2*x for 0 <= x <= 100] - The position of the loop variable in the middle of a three-way comparison is not as apparent as the variable in the present for item in list syntax, leading to a possible loss of readability. We feel that this loss is outweighed by the increase in readability from a natural integer iteration syntax. - To some extent, this PEP addresses the same issues as PEP 276 [4]. We feel that the two PEPs are not in conflict since PEP 276 is primarily concerned with half-open ranges starting in 0 (the easy case of range()) while this PEP is primarily concerned with simplifying all other cases. However, if this PEP is approved, its new simpler syntax for integer loops could to some extent reduce the motivation for PEP 276. - It is not clear whether it makes sense to allow floating point bounds for an integer loop: if a float represents an inexact value, how can it be used to determine an exact sequence of integers? On the other hand, disallowing float bounds would make it difficult to use floor() and ceiling() in integer for-loops, as it is difficult to use them now with range(). We have erred on the side of flexibility, but this may lead to some implementation difficulties in determining the smallest and largest integer values that would cause a given comparison to be true. - Should types other than int, long, and float be allowed as bounds? Another choice would be to convert all bounds to integers by int(), and allow as bounds anything that can be so converted instead of just floats. However, this would change the semantics: 0.3 <= x is not the same as int(0.3) <= x, and it would be confusing for a loop with 0.3 as lower bound to start at zero. Also, in general int(f) can be very far from f. Implementation An implementation is not available at this time. Implementation is not expected to pose any great difficulties: the new syntax could, if necessary, be recognized by parsing a general expression after each "for" keyword and testing whether the top level operation of the expression is "in" or a three-way comparison. The Python compiler would convert any instance of the new syntax into a loop over the items in a special iterator object. References [1] PEP 204, Range Literals http://www.python.org/peps/pep-0204.html [2] PEP 212, Loop Counter Iteration http://www.python.org/peps/pep-0212.html [3] PEP 281, Loop Counter Iteration with range and xrange http://www.python.org/peps/pep-0281.html [4] PEP 276, Simple Iterator for ints http://www.python.org/peps/pep-0276.html Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil fill-column: 70 End: From bwarsaw@users.sourceforge.net Wed Mar 6 13:16:25 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Wed, 06 Mar 2002 05:16:25 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.159,1.160 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv28282 Modified Files: pep-0000.txt Log Message: Added PEP 284, Integer for-loops, Eppstein & Ewing Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.159 retrieving revision 1.160 diff -C2 -d -r1.159 -r1.160 *** pep-0000.txt 27 Feb 2002 23:02:11 -0000 1.159 --- pep-0000.txt 6 Mar 2002 13:16:22 -0000 1.160 *************** *** 250,253 **** --- 250,254 ---- S 282 A Logging System Mick I 283 Python 2.3 Release Schedule Hylton + S 284 Integer for-loops Eppstein, Ewing SR 666 Reject Foolish Indentation Creighton *************** *** 276,285 **** Drake, Fred fdrake@acm.org Dubois, Paul F. paul@pfdubois.com Evans, Clark C. cce@clarkevans.com Giacometti, Frédéric B. fred@arakne.com Goodger, David dgoodger@bigfoot.com Griffin, Grant g2@iowegian.com Hetland, Magnus Lie magnus@hetland.org ! Hettinger, Raymond D. othello@javanet.com Hodgson, Neil neilh@scintilla.org Hudson, Michael mwh@python.net --- 277,288 ---- Drake, Fred fdrake@acm.org Dubois, Paul F. paul@pfdubois.com + Eppstein, David eppstein@ics.uci.edu Evans, Clark C. cce@clarkevans.com + Ewing, Greg greg@cosc.canterbury.ac.nz Giacometti, Frédéric B. fred@arakne.com Goodger, David dgoodger@bigfoot.com Griffin, Grant g2@iowegian.com Hetland, Magnus Lie magnus@hetland.org ! Hettinger, Raymond D. python@rcn.com Hodgson, Neil neilh@scintilla.org Hudson, Michael mwh@python.net From mwh@users.sourceforge.net Wed Mar 6 17:18:17 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Wed, 06 Mar 2002 09:18:17 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_structseq.py,1.2,1.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv26183 Modified Files: test_structseq.py Log Message: Test for [ 526039 ] devious code can crash structseqs Bugfix candidate. Index: test_structseq.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_structseq.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** test_structseq.py 31 Oct 2001 03:46:14 -0000 1.2 --- test_structseq.py 6 Mar 2002 17:18:15 -0000 1.3 *************** *** 14,16 **** --- 14,28 ---- vereq(t[i:j], astuple[i:j]) + # Devious code could crash structseqs' contructors + class C: + def __getitem__(self, i): + raise IndexError + def __len__(self): + return 9 + + try: + repr(time.struct_time(C())) + except: + pass + # XXX more needed From mwh@python.net Wed Mar 6 17:22:30 2002 From: mwh@python.net (Michael Hudson) Date: 06 Mar 2002 17:22:30 +0000 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_structseq.py,1.2,1.3 In-Reply-To: Michael Hudson's message of "Wed, 06 Mar 2002 09:18:17 -0800" References: Message-ID: <2m1yex1ui1.fsf@starship.python.net> Michael Hudson writes: > Update of /cvsroot/python/python/dist/src/Lib/test > In directory usw-pr-cvs1:/tmp/cvs-serv26183 > > Modified Files: > test_structseq.py > Log Message: > Test for > > [ 526039 ] devious code can crash structseqs > > Bugfix candidate. Hmm, I made some checkins before this one: to Lib/os.py, Objects/structseq.c and Lib/test/pickletester.py. I wonder where they went? Cheers, M. -- Every now and then, Google doesn't throw up what I need so I start checking Altavista, Yahoo, etc. In almost every single case, I am brutally reminded why I use Google in the first place. -- John Riddoch, asr From mwh@users.sourceforge.net Wed Mar 6 17:11:20 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Wed, 06 Mar 2002 09:11:20 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib os.py,1.51,1.52 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv22847 Modified Files: os.py Log Message: Special support for pickling os.stat and os.stat_vfs results portably (the types come from different modules on different platforms). Added tests for pickling these types. May be a bugfix candidate. Index: os.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/os.py,v retrieving revision 1.51 retrieving revision 1.52 diff -C2 -d -r1.51 -r1.52 *** os.py 24 Feb 2002 05:32:32 -0000 1.51 --- os.py 6 Mar 2002 17:11:17 -0000 1.52 *************** *** 603,604 **** --- 603,624 ---- return stdin, stdout __all__.append("popen4") + + import copy_reg as _copy_reg + + def _make_stat_result(tup, dict): + return stat_result(tup, dict) + + def _pickle_stat_result(sr): + (type, args) = sr.__reduce__() + return (_make_stat_result, args) + + _copy_reg.pickle(stat_result, _pickle_stat_result,_make_stat_result) + + def _make_statvfs_result(tup, dict): + return statvfs_result(tup, dict) + + def _pickle_statvfs_result(sr): + (type, args) = sr.__reduce__() + return (_make_statvfs_result, args) + + _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,_make_statvfs_result) From mwh@users.sourceforge.net Wed Mar 6 17:11:20 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Wed, 06 Mar 2002 09:11:20 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test pickletester.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv22847/test Modified Files: pickletester.py Log Message: Special support for pickling os.stat and os.stat_vfs results portably (the types come from different modules on different platforms). Added tests for pickling these types. May be a bugfix candidate. Index: pickletester.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/pickletester.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** pickletester.py 5 Mar 2002 13:27:58 -0000 1.13 --- pickletester.py 6 Mar 2002 17:11:18 -0000 1.14 *************** *** 255,258 **** --- 255,269 ---- u = self.loads(s) self.assertEqual(t, u) + import os + if hasattr(os, "stat"): + t = os.stat(os.curdir) + s = self.dumps(t) + u = self.loads(s) + self.assertEqual(t, u) + if hasattr(os, "statvfs"): + t = os.statvfs(os.curdir) + s = self.dumps(t) + u = self.loads(s) + self.assertEqual(t, u) class AbstractPickleModuleTests(unittest.TestCase): From mwh@users.sourceforge.net Wed Mar 6 17:07:51 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Wed, 06 Mar 2002 09:07:51 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects structseq.c,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv20601 Modified Files: structseq.c Log Message: Apply (my) patch: [ 526072 ] pickling os.stat results round II structseq's constructors can now take "invisible" fields in a dict. Gave the constructors better error messages. their __reduce__ method puts these fields in a dict. (this is all in aid of getting os.stat_result's to pickle portably) Also fixes [ 526039 ] devious code can crash structseqs Thought needed about how much of this counts as a bugfix. Certainly #526039 needs to be fixed. Index: structseq.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** structseq.c 5 Mar 2002 13:27:57 -0000 1.4 --- structseq.c 6 Mar 2002 17:07:49 -0000 1.5 *************** *** 85,121 **** { PyObject *arg = NULL; PyStructSequence *res = NULL; ! int len, required_len, i; ! static char *kwlist[] = {"sequence", 0}; ! static char msgbuf[128]; ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:structseq", ! kwlist, &arg)) return NULL; ! if (!PySequence_Check(arg)) { ! PyErr_SetString(PyExc_TypeError, ! "constructor requires a sequence"); return NULL; } ! len = PySequence_Length(arg); ! required_len = REAL_SIZE_TP(type); ! if (len != required_len) { ! PyOS_snprintf( ! msgbuf, sizeof(msgbuf), ! "constructor takes exactly %d arguments (%d given)", ! required_len, ! len); ! PyErr_SetString(PyExc_TypeError, msgbuf); return NULL; } res = (PyStructSequence*) PyStructSequence_New(type); for (i = 0; i < len; ++i) { ! /* INCREF???? XXXX */ ! res->ob_item[i] = PySequence_GetItem(arg, i); } return (PyObject*) res; } --- 85,161 ---- { PyObject *arg = NULL; + PyObject *dict = NULL; + PyObject *ob; PyStructSequence *res = NULL; ! int len, min_len, max_len, i; ! static char *kwlist[] = {"sequence", "dict", 0}; ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq", ! kwlist, &arg, &dict)) return NULL; ! arg = PySequence_Fast(arg, "constructor requires a sequence"); ! ! if (!arg) { return NULL; } ! if (dict && !PyDict_Check(dict)) { ! PyErr_Format(PyExc_TypeError, ! "%.500s() takes a dict as second arg, if any", ! type->tp_name); ! Py_DECREF(arg); return NULL; } + len = PySequence_Fast_GET_SIZE(arg); + min_len = VISIBLE_SIZE_TP(type); + max_len = REAL_SIZE_TP(type); + + if (min_len != max_len) { + if (len < min_len) { + PyErr_Format(PyExc_TypeError, + "%.500s() takes an at least %d-sequence (%d-sequence given)", + type->tp_name, min_len, len); + Py_DECREF(arg); + return NULL; + } + + if (len > max_len) { + PyErr_Format(PyExc_TypeError, + "%.500s() takes an at most %d-sequence (%d-sequence given)", + type->tp_name, max_len, len); + Py_DECREF(arg); + return NULL; + } + } + else { + if (len != min_len) { + PyErr_Format(PyExc_TypeError, + "%.500s() takes a %d-sequence (%d-sequence given)", + type->tp_name, min_len, len); + Py_DECREF(arg); + return NULL; + } + } + res = (PyStructSequence*) PyStructSequence_New(type); for (i = 0; i < len; ++i) { ! PyObject *v = PySequence_Fast_GET_ITEM(arg, i); ! Py_INCREF(v); ! res->ob_item[i] = v; ! } ! for (; i < max_len; ++i) { ! if (dict && (ob = PyDict_GetItemString( ! dict, type->tp_members[i].name))) { ! } ! else { ! ob = Py_None; ! } ! Py_INCREF(ob); ! res->ob_item[i] = ob; } + Py_DECREF(arg); return (PyObject*) res; } *************** *** 193,211 **** { PyObject* tup; ! long n_fields; int i; n_fields = REAL_SIZE(self); ! tup = PyTuple_New(n_fields); if (!tup) { return NULL; } ! for (i = 0; i < n_fields; i++) { Py_INCREF(self->ob_item[i]); PyTuple_SET_ITEM(tup, i, self->ob_item[i]); } ! return Py_BuildValue("(O(O))", self->ob_type, tup); } --- 233,264 ---- { PyObject* tup; ! PyObject* dict; ! long n_fields, n_visible_fields; int i; n_fields = REAL_SIZE(self); ! n_visible_fields = VISIBLE_SIZE(self); ! tup = PyTuple_New(n_visible_fields); if (!tup) { return NULL; } ! dict = PyDict_New(); ! if (!dict) { ! Py_DECREF(tup); ! return NULL; ! } ! ! for (i = 0; i < n_visible_fields; i++) { Py_INCREF(self->ob_item[i]); PyTuple_SET_ITEM(tup, i, self->ob_item[i]); } ! for (; i < n_fields; i++) { ! PyDict_SetItemString(dict, self->ob_type->tp_members[i].name, ! self->ob_item[i]); ! } ! ! return Py_BuildValue("(O(OO))", self->ob_type, tup, dict); } From neal@metaslash.com Wed Mar 6 17:34:28 2002 From: neal@metaslash.com (Neal Norwitz) Date: Wed, 06 Mar 2002 12:34:28 -0500 Subject: [Python-checkins] CVS: python/dist/src/Lib os.py,1.51,1.52 References: Message-ID: <3C865324.C0D3B332@metaslash.com> Michael: I'm curious why you did import copy_reg as _copy_reg. Is it because you don't want clutter when doing 'from os import *'? Would it be better to do: import copy_reg # use copy_reg del copy_reg ? Neal -- Michael Hudson wrote: > > Update of /cvsroot/python/python/dist/src/Lib > In directory usw-pr-cvs1:/tmp/cvs-serv22847 > > Modified Files: > os.py > Log Message: > Special support for pickling os.stat and os.stat_vfs results portably > (the types come from different modules on different platforms). > > Added tests for pickling these types. > > May be a bugfix candidate. > > Index: os.py > =================================================================== > RCS file: /cvsroot/python/python/dist/src/Lib/os.py,v > retrieving revision 1.51 > retrieving revision 1.52 > diff -C2 -d -r1.51 -r1.52 > *** os.py 24 Feb 2002 05:32:32 -0000 1.51 > --- os.py 6 Mar 2002 17:11:17 -0000 1.52 > *************** > *** 603,604 **** > --- 603,624 ---- > return stdin, stdout > __all__.append("popen4") > + > + import copy_reg as _copy_reg > + > + def _make_stat_result(tup, dict): > + return stat_result(tup, dict) > + > + def _pickle_stat_result(sr): > + (type, args) = sr.__reduce__() > + return (_make_stat_result, args) > + > + _copy_reg.pickle(stat_result, _pickle_stat_result,_make_stat_result) > + > + def _make_statvfs_result(tup, dict): > + return statvfs_result(tup, dict) > + > + def _pickle_statvfs_result(sr): > + (type, args) = sr.__reduce__() > + return (_make_statvfs_result, args) > + > + _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,_make_statvfs_result) From bwarsaw@users.sourceforge.net Wed Mar 6 20:48:24 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Wed, 06 Mar 2002 12:48:24 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.160,1.161 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv31219 Modified Files: pep-0000.txt Log Message: Added PEP 284 to the "Open PEPs" category (although Guido will likely reorganize this soon ;). Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.160 retrieving revision 1.161 diff -C2 -d -r1.160 -r1.161 *** pep-0000.txt 6 Mar 2002 13:16:22 -0000 1.160 --- pep-0000.txt 6 Mar 2002 20:48:22 -0000 1.161 *************** *** 86,89 **** --- 86,90 ---- S 281 Loop Counter Iteration with range and xrange Hetland S 282 A Logging System Mick + S 284 Integer for-loops Eppstein, Ewing Finished PEPs (done, implemented in CVS) From bwarsaw@users.sourceforge.net Wed Mar 6 20:53:49 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Wed, 06 Mar 2002 12:53:49 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0284.txt,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv455 Modified Files: pep-0284.txt Log Message: An update from David Eppstein. Index: pep-0284.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0284.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pep-0284.txt 6 Mar 2002 13:16:08 -0000 1.1 --- pep-0284.txt 6 Mar 2002 20:53:47 -0000 1.2 *************** *** 115,119 **** for_test: target_list "in" expression_list | or_expr less_comp or_expr less_comp or_expr | ! or_expr greater_comp identifier greater_comp or_expr less_comp: "<" | "<=" greater_comp: ">" | ">=" --- 115,119 ---- for_test: target_list "in" expression_list | or_expr less_comp or_expr less_comp or_expr | ! or_expr greater_comp or_expr greater_comp or_expr less_comp: "<" | "<=" greater_comp: ">" | ">=" From jhylton@users.sourceforge.net Wed Mar 6 20:56:48 2002 From: jhylton@users.sourceforge.net (Jeremy Hylton) Date: Wed, 06 Mar 2002 12:56:48 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0283.txt,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv1333 Modified Files: pep-0283.txt Log Message: Put "PEP" in front of PEP numbers. Index: pep-0283.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0283.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pep-0283.txt 27 Feb 2002 23:06:43 -0000 1.2 --- pep-0283.txt 6 Mar 2002 20:56:46 -0000 1.3 *************** *** 43,52 **** PEP isn't on this list, it's because I'm not a confident channeler. ! 266 Optimizing Global Variable/Attribute Access Montanaro ! 267 Optimized Access to Module Namespaces Hylton ! 269 Pgen Module for Python Riehl ! 273 Import Modules from Zip Archives Ahlstrom ! 280 Optimizing access to globals van Rossum ! 282 A Logging System Mick Copyright --- 43,52 ---- PEP isn't on this list, it's because I'm not a confident channeler. ! PEP 266 Optimizing Global Variable/Attribute Access Montanaro ! PEP 267 Optimized Access to Module Namespaces Hylton ! PEP 269 Pgen Module for Python Riehl ! PEP 273 Import Modules from Zip Archives Ahlstrom ! PEP 280 Optimizing access to globals van Rossum ! PEP 282 A Logging System Mick Copyright From jackjansen@users.sourceforge.net Wed Mar 6 21:57:49 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 06 Mar 2002 13:57:49 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Build _CG.carbon.mcp,1.2,1.2.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Build In directory usw-pr-cvs1:/tmp/cvs-serv22676/Python 2.2/Mac/Build Modified Files: Tag: release22-maint _CG.carbon.mcp Log Message: Backport of 1.3: CGStubLib wasn't weak-linked, fixed. Index: _CG.carbon.mcp =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Build/_CG.carbon.mcp,v retrieving revision 1.2 retrieving revision 1.2.4.1 diff -C2 -d -r1.2 -r1.2.4.1 Binary files /tmp/cvsGwoSjw and /tmp/cvs2f9JhS differ From jackjansen@users.sourceforge.net Wed Mar 6 21:59:39 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 06 Mar 2002 13:59:39 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/cg cgsupport.py,1.2,1.2.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cg In directory usw-pr-cvs1:/tmp/cvs-serv23586/Python 2.2/Mac/Modules/cg Modified Files: Tag: release22-maint cgsupport.py Log Message: Backport of 1.4 and 1.5: Added support for SyncCGContextOriginWithPort Added ClipCGContextToRegion Index: cgsupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/cgsupport.py,v retrieving revision 1.2 retrieving revision 1.2.6.1 diff -C2 -d -r1.2 -r1.2.6.1 *** cgsupport.py 13 Dec 2001 13:40:04 -0000 1.2 --- cgsupport.py 6 Mar 2002 21:59:37 -0000 1.2.6.1 *************** *** 18,21 **** --- 18,23 ---- from macsupport import * + CGrafPtr = OpaqueByValueType("CGrafPtr", "GrafObj") + RgnHandle = OpaqueByValueType("RgnHandle", "ResObj") # Create the type objects *************** *** 275,278 **** --- 277,296 ---- # ADD _methods initializer here execfile(INPUTFILE) + + # manual method, lives in Quickdraw.h + f = Method(void, 'SyncCGContextOriginWithPort', + (CGContextRef, 'ctx', InMode), + (CGrafPtr, 'port', InMode), + ) + CGContextRef_methods.append(f) + + # manual method, lives in Quickdraw.h + f = Method(void, 'ClipCGContextToRegion', + (CGContextRef, 'ctx', InMode), + (Rect, 'portRect', InMode), + (RgnHandle, 'region', InMode), + ) + CGContextRef_methods.append(f) + CreateCGContextForPort_body = """\ From jackjansen@users.sourceforge.net Wed Mar 6 21:59:47 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 06 Mar 2002 13:59:47 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/cg _CGmodule.c,1.3,1.3.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cg In directory usw-pr-cvs1:/tmp/cvs-serv23624/Python 2.2/Mac/Modules/cg Modified Files: Tag: release22-maint _CGmodule.c Log Message: Backport of 1.4 and 1.5: Added support for SyncCGContextOriginWithPort Added ClipCGContextToRegion Index: _CGmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/_CGmodule.c,v retrieving revision 1.3 retrieving revision 1.3.4.1 diff -C2 -d -r1.3 -r1.3.4.1 *** _CGmodule.c 18 Dec 2001 15:38:24 -0000 1.3 --- _CGmodule.c 6 Mar 2002 21:59:45 -0000 1.3.4.1 *************** *** 1116,1119 **** --- 1116,1150 ---- } + static PyObject *CGContextRefObj_SyncCGContextOriginWithPort(CGContextRefObject *_self, PyObject *_args) + { + PyObject *_res = NULL; + CGrafPtr port; + if (!PyArg_ParseTuple(_args, "O&", + GrafObj_Convert, &port)) + return NULL; + SyncCGContextOriginWithPort(_self->ob_itself, + port); + Py_INCREF(Py_None); + _res = Py_None; + return _res; + } + + static PyObject *CGContextRefObj_ClipCGContextToRegion(CGContextRefObject *_self, PyObject *_args) + { + PyObject *_res = NULL; + Rect portRect; + RgnHandle region; + if (!PyArg_ParseTuple(_args, "O&O&", + PyMac_GetRect, &portRect, + ResObj_Convert, ®ion)) + return NULL; + ClipCGContextToRegion(_self->ob_itself, + &portRect, + region); + Py_INCREF(Py_None); + _res = Py_None; + return _res; + } + static PyMethodDef CGContextRefObj_methods[] = { {"CGContextSaveGState", (PyCFunction)CGContextRefObj_CGContextSaveGState, 1, *************** *** 1229,1232 **** --- 1260,1267 ---- {"CGContextSetShouldAntialias", (PyCFunction)CGContextRefObj_CGContextSetShouldAntialias, 1, "(int shouldAntialias) -> None"}, + {"SyncCGContextOriginWithPort", (PyCFunction)CGContextRefObj_SyncCGContextOriginWithPort, 1, + "(CGrafPtr port) -> None"}, + {"ClipCGContextToRegion", (PyCFunction)CGContextRefObj_ClipCGContextToRegion, 1, + "(Rect portRect, RgnHandle region) -> None"}, {NULL, NULL, 0} }; From jackjansen@users.sourceforge.net Wed Mar 6 21:59:52 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 06 Mar 2002 13:59:52 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/cg CGStubLib,1.1,1.1.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cg In directory usw-pr-cvs1:/tmp/cvs-serv23661/Python 2.2/Mac/Modules/cg Modified Files: Tag: release22-maint CGStubLib Log Message: Backport of 1.4 and 1.5: Added support for SyncCGContextOriginWithPort Added ClipCGContextToRegion Index: CGStubLib =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/CGStubLib,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -C2 -d -r1.1 -r1.1.6.1 Binary files /tmp/cvsaeMwET and /tmp/cvsuiVkdD differ From jackjansen@users.sourceforge.net Wed Mar 6 21:59:56 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 06 Mar 2002 13:59:56 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/cg CGStubLib.exp,1.1,1.1.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cg In directory usw-pr-cvs1:/tmp/cvs-serv23696/Python 2.2/Mac/Modules/cg Modified Files: Tag: release22-maint CGStubLib.exp Log Message: Backport of 1.4 and 1.5: Added support for SyncCGContextOriginWithPort Added ClipCGContextToRegion Index: CGStubLib.exp =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/CGStubLib.exp,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -C2 -d -r1.1 -r1.1.6.1 *** CGStubLib.exp 13 Dec 2001 13:17:20 -0000 1.1 --- CGStubLib.exp 6 Mar 2002 21:59:54 -0000 1.1.6.1 *************** *** 57,58 **** --- 57,60 ---- CGContextRelease CreateCGContextForPort + SyncCGContextOriginWithPort + ClipCGContextToRegion From jackjansen@users.sourceforge.net Wed Mar 6 22:00:31 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 06 Mar 2002 14:00:31 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac ReadMe,1.38.4.2,1.38.4.2.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac In directory usw-pr-cvs1:/tmp/cvs-serv23958/Python 2.2/Mac Modified Files: Tag: release22-maint ReadMe Log Message: First stab at files for 2.2.1. Index: ReadMe =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/ReadMe,v retrieving revision 1.38.4.2 retrieving revision 1.38.4.2.2.1 diff -C2 -d -r1.38.4.2 -r1.38.4.2.2.1 *** ReadMe 26 Dec 2001 22:56:44 -0000 1.38.4.2 --- ReadMe 6 Mar 2002 22:00:29 -0000 1.38.4.2.2.1 *************** *** 1,3 **** ! How to install Python 2.2 on your Macintosh --------------------------------------------- --- 1,3 ---- ! How to install Python 2.2.1 on your Macintosh --------------------------------------------- *************** *** 36,96 **** If you want 68k support you will have get MacPython 1.5.2. - Toolbox module reorganization and more - -------------------------------------- - - You can safely skip this section if this is your first encounter with MacPython. - - This release has a new organization of the mac-specific modules, and in - general brings the MacPython folder structure more in line with - unix-Python. This is not only a good idea, it will also immensely - facilitate moving MacPython functionality to an OSX Python that is based - on Mach-O and the unix-Python distribution. But don't worry: MacPython - is definitely not dead yet, and the hope is that the transition will be - as seamless as possible. - - First a change that should not cause too much concern: :Mac:Plugins has - gone, and most of the dynamically loaded modules have moved to - :Lib:lib-dynload. - - Second, and more important: the toolbox modules, such as Res and - Resource, have moved to a Carbon package. So, in stead of "import Res" - you should now say "from Carbon import Res" and in stead of "from Res - import *" you should use "from Carbon.Res import *". For the lifetime of - MacPython 2.2 there is a folder :Mac:Lib:lib-compat on sys.path that - contains modules with the old names which imports the new names after - issuing a warning. - - Note that although the package is called Carbon the modules work fine under - classic PPC, and they are normal classic modules. Also note that some - modules you may think of as toolbox modules (such as Waste) really are not, - and they are not in the Carbon package. - - Also, all toolbox modules have been updated to Universal Headers 3.4, and - are (for classic PPC) weak-linked against InterfaceLib so that they should - work on all systems back to MacOS 8.1. Calling an unimplemented function will - raise an exception, not crash your interpreter. - - Another change related to the OSX growth path is that there is a new module - macresource that you can use to easily open a resource file accompanying your - script. Use "macresource.need("DLOG", MY_DIALOG_ID, "name.rsrc") and if the - given resource is not available (it _is_ available if your script has been - turned into an applet) the given resource file will be opened. This method will - eventually also contain the magic needed to open the resource file on - OSX MachO Python. - - Another feature to help with the OSX transition is that if you open a - textfile for reading MacPython will now accept either unix linefeeds - (LF, '\n') or Macintosh linefeeds (CR, '\r') and present both of them - as '\n'. This is done on a low level, so it works for files opened by - scripts as well as for your scripts and modules itself. This can be - turned off with a preference/startup option. - - But: - - this works only for input, and there's no way to find out what the original - linefeed convention of the file was. - - Windows \r\n linefeeds are not supported and get turned into \n\n. - - in 2.3 this feature will be replaced by a more general, platform independent - way of handling files with foreign newline conventions. - What to install --------------- --- 36,39 ---- *************** *** 171,175 **** Up to three items are installed in the system folder: the interpreter shared libraries PythonCore and PythonCoreCarbon live in the Extensions ! folder and the "Python 2.2 Preferences" file in the Python subfolder in the Preferences folder. All the rest of Python lives in the folder you installed in. --- 114,118 ---- Up to three items are installed in the system folder: the interpreter shared libraries PythonCore and PythonCoreCarbon live in the Extensions ! folder and the "Python 2.2.1 Preferences" file in the Python subfolder in the Preferences folder. All the rest of Python lives in the folder you installed in. *************** *** 219,225 **** are lost and you have to set them again. ! After you are satisfied that 2.2 works as expected you can trash anything in the system folder that has "python" in the name and not ! "2.2". The ConfigurePython... applets will try to detect incompatible --- 162,168 ---- are lost and you have to set them again. ! After you are satisfied that 2.2.1 works as expected you can trash anything in the system folder that has "python" in the name and not ! "2.2.1". The ConfigurePython... applets will try to detect incompatible From jackjansen@users.sourceforge.net Wed Mar 6 22:00:37 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Wed, 06 Mar 2002 14:00:37 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac Relnotes,1.28.4.2,1.28.4.2.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac In directory usw-pr-cvs1:/tmp/cvs-serv24034/Python 2.2/Mac Modified Files: Tag: release22-maint Relnotes Log Message: First stab at files for 2.2.1. Index: Relnotes =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Relnotes,v retrieving revision 1.28.4.2 retrieving revision 1.28.4.2.2.1 diff -C2 -d -r1.28.4.2 -r1.28.4.2.2.1 *** Relnotes 26 Dec 2001 22:56:50 -0000 1.28.4.2 --- Relnotes 6 Mar 2002 22:00:35 -0000 1.28.4.2.2.1 *************** *** 1,3 **** ! Changes in 2.2 since 2.1.1 ---------------------------- --- 1,3 ---- ! Changes in 2.2.1 since 2.2 ---------------------------- *************** *** 5,55 **** for machine-independent changes. ! ! - The main change is that all toolbox modules have moved to a package called Carbon. ! So things like "import Res" should be changed to "from Carbon import Res", and ! "from Res import *" to "from Carbon.Res import *". Please see the readme file for ! some open questions and join the discussions on pythonmac-sig if you have anything ! to contribute. Aside from reducing clutter this change will also benefit the ! port to Mach-O/OSX Python later. ! - All toolbox modules have been updated to Universal Headers 3.4. ! - Toolbox modules are weaklinked against InterfaceLib (for PPC builds) and raise ! an exception when you call an unimplemented one on an old MacOS. ! - On input MacPython now accepts either \n (unix style) or \r (mac style) newlines ! for text files. This behaviour can be turned off with a preference. ! This is an experimental feature; again: feedback is requested. ! - The IDE looks better on OS X, but still not as good as on OS9. ! - Command-dot handling has been improved a lot: scripts are now much easier to interrupt, ! and they only scan for cmd-. while in the foreground. ! - "Copy" from the MacPython console window was always disabled. Fixed. ! - This release should run on MacOS 8.1 again. ! - A new, rather different GUSI I/O library is used. ! - time.time() returns positive values again. ! - There is a new module macresource which makes it easier to open a resource file ! accompanying your script when the script is not (yet) converted to an applet. ! This module will later also do the right thing in Mach-O/OSX Python. ! - (Carbon only) experimental modules Carbon.CG (CoreGraphics) and CarbonEvt have ! been added. ! - A new, experimental module hfsplus is included, which gives access to some of the ! functionality of the HFS+ API. ! - A new, experimental module gives access to Carbon Events. ! - Threads had a stack that was too small for many serious Python applications (20K). ! They now get 64K. There is still no overflow check, though. ! - Garbage collection and the gc module have (finally) been enabled. ! - EasyDialogs.ProgressBar now has indeterminate progressbars if you specify maxval=0. ! This is also the new default. Patch supplied by Dean Draayer. ! - There are new preferences for enabling old-style division warnings and for ! accepting unix-style newlines in text input files. These can also be set during ! startup, and in addition you can select very verbose import tracing. ! - The NavServices override for StandardFile has moved from early startup to the ! time you import macfs. This speeds up MacPython startup. ! - Various outdated scripts have been moved to :Mac:Unsupported. ! - Various outdated items from :Mac:Lib:test have been removed. ! - C Developers: you know have control over the Python console if you are embedding ! MacPython in another application, thanks to Alexandre Parenteau. :Mac:Demo:embed.html ! has very minimal documentation. ! - BuildCGIApplet works again. ! - The CodeWarrior OSA suite missed quit(). It is back. ! - Contrib:morefindertools is gone, the functionality has been integrated into ! the standard module findertools.py. Known problems --- 5,12 ---- for machine-independent changes. ! - This release should work on multiprocessor OSX machines. ! - The problem with incomplete read()s on sockets has been fixed. ! - NavServices is now weaklinked, so this release should work on a virgin Mac OS 8.1. ! - Much more: to be supplied. Known problems *************** *** 59,66 **** http://www.cwi.nl/~jack/macpython.html. - - MacPython 2.2 (and MacPython 2.1) will not run correctly on a multiprocessor MacOS X - machine, it will quickly deadlock during I/O operations. The GUSI I/O library is suspected, - hints/clues/workarounds are solicited. This problem also occurs intermittently on fast - OS X single-processor machines. - Tkinter does not work under Carbon. - The IDE and Tkinter do not work together. Run tkinter programs under PythonInterpreter. --- 16,19 ---- From mwh@users.sourceforge.net Thu Mar 7 09:58:59 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 01:58:59 -0800 Subject: [Python-checkins] CVS: python/dist/src setup.py,1.83,1.84 configure.in,1.292,1.293 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv16226 Modified Files: setup.py configure.in Log Message: Apply Jack's patch attached to [ 508779 ] Disable flat namespace on MacOS X I presume you wanted this on the trunk too, Jack? 2.2.1 candidate. Index: setup.py =================================================================== RCS file: /cvsroot/python/python/dist/src/setup.py,v retrieving revision 1.83 retrieving revision 1.84 diff -C2 -d -r1.83 -r1.84 *** setup.py 1 Mar 2002 14:16:31 -0000 1.83 --- setup.py 7 Mar 2002 09:58:56 -0000 1.84 *************** *** 605,609 **** # procedure triggers on. frameworkdir = sysconfig.get_config_var('PYTHONFRAMEWORKDIR') ! exts.append( Extension('gestalt', ['gestaltmodule.c']) ) exts.append( Extension('MacOS', ['macosmodule.c'], extra_link_args=['-framework', 'Carbon']) ) --- 605,610 ---- # procedure triggers on. frameworkdir = sysconfig.get_config_var('PYTHONFRAMEWORKDIR') ! exts.append( Extension('gestalt', ['gestaltmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('MacOS', ['macosmodule.c'], extra_link_args=['-framework', 'Carbon']) ) *************** *** 614,619 **** '../Python/getapplbycreator.c'], extra_link_args=['-framework', 'Carbon']) ) ! exts.append( Extension('_CF', ['cf/_CFmodule.c']) ) ! exts.append( Extension('_Res', ['res/_Resmodule.c']) ) exts.append( Extension('_Snd', ['snd/_Sndmodule.c'], extra_link_args=['-framework', 'Carbon']) ) --- 615,622 ---- '../Python/getapplbycreator.c'], extra_link_args=['-framework', 'Carbon']) ) ! exts.append( Extension('_CF', ['cf/_CFmodule.c'], ! extra_link_args=['-framework', 'CoreFoundation']) ) ! exts.append( Extension('_Res', ['res/_Resmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Snd', ['snd/_Sndmodule.c'], extra_link_args=['-framework', 'Carbon']) ) Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.292 retrieving revision 1.293 diff -C2 -d -r1.292 -r1.293 *** configure.in 24 Feb 2002 16:05:05 -0000 1.292 --- configure.in 7 Mar 2002 09:58:56 -0000 1.293 *************** *** 794,799 **** LDSHARED="$LDSHARED "'-framework $(PYTHONFRAMEWORK)' else ! # No framework. Ignore undefined symbols, assuming they come from Python ! LDSHARED="$LDSHARED -flat_namespace -undefined suppress" fi ;; Linux*|GNU*) LDSHARED="gcc -shared";; --- 794,800 ---- LDSHARED="$LDSHARED "'-framework $(PYTHONFRAMEWORK)' else ! # No framework, use the Python app as bundle-loader ! BLDSHARED="$LDSHARED "'-bundle_loader $(BUILDPYTHON)' ! LDSHARED="$LDSHARED "'-bundle_loader $(BINDIR)/$(PYTHON)' fi ;; Linux*|GNU*) LDSHARED="gcc -shared";; From mwh@users.sourceforge.net Thu Mar 7 09:59:18 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 01:59:18 -0800 Subject: [Python-checkins] CVS: python/dist/src configure,1.283,1.284 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv16626 Modified Files: configure Log Message: Regenerate. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.283 retrieving revision 1.284 diff -C2 -d -r1.283 -r1.284 *** configure 24 Feb 2002 16:05:04 -0000 1.283 --- configure 7 Mar 2002 09:59:15 -0000 1.284 *************** *** 1,5 **** #! /bin/sh ! # From configure.in Revision: 1.291 # Guess values for system-dependent variables and create Makefiles. --- 1,5 ---- #! /bin/sh ! # From configure.in Revision: 1.292 [...3245 lines suppressed...] if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 7595,7599 **** SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7598: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then --- 7596,7600 ---- SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7599: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then From mwh@users.sourceforge.net Thu Mar 7 10:04:52 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 02:04:52 -0800 Subject: [Python-checkins] CVS: python/dist/src setup.py,1.73.4.1,1.73.4.2 configure.in,1.288.6.1,1.288.6.2 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv18640 Modified Files: Tag: release22-maint setup.py configure.in Log Message: backport my checkin of revision 1.84 of setup.py revision 1.293 of configure.in Apply Jack's patch attached to [ 508779 ] Disable flat namespace on MacOS X I presume you wanted this on the trunk too, Jack? 2.2.1 candidate. Index: setup.py =================================================================== RCS file: /cvsroot/python/python/dist/src/setup.py,v retrieving revision 1.73.4.1 retrieving revision 1.73.4.2 diff -C2 -d -r1.73.4.1 -r1.73.4.2 *** setup.py 1 Mar 2002 08:58:32 -0000 1.73.4.1 --- setup.py 7 Mar 2002 10:04:49 -0000 1.73.4.2 *************** *** 587,591 **** # procedure triggers on. frameworkdir = sysconfig.get_config_var('PYTHONFRAMEWORKDIR') ! exts.append( Extension('gestalt', ['gestaltmodule.c']) ) exts.append( Extension('MacOS', ['macosmodule.c'], extra_link_args=['-framework', 'Carbon']) ) --- 587,592 ---- # procedure triggers on. frameworkdir = sysconfig.get_config_var('PYTHONFRAMEWORKDIR') ! exts.append( Extension('gestalt', ['gestaltmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('MacOS', ['macosmodule.c'], extra_link_args=['-framework', 'Carbon']) ) *************** *** 596,601 **** '../Python/getapplbycreator.c'], extra_link_args=['-framework', 'Carbon']) ) ! exts.append( Extension('_CF', ['cf/_CFmodule.c']) ) ! exts.append( Extension('_Res', ['res/_Resmodule.c']) ) exts.append( Extension('_Snd', ['snd/_Sndmodule.c'], extra_link_args=['-framework', 'Carbon']) ) --- 597,604 ---- '../Python/getapplbycreator.c'], extra_link_args=['-framework', 'Carbon']) ) ! exts.append( Extension('_CF', ['cf/_CFmodule.c'], ! extra_link_args=['-framework', 'CoreFoundation']) ) ! exts.append( Extension('_Res', ['res/_Resmodule.c'], ! extra_link_args=['-framework', 'Carbon']) ) exts.append( Extension('_Snd', ['snd/_Sndmodule.c'], extra_link_args=['-framework', 'Carbon']) ) Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.288.6.1 retrieving revision 1.288.6.2 diff -C2 -d -r1.288.6.1 -r1.288.6.2 *** configure.in 25 Feb 2002 10:55:47 -0000 1.288.6.1 --- configure.in 7 Mar 2002 10:04:49 -0000 1.288.6.2 *************** *** 794,799 **** LDSHARED="$LDSHARED "'-framework $(PYTHONFRAMEWORK)' else ! # No framework. Ignore undefined symbols, assuming they come from Python ! LDSHARED="$LDSHARED -flat_namespace -undefined suppress" fi ;; Linux*) LDSHARED="gcc -shared";; --- 794,800 ---- LDSHARED="$LDSHARED "'-framework $(PYTHONFRAMEWORK)' else ! # No framework, use the Python app as bundle-loader ! BLDSHARED="$LDSHARED "'-bundle_loader $(BUILDPYTHON)' ! LDSHARED="$LDSHARED "'-bundle_loader $(BINDIR)/$(PYTHON)' fi ;; Linux*) LDSHARED="gcc -shared";; From mwh@users.sourceforge.net Thu Mar 7 10:05:12 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 02:05:12 -0800 Subject: [Python-checkins] CVS: python/dist/src configure,1.279.6.1,1.279.6.2 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv18697 Modified Files: Tag: release22-maint configure Log Message: Regenerate. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.279.6.1 retrieving revision 1.279.6.2 diff -C2 -d -r1.279.6.1 -r1.279.6.2 *** configure 25 Feb 2002 10:55:46 -0000 1.279.6.1 --- configure 7 Mar 2002 10:05:09 -0000 1.279.6.2 *************** *** 1,5 **** #! /bin/sh ! # From configure.in Revision: 1.288 # Guess values for system-dependent variables and create Makefiles. --- 1,5 ---- #! /bin/sh ! # From configure.in Revision: 1.288.6.2 [...3212 lines suppressed...] if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 7544,7548 **** SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7547: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then --- 7545,7549 ---- SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7548: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then From mwh@users.sourceforge.net Thu Mar 7 10:09:51 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 02:09:51 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_structseq.py,1.2,1.2.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv20209 Modified Files: Tag: release22-maint test_structseq.py Log Message: backport my checkin of revision 1.3 of test_structseq.py Test for [ 526039 ] devious code can crash structseqs Bugfix candidate. I haven't actually fixed this on the branch yet. Will soon. Index: test_structseq.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_structseq.py,v retrieving revision 1.2 retrieving revision 1.2.8.1 diff -C2 -d -r1.2 -r1.2.8.1 *** test_structseq.py 31 Oct 2001 03:46:14 -0000 1.2 --- test_structseq.py 7 Mar 2002 10:09:48 -0000 1.2.8.1 *************** *** 14,16 **** --- 14,28 ---- vereq(t[i:j], astuple[i:j]) + # Devious code could crash structseqs' contructors + class C: + def __getitem__(self, i): + raise IndexError + def __len__(self): + return 9 + + try: + repr(time.struct_time(C())) + except: + pass + # XXX more needed From mwh@users.sourceforge.net Thu Mar 7 10:12:14 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 02:12:14 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib os.py,1.50,1.50.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv21104 Modified Files: Tag: release22-maint os.py Log Message: backport my checkin of revision 1.52 of os.py revision 1.52 date: 2002/03/06 17:11:17; author: mwh; state: Exp; lines: +20 -0 Special support for pickling os.stat and os.stat_vfs results portably (the types come from different modules on different platforms). Added tests for pickling these types. May be a bugfix candidate. Index: os.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/os.py,v retrieving revision 1.50 retrieving revision 1.50.8.1 diff -C2 -d -r1.50 -r1.50.8.1 *** os.py 30 Oct 2001 05:56:40 -0000 1.50 --- os.py 7 Mar 2002 10:12:11 -0000 1.50.8.1 *************** *** 592,593 **** --- 592,613 ---- return stdin, stdout __all__.append("popen4") + + import copy_reg as _copy_reg + + def _make_stat_result(tup, dict): + return stat_result(tup, dict) + + def _pickle_stat_result(sr): + (type, args) = sr.__reduce__() + return (_make_stat_result, args) + + _copy_reg.pickle(stat_result, _pickle_stat_result,_make_stat_result) + + def _make_statvfs_result(tup, dict): + return statvfs_result(tup, dict) + + def _pickle_statvfs_result(sr): + (type, args) = sr.__reduce__() + return (_make_statvfs_result, args) + + _copy_reg.pickle(statvfs_result, _pickle_statvfs_result,_make_statvfs_result) From mwh@users.sourceforge.net Thu Mar 7 10:12:40 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 02:12:40 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test pickletester.py,1.12.4.1,1.12.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv21239 Modified Files: Tag: release22-maint pickletester.py Log Message: backport my checkin of revision 1.14 of pickletester.py Special support for pickling os.stat and os.stat_vfs results portably (the types come from different modules on different platforms). Added tests for pickling these types. May be a bugfix candidate. Index: pickletester.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/pickletester.py,v retrieving revision 1.12.4.1 retrieving revision 1.12.4.2 diff -C2 -d -r1.12.4.1 -r1.12.4.2 *** pickletester.py 5 Mar 2002 14:01:28 -0000 1.12.4.1 --- pickletester.py 7 Mar 2002 10:12:38 -0000 1.12.4.2 *************** *** 255,258 **** --- 255,269 ---- u = self.loads(s) self.assertEqual(t, u) + import os + if hasattr(os, "stat"): + t = os.stat(os.curdir) + s = self.dumps(t) + u = self.loads(s) + self.assertEqual(t, u) + if hasattr(os, "statvfs"): + t = os.statvfs(os.curdir) + s = self.dumps(t) + u = self.loads(s) + self.assertEqual(t, u) class AbstractPickleModuleTests(unittest.TestCase): From mwh@users.sourceforge.net Thu Mar 7 10:16:45 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 02:16:45 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects structseq.c,1.3.6.1,1.3.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv22453 Modified Files: Tag: release22-maint structseq.c Log Message: After some thinking, I decided to move all of this across onto the branch. I don't think it can break code, so the only risk is introducing new bugs. In that vein, can I ask -checkins readers who have time to carefully look this over, check my refcounts &c? TIA. backport my checkin of revision 1.5 of structseq.c Apply (my) patch: [ 526072 ] pickling os.stat results round II structseq's constructors can now take "invisible" fields in a dict. Gave the constructors better error messages. their __reduce__ method puts these fields in a dict. (this is all in aid of getting os.stat_result's to pickle portably) Also fixes [ 526039 ] devious code can crash structseqs Thought needed about how much of this counts as a bugfix. Certainly #526039 needs to be fixed. Index: structseq.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v retrieving revision 1.3.6.1 retrieving revision 1.3.6.2 diff -C2 -d -r1.3.6.1 -r1.3.6.2 *** structseq.c 5 Mar 2002 14:00:52 -0000 1.3.6.1 --- structseq.c 7 Mar 2002 10:16:43 -0000 1.3.6.2 *************** *** 85,121 **** { PyObject *arg = NULL; PyStructSequence *res = NULL; ! int len, required_len, i; ! static char *kwlist[] = {"sequence", 0}; ! static char msgbuf[128]; ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:structseq", ! kwlist, &arg)) return NULL; ! if (!PySequence_Check(arg)) { ! PyErr_SetString(PyExc_TypeError, ! "constructor requires a sequence"); return NULL; } ! len = PySequence_Length(arg); ! required_len = REAL_SIZE_TP(type); ! if (len != required_len) { ! PyOS_snprintf( ! msgbuf, sizeof(msgbuf), ! "constructor takes exactly %d arguments (%d given)", ! required_len, ! len); ! PyErr_SetString(PyExc_TypeError, msgbuf); return NULL; } res = (PyStructSequence*) PyStructSequence_New(type); for (i = 0; i < len; ++i) { ! /* INCREF???? XXXX */ ! res->ob_item[i] = PySequence_GetItem(arg, i); } return (PyObject*) res; } --- 85,161 ---- { PyObject *arg = NULL; + PyObject *dict = NULL; + PyObject *ob; PyStructSequence *res = NULL; ! int len, min_len, max_len, i; ! static char *kwlist[] = {"sequence", "dict", 0}; ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq", ! kwlist, &arg, &dict)) return NULL; ! arg = PySequence_Fast(arg, "constructor requires a sequence"); ! ! if (!arg) { return NULL; } ! if (dict && !PyDict_Check(dict)) { ! PyErr_Format(PyExc_TypeError, ! "%.500s() takes a dict as second arg, if any", ! type->tp_name); ! Py_DECREF(arg); return NULL; } + len = PySequence_Fast_GET_SIZE(arg); + min_len = VISIBLE_SIZE_TP(type); + max_len = REAL_SIZE_TP(type); + + if (min_len != max_len) { + if (len < min_len) { + PyErr_Format(PyExc_TypeError, + "%.500s() takes an at least %d-sequence (%d-sequence given)", + type->tp_name, min_len, len); + Py_DECREF(arg); + return NULL; + } + + if (len > max_len) { + PyErr_Format(PyExc_TypeError, + "%.500s() takes an at most %d-sequence (%d-sequence given)", + type->tp_name, max_len, len); + Py_DECREF(arg); + return NULL; + } + } + else { + if (len != min_len) { + PyErr_Format(PyExc_TypeError, + "%.500s() takes a %d-sequence (%d-sequence given)", + type->tp_name, min_len, len); + Py_DECREF(arg); + return NULL; + } + } + res = (PyStructSequence*) PyStructSequence_New(type); for (i = 0; i < len; ++i) { ! PyObject *v = PySequence_Fast_GET_ITEM(arg, i); ! Py_INCREF(v); ! res->ob_item[i] = v; ! } ! for (; i < max_len; ++i) { ! if (dict && (ob = PyDict_GetItemString( ! dict, type->tp_members[i].name))) { ! } ! else { ! ob = Py_None; ! } ! Py_INCREF(ob); ! res->ob_item[i] = ob; } + Py_DECREF(arg); return (PyObject*) res; } *************** *** 193,211 **** { PyObject* tup; ! long n_fields; int i; n_fields = REAL_SIZE(self); ! tup = PyTuple_New(n_fields); if (!tup) { return NULL; } ! for (i = 0; i < n_fields; i++) { Py_INCREF(self->ob_item[i]); PyTuple_SET_ITEM(tup, i, self->ob_item[i]); } ! return Py_BuildValue("(O(O))", self->ob_type, tup); } --- 233,264 ---- { PyObject* tup; ! PyObject* dict; ! long n_fields, n_visible_fields; int i; n_fields = REAL_SIZE(self); ! n_visible_fields = VISIBLE_SIZE(self); ! tup = PyTuple_New(n_visible_fields); if (!tup) { return NULL; } ! dict = PyDict_New(); ! if (!dict) { ! Py_DECREF(tup); ! return NULL; ! } ! ! for (i = 0; i < n_visible_fields; i++) { Py_INCREF(self->ob_item[i]); PyTuple_SET_ITEM(tup, i, self->ob_item[i]); } ! for (; i < n_fields; i++) { ! PyDict_SetItemString(dict, self->ob_type->tp_members[i].name, ! self->ob_item[i]); ! } ! ! return Py_BuildValue("(O(OO))", self->ob_type, tup, dict); } From lemburg@users.sourceforge.net Thu Mar 7 11:14:28 2002 From: lemburg@users.sourceforge.net (M.-A. Lemburg) Date: Thu, 07 Mar 2002 03:14:28 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0263.txt,1.9,1.10 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv3542 Modified Files: pep-0263.txt Log Message: Clarified the class of possible source code encodings. Added link to Martin's patch. Index: pep-0263.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0263.txt,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** pep-0263.txt 1 Mar 2002 19:07:46 -0000 1.9 --- pep-0263.txt 7 Mar 2002 11:14:26 -0000 1.10 *************** *** 77,85 **** source code. ! Only ASCII compatible encodings are allowed as source code ! encoding to assure that Python language elements other than ! literals and comments remain readable by ASCII processing tools ! and to avoid problems with wide characters encodings such as ! UTF-16. 2. Handling of escape sequences should continue to work as it does --- 77,87 ---- source code. ! Any encoding which allows processing the first two lines in ! the way indicated above is allowed as source code encoding, ! this includes ASCII compatible encodings as well as certain ! multi-byte encodings such as Shift_JIS. It does not include ! encodings which use two or more bytes for all characters ! like e.g. UTF-16. The reason for this is to keep the encoding ! detection algorithm in the tokenizer simple. 2. Handling of escape sequences should continue to work as it does *************** *** 139,142 **** --- 141,147 ---- for encoding detection as decsribed above. + Martin v. Loewis is working on a patch which implements phase 1. + See [1] for details. + Scope *************** *** 145,150 **** --- 150,161 ---- robust and portable definition. + References + + [1] Phase 1 implementation: + http://sourceforge.net/tracker/?func=detail&atid=305470&aid=526840&group_id=5470 + History + 1.10 and above: see CVS history 1.8: Added '.' to the coding RE. 1.7: Added warnings to phase 1 implementation. Replaced the From neal@metaslash.com Thu Mar 7 12:59:07 2002 From: neal@metaslash.com (Neal Norwitz) Date: Thu, 07 Mar 2002 07:59:07 -0500 Subject: [Python-checkins] CVS: python/dist/src/Objects structseq.c,1.3.6.1,1.3.6.2 References: Message-ID: <3C87641B.30450C0@metaslash.com> Do you need to do: Py_XDECREF(dict); in all the places you Py_DECREF(arg)? Neal -- Michael Hudson wrote: > > Update of /cvsroot/python/python/dist/src/Objects > In directory usw-pr-cvs1:/tmp/cvs-serv22453 > > Modified Files: > Tag: release22-maint > structseq.c > Log Message: > After some thinking, I decided to move all of this across onto > the branch. I don't think it can break code, so the only risk > is introducing new bugs. In that vein, can I ask -checkins readers > who have time to carefully look this over, check my refcounts &c? > TIA. > > backport my checkin of > revision 1.5 of structseq.c > > Apply (my) patch: > > [ 526072 ] pickling os.stat results round II > > structseq's constructors can now take "invisible" fields in a dict. > Gave the constructors better error messages. > their __reduce__ method puts these fields in a dict. > > (this is all in aid of getting os.stat_result's to pickle portably) > > Also fixes > > [ 526039 ] devious code can crash structseqs > > Thought needed about how much of this counts as a bugfix. Certainly > #526039 needs to be fixed. > > Index: structseq.c > =================================================================== > RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v > retrieving revision 1.3.6.1 > retrieving revision 1.3.6.2 > diff -C2 -d -r1.3.6.1 -r1.3.6.2 > *** structseq.c 5 Mar 2002 14:00:52 -0000 1.3.6.1 > --- structseq.c 7 Mar 2002 10:16:43 -0000 1.3.6.2 > *************** > *** 85,121 **** > { > PyObject *arg = NULL; > PyStructSequence *res = NULL; > ! int len, required_len, i; > ! static char *kwlist[] = {"sequence", 0}; > ! static char msgbuf[128]; > > ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:structseq", > ! kwlist, &arg)) > return NULL; > > ! if (!PySequence_Check(arg)) { > ! PyErr_SetString(PyExc_TypeError, > ! "constructor requires a sequence"); > return NULL; > } > > ! len = PySequence_Length(arg); > ! required_len = REAL_SIZE_TP(type); > ! if (len != required_len) { > ! PyOS_snprintf( > ! msgbuf, sizeof(msgbuf), > ! "constructor takes exactly %d arguments (%d given)", > ! required_len, > ! len); > ! PyErr_SetString(PyExc_TypeError, msgbuf); > return NULL; > } > > res = (PyStructSequence*) PyStructSequence_New(type); > for (i = 0; i < len; ++i) { > ! /* INCREF???? XXXX */ > ! res->ob_item[i] = PySequence_GetItem(arg, i); > } > > return (PyObject*) res; > } > --- 85,161 ---- > { > PyObject *arg = NULL; > + PyObject *dict = NULL; > + PyObject *ob; > PyStructSequence *res = NULL; > ! int len, min_len, max_len, i; > ! static char *kwlist[] = {"sequence", "dict", 0}; > > ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq", > ! kwlist, &arg, &dict)) > return NULL; > > ! arg = PySequence_Fast(arg, "constructor requires a sequence"); > ! > ! if (!arg) { > return NULL; > } > > ! if (dict && !PyDict_Check(dict)) { > ! PyErr_Format(PyExc_TypeError, > ! "%.500s() takes a dict as second arg, if any", > ! type->tp_name); > ! Py_DECREF(arg); > return NULL; > } > > + len = PySequence_Fast_GET_SIZE(arg); > + min_len = VISIBLE_SIZE_TP(type); > + max_len = REAL_SIZE_TP(type); > + > + if (min_len != max_len) { > + if (len < min_len) { > + PyErr_Format(PyExc_TypeError, > + "%.500s() takes an at least %d-sequence (%d-sequence given)", > + type->tp_name, min_len, len); > + Py_DECREF(arg); > + return NULL; > + } > + > + if (len > max_len) { > + PyErr_Format(PyExc_TypeError, > + "%.500s() takes an at most %d-sequence (%d-sequence given)", > + type->tp_name, max_len, len); > + Py_DECREF(arg); > + return NULL; > + } > + } > + else { > + if (len != min_len) { > + PyErr_Format(PyExc_TypeError, > + "%.500s() takes a %d-sequence (%d-sequence given)", > + type->tp_name, min_len, len); > + Py_DECREF(arg); > + return NULL; > + } > + } > + > res = (PyStructSequence*) PyStructSequence_New(type); > for (i = 0; i < len; ++i) { > ! PyObject *v = PySequence_Fast_GET_ITEM(arg, i); > ! Py_INCREF(v); > ! res->ob_item[i] = v; > ! } > ! for (; i < max_len; ++i) { > ! if (dict && (ob = PyDict_GetItemString( > ! dict, type->tp_members[i].name))) { > ! } > ! else { > ! ob = Py_None; > ! } > ! Py_INCREF(ob); > ! res->ob_item[i] = ob; > } > > + Py_DECREF(arg); > return (PyObject*) res; > } From mwh@users.sourceforge.net Thu Mar 7 15:13:43 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 07:13:43 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects structseq.c,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv3270 Modified Files: structseq.c Log Message: Guido pointed out that I was missing a couple decrefs. Index: structseq.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** structseq.c 6 Mar 2002 17:07:49 -0000 1.5 --- structseq.c 7 Mar 2002 15:13:40 -0000 1.6 *************** *** 234,237 **** --- 234,238 ---- PyObject* tup; PyObject* dict; + PyObject* result; long n_fields, n_visible_fields; int i; *************** *** 260,264 **** } ! return Py_BuildValue("(O(OO))", self->ob_type, tup, dict); } --- 261,270 ---- } ! result = Py_BuildValue("(O(OO))", self->ob_type, tup, dict); ! ! Py_DECREF(tup); ! Py_DECREF(dict); ! ! return result; } From mwh@users.sourceforge.net Thu Mar 7 15:16:09 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Thu, 07 Mar 2002 07:16:09 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects structseq.c,1.3.6.2,1.3.6.3 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv4235 Modified Files: Tag: release22-maint structseq.c Log Message: backport my checkin of revision 1.6 of structseq.c Guido pointed out that I was missing a couple decrefs. Index: structseq.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v retrieving revision 1.3.6.2 retrieving revision 1.3.6.3 diff -C2 -d -r1.3.6.2 -r1.3.6.3 *** structseq.c 7 Mar 2002 10:16:43 -0000 1.3.6.2 --- structseq.c 7 Mar 2002 15:16:07 -0000 1.3.6.3 *************** *** 234,237 **** --- 234,238 ---- PyObject* tup; PyObject* dict; + PyObject* result; long n_fields, n_visible_fields; int i; *************** *** 260,264 **** } ! return Py_BuildValue("(O(OO))", self->ob_type, tup, dict); } --- 261,270 ---- } ! result = Py_BuildValue("(O(OO))", self->ob_type, tup, dict); ! ! Py_DECREF(tup); ! Py_DECREF(dict); ! ! return result; } From nascheme@users.sourceforge.net Thu Mar 7 18:56:35 2002 From: nascheme@users.sourceforge.net (Neil Schemenauer) Date: Thu, 07 Mar 2002 10:56:35 -0800 Subject: [Python-checkins] CVS: python/nondist/sf-html index.html,1.12,1.13 Message-ID: Update of /cvsroot/python/python/nondist/sf-html In directory usw-pr-cvs1:/tmp/cvs-serv16606 Modified Files: index.html Log Message: Add link to AMK's "Becoming a Python Developer" article. Index: index.html =================================================================== RCS file: /cvsroot/python/python/nondist/sf-html/index.html,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** index.html 22 Apr 2001 06:22:21 -0000 1.12 --- index.html 7 Mar 2002 18:56:32 -0000 1.13 *************** *** 59,62 **** --- 59,69 ----
  • + Becoming a + Python Developer + - Recommended reading for aspiring Python developers (written by Andrew + Kuchling). +
  • + +
  • python-dev Summaries - Summaries of discussion on the developers' mailing list From bwarsaw@users.sourceforge.net Thu Mar 7 19:20:48 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Thu, 07 Mar 2002 11:20:48 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0010.txt,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv24229 Added Files: pep-0010.txt Log Message: PEP 10, Voting Guidelines, Barry Warsaw --- NEW FILE: pep-0010.txt --- PEP: 10 Title: Voting Guidelines Version: $Revision: 1.1 $ Last-Modified: $Date: 2002/03/07 19:20:45 $ Author: barry@zope.com (Barry A. Warsaw) Status: Active Type: Informational Created: 07-Mar-2002 Post-History: Abstract This PEP outlines the python-dev voting guidelines. These guidelines serve to provide feedback or gauge the "wind direction" on a particular proposal, idea, or feature. They don't have a binding force. Rationale When a new idea, feature, patch, etc. is floated in the Python community, either through a PEP or on the mailing lists (most likely on python-dev [1]), it is sometimes helpful to gauge the community's general sentiment. Sometimes people just want to register their opinion of an idea. Sometimes the BDFL wants to take a straw poll. Whatever the reason, these guidelines have been adopted so as to provide a common language for developers. While opinions are (sometimes) useful, but they are never binding. Opinions that are accompanied by rationales are always valued higher than bare scores (this is especially true with -1 votes). Voting Scores The scoring guidelines are loosely derived from the Apache voting procedure [2], with of course our own spin on things. There are 4 possible vote scores: +1 I like it +0 I don't care, but go ahead -0 I don't care, so why bother? -1 I hate it You may occasionally see wild flashes of enthusiasm (either for or against) with vote scores like +2, +1000, or -1000. These aren't really valued much beyond the above scores, but it's nice to see people get excited about such geeky stuff. References [1] Becoming a Python Developer, Andrew Kuchling http://www.amk.ca/python/writing/python-dev.html [2] Apache Project Guidelines and Voting Rules http://httpd.apache.org/dev/guidelines.html Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil fill-column: 70 End: From bwarsaw@users.sourceforge.net Thu Mar 7 19:21:13 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Thu, 07 Mar 2002 11:21:13 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.161,1.162 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv24418 Modified Files: pep-0000.txt Log Message: Added PEP 10, Voting Guidelines, Barry Warsaw Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.161 retrieving revision 1.162 diff -C2 -d -r1.161 -r1.162 *** pep-0000.txt 6 Mar 2002 20:48:22 -0000 1.161 --- pep-0000.txt 7 Mar 2002 19:21:11 -0000 1.162 *************** *** 34,37 **** --- 34,38 ---- I 8 Style Guide for Python Code van Rossum, Warsaw I 9 Sample PEP Template Warsaw + I 10 Voting Guidelines Warsaw Other Informational PEPs *************** *** 160,163 **** --- 161,165 ---- I 8 Style Guide for Python Code van Rossum, Warsaw I 9 Sample PEP Template Warsaw + I 10 Voting Guidelines Warsaw I 42 Small Feature Requests Hylton From bwarsaw@users.sourceforge.net Thu Mar 7 19:26:09 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Thu, 07 Mar 2002 11:26:09 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0010.txt,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv26274 Modified Files: pep-0010.txt Log Message: I'm agonna post it today. Index: pep-0010.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0010.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pep-0010.txt 7 Mar 2002 19:20:45 -0000 1.1 --- pep-0010.txt 7 Mar 2002 19:26:07 -0000 1.2 *************** *** 7,11 **** Type: Informational Created: 07-Mar-2002 ! Post-History: --- 7,11 ---- Type: Informational Created: 07-Mar-2002 ! Post-History: 07-Mar-2002 From bwarsaw@users.sourceforge.net Thu Mar 7 20:02:11 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Thu, 07 Mar 2002 12:02:11 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.162,1.163 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv6148 Modified Files: pep-0000.txt Log Message: Don't mention a specific Python version. Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.162 retrieving revision 1.163 diff -C2 -d -r1.162 -r1.163 *** pep-0000.txt 7 Mar 2002 19:21:11 -0000 1.162 --- pep-0000.txt 7 Mar 2002 20:02:09 -0000 1.163 *************** *** 45,54 **** I 272 API for Secret-Key Encryption Algorithms Kuchling ! Accepted PEPs (accepted for Python 2.2; may not be implemented yet) S 252 Making Types Look More Like Classes van Rossum S 253 Subtyping Built-in Types van Rossum ! Open PEPs (under consideration for Python 2.3) I 42 Small Feature Requests Hylton --- 45,54 ---- I 272 API for Secret-Key Encryption Algorithms Kuchling ! Accepted PEPs (accepted; may not be implemented yet) S 252 Making Types Look More Like Classes van Rossum S 253 Subtyping Built-in Types van Rossum ! Open PEPs (under consideration) I 42 Small Feature Requests Hylton From montanaro@users.sourceforge.net Thu Mar 7 22:58:04 2002 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Thu, 07 Mar 2002 14:58:04 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib pydoc.py,1.57,1.58 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv30162 Modified Files: pydoc.py Log Message: add repr_str as alias for repr_string in both HTMLRepr and TextRepr classes - reflects the change in type("").__name__ between 2.1 and 2.2. The __name__ field is used to find a method to call for particular types. Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.57 retrieving revision 1.58 diff -C2 -d -r1.57 -r1.58 *** pydoc.py 3 Mar 2002 03:12:30 -0000 1.57 --- pydoc.py 7 Mar 2002 22:58:02 -0000 1.58 *************** *** 312,315 **** --- 312,317 ---- self.escape(testrepr)) + repr_str = repr_string + def repr_instance(self, x, level): try: *************** *** 860,863 **** --- 862,867 ---- return 'r' + testrepr[0] + test + testrepr[0] return testrepr + + repr_str = repr_string def repr_instance(self, x, level): From fdrake@users.sourceforge.net Fri Mar 8 00:54:45 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 07 Mar 2002 16:54:45 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.158,1.159 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv26132/tut Modified Files: tut.tex Log Message: "Shortcut" should be "short-circuit". This closes SF bug #526277. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.158 retrieving revision 1.159 diff -C2 -d -r1.158 -r1.159 *** tut.tex 29 Jan 2002 14:53:30 -0000 1.158 --- tut.tex 8 Mar 2002 00:54:43 -0000 1.159 *************** *** 2040,2049 **** The Boolean operators \code{and} and \code{or} are so-called ! \emph{shortcut} operators: their arguments are evaluated from left to ! right, and evaluation stops as soon as the outcome is determined. ! E.g., if \code{A} and \code{C} are true but \code{B} is false, \code{A ! and B and C} does not evaluate the expression C. In general, the ! return value of a shortcut operator, when used as a general value and ! not as a Boolean, is the last evaluated argument. It is possible to assign the result of a comparison or other Boolean --- 2040,2050 ---- The Boolean operators \code{and} and \code{or} are so-called ! \emph{short-circuit} operators: their arguments are evaluated from ! left to right, and evaluation stops as soon as the outcome is ! determined. For example, if \code{A} and \code{C} are true but ! \code{B} is false, \code{A and B and C} does not evaluate the ! expression \code{C}. In general, the return value of a short-circuit ! operator, when used as a general value and not as a Boolean, is the ! last evaluated argument. It is possible to assign the result of a comparison or other Boolean From fdrake@users.sourceforge.net Fri Mar 8 01:01:26 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 07 Mar 2002 17:01:26 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.156.4.1.2.1,1.156.4.1.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv27547/tut Modified Files: Tag: release22-maint tut.tex Log Message: "Shortcut" should be "short-circuit". This closes SF bug #526277. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.156.4.1.2.1 retrieving revision 1.156.4.1.2.2 diff -C2 -d -r1.156.4.1.2.1 -r1.156.4.1.2.2 *** tut.tex 29 Jan 2002 14:54:18 -0000 1.156.4.1.2.1 --- tut.tex 8 Mar 2002 01:01:23 -0000 1.156.4.1.2.2 *************** *** 2040,2049 **** The Boolean operators \code{and} and \code{or} are so-called ! \emph{shortcut} operators: their arguments are evaluated from left to ! right, and evaluation stops as soon as the outcome is determined. ! E.g., if \code{A} and \code{C} are true but \code{B} is false, \code{A ! and B and C} does not evaluate the expression C. In general, the ! return value of a shortcut operator, when used as a general value and ! not as a Boolean, is the last evaluated argument. It is possible to assign the result of a comparison or other Boolean --- 2040,2050 ---- The Boolean operators \code{and} and \code{or} are so-called ! \emph{short-circuit} operators: their arguments are evaluated from ! left to right, and evaluation stops as soon as the outcome is ! determined. For example, if \code{A} and \code{C} are true but ! \code{B} is false, \code{A and B and C} does not evaluate the ! expression \code{C}. In general, the return value of a short-circuit ! operator, when used as a general value and not as a Boolean, is the ! last evaluated argument. It is possible to assign the result of a comparison or other Boolean From fdrake@users.sourceforge.net Fri Mar 8 01:01:52 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 07 Mar 2002 17:01:52 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/tut tut.tex,1.133.2.5,1.133.2.6 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory usw-pr-cvs1:/tmp/cvs-serv27668/tut Modified Files: Tag: release21-maint tut.tex Log Message: "Shortcut" should be "short-circuit". This closes SF bug #526277. Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.133.2.5 retrieving revision 1.133.2.6 diff -C2 -d -r1.133.2.5 -r1.133.2.6 *** tut.tex 18 Jul 2001 19:21:43 -0000 1.133.2.5 --- tut.tex 8 Mar 2002 01:01:50 -0000 1.133.2.6 *************** *** 2000,2009 **** The Boolean operators \code{and} and \code{or} are so-called ! \emph{shortcut} operators: their arguments are evaluated from left to ! right, and evaluation stops as soon as the outcome is determined. ! E.g., if \code{A} and \code{C} are true but \code{B} is false, \code{A ! and B and C} does not evaluate the expression C. In general, the ! return value of a shortcut operator, when used as a general value and ! not as a Boolean, is the last evaluated argument. It is possible to assign the result of a comparison or other Boolean --- 2000,2010 ---- The Boolean operators \code{and} and \code{or} are so-called ! \emph{short-circuit} operators: their arguments are evaluated from ! left to right, and evaluation stops as soon as the outcome is ! determined. For example, if \code{A} and \code{C} are true but ! \code{B} is false, \code{A and B and C} does not evaluate the ! expression \code{C}. In general, the return value of a short-circuit ! operator, when used as a general value and not as a Boolean, is the ! last evaluated argument. It is possible to assign the result of a comparison or other Boolean From pierslauder@users.sourceforge.net Fri Mar 8 01:53:26 2002 From: pierslauder@users.sourceforge.net (Piers Lauder) Date: Thu, 07 Mar 2002 17:53:26 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libimaplib.tex,1.18,1.19 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv5034/dist/src/Doc/lib Modified Files: libimaplib.tex Log Message: add SSL class submitted by Tino Lange Index: libimaplib.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libimaplib.tex,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** libimaplib.tex 20 Jul 2001 11:04:19 -0000 1.18 --- libimaplib.tex 8 Mar 2002 01:53:24 -0000 1.19 *************** *** 10,23 **** % converted by Fred L. Drake, Jr. . % Revised by ESR, January 2000. \indexii{IMAP4}{protocol} ! This module defines a class, \class{IMAP4}, which encapsulates a ! connection to an IMAP4 server and implements a large subset of the IMAP4rev1 client protocol as defined in \rfc{2060}. It is backward compatible with IMAP4 (\rfc{1730}) servers, but note that the \samp{STATUS} command is not supported in IMAP4. ! A single class is provided by the \module{imaplib} module: \begin{classdesc}{IMAP4}{\optional{host\optional{, port}}} --- 10,25 ---- % converted by Fred L. Drake, Jr. . % Revised by ESR, January 2000. + % Changes for IMAP4_SSL by Tino Lange , March 2002 \indexii{IMAP4}{protocol} + \indexii{IMAP4_SSL}{protocol} ! This module defines two classes, \class{IMAP4} and \class{IMAP4_SSL}, which encapsulate a ! connection to an IMAP4 server and implement a large subset of the IMAP4rev1 client protocol as defined in \rfc{2060}. It is backward compatible with IMAP4 (\rfc{1730}) servers, but note that the \samp{STATUS} command is not supported in IMAP4. ! Two classes are provided by the \module{imaplib} module, \class{IMAP4} is the base class: \begin{classdesc}{IMAP4}{\optional{host\optional{, port}}} *************** *** 49,52 **** --- 51,65 ---- \end{excdesc} + There's also a subclass for secure connections: + + \begin{classdesc}{IMAP4_SSL}{\optional{host\optional{, port\optional{, keyfile\optional{, certfile}}}}} + This is a subclass derived from \class{IMAP4} that connects over an SSL encrypted socket + (to use this class you need a socket module that was compiled with SSL support). + If \var{host} is not specified, \code{''} (the local host) is used. + If \var{port} is omitted, the standard IMAP4-over-SSL port (993) is used. + \var{keyfile} and \var{certfile} are also optional - they can contain a PEM formatted + private key and certificate chain file for the SSL connection. + \end{classdesc} + The following utility functions are defined: *************** *** 309,312 **** --- 322,332 ---- Allow simple extension commands notified by server in \samp{CAPABILITY} response. + \end{methoddesc} + + + Instances of \class{IMAP4_SSL} have just one additional method: + + \begin{methoddesc}{ssl}{} + Returns SSLObject instance used for the secure connection with the server. \end{methoddesc} From pierslauder@users.sourceforge.net Fri Mar 8 01:53:26 2002 From: pierslauder@users.sourceforge.net (Piers Lauder) Date: Thu, 07 Mar 2002 17:53:26 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib imaplib.py,1.43,1.44 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv5034/dist/src/Lib Modified Files: imaplib.py Log Message: add SSL class submitted by Tino Lange Index: imaplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/imaplib.py,v retrieving revision 1.43 retrieving revision 1.44 diff -C2 -d -r1.43 -r1.44 *** imaplib.py 22 Feb 2002 01:15:17 -0000 1.43 --- imaplib.py 8 Mar 2002 01:53:24 -0000 1.44 *************** *** 16,21 **** # String method conversion by ESR, February 2001. # GET/SETACL contributed by Anthony Baxter April 2001. ! __version__ = "2.50" import binascii, re, socket, time, random, sys --- 16,22 ---- # String method conversion by ESR, February 2001. # GET/SETACL contributed by Anthony Baxter April 2001. + # IMAP4_SSL contributed by Tino Lange March 2002. ! __version__ = "2.51" import binascii, re, socket, time, random, sys *************** *** 980,983 **** --- 981,1056 ---- i = 0 n -= 1 + + + + class IMAP4_SSL(IMAP4): + + """IMAP4 client class over SSL connection + + Instantiate with: IMAP4_SSL([, host[, port[, keyfile[, certfile]]]]) + + host - host's name (default: localhost); + port - port number (default: standard IMAP4 SSL port). + keyfile - PEM formatted file that contains your private key (default: None); + certfile - PEM formatted certificate chain file (default: None); + + for more documentation see the docstring of the parent class IMAP4. + """ + + + def __init__(self, host = '', port = IMAP4_SSL_PORT, keyfile = None, certfile = None): + self.keyfile = keyfile + self.certfile = certfile + IMAP4.__init__(self, host, port) + + + def open(self, host, port): + """Setup connection to remote server on "host:port". + This connection will be used by the routines: + read, readline, send, shutdown. + """ + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.connect((self.host, self.port)) + self.sslobj = socket.ssl(self.sock,self.keyfile, self.certfile) + + + def read(self, size): + """Read 'size' bytes from remote.""" + return self.sslobj.read(size) + + + def readline(self): + """Read line from remote.""" + line = "" + while 1: + char = self.sslobj.read(1) + line += char + if char == "\n": return line + + + def send(self, data): + """Send data to remote.""" + self.sslobj.write(data) + + + def shutdown(self): + """Close I/O established in "open".""" + self.sock.close() + + + def socket(self): + """Return socket instance used to connect to IMAP4 server. + + socket = .socket() + """ + return self.sock + + + def ssl(self): + """Return SSLObject instance used to communicate with the IMAP4 server. + + ssl = .socket.ssl() + """ + return self.sslobj From montanaro@users.sourceforge.net Fri Mar 8 02:36:20 2002 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Thu, 07 Mar 2002 18:36:20 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib BaseHTTPServer.py,1.17,1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv13324 Modified Files: BaseHTTPServer.py Log Message: add Content-Type header to error responses this closes patch 502080 Index: BaseHTTPServer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/BaseHTTPServer.py,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** BaseHTTPServer.py 25 Jul 2001 06:12:16 -0000 1.17 --- BaseHTTPServer.py 8 Mar 2002 02:36:18 -0000 1.18 *************** *** 288,291 **** --- 288,292 ---- self.log_error("code %d, message %s", code, message) self.send_response(code, message) + self.send_header("Content-Type", "text/html") self.end_headers() self.wfile.write(self.error_message_format % From fdrake@users.sourceforge.net Fri Mar 8 03:15:52 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 07 Mar 2002 19:15:52 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/mac libscrap.tex,NONE,1.1 toolbox.tex,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/mac In directory usw-pr-cvs1:/tmp/cvs-serv20972 Modified Files: toolbox.tex Added Files: libscrap.tex Log Message: I started writing more documentation on the Scrap module at one point, but it is difficult to do without a Mac box to try things out on. This expands on what was there only a little bit; hopefully someone with a Mac can work on this as well! --- NEW FILE: libscrap.tex --- \section{\module{Carbon.Scrap} --- Scrap Manager} \declaremodule{standard}{Carbon.Scrap} \platform{Mac} \modulesynopsis{The Scrap Manager provides basic services for implementing cut \&\ paste and clipboard operations.} This module is only fully available on MacOS9 and earlier under classic PPC MacPython. Very limited functionality is available under Carbon MacPython. The Scrap\index{Scrap Manager} Manager supports the simplest form of cut \&\ paste operations on the Macintosh. It can be use for both inter- and intra-application clipboard operations. The \module{Scrap} module provides low-level access to the functions of the Scrap Manager. It contains the following functions: \begin{funcdesc}{InfoScrap}{} Return current information about the scrap. The information is encoded as a tuple containing the fields \code{(\var{size}, \var{handle}, \var{count}, \var{state}, \var{path})}. \begin{tableii}{l|l}{var}{Field}{Meaning} \lineii{size}{Size of the scrap in bytes.} \lineii{handle}{Resource object representing the scrap.} \lineii{count}{Serial number of the scrap contents.} \lineii{state}{Integer; positive if in memory, \code{0} if on disk, negative if uninitialized.} \lineii{path}{Filename of the scrap when stored on disk.} \end{tableii} \end{funcdesc} \begin{seealso} \seetitle[http://developer.apple.com/techpubs/mac/MoreToolbox/MoreToolbox-109.html] {Scrap Manager}{Apple's documentation for the Scrap Manager gives a lot of useful information about using the Scrap Manager in applications.} \end{seealso} Index: toolbox.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/mac/toolbox.tex,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** toolbox.tex 17 Jan 2002 04:51:55 -0000 1.5 --- toolbox.tex 8 Mar 2002 03:15:49 -0000 1.6 *************** *** 134,152 **** ! \section{\module{Carbon.Scrap} --- Scrap Manager} ! \declaremodule{standard}{Carbon.Scrap} ! \platform{Mac} ! \modulesynopsis{The Scrap Manager provides basic services for ! implementing cut \&\ paste and clipboard operations.} ! ! This module is only fully available on MacOS9 and earlier under classic PPC ! MacPython. Very limited functionality is available under Carbon MacPython. ! ! \begin{seealso} ! \seetitle[http://developer.apple.com/techpubs/mac/MoreToolbox/MoreToolbox-109.html]{Scrap ! Manager}{Apple's documentation for the Scrap Manager gives ! a lot of useful information about using the Scrap Manager ! in applications.} ! \end{seealso} --- 134,138 ---- ! \input{libscrap} From fdrake@users.sourceforge.net Fri Mar 8 03:18:21 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Thu, 07 Mar 2002 19:18:21 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc Makefile.deps,1.82,1.83 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory usw-pr-cvs1:/tmp/cvs-serv21425 Modified Files: Makefile.deps Log Message: Add entry for mac/libscrap.tex. Index: Makefile.deps =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile.deps,v retrieving revision 1.82 retrieving revision 1.83 diff -C2 -d -r1.82 -r1.83 *** Makefile.deps 24 Jan 2002 16:38:08 -0000 1.82 --- Makefile.deps 8 Mar 2002 03:18:19 -0000 1.83 *************** *** 334,338 **** mac/libmacic.tex \ mac/libframework.tex \ ! mac/libminiae.tex INSTFILES = $(HOWTOSTYLES) inst/inst.tex --- 334,339 ---- mac/libmacic.tex \ mac/libframework.tex \ ! mac/libminiae.tex \ ! mac/libscrap.tex INSTFILES = $(HOWTOSTYLES) inst/inst.tex From bwarsaw@users.sourceforge.net Fri Mar 8 05:43:24 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Thu, 07 Mar 2002 21:43:24 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.163,1.164 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv14134 Modified Files: pep-0000.txt Log Message: Add a link to Guido's Parade of PEPs. Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.163 retrieving revision 1.164 diff -C2 -d -r1.163 -r1.164 *** pep-0000.txt 7 Mar 2002 20:02:09 -0000 1.163 --- pep-0000.txt 8 Mar 2002 05:43:22 -0000 1.164 *************** *** 17,20 **** --- 17,24 ---- texts represent their historical record. + The BDFL maintains his own Pronouncements page[2] at + http://www.python.org/doc/essays/pepparade.html which contains his + musings on the various outstanding PEPs. + Index by Category *************** *** 323,327 **** [1] View PEP history online ! http://cvs.sf.net/cgi-bin/viewcvs.cgi/python/python/nondist/peps/ --- 327,334 ---- [1] View PEP history online ! http://cvs.sf.net/cgi-bin/viewcvs.cgi/python/python/nondist/peps/ ! ! [2] The Benevolent Dictator For Life's Parade of PEPs ! http://www.python.org/doc/essays/pepparade.html From tim_one@users.sourceforge.net Fri Mar 8 05:43:34 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Thu, 07 Mar 2002 21:43:34 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_mmap.py,1.19,1.20 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv13773/python/Lib/test Modified Files: test_mmap.py Log Message: SF bug 515943: searching for data with \0 in mmap. mmap_find_method(): this obtained the string to find via s#, but it ignored its length, acting as if it were \0-terminated instead. Someone please run on Linux too (the extended test_mmap works on Windows). Bugfix candidate. Index: test_mmap.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_mmap.py,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** test_mmap.py 13 Nov 2001 23:39:47 -0000 1.19 --- test_mmap.py 8 Mar 2002 05:43:32 -0000 1.20 *************** *** 245,248 **** --- 245,273 ---- pass + # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2, + # searching for data with embedded \0 bytes didn't work. + f = open(TESTFN, 'w+') + + try: # unlink TESTFN no matter what + data = 'aabaac\x00deef\x00\x00aa\x00' + n = len(data) + f.write(data) + m = mmap.mmap(f.fileno(), n) + f.close() + + for start in range(n+1): + for finish in range(start, n+1): + slice = data[start : finish] + vereq(m.find(slice), data.find(slice)) + vereq(m.find(slice + 'x'), -1) + + finally: + try: + os.unlink(TESTFN) + except OSError: + pass + + + print ' Test passed' From tim_one@users.sourceforge.net Fri Mar 8 05:43:34 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Thu, 07 Mar 2002 21:43:34 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules mmapmodule.c,2.37,2.38 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv13773/python/Modules Modified Files: mmapmodule.c Log Message: SF bug 515943: searching for data with \0 in mmap. mmap_find_method(): this obtained the string to find via s#, but it ignored its length, acting as if it were \0-terminated instead. Someone please run on Linux too (the extended test_mmap works on Windows). Bugfix candidate. Index: mmapmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/mmapmodule.c,v retrieving revision 2.37 retrieving revision 2.38 diff -C2 -d -r2.37 -r2.38 *** mmapmodule.c 17 Jan 2002 23:15:58 -0000 2.37 --- mmapmodule.c 8 Mar 2002 05:43:32 -0000 2.38 *************** *** 252,269 **** else if ((size_t)start > self->size) start = self->size; - p = self->data + start; ! while (p < e) { ! char *s = p; ! char *n = needle; ! while ((sdata)); } - p++; } return Py_BuildValue ("l", (long) -1); --- 252,265 ---- else if ((size_t)start > self->size) start = self->size; ! for (p = self->data + start; p + len <= e; ++p) { ! int i; ! for (i = 0; i < len && needle[i] == p[i]; ++i) ! /* nothing */; ! if (i == len) { return Py_BuildValue ( "l", (long) (p - self->data)); } } return Py_BuildValue ("l", (long) -1); From pierslauder@users.sourceforge.net Fri Mar 8 09:05:14 2002 From: pierslauder@users.sourceforge.net (Piers Lauder) Date: Fri, 08 Mar 2002 01:05:14 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib imaplib.py,1.44,1.45 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv20403/dist/src/Lib Modified Files: imaplib.py Log Message: fixed missing IMAP4_SSL_PORT Index: imaplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/imaplib.py,v retrieving revision 1.44 retrieving revision 1.45 diff -C2 -d -r1.44 -r1.45 *** imaplib.py 8 Mar 2002 01:53:24 -0000 1.44 --- imaplib.py 8 Mar 2002 09:05:12 -0000 1.45 *************** *** 30,33 **** --- 30,34 ---- Debug = 0 IMAP4_PORT = 143 + IMAP4_SSL_PORT = 993 AllowedVersions = ('IMAP4REV1', 'IMAP4') # Most recent first *************** *** 988,992 **** """IMAP4 client class over SSL connection ! Instantiate with: IMAP4_SSL([, host[, port[, keyfile[, certfile]]]]) host - host's name (default: localhost); --- 989,993 ---- """IMAP4 client class over SSL connection ! Instantiate with: IMAP4_SSL([host[, port[, keyfile[, certfile]]]]) host - host's name (default: localhost); From neal@metaslash.com Fri Mar 8 12:55:51 2002 From: neal@metaslash.com (Neal Norwitz) Date: Fri, 08 Mar 2002 07:55:51 -0500 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_mmap.py,1.19,1.20 References: Message-ID: <3C88B4D7.3B6D6CEB@metaslash.com> Tim Peters wrote: > > Update of /cvsroot/python/python/dist/src/Lib/test > In directory usw-pr-cvs1:/tmp/cvs-serv13773/python/Lib/test > > Modified Files: > test_mmap.py > Log Message: > SF bug 515943: searching for data with \0 in mmap. > mmap_find_method(): this obtained the string to find via s#, but it > ignored its length, acting as if it were \0-terminated instead. > > Someone please run on Linux too (the extended test_mmap works on Windows). Works for me: Linux epoch 2.4.7-10 #1 Thu Sep 6 16:46:36 EDT 2001 i686 unknown Red Hat Linux release 7.2 (Enigma) From mwh@users.sourceforge.net Fri Mar 8 13:39:27 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Fri, 08 Mar 2002 05:39:27 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_mmap.py,1.19,1.19.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv25125 Modified Files: Tag: release22-maint test_mmap.py Log Message: backport tim_one's checkin of revision 1.20 of test_mmap.py SF bug 515943: searching for data with \0 in mmap. mmap_find_method(): this obtained the string to find via s#, but it ignored its length, acting as if it were \0-terminated instead. Someone please run on Linux too (the extended test_mmap works on Windows). Bugfix candidate. Index: test_mmap.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_mmap.py,v retrieving revision 1.19 retrieving revision 1.19.8.1 diff -C2 -d -r1.19 -r1.19.8.1 *** test_mmap.py 13 Nov 2001 23:39:47 -0000 1.19 --- test_mmap.py 8 Mar 2002 13:39:25 -0000 1.19.8.1 *************** *** 245,248 **** --- 245,273 ---- pass + # Do a tougher .find() test. SF bug 515943 pointed out that, in 2.2, + # searching for data with embedded \0 bytes didn't work. + f = open(TESTFN, 'w+') + + try: # unlink TESTFN no matter what + data = 'aabaac\x00deef\x00\x00aa\x00' + n = len(data) + f.write(data) + m = mmap.mmap(f.fileno(), n) + f.close() + + for start in range(n+1): + for finish in range(start, n+1): + slice = data[start : finish] + vereq(m.find(slice), data.find(slice)) + vereq(m.find(slice + 'x'), -1) + + finally: + try: + os.unlink(TESTFN) + except OSError: + pass + + + print ' Test passed' From mwh@users.sourceforge.net Fri Mar 8 13:40:09 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Fri, 08 Mar 2002 05:40:09 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules mmapmodule.c,2.35.6.1,2.35.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv25367 Modified Files: Tag: release22-maint mmapmodule.c Log Message: backport tim_one's checkin of revision 2.38 of mmapmodule.c SF bug 515943: searching for data with \0 in mmap. mmap_find_method(): this obtained the string to find via s#, but it ignored its length, acting as if it were \0-terminated instead. Someone please run on Linux too (the extended test_mmap works on Windows). Bugfix candidate. Index: mmapmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/mmapmodule.c,v retrieving revision 2.35.6.1 retrieving revision 2.35.6.2 diff -C2 -d -r2.35.6.1 -r2.35.6.2 *** mmapmodule.c 12 Jan 2002 11:13:23 -0000 2.35.6.1 --- mmapmodule.c 8 Mar 2002 13:40:07 -0000 2.35.6.2 *************** *** 252,269 **** else if ((size_t)start > self->size) start = self->size; - p = self->data + start; ! while (p < e) { ! char *s = p; ! char *n = needle; ! while ((sdata)); } - p++; } return Py_BuildValue ("l", (long) -1); --- 252,265 ---- else if ((size_t)start > self->size) start = self->size; ! for (p = self->data + start; p + len <= e; ++p) { ! int i; ! for (i = 0; i < len && needle[i] == p[i]; ++i) ! /* nothing */; ! if (i == len) { return Py_BuildValue ( "l", (long) (p - self->data)); } } return Py_BuildValue ("l", (long) -1); From mwh@users.sourceforge.net Fri Mar 8 13:40:48 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Fri, 08 Mar 2002 05:40:48 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib pydoc.py,1.56,1.56.8.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv25524 Modified Files: Tag: release22-maint pydoc.py Log Message: backport montanaro's checkin of revision 1.58 of pydoc.py add repr_str as alias for repr_string in both HTMLRepr and TextRepr classes - reflects the change in type("").__name__ between 2.1 and 2.2. The __name__ field is used to find a method to call for particular types. Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.56 retrieving revision 1.56.8.1 diff -C2 -d -r1.56 -r1.56.8.1 *** pydoc.py 31 Oct 2001 04:20:26 -0000 1.56 --- pydoc.py 8 Mar 2002 13:40:46 -0000 1.56.8.1 *************** *** 312,315 **** --- 312,317 ---- self.escape(testrepr)) + repr_str = repr_string + def repr_instance(self, x, level): try: *************** *** 860,863 **** --- 862,867 ---- return 'r' + testrepr[0] + test + testrepr[0] return testrepr + + repr_str = repr_string def repr_instance(self, x, level): From mwh@users.sourceforge.net Fri Mar 8 13:41:11 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Fri, 08 Mar 2002 05:41:11 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib BaseHTTPServer.py,1.17,1.17.16.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv25646 Modified Files: Tag: release22-maint BaseHTTPServer.py Log Message: backport montanaro's checkin of revision 1.18 of BaseHTTPServer.py add Content-Type header to error responses this closes patch 502080 Index: BaseHTTPServer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/BaseHTTPServer.py,v retrieving revision 1.17 retrieving revision 1.17.16.1 diff -C2 -d -r1.17 -r1.17.16.1 *** BaseHTTPServer.py 25 Jul 2001 06:12:16 -0000 1.17 --- BaseHTTPServer.py 8 Mar 2002 13:41:09 -0000 1.17.16.1 *************** *** 288,291 **** --- 288,292 ---- self.log_error("code %d, message %s", code, message) self.send_response(code, message) + self.send_header("Content-Type", "text/html") self.end_headers() self.wfile.write(self.error_message_format % From jackjansen@users.sourceforge.net Fri Mar 8 13:43:04 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Fri, 08 Mar 2002 05:43:04 -0800 Subject: [Python-checkins] CVS: python/dist/src configure.in,1.293,1.294 configure,1.284,1.285 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv26013 Modified Files: configure.in configure Log Message: When testing for availability of pthreads without special compiler options or libraries also look for thread_detach. SGI has thread_create in libc but complete pthread support only in -lpthread. Fixes #522393. 2.2.1 candidate.Killed by signal 2. Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.293 retrieving revision 1.294 diff -C2 -d -r1.293 -r1.294 *** configure.in 7 Mar 2002 09:58:56 -0000 1.293 --- configure.in 8 Mar 2002 13:43:01 -0000 1.294 *************** *** 466,469 **** --- 466,470 ---- if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; + (void)pthread_detach(p); return 0; } *************** *** 498,501 **** --- 499,503 ---- if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; + (void)pthread_detach(p); return 0; } Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.284 retrieving revision 1.285 diff -C2 -d -r1.284 -r1.285 *** configure 7 Mar 2002 09:59:15 -0000 1.284 --- configure 8 Mar 2002 13:43:01 -0000 1.285 *************** *** 1,5 **** #! /bin/sh ! # From configure.in Revision: 1.292 # Guess values for system-dependent variables and create Makefiles. --- 1,5 ---- #! /bin/sh ! # From configure.in Revision: 1.293 [...4383 lines suppressed...] if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 7596,7600 **** SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7599: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then --- 7598,7602 ---- SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7601: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then From mwh@users.sourceforge.net Fri Mar 8 14:11:20 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Fri, 08 Mar 2002 06:11:20 -0800 Subject: [Python-checkins] CVS: python/dist/src configure.in,1.288.6.2,1.288.6.3 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv3255 Modified Files: Tag: release22-maint configure.in Log Message: backport jackjansen's checkin of revision 1.294 of configure.in revision 1.285 of configure When testing for availability of pthreads without special compiler options or libraries also look for thread_detach. SGI has thread_create in libc but complete pthread support only in -lpthread. Fixes #522393. 2.2.1 candidate.Killed by signal 2. Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.288.6.2 retrieving revision 1.288.6.3 diff -C2 -d -r1.288.6.2 -r1.288.6.3 *** configure.in 7 Mar 2002 10:04:49 -0000 1.288.6.2 --- configure.in 8 Mar 2002 14:11:18 -0000 1.288.6.3 *************** *** 466,469 **** --- 466,470 ---- if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; + (void)pthread_detach(p); return 0; } *************** *** 498,501 **** --- 499,503 ---- if(pthread_create(&p,NULL,routine,NULL)!=0) return 1; + (void)pthread_detach(p); return 0; } From mwh@users.sourceforge.net Fri Mar 8 14:11:39 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Fri, 08 Mar 2002 06:11:39 -0800 Subject: [Python-checkins] CVS: python/dist/src configure,1.279.6.2,1.279.6.3 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv3351 Modified Files: Tag: release22-maint configure Log Message: backport jackjansen's checkin of revision 1.294 of configure.in revision 1.285 of configure When testing for availability of pthreads without special compiler options or libraries also look for thread_detach. SGI has thread_create in libc but complete pthread support only in -lpthread. Fixes #522393. 2.2.1 candidate.Killed by signal 2. Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.279.6.2 retrieving revision 1.279.6.3 diff -C2 -d -r1.279.6.2 -r1.279.6.3 *** configure 7 Mar 2002 10:05:09 -0000 1.279.6.2 --- configure 8 Mar 2002 14:11:35 -0000 1.279.6.3 *************** *** 1,5 **** #! /bin/sh ! # From configure.in Revision: 1.288.6.2 # Guess values for system-dependent variables and create Makefiles. --- 1,5 ---- #! /bin/sh ! # From configure.in Revision: 1.288.6.3 [...4350 lines suppressed...] if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < *************** *** 7545,7549 **** SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7548: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then --- 7547,7551 ---- SRCDIRS="Parser Grammar Objects Python Modules" echo $ac_n "checking for build directories""... $ac_c" 1>&6 ! echo "configure:7550: checking for build directories" >&5 for dir in $SRCDIRS; do if test ! -d $dir; then From gvanrossum@users.sourceforge.net Fri Mar 8 15:38:39 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 08 Mar 2002 07:38:39 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0285.txt,NONE,1.1 pep-0000.txt,1.164,1.165 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv29072 Modified Files: pep-0000.txt Added Files: pep-0285.txt Log Message: PEP 285: Adding a bool type --- NEW FILE: pep-0285.txt --- PEP: 285 Title: Adding a bool type Version: $Revision: 1.1 $ Last-Modified: $Date: 2002/03/08 15:38:37 $ Author: guido@python.org (Guido van Rossum) Status: Draft Type: Standards Track Created: 8-Mar-2002 Python-Version: 2.3 Post-History: 8-Mar-2002 (python-dev) Abstract This PEP proposes the introduction of a new built-in type, bool, with two constants, False and True. The bool type would be a straightforward subtype (in C) of the int type, and the values False and True would behave like 0 and 1 in most respects (e.g. False==0 and True==1 would be true) except repr() and str(). All built-in operations that conceptually return a Boolean result will be changed to return False or True instead of 0 or 1; for example, comparisons and the "not" operator. Rationale Most languages eventually grow a Boolean type; even C99 has one. It's useful to be able to tell from a function result that the outcome has Boolean semantics. Specification The following Python code specifies most of the properties of the new type: class bool(int): def __new__(cls, val=0, _create=0): if _create: # This is nor part of the spec, # just a hack to bootstrap False and True return int.__new__(cls, not not val) elif val: return True else: return False def __repr__(self): if self: return "True" else: return "False" __str__ = __repr__ def __and__(self, other): if isinstance(other, bool): return bool(int(self) & int(other)) else: return NotImplemented __rand__ = __and__ def __or__(self, other): if isinstance(other, bool): return bool(int(self) | int(other)) else: return NotImplemented __ror__ = __or__ def __xor__(self, other): if isinstance(other, bool): return bool(int(self) ^ int(other)) else: return NotImplemented __rxor__ = __xor__ False = bool(0, _create=1) True = bool(1, _create=1) Issues Because the repr() or str() of a bool value is different from an int value, some code (e.g. doctest-based unit tests) may fail. How much of a backwards compatibility problem this will be, I don't know. If we find this is a real problem, we could add a command-line option to make False and True aliases for 0 and 1 and bool an alias for int. Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil fill-column: 70 End: Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.164 retrieving revision 1.165 diff -C2 -d -r1.164 -r1.165 *** pep-0000.txt 8 Mar 2002 05:43:22 -0000 1.164 --- pep-0000.txt 8 Mar 2002 15:38:37 -0000 1.165 *************** *** 92,95 **** --- 92,96 ---- S 282 A Logging System Mick S 284 Integer for-loops Eppstein, Ewing + S 285 Adding a bool type van Rossum Finished PEPs (done, implemented in CVS) *************** *** 258,261 **** --- 259,263 ---- I 283 Python 2.3 Release Schedule Hylton S 284 Integer for-loops Eppstein, Ewing + S 285 Adding a bool type van Rossum SR 666 Reject Foolish Indentation Creighton From gvanrossum@users.sourceforge.net Fri Mar 8 16:15:07 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 08 Mar 2002 08:15:07 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0285.txt,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv11303 Modified Files: pep-0285.txt Log Message: Clarify issues baded upon the first questions. Don't add "(python-dev)" to Post-History header. Index: pep-0285.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0285.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pep-0285.txt 8 Mar 2002 15:38:37 -0000 1.1 --- pep-0285.txt 8 Mar 2002 16:15:04 -0000 1.2 *************** *** 8,12 **** Created: 8-Mar-2002 Python-Version: 2.3 ! Post-History: 8-Mar-2002 (python-dev) --- 8,12 ---- Created: 8-Mar-2002 Python-Version: 2.3 ! Post-History: 8-Mar-2002 *************** *** 82,85 **** --- 82,98 ---- False = bool(0, _create=1) True = bool(1, _create=1) + + The values False and True will be singletons, like None; the C + implementation will not allow other instances of bool to be + created. + + All built-in operations that are defined to return a Boolean + result will be changed to return False or True instead of 0 or 1. + In particular, this affects comparisons (<, <=, ==, !=, >, >=, is, + is not, in, not it), the unary operator 'not', and built-in + functions like hasattr(), isinstance() and issubclass(), the dict + method has_key(), string methods endswith(), isalnum(), isalpha(), + isdigit(), islower(), isspace(), istitle(), isupper(), and + startswith(), and the closed attribute of file objects. From jhylton@users.sourceforge.net Fri Mar 8 17:17:35 2002 From: jhylton@users.sourceforge.net (Jeremy Hylton) Date: Fri, 08 Mar 2002 09:17:35 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules cStringIO.c,2.32,2.33 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv3697 Modified Files: cStringIO.c Log Message: Fix SF bug #526518 The doc string for cStringIO suggested that str() of a StringIO object was equivalent to getvalue(). This was never true, so repair the doc string. (doctest would have helped here.) Bug fix candidate for any past versions. Index: cStringIO.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/cStringIO.c,v retrieving revision 2.32 retrieving revision 2.33 diff -C2 -d -r2.32 -r2.33 *** cStringIO.c 8 Dec 2001 18:02:56 -0000 2.32 --- cStringIO.c 8 Mar 2002 17:17:33 -0000 2.33 *************** *** 68,72 **** " an_output_stream.write(some_stuff)\n" " ...\n" ! " value=an_output_stream.getvalue() # str(an_output_stream) works too!\n" "\n" " an_input_stream=StringIO(a_string)\n" --- 68,72 ---- " an_output_stream.write(some_stuff)\n" " ...\n" ! " value=an_output_stream.getvalue()\n" "\n" " an_input_stream=StringIO(a_string)\n" From akuchling@users.sourceforge.net Fri Mar 8 17:19:12 2002 From: akuchling@users.sourceforge.net (A.M. Kuchling) Date: Fri, 08 Mar 2002 09:19:12 -0800 Subject: [Python-checkins] CVS: python/dist/src/Tools/webchecker webchecker.py,1.25,1.26 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/webchecker In directory usw-pr-cvs1:/tmp/cvs-serv3956 Modified Files: webchecker.py Log Message: [Bug #512799] urllib.splittype() returns a 2-tuple. (Reported by seb bacon) Index: webchecker.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/webchecker/webchecker.py,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** webchecker.py 11 Dec 2001 22:41:24 -0000 1.25 --- webchecker.py 8 Mar 2002 17:19:10 -0000 1.26 *************** *** 482,486 **** return self.name_table[url] ! scheme = urllib.splittype(url) if scheme in ('mailto', 'news', 'javascript', 'telnet'): self.note(1, " Not checking %s URL" % scheme) --- 482,486 ---- return self.name_table[url] ! scheme, path = urllib.splittype(url) if scheme in ('mailto', 'news', 'javascript', 'telnet'): self.note(1, " Not checking %s URL" % scheme) From akuchling@users.sourceforge.net Fri Mar 8 17:46:05 2002 From: akuchling@users.sourceforge.net (A.M. Kuchling) Date: Fri, 08 Mar 2002 09:46:05 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libxmlrpclib.tex,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv12711 Modified Files: libxmlrpclib.tex Log Message: [Bug #486527] Note that the caller has to ensure there are no control characters in strings being passed via XML-RPC. Fix some typos. 2.2.1 bugfix candidate. Index: libxmlrpclib.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libxmlrpclib.tex,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** libxmlrpclib.tex 1 Oct 2001 21:05:30 -0000 1.5 --- libxmlrpclib.tex 8 Mar 2002 17:46:02 -0000 1.6 *************** *** 60,63 **** --- 60,73 ---- XML-RPC server errors, or \exception{ProtocolError} used to signal an error in the HTTP/HTTPS transport layer. + + When passing strings, characters special to XML such as \samp{<}, + \samp{>}, and \samp{\&} will be automatically escaped. However, it's + the caller's responsibility to ensure that the string is free of + characters that aren't allowed in XML, such as the control characters + with ASCII values between 0 and 31; failing to do this will result in + an XML-RPC request that isn't well-formed XML. If you have to pass + arbitrary strings via XML-RPC, use the \class{Binary} wrapper class + described below. + \end{classdesc} *************** *** 201,205 **** \begin{memberdesc}{url} ! The URI or URL that triggered te error. \end{memberdesc} --- 211,215 ---- \begin{memberdesc}{url} ! The URI or URL that triggered the error. \end{memberdesc} *************** *** 209,213 **** \begin{memberdesc}{errmsg} ! The eror message of diagnostic string. \end{memberdesc} --- 219,223 ---- \begin{memberdesc}{errmsg} ! The error message or diagnostic string. \end{memberdesc} From akuchling@users.sourceforge.net Fri Mar 8 18:08:50 2002 From: akuchling@users.sourceforge.net (A.M. Kuchling) Date: Fri, 08 Mar 2002 10:08:50 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib ConfigParser.py,1.38,1.39 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv18758 Modified Files: ConfigParser.py Log Message: [Bug #523301] ConfigParser.write() produces broken output for values that were originally rfc822-like line continuations. Modified version of a patch from Matthias Ralfs. Index: ConfigParser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ConfigParser.py,v retrieving revision 1.38 retrieving revision 1.39 diff -C2 -d -r1.38 -r1.39 *** ConfigParser.py 18 Oct 2001 21:57:37 -0000 1.38 --- ConfigParser.py 8 Mar 2002 18:08:47 -0000 1.39 *************** *** 345,349 **** fp.write("[DEFAULT]\n") for (key, value) in self.__defaults.items(): ! fp.write("%s = %s\n" % (key, value)) fp.write("\n") for section in self.sections(): --- 345,349 ---- fp.write("[DEFAULT]\n") for (key, value) in self.__defaults.items(): ! fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t'))) fp.write("\n") for section in self.sections(): *************** *** 353,357 **** if key == "__name__": continue ! fp.write("%s = %s\n" % (key, value)) fp.write("\n") --- 353,357 ---- if key == "__name__": continue ! fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t'))) fp.write("\n") From akuchling@users.sourceforge.net Fri Mar 8 18:10:14 2002 From: akuchling@users.sourceforge.net (A.M. Kuchling) Date: Fri, 08 Mar 2002 10:10:14 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test/output test_cfgparser,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test/output In directory usw-pr-cvs1:/tmp/cvs-serv19827/output Modified Files: test_cfgparser Log Message: As part of fixing bug #523301, add a simple test of ConfigParser.write() Index: test_cfgparser =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/output/test_cfgparser,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** test_cfgparser 8 Oct 2001 17:13:12 -0000 1.5 --- test_cfgparser 8 Mar 2002 18:10:12 -0000 1.6 *************** *** 1,4 **** --- 1,5 ---- test_cfgparser Testing basic accessors... + Testing writing of files... Testing case sensitivity... Testing interpretation of boolean Values... From akuchling@users.sourceforge.net Fri Mar 8 18:10:14 2002 From: akuchling@users.sourceforge.net (A.M. Kuchling) Date: Fri, 08 Mar 2002 10:10:14 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_cfgparser.py,1.9,1.10 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv19827 Modified Files: test_cfgparser.py Log Message: As part of fixing bug #523301, add a simple test of ConfigParser.write() Index: test_cfgparser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_cfgparser.py,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** test_cfgparser.py 8 Oct 2001 17:13:11 -0000 1.9 --- test_cfgparser.py 8 Mar 2002 18:10:12 -0000 1.10 *************** *** 15,18 **** --- 15,19 ---- r'Foo Bar', r'Internationalized Stuff', + r'Long Line', r'Section\with$weird%characters[' '\t', r'Spacey Bar', *************** *** 48,52 **** --- 49,72 ---- " that never existed") + verify(cf.get('Long Line', 'foo', raw=1) == + 'this line is much, much longer than my editor\nlikes it.') + + + def write(src): + print "Testing writing of files..." + cf = ConfigParser.ConfigParser() + sio = StringIO.StringIO(src) + cf.readfp(sio) + output = StringIO.StringIO() + cf.write(output) + verify(output, """[DEFAULT] + foo = another very + long line + [Long Line] + foo = this line is much, much longer than my editor + likes it. + """) + def case_sensitivity(): print "Testing case sensitivity..." *************** *** 192,195 **** --- 212,218 ---- [Commented Bar] foo: bar ; comment + [Long Line] + foo: this line is much, much longer than my editor + likes it. [Section\with$weird%characters[""" '\t' r"""] [Internationalized Stuff] *************** *** 199,202 **** --- 222,231 ---- foo[de]=Deutsch """) + write("""[Long Line] + foo: this line is much, much longer than my editor + likes it. + [DEFAULT] + foo: another very + long line""") case_sensitivity() boolean(r""" From akuchling@users.sourceforge.net Fri Mar 8 18:20:02 2002 From: akuchling@users.sourceforge.net (A.M. Kuchling) Date: Fri, 08 Mar 2002 10:20:02 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib asyncore.py,1.28,1.29 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv22297 Modified Files: asyncore.py Log Message: [Bug #517554] When a signal happens during the select call in asyncore.poll, the select fails with EINTR, which the code catches. However, the code fails to clear the r/w/e arrays (like poll3 does), which means it acts as if every descriptor had received all possible events. Bug report and patch by Cesar Eduardo Barros Index: asyncore.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/asyncore.py,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** asyncore.py 14 Dec 2001 16:15:11 -0000 1.28 --- asyncore.py 8 Mar 2002 18:19:59 -0000 1.29 *************** *** 81,84 **** --- 81,85 ---- if err[0] != EINTR: raise + r = []; w = []; e = [] if DEBUG: From akuchling@users.sourceforge.net Fri Mar 8 18:27:15 2002 From: akuchling@users.sourceforge.net (A.M. Kuchling) Date: Fri, 08 Mar 2002 10:27:15 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib asynchat.py,1.15,1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv23896 Modified Files: asynchat.py Log Message: [Bug #491820] Define two abstract methods to shut up Pychecker, and for documentation purposes. These implementations are the same as the ones suggested by Skip in the bug report. Index: asynchat.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/asynchat.py,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** asynchat.py 8 Apr 2001 07:23:44 -0000 1.15 --- asynchat.py 8 Mar 2002 18:27:11 -0000 1.16 *************** *** 65,68 **** --- 65,74 ---- asyncore.dispatcher.__init__ (self, conn) + def collect_incoming_data(self, data): + raise NotImplementedError, "must be implemented in subclass" + + def found_terminator(self): + raise NotImplementedError, "must be implemented in subclass" + def set_terminator (self, term): "Set the input delimiter. Can be a fixed string of any length, an integer, or None" From gvanrossum@users.sourceforge.net Fri Mar 8 18:28:05 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 08 Mar 2002 10:28:05 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0285.txt,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv24565 Modified Files: pep-0285.txt Log Message: Some more clarifications. Index: pep-0285.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0285.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pep-0285.txt 8 Mar 2002 16:15:04 -0000 1.2 --- pep-0285.txt 8 Mar 2002 18:28:03 -0000 1.3 *************** *** 27,31 **** Most languages eventually grow a Boolean type; even C99 has one. It's useful to be able to tell from a function result that the ! outcome has Boolean semantics. --- 27,33 ---- Most languages eventually grow a Boolean type; even C99 has one. It's useful to be able to tell from a function result that the ! outcome has Boolean semantics, and it helps with things like RPC ! protocols that may prefer to encode Booleans differently from ! integers. *************** *** 37,46 **** class bool(int): ! def __new__(cls, val=0, _create=0): ! if _create: ! # This is nor part of the spec, ! # just a hack to bootstrap False and True ! return int.__new__(cls, not not val) ! elif val: return True else: --- 39,46 ---- class bool(int): ! def __new__(cls, val=0): ! # This constructor doesn't return a new instance; ! # it returns an existing instance ! if val: return True else: *************** *** 79,89 **** __rxor__ = __xor__ ! ! False = bool(0, _create=1) ! True = bool(1, _create=1) The values False and True will be singletons, like None; the C implementation will not allow other instances of bool to be ! created. All built-in operations that are defined to return a Boolean --- 79,91 ---- __rxor__ = __xor__ ! # Bootstrap truth values through sheer willpower ! False = int.__new__(bool, 0) ! True = int.__new__(bool, 1) The values False and True will be singletons, like None; the C implementation will not allow other instances of bool to be ! created. At the C level, the existing globals Py_False and ! Py_True will be identical to the built-in singletons False and ! True. All built-in operations that are defined to return a Boolean *************** *** 96,110 **** startswith(), and the closed attribute of file objects. Issues Because the repr() or str() of a bool value is different from an ! int value, some code (e.g. doctest-based unit tests) may fail. ! How much of a backwards compatibility problem this will be, I ! don't know. If we find this is a real problem, we could add a ! command-line option to make False and True aliases for 0 and 1 and ! bool an alias for int. - Copyright --- 98,121 ---- startswith(), and the closed attribute of file objects. + Note that subclassing from int means that True+1 is valid and + equals 2, and so on. This is important for backwards + compatibility: because comparisons and so on currently return + integer values, there's no way of telling what uses existing + applications make of these values. + Issues Because the repr() or str() of a bool value is different from an ! int value, some code (e.g. doctest-based unit tests, and possibly ! database code that relies on things like "%s" % truthvalue) may ! fail. How much of a backwards compatibility problem this will be, ! I don't know. If we find this is a real problem, we could add a ! command-line option to change the repr() and str() of False and ! True to be '0' and '1'; or we could make this the defined ! behavior, but that would defeat some of the purpose (being able to ! see that a printed result is intended to be a truth value). ! Copyright From jhylton@users.sourceforge.net Fri Mar 8 19:35:54 2002 From: jhylton@users.sourceforge.net (Jeremy Hylton) Date: Fri, 08 Mar 2002 11:35:54 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib httplib.py,1.44,1.45 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv9042 Modified Files: httplib.py Log Message: SF bug report #405939: wrong Host header with proxy In August, Greg said this looked good, so I'm going ahead with it. The fix is different from the one in the bug report. Instead of using a regular expression to extract the host from the url, I use urlparse.urlsplit. Martin commented that the patch doesn't address URLs that have basic authentication username and password in the header. I don't see any code anywhere in httplib that supports this feature, so I'm not going to address it for this fix. Bug fix candidate. Index: httplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/httplib.py,v retrieving revision 1.44 retrieving revision 1.45 diff -C2 -d -r1.44 -r1.45 *** httplib.py 16 Feb 2002 23:06:16 -0000 1.44 --- httplib.py 8 Mar 2002 19:35:51 -0000 1.45 *************** *** 70,73 **** --- 70,74 ---- import mimetools import socket + from urlparse import urlsplit try: *************** *** 468,474 **** # as Apache) barf when they see two Host: headers ! # if we need a non-standard port,include it in the header ! if self.port == HTTP_PORT: ! self.putheader('Host', self.host) else: self.putheader('Host', "%s:%s" % (self.host, self.port)) --- 469,481 ---- # as Apache) barf when they see two Host: headers ! # If we need a non-standard port,include it in the header. ! # If the request is going through a proxy, but the host of ! # the actual URL, not the host of the proxy. ! ! if url.startswith('http:'): ! nil, netloc, nil, nil, nil = urlsplit(url) ! self.putheader('Host', netloc) ! elif self.port == HTTP_PORT: ! self.putheader('Host', netloc) else: self.putheader('Host', "%s:%s" % (self.host, self.port)) *************** *** 856,859 **** --- 863,877 ---- print print h.getfile().read() + + # minimal test that code to extract host from url works + class HTTP11(HTTP): + _http_vsn = 11 + _http_vsn_str = 'HTTP/1.1' + + h = HTTP11('www.python.org') + h.putrequest('GET', 'http://www.python.org/~jeremy/') + h.endheaders() + h.getreply() + h.close() if hasattr(socket, 'ssl'): From akuchlin@mems-exchange.org Fri Mar 8 19:39:41 2002 From: akuchlin@mems-exchange.org (Andrew Kuchling) Date: Fri, 8 Mar 2002 14:39:41 -0500 Subject: [Python-checkins] CVS: python/dist/src/Lib httplib.py,1.44,1.45 In-Reply-To: References: Message-ID: <20020308193941.GA10846@ute.mems-exchange.org> On Fri, Mar 08, 2002 at 11:35:54AM -0800, Jeremy Hylton wrote: >SF bug report #405939: wrong Host header with proxy >! if url.startswith('http:'): >! nil, netloc, nil, nil, nil = urlsplit(url) Does it matter that this won't catch https:// URLs? --amk From jeremy@zope.com Fri Mar 8 19:43:22 2002 From: jeremy@zope.com (Jeremy Hylton) Date: Fri, 08 Mar 2002 14:43:22 -0500 Subject: [Python-checkins] CVS: python/dist/src/Lib httplib.py,1.44,1.45 In-Reply-To: <20020308193941.GA10846@ute.mems-exchange.org> Message-ID: On Fri, 8 Mar 2002 14:39:41 -0500 Andrew Kuchling wrote: > On Fri, Mar 08, 2002 at 11:35:54AM -0800, Jeremy Hylton > wrote: > >SF bug report #405939: wrong Host header with proxy > >! if url.startswith('http:'): > >! nil, netloc, nil, nil, nil = > urlsplit(url) > > Does it matter that this won't catch https:// URLs? Probably. I should probably change the initial test to startswith 'http' and then verify that the netloc return from urlsplit() is not ''. Sound good to you? Jeremy From gvanrossum@users.sourceforge.net Fri Mar 8 19:48:46 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Fri, 08 Mar 2002 11:48:46 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0285.txt,1.3,1.4 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv12633 Modified Files: pep-0285.txt Log Message: More rationale and issues. Index: pep-0285.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0285.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** pep-0285.txt 8 Mar 2002 18:28:03 -0000 1.3 --- pep-0285.txt 8 Mar 2002 19:48:44 -0000 1.4 *************** *** 26,33 **** Most languages eventually grow a Boolean type; even C99 has one. ! It's useful to be able to tell from a function result that the ! outcome has Boolean semantics, and it helps with things like RPC ! protocols that may prefer to encode Booleans differently from ! integers. --- 26,78 ---- Most languages eventually grow a Boolean type; even C99 has one. ! ! Many programmers apparently feel the need for a Boolean type; most ! Python documentation contains a bit of an apology for the absence ! of a Boolean type. I've seen lots of module that defined ! constants "False=0" and "True=1" (or similar) at the top and used ! those. The problem with this is that everybody does it ! differently. For example, should you use "FALSE", "false", ! "False", "F" or even "f"? And should false be the value zero or ! None, or perhaps a truth value of a different type that will print ! as "true" or "false"? Adding a standard bool type to the language ! resolves those issues. ! ! Some external libraries (e.g. databases and RPC packages) need to ! be able to distinguish between Boolean and integral values, and ! while it's usually possible to create a solution, it would be ! easier if the language offered a standard Boolean type. ! ! And here's an argument derived from teaching Python. When showing ! people comparison operators etc. in the interactive shell, I think ! this is a bit ugly: ! ! >>> a = 13 ! >>> b = 12 ! >>> a > b ! 1 ! >>> ! ! If this was: ! ! >>> a > b ! True ! >>> ! ! it would require one millisecond less thinking each time a 0 or 1 ! was printed. ! ! There's also the issue (which I've seen puzzling even experienced ! Pythonistas who had been away from the language for a while) that if ! you see: ! ! >>> cmp(a, b) ! 1 ! >>> cmp(a, a) ! 0 ! >>> ! ! you might be tempted to believe that cmp() also returned a truth ! value. If ints are not (normally) used for Booleans results, this ! would stand out much more clearly as something completely different. *************** *** 111,119 **** database code that relies on things like "%s" % truthvalue) may fail. How much of a backwards compatibility problem this will be, ! I don't know. If we find this is a real problem, we could add a ! command-line option to change the repr() and str() of False and ! True to be '0' and '1'; or we could make this the defined ! behavior, but that would defeat some of the purpose (being able to ! see that a printed result is intended to be a truth value). --- 156,170 ---- database code that relies on things like "%s" % truthvalue) may fail. How much of a backwards compatibility problem this will be, ! I don't know. If we this turns out to be a real problem, we could ! changes the rules so that str() of a bool returns "0" or "1", ! while repr() of a bool still returns "False" or "True". ! ! Other languages (C99, C++, Java) name the constants "false" and ! "true", in all lowercase. In Python, I prefer to stick with the ! example set by the existing built-in constants, which all use ! CapitalizedWords: None, Ellipsis, NotImplemented (as well as all ! built-in exceptions). Python's built-in module uses all lowercase ! for functions and types only. But I'm willing to consider the ! lowercase alternatives if enough people think it looks better. From jhylton@users.sourceforge.net Fri Mar 8 21:11:39 2002 From: jhylton@users.sourceforge.net (Jeremy Hylton) Date: Fri, 08 Mar 2002 13:11:39 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.96,2.97 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv1697 Modified Files: abstract.c Log Message: Fix for SF bug 516727: MyInt(2) + "3" -> NotImplemented PyNumber_Add() tries the nb_add slot first, then falls back to sq_concat. However, tt didn't check the return value of sq_concat. If sq_concat returns NotImplemented, raise the standard TypeError. Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.96 retrieving revision 2.97 diff -C2 -d -r2.96 -r2.97 *** abstract.c 2 Mar 2002 04:14:21 -0000 2.96 --- abstract.c 8 Mar 2002 21:11:37 -0000 2.97 *************** *** 606,614 **** if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; ! Py_DECREF(Py_NotImplemented); ! if (m && m->sq_concat) { result = (*m->sq_concat)(v, w); ! } ! else { PyErr_Format( PyExc_TypeError, --- 606,613 ---- if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; ! Py_DECREF(result); ! if (m && m->sq_concat) result = (*m->sq_concat)(v, w); ! if (result == Py_NotImplemented) { PyErr_Format( PyExc_TypeError, From jhylton@users.sourceforge.net Fri Mar 8 21:28:56 2002 From: jhylton@users.sourceforge.net (Jeremy Hylton) Date: Fri, 08 Mar 2002 13:28:56 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.97,2.98 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv6741 Modified Files: abstract.c Log Message: Fix leak of NotImplemented in previous checkin to PyNumber_Add(). If result == Py_NotImplemented, always DECREF it before assigning a new value to result. Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.97 retrieving revision 2.98 diff -C2 -d -r2.97 -r2.98 *** abstract.c 8 Mar 2002 21:11:37 -0000 2.97 --- abstract.c 8 Mar 2002 21:28:54 -0000 2.98 *************** *** 606,619 **** if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; ! Py_DECREF(result); ! if (m && m->sq_concat) result = (*m->sq_concat)(v, w); if (result == Py_NotImplemented) { ! PyErr_Format( PyExc_TypeError, "unsupported operand types for +: '%s' and '%s'", v->ob_type->tp_name, w->ob_type->tp_name); ! result = NULL; } } --- 606,621 ---- if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; ! if (m && m->sq_concat) { ! Py_DECREF(result); result = (*m->sq_concat)(v, w); + } if (result == Py_NotImplemented) { ! Py_DECREF(result); ! PyErr_Format( PyExc_TypeError, "unsupported operand types for +: '%s' and '%s'", v->ob_type->tp_name, w->ob_type->tp_name); ! result = NULL; } } From jhylton@users.sourceforge.net Fri Mar 8 21:32:02 2002 From: jhylton@users.sourceforge.net (Jeremy Hylton) Date: Fri, 08 Mar 2002 13:32:02 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_pyclbr.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv7405 Modified Files: test_pyclbr.py Log Message: Fix pyclbr test of httplib without really understanding pyclbr. It seems that the new class HTTP11 in httplib.test() isn't discoverable by pyclbr, which causes this test to fail. Index: test_pyclbr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_pyclbr.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** test_pyclbr.py 3 Oct 2001 04:08:26 -0000 1.6 --- test_pyclbr.py 8 Mar 2002 21:31:59 -0000 1.7 *************** *** 141,145 **** cm('httplib', ignore=('error', # set with = ! 'HTTPS')) # not on all platforms cm('Cookie', ignore=('__str__', 'Cookie')) # set with = --- 141,146 ---- cm('httplib', ignore=('error', # set with = ! 'HTTPS', ! 'HTTP11')) # not on all platforms cm('Cookie', ignore=('__str__', 'Cookie')) # set with = From jhylton@users.sourceforge.net Fri Mar 8 21:43:54 2002 From: jhylton@users.sourceforge.net (Jeremy Hylton) Date: Fri, 08 Mar 2002 13:43:54 -0800 Subject: [Python-checkins] CVS: python/dist/src configure.in,1.294,1.295 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv10559 Modified Files: configure.in Log Message: Add fix for AIX as reported by srubben in SF bug #477487. Untested, of course. Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.294 retrieving revision 1.295 diff -C2 -d -r1.294 -r1.295 *** configure.in 8 Mar 2002 13:43:01 -0000 1.294 --- configure.in 8 Mar 2002 21:43:51 -0000 1.295 *************** *** 293,297 **** case $ac_sys_system in AIX*) ! LINKCC="\$(srcdir)/Modules/makexp_aix Modules/python.exp \"\" \$(LIBRARY); $(LINKCC)";; dgux*) LINKCC="LD_RUN_PATH=$libdir $(LINKCC)";; --- 293,297 ---- case $ac_sys_system in AIX*) ! LINKCC="\$(srcdir)/Modules/makexp_aix Modules/python.exp \"\" \$(LIBRARY); $LINKCC";; dgux*) LINKCC="LD_RUN_PATH=$libdir $(LINKCC)";; From fdrake@users.sourceforge.net Fri Mar 8 22:02:08 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Fri, 08 Mar 2002 14:02:08 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/dist dist.tex,1.36,1.37 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/dist In directory usw-pr-cvs1:/tmp/cvs-serv14250/dist Modified Files: dist.tex Log Message: Add more explanation of how data_files is used (esp. where the files end up in the installation and how that location is determined). Index: dist.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/dist/dist.tex,v retrieving revision 1.36 retrieving revision 1.37 diff -C2 -d -r1.36 -r1.37 *** dist.tex 16 Aug 2001 21:25:24 -0000 1.36 --- dist.tex 8 Mar 2002 22:02:06 -0000 1.37 *************** *** 633,638 **** data files, anything which does not fit in the previous categories. ! \option{data\_files} specify a sequence of \code{(directory, files)} ! pairs in the following way: \begin{verbatim} --- 633,638 ---- data files, anything which does not fit in the previous categories. ! \option{data\_files} specifies a sequence of (\var{directory}, ! \var{files}) pairs in the following way: \begin{verbatim} *************** *** 644,647 **** --- 644,658 ---- Note that you can specify the directory names where the data files will be installed, but you cannot rename the data files themselves. + + Each (\var{directory}, \var{files}) pair in the sequence specifies the + installation directory and the files to install there. If + \var{directory} is a relative path, it is interpreted relative to the + installation prefix (Python's \code{sys.prefix} for pure-Python + packages, \code{sys.exec_prefix} for packages that contain extension + modules). Each file name in \var{files} is interpreted relative to + the \file{setup.py} script at the top of the package source + distribution. No directory information from \var{files} is used to + determine the final location of the installed file; only the name of + the file is used. You can specify the \option{data\_files} options as a simple sequence From fdrake@users.sourceforge.net Fri Mar 8 22:02:19 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Fri, 08 Mar 2002 14:02:19 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/dist dist.tex,1.36,1.36.16.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/dist In directory usw-pr-cvs1:/tmp/cvs-serv14325/dist Modified Files: Tag: release22-maint dist.tex Log Message: Add more explanation of how data_files is used (esp. where the files end up in the installation and how that location is determined). Index: dist.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/dist/dist.tex,v retrieving revision 1.36 retrieving revision 1.36.16.1 diff -C2 -d -r1.36 -r1.36.16.1 *** dist.tex 16 Aug 2001 21:25:24 -0000 1.36 --- dist.tex 8 Mar 2002 22:02:17 -0000 1.36.16.1 *************** *** 633,638 **** data files, anything which does not fit in the previous categories. ! \option{data\_files} specify a sequence of \code{(directory, files)} ! pairs in the following way: \begin{verbatim} --- 633,638 ---- data files, anything which does not fit in the previous categories. ! \option{data\_files} specifies a sequence of (\var{directory}, ! \var{files}) pairs in the following way: \begin{verbatim} *************** *** 644,647 **** --- 644,658 ---- Note that you can specify the directory names where the data files will be installed, but you cannot rename the data files themselves. + + Each (\var{directory}, \var{files}) pair in the sequence specifies the + installation directory and the files to install there. If + \var{directory} is a relative path, it is interpreted relative to the + installation prefix (Python's \code{sys.prefix} for pure-Python + packages, \code{sys.exec_prefix} for packages that contain extension + modules). Each file name in \var{files} is interpreted relative to + the \file{setup.py} script at the top of the package source + distribution. No directory information from \var{files} is used to + determine the final location of the installed file; only the name of + the file is used. You can specify the \option{data\_files} options as a simple sequence From fdrake@users.sourceforge.net Fri Mar 8 22:02:28 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Fri, 08 Mar 2002 14:02:28 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/dist dist.tex,1.33,1.33.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/dist In directory usw-pr-cvs1:/tmp/cvs-serv14367/dist Modified Files: Tag: release21-maint dist.tex Log Message: Add more explanation of how data_files is used (esp. where the files end up in the installation and how that location is determined). Index: dist.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/dist/dist.tex,v retrieving revision 1.33 retrieving revision 1.33.4.1 diff -C2 -d -r1.33 -r1.33.4.1 *** dist.tex 1 Mar 2001 18:35:43 -0000 1.33 --- dist.tex 8 Mar 2002 22:02:26 -0000 1.33.4.1 *************** *** 633,638 **** data files, anything which does not fit in the previous categories. ! \option{data\_files} specify a sequence of \code{(directory, files)} ! pairs in the following way: \begin{verbatim} --- 633,638 ---- data files, anything which does not fit in the previous categories. ! \option{data\_files} specifies a sequence of (\var{directory}, ! \var{files}) pairs in the following way: \begin{verbatim} *************** *** 644,647 **** --- 644,658 ---- Note that you can specify the directory names where the data files will be installed, but you cannot rename the data files themselves. + + Each (\var{directory}, \var{files}) pair in the sequence specifies the + installation directory and the files to install there. If + \var{directory} is a relative path, it is interpreted relative to the + installation prefix (Python's \code{sys.prefix} for pure-Python + packages, \code{sys.exec_prefix} for packages that contain extension + modules). Each file name in \var{files} is interpreted relative to + the \file{setup.py} script at the top of the package source + distribution. No directory information from \var{files} is used to + determine the final location of the installed file; only the name of + the file is used. You can specify the \option{data\_files} options as a simple sequence From tim_one@users.sourceforge.net Sat Mar 9 00:06:28 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 08 Mar 2002 16:06:28 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.247,2.248 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv11689/python/Python Modified Files: bltinmodule.c Log Message: Docstring for filter(): Someone on the Tutor list reasonably complained that it didn't tell enough of the truth. Bugfix candidate (I guess -- it helps and it's harmless). Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.247 retrieving revision 2.248 diff -C2 -d -r2.247 -r2.248 *** bltinmodule.c 12 Jan 2002 11:05:09 -0000 2.247 --- bltinmodule.c 9 Mar 2002 00:06:26 -0000 2.248 *************** *** 248,256 **** static char filter_doc[] = ! "filter(function, sequence) -> list\n\ ! \n\ ! Return a list containing those items of sequence for which function(item)\n\ ! is true. If function is None, return a list of items that are true."; ! static PyObject * --- 248,256 ---- static char filter_doc[] = ! "filter(function or None, sequence) -> list, tuple, or string\n" ! "\n" ! "Return those items of sequence for which function(item) is true. If\n" ! "function is None, return the items that are true. If sequence is a tuple\n" ! "or string, return the same type, else return a list."; static PyObject * From tim_one@users.sourceforge.net Sat Mar 9 04:58:26 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 08 Mar 2002 20:58:26 -0800 Subject: [Python-checkins] CVS: python/dist/src/Include pyport.h,2.44,2.45 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv1957/python/Include Modified Files: pyport.h Log Message: SF bug 525705: [2.2] underflow raise OverflowException. Another year in the quest to out-guess random C behavior. Added macros Py_ADJUST_ERANGE1(X) and Py_ADJUST_ERANGE2(X, Y). The latter is useful for functions with complex results. Two corrections to errno- after-libm-call are attempted: 1. If the platform set errno to ERANGE due to underflow, clear errno. Some unknown subset of libm versions and link options do this. It's allowed by C89, but I never figured anyone would do it. 2. If the platform did not set errno but overflow occurred, force errno to ERANGE. C89 required setting errno to ERANGE, but C99 doesn't. Some unknown subset of libm versions and link options do it the C99 way now. Bugfix candidate, but hold off until some Linux people actually try it, with and without -lieee. I'll send a help plea to Python-Dev. Index: pyport.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pyport.h,v retrieving revision 2.44 retrieving revision 2.45 diff -C2 -d -r2.44 -r2.45 *** pyport.h 2 Mar 2002 08:43:19 -0000 2.44 --- pyport.h 9 Mar 2002 04:58:24 -0000 2.45 *************** *** 288,291 **** --- 288,326 ---- } while(0) + /* Py_ADJUST_ERANGE1(x) + * Py_ADJUST_ERANGE2(x, y) + * Set errno to 0 before calling a libm function, and invoke one of these + * macros after, passing the function result(s) (Py_ADJUST_ERANGE2 is useful + * for functions returning complex results). This makes two kinds of + * adjustments to errno: (A) If it looks like the platform libm set + * errno=ERANGE due to underflow, clear errno. (B) If it looks like the + * platform libm overflowed but didn't set errno, force errno to ERANGE. In + * effect, we're trying to force a useful implementation of C89 errno + * behavior. + * Caution: + * This isn't reliable. See Py_OVERFLOWED comments. + * X and Y may be evaluated more than once. + */ + #define Py_ADJUST_ERANGE1(X) \ + do { \ + if (errno == 0) { \ + if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL) \ + errno = ERANGE; \ + } \ + else if (errno == ERANGE && (X) == 0.0) \ + errno = 0; \ + } while(0) + + #define Py_ADJUST_ERANGE2(X, Y) \ + do { \ + if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL || \ + (Y) == Py_HUGE_VAL || (Y) == -Py_HUGE_VAL) { \ + if (errno == 0) \ + errno = ERANGE; \ + } \ + else if (errno == ERANGE) \ + errno = 0; \ + } while(0) + /************************************************************************** Prototypes that are missing from the standard include files on some systems From tim_one@users.sourceforge.net Sat Mar 9 04:58:26 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 08 Mar 2002 20:58:26 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules cmathmodule.c,2.27,2.28 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv1957/python/Modules Modified Files: cmathmodule.c Log Message: SF bug 525705: [2.2] underflow raise OverflowException. Another year in the quest to out-guess random C behavior. Added macros Py_ADJUST_ERANGE1(X) and Py_ADJUST_ERANGE2(X, Y). The latter is useful for functions with complex results. Two corrections to errno- after-libm-call are attempted: 1. If the platform set errno to ERANGE due to underflow, clear errno. Some unknown subset of libm versions and link options do this. It's allowed by C89, but I never figured anyone would do it. 2. If the platform did not set errno but overflow occurred, force errno to ERANGE. C89 required setting errno to ERANGE, but C99 doesn't. Some unknown subset of libm versions and link options do it the C99 way now. Bugfix candidate, but hold off until some Linux people actually try it, with and without -lieee. I'll send a help plea to Python-Dev. Index: cmathmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/cmathmodule.c,v retrieving revision 2.27 retrieving revision 2.28 diff -C2 -d -r2.27 -r2.28 *** cmathmodule.c 6 Sep 2001 08:16:17 -0000 2.27 --- cmathmodule.c 9 Mar 2002 04:58:24 -0000 2.28 *************** *** 338,343 **** x = (*func)(x); PyFPE_END_PROTECT(x) ! Py_SET_ERANGE_IF_OVERFLOW(x.real); ! Py_SET_ERANGE_IF_OVERFLOW(x.imag); if (errno != 0) return math_error(); --- 338,342 ---- x = (*func)(x); PyFPE_END_PROTECT(x) ! Py_ADJUST_ERANGE2(x.real, x.imag); if (errno != 0) return math_error(); From tim_one@users.sourceforge.net Sat Mar 9 04:58:26 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Fri, 08 Mar 2002 20:58:26 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects floatobject.c,2.110,2.111 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv1957/python/Objects Modified Files: floatobject.c Log Message: SF bug 525705: [2.2] underflow raise OverflowException. Another year in the quest to out-guess random C behavior. Added macros Py_ADJUST_ERANGE1(X) and Py_ADJUST_ERANGE2(X, Y). The latter is useful for functions with complex results. Two corrections to errno- after-libm-call are attempted: 1. If the platform set errno to ERANGE due to underflow, clear errno. Some unknown subset of libm versions and link options do this. It's allowed by C89, but I never figured anyone would do it. 2. If the platform did not set errno but overflow occurred, force errno to ERANGE. C89 required setting errno to ERANGE, but C99 doesn't. Some unknown subset of libm versions and link options do it the C99 way now. Bugfix candidate, but hold off until some Linux people actually try it, with and without -lieee. I'll send a help plea to Python-Dev. Index: floatobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v retrieving revision 2.110 retrieving revision 2.111 diff -C2 -d -r2.110 -r2.111 *** floatobject.c 11 Dec 2001 20:31:34 -0000 2.110 --- floatobject.c 9 Mar 2002 04:58:24 -0000 2.111 *************** *** 578,584 **** ix = pow(iv, iw); PyFPE_END_PROTECT(ix) ! Py_SET_ERANGE_IF_OVERFLOW(ix); if (errno != 0) { ! /* XXX could it be another type of error? */ PyErr_SetFromErrno(PyExc_OverflowError); return NULL; --- 578,584 ---- ix = pow(iv, iw); PyFPE_END_PROTECT(ix) ! Py_ADJUST_ERANGE1(ix); if (errno != 0) { ! assert(errno == ERANGE); PyErr_SetFromErrno(PyExc_OverflowError); return NULL; From jhylton@users.sourceforge.net Sat Mar 9 06:07:25 2002 From: jhylton@users.sourceforge.net (Jeremy Hylton) Date: Fri, 08 Mar 2002 22:07:25 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib httplib.py,1.45,1.46 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv14755 Modified Files: httplib.py Log Message: Fix SF bug 525520. Don't automatically add a Host: header if the headers passed to request() already has a Host key. Index: httplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/httplib.py,v retrieving revision 1.45 retrieving revision 1.46 diff -C2 -d -r1.45 -r1.46 *** httplib.py 8 Mar 2002 19:35:51 -0000 1.45 --- httplib.py 9 Mar 2002 06:07:23 -0000 1.46 *************** *** 411,415 **** raise ! def putrequest(self, method, url): """Send a request to the server. --- 411,415 ---- raise ! def putrequest(self, method, url, skip_host=0): """Send a request to the server. *************** *** 462,483 **** # Issue some standard headers for better HTTP/1.1 compliance ! # this header is issued *only* for HTTP/1.1 connections. more ! # specifically, this means it is only issued when the client uses ! # the new HTTPConnection() class. backwards-compat clients will ! # be using HTTP/1.0 and those clients may be issuing this header ! # themselves. we should NOT issue it twice; some web servers (such ! # as Apache) barf when they see two Host: headers ! # If we need a non-standard port,include it in the header. ! # If the request is going through a proxy, but the host of ! # the actual URL, not the host of the proxy. ! if url.startswith('http:'): ! nil, netloc, nil, nil, nil = urlsplit(url) ! self.putheader('Host', netloc) ! elif self.port == HTTP_PORT: ! self.putheader('Host', netloc) ! else: ! self.putheader('Host', "%s:%s" % (self.host, self.port)) # note: we are assuming that clients will not attempt to set these --- 462,490 ---- # Issue some standard headers for better HTTP/1.1 compliance ! if not skip_host: ! # this header is issued *only* for HTTP/1.1 ! # connections. more specifically, this means it is ! # only issued when the client uses the new ! # HTTPConnection() class. backwards-compat clients ! # will be using HTTP/1.0 and those clients may be ! # issuing this header themselves. we should NOT issue ! # it twice; some web servers (such as Apache) barf ! # when they see two Host: headers ! # If we need a non-standard port,include it in the ! # header. If the request is going through a proxy, ! # but the host of the actual URL, not the host of the ! # proxy. ! netloc = '' ! if url.startswith('http'): ! nil, netloc, nil, nil, nil = urlsplit(url) ! ! if netloc: ! self.putheader('Host', netloc) ! elif self.port == HTTP_PORT: ! self.putheader('Host', self.host) ! else: ! self.putheader('Host', "%s:%s" % (self.host, self.port)) # note: we are assuming that clients will not attempt to set these *************** *** 537,541 **** def _send_request(self, method, url, body, headers): ! self.putrequest(method, url) if body: --- 544,555 ---- def _send_request(self, method, url, body, headers): ! # If headers already contains a host header, then define the ! # optional skip_host argument to putrequest(). The check is ! # harder because field names are case insensitive. ! if (headers.has_key('Host') ! or [k for k in headers.iterkeys() if k.lower() == "host"]): ! self.putrequest(method, url, skip_host=1) ! else: ! self.putrequest(method, url) if body: From loewis@users.sourceforge.net Sat Mar 9 10:06:17 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sat, 09 Mar 2002 02:06:17 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/ext building.tex,NONE,1.1 ext.tex,1.104,1.105 windows.tex,1.3,1.4 unix.tex,1.2,NONE Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory usw-pr-cvs1:/tmp/cvs-serv16657 Modified Files: ext.tex windows.tex Added Files: building.tex Removed Files: unix.tex Log Message: Patch #500136: Update Update ext build documentation. 2.2.1 candidate. --- NEW FILE: building.tex --- \chapter{Building C and \Cpp{} Extensions with distutils \label{building}} \sectionauthor{Martin v. L\"owis}{martin@v.loewis.de} Starting in Python 1.4, Python provides, on \UNIX{}, a special make file for building make files for building dynamically-linked extensions and custom interpreters. Starting with Python 2.0, this mechanism (known as related to Makefile.pre.in, and Setup files) is no longer supported. Building custom interpreters was rarely used, and extensions modules can be build using distutils. Building an extension module using distutils requires that distutils is installed on the build machine, which is included in Python 2.x and available separately for Python 1.5. Since distutils also supports creation of binary packages, users don't necessarily need a compiler and distutils to install the extension. A distutils package contains a driver script, \file{setup.py}. This is a plain Python file, which, in the most simple case, could look like this: \begin{verbatim} from distutils.core import setup, Extension module1 = Extension('demo', sources = ['demo.c']) setup (name = 'PackageName', version = '1.0', description = 'This is a demo package', ext_modules = [module1]) \end{verbatim} With this \file{setup.py}, and a file \file{demo.c}, running \begin{verbatim} python setup.py build \end{verbatim} will compile \file{demo.c}, and produce an extension module named \samp{demo} in the \file{build} directory. Depending on the system, the module file will end up in a subdirectory \file{build/lib.system}, and may have a name like \file{demo.so} or \file{demo.pyd}. In the \file{setup.py}, all execution is performed by calling the \samp{setup} function. This takes a variable number of keyword arguments, of which the example above uses only a subset. Specifically, the example specifies meta-information to build packages, and it specifies the contents of the package. Normally, a package will contain of addition modules, like Python source modules, documentation, subpackages, etc. Please refer to the distutils documentation in \citetitle[../dist/dist.html]{Distributing Python Modules} to learn more about the features of distutils; this section explains building extension modules only. It is common to pre-compute arguments to \function{setup}, to better structure the driver script. In the example above, the\samp{ext_modules} argument to \function{setup} is a list of extension modules, each of which is an instance of the \class{Extension}. In the example, the instance defines an extension named \samp{demo} which is build by compiling a single source file, \file{demo.c}. In many cases, building an extension is more complex, since additional preprocessor defines and libraries may be needed. This is demonstrated in the example below. \begin{verbatim} from distutils.core import setup, Extension module1 = Extension('demo', define_macros = [('MAJOR_VERSION', '1'), ('MINOR_VERSION', '0')], include_dirs = ['/usr/local/include'], libraries = ['tcl83'], library_dirs = ['/usr/local/lib'], sources = ['demo.c']) setup (name = 'PackageName', version = '1.0', description = 'This is a demo package', author = 'Martin v. Loewis', author_email = 'martin@v.loewis.de', url = 'http://www.python.org/doc/current/ext/building.html', long_description = ''' This is really just a demo package. ''', ext_modules = [module1]) \end{verbatim} In this example, \function{setup} is called with additional meta-information, which is recommended when distribution packages have to be built. For the extension itself, it specifies preprocessor defines, include directories, library directories, and libraries. Depending on the compiler, distutils passes this information in different ways to the compiler. For example, on \UNIX{}, this may result in the compilation commands \begin{verbatim} gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -DMAJOR_VERSION=1 -DMINOR_VERSION=0 -I/usr/local/include -I/usr/local/include/python2.2 -c demo.c -o build/temp.linux-i686-2.2/demo.o gcc -shared build/temp.linux-i686-2.2/demo.o -L/usr/local/lib -ltcl83 -o build/lib.linux-i686-2.2/demo.so \end{verbatim} These lines are for demonstration purposes only; distutils users should trust that distutils gets the invocations right. \section{Distributing your extension modules \label{distributing}} When an extension has been successfully build, there are three ways to use it. End-users will typically want to install the module, they do so by running \begin{verbatim} python setup.py install \end{verbatim} Module maintainers should produce source packages; to do so, they run \begin{verbatim} python setup.py sdist \end{verbatim} In some cases, additional files need to be included in a source distribution; this is done through a \file{MANIFEST.in} file; see the distutils documentation for details. If the source distribution has been build successfully, maintainers can also create binary distributions. Depending on the platform, one of the following commands can be used to do so. \begin{verbatim} python setup.py bdist_wininst python setup.py bdist_rpm python setup.py bdist_dumb \end{verbatim} Index: ext.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/ext.tex,v retrieving revision 1.104 retrieving revision 1.105 diff -C2 -d -r1.104 -r1.105 *** ext.tex 20 Aug 2001 19:30:29 -0000 1.104 --- ext.tex 9 Mar 2002 10:06:14 -0000 1.105 *************** *** 53,57 **** \input{extending} \input{newtypes} ! \input{unix} \input{windows} \input{embedding} --- 53,57 ---- \input{extending} \input{newtypes} ! \input{building} \input{windows} \input{embedding} Index: windows.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/windows.tex,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** windows.tex 13 Dec 2001 17:20:32 -0000 1.3 --- windows.tex 9 Mar 2002 10:06:14 -0000 1.4 *************** *** 10,13 **** --- 10,17 ---- software which can be successfully built on both \UNIX{} and Windows. + Module authors are encouraged to use the distutils approach for + building extension modules, instead of the one described in this + section. You will still need the C compiler that was used to build + Python; typically Microsoft Visual \Cpp. \section{A Cookbook Approach \label{win-cookbook}} --- unix.tex DELETED --- From loewis@users.sourceforge.net Sat Mar 9 12:03:01 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sat, 09 Mar 2002 04:03:01 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects longobject.c,1.114,1.115 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv4126 Modified Files: longobject.c Log Message: Patch #494047: removes 64-bit ?: to cope on plan9. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.114 retrieving revision 1.115 diff -C2 -d -r1.114 -r1.115 *** longobject.c 2 Mar 2002 04:18:04 -0000 1.114 --- longobject.c 9 Mar 2002 12:02:59 -0000 1.115 *************** *** 695,699 **** SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1); ! return res < 0 ? (LONG_LONG)res : bytes; } --- 695,703 ---- SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1); ! /* Plan 9 can't handle LONG_LONG in ? : expressions */ ! if (res < 0) ! return (LONG_LONG)res; ! else ! return bytes; } *************** *** 717,721 **** SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0); ! return res < 0 ? (unsigned LONG_LONG)res : bytes; } --- 721,729 ---- SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0); ! /* Plan 9 can't handle LONG_LONG in ? : expressions */ ! if (res < 0) ! return (unsigned LONG_LONG)res; ! else ! return bytes; } From loewis@users.sourceforge.net Sat Mar 9 12:07:53 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sat, 09 Mar 2002 04:07:53 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.248,2.249 errors.c,2.67,2.68 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv5110 Modified Files: bltinmodule.c errors.c Log Message: Patch #494045: patches errno and stat to cope on plan9. Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.248 retrieving revision 2.249 diff -C2 -d -r2.248 -r2.249 *** bltinmodule.c 9 Mar 2002 00:06:26 -0000 2.248 --- bltinmodule.c 9 Mar 2002 12:07:51 -0000 2.249 *************** *** 537,543 **** PyCompilerFlags cf; int exists; - #ifndef RISCOS - struct stat s; - #endif if (!PyArg_ParseTuple(args, "s|O!O!:execfile", --- 537,540 ---- *************** *** 561,576 **** exists = 0; /* Test for existence or directory. */ ! #ifndef RISCOS ! if (!stat(filename, &s)) { ! if (S_ISDIR(s.st_mode)) ! #if defined(PYOS_OS2) && defined(PYCC_VACPP) ! errno = EOS2ERR; ! #else ! errno = EISDIR; ! #endif ! else ! exists = 1; } ! #else if (object_exists(filename)) { if (isdir(filename)) --- 558,574 ---- exists = 0; /* Test for existence or directory. */ ! #if defined(PLAN9) ! { ! Dir *d; ! ! if ((d = dirstat(filename))!=nil) { ! if(d->mode & DMDIR) ! werrstr("is a directory"); ! else ! exists = 1; ! free(d); ! } } ! #elif defined(RISCOS) if (object_exists(filename)) { if (isdir(filename)) *************** *** 579,583 **** exists = 1; } ! #endif /* RISCOS */ if (exists) { --- 577,595 ---- exists = 1; } ! #else /* standard Posix */ ! { ! struct stat s; ! if (stat(filename, &s) == 0) { ! if (S_ISDIR(s.st_mode)) ! # if defined(PY_OS2) && defined(PYCC_VACPP) ! errno = EOS2ERR; ! # else ! errno = EISDIR; ! # endif ! else ! exists = 1; ! } ! } ! #endif if (exists) { Index: errors.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v retrieving revision 2.67 retrieving revision 2.68 diff -C2 -d -r2.67 -r2.68 *** errors.c 3 Mar 2002 21:30:27 -0000 2.67 --- errors.c 9 Mar 2002 12:07:51 -0000 2.68 *************** *** 265,268 **** --- 265,271 ---- char *s; int i = errno; + #ifdef PLAN9 + char errbuf[ERRMAX]; + #endif #ifdef MS_WIN32 char *s_buf = NULL; *************** *** 272,275 **** --- 275,282 ---- return NULL; #endif + #ifdef PLAN9 + rerrstr(errbuf, sizeof errbuf); + s = errbuf; + #else if (i == 0) s = "Error"; /* Sometimes errno didn't get set */ *************** *** 306,310 **** } } ! #endif if (filename != NULL) v = Py_BuildValue("(iss)", i, s, filename); --- 313,318 ---- } } ! #endif /* Unix/Windows */ ! #endif /* PLAN 9*/ if (filename != NULL) v = Py_BuildValue("(iss)", i, s, filename); From loewis@users.sourceforge.net Sat Mar 9 12:10:56 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sat, 09 Mar 2002 04:10:56 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python thread.c,2.40,2.41 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv5662 Modified Files: thread.c Log Message: Patch #504224: add plan9 threads include to thread.c. Index: thread.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/thread.c,v retrieving revision 2.40 retrieving revision 2.41 diff -C2 -d -r2.40 -r2.41 *** thread.c 12 Jan 2002 11:05:11 -0000 2.40 --- thread.c 9 Mar 2002 12:10:54 -0000 2.41 *************** *** 134,137 **** --- 134,141 ---- #endif + #ifdef PLAN9_THREADS + #include "thread_plan9.h" + #endif + /* #ifdef FOOBAR_THREADS From gvanrossum@users.sourceforge.net Sat Mar 9 14:53:06 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 09 Mar 2002 06:53:06 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0285.txt,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv763 Modified Files: pep-0285.txt Log Message: Fix subtle bugs in &|^ overloading. Index: pep-0285.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0285.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** pep-0285.txt 8 Mar 2002 19:48:44 -0000 1.4 --- pep-0285.txt 9 Mar 2002 14:53:04 -0000 1.5 *************** *** 104,108 **** return bool(int(self) & int(other)) else: ! return NotImplemented __rand__ = __and__ --- 104,108 ---- return bool(int(self) & int(other)) else: ! return int.__and__(self, other) __rand__ = __and__ *************** *** 112,116 **** return bool(int(self) | int(other)) else: ! return NotImplemented __ror__ = __or__ --- 112,116 ---- return bool(int(self) | int(other)) else: ! return int.__or__(self, other) __ror__ = __or__ *************** *** 120,124 **** return bool(int(self) ^ int(other)) else: ! return NotImplemented __rxor__ = __xor__ --- 120,124 ---- return bool(int(self) ^ int(other)) else: ! return int.__xor__(self, other) __rxor__ = __xor__ From gvanrossum@users.sourceforge.net Sun Mar 10 03:36:17 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 09 Mar 2002 19:36:17 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0285.txt,1.5,1.6 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv26723 Modified Files: pep-0285.txt Log Message: Add callable() to the list of functions returning 'bool'. Index: pep-0285.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0285.txt,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** pep-0285.txt 9 Mar 2002 14:53:04 -0000 1.5 --- pep-0285.txt 10 Mar 2002 03:36:14 -0000 1.6 *************** *** 138,145 **** In particular, this affects comparisons (<, <=, ==, !=, >, >=, is, is not, in, not it), the unary operator 'not', and built-in ! functions like hasattr(), isinstance() and issubclass(), the dict ! method has_key(), string methods endswith(), isalnum(), isalpha(), ! isdigit(), islower(), isspace(), istitle(), isupper(), and ! startswith(), and the closed attribute of file objects. Note that subclassing from int means that True+1 is valid and --- 138,146 ---- In particular, this affects comparisons (<, <=, ==, !=, >, >=, is, is not, in, not it), the unary operator 'not', and built-in ! functions like callable(), hasattr(), isinstance() and ! issubclass(), the dict method has_key(), string methods ! endswith(), isalnum(), isalpha(), isdigit(), islower(), isspace(), ! istitle(), isupper(), and startswith(), and the closed attribute ! of file objects. Note that subclassing from int means that True+1 is valid and From gvanrossum@users.sourceforge.net Sun Mar 10 04:46:52 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 09 Mar 2002 20:46:52 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0285.txt,1.6,1.7 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv4767 Modified Files: pep-0285.txt Log Message: Some clarifications. Add section on compatibility (and why this means our bool is not very 'pure'). Index: pep-0285.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0285.txt,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pep-0285.txt 10 Mar 2002 03:36:14 -0000 1.6 --- pep-0285.txt 10 Mar 2002 04:46:49 -0000 1.7 *************** *** 16,24 **** with two constants, False and True. The bool type would be a straightforward subtype (in C) of the int type, and the values ! False and True would behave like 0 and 1 in most respects (e.g. ! False==0 and True==1 would be true) except repr() and str(). All ! built-in operations that conceptually return a Boolean result will ! be changed to return False or True instead of 0 or 1; for example, ! comparisons and the "not" operator. --- 16,24 ---- with two constants, False and True. The bool type would be a straightforward subtype (in C) of the int type, and the values ! False and True would behave like 0 and 1 in most respects (for ! example, False==0 and True==1 would be true) except repr() and ! str(). All built-in operations that conceptually return a Boolean ! result will be changed to return False or True instead of 0 or 1; ! for example, comparisons and the "not" operator. *************** *** 38,42 **** resolves those issues. ! Some external libraries (e.g. databases and RPC packages) need to be able to distinguish between Boolean and integral values, and while it's usually possible to create a solution, it would be --- 38,42 ---- resolves those issues. ! Some external libraries (like databases and RPC packages) need to be able to distinguish between Boolean and integral values, and while it's usually possible to create a solution, it would be *************** *** 137,146 **** result will be changed to return False or True instead of 0 or 1. In particular, this affects comparisons (<, <=, ==, !=, >, >=, is, ! is not, in, not it), the unary operator 'not', and built-in ! functions like callable(), hasattr(), isinstance() and ! issubclass(), the dict method has_key(), string methods endswith(), isalnum(), isalpha(), isdigit(), islower(), isspace(), ! istitle(), isupper(), and startswith(), and the closed attribute ! of file objects. Note that subclassing from int means that True+1 is valid and --- 137,147 ---- result will be changed to return False or True instead of 0 or 1. In particular, this affects comparisons (<, <=, ==, !=, >, >=, is, ! is not, in, not it), the unary operator 'not', the built-in ! functions callable(), hasattr(), isinstance() and issubclass(), ! the dict method has_key(), the string and unicode methods endswith(), isalnum(), isalpha(), isdigit(), islower(), isspace(), ! istitle(), isupper(), and startswith(), the unicode methods ! isdecimal() and isnumeric(), and the closed attribute of file ! objects. Note that subclassing from int means that True+1 is valid and *************** *** 151,163 **** Issues Because the repr() or str() of a bool value is different from an ! int value, some code (e.g. doctest-based unit tests, and possibly ! database code that relies on things like "%s" % truthvalue) may ! fail. How much of a backwards compatibility problem this will be, ! I don't know. If we this turns out to be a real problem, we could ! changes the rules so that str() of a bool returns "0" or "1", ! while repr() of a bool still returns "False" or "True". Other languages (C99, C++, Java) name the constants "false" and --- 152,185 ---- + Compatibility + + Because of backwards compatibility, the bool type lacks many + properties that some would like to see. For example, arithmetic + operations with one or two bool arguments is allowed, treating + False as 0 and True as 1. Also, a bool may be used as a sequence + index. + + I don't see this as a problem, and I don't want evolve the + language in this direction either; I don't believe that a stricter + interpretation of "Booleanness" makes the language much clearer. + + Another consequence of the compatibility requirement is that the + expression "True and 6" has the value 6, and similarly the + expression "False or 0" has the value 0. The "and" and "or" + operators are usefully defined to return the first argument that + determines the outcome. Of course, if both arguments are bools, + the outcome is always a bool. It can also easily be coerced into + being a bool by writing for example "bool(x and y)". + + Issues Because the repr() or str() of a bool value is different from an ! int value, some code (for example doctest-based unit tests, and ! possibly database code that relies on things like "%s" % truth) ! may fail. How much of a backwards compatibility problem this will ! be, I don't know. If we this turns out to be a real problem, we ! could changes the rules so that str() of a bool returns "0" or ! "1", while repr() of a bool still returns "False" or "True". Other languages (C99, C++, Java) name the constants "false" and From gvanrossum@users.sourceforge.net Sun Mar 10 05:47:38 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sat, 09 Mar 2002 21:47:38 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0285.txt,1.7,1.8 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv13503 Modified Files: pep-0285.txt Log Message: Add link to implementation. Index: pep-0285.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0285.txt,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** pep-0285.txt 10 Mar 2002 04:46:49 -0000 1.7 --- pep-0285.txt 10 Mar 2002 05:47:36 -0000 1.8 *************** *** 192,195 **** --- 192,203 ---- + Implementation + + An experimental, but fairly complete implementation in C has been + uploaded to the SourceForge patch manager: + + http://sourceforge.net/tracker/index.php?func=detail&aid=528022&group_id=5470&atid=305470 + + Copyright From tim_one@users.sourceforge.net Sun Mar 10 07:59:15 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 09 Mar 2002 23:59:15 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_generators.py,1.30,1.31 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv29778/python/Lib/test Modified Files: test_generators.py Log Message: SF patch 499062: Minor typo in test_generators.py. There's no actual patch there. It's an objection that Guido's example doesn't actually generator "leaves", so change the comment that says it does. Index: test_generators.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_generators.py,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -d -r1.30 -r1.31 *** test_generators.py 6 Dec 2001 06:23:25 -0000 1.30 --- test_generators.py 10 Mar 2002 07:59:13 -0000 1.31 *************** *** 260,264 **** >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") ! >>> # A recursive generator that generates Tree leaves in in-order. >>> def inorder(t): ... if t: --- 260,264 ---- >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ") ! >>> # A recursive generator that generates Tree labels in in-order. >>> def inorder(t): ... if t: From tim_one@users.sourceforge.net Sun Mar 10 07:59:30 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sat, 09 Mar 2002 23:59:30 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0255.txt,1.17,1.18 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv29951 Modified Files: pep-0255.txt Log Message: SF patch 499062: Minor typo in test_generators.py. There's no actual patch there. It's an objection that Guido's example doesn't actually generator "leaves", so change the comment that says it does. Index: pep-0255.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0255.txt,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** pep-0255.txt 15 Aug 2001 05:46:40 -0000 1.17 --- pep-0255.txt 10 Mar 2002 07:59:28 -0000 1.18 *************** *** 323,327 **** return Tree(list[i], tree(list[:i]), tree(list[i+1:])) ! # A recursive generator that generates Tree leaves in in-order. def inorder(t): if t: --- 323,327 ---- return Tree(list[i], tree(list[:i]), tree(list[i+1:])) ! # A recursive generator that generates Tree labels in in-order. def inorder(t): if t: From gvanrossum@users.sourceforge.net Sun Mar 10 14:11:19 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 10 Mar 2002 06:11:19 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.127,2.128 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv27065 Modified Files: typeobject.c Log Message: Bugfix candidate. Adapter from SF patch 528038; fixes SF bug 527816. The wrapper for __nonzero__ should be wrap_inquiry rather than wrap_unaryfunc, since the slot returns an int, not a PyObject *. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.127 retrieving revision 2.128 diff -C2 -d -r2.127 -r2.128 *** typeobject.c 18 Feb 2002 17:46:48 -0000 2.127 --- typeobject.c 10 Mar 2002 14:11:16 -0000 2.128 *************** *** 3509,3513 **** UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, "abs(x)"), ! UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_unaryfunc, "x != 0"), UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"), --- 3509,3513 ---- UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, "abs(x)"), ! UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquiry, "x != 0"), UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"), From loewis@users.sourceforge.net Sun Mar 10 16:00:01 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 10 Mar 2002 08:00:01 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib ftplib.py,1.65,1.66 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv27998 Modified Files: ftplib.py Log Message: Access the exception argument to see whether it starts with '500'. Fixes #527855. Index: ftplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ftplib.py,v retrieving revision 1.65 retrieving revision 1.66 diff -C2 -d -r1.65 -r1.66 *** ftplib.py 16 Feb 2002 23:06:15 -0000 1.65 --- ftplib.py 10 Mar 2002 15:59:58 -0000 1.66 *************** *** 488,493 **** return self.voidcmd('CDUP') except error_perm, msg: ! if msg[:3] != '500': ! raise error_perm, msg elif dirname == '': dirname = '.' # does nothing, but could return error --- 488,493 ---- return self.voidcmd('CDUP') except error_perm, msg: ! if msg.args[0][:3] != '500': ! raise elif dirname == '': dirname = '.' # does nothing, but could return error From jvr@users.sourceforge.net Sun Mar 10 19:28:04 2002 From: jvr@users.sourceforge.net (Just van Rossum) Date: Sun, 10 Mar 2002 11:28:04 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Lib macostools.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Lib In directory usw-pr-cvs1:/tmp/cvs-serv3745 Modified Files: macostools.py Log Message: mkalias() now also works for folders. Fixes bug #515830. Index: macostools.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Lib/macostools.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** macostools.py 21 Jan 2002 23:02:03 -0000 1.13 --- macostools.py 10 Mar 2002 19:28:02 -0000 1.14 *************** *** 35,41 **** else: alias = srcfss.NewAlias() ! srcfinfo = srcfss.GetFInfo() ! ! Res.FSpCreateResFile(dstfss, srcfinfo.Creator, srcfinfo.Type, -1) h = Res.FSpOpenResFile(dstfss, 3) resource = Res.Resource(alias.data) --- 35,45 ---- else: alias = srcfss.NewAlias() ! ! if os.path.isdir(src): ! cr, tp = 'MACS', 'fdrp' ! else: ! cr, tp = srcfss.GetCreatorType() ! ! Res.FSpCreateResFile(dstfss, cr, tp, -1) h = Res.FSpOpenResFile(dstfss, 3) resource = Res.Resource(alias.data) From jackjansen@users.sourceforge.net Sun Mar 10 21:29:57 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Sun, 10 Mar 2002 13:29:57 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Tools/IDE PyDebugger.py,1.8,1.8.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Tools/IDE In directory usw-pr-cvs1:/tmp/cvs-serv32509/Mac/Tools/IDE Modified Files: Tag: release22-maint PyDebugger.py Log Message: Backport of 1.9 (missed last time around): Changes by Donovan Preston (and a few minor ones by me) to make IDE run under MachoPython. Mainly making sure we don't call routines that don't exist and representing pathnames in a os.separator-neutral format. Index: PyDebugger.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Tools/IDE/PyDebugger.py,v retrieving revision 1.8 retrieving revision 1.8.6.1 diff -C2 -d -r1.8 -r1.8.6.1 *** PyDebugger.py 18 Nov 2001 14:12:43 -0000 1.8 --- PyDebugger.py 10 Mar 2002 21:29:55 -0000 1.8.6.1 *************** *** 497,501 **** try: try: ! MacOS.EnableAppswitch(0) if self.quitting: # returning None is not enough, a former BdbQuit exception --- 497,502 ---- try: try: ! if hasattr(MacOS, 'EnableAppswitch'): ! MacOS.EnableAppswitch(0) if self.quitting: # returning None is not enough, a former BdbQuit exception *************** *** 513,517 **** return self.trace_dispatch finally: ! MacOS.EnableAppswitch(-1) except KeyboardInterrupt: self.set_step() --- 514,519 ---- return self.trace_dispatch finally: ! if hasattr(MacOS, 'EnableAppswitch'): ! MacOS.EnableAppswitch(-1) except KeyboardInterrupt: self.set_step() From jackjansen@users.sourceforge.net Sun Mar 10 21:33:21 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Sun, 10 Mar 2002 13:33:21 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Modules/waste wastemodule.c,1.21,1.21.4.1 wastescan.py,1.7,1.7.22.1 wastesupport.py,1.14,1.14.20.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/waste In directory usw-pr-cvs1:/tmp/cvs-serv526 Modified Files: Tag: release22-maint wastemodule.c wastescan.py wastesupport.py Log Message: Backport of 1.22: Use waste included with CW in stead of separate package. (But a truer log message would have been "updated to current version of waste", as in MachoPython we use a normal standalone separate Waste distribution). Index: wastemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/waste/wastemodule.c,v retrieving revision 1.21 retrieving revision 1.21.4.1 diff -C2 -d -r1.21 -r1.21.4.1 *** wastemodule.c 18 Dec 2001 15:36:13 -0000 1.21 --- wastemodule.c 10 Mar 2002 21:33:19 -0000 1.21.4.1 *************** *** 267,270 **** --- 267,294 ---- } + static PyObject *WEOObj_WEGetObjectOwner(WEOObject *_self, PyObject *_args) + { + PyObject *_res = NULL; + WEReference _rv; + if (!PyArg_ParseTuple(_args, "")) + return NULL; + _rv = WEGetObjectOwner(_self->ob_itself); [...2589 lines suppressed...] --- 2425,2443 ---- "() -> None"}, {"WEHandleTSMEvent", (PyCFunction)waste_WEHandleTSMEvent, 1, ! "(AppleEvent inAppleEvent) -> (AppleEvent ioReply)"}, {"WELongPointToPoint", (PyCFunction)waste_WELongPointToPoint, 1, ! "(LongPt inLongPoint) -> (Point outPoint)"}, {"WEPointToLongPoint", (PyCFunction)waste_WEPointToLongPoint, 1, ! "(Point inPoint) -> (LongPt outLongPoint)"}, {"WESetLongRect", (PyCFunction)waste_WESetLongRect, 1, ! "(SInt32 inLeft, SInt32 inTop, SInt32 inRight, SInt32 inBottom) -> (LongRect outLongRect)"}, {"WELongRectToRect", (PyCFunction)waste_WELongRectToRect, 1, ! "(LongRect inLongRect) -> (Rect outRect)"}, {"WERectToLongRect", (PyCFunction)waste_WERectToLongRect, 1, ! "(Rect inRect) -> (LongRect outLongRect)"}, {"WEOffsetLongRect", (PyCFunction)waste_WEOffsetLongRect, 1, ! "(SInt32 inHorizontalOffset, SInt32 inVerticalOffset) -> (LongRect ioLongRect)"}, {"WELongPointInLongRect", (PyCFunction)waste_WELongPointInLongRect, 1, ! "(LongPt inLongPoint, LongRect inLongRect) -> (Boolean _rv)"}, {"STDObjectHandlers", (PyCFunction)waste_STDObjectHandlers, 1, NULL}, Index: wastescan.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/waste/wastescan.py,v retrieving revision 1.7 retrieving revision 1.7.22.1 diff -C2 -d -r1.7 -r1.7.22.1 *** wastescan.py 17 Apr 1998 14:07:55 -0000 1.7 --- wastescan.py 10 Mar 2002 21:33:19 -0000 1.7.22.1 *************** *** 5,12 **** BGENDIR=os.path.join(sys.prefix, ':Tools:bgen:bgen') sys.path.append(BGENDIR) ! from scantools import Scanner_PreUH3 from bgenlocations import MWERKSDIR, TOOLBOXDIR ! WASTEDIR=":::::Waste 1.3 Distribution:WASTE C/C++ Headers:" OBJECT = "TEHandle" --- 5,13 ---- BGENDIR=os.path.join(sys.prefix, ':Tools:bgen:bgen') sys.path.append(BGENDIR) ! from scantools import Scanner from bgenlocations import MWERKSDIR, TOOLBOXDIR ! #WASTEDIR=":::::Waste 1.3 Distribution:WASTE C/C++ Headers:" ! WASTEDIR=MWERKSDIR + 'MacOS Support:(Third Party Support):Waste 2.0 Distribution:C_C++ Headers:' OBJECT = "TEHandle" *************** *** 27,31 **** print "=== Done. It's up to you to compile it now! ===" ! class MyScanner(Scanner_PreUH3): def destination(self, type, name, arglist): --- 28,33 ---- print "=== Done. It's up to you to compile it now! ===" ! #class MyScanner(Scanner_PreUH3): ! class MyScanner(Scanner): def destination(self, type, name, arglist): *************** *** 53,56 **** --- 55,60 ---- "WEGetInfo", "WEVersion", # Unfortunately... + "WEPut", # XXXX TBD: needs array of flavortypes. + "WEGetOneAttribute", # XXXX TBD: output buffer ] *************** *** 61,64 **** --- 65,96 ---- "WEFontIDToNameUPP", "WEFontNameToIDUPP", + "WEClickLoopUPP", + "WEScrollUPP", + "WETSMPreUpdateUPP", + "WETSMPostUpdateUPP", + "WEPreTrackDragUPP", + "WETranslateDragUPP", + "WEHiliteDropAreaUPP", + "WEDrawTextUPP", + "WEDrawTSMHiliteUPP", + "WEPixelToCharUPP", + "WECharToPixelUPP", + "WELineBreakUPP", + "WEWordBreakUPP", + "WECharByteUPP", + "WECharTypeUPP", + "WEEraseUPP", + "WEFluxUPP", + "WENewObjectUPP", + "WEDisposeObjectUPP", + "WEDrawObjectUPP", + "WEClickObjectUPP", + "WEStreamObjectUPP", + "WEHoverObjectUPP", + "WERuler", # XXXX To be done + "WERuler_ptr", # ditto + "WEParaInfo", # XXXX To be done + "WEPrintSession", # XXXX To be done + "WEPrintOptions_ptr", # XXXX To be done ] *************** *** 69,90 **** # WEContinuousStyle ! ([("WEStyleMode", "mode", "OutMode"), ("TextStyle", "ts", "OutMode")], ! [("WEStyleMode", "mode", "InOutMode"), ("TextStyle", "ts", "OutMode")]), # WECopyRange ! ([('Handle', 'hText', 'InMode'), ('StScrpHandle', 'hStyles', 'InMode'), ! ('WESoupHandle', 'hSoup', 'InMode')], ! [('OptHandle', 'hText', 'InMode'), ('OptStScrpHandle', 'hStyles', 'InMode'), ! ('OptSoupHandle', 'hSoup', 'InMode')]), # WEInsert ! ([('StScrpHandle', 'hStyles', 'InMode'), ('WESoupHandle', 'hSoup', 'InMode')], ! [('OptStScrpHandle', 'hStyles', 'InMode'), ('OptSoupHandle', 'hSoup', 'InMode')]), # WEGetObjectOwner ("WEGetObjectOwner", [('WEReference', '*', 'ReturnMode')], ! [('ExistingWEReference', '*', 'ReturnMode')]) ! ] --- 101,129 ---- # WEContinuousStyle ! ([("WEStyleMode", "ioMode", "OutMode"), ("TextStyle", "outTextStyle", "OutMode")], ! [("WEStyleMode", "*", "InOutMode"), ("TextStyle", "*", "*")]), # WECopyRange ! ([('Handle', 'outText', 'InMode'), ('StScrpHandle', 'outStyles', 'InMode'), ! ('WESoupHandle', 'outSoup', 'InMode')], ! [('OptHandle', '*', '*'), ('OptStScrpHandle', '*', '*'), ! ('OptSoupHandle', '*', '*')]), # WEInsert ! ([('StScrpHandle', 'inStyles', 'InMode'), ('WESoupHandle', 'inSoup', 'InMode')], ! [('OptStScrpHandle', '*', '*'), ('OptSoupHandle', '*', '*')]), # WEGetObjectOwner ("WEGetObjectOwner", [('WEReference', '*', 'ReturnMode')], ! [('ExistingWEReference', '*', 'ReturnMode')]), ! ! # WEFindParagraph ! ([("char_ptr", "inKey", "InMode")], ! [("stringptr", "*", "*")]), ! ! # WESetOneAttribute ! ([("void_ptr", "*", "InMode"), ("ByteCount", "*", "InMode")], ! [("InBuffer", "*", "*")]), ] Index: wastesupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/waste/wastesupport.py,v retrieving revision 1.14 retrieving revision 1.14.20.1 diff -C2 -d -r1.14 -r1.14.20.1 *** wastesupport.py 20 Jun 2001 21:21:07 -0000 1.14 --- wastesupport.py 10 Mar 2002 21:33:19 -0000 1.14.20.1 *************** *** 37,40 **** --- 37,41 ---- WEStyleMode = Type("WEStyleMode", "H") + WERulerMode = Type("WERulerMode", "l") WEActionKind = Type("WEActionKind", "h") WEAlignment = Type("WEAlignment", "B") *************** *** 55,58 **** --- 56,62 ---- LongRect = OpaqueType("LongRect", "LongRect") LongRect_ptr = LongRect + + TextEncodingVariant = Type("TextEncodingVariant", "l") + TextEncodingFormat = Type("TextEncodingFormat", "l") includestuff = includestuff + """ From gvanrossum@users.sourceforge.net Mon Mar 11 00:07:15 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 10 Mar 2002 16:07:15 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.116,1.117 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv4829 Modified Files: test_descr.py Log Message: Bugfix candidate. Adapter from SF patch 528038; fixes SF bug 527816. The wrapper for __nonzero__ should be wrap_inquiry rather than wrap_unaryfunc, since the slot returns an int, not a PyObject *. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.116 retrieving revision 1.117 diff -C2 -d -r1.116 -r1.117 *** test_descr.py 2 Mar 2002 04:18:04 -0000 1.116 --- test_descr.py 11 Mar 2002 00:07:13 -0000 1.117 *************** *** 427,430 **** --- 427,433 ---- if verbose: print "Testing int operations..." numops(100, 3) + # The following crashes in Python 2.2 + vereq((1).__nonzero__(), 1) + vereq((0).__nonzero__(), 0) def longs(): From tim_one@users.sourceforge.net Mon Mar 11 00:24:02 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Mar 2002 16:24:02 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_largefile.py,1.12,1.13 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv6297/python/Lib/test Modified Files: test_largefile.py Log Message: file_truncate(): provide full "large file" support on Windows, by dropping MS's inadequate _chsize() function. This was inspired by SF patch 498109 ("fileobject truncate support for win32"), which I rejected. libstdtypes.tex: Someone who knows should update the availability blurb. For example, if it's available on Linux, it would be good to say so. test_largefile: Uncommented the file.truncate() tests, and reworked to do more. The old comment about "permission errors" in the truncation tests under Windows was almost certainly due to that the file wasn't open for *write* access at this point, so of course MS wouldn't let you truncate it. I'd be appalled if a Unixish system did. CAUTION: Someone should run this test on Linux (etc) too. The truncation part was commented out before. Note that test_largefile isn't run by default. Index: test_largefile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_largefile.py,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** test_largefile.py 11 Dec 2001 17:57:26 -0000 1.12 --- test_largefile.py 11 Mar 2002 00:24:00 -0000 1.13 *************** *** 129,147 **** f.close() ! ! # XXX add tests for truncate if it exists ! # XXX has truncate ever worked on Windows? specifically on WinNT I get: ! # "IOError: [Errno 13] Permission denied" ! ##try: ! ## newsize = size - 10 ! ## f.seek(newsize) ! ## f.truncate() ! ## expect(f.tell(), newsize) ! ## newsize = newsize - 1 ! ## f.seek(0) ! ## f.truncate(newsize) ! ## expect(f.tell(), newsize) ! ##except AttributeError: ! ## pass os.unlink(name) --- 129,156 ---- f.close() ! if hasattr(f, 'truncate'): ! if test_support.verbose: ! print 'try truncate' ! f = open(name, 'r+b') ! f.seek(0, 2) ! expect(f.tell(), size+1) ! # Cut it back via seek + truncate with no argument. ! newsize = size - 10 ! f.seek(newsize) ! f.truncate() ! expect(f.tell(), newsize) ! # Ensure that truncate(bigger than true size) doesn't grow the file. ! f.truncate(size) ! expect(f.tell(), newsize) ! # Ensure that truncate(smaller than true size) shrinks the file. ! newsize -= 1 ! f.seek(0) ! f.truncate(newsize) ! expect(f.tell(), newsize) ! # cut it waaaaay back ! f.truncate(1) ! f.seek(0) ! expect(len(f.read()), 1) ! f.close() os.unlink(name) From tim_one@users.sourceforge.net Mon Mar 11 00:24:02 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Mar 2002 16:24:02 -0800 Subject: [Python-checkins] CVS: python/dist/src/Misc NEWS,1.360,1.361 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory usw-pr-cvs1:/tmp/cvs-serv6297/python/Misc Modified Files: NEWS Log Message: file_truncate(): provide full "large file" support on Windows, by dropping MS's inadequate _chsize() function. This was inspired by SF patch 498109 ("fileobject truncate support for win32"), which I rejected. libstdtypes.tex: Someone who knows should update the availability blurb. For example, if it's available on Linux, it would be good to say so. test_largefile: Uncommented the file.truncate() tests, and reworked to do more. The old comment about "permission errors" in the truncation tests under Windows was almost certainly due to that the file wasn't open for *write* access at this point, so of course MS wouldn't let you truncate it. I'd be appalled if a Unixish system did. CAUTION: Someone should run this test on Linux (etc) too. The truncation part was commented out before. Note that test_largefile isn't run by default. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.360 retrieving revision 1.361 diff -C2 -d -r1.360 -r1.361 *** NEWS 3 Mar 2002 21:30:27 -0000 1.360 --- NEWS 11 Mar 2002 00:24:00 -0000 1.361 *************** *** 74,78 **** to stop Python development. Thanks for all the fish! ! - Some of us don't like fish, so we changed Python's magic number scheme to a new one. See Python/import.c for details. --- 74,78 ---- to stop Python development. Thanks for all the fish! ! - Some of us don't like fish, so we changed Python's magic number scheme to a new one. See Python/import.c for details. *************** *** 84,87 **** --- 84,91 ---- Windows + + - file.truncate([newsize]) now works on Windows for all newsize values. + It used to fail if newsize didn't fit in 32 bits, reflecting a + limitation of MS _chsize (which is no longer used). - os.waitpid() is now implemented for Windows, and can be used to block From tim_one@users.sourceforge.net Mon Mar 11 00:24:02 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Mar 2002 16:24:02 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libstdtypes.tex,1.81,1.82 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv6297/python/Doc/lib Modified Files: libstdtypes.tex Log Message: file_truncate(): provide full "large file" support on Windows, by dropping MS's inadequate _chsize() function. This was inspired by SF patch 498109 ("fileobject truncate support for win32"), which I rejected. libstdtypes.tex: Someone who knows should update the availability blurb. For example, if it's available on Linux, it would be good to say so. test_largefile: Uncommented the file.truncate() tests, and reworked to do more. The old comment about "permission errors" in the truncation tests under Windows was almost certainly due to that the file wasn't open for *write* access at this point, so of course MS wouldn't let you truncate it. I'd be appalled if a Unixish system did. CAUTION: Someone should run this test on Linux (etc) too. The truncation part was commented out before. Note that test_largefile isn't run by default. Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.81 retrieving revision 1.82 diff -C2 -d -r1.81 -r1.82 *** libstdtypes.tex 26 Dec 2001 20:06:40 -0000 1.81 --- libstdtypes.tex 11 Mar 2002 00:24:00 -0000 1.82 *************** *** 1155,1161 **** Truncate the file's size. If the optional \var{size} argument present, the file is truncated to (at most) that size. The size ! defaults to the current position. Availability of this function ! depends on the operating system version (for example, not all ! \UNIX{} versions support this operation). \end{methoddesc} --- 1155,1160 ---- Truncate the file's size. If the optional \var{size} argument present, the file is truncated to (at most) that size. The size ! defaults to the current position. ! Availability: Windows, many \UNIX variants. \end{methoddesc} From tim_one@users.sourceforge.net Mon Mar 11 00:24:02 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Sun, 10 Mar 2002 16:24:02 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects fileobject.c,2.144,2.145 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv6297/python/Objects Modified Files: fileobject.c Log Message: file_truncate(): provide full "large file" support on Windows, by dropping MS's inadequate _chsize() function. This was inspired by SF patch 498109 ("fileobject truncate support for win32"), which I rejected. libstdtypes.tex: Someone who knows should update the availability blurb. For example, if it's available on Linux, it would be good to say so. test_largefile: Uncommented the file.truncate() tests, and reworked to do more. The old comment about "permission errors" in the truncation tests under Windows was almost certainly due to that the file wasn't open for *write* access at this point, so of course MS wouldn't let you truncate it. I'd be appalled if a Unixish system did. CAUTION: Someone should run this test on Linux (etc) too. The truncation part was commented out before. Note that test_largefile isn't run by default. Index: fileobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v retrieving revision 2.144 retrieving revision 2.145 diff -C2 -d -r2.144 -r2.145 *** fileobject.c 26 Feb 2002 11:36:35 -0000 2.144 --- fileobject.c 11 Mar 2002 00:24:00 -0000 2.145 *************** *** 11,16 **** #ifdef MS_WIN32 #define fileno _fileno ! /* can (almost fully) duplicate with _chsize, see file_truncate */ #define HAVE_FTRUNCATE #endif --- 11,18 ---- #ifdef MS_WIN32 #define fileno _fileno ! /* can simulate truncate with Win32 API functions; see file_truncate */ #define HAVE_FTRUNCATE + #define WINDOWS_LEAN_AND_MEAN + #include #endif *************** *** 380,383 **** --- 382,388 ---- if (!PyArg_ParseTuple(args, "|O:truncate", &newsizeobj)) return NULL; + + /* Set newsize to current postion if newsizeobj NULL, else to the + specified value. */ if (newsizeobj != NULL) { #if !defined(HAVE_LARGEFILE_SUPPORT) *************** *** 390,424 **** if (PyErr_Occurred()) return NULL; ! } else { ! /* Default to current position*/ Py_BEGIN_ALLOW_THREADS errno = 0; newsize = _portable_ftell(f->f_fp); Py_END_ALLOW_THREADS ! if (newsize == -1) { ! PyErr_SetFromErrno(PyExc_IOError); ! clearerr(f->f_fp); ! return NULL; ! } } Py_BEGIN_ALLOW_THREADS errno = 0; ret = fflush(f->f_fp); Py_END_ALLOW_THREADS ! if (ret != 0) goto onioerror; #ifdef MS_WIN32 ! /* can use _chsize; if, however, the newsize overflows 32-bits then ! _chsize is *not* adequate; in this case, an OverflowError is raised */ ! if (newsize > LONG_MAX) { ! PyErr_SetString(PyExc_OverflowError, ! "the new size is too long for _chsize (it is limited to 32-bit values)"); ! return NULL; ! } else { ! Py_BEGIN_ALLOW_THREADS errno = 0; ! ret = _chsize(fileno(f->f_fp), (long)newsize); ! Py_END_ALLOW_THREADS ! if (ret != 0) goto onioerror; } #else --- 395,459 ---- if (PyErr_Occurred()) return NULL; ! } ! else { ! /* Default to current position. */ Py_BEGIN_ALLOW_THREADS errno = 0; newsize = _portable_ftell(f->f_fp); Py_END_ALLOW_THREADS ! if (newsize == -1) ! goto onioerror; } + + /* Flush the file. */ Py_BEGIN_ALLOW_THREADS errno = 0; ret = fflush(f->f_fp); Py_END_ALLOW_THREADS ! if (ret != 0) ! goto onioerror; #ifdef MS_WIN32 ! /* MS _chsize doesn't work if newsize doesn't fit in 32 bits, ! so don't even try using it. truncate() should never grow the ! file, but MS SetEndOfFile will grow a file, so we need to ! compare the specified newsize to the actual size. Some ! optimization could be done here when newsizeobj is NULL. */ ! { ! Py_off_t currentEOF; /* actual size */ ! HANDLE hFile; ! int error; ! ! /* First move to EOF, and set currentEOF to the size. */ errno = 0; ! if (_portable_fseek(f->f_fp, 0, SEEK_END) != 0) ! goto onioerror; ! errno = 0; ! currentEOF = _portable_ftell(f->f_fp); ! if (currentEOF == -1) ! goto onioerror; ! ! if (newsize > currentEOF) ! newsize = currentEOF; /* never grow the file */ ! ! /* Move to newsize, and truncate the file there. */ ! if (newsize != currentEOF) { ! errno = 0; ! if (_portable_fseek(f->f_fp, newsize, SEEK_SET) != 0) ! goto onioerror; ! Py_BEGIN_ALLOW_THREADS ! errno = 0; ! hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp)); ! error = hFile == (HANDLE)-1; ! if (!error) { ! error = SetEndOfFile(hFile) == 0; ! if (error) ! errno = EACCES; ! } ! Py_END_ALLOW_THREADS ! if (error) ! goto onioerror; ! } ! } #else From gvanrossum@users.sourceforge.net Mon Mar 11 01:05:34 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Sun, 10 Mar 2002 17:05:34 -0800 Subject: [Python-checkins] CVS: python/dist/src README,1.140,1.141 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv15827 Modified Files: README Log Message: Update version number in README. Index: README =================================================================== RCS file: /cvsroot/python/python/dist/src/README,v retrieving revision 1.140 retrieving revision 1.141 diff -C2 -d -r1.140 -r1.141 *** README 27 Feb 2002 13:29:45 -0000 1.140 --- README 11 Mar 2002 01:05:32 -0000 1.141 *************** *** 1,3 **** ! This is Python version 2.2 ========================== --- 1,3 ---- ! This is Python version 2.3 (pre-alpha) ========================== From loewis@users.sourceforge.net Mon Mar 11 06:46:54 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Sun, 10 Mar 2002 22:46:54 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib gzip.py,1.28,1.29 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv22818 Modified Files: gzip.py Log Message: Patch #443899: Check modes on files before performing operations. Use IOErrors where file objects use them. Index: gzip.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/gzip.py,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** gzip.py 13 Oct 2001 18:33:51 -0000 1.28 --- gzip.py 11 Mar 2002 06:46:52 -0000 1.29 *************** *** 62,66 **** 0) else: ! raise ValueError, "Mode " + mode + " not supported" self.fileobj = fileobj --- 62,66 ---- 0) else: ! raise IOError, "Mode " + mode + " not supported" self.fileobj = fileobj *************** *** 134,137 **** --- 134,141 ---- def write(self,data): + if self.mode != WRITE: + import errno + raise IOError(errno.EBADF, "write() on read-only GzipFile object") + if self.fileobj is None: raise ValueError, "write() on closed GzipFile object" *************** *** 143,146 **** --- 147,154 ---- def read(self, size=-1): + if self.mode != READ: + import errno + raise IOError(errno.EBADF, "write() on read-only GzipFile object") + if self.extrasize <= 0 and self.fileobj is None: return '' From sjoerd@users.sourceforge.net Mon Mar 11 09:20:50 2002 From: sjoerd@users.sourceforge.net (Sjoerd Mullender) Date: Mon, 11 Mar 2002 01:20:50 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules zlibmodule.c,2.57,2.58 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv24247 Modified Files: zlibmodule.c Log Message: Changed C++ comment into standard comment. Index: zlibmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/zlibmodule.c,v retrieving revision 2.57 retrieving revision 2.58 diff -C2 -d -r2.57 -r2.58 *** zlibmodule.c 8 Dec 2001 18:02:58 -0000 2.57 --- zlibmodule.c 11 Mar 2002 09:20:47 -0000 2.58 *************** *** 882,885 **** #ifdef WITH_THREAD zlib_lock = PyThread_allocate_lock(); ! #endif // WITH_THREAD } --- 882,885 ---- #ifdef WITH_THREAD zlib_lock = PyThread_allocate_lock(); ! #endif /* WITH_THREAD */ } From mwh@users.sourceforge.net Mon Mar 11 10:02:20 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:02:20 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules cStringIO.c,2.32,2.32.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv1399 Modified Files: Tag: release22-maint cStringIO.c Log Message: backport jhylton's checkin of revision 2.33 of cStringIO.c Fix SF bug #526518 The doc string for cStringIO suggested that str() of a StringIO object was equivalent to getvalue(). This was never true, so repair the doc string. (doctest would have helped here.) Bug fix candidate for any past versions. Index: cStringIO.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/cStringIO.c,v retrieving revision 2.32 retrieving revision 2.32.6.1 diff -C2 -d -r2.32 -r2.32.6.1 *** cStringIO.c 8 Dec 2001 18:02:56 -0000 2.32 --- cStringIO.c 11 Mar 2002 10:02:18 -0000 2.32.6.1 *************** *** 68,72 **** " an_output_stream.write(some_stuff)\n" " ...\n" ! " value=an_output_stream.getvalue() # str(an_output_stream) works too!\n" "\n" " an_input_stream=StringIO(a_string)\n" --- 68,72 ---- " an_output_stream.write(some_stuff)\n" " ...\n" ! " value=an_output_stream.getvalue()\n" "\n" " an_input_stream=StringIO(a_string)\n" From mwh@users.sourceforge.net Mon Mar 11 10:04:09 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:04:09 -0800 Subject: [Python-checkins] CVS: python/dist/src/Tools/webchecker webchecker.py,1.25,1.25.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/webchecker In directory usw-pr-cvs1:/tmp/cvs-serv1787 Modified Files: Tag: release22-maint webchecker.py Log Message: I presume most of the fixes currently hitting the tree should go into 2.2.1, but it would be nice if people remembered to comment on their fixes' applicability! backport akuchling's checkin of revision 1.26 of webchecker.py [Bug #512799] urllib.splittype() returns a 2-tuple. (Reported by seb bacon) Index: webchecker.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/webchecker/webchecker.py,v retrieving revision 1.25 retrieving revision 1.25.6.1 diff -C2 -d -r1.25 -r1.25.6.1 *** webchecker.py 11 Dec 2001 22:41:24 -0000 1.25 --- webchecker.py 11 Mar 2002 10:04:07 -0000 1.25.6.1 *************** *** 482,486 **** return self.name_table[url] ! scheme = urllib.splittype(url) if scheme in ('mailto', 'news', 'javascript', 'telnet'): self.note(1, " Not checking %s URL" % scheme) --- 482,486 ---- return self.name_table[url] ! scheme, path = urllib.splittype(url) if scheme in ('mailto', 'news', 'javascript', 'telnet'): self.note(1, " Not checking %s URL" % scheme) From mwh@users.sourceforge.net Mon Mar 11 10:05:09 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:05:09 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libxmlrpclib.tex,1.5,1.5.10.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv1974 Modified Files: Tag: release22-maint libxmlrpclib.tex Log Message: backport akuchling's checkin of revision 1.6 of libxmlrpclib.tex [Bug #486527] Note that the caller has to ensure there are no control characters in strings being passed via XML-RPC. Fix some typos. 2.2.1 bugfix candidate. Index: libxmlrpclib.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libxmlrpclib.tex,v retrieving revision 1.5 retrieving revision 1.5.10.1 diff -C2 -d -r1.5 -r1.5.10.1 *** libxmlrpclib.tex 1 Oct 2001 21:05:30 -0000 1.5 --- libxmlrpclib.tex 11 Mar 2002 10:05:07 -0000 1.5.10.1 *************** *** 60,63 **** --- 60,73 ---- XML-RPC server errors, or \exception{ProtocolError} used to signal an error in the HTTP/HTTPS transport layer. + + When passing strings, characters special to XML such as \samp{<}, + \samp{>}, and \samp{\&} will be automatically escaped. However, it's + the caller's responsibility to ensure that the string is free of + characters that aren't allowed in XML, such as the control characters + with ASCII values between 0 and 31; failing to do this will result in + an XML-RPC request that isn't well-formed XML. If you have to pass + arbitrary strings via XML-RPC, use the \class{Binary} wrapper class + described below. + \end{classdesc} *************** *** 201,205 **** \begin{memberdesc}{url} ! The URI or URL that triggered te error. \end{memberdesc} --- 211,215 ---- \begin{memberdesc}{url} ! The URI or URL that triggered the error. \end{memberdesc} *************** *** 209,213 **** \begin{memberdesc}{errmsg} ! The eror message of diagnostic string. \end{memberdesc} --- 219,223 ---- \begin{memberdesc}{errmsg} ! The error message or diagnostic string. \end{memberdesc} From mwh@users.sourceforge.net Mon Mar 11 10:06:38 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:06:38 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib httplib.py,1.42.10.1,1.42.10.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv2294 Modified Files: Tag: release22-maint httplib.py Log Message: backport jhylton's checkin of revision 1.45 of httplib.py SF bug report #405939: wrong Host header with proxy In August, Greg said this looked good, so I'm going ahead with it. The fix is different from the one in the bug report. Instead of using a regular expression to extract the host from the url, I use urlparse.urlsplit. Martin commented that the patch doesn't address URLs that have basic authentication username and password in the header. I don't see any code anywhere in httplib that supports this feature, so I'm not going to address it for this fix. Bug fix candidate. Index: httplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/httplib.py,v retrieving revision 1.42.10.1 retrieving revision 1.42.10.2 diff -C2 -d -r1.42.10.1 -r1.42.10.2 *** httplib.py 16 Feb 2002 23:08:24 -0000 1.42.10.1 --- httplib.py 11 Mar 2002 10:06:36 -0000 1.42.10.2 *************** *** 70,73 **** --- 70,74 ---- import mimetools import socket + from urlparse import urlsplit try: *************** *** 468,474 **** # as Apache) barf when they see two Host: headers ! # if we need a non-standard port,include it in the header ! if self.port == HTTP_PORT: ! self.putheader('Host', self.host) else: self.putheader('Host', "%s:%s" % (self.host, self.port)) --- 469,481 ---- # as Apache) barf when they see two Host: headers ! # If we need a non-standard port,include it in the header. ! # If the request is going through a proxy, but the host of ! # the actual URL, not the host of the proxy. ! ! if url.startswith('http:'): ! nil, netloc, nil, nil, nil = urlsplit(url) ! self.putheader('Host', netloc) ! elif self.port == HTTP_PORT: ! self.putheader('Host', netloc) else: self.putheader('Host', "%s:%s" % (self.host, self.port)) *************** *** 857,860 **** --- 864,878 ---- print print h.getfile().read() + + # minimal test that code to extract host from url works + class HTTP11(HTTP): + _http_vsn = 11 + _http_vsn_str = 'HTTP/1.1' + + h = HTTP11('www.python.org') + h.putrequest('GET', 'http://www.python.org/~jeremy/') + h.endheaders() + h.getreply() + h.close() if hasattr(socket, 'ssl'): From mwh@users.sourceforge.net Mon Mar 11 10:11:48 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:11:48 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.93.6.1,2.93.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv3490 Modified Files: Tag: release22-maint abstract.c Log Message: backport jhylton's checkin of revision 2.97 of abstract.c Fix for SF bug 516727: MyInt(2) + "3" -> NotImplemented PyNumber_Add() tries the nb_add slot first, then falls back to sq_concat. However, it didn't check the return value of sq_concat. If sq_concat returns NotImplemented, raise the standard TypeError. Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.93.6.1 retrieving revision 2.93.6.2 diff -C2 -d -r2.93.6.1 -r2.93.6.2 *** abstract.c 5 Jan 2002 10:52:38 -0000 2.93.6.1 --- abstract.c 11 Mar 2002 10:11:46 -0000 2.93.6.2 *************** *** 606,614 **** if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; ! Py_DECREF(Py_NotImplemented); ! if (m && m->sq_concat) { result = (*m->sq_concat)(v, w); ! } ! else { PyErr_Format( PyExc_TypeError, --- 606,613 ---- if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; ! Py_DECREF(result); ! if (m && m->sq_concat) result = (*m->sq_concat)(v, w); ! if (result == Py_NotImplemented) { PyErr_Format( PyExc_TypeError, From mwh@users.sourceforge.net Mon Mar 11 10:13:01 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:13:01 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.93.6.2,2.93.6.3 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv3846 Modified Files: Tag: release22-maint abstract.c Log Message: Probably should have merged the two checkins to this file (oh well). backport jhylton's checkin of revision 2.98 of abstract.c Fix leak of NotImplemented in previous checkin to PyNumber_Add(). If result == Py_NotImplemented, always DECREF it before assigning a new value to result. Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.93.6.2 retrieving revision 2.93.6.3 diff -C2 -d -r2.93.6.2 -r2.93.6.3 *** abstract.c 11 Mar 2002 10:11:46 -0000 2.93.6.2 --- abstract.c 11 Mar 2002 10:12:58 -0000 2.93.6.3 *************** *** 606,619 **** if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; ! Py_DECREF(result); ! if (m && m->sq_concat) result = (*m->sq_concat)(v, w); if (result == Py_NotImplemented) { ! PyErr_Format( PyExc_TypeError, "unsupported operand types for +: '%s' and '%s'", v->ob_type->tp_name, w->ob_type->tp_name); ! result = NULL; } } --- 606,621 ---- if (result == Py_NotImplemented) { PySequenceMethods *m = v->ob_type->tp_as_sequence; ! if (m && m->sq_concat) { ! Py_DECREF(result); result = (*m->sq_concat)(v, w); + } if (result == Py_NotImplemented) { ! Py_DECREF(result); ! PyErr_Format( PyExc_TypeError, "unsupported operand types for +: '%s' and '%s'", v->ob_type->tp_name, w->ob_type->tp_name); ! result = NULL; } } From mwh@users.sourceforge.net Mon Mar 11 10:14:25 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:14:25 -0800 Subject: [Python-checkins] CVS: python/dist/src configure.in,1.288.6.3,1.288.6.4 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv4169 Modified Files: Tag: release22-maint configure.in Log Message: backport jhylton's checkin of revision 1.295 of configure.in Add fix for AIX as reported by srubben in SF bug #477487. Untested, of course. Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.288.6.3 retrieving revision 1.288.6.4 diff -C2 -d -r1.288.6.3 -r1.288.6.4 *** configure.in 8 Mar 2002 14:11:18 -0000 1.288.6.3 --- configure.in 11 Mar 2002 10:14:23 -0000 1.288.6.4 *************** *** 293,297 **** case $ac_sys_system in AIX*) ! LINKCC="\$(srcdir)/Modules/makexp_aix Modules/python.exp \"\" \$(LIBRARY); $(LINKCC)";; dgux*) LINKCC="LD_RUN_PATH=$libdir $(LINKCC)";; --- 293,297 ---- case $ac_sys_system in AIX*) ! LINKCC="\$(srcdir)/Modules/makexp_aix Modules/python.exp \"\" \$(LIBRARY); $LINKCC";; dgux*) LINKCC="LD_RUN_PATH=$libdir $(LINKCC)";; From mwh@users.sourceforge.net Mon Mar 11 10:15:02 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:15:02 -0800 Subject: [Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.246.4.1,2.246.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory usw-pr-cvs1:/tmp/cvs-serv4314 Modified Files: Tag: release22-maint bltinmodule.c Log Message: backport tim_one's checkin of revision 2.248 of bltinmodule.c Docstring for filter(): Someone on the Tutor list reasonably complained that it didn't tell enough of the truth. Bugfix candidate (I guess -- it helps and it's harmless). Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.246.4.1 retrieving revision 2.246.4.2 diff -C2 -d -r2.246.4.1 -r2.246.4.2 *** bltinmodule.c 12 Jan 2002 11:13:24 -0000 2.246.4.1 --- bltinmodule.c 11 Mar 2002 10:15:00 -0000 2.246.4.2 *************** *** 248,256 **** static char filter_doc[] = ! "filter(function, sequence) -> list\n\ ! \n\ ! Return a list containing those items of sequence for which function(item)\n\ ! is true. If function is None, return a list of items that are true."; ! static PyObject * --- 248,256 ---- static char filter_doc[] = ! "filter(function or None, sequence) -> list, tuple, or string\n" ! "\n" ! "Return those items of sequence for which function(item) is true. If\n" ! "function is None, return the items that are true. If sequence is a tuple\n" ! "or string, return the same type, else return a list."; static PyObject * From mwh@users.sourceforge.net Mon Mar 11 10:16:25 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:16:25 -0800 Subject: [Python-checkins] CVS: python/dist/src/Include pyport.h,2.40.8.1,2.40.8.2 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory usw-pr-cvs1:/tmp/cvs-serv4672 Modified Files: Tag: release22-maint pyport.h Log Message: This has been declared to work. backport tim_one's checkin of revision 2.45 of pyport.h SF bug 525705: [2.2] underflow raise OverflowException. Another year in the quest to out-guess random C behavior. Added macros Py_ADJUST_ERANGE1(X) and Py_ADJUST_ERANGE2(X, Y). The latter is useful for functions with complex results. Two corrections to errno- after-libm-call are attempted: 1. If the platform set errno to ERANGE due to underflow, clear errno. Some unknown subset of libm versions and link options do this. It's allowed by C89, but I never figured anyone would do it. 2. If the platform did not set errno but overflow occurred, force errno to ERANGE. C89 required setting errno to ERANGE, but C99 doesn't. Some unknown subset of libm versions and link options do it the C99 way now. Bugfix candidate, but hold off until some Linux people actually try it, with and without -lieee. I'll send a help plea to Python-Dev. Index: pyport.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pyport.h,v retrieving revision 2.40.8.1 retrieving revision 2.40.8.2 diff -C2 -d -r2.40.8.1 -r2.40.8.2 *** pyport.h 5 Mar 2002 14:24:45 -0000 2.40.8.1 --- pyport.h 11 Mar 2002 10:16:23 -0000 2.40.8.2 *************** *** 286,289 **** --- 286,324 ---- } while(0) + /* Py_ADJUST_ERANGE1(x) + * Py_ADJUST_ERANGE2(x, y) + * Set errno to 0 before calling a libm function, and invoke one of these + * macros after, passing the function result(s) (Py_ADJUST_ERANGE2 is useful + * for functions returning complex results). This makes two kinds of + * adjustments to errno: (A) If it looks like the platform libm set + * errno=ERANGE due to underflow, clear errno. (B) If it looks like the + * platform libm overflowed but didn't set errno, force errno to ERANGE. In + * effect, we're trying to force a useful implementation of C89 errno + * behavior. + * Caution: + * This isn't reliable. See Py_OVERFLOWED comments. + * X and Y may be evaluated more than once. + */ + #define Py_ADJUST_ERANGE1(X) \ + do { \ + if (errno == 0) { \ + if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL) \ + errno = ERANGE; \ + } \ + else if (errno == ERANGE && (X) == 0.0) \ + errno = 0; \ + } while(0) + + #define Py_ADJUST_ERANGE2(X, Y) \ + do { \ + if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL || \ + (Y) == Py_HUGE_VAL || (Y) == -Py_HUGE_VAL) { \ + if (errno == 0) \ + errno = ERANGE; \ + } \ + else if (errno == ERANGE) \ + errno = 0; \ + } while(0) + /************************************************************************** Prototypes that are missing from the standard include files on some systems From mwh@users.sourceforge.net Mon Mar 11 10:16:49 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:16:49 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules cmathmodule.c,2.27,2.27.14.1 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv4754 Modified Files: Tag: release22-maint cmathmodule.c Log Message: backport tim_one's checkin of revision 2.28 of cmathmodule.c SF bug 525705: [2.2] underflow raise OverflowException. Another year in the quest to out-guess random C behavior. Added macros Py_ADJUST_ERANGE1(X) and Py_ADJUST_ERANGE2(X, Y). The latter is useful for functions with complex results. Two corrections to errno- after-libm-call are attempted: 1. If the platform set errno to ERANGE due to underflow, clear errno. Some unknown subset of libm versions and link options do this. It's allowed by C89, but I never figured anyone would do it. 2. If the platform did not set errno but overflow occurred, force errno to ERANGE. C89 required setting errno to ERANGE, but C99 doesn't. Some unknown subset of libm versions and link options do it the C99 way now. Bugfix candidate, but hold off until some Linux people actually try it, with and without -lieee. I'll send a help plea to Python-Dev. Index: cmathmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/cmathmodule.c,v retrieving revision 2.27 retrieving revision 2.27.14.1 diff -C2 -d -r2.27 -r2.27.14.1 *** cmathmodule.c 6 Sep 2001 08:16:17 -0000 2.27 --- cmathmodule.c 11 Mar 2002 10:16:47 -0000 2.27.14.1 *************** *** 338,343 **** x = (*func)(x); PyFPE_END_PROTECT(x) ! Py_SET_ERANGE_IF_OVERFLOW(x.real); ! Py_SET_ERANGE_IF_OVERFLOW(x.imag); if (errno != 0) return math_error(); --- 338,342 ---- x = (*func)(x); PyFPE_END_PROTECT(x) ! Py_ADJUST_ERANGE2(x.real, x.imag); if (errno != 0) return math_error(); From mwh@users.sourceforge.net Mon Mar 11 10:17:20 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:17:20 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects floatobject.c,2.110,2.110.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv4900 Modified Files: Tag: release22-maint floatobject.c Log Message: backport tim_one's checkin of revision 2.111 of floatobject.c SF bug 525705: [2.2] underflow raise OverflowException. Another year in the quest to out-guess random C behavior. Added macros Py_ADJUST_ERANGE1(X) and Py_ADJUST_ERANGE2(X, Y). The latter is useful for functions with complex results. Two corrections to errno- after-libm-call are attempted: 1. If the platform set errno to ERANGE due to underflow, clear errno. Some unknown subset of libm versions and link options do this. It's allowed by C89, but I never figured anyone would do it. 2. If the platform did not set errno but overflow occurred, force errno to ERANGE. C89 required setting errno to ERANGE, but C99 doesn't. Some unknown subset of libm versions and link options do it the C99 way now. Bugfix candidate, but hold off until some Linux people actually try it, with and without -lieee. I'll send a help plea to Python-Dev. Index: floatobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/floatobject.c,v retrieving revision 2.110 retrieving revision 2.110.6.1 diff -C2 -d -r2.110 -r2.110.6.1 *** floatobject.c 11 Dec 2001 20:31:34 -0000 2.110 --- floatobject.c 11 Mar 2002 10:17:17 -0000 2.110.6.1 *************** *** 578,584 **** ix = pow(iv, iw); PyFPE_END_PROTECT(ix) ! Py_SET_ERANGE_IF_OVERFLOW(ix); if (errno != 0) { ! /* XXX could it be another type of error? */ PyErr_SetFromErrno(PyExc_OverflowError); return NULL; --- 578,584 ---- ix = pow(iv, iw); PyFPE_END_PROTECT(ix) ! Py_ADJUST_ERANGE1(ix); if (errno != 0) { ! assert(errno == ERANGE); PyErr_SetFromErrno(PyExc_OverflowError); return NULL; From mwh@users.sourceforge.net Mon Mar 11 10:19:18 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:19:18 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib httplib.py,1.42.10.2,1.42.10.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv5404 Modified Files: Tag: release22-maint httplib.py Log Message: I *think* this should go in. May be wrong -- please howl in protest if so. backport jhylton's checkin of revision 1.46 of httplib.py Fix SF bug 525520. Don't automatically add a Host: header if the headers passed to request() already has a Host key. Index: httplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/httplib.py,v retrieving revision 1.42.10.2 retrieving revision 1.42.10.3 diff -C2 -d -r1.42.10.2 -r1.42.10.3 *** httplib.py 11 Mar 2002 10:06:36 -0000 1.42.10.2 --- httplib.py 11 Mar 2002 10:19:16 -0000 1.42.10.3 *************** *** 411,415 **** raise ! def putrequest(self, method, url): """Send a request to the server. --- 411,415 ---- raise ! def putrequest(self, method, url, skip_host=0): """Send a request to the server. *************** *** 462,483 **** # Issue some standard headers for better HTTP/1.1 compliance ! # this header is issued *only* for HTTP/1.1 connections. more ! # specifically, this means it is only issued when the client uses ! # the new HTTPConnection() class. backwards-compat clients will ! # be using HTTP/1.0 and those clients may be issuing this header ! # themselves. we should NOT issue it twice; some web servers (such ! # as Apache) barf when they see two Host: headers ! # If we need a non-standard port,include it in the header. ! # If the request is going through a proxy, but the host of ! # the actual URL, not the host of the proxy. ! if url.startswith('http:'): ! nil, netloc, nil, nil, nil = urlsplit(url) ! self.putheader('Host', netloc) ! elif self.port == HTTP_PORT: ! self.putheader('Host', netloc) ! else: ! self.putheader('Host', "%s:%s" % (self.host, self.port)) # note: we are assuming that clients will not attempt to set these --- 462,490 ---- # Issue some standard headers for better HTTP/1.1 compliance ! if not skip_host: ! # this header is issued *only* for HTTP/1.1 ! # connections. more specifically, this means it is ! # only issued when the client uses the new ! # HTTPConnection() class. backwards-compat clients ! # will be using HTTP/1.0 and those clients may be ! # issuing this header themselves. we should NOT issue ! # it twice; some web servers (such as Apache) barf ! # when they see two Host: headers ! # If we need a non-standard port,include it in the ! # header. If the request is going through a proxy, ! # but the host of the actual URL, not the host of the ! # proxy. ! netloc = '' ! if url.startswith('http'): ! nil, netloc, nil, nil, nil = urlsplit(url) ! ! if netloc: ! self.putheader('Host', netloc) ! elif self.port == HTTP_PORT: ! self.putheader('Host', self.host) ! else: ! self.putheader('Host', "%s:%s" % (self.host, self.port)) # note: we are assuming that clients will not attempt to set these *************** *** 537,541 **** def _send_request(self, method, url, body, headers): ! self.putrequest(method, url) if body: --- 544,555 ---- def _send_request(self, method, url, body, headers): ! # If headers already contains a host header, then define the ! # optional skip_host argument to putrequest(). The check is ! # harder because field names are case insensitive. ! if (headers.has_key('Host') ! or [k for k in headers.iterkeys() if k.lower() == "host"]): ! self.putrequest(method, url, skip_host=1) ! else: ! self.putrequest(method, url) if body: From mwh@users.sourceforge.net Mon Mar 11 10:19:50 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:19:50 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.126.4.1,2.126.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv5500 Modified Files: Tag: release22-maint typeobject.c Log Message: backport gvanrossum's checkin of revision 2.128 of typeobject.c Bugfix candidate. Adapter from SF patch 528038; fixes SF bug 527816. The wrapper for __nonzero__ should be wrap_inquiry rather than wrap_unaryfunc, since the slot returns an int, not a PyObject *. Index: typeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v retrieving revision 2.126.4.1 retrieving revision 2.126.4.2 diff -C2 -d -r2.126.4.1 -r2.126.4.2 *** typeobject.c 22 Feb 2002 13:31:18 -0000 2.126.4.1 --- typeobject.c 11 Mar 2002 10:19:48 -0000 2.126.4.2 *************** *** 3509,3513 **** UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, "abs(x)"), ! UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_unaryfunc, "x != 0"), UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"), --- 3509,3513 ---- UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, "abs(x)"), ! UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquiry, "x != 0"), UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"), From mwh@users.sourceforge.net Mon Mar 11 10:20:06 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:20:06 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.113.4.3,1.113.4.4 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv5606 Modified Files: Tag: release22-maint test_descr.py Log Message: backport gvanrossum's checkin of revision 1.117 of test_descr.py Bugfix candidate. Adapter from SF patch 528038; fixes SF bug 527816. The wrapper for __nonzero__ should be wrap_inquiry rather than wrap_unaryfunc, since the slot returns an int, not a PyObject *. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.113.4.3 retrieving revision 1.113.4.4 diff -C2 -d -r1.113.4.3 -r1.113.4.4 *** test_descr.py 5 Mar 2002 15:38:43 -0000 1.113.4.3 --- test_descr.py 11 Mar 2002 10:20:04 -0000 1.113.4.4 *************** *** 427,430 **** --- 427,433 ---- if verbose: print "Testing int operations..." numops(100, 3) + # The following crashes in Python 2.2 + vereq((1).__nonzero__(), 1) + vereq((0).__nonzero__(), 0) def longs(): From mwh@users.sourceforge.net Mon Mar 11 10:20:38 2002 From: mwh@users.sourceforge.net (Michael Hudson) Date: Mon, 11 Mar 2002 02:20:38 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib ftplib.py,1.60.10.2,1.60.10.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv5776 Modified Files: Tag: release22-maint ftplib.py Log Message: backport loewis' checkin of revision 1.66 of ftplib.py Access the exception argument to see whether it starts with '500'. Fixes #527855. Index: ftplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ftplib.py,v retrieving revision 1.60.10.2 retrieving revision 1.60.10.3 diff -C2 -d -r1.60.10.2 -r1.60.10.3 *** ftplib.py 16 Feb 2002 23:08:24 -0000 1.60.10.2 --- ftplib.py 11 Mar 2002 10:20:36 -0000 1.60.10.3 *************** *** 493,498 **** return self.voidcmd('CDUP') except error_perm, msg: ! if msg[:3] != '500': ! raise error_perm, msg elif dirname == '': dirname = '.' # does nothing, but could return error --- 493,498 ---- return self.voidcmd('CDUP') except error_perm, msg: ! if msg.args[0][:3] != '500': ! raise elif dirname == '': dirname = '.' # does nothing, but could return error From gvanrossum@users.sourceforge.net Mon Mar 11 13:21:27 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Mon, 11 Mar 2002 05:21:27 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.117,1.118 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv18470 Modified Files: test_descr.py Log Message: Add a check that SF bug 516727 is really fixed. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.117 retrieving revision 1.118 diff -C2 -d -r1.117 -r1.118 *** test_descr.py 11 Mar 2002 00:07:13 -0000 1.117 --- test_descr.py 11 Mar 2002 13:21:25 -0000 1.118 *************** *** 430,433 **** --- 430,443 ---- vereq((1).__nonzero__(), 1) vereq((0).__nonzero__(), 0) + # This returns 'NotImplemented' in Python 2.2 + class C(int): + def __add__(self, other): + return NotImplemented + try: + C() + "" + except TypeError: + pass + else: + raise TestFailed, "NotImplemented should have caused TypeErrpr" def longs(): From nnorwitz@users.sourceforge.net Mon Mar 11 14:44:15 2002 From: nnorwitz@users.sourceforge.net (Neal Norwitz) Date: Mon, 11 Mar 2002 06:44:15 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.118,1.119 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv10014/Lib/test Modified Files: test_descr.py Log Message: Fix typo Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.118 retrieving revision 1.119 diff -C2 -d -r1.118 -r1.119 *** test_descr.py 11 Mar 2002 13:21:25 -0000 1.118 --- test_descr.py 11 Mar 2002 14:44:12 -0000 1.119 *************** *** 439,443 **** pass else: ! raise TestFailed, "NotImplemented should have caused TypeErrpr" def longs(): --- 439,443 ---- pass else: ! raise TestFailed, "NotImplemented should have caused TypeError" def longs(): From bwarsaw@users.sourceforge.net Mon Mar 11 17:23:16 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 09:23:16 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0002.txt,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv25464 Modified Files: pep-0002.txt Log Message: This PEP has a new champion Martijn Faassen, and it actually contains text now. :) Committing for Martijn, after minor formatting and style changes. Index: pep-0002.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0002.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pep-0002.txt 21 Mar 2001 17:35:05 -0000 1.2 --- pep-0002.txt 11 Mar 2002 17:23:14 -0000 1.3 *************** *** 2,17 **** Title: Procedure for Adding New Modules Version: $Revision$ ! Author: esr@snark.thyrsus.com (Eric S. Raymond) ! Status: Deferred Type: Informational ! Created: 07-Aug-2000 ! Post-History: ! Abstract ! This PEP will describes review and voting procedures for ! incorporating candidate modules and extensions into the Python ! core. --- 2,193 ---- Title: Procedure for Adding New Modules Version: $Revision$ ! Last-Modified: $Date$ ! Author: faassen@infrae.com (Martijn Faassen) ! Status: Draft Type: Informational ! Created: 07-Jul-2001 ! Post-History: 07-Jul-2001, 09-Mar-2002 ! Introduction ! The Python Standard Library contributes significantly to Python's ! success. The language comes with "batteries included", so it is ! easy for people to become productive with just the standard ! library alone. It is therefore important that this library grows ! with the language, and that such growth is supported and ! encouraged. ! ! Many contributions to the library are not created by core ! developers but by people from the Python community who are experts ! in their particular field. Furthermore, community members are ! also the users of the standard library, applying it in a great ! diversity of settings. This makes the community well equipped to ! detect and report gaps in the library; things that are missing but ! should be added. ! ! New functionality is commonly added to the library in the form of ! new modules. This PEP will describe the procedure for the ! _addition_ of new modules. PEP 4 deals with procedures for ! deprecation of modules; the _removal_ of old and unused modules ! from the standard library. Finally there is also the issue of ! _changing_ existing modules to make the picture of library ! evolution complete. PEP 3 and PEP 5 give some guidelines on this. ! The continued maintenance of existing modules is an integral part ! of the decision on whether to add a new module to the standard ! library. Therefore, this PEP also introduces concepts ! (integrators, maintainers) relevant to the maintenance issue. ! ! ! Integrators ! ! The integrators are a group of people with the following ! responsibilities: ! ! - They determine if a proposed contribution should become part of ! the standard library. ! ! - They integrate accepted contributions into the standard library. ! ! - They produce standard library releases. ! ! This group of people shall be PythonLabs, led by Guido. ! ! ! Maintainer(s) ! ! All contributions to the standard library need one or more ! maintainers. This can be an individual, but it is frequently a ! group of people such as the XML-SIG. Groups may subdivide ! maintenance tasks among themselves. One ore more maintainers ! shall be the _head maintainer_ (usually this is also the main ! developer). Head maintainers are convenient people the ! integrators can address if they want to resolve specific issues, ! such as the ones detailed later in this document. ! ! ! Developers(s) ! ! Contributions to the standard library have been developed by one ! or more developers. The initial maintainers are the original ! developers unless there are special circumstances (which should be ! detailed in the PEP proposing the contribution). ! ! ! Acceptance Procedure ! ! When developers wish to have a contribution accepted into the ! standard library, they will first form a group of maintainers ! (normally initially consisting of themselves). ! ! Then, this group shall produce a PEP called a library PEP. A ! library PEP is a special form of standards track PEP. The library ! PEP gives an overview of the proposed contribution, along with the ! proposed contribution as the reference implementation. This PEP ! should also contain a motivation on why this contribution should ! be part of the standard library. ! ! One or more maintainers shall step forward as PEP champion (the ! people listed in the Author field are the champions). The PEP ! champion(s) shall be the initial head maintainer(s). ! ! As described in PEP 1, a standards track PEP should consist of a ! design document and a reference implementation. The library PEP ! differs from a normal standard track PEP in that the reference ! implementation should in this case always already have been ! written before the PEP is to be reviewed for inclusion by the ! integrators and to be commented upon by the community; the ! reference implementation _is_ the proposed contribution. ! ! This different requirement exists for the following reasons: ! ! - The integrators can only properly evaluate a contribution to the ! standard library when there is source code and documentation to ! look at; i.e. the reference implementation is always necessary ! to aid people in studying the PEP. ! ! - Even rejected contributions will be useful outside the standard ! library, so there will a lower risk of waste of effort by the ! developers. ! ! - It will impress the integrators of the seriousness of ! contribution and will help guard them against having to evaluate ! too many frivolous proposals. ! ! Once the library PEP has been submitted for review, the ! integrators will then evaluate it. The PEP will follow the normal ! PEP work flow as described in PEP 1. If the PEP is accepted, they ! will work through the head maintainers to make the contribution ! ready for integration. ! ! ! Maintenance Procedure ! ! After a contribution has been accepted, the job is not over for ! both integrators and maintainers. The integrators will forward ! any bug reports in the standard library to the appropriate head ! maintainers. ! ! Before the feature freeze preparing for a release of the standard ! library, the integrators will check with the head maintainers for ! all contributions, to see if there are any updates to be included ! in the next release. The integrators will evaluate any such ! updates for issues like backwards compatibility and may require ! PEPs if the changes are deemed to be large. ! ! The head maintainers should take an active role in keeping up to ! date with the Python development process. If a head maintainer is ! unable to function in this way, he or she should announce the ! intention to step down to the integrators and the rest of the ! maintainers, so that a replacement can step forward. The ! integrators should at all times be capable of reaching the head ! maintainers by email. ! ! In the case where no head maintainer can be found (possibly ! because there are no maintainers left), the integrators will issue ! a call to the community at large asking for new maintainers to ! step forward. If no one does, the integrators can decide to ! declare the contribution deprecated as described in PEP 4. ! ! ! Open issues ! ! There needs to be some procedure so that the integrators can ! always reach the maintainers (or at least the head maintainers). ! This could be accomplished by a mailing list to which all head ! maintainers should be subscribed (this could be python-dev). ! Another possibility, which may be useful in any case, is the ! maintenance of a list similar to that of the list of PEPs which ! lists all the contributions and their head maintainers with ! contact info. This could in fact be part of the list of the PEPs, ! as a new contribution requires a PEP. But since the ! authors/owners of a PEP introducing a new module may eventually be ! different from those who maintain it, this wouldn't resolve all ! issues yet. ! ! Should there be a list of what criteria integrators use for ! evaluating contributions? (Source code but also things like ! documentation and a test suite, as well as such vague things like ! 'dependability of the maintainers'.) ! ! This relates to all the technical issues; check-in privileges, ! coding style requirements, documentation requirements, test suite ! requirements. These are preferably part of another PEP. ! ! Should the current standard library be subdivided among ! maintainers? Many parts already have (informal) maintainers; it ! may be good to make this more explicit. ! ! Perhaps there is a better word for 'contribution'; the word ! 'contribution' may not imply enough that the process (of ! development and maintenance) does not stop after the contribution ! is accepted and integrated into the library. ! ! Relationship to the mythical Catalog? ! ! ! Copyright ! ! This document has been placed in the public domain. *************** *** 20,22 **** --- 196,199 ---- mode: indented-text indent-tabs-mode: nil + fill-column: 70 End: From bwarsaw@users.sourceforge.net Mon Mar 11 17:24:11 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 09:24:11 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.165,1.166 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv25726 Modified Files: pep-0000.txt Log Message: PEP 2 is undeferred now that Martijn Faassen has taken over. Added Martijn's name to the list of PEP authors and removed Eric Raymond's (since he no longer authors any PEPs). Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.165 retrieving revision 1.166 diff -C2 -d -r1.165 -r1.166 *** pep-0000.txt 8 Mar 2002 15:38:37 -0000 1.165 --- pep-0000.txt 11 Mar 2002 17:24:09 -0000 1.166 *************** *** 31,34 **** --- 31,35 ---- I 0 Index of Python Enhancement Proposals Warsaw I 1 PEP Guidelines Warsaw, Hylton + I 2 Procedure for Adding New Modules Faassen I 3 Guidelines for Handling Bug Reports Hylton I 4 Deprecation of Standard Modules von Loewis *************** *** 129,133 **** Empty PEPs (or containing only an abstract) - ID 2 Procedure for Adding New Modules Raymond SD 210 Decoupling the Interpreter Loop Ascher ID 220 Coroutines, Generators, Continuations McMillan --- 130,133 ---- *************** *** 158,162 **** I 0 Index of Python Enhancement Proposals Warsaw I 1 PEP Guidelines Warsaw, Hylton ! ID 2 Procedure for Adding New Modules Raymond I 3 Guidelines for Handling Bug Reports Hylton I 4 Deprecation of Standard Modules von Loewis --- 158,162 ---- I 0 Index of Python Enhancement Proposals Warsaw I 1 PEP Guidelines Warsaw, Hylton ! I 2 Procedure for Adding New Modules Faassen I 3 Guidelines for Handling Bug Reports Hylton I 4 Deprecation of Standard Modules von Loewis *************** *** 289,292 **** --- 289,293 ---- Evans, Clark C. cce@clarkevans.com Ewing, Greg greg@cosc.canterbury.ac.nz + Faassen, Martijn faassen@infrae.com Giacometti, Frédéric B. fred@arakne.com Goodger, David dgoodger@bigfoot.com *************** *** 311,315 **** Petrone, Jason jp@demonseed.net Prescod, Paul paul@prescod.net - Raymond, Eric esr@snark.thyrsus.com Reifschneider, Sean jafo-pep@tummy.com Riehl, Jonathan jriehl@spaceship.com --- 312,315 ---- From bwarsaw@users.sourceforge.net Mon Mar 11 17:30:37 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 09:30:37 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0286.txt,NONE,1.1 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv27422 Added Files: pep-0286.txt Log Message: PEP 286, Enhanced Argument Tuples, Martin von Loewis --- NEW FILE: pep-0286.txt --- PEP: 286 Title: Enhanced Argument Tuples Version: $Revision: 1.1 $ Last-Modified: $Date: 2002/03/11 17:30:35 $ Author: loewis@informatik.hu-berlin.de (Martin von Loewis) Status: Active Type: Standards Track Created: 3-Mar-2002 Python-Version: 2.3 Post-History: Abstract PyArg_ParseTuple is confronted with difficult memory management if an argument converter creates new memory. To deal with these cases, a specialized argument type is proposed. Problem description Today, argument tuples keep references to the function arguments, which are guaranteed to live as long as the argument tuple exists which is at least as long as the function call is being executed. In some cases, parsing an argument will allocate new memory, which is then to be released by the caller. This has two problems: 1. In case of failure, the application cannot know what memory to release; most callers don't even know that they have the responsibility to release that memory. Example for this are the N converter (bug #416288) and the es# converter (bug #501716). 2. Even for successful argument parsing, it is still inconvenient for the caller to be responsible for releasing the memory. In some cases, this is unnecessarily inefficient. For example, the es converter copies the conversion result into memory, even though there already is a string object that has the right contents. Proposed solution A new type 'argument tuple' is introduced. This type derives from tuple, adding an __dict__ member (at tp_dictoffset -4). Instances of this type might get the following attributes: - 'failobjects', a list of objects which need to be deallocated in case of success - 'okobjects', a list of object which will be released when the argument tuple is released To manage this type, the following functions will be added, and used appropriately in ceval.c and getargs.c: - PyArgTuple_New(int); - PyArgTuple_AddFailObject(PyObject*, PyObject*); - PyArgTuple_AddFailMemory(PyObject*, void*); - PyArgTuple_AddOkObject(PyObject*, PyObject*); - PyArgTuple_AddOkMemory(PyObject*, void*); - PyArgTuple_ClearFailed(PyObject*); When argument parsing fails, all fail objects will be released through Py_DECREF, and all fail memory will be released through PyMem_Free. If parsing succeeds, the references to the fail objects and fail memory are dropped, without releasing anything. When the argument tuple is released, all ok objects and memory will be released. If those functions are called with an object of a different type, a warning is issued and no further action is taken; usage of the affected converters without using argument tuples is deprecated. Affected converters The following converters will add fail memory and fail objects: N, es, et, es#, et# (unless memory is passed into the converter) New converters To simplify Unicode conversion, the e* converters are duplicated as E* converters (Es, Et, Es#, Et#). The usage of the E* converters is identical to that of the e* converters, except that the application will not need to manage the resulting memory. This will be implemented through registration of Ok objects with the argument tuple. The e* converters are deprecated. Copyright This document has been placed in the public domain. Local Variables: mode: indented-text indent-tabs-mode: nil fill-column: 70 End: From bwarsaw@users.sourceforge.net Mon Mar 11 17:31:05 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 09:31:05 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.166,1.167 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv27590 Modified Files: pep-0000.txt Log Message: Added PEP 286, Enhanced Argument Tuples, Martin von Loewis Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.166 retrieving revision 1.167 diff -C2 -d -r1.166 -r1.167 *** pep-0000.txt 11 Mar 2002 17:24:09 -0000 1.166 --- pep-0000.txt 11 Mar 2002 17:31:02 -0000 1.167 *************** *** 94,97 **** --- 94,98 ---- S 284 Integer for-loops Eppstein, Ewing S 285 Adding a bool type van Rossum + S 286 Enhanced Argument Tuples von Loewis Finished PEPs (done, implemented in CVS) *************** *** 260,263 **** --- 261,265 ---- S 284 Integer for-loops Eppstein, Ewing S 285 Adding a bool type van Rossum + S 286 Enhanced Argument Tuples von Loewis SR 666 Reject Foolish Indentation Creighton From bwarsaw@users.sourceforge.net Mon Mar 11 17:36:53 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 09:36:53 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0006.txt,1.7,1.8 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv29249 Modified Files: pep-0006.txt Log Message: Status changed to Active. Index: pep-0006.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0006.txt,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** pep-0006.txt 21 Oct 2001 18:24:08 -0000 1.7 --- pep-0006.txt 11 Mar 2002 17:36:50 -0000 1.8 *************** *** 3,7 **** Version: $Revision$ Author: aahz@pobox.com (Aahz) ! Status: Draft Type: Informational Created: 15-Mar-2001 --- 3,7 ---- Version: $Revision$ Author: aahz@pobox.com (Aahz) ! Status: Active Type: Informational Created: 15-Mar-2001 From bwarsaw@users.sourceforge.net Mon Mar 11 17:33:52 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 09:33:52 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0279.txt,1.5,1.6 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv28327 Modified Files: pep-0279.txt Log Message: PEP 279 update from Raymond Hettinger Index: pep-0279.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0279.txt,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** pep-0279.txt 4 Mar 2002 13:20:02 -0000 1.5 --- pep-0279.txt 11 Mar 2002 17:33:49 -0000 1.6 *************** *** 21,64 **** Rationale ! Starting with xrange() and xreadlines(), Python has been evolving ! toward a model that provides lazy evaluation as an alternative ! when complete evaluation is not desired because of memory ! restrictions or availability of data. ! ! Starting with Python 2.2, a second evolutionary direction came in ! the form of iterators and generators. The iter() factory function ! and generators were provided as convenient means of creating ! iterators. Deep changes were made to use iterators as a unifying ! theme throughout Python. The unification came in the form of establishing a common iterable interface for mappings, sequences, ! and file objects. In the case of mappings and file objects, lazy ! evaluation became the norm. ! The next steps in the evolution of generators are: ! 1. Add built-in functions which provide lazy alternatives to their ! complete evaluation counterparts and one other convenience ! function which was made possible once iterators and generators ! became available. The new functions are xzip, xmap, xfilter, ! and indexed. ! 2. Provide a generator alternative to list comprehensions [3] ! making generator creation as convenient as list creation. ! 3. Extend the syntax of the 'yield' keyword to enable generator ! parameter passing. The resulting increase in power simplifies ! the creation of consumer streams which have a complex execution ! state and/or variable state. ! 4. Add a generator method to enable exceptions to be passed to a generator. Currently, there is no clean method for triggering exceptions from outside the generator. Also, generator exception passing helps mitigate the try/finally prohibition for generators. All of the suggestions are designed to take advantage of the existing implementation and require little additional effort to incorporate. Each is backward compatible and requires no new ! keywords. These generator tools go into Python 2.3 when generators become final and are not imported from __future__. --- 21,81 ---- Rationale ! Python 2.2 introduced the concept of an iterable interface as proposed ! in PEP 234 [4]. The iter() factory function was provided as common ! calling convention and deep changes were made to use iterators as a ! unifying theme throughout Python. The unification came in the form of establishing a common iterable interface for mappings, sequences, ! and file objects. ! Generators, as proposed in PEP 255 [1], were introduced as a means for ! making it easier to create iterators, especially ones with a complex ! internal execution or variable states. When I created new programs, ! generators were often the tool of choice for creating an iterator. ! However, when updating existing programs, I found that the tool had ! another use, one that improved program function as well as structure. ! Those programs exhibited a pattern of creating large lists and then ! looping over them. As data sizes increased, the programs encountered ! scalability limitations owing to excessive memory consumption (and ! malloc time) for the intermediate lists. Generators were found to be ! directly substitutable for the lists while eliminating the memory ! issues through lazy evaluation a.k.a. just in time manufacturing. ! Python itself encountered similar issues. As a result, xrange() and ! xreadlines() were introduced. And, in the case of file objects and ! mappings, lazy evaluation became the norm. Generators provide a tool ! to program memory conserving for-loops whenever complete evaluation is ! not desired because of memory restrictions or availability of data. ! The next steps in the evolution of generators are: ! 1. Add a new builtin function, indexed() which was made possible ! once iterators and generators became available. It provides ! all iterables with the same advantage that iteritem() affords ! to dictionaries -- a compact, readable, reliable index notation. ! ! 2. Establish a generator alternative to list comprehensions [3] ! to provide a simple way to convert a list comprehensions into ! generators whenever memory issues arise. ! ! 3. Add a generator method to enable exceptions to be passed to a generator. Currently, there is no clean method for triggering exceptions from outside the generator. Also, generator exception passing helps mitigate the try/finally prohibition for generators. + 4. [Proposal 4 is now deferred until Python 2.4] + Extend the syntax of the 'yield' keyword to enable generator + parameter passing. The resulting increase in power simplifies + the creation of consumer streams which have a complex execution + state and/or variable state. + All of the suggestions are designed to take advantage of the existing implementation and require little additional effort to incorporate. Each is backward compatible and requires no new ! keywords. The first three generator tools go into Python 2.3 when generators become final and are not imported from __future__. + The fourth proposal should be considered deferred and will be + proposed for Python 2.4 after the Python community has more + experience with generators. *************** *** 67,149 **** There is not currently a CPython implementation; however, a simulation ! module written in pure Python is available on SourceForge [8]. The simulation covers every feature proposed in this PEP and is meant to allow direct experimentation with the proposals. ! There is also a module [9] with working source code for all of the examples used in this PEP. It serves as a test suite for the simulator and it documents how each of the new features works in practice. ! Specification for new built-ins: ! ! def xfilter(pred, gen): ! ''' ! xfilter(...) ! xfilter(function, sequence) -> list ! ! Return an iterator containing those items of sequence for ! which function is true. If function is None, return a list of ! items that are true. ! ''' ! if pred is None: ! for i in gen: ! if i: ! yield i ! else: ! for i in gen: ! if pred(i): ! yield i ! ! def xmap(fun, *collections): ### Code from Python Cookbook [6] ! ''' ! xmap(...) ! xmap(function, sequence[, sequence, ...]) -> list ! ! Return an iterator applying the function to the items of the ! argument collection(s). If more than one collection is given, ! the function is called with an argument list consisting of the ! corresponding item of each collection, substituting None for ! missing values when not all collections have the same length. ! If the function is None, return an iterator of the items of the ! collection (or an iterator of tuples if more than one collection). ! ''' ! gens = map(iter, collections) ! values_left = [1] ! def values(): ! # Emulate map behavior by padding sequences with None ! # when they run out of values. ! values_left[0] = 0 ! for i in range(len(gens)): ! iterator = gens[i] ! if iterator is None: ! yield None ! else: ! try: ! yield iterator.next() ! values_left[0] = 1 ! except StopIteration: ! gens[i] = None ! yield None ! while 1: ! args = tuple(values()) ! if not values_left[0]: ! raise StopIteration ! yield fun(*args) ! ! def xzip(*collections): ! ''' ! xzip(...) ! xzip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)] ! ! Return a iterator of tuples, where each tuple contains the ! i-th element from each of the argument sequences or iterable. ! The returned iterator is truncated in length to the length of ! the shortest argument collection. ! ''' ! gens = map(iter, collections) ! while 1: ! yield tuple([g.next() for g in gens]) def indexed(collection, cnt=0, limit=None): --- 84,105 ---- There is not currently a CPython implementation; however, a simulation ! module written in pure Python is available on SourceForge [7]. The simulation covers every feature proposed in this PEP and is meant to allow direct experimentation with the proposals. ! There is also a module [8] with working source code for all of the examples used in this PEP. It serves as a test suite for the simulator and it documents how each of the new features works in practice. + The authors and implementers of PEP 255 [1] were contacted to provide + their assessment of whether these enhancements were going to be + straight-forward to implement and require only minor modification + of the existing generator code. Neil felt the assertion was correct. + Ka-Ping thought so also. GvR said he could believe that it was true. + Tim did not have an opportunity to give an assessment. + ! Specification for a new builtin: def indexed(collection, cnt=0, limit=None): *************** *** 160,164 **** xrange, sequence, or iterable object. Also, those proposals were presented and evaluated in the world prior to Python 2.2 which did ! not include generators. As a result, the generator-less version in PEP 212 had the disadvantage of consuming memory with a giant list of tuples. The generator version presented here is fast and light, --- 116,120 ---- xrange, sequence, or iterable object. Also, those proposals were presented and evaluated in the world prior to Python 2.2 which did ! not include generators. As a result, the non-generator version in PEP 212 had the disadvantage of consuming memory with a giant list of tuples. The generator version presented here is fast and light, *************** *** 166,199 **** in mid-stream. ! ! Note B: An alternate, simplified definition of indexed is: ! ! def indexed(collection, cnt=0, limit=sys.maxint): ! 'Generates an indexed series: (0,seqn[0]), (1,seqn[1]) ...' ! return xzip( xrange(cnt,limit), collection ) ! ! ! Note C: As it stands, the Python code for xmap is slow. The actual ! implementation of the functions should be written in C for speed. ! The pure Python code listed above is meant only to specify how the ! functions would behave, in particular that they should as closely as ! possible emulate their non-lazy counterparts. ! Note D: Almost all of the PEP reviewers welcomed these functions but were ! divided as to whether they should be built-ins or in a separate module. ! The main argument for a separate module was to slow the rate of language ! inflation. The main argument for built-ins was that these functions are ! destined to be part of a core programming style, applicable to any object ! with an iterable interface. Just as zip() solves the problem of looping ! over multiple sequences, the indexed() function solves the loop counter ! problem. Likewise, the x-functions solve the problem of applying ! functional constructs without forcing the evaluation of an entire sequence. ! If only one built-in were allowed, then indexed() is the most important general purpose tool, solving the broadest class of problems while ! improving program brevity, clarity and reliability. Specification for Generator Comprehensions: --- 122,172 ---- in mid-stream. ! There are other PEPs which touch on related issues: integer iterators, ! integer for-loops, and one for modifying the arguments to range and ! xrange. The indexed() proposal does not preclude the other proposals ! and it still meets an important need even if those are adopted -- the need ! to count items in any iterable. The other proposals give a means of ! producing an index but not the corresponding value. This is especially ! problematic if a sequence is given which doesn't support random access ! such as a file object, generator, or sequence defined with __getitem__. ! Note B: Almost all of the PEP reviewers welcomed the function but were ! divided as to whether there should be any builtins. The main argument ! for a separate module was to slow the rate of language inflation. The ! main argument for a builtin was that the function is destined to be ! part of a core programming style, applicable to any object with an ! iterable interface. Just as zip() solves the problem of looping ! over multiple sequences, the indexed() function solves the loop ! counter problem. ! If only one builtin is allowed, then indexed() is the most important general purpose tool, solving the broadest class of problems while ! improving program brevity, clarity and reliability. ! + Commentary from GvR: filter and map should die and be subsumed into list + comprehensions, not grow more variants. I'd rather introduce builtins + that do iterator algebra (e.g. the iterzip that I've often used as + an example). + + Commentary from Ka-Ping Yee: I'm also quite happy with everything you + proposed ... and the extra builtins (really 'indexed' in particular) + are things I have wanted for a long time. + + Commentary from Neil Schemenauer: The new builtins sound okay. Guido + may be concerned with increasing the number of builtins too much. You + might be better off selling them as part of a module. If you use a + module then you can add lots of useful functions (Haskell has lots of + them that we could steal). + Author response: Prior to these comments, four builtins were proposed. + After the comments, xmap xfilter and xzip were withdrawn. The one + that remains is vital for the language and is proposed by itself. + + I still secretly covet xzip() a.k.a. iterzip() but think that it will + happen on its own someday. + + Specification for Generator Comprehensions: *************** *** 225,229 **** minus side, the brackets may falsely suggest that the whole expression returns a list. Most of the feedback received to date ! indicates that brackets are helpful and not misleading. Note B: List comprehensions expose their looping variable and --- 198,211 ---- minus side, the brackets may falsely suggest that the whole expression returns a list. Most of the feedback received to date ! indicates that brackets are helpful and not misleading. Unfortunately, ! the one dissent is from GvR. ! ! A key advantage of the generator comprehension syntax is that it ! makes it trivially easy to transform existing list comprehension ! code to a generator by adding yield. Likewise, it can be converted ! back to a list by deleting yield. This makes it easy to scale-up ! programs from small datasets to ones large enough to warrant ! just in time evaluation. ! Note B: List comprehensions expose their looping variable and *************** *** 247,252 **** ! Specification for Generator Parameter Passing: 1. Allow 'yield' to assign a value as in: --- 229,341 ---- + Commentary from GvR: Cute hack, but I think the use of the [] syntax + strongly suggests that it would return a list, not an iterator. I + also think that this is trying to turn Python into a functional + language, where most algorithms use lazy infinite sequences, and I + just don't think that's where its future lies. + + Commentary from Ka-Ping Yee: I am very happy with the things you have + proposed in this PEP. I feel quite positive about generator + comprehensions and have no reservations. So a +1 on that. ! Commentary from Neil Schemenauer: I'm -0 on the generator list ! comprehensions. They don't seem to add much. You could easily use ! a nested generator to do the same thing. They smell like lambda. ! ! Author response: This may be before its time in that some people still ! don't like list comprehensions and half of this PEP's reviewers did ! not have any use for generators in any form. What I like best about ! generator comprehensions is that I can design using list ! comprehensions and then easily switch to a generator (by adding ! yield) in response to scalability requirements (when the list ! comprehension produces too large of an intermediate result). ! ! ! ! Specification for Generator Exception Passing: ! ! Add a .throw(exception) method to the generator interface: ! ! def logger(): ! start = time.time() ! log = [] ! try: ! while 1:0 ! log.append( time.time() - start ) ! yield log[-1] ! except WriteLog: ! return log ! ! g = logger() ! for i in [10,20,40,80,160]: ! testsuite(i) ! g.next() ! g.throw(WriteLog) ! ! There is no existing work-around for triggering an exception ! inside a generator. This is a true deficiency. It is the only ! case in Python where active code cannot be excepted to or through. ! ! Generator exception passing also helps address an intrinsic limitation ! on generators, the prohibition against their using try/finally to ! trigger clean-up code [1]. Without .throw(), the current work-around ! forces the resolution or clean-up code to be moved outside the generator. ! ! ! Note A: The name of the throw method was selected for several ! reasons. Raise is a keyword and so cannot be used as a method ! name. Unlike raise which immediately raises an exception from the ! current execution point, throw will first return to the generator ! and then raise the exception. The word throw is suggestive of ! putting the exception in another location. The word throw is ! already associated with exceptions in other languages. ! ! Alternative method names were considered: resolve(), signal(), ! genraise(), raiseinto(), and flush(). None of these seem to fit ! as well as throw(). ! ! ! Note B: The throw syntax should exactly match raise's syntax: ! ! throw([expression, [expression, [expression]]]) ! ! Accordingly, it should be implemented to handle all of the following: ! ! raise string g.throw(string) ! raise string, data g.throw(string,data) ! raise class, instance g.throw(class,instance) ! raise instance g.throw(instance) ! raise g.throw() ! ! ! Commentary from GvR: I'm not convinced that the cleanup problem that ! this is trying to solve exists in practice. I've never felt the need ! to put yield inside a try/except. I think the PEP doesn't make enough ! of a case that this is useful. ! ! Commentary from Ka-Ping Yee: I agree that the exception issue needs to ! be resolved and [that] you have suggested a fine solution. ! ! Commentary from Neil Schemenauer: The exception passing idea is one I ! hadn't thought of before and looks interesting. If we enable the ! passing of values back, then we should add this feature too. ! ! Author response: If the sole use of generators is to simplify writing ! iterators for lazy producers, then the odds of needing generator ! exception passing are very slim. If, on the other hand, generators ! are used to write lazy consumers, create coroutines, generate output ! streams, or simply for their marvelous capability for restarting a ! previously frozen state, THEN the need to raise exceptions will ! come up almost every time. ! ! I'm no judge of what is truly Pythonic, but am still astonished ! that there can exist blocks of code that can't be excepted to or ! through, that the try/finally combination is blocked, and that the ! only work-around is to rewrite as a class and move the exception ! code out of the function or method being excepted. ! ! ! ! Specification for Generator Parameter Passing [Deferred Proposal] 1. Allow 'yield' to assign a value as in: *************** *** 326,330 **** ostream.next(firstdat) # Analogous to file.write(dat) ostream.next(seconddat) ! ostream.throw(FlushStream) # This feature proposed below --- 415,419 ---- ostream.next(firstdat) # Analogous to file.write(dat) ostream.next(seconddat) ! ostream.throw(FlushStream) # This feature proposed above *************** *** 332,336 **** Loop over the picture files in a directory, shrink them ! one at a time to thumbnail size using PIL [7], and send them to a lazy consumer. That consumer is responsible for creating a large blank image, accepting thumbnails one at a time and placing them --- 421,425 ---- Loop over the picture files in a directory, shrink them ! one at a time to thumbnail size using PIL [6], and send them to a lazy consumer. That consumer is responsible for creating a large blank image, accepting thumbnails one at a time and placing them *************** *** 351,462 **** ! Specification for Generator Exception Passing: ! ! Add a .throw(exception) method to the generator interface: ! ! def mygen(): ! try: ! while 1: ! x = yield None ! print x ! except FlushStream: ! print 'Done' ! ! g = mygen() ! g.next(5) ! g.throw(FlushStream) ! There is no existing work-around for triggering an exception ! inside a generator. This is a true deficiency. It is the only ! case in Python where active code cannot be excepted to or through. ! Even if the .next(arg) proposal is not adopted, we should add the ! .throw() method. ! Generator exception passing also helps address an intrinsic limitation ! on generators, the prohibition against their using try/finally to ! trigger clean-up code [1]. Without .throw(), the current work-around ! forces the resolution or clean-up code to be moved outside the generator. ! - Note A: The name of the throw method was selected for several - reasons. Raise is a keyword and so cannot be used as a method - name. Unlike raise which immediately raises an exception from the - current execution point, throw will first return to the generator - and then raise the exception. The word throw is suggestive of - putting the exception in another location. The word throw is - already associated with exceptions in other languages. - Alternative method names were considered: resolve(), signal(), - genraise(), raiseinto(), and flush(). None of these seem to fit - as well as throw(). ! Note B: The throw syntax should exactly match raise's syntax: ! ! throw([expression, [expression, [expression]]]) ! ! Accordingly, it should be implemented to handle all of the following: ! raise string g.throw(string) ! raise string, data g.throw(string,data) ! raise class, instance g.throw(class,instance) ! raise instance g.throw(instance) ! raise g.throw() ! ! ! Discussion of Restartability: ! ! Inside for-loops, generators are not substitutable for lists unless they ! are accessed only once. A second access only works for restartable ! objects like lists, dicts, objects defined with __getitem__, and ! xrange objects. Generators are not the only objects which are not ! restartable. Other examples of non-restartable sequences include file ! objects, xreadlines objects, and the result of iter(callable,sentinel). ! ! Since the proposed built-in functions return generators, they are also ! non-restartable. As a result, 'xmap' is not substitutable for 'map' in ! the following example: ! ! alphabet = map(chr, xrange(ord('a'), ord('z')+1)) ! twoletterwords = [a+b for a in alphabet for b in alphabet] ! ! Since generator comprehensions also return generators, they are not ! restartable. Consequently, they are not substitutable for list ! comprehensions in the following example: ! ! digits = [str(i) for i in xrange(10)] ! alphadig = [a+d for a in 'abcdefg' for d in digits] ! ! To achieve substitutabity, generator comprehensions and x-functions ! can be implemented in a way that supports restarts. PEP 234 [4] ! explicitly states that restarts are to be supported through repeated ! calls to iter(). With that guidance, it is easy to add restartability ! to generator comprehensions using a simple wrapper class around the ! generator function and modifying the implementation above to return: ! ! g = Restartable(__temp) # instead of g = __temp() ! ! Restartable is a simple (12 line) class which calls the generator function ! to create a new, re-wound generator whenever iter() requests a restart. ! Calls to .next() are simply forwarded to the generator. The Python source ! code for the Restartable class can found in the PEP 279 simulator [8]. ! An actual implementation in C can achieve re-startability directly and ! would not need the slow class wrapper used in the pure Python simulation. ! ! The XLazy library [10] shows how restarts can be implemented for xmap, ! xfilter, and xzip. ! ! The upside of adding restart capability is that more list comprehensions ! can be made lazy and save memory by adding 'yield'. Likewise, ! more expressions that use map, filter, and zip can be made lazy just by ! adding 'x'. ! A possible downside is that x-functions have no control over whether their ! inputs are themselves restartable. With non-restartable inputs like ! generators or files, an x-function restart will not produce a meaningful ! result. References --- 440,490 ---- + Commentary from GvR: We discussed this at length when we were hashing + out generators and coroutines, and found that there's always a problem + with this: the argument to the first next() call has to be thrown away, + because it doesn't correspond to a yield statement. This looks ugly + (note that the example code has a dummy call to next() to get the + generator going). But there may be useful examples that can only be + programmed (elegantly) with this feature, so I'm reserving judgment. + I can believe that it's easy to implement. ! Commentary from Ka-Ping Yee: I also think there is a lot of power to be ! gained from generator argument passing. ! Commentary from Neil Schemenauer: I like the idea of being able to pass ! values back into a generator. I originally pitched this idea to Guido ! but in the end we decided against it (at least for the initial ! implementation). There was a few issues to work out but I can't seem ! to remember what they were. My feeling is that we need to wait until ! the Python community has more experience with generators before adding ! this feature. Maybe for 2.4 but not for 2.3. In the mean time you ! can work around this limitation by making your generator a method. ! Values can be passed back by mutating the instance. ! Author response: Okay, consider this part of the proposal deferred ! until 2.4. + Restartability ! [Discussion of restartability deleted] ! Commentary from GvR: The PEP then goes on to discuss restartable ! iterators. I think this is an evil idea obtained from reading too ! much about C++ STL iterators. It should definitely be a separate ! PEP if the author wants me to take this seriously. ! Commentary from Ka-Ping Yee: I have less of an opinion on restartability ! since i have not yet had to really run into that issue. It seems ! reasonable that it might be good idea, though perhaps YAGNI will apply ! here until I experience the need for it first-hand. + Author response: Over thirty reviewers responded, only one was interested + in restartability on the theory that it made life easier for beginners + and that it made lazy evaluation more substitutable for full + evaluation. I was never sold on it myself. Consider it retracted. + References *************** *** 477,496 **** http://gnosis.cx/publish/programming/charming_python_b5.txt ! [6] The code fragment for xmap() was found at: ! http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66448 ! ! [7] PIL, the Python Imaging Library can be found at: http://www.pythonware.com/products/pil/ ! [8] A pure Python simulation of every feature in this PEP is at: http://sourceforge.net/tracker/download.php?group_id=5470&atid=305470&file_id=17348&aid=513752 ! [9] The full, working source code for each of the examples in this PEP along with other examples and tests is at: http://sourceforge.net/tracker/download.php?group_id=5470&atid=305470&file_id=17412&aid=513756 ! [10] Oren Tirosh's XLazy library with re-startable x-functions is at: ! http://www.tothink.com/python/dataflow/ ! Copyright --- 505,519 ---- http://gnosis.cx/publish/programming/charming_python_b5.txt ! [6] PIL, the Python Imaging Library can be found at: http://www.pythonware.com/products/pil/ ! [7] A pure Python simulation of every feature in this PEP is at: http://sourceforge.net/tracker/download.php?group_id=5470&atid=305470&file_id=17348&aid=513752 ! [8] The full, working source code for each of the examples in this PEP along with other examples and tests is at: http://sourceforge.net/tracker/download.php?group_id=5470&atid=305470&file_id=17412&aid=513756 ! Copyright From bwarsaw@users.sourceforge.net Mon Mar 11 17:40:52 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 09:40:52 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0276.txt,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv30522 Modified Files: pep-0276.txt Log Message: James's last update, and mark this PEP rejected. Index: pep-0276.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0276.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pep-0276.txt 13 Nov 2001 20:52:37 -0000 1.1 --- pep-0276.txt 11 Mar 2002 17:40:50 -0000 1.2 *************** *** 4,8 **** Last-Modified: $Date$ Author: james_althoff@i2.com (Jim Althoff) ! Status: Draft Type: Standards Track Created: 12-Nov-2001 --- 4,8 ---- Last-Modified: $Date$ Author: james_althoff@i2.com (Jim Althoff) ! Status: Rejected Type: Standards Track Created: 12-Nov-2001 *************** *** 98,108 **** function to generate a sequence of indices as in, for example: ! for rowcount in range(table.getRowCount()): ! print table.getValueAt(rowcount, 0) or ! for rowcount in xrange(table.getRowCount()): ! print table.getValueAt(rowcount, 0) From time to time there are discussions in the Python community --- 98,108 ---- function to generate a sequence of indices as in, for example: ! for rowcount in range(table.getRowCount()): ! print table.getValueAt(rowcount, 0) or ! for rowcount in xrange(table.getRowCount()): ! print table.getValueAt(rowcount, 0) From time to time there are discussions in the Python community *************** *** 121,125 **** - Unwieldy, especially when combined with the len() function, i.e., xrange(len(sequence)) ! - Not as convenient as equivalent mechanisms in other languages, --- 121,125 ---- - Unwieldy, especially when combined with the len() function, i.e., xrange(len(sequence)) ! - Not as convenient as equivalent mechanisms in other languages, *************** *** 162,167 **** for-loop idiom: ! for rowcount in table.getRowCount(): ! print table.getValueAt(rowcount, 0) The following benefits for this approach vis-a-vis the current --- 162,167 ---- for-loop idiom: ! for rowcount in table.getRowCount(): ! print table.getValueAt(rowcount, 0) The following benefits for this approach vis-a-vis the current *************** *** 191,198 **** lists, tuples, dictionaries, strings, and files. - Preliminary discussion on the Python interest mailing list - suggests a reasonable amount of initial support for this PEP - (along with some dissents/issues noted below). - Backwards Compatibility --- 191,194 ---- *************** *** 211,216 **** xrange(), for example: ! for rowcount in table.getRowCount(): ! print table.getValueAt(rowcount, 0) in Python 2.2 raises a TypeError exception. --- 207,212 ---- xrange(), for example: ! for rowcount in table.getRowCount(): ! print table.getValueAt(rowcount, 0) in Python 2.2 raises a TypeError exception. *************** *** 239,247 **** - Issues: ! Based on some preliminary discussion on the Python interest ! mailing list, the following concerns have been voiced: - Is it obvious that iter(5) maps to the sequence 0,1,2,3,4? --- 235,264 ---- Issues: ! Extensive discussions concerning PEP 276 on the Python interest ! mailing list suggests a range of opinions: some in favor, some ! neutral, some against. Those in favor tend to agree with the ! claims above of the usefulness, convenience, ease of learning, ! and simplicity of a simple iterator for integers. ! ! Issues with PEP 276 include: ! ! - Using range/xrange is fine as is. ! ! Response: Some posters feel this way. Other disagree. ! ! - Some feel that iterating over the sequence "0, 1, 2, ..., n-1" ! for an integer n is not intuitive. "for i in 5:" is considered ! (by some) to be "non-obvious", for example. Some dislike this ! usage because it doesn't have "the right feel". Some dislike it ! because they believe that this type of usage forces one to view ! integers as a sequences and this seems wrong to them. Some ! dislike it because they prefer to view for-loops as dealing ! with explicit sequences rather than with arbitrary iterators. ! ! Response: Some like the proposed idiom and see it as simple, ! elegant, easy to learn, and easy to use. Some are neutral on ! this issue. Others, as noted, dislike it. - Is it obvious that iter(5) maps to the sequence 0,1,2,3,4? *************** *** 251,265 **** (inclusively) the index whose value is one less than the length of the sequence, it is argued that the proposed sequence is ! reasonably intuitive to a Python programmer while being useful ! and practical. ! ! - "in" (as in "for i in x") does not match standard English usage ! in this case. "up to" or something similar might be better. ! ! Response: Not everyone felt that matching standard English ! perfectly is a requirement. It is noted that "for:else:" ! doesn't match standard English very well either. And few are ! excited about adding a new keyword, especially just to get a ! somewhat better match to standard English usage. - Possible ambiguity --- 268,277 ---- (inclusively) the index whose value is one less than the length of the sequence, it is argued that the proposed sequence is ! reasonably intuitive to the Python programmer while being useful ! and practical. More importantly, it is argued that once learned ! this convention is very easy to remember. Note that the doc ! string for the range function makes a reference to the ! natural and useful association between range(n) and the indices ! for a list whose length is n. - Possible ambiguity *************** *** 269,302 **** might be mistaken for ! for i in (10,): print i ! Response: The predicted ambiguity was not readily apparent to ! several of the posters. ! - It would be better to add special new syntax such as: ! for i in 0..10: print i ! Response: There are other PEPs that take this approach[2][3]. ! - It would be better to reuse the ellipsis literal syntax (...) ! Response: Shares disadvantages of other proposals that require ! changes to the syntax. Needs more design to determine how it ! would handle the general case of start,stop,step, ! open/closed/half-closed intervals, etc. Needs a PEP. ! - It would be better to reuse the slicing literal syntax attached ! to the int class, e.g., int[0:10] ! Response: Same as previous response. In addition, design ! consideration needs to be given to what it would mean if one ! uses slicing syntax after some arbitrary class other than class ! int. Needs a PEP. - Might dissuade newbies from using the indexed for-loop idiom when the standard "for item in collection:" idiom is clearly better. ! Response: The standard idiom is so nice when "it fits" that it needs neither extra "carrot" nor "stick". On the other hand, one does notice cases of overuse/misuse of the standard idiom --- 281,335 ---- might be mistaken for ! for i in (10,): print i ! Response: This is exactly the same situation with strings in ! current Python (replace 10 with 'spam' in the above, for ! example). ! - Too general: in the newest releases of Python there are ! contexts -- as with for-loops -- where iterators are called ! implicitly. Some fear that having an iterator invoked for ! an integer in one of the context (excluding for-loops) might ! lead to unexpected behavior and bugs. The "x, = 1" example ! noted above is an a case in point. ! Response: From the author's perspective the examples of the ! above that were identified in the PEP 276 discussions did ! not appear to be ones that would be accidentally misused ! in ways that would lead to subtle and hard-to-detect errors. ! In addition, it seems that there is a way to deal with this ! issue by using a variation of what is outlined in the ! specification section of this proposal. Instead of adding ! an __iter__ method to class int, change the for-loop handling ! code to convert (in essense) from ! for i in n: # when isinstance(n,int) is 1 ! to ! for i in xrange(n): ! This approach gives the same results in a for-loop as an ! __iter__ method would but would prevent iteration on integer ! values in any other context. Lists and tuples, for example, ! don't have __iter__ and are handled with special code. ! Integer values would be one more special case. ! ! - "i in n" seems very unnatural. ! ! Response: Some feel that "i in len(mylist)" would be easily ! understandable and useful. Some don't like it, particularly ! when a literal is used as in "i in 5". If the variant ! mentioned in the response to the previous issue is implemented, ! this issue is moot. If not, then one could also address this ! issue by defining a __contains__ method in class int that would ! always raise a TypeError. This would then make the behavior of ! "i in n" identical to that of current Python. - Might dissuade newbies from using the indexed for-loop idiom when the standard "for item in collection:" idiom is clearly better. ! Response: The standard idiom is so nice when it fits that it needs neither extra "carrot" nor "stick". On the other hand, one does notice cases of overuse/misuse of the standard idiom *************** *** 304,370 **** idiom), as in: ! for item in sequence: ! print sequence.index(item) ! ! - Doesn't handle the general case of start,stop,step ! ! Response: use the existing range() or xrange() mechanisms. Or, ! see below. ! ! ! Extension ! ! If one wants to handle general indexing (start,stop,step) without ! having to resort to using the range() or xrange() functions then ! the following could be incorporated into the current proposal. ! ! Add an "iter" method (or use some other preferred name) to ! types.IntType with the following signature: ! ! def iter(start=0, step=1): ! ! This method would have the (hopefully) obvious semantics. ! ! Then one could do, for example: ! ! x = 100 ! for i in x.iter(start=1, step=2): ! print i ! ! Under this extension (for x bound to an int), ! for i in x: ! would be equivalent to ! for i in x.iter(): ! and to ! for i in x.iter(start=0, step=1): ! This extension is consistent with the generalization provided by ! the current mechanism for dictionaries whereby one can use: ! for k in d.iterkeys(): ! for v in d.itervalues(): ! for k,v in d.iteritems(): ! depending on one's needs, given that ! for i in d: ! has a meaning aimed at the most common and useful case (d.iterkeys()). Implementation ! An implementation is not available at this time and although the ! author is not qualified to comment on such he will, nonetheless, ! speculate that this might be straightforward and, hopefully, might ! consist of little more than setting the tp_iter slot in ! types.IntType to point to a simple iterator function that would be ! similar to -- or perhaps even a wrapper around -- the xrange() ! function. --- 337,388 ---- idiom), as in: ! for item in sequence: ! print sequence.index(item) ! - Why not propose even bigger changes? ! The majority of disagreement with PEP 276 came from those who ! favor much larger changes to Python to address the more general ! problem of specifying a sequence of integers where such ! a specification is general enough to handle the starting value, ! ending value, and stepping value of the sequence and also ! addresses variations of open, closed, and half-open (half-closed) ! integer intervals. Many suggestions of such were discussed. ! These include: ! - adding Haskell-like notation for specifying a sequence of ! integers in a literal list, ! - various uses of slicing notation to specify sequences, ! - changes to the syntax of for-in loops to allow the use of ! relational operators in the loop header, ! - creation of an integer-interval class along with methods that ! overload relational operators or division operators ! to provide "slicing" on integer-interval objects, ! - and more. ! It should be noted that there was much debate but not an ! overwhelming concensus for any of these larger-scale suggestions. ! Clearly, PEP 276 does not propose such a large-scale change ! and instead focuses on a specific problem area. Towards the ! end of the discussion period, several posters expressed favor ! for the narrow focus and simplicity of PEP 276 vis-a-vis the more ! ambitious suggestions that were advanced. There did appear to be ! concensus for the need for a PEP for any such larger-scale, ! alternative suggestion. In light of this recognition, details of ! the various alternative suggestions are not discussed here further. Implementation ! An implementation is not available at this time but is expected ! to be straightforward. The author has implemented a subclass of ! int with an __iter__ method (written in Python) as a means to test ! out the ideas in this proposal, however. From bwarsaw@users.sourceforge.net Mon Mar 11 17:41:09 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 09:41:09 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.167,1.168 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv30608 Modified Files: pep-0000.txt Log Message: PEP 276 is now formally rejected. Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.167 retrieving revision 1.168 diff -C2 -d -r1.167 -r1.168 *** pep-0000.txt 11 Mar 2002 17:31:02 -0000 1.167 --- pep-0000.txt 11 Mar 2002 17:41:07 -0000 1.168 *************** *** 85,89 **** S 274 Dict Comprehensions Warsaw S 275 Switching on Multiple Values Lemburg - S 276 Simple Iterator for ints Althoff S 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen --- 85,88 ---- *************** *** 150,153 **** --- 149,153 ---- SR 259 Omit printing newline after newline van Rossum SR 271 Prefixing sys.path by command line option Giacometti + SR 276 Simple Iterator for ints Althoff SR 666 Reject Foolish Indentation Creighton *************** *** 251,255 **** S 274 Dict Comprehensions Warsaw S 275 Switching on Multiple Values Lemburg ! S 276 Simple Iterator for ints Althoff S 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen --- 251,255 ---- S 274 Dict Comprehensions Warsaw S 275 Switching on Multiple Values Lemburg ! SR 276 Simple Iterator for ints Althoff S 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen From tim.one@comcast.net Mon Mar 11 17:50:51 2002 From: tim.one@comcast.net (Tim Peters) Date: Mon, 11 Mar 2002 12:50:51 -0500 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.167,1.168 In-Reply-To: Message-ID: [Barry] > Modified Files: > pep-0000.txt > Log Message: > PEP 276 is now formally rejected. It shouldn't be rejected unless/until the reason for rejection is recorded in the PEP. (Even if it's only "butt ugly" .) From barry@zope.com Mon Mar 11 18:11:00 2002 From: barry@zope.com (Barry A. Warsaw) Date: Mon, 11 Mar 2002 13:11:00 -0500 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.167,1.168 References: Message-ID: <15500.62260.919538.330290@anthem.wooz.org> >>>>> "TP" == Tim Peters writes: TP> [Barry] >> Modified Files: pep-0000.txt Log Message: PEP 276 is now >> formally rejected. TP> It shouldn't be rejected unless/until the reason for rejection TP> is recorded in the PEP. (Even if it's only "butt ugly" TP> .) Guido, do you mind adding a rejection reason to the PEP? -Barry From guido@python.org Mon Mar 11 18:32:44 2002 From: guido@python.org (Guido van Rossum) Date: Mon, 11 Mar 2002 13:32:44 -0500 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.167,1.168 In-Reply-To: Your message of "Mon, 11 Mar 2002 13:11:00 EST." <15500.62260.919538.330290@anthem.wooz.org> References: <15500.62260.919538.330290@anthem.wooz.org> Message-ID: <200203111832.g2BIWiP04841@pcp742651pcs.reston01.va.comcast.net> > TP> It shouldn't be rejected unless/until the reason for rejection > TP> is recorded in the PEP. (Even if it's only "butt ugly" > TP> .) > > Guido, do you mind adding a rejection reason to the PEP? Um, I didn't formally reject it, and would prefer to keep it open for now. --Guido van Rossum (home page: http://www.python.org/~guido/) From fdrake@users.sourceforge.net Mon Mar 11 18:42:10 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Mar 2002 10:42:10 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc Makefile.deps,1.83,1.84 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory usw-pr-cvs1:/tmp/cvs-serv17469 Modified Files: Makefile.deps Log Message: Make the extension manual format using the Makefile; recent changes broke the dependency information. Index: Makefile.deps =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile.deps,v retrieving revision 1.83 retrieving revision 1.84 diff -C2 -d -r1.83 -r1.84 *** Makefile.deps 8 Mar 2002 03:18:19 -0000 1.83 --- Makefile.deps 11 Mar 2002 18:42:08 -0000 1.84 *************** *** 57,61 **** ext/extending.tex \ ext/newtypes.tex \ ! ext/unix.tex \ ext/windows.tex \ ext/embedding.tex \ --- 57,61 ---- ext/extending.tex \ ext/newtypes.tex \ ! ext/building.tex \ ext/windows.tex \ ext/embedding.tex \ From fdrake@users.sourceforge.net Mon Mar 11 18:46:31 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Mar 2002 10:46:31 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/api abstract.tex,1.9,1.10 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv18616/api Modified Files: abstract.tex Log Message: Documentation for PyObject_GetIter(), contributed by Greg Chapman (with only minor changes by Fred). This closes SF bug #498607. Index: abstract.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/abstract.tex,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** abstract.tex 26 Dec 2001 16:53:48 -0000 1.9 --- abstract.tex 11 Mar 2002 18:46:29 -0000 1.10 *************** *** 308,311 **** --- 308,319 ---- \end{cfuncdesc} + \begin{cfuncdesc}{PyObject*}{PyObject_GetIter}{PyObject *o} + This is equivalent to the Python expression \samp{iter(\var{o})}. + It returns a new iterator for the object argument, or the object + itself if the object is already an iterator. Raises + \exception{TypeError} and returns \NULL{} if the object cannot be + iterated. + \end{cfuncdesc} + \section{Number Protocol \label{number}} *************** *** 856,863 **** \begin{verbatim} ! PyObject *iterator = ...; PyObject *item; ! while (item = PyIter_Next(iter)) { /* do something with item */ ... --- 864,875 ---- \begin{verbatim} ! PyObject *iterator = PyObject_GetIter(obj); PyObject *item; ! if (iterator == NULL) { ! /* propagate error */ ! } ! ! while (item = PyIter_Next(iterator)) { /* do something with item */ ... *************** *** 865,870 **** Py_DECREF(item); } if (PyErr_Occurred()) { ! /* propogate error */ } else { --- 877,885 ---- Py_DECREF(item); } + + Py_DECREF(iterator); + if (PyErr_Occurred()) { ! /* propagate error */ } else { From bwarsaw@users.sourceforge.net Mon Mar 11 18:54:42 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 10:54:42 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0276.txt,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv20865 Modified Files: pep-0276.txt Log Message: Un-reject this PEP. Index: pep-0276.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0276.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pep-0276.txt 11 Mar 2002 17:40:50 -0000 1.2 --- pep-0276.txt 11 Mar 2002 18:54:40 -0000 1.3 *************** *** 4,8 **** Last-Modified: $Date$ Author: james_althoff@i2.com (Jim Althoff) ! Status: Rejected Type: Standards Track Created: 12-Nov-2001 --- 4,8 ---- Last-Modified: $Date$ Author: james_althoff@i2.com (Jim Althoff) ! Status: Active Type: Standards Track Created: 12-Nov-2001 From bwarsaw@users.sourceforge.net Mon Mar 11 18:55:33 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 10:55:33 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.168,1.169 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv21318 Modified Files: pep-0000.txt Log Message: Unreject PEP 276 Index: pep-0000.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0000.txt,v retrieving revision 1.168 retrieving revision 1.169 diff -C2 -d -r1.168 -r1.169 *** pep-0000.txt 11 Mar 2002 17:41:07 -0000 1.168 --- pep-0000.txt 11 Mar 2002 18:55:31 -0000 1.169 *************** *** 85,88 **** --- 85,89 ---- S 274 Dict Comprehensions Warsaw S 275 Switching on Multiple Values Lemburg + S 276 Simple Iterator for ints Althoff S 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen *************** *** 149,153 **** SR 259 Omit printing newline after newline van Rossum SR 271 Prefixing sys.path by command line option Giacometti - SR 276 Simple Iterator for ints Althoff SR 666 Reject Foolish Indentation Creighton --- 150,153 ---- *************** *** 251,255 **** S 274 Dict Comprehensions Warsaw S 275 Switching on Multiple Values Lemburg ! SR 276 Simple Iterator for ints Althoff S 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen --- 251,255 ---- S 274 Dict Comprehensions Warsaw S 275 Switching on Multiple Values Lemburg ! S 276 Simple Iterator for ints Althoff S 277 Unicode file name support for Windows NT Hodgson S 278 Universal Newline Support Jansen From barry@zope.com Mon Mar 11 18:56:11 2002 From: barry@zope.com (Barry A. Warsaw) Date: Mon, 11 Mar 2002 13:56:11 -0500 Subject: [Python-checkins] CVS: python/nondist/peps pep-0000.txt,1.167,1.168 References: <15500.62260.919538.330290@anthem.wooz.org> <200203111832.g2BIWiP04841@pcp742651pcs.reston01.va.comcast.net> Message-ID: <15500.64971.602650.524442@anthem.wooz.org> >>>>> "GvR" == Guido van Rossum writes: GvR> Um, I didn't formally reject it, and would prefer to keep it GvR> open for now. I've un-rejected it. -Barry From fdrake@users.sourceforge.net Mon Mar 11 19:02:01 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Mon, 11 Mar 2002 11:02:01 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/api abstract.tex,1.8.6.1,1.8.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv23448/api Modified Files: Tag: release22-maint abstract.tex Log Message: Documentation for PyObject_GetIter(), contributed by Greg Chapman (with only minor changes by Fred). This closes SF bug #498607. Index: abstract.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/abstract.tex,v retrieving revision 1.8.6.1 retrieving revision 1.8.6.2 diff -C2 -d -r1.8.6.1 -r1.8.6.2 *** abstract.tex 28 Dec 2001 04:30:38 -0000 1.8.6.1 --- abstract.tex 11 Mar 2002 19:01:58 -0000 1.8.6.2 *************** *** 308,311 **** --- 308,319 ---- \end{cfuncdesc} + \begin{cfuncdesc}{PyObject*}{PyObject_GetIter}{PyObject *o} + This is equivalent to the Python expression \samp{iter(\var{o})}. + It returns a new iterator for the object argument, or the object + itself if the object is already an iterator. Raises + \exception{TypeError} and returns \NULL{} if the object cannot be + iterated. + \end{cfuncdesc} + \section{Number Protocol \label{number}} *************** *** 856,863 **** \begin{verbatim} ! PyObject *iterator = ...; PyObject *item; ! while (item = PyIter_Next(iter)) { /* do something with item */ ... --- 864,875 ---- \begin{verbatim} ! PyObject *iterator = PyObject_GetIter(obj); PyObject *item; ! if (iterator == NULL) { ! /* propagate error */ ! } ! ! while (item = PyIter_Next(iterator)) { /* do something with item */ ... *************** *** 865,870 **** Py_DECREF(item); } if (PyErr_Occurred()) { ! /* propogate error */ } else { --- 877,885 ---- Py_DECREF(item); } + + Py_DECREF(iterator); + if (PyErr_Occurred()) { ! /* propagate error */ } else { From bwarsaw@users.sourceforge.net Mon Mar 11 19:31:46 2002 From: bwarsaw@users.sourceforge.net (Barry Warsaw) Date: Mon, 11 Mar 2002 11:31:46 -0800 Subject: [Python-checkins] CVS: python/nondist/peps pep-0279.txt,1.6,1.7 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory usw-pr-cvs1:/tmp/cvs-serv30928 Modified Files: pep-0279.txt Log Message: One more update from Raymond Hettinger. Index: pep-0279.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0279.txt,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pep-0279.txt 11 Mar 2002 17:33:49 -0000 1.6 --- pep-0279.txt 11 Mar 2002 19:31:23 -0000 1.7 *************** *** 52,56 **** 1. Add a new builtin function, indexed() which was made possible once iterators and generators became available. It provides ! all iterables with the same advantage that iteritem() affords to dictionaries -- a compact, readable, reliable index notation. --- 52,56 ---- 1. Add a new builtin function, indexed() which was made possible once iterators and generators became available. It provides ! all iterables with the same advantage that iteritems() affords to dictionaries -- a compact, readable, reliable index notation. *************** *** 160,163 **** --- 160,169 ---- module then you can add lots of useful functions (Haskell has lots of them that we could steal). + + Commentary for Magnus Lie Hetland: I think indexed would be a useful and + natural built-in function. I would certainly use it a lot. + I like indexed() a lot; +1. I'm quite happy to have it make PEP 281 + obsolete. Adding a separate module for iterator utilities seems like + a good idea. Author response: Prior to these comments, four builtins were proposed. *************** *** 243,246 **** --- 249,257 ---- a nested generator to do the same thing. They smell like lambda. + Commentary for Magnus Lie Hetland: Generator comprehensions seem mildly + useful, but I vote +0. Defining a separate, named generator would + probably be my preference. On the other hand, I do see the advantage + of "scaling up" from list comprehensions. + Author response: This may be before its time in that some people still don't like list comprehensions and half of this PEP's reviewers did *************** *** 262,266 **** try: while 1:0 ! log.append( time.time() - start ) yield log[-1] except WriteLog: --- 273,277 ---- try: while 1:0 ! log.append( time.time() - start ) yield log[-1] except WriteLog: *************** *** 321,325 **** passing of values back, then we should add this feature too. ! Author response: If the sole use of generators is to simplify writing iterators for lazy producers, then the odds of needing generator exception passing are very slim. If, on the other hand, generators --- 332,339 ---- passing of values back, then we should add this feature too. ! Commentary for Magnus Lie Hetland: Even though I cannot speak for the ! ease of implementation, I vote +1 for the exception passing mechanism. ! ! Author response: When the sole use of generators is to simplify writing iterators for lazy producers, then the odds of needing generator exception passing are very slim. If, on the other hand, generators *************** *** 462,465 **** --- 476,486 ---- Values can be passed back by mutating the instance. + Commentary for Magnus Lie Hetland: I like the generator parameter + passing mechanism. Although I see no need to defer it, deferral seems + to be the most likely scenario, and in the meantime I guess the + functionality can be emulated either by implementing the generator + as a method, or by passing a parameter with the exception + passing mechanism. + Author response: Okay, consider this part of the proposal deferred until 2.4. *************** *** 480,483 **** --- 501,507 ---- reasonable that it might be good idea, though perhaps YAGNI will apply here until I experience the need for it first-hand. + + Commentary for Magnus Lie Hetland: I guess there is no real need to comment + on restartability, but I can't see that I have any need for it. Author response: Over thirty reviewers responded, only one was interested From tim_one@users.sourceforge.net Tue Mar 12 03:04:46 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Mar 2002 19:04:46 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects fileobject.c,2.145,2.146 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv17165/python/Objects Modified Files: fileobject.c Log Message: Change Windows file.truncate() to (a) restore the original file position, and (b) stop trying to prevent file growth. Beef up the file.truncate() docs. Change test_largefile.py to stop assuming that f.truncate() moves the file pointer to the truncation point, and to verify instead that it leaves the file position alone. Remove the test for what happens when a specified size exceeds the original file size (it's ill-defined, according to the Single Unix Spec). Index: fileobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v retrieving revision 2.145 retrieving revision 2.146 diff -C2 -d -r2.145 -r2.146 *** fileobject.c 11 Mar 2002 00:24:00 -0000 2.145 --- fileobject.c 12 Mar 2002 03:04:44 -0000 2.146 *************** *** 416,454 **** #ifdef MS_WIN32 /* MS _chsize doesn't work if newsize doesn't fit in 32 bits, ! so don't even try using it. truncate() should never grow the ! file, but MS SetEndOfFile will grow a file, so we need to ! compare the specified newsize to the actual size. Some ! optimization could be done here when newsizeobj is NULL. */ { ! Py_off_t currentEOF; /* actual size */ HANDLE hFile; int error; ! /* First move to EOF, and set currentEOF to the size. */ ! errno = 0; ! if (_portable_fseek(f->f_fp, 0, SEEK_END) != 0) ! goto onioerror; ! errno = 0; ! currentEOF = _portable_ftell(f->f_fp); ! if (currentEOF == -1) ! goto onioerror; ! ! if (newsize > currentEOF) ! newsize = currentEOF; /* never grow the file */ ! ! /* Move to newsize, and truncate the file there. */ ! if (newsize != currentEOF) { errno = 0; ! if (_portable_fseek(f->f_fp, newsize, SEEK_SET) != 0) goto onioerror; Py_BEGIN_ALLOW_THREADS errno = 0; ! hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp)); ! error = hFile == (HANDLE)-1; ! if (!error) { ! error = SetEndOfFile(hFile) == 0; ! if (error) ! errno = EACCES; ! } Py_END_ALLOW_THREADS if (error) --- 416,443 ---- #ifdef MS_WIN32 /* MS _chsize doesn't work if newsize doesn't fit in 32 bits, ! so don't even try using it. */ { ! Py_off_t current; /* current file position */ HANDLE hFile; int error; ! /* current <- current file postion. */ ! if (newsizeobj == NULL) ! current = newsize; ! else { ! Py_BEGIN_ALLOW_THREADS errno = 0; ! current = _portable_ftell(f->f_fp); ! Py_END_ALLOW_THREADS ! if (current == -1) goto onioerror; + } + + /* Move to newsize. */ + if (current != newsize) { Py_BEGIN_ALLOW_THREADS errno = 0; ! error = _portable_fseek(f->f_fp, newsize, SEEK_SET) ! != 0; Py_END_ALLOW_THREADS if (error) *************** *** 456,459 **** --- 445,472 ---- } + /* Truncate. Note that this may grow the file! */ + Py_BEGIN_ALLOW_THREADS + errno = 0; + hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp)); + error = hFile == (HANDLE)-1; + if (!error) { + error = SetEndOfFile(hFile) == 0; + if (error) + errno = EACCES; + } + Py_END_ALLOW_THREADS + if (error) + goto onioerror; + + /* Restore original file position. */ + if (current != newsize) { + Py_BEGIN_ALLOW_THREADS + errno = 0; + error = _portable_fseek(f->f_fp, current, SEEK_SET) + != 0; + Py_END_ALLOW_THREADS + if (error) + goto onioerror; + } } #else From tim_one@users.sourceforge.net Tue Mar 12 03:04:46 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Mar 2002 19:04:46 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_largefile.py,1.13,1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv17165/python/Lib/test Modified Files: test_largefile.py Log Message: Change Windows file.truncate() to (a) restore the original file position, and (b) stop trying to prevent file growth. Beef up the file.truncate() docs. Change test_largefile.py to stop assuming that f.truncate() moves the file pointer to the truncation point, and to verify instead that it leaves the file position alone. Remove the test for what happens when a specified size exceeds the original file size (it's ill-defined, according to the Single Unix Spec). Index: test_largefile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_largefile.py,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** test_largefile.py 11 Mar 2002 00:24:00 -0000 1.13 --- test_largefile.py 12 Mar 2002 03:04:44 -0000 1.14 *************** *** 134,155 **** f = open(name, 'r+b') f.seek(0, 2) ! expect(f.tell(), size+1) # Cut it back via seek + truncate with no argument. newsize = size - 10 f.seek(newsize) f.truncate() ! expect(f.tell(), newsize) ! # Ensure that truncate(bigger than true size) doesn't grow the file. ! f.truncate(size) ! expect(f.tell(), newsize) # Ensure that truncate(smaller than true size) shrinks the file. newsize -= 1 ! f.seek(0) f.truncate(newsize) ! expect(f.tell(), newsize) # cut it waaaaay back - f.truncate(1) f.seek(0) ! expect(len(f.read()), 1) f.close() --- 134,161 ---- f = open(name, 'r+b') f.seek(0, 2) ! expect(f.tell(), size+1) # else we've lost track of the true size # Cut it back via seek + truncate with no argument. newsize = size - 10 f.seek(newsize) f.truncate() ! expect(f.tell(), newsize) # else pointer moved ! f.seek(0, 2) ! expect(f.tell(), newsize) # else wasn't truncated # Ensure that truncate(smaller than true size) shrinks the file. newsize -= 1 ! f.seek(42) f.truncate(newsize) ! expect(f.tell(), 42) # else pointer moved ! f.seek(0, 2) ! expect(f.tell(), newsize) # else wasn't truncated ! ! # XXX truncate(larger than true size) is ill-defined across platforms ! # cut it waaaaay back f.seek(0) ! f.truncate(1) ! expect(f.tell(), 0) # else pointer moved ! expect(len(f.read()), 1) # else wasn't truncated ! f.close() From tim_one@users.sourceforge.net Tue Mar 12 03:04:46 2002 From: tim_one@users.sourceforge.net (Tim Peters) Date: Mon, 11 Mar 2002 19:04:46 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libstdtypes.tex,1.82,1.83 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv17165/python/Doc/lib Modified Files: libstdtypes.tex Log Message: Change Windows file.truncate() to (a) restore the original file position, and (b) stop trying to prevent file growth. Beef up the file.truncate() docs. Change test_largefile.py to stop assuming that f.truncate() moves the file pointer to the truncation point, and to verify instead that it leaves the file position alone. Remove the test for what happens when a specified size exceeds the original file size (it's ill-defined, according to the Single Unix Spec). Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.82 retrieving revision 1.83 diff -C2 -d -r1.82 -r1.83 *** libstdtypes.tex 11 Mar 2002 00:24:00 -0000 1.82 --- libstdtypes.tex 12 Mar 2002 03:04:44 -0000 1.83 *************** *** 162,166 **** \subsection{Numeric Types \label{typesnumeric}} ! There are four numeric types: \dfn{plain integers}, \dfn{long integers}, \dfn{floating point numbers}, and \dfn{complex numbers}. Plain integers (also just called \dfn{integers}) --- 162,166 ---- \subsection{Numeric Types \label{typesnumeric}} ! There are four numeric types: \dfn{plain integers}, \dfn{long integers}, \dfn{floating point numbers}, and \dfn{complex numbers}. Plain integers (also just called \dfn{integers}) *************** *** 179,183 **** Complex numbers have a real and imaginary part, which are both implemented using \ctype{double} in C. To extract these parts from ! a complex number \var{z}, use \code{\var{z}.real} and \code{\var{z}.imag}. Numbers are created by numeric literals or as the result of built-in --- 179,183 ---- Complex numbers have a real and imaginary part, which are both implemented using \ctype{double} in C. To extract these parts from ! a complex number \var{z}, use \code{\var{z}.real} and \code{\var{z}.imag}. Numbers are created by numeric literals or as the result of built-in *************** *** 249,253 **** \item[(1)] For (plain or long) integer division, the result is an integer. ! The result is always rounded towards minus infinity: 1/2 is 0, (-1)/2 is -1, 1/(-2) is -1, and (-1)/(-2) is 0. Note that the result is a long integer if either operand is a long integer, regardless of --- 249,253 ---- \item[(1)] For (plain or long) integer division, the result is an integer. ! The result is always rounded towards minus infinity: 1/2 is 0, (-1)/2 is -1, 1/(-2) is -1, and (-1)/(-2) is 0. Note that the result is a long integer if either operand is a long integer, regardless of *************** *** 473,477 **** \code{len(\var{s}) + \var{j}} is substituted. But note that \code{-0} is still \code{0}. ! \item[(3)] The slice of \var{s} from \var{i} to \var{j} is defined as the sequence of items with index \var{k} such that \code{\var{i} <= --- 473,477 ---- \code{len(\var{s}) + \var{j}} is substituted. But note that \code{-0} is still \code{0}. ! \item[(3)] The slice of \var{s} from \var{i} to \var{j} is defined as the sequence of items with index \var{k} such that \code{\var{i} <= *************** *** 809,813 **** Additional string operations are defined in standard modules \refmodule{string}\refstmodindex{string} and ! \refmodule{re}.\refstmodindex{re} --- 809,813 ---- Additional string operations are defined in standard modules \refmodule{string}\refstmodindex{string} and ! \refmodule{re}.\refstmodindex{re} *************** *** 882,886 **** deprecated since Python 1.4. ! \item[(2)] Raises an exception when \var{x} is not a list object. The \method{extend()} method is experimental and not supported by mutable sequence types other than lists. --- 882,886 ---- deprecated since Python 1.4. ! \item[(2)] Raises an exception when \var{x} is not a list object. The \method{extend()} method is experimental and not supported by mutable sequence types other than lists. *************** *** 1035,1039 **** File objects\obindex{file} are implemented using C's \code{stdio} package and can be created with the built-in constructor ! \function{file()}\bifuncindex{file} described in section \ref{built-in-funcs}, ``Built-in Functions.''\footnote{\function{file()} is new in Python 2.2. The older built-in \function{open()} is an --- 1035,1039 ---- File objects\obindex{file} are implemented using C's \code{stdio} package and can be created with the built-in constructor ! \function{file()}\bifuncindex{file} described in section \ref{built-in-funcs}, ``Built-in Functions.''\footnote{\function{file()} is new in Python 2.2. The older built-in \function{open()} is an *************** *** 1101,1108 **** Read one entire line from the file. A trailing newline character is kept in the string\footnote{ ! The advantage of leaving the newline on is that an empty string ! can be returned to mean \EOF{} without being ambiguous. Another ! advantage is that (in cases where it might matter, for example. if you ! want to make an exact copy of a file while scanning its lines) you can tell whether the last line of a file ended in a newline or not (yes this happens!). --- 1101,1108 ---- Read one entire line from the file. A trailing newline character is kept in the string\footnote{ ! The advantage of leaving the newline on is that an empty string ! can be returned to mean \EOF{} without being ambiguous. Another ! advantage is that (in cases where it might matter, for example. if you ! want to make an exact copy of a file while scanning its lines) you can tell whether the last line of a file ended in a newline or not (yes this happens!). *************** *** 1153,1159 **** \begin{methoddesc}[file]{truncate}{\optional{size}} ! Truncate the file's size. If the optional \var{size} argument present, the file is truncated to (at most) that size. The size ! defaults to the current position. Availability: Windows, many \UNIX variants. \end{methoddesc} --- 1153,1164 ---- \begin{methoddesc}[file]{truncate}{\optional{size}} ! Truncate the file's size. If the optional \var{size} argument is present, the file is truncated to (at most) that size. The size ! defaults to the current position. The current file position is ! not changed. Note that if a specified size exceeds the file's ! current size, the result is platform-dependent: possibilities ! include that file may remain unchanged, increase to the specified ! size as if zero-filled, or increase to the specified size with ! undefined new content. Availability: Windows, many \UNIX variants. \end{methoddesc} From fdrake@users.sourceforge.net Tue Mar 12 14:26:39 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 06:26:39 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/hotshot log.py,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/hotshot In directory usw-pr-cvs1:/tmp/cvs-serv19642 Modified Files: log.py Log Message: Set/update self.cwd properly. Index: log.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/hotshot/log.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** log.py 29 Oct 2001 20:57:23 -0000 1.4 --- log.py 12 Mar 2002 14:26:37 -0000 1.5 *************** *** 38,42 **** --- 38,48 ---- self._nextitem = self._reader.next self._info = self._reader.info + if self._info.has_key('current-directory'): + self.cwd = self._info['current-directory'] + else: + self.cwd = None self._stack = [] + self._append = self._stack.append + self._pop = self._stack.pop def addinfo(self, key, value): *************** *** 54,57 **** --- 60,85 ---- pass + def get_filename(self, fileno): + try: + return self._filemap[fileno] + except KeyError: + raise ValueError, "unknown fileno" + + def get_filenames(self): + return self._filemap.values() + + def get_fileno(self, filename): + filename = os.path.normcase(os.path.normpath(filename)) + for fileno, name in self._filemap.items(): + if name == filename: + return fileno + raise ValueError, "unknown filename" + + def get_funcname(self, fileno, lineno): + try: + return self._funcmap[(fileno, lineno)] + except KeyError: + raise ValueError, "unknown function location" + # Iteration support: # This adds an optional (& ignored) parameter to next() so that the *************** *** 67,92 **** self._reader.close() raise StopIteration() if what == WHAT_DEFINE_FILE: ! self._filemap[fileno] = tdelta ! continue ! if what == WHAT_DEFINE_FUNC: filename = self._filemap[fileno] self._funcmap[(fileno, lineno)] = (filename, tdelta) ! continue ! if what == WHAT_ADD_INFO: # value already loaded into self.info; call the # overridable addinfo() handler so higher-level code # can pick up the new value self.addinfo(tdelta, lineno) - continue - if what == WHAT_ENTER: - t = self._decode_location(fileno, lineno) - filename, funcname = t - self._stack.append((filename, funcname, lineno)) - elif what == WHAT_EXIT: - filename, funcname, lineno = self._stack.pop() else: ! filename, funcname, firstlineno = self._stack[-1] ! return what, (filename, lineno, funcname), tdelta if sys.version < "2.2": --- 95,129 ---- self._reader.close() raise StopIteration() + + # handle the most common cases first + + if what == WHAT_ENTER: + filename, funcname = self._decode_location(fileno, lineno) + self._append((filename, funcname, lineno)) + return what, (filename, lineno, funcname), tdelta + + if what == WHAT_EXIT: + filename, funcname, lineno = self._pop() + return what, (filename, lineno, funcname), tdelta + + if what == WHAT_LINENO: + filename, funcname, firstlineno = self._stack[-1] + return what, (filename, lineno, funcname), tdelta + if what == WHAT_DEFINE_FILE: ! filename = os.path.normcase(os.path.normpath(tdelta)) ! self._filemap[fileno] = filename ! elif what == WHAT_DEFINE_FUNC: filename = self._filemap[fileno] self._funcmap[(fileno, lineno)] = (filename, tdelta) ! elif what == WHAT_ADD_INFO: # value already loaded into self.info; call the # overridable addinfo() handler so higher-level code # can pick up the new value + if tdelta == 'current-directory': + self.cwd = lineno self.addinfo(tdelta, lineno) else: ! raise ValueError, "unknown event type" if sys.version < "2.2": From jackjansen@users.sourceforge.net Tue Mar 12 15:05:13 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Tue, 12 Mar 2002 07:05:13 -0800 Subject: [Python-checkins] CVS: python/dist/src/Mac/Lib macostools.py,1.12.14.1,1.12.14.2 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Lib In directory usw-pr-cvs1:/tmp/cvs-serv2273 Modified Files: Tag: release22-maint macostools.py Log Message: Backport of 1.14: mkalias() now also works for folders. Fixes bug #515830. Index: macostools.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Lib/macostools.py,v retrieving revision 1.12.14.1 retrieving revision 1.12.14.2 diff -C2 -d -r1.12.14.1 -r1.12.14.2 *** macostools.py 24 Feb 2002 22:50:03 -0000 1.12.14.1 --- macostools.py 12 Mar 2002 15:05:11 -0000 1.12.14.2 *************** *** 35,41 **** else: alias = srcfss.NewAlias() ! srcfinfo = srcfss.GetFInfo() ! ! Res.FSpCreateResFile(dstfss, srcfinfo.Creator, srcfinfo.Type, -1) h = Res.FSpOpenResFile(dstfss, 3) resource = Res.Resource(alias.data) --- 35,45 ---- else: alias = srcfss.NewAlias() ! ! if os.path.isdir(src): ! cr, tp = 'MACS', 'fdrp' ! else: ! cr, tp = srcfss.GetCreatorType() ! ! Res.FSpCreateResFile(dstfss, cr, tp, -1) h = Res.FSpOpenResFile(dstfss, 3) resource = Res.Resource(alias.data) From jackjansen@users.sourceforge.net Tue Mar 12 15:25:56 2002 From: jackjansen@users.sourceforge.net (Jack Jansen) Date: Tue, 12 Mar 2002 07:25:56 -0800 Subject: [Python-checkins] CVS: python/dist/src configure.in,1.295,1.296 configure,1.285,1.286 Message-ID: Update of /cvsroot/python/python/dist/src In directory usw-pr-cvs1:/tmp/cvs-serv12073 Modified Files: configure.in configure Log Message: Add a -Wno-long-double flag to the compile flags on Mac OS X. Fixes bug 525481. (Probably not a 2.2.1 candidate, unless the fix that introduced a long double into objimpl.h (rev. 2.44) is backported to 2.2.1). Index: configure.in =================================================================== RCS file: /cvsroot/python/python/dist/src/configure.in,v retrieving revision 1.295 retrieving revision 1.296 diff -C2 -d -r1.295 -r1.296 *** configure.in 8 Mar 2002 21:43:51 -0000 1.295 --- configure.in 12 Mar 2002 15:25:52 -0000 1.296 *************** *** 399,403 **** case $ac_sys_system in Darwin*) ! OPT="$OPT -no-cpp-precomp";; esac fi --- 399,403 ---- case $ac_sys_system in Darwin*) ! OPT="$OPT -Wno-long-double -no-cpp-precomp";; esac fi Index: configure =================================================================== RCS file: /cvsroot/python/python/dist/src/configure,v retrieving revision 1.285 retrieving revision 1.286 diff -C2 -d -r1.285 -r1.286 *** configure 8 Mar 2002 13:43:01 -0000 1.285 --- configure 12 Mar 2002 15:25:52 -0000 1.286 *************** *** 1,5 **** #! /bin/sh ! # From configure.in Revision: 1.293 # Guess values for system-dependent variables and create Makefiles. --- 1,5 ---- #! /bin/sh ! # From configure.in Revision: 1.295 # Guess values for system-dependent variables and create Makefiles. *************** *** 1429,1433 **** case $ac_sys_system in AIX*) ! LINKCC="\$(srcdir)/Modules/makexp_aix Modules/python.exp \"\" \$(LIBRARY); $(LINKCC)";; dgux*) LINKCC="LD_RUN_PATH=$libdir $(LINKCC)";; --- 1429,1433 ---- case $ac_sys_system in AIX*) ! LINKCC="\$(srcdir)/Modules/makexp_aix Modules/python.exp \"\" \$(LIBRARY); $LINKCC";; dgux*) LINKCC="LD_RUN_PATH=$libdir $(LINKCC)";; *************** *** 1690,1694 **** case $ac_sys_system in Darwin*) ! OPT="$OPT -no-cpp-precomp";; esac fi --- 1690,1694 ---- case $ac_sys_system in Darwin*) ! OPT="$OPT -Wno-long-double -no-cpp-precomp";; esac fi From montanaro@users.sourceforge.net Tue Mar 12 19:16:21 2002 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Tue, 12 Mar 2002 11:16:21 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib popen2.py,1.21,1.22 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv15544 Modified Files: popen2.py Log Message: Popen3 and Popen4 should be in __all__ Index: popen2.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/popen2.py,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** popen2.py 24 Feb 2002 05:32:32 -0000 1.21 --- popen2.py 12 Mar 2002 19:16:19 -0000 1.22 *************** *** 11,15 **** import types ! __all__ = ["popen2", "popen3", "popen4"] MAXFD = 256 # Max number of file descriptors (os.getdtablesize()???) --- 11,15 ---- import types ! __all__ = ["popen2", "popen3", "popen4", "Popen3", "Popen4"] MAXFD = 256 # Max number of file descriptors (os.getdtablesize()???) From montanaro@users.sourceforge.net Tue Mar 12 19:48:05 2002 From: montanaro@users.sourceforge.net (Skip Montanaro) Date: Tue, 12 Mar 2002 11:48:05 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib popen2.py,1.22,1.23 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory usw-pr-cvs1:/tmp/cvs-serv28717 Modified Files: popen2.py Log Message: back out spurious change from 1.22 Index: popen2.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/popen2.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** popen2.py 12 Mar 2002 19:16:19 -0000 1.22 --- popen2.py 12 Mar 2002 19:48:03 -0000 1.23 *************** *** 11,15 **** import types ! __all__ = ["popen2", "popen3", "popen4", "Popen3", "Popen4"] MAXFD = 256 # Max number of file descriptors (os.getdtablesize()???) --- 11,15 ---- import types ! __all__ = ["popen2", "popen3", "popen4"] MAXFD = 256 # Max number of file descriptors (os.getdtablesize()???) From fdrake@users.sourceforge.net Tue Mar 12 19:49:34 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 11:49:34 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libwarnings.tex,1.6,1.7 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv29441/lib Modified Files: libwarnings.tex Log Message: "level" keyword argument in example should be "stacklevel". This closes SF bug #517684. Index: libwarnings.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libwarnings.tex,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** libwarnings.tex 14 Aug 2001 21:51:50 -0000 1.6 --- libwarnings.tex 12 Mar 2002 19:49:31 -0000 1.7 *************** *** 154,158 **** \begin{verbatim} def deprecation(message): ! warnings.warn(message, DeprecationWarning, level=2) \end{verbatim} --- 154,158 ---- \begin{verbatim} def deprecation(message): ! warnings.warn(message, DeprecationWarning, stacklevel=2) \end{verbatim} From fdrake@users.sourceforge.net Tue Mar 12 19:51:18 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 11:51:18 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libwarnings.tex,1.6,1.6.16.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv30183/lib Modified Files: Tag: release22-maint libwarnings.tex Log Message: "level" keyword argument in example should be "stacklevel". This closes SF bug #517684. Index: libwarnings.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libwarnings.tex,v retrieving revision 1.6 retrieving revision 1.6.16.1 diff -C2 -d -r1.6 -r1.6.16.1 *** libwarnings.tex 14 Aug 2001 21:51:50 -0000 1.6 --- libwarnings.tex 12 Mar 2002 19:51:16 -0000 1.6.16.1 *************** *** 154,158 **** \begin{verbatim} def deprecation(message): ! warnings.warn(message, DeprecationWarning, level=2) \end{verbatim} --- 154,158 ---- \begin{verbatim} def deprecation(message): ! warnings.warn(message, DeprecationWarning, stacklevel=2) \end{verbatim} From fdrake@users.sourceforge.net Tue Mar 12 19:52:01 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 11:52:01 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/lib libwarnings.tex,1.5,1.5.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory usw-pr-cvs1:/tmp/cvs-serv30546/lib Modified Files: Tag: release21-maint libwarnings.tex Log Message: "level" keyword argument in example should be "stacklevel". This closes SF bug #517684. Index: libwarnings.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libwarnings.tex,v retrieving revision 1.5 retrieving revision 1.5.4.1 diff -C2 -d -r1.5 -r1.5.4.1 *** libwarnings.tex 28 Feb 2001 23:34:21 -0000 1.5 --- libwarnings.tex 12 Mar 2002 19:51:59 -0000 1.5.4.1 *************** *** 154,158 **** \begin{verbatim} def deprecation(message): ! warnings.warn(message, DeprecationWarning, level=2) \end{verbatim} --- 154,158 ---- \begin{verbatim} def deprecation(message): ! warnings.warn(message, DeprecationWarning, stacklevel=2) \end{verbatim} From fdrake@users.sourceforge.net Tue Mar 12 20:12:56 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 12:12:56 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/api concrete.tex,1.8,1.9 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv6000 Modified Files: concrete.tex Log Message: Add a note that Py_None needs the same reference count treatment as any other PyObject *. This closes SF bug #494007. Index: concrete.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/concrete.tex,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** concrete.tex 23 Jan 2002 10:54:41 -0000 1.8 --- concrete.tex 12 Mar 2002 20:12:54 -0000 1.9 *************** *** 75,79 **** \begin{cvardesc}{PyObject*}{Py_None} The Python \code{None} object, denoting lack of value. This object ! has no methods. \end{cvardesc} --- 75,80 ---- \begin{cvardesc}{PyObject*}{Py_None} The Python \code{None} object, denoting lack of value. This object ! has no methods. It needs to be treated just like any other object ! with respect to reference counts. \end{cvardesc} From fdrake@users.sourceforge.net Tue Mar 12 20:17:13 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 12:17:13 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/api concrete.tex,1.6,1.6.6.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv7554 Modified Files: Tag: release22-maint concrete.tex Log Message: Add a note that Py_None needs the same reference count treatment as any other PyObject *. This closes SF bug #494007. Index: concrete.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/concrete.tex,v retrieving revision 1.6 retrieving revision 1.6.6.1 diff -C2 -d -r1.6 -r1.6.6.1 *** concrete.tex 11 Dec 2001 19:40:16 -0000 1.6 --- concrete.tex 12 Mar 2002 20:17:11 -0000 1.6.6.1 *************** *** 75,79 **** \begin{cvardesc}{PyObject*}{Py_None} The Python \code{None} object, denoting lack of value. This object ! has no methods. \end{cvardesc} --- 75,80 ---- \begin{cvardesc}{PyObject*}{Py_None} The Python \code{None} object, denoting lack of value. This object ! has no methods. It needs to be treated just like any other object ! with respect to reference counts. \end{cvardesc} From fdrake@users.sourceforge.net Tue Mar 12 20:18:03 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 12:18:03 -0800 Subject: [Python-checkins] CVS: python/dist/src/Doc/api api.tex,1.117.2.11,1.117.2.12 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory usw-pr-cvs1:/tmp/cvs-serv7807 Modified Files: Tag: release21-maint api.tex Log Message: Add a note that Py_None needs the same reference count treatment as any other PyObject *. This closes SF bug #494007. Index: api.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/api.tex,v retrieving revision 1.117.2.11 retrieving revision 1.117.2.12 diff -C2 -d -r1.117.2.11 -r1.117.2.12 *** api.tex 6 Dec 2001 20:38:15 -0000 1.117.2.11 --- api.tex 12 Mar 2002 20:18:01 -0000 1.117.2.12 *************** *** 2175,2179 **** \begin{cvardesc}{PyObject*}{Py_None} The Python \code{None} object, denoting lack of value. This object has ! no methods. \end{cvardesc} --- 2175,2180 ---- \begin{cvardesc}{PyObject*}{Py_None} The Python \code{None} object, denoting lack of value. This object has ! no methods. It needs to be treated just like any other object with ! respect to reference counts. \end{cvardesc} From gvanrossum@users.sourceforge.net Tue Mar 12 20:37:04 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 12 Mar 2002 12:37:04 -0800 Subject: [Python-checkins] CVS: python/dist/src/Objects moduleobject.c,2.40,2.41 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory usw-pr-cvs1:/tmp/cvs-serv14407 Modified Files: moduleobject.c Log Message: Fix for SF bug #529050 - ModuleType.__new__ crash. There were several places that assumed the md_dict field was always set, but it needn't be. Fixed these to be more careful. I changed PyModule_GetDict() to initialize md_dict to a new dictionary if it's NULL. Bugfix candidate. Index: moduleobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/moduleobject.c,v retrieving revision 2.40 retrieving revision 2.41 diff -C2 -d -r2.40 -r2.41 *** moduleobject.c 21 Oct 2001 22:27:35 -0000 2.40 --- moduleobject.c 12 Mar 2002 20:37:02 -0000 2.41 *************** *** 44,52 **** PyModule_GetDict(PyObject *m) { if (!PyModule_Check(m)) { PyErr_BadInternalCall(); return NULL; } ! return ((PyModuleObject *)m) -> md_dict; } --- 44,56 ---- PyModule_GetDict(PyObject *m) { + PyObject *d; if (!PyModule_Check(m)) { PyErr_BadInternalCall(); return NULL; } ! d = ((PyModuleObject *)m) -> md_dict; ! if (d == NULL) ! ((PyModuleObject *)m) -> md_dict = d = PyDict_New(); ! return d; } *************** *** 54,57 **** --- 58,62 ---- PyModule_GetName(PyObject *m) { + PyObject *d; PyObject *nameobj; if (!PyModule_Check(m)) { *************** *** 59,65 **** return NULL; } ! nameobj = PyDict_GetItemString(((PyModuleObject *)m)->md_dict, ! "__name__"); ! if (nameobj == NULL || !PyString_Check(nameobj)) { PyErr_SetString(PyExc_SystemError, "nameless module"); return NULL; --- 64,72 ---- return NULL; } ! d = ((PyModuleObject *)m)->md_dict; ! if (d == NULL || ! (nameobj = PyDict_GetItemString(d, "__name__")) == NULL || ! !PyString_Check(nameobj)) ! { PyErr_SetString(PyExc_SystemError, "nameless module"); return NULL; *************** *** 71,74 **** --- 78,82 ---- PyModule_GetFilename(PyObject *m) { + PyObject *d; PyObject *fileobj; if (!PyModule_Check(m)) { *************** *** 76,82 **** return NULL; } ! fileobj = PyDict_GetItemString(((PyModuleObject *)m)->md_dict, ! "__file__"); ! if (fileobj == NULL || !PyString_Check(fileobj)) { PyErr_SetString(PyExc_SystemError, "module filename missing"); return NULL; --- 84,92 ---- return NULL; } ! d = ((PyModuleObject *)m)->md_dict; ! if (d == NULL || ! (fileobj = PyDict_GetItemString(d, "__file__")) == NULL || ! !PyString_Check(fileobj)) ! { PyErr_SetString(PyExc_SystemError, "module filename missing"); return NULL; *************** *** 100,103 **** --- 110,115 ---- d = ((PyModuleObject *)m)->md_dict; + if (d == NULL) + return; /* First, clear only names starting with a single underscore */ From gvanrossum@users.sourceforge.net Tue Mar 12 20:43:34 2002 From: gvanrossum@users.sourceforge.net (Guido van Rossum) Date: Tue, 12 Mar 2002 12:43:34 -0800 Subject: [Python-checkins] CVS: python/dist/src/Lib/test test_descr.py,1.119,1.120 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory usw-pr-cvs1:/tmp/cvs-serv17549 Modified Files: test_descr.py Log Message: Test for the fix I just checked in to moduleobject.c. Bugfix candidate. Index: test_descr.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_descr.py,v retrieving revision 1.119 retrieving revision 1.120 diff -C2 -d -r1.119 -r1.120 *** test_descr.py 11 Mar 2002 14:44:12 -0000 1.119 --- test_descr.py 12 Mar 2002 20:43:31 -0000 1.120 *************** *** 2731,2734 **** --- 2731,2745 ---- z = deepcopy(a) # This blew up before + def modules(): + if verbose: print "Testing uninitialized module objects..." + from types import ModuleType as M + m = M.__new__(M) + str(m) + vereq(hasattr(m, "__name__"), 0) + vereq(hasattr(m, "__file__"), 0) + vereq(hasattr(m, "foo"), 0) + vereq(m.__dict__, None) + m.foo = 1 + vereq(m.__dict__, {"foo": 1}) def test_main(): *************** *** 2787,2790 **** --- 2798,2802 ---- strops() deepcopyrecursive() + modules() if verbose: print "All OK" From fdrake@users.sourceforge.net Tue Mar 12 21:38:34 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 13:38:34 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.216.4.2,2.216.4.3 timemodule.c,2.118.6.1,2.118.6.2 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv5503 Modified Files: Tag: release22-maint posixmodule.c timemodule.c Log Message: Update docstrings to use te attribute names of the new structures returned by stat and time functions. This closes SF patch #523271. Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.216.4.2 retrieving revision 2.216.4.3 diff -C2 -d -r2.216.4.2 -r2.216.4.3 *** posixmodule.c 12 Jan 2002 11:13:23 -0000 2.216.4.2 --- posixmodule.c 12 Mar 2002 21:38:31 -0000 2.216.4.3 *************** *** 1301,1305 **** static char posix_stat__doc__[] = ! "stat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\ Perform a stat system call on the given path."; --- 1301,1306 ---- static char posix_stat__doc__[] = ! "stat(path) -> (st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid,\n\ ! st_size, st_atime, st_mtime, st_ctime)\n\ Perform a stat system call on the given path."; *************** *** 3369,3373 **** static char posix_lstat__doc__[] = ! "lstat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\ Like stat(path), but do not follow symbolic links."; --- 3370,3375 ---- static char posix_lstat__doc__[] = ! "lstat(path) -> (st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid,\n\ ! st_size, st_atime, st_mtime, st_ctime)\n\ Like stat(path), but do not follow symbolic links."; Index: timemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/timemodule.c,v retrieving revision 2.118.6.1 retrieving revision 2.118.6.2 diff -C2 -d -r2.118.6.1 -r2.118.6.2 *** timemodule.c 12 Jan 2002 11:13:24 -0000 2.118.6.1 --- timemodule.c 12 Mar 2002 21:38:31 -0000 2.118.6.2 *************** *** 286,290 **** static char gmtime_doc[] = ! "gmtime([seconds]) -> (year,month,day,hour,minute,second,weekday,dayofyear,dst)\n\ \n\ Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\ --- 286,291 ---- static char gmtime_doc[] = ! "gmtime([seconds]) -> (tm_year, tm_mon, tm_day, tm_hour, tm_min,\n\ ! tm_sec, tm_wday, tm_yday, tm_isdst)\n\ \n\ Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\ *************** *** 303,307 **** static char localtime_doc[] = ! "localtime([seconds]) -> (year,month,day,hour,minute,second,weekday,dayofyear,dst)\n\ \n\ Convert seconds since the Epoch to a time tuple expressing local time.\n\ --- 304,308 ---- static char localtime_doc[] = ! "localtime([seconds]) -> (tm_year,tm_mon,tm_day,tm_hour,tm_min,tm_sec,tm_wday,tm_yday,tm_isdst)\n\ \n\ Convert seconds since the Epoch to a time tuple expressing local time.\n\ From fdrake@users.sourceforge.net Tue Mar 12 21:38:51 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 13:38:51 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.224,2.225 timemodule.c,2.123,2.124 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv5586 Modified Files: posixmodule.c timemodule.c Log Message: Update docstrings to use te attribute names of the new structures returned by stat and time functions. This closes SF patch #523271. Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.224 retrieving revision 2.225 diff -C2 -d -r2.224 -r2.225 *** posixmodule.c 3 Mar 2002 23:17:02 -0000 2.224 --- posixmodule.c 12 Mar 2002 21:38:49 -0000 2.225 *************** *** 1316,1320 **** static char posix_stat__doc__[] = ! "stat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\ Perform a stat system call on the given path."; --- 1316,1321 ---- static char posix_stat__doc__[] = ! "stat(path) -> (st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid,\n\ ! st_size, st_atime, st_mtime, st_ctime)\n\ Perform a stat system call on the given path."; *************** *** 4057,4061 **** static char posix_lstat__doc__[] = ! "lstat(path) -> (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\ Like stat(path), but do not follow symbolic links."; --- 4058,4063 ---- static char posix_lstat__doc__[] = ! "lstat(path) -> (st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid,\n\ ! st_size, st_atime, st_mtime, st_ctime)\n\ Like stat(path), but do not follow symbolic links."; Index: timemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/timemodule.c,v retrieving revision 2.123 retrieving revision 2.124 diff -C2 -d -r2.123 -r2.124 *** timemodule.c 3 Mar 2002 02:59:16 -0000 2.123 --- timemodule.c 12 Mar 2002 21:38:49 -0000 2.124 *************** *** 286,290 **** static char gmtime_doc[] = ! "gmtime([seconds]) -> (year,month,day,hour,minute,second,weekday,dayofyear,dst)\n\ \n\ Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\ --- 286,291 ---- static char gmtime_doc[] = ! "gmtime([seconds]) -> (tm_year, tm_mon, tm_day, tm_hour, tm_min,\n\ ! tm_sec, tm_wday, tm_yday, tm_isdst)\n\ \n\ Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\ *************** *** 303,307 **** static char localtime_doc[] = ! "localtime([seconds]) -> (year,month,day,hour,minute,second,weekday,dayofyear,dst)\n\ \n\ Convert seconds since the Epoch to a time tuple expressing local time.\n\ --- 304,308 ---- static char localtime_doc[] = ! "localtime([seconds]) -> (tm_year,tm_mon,tm_day,tm_hour,tm_min,tm_sec,tm_wday,tm_yday,tm_isdst)\n\ \n\ Convert seconds since the Epoch to a time tuple expressing local time.\n\ From fdrake@users.sourceforge.net Tue Mar 12 21:49:46 2002 From: fdrake@users.sourceforge.net (Fred L. Drake) Date: Tue, 12 Mar 2002 13:49:46 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules xxmodule.c,2.25,2.26 xxsubtype.c,2.12,2.13 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv8771 Modified Files: xxmodule.c xxsubtype.c Log Message: Change the example code to prefer PyModule_Add*() instead of using the module dictionary directly. Also, be more careful about not re-initializing globals in the event of re-initialization of a C extension. Index: xxmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/xxmodule.c,v retrieving revision 2.25 retrieving revision 2.26 diff -C2 -d -r2.25 -r2.26 *** xxmodule.c 8 Dec 2001 18:02:58 -0000 2.25 --- xxmodule.c 12 Mar 2002 21:49:44 -0000 2.26 *************** *** 232,237 **** /* Add some symbolic constants to the module */ ! d = PyModule_GetDict(m); ! ErrorObject = PyErr_NewException("xx.error", NULL, NULL); ! PyDict_SetItemString(d, "error", ErrorObject); } --- 232,241 ---- /* Add some symbolic constants to the module */ ! if (ErrorObject == NULL) { ! ErrorObject = PyErr_NewException("xx.error", NULL, NULL); ! if (ErrorObject == NULL) ! return; ! } ! Py_INCREF(ErrorObject); ! PyModule_AddObject(d, "error", ErrorObject); } Index: xxsubtype.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/xxsubtype.c,v retrieving revision 2.12 retrieving revision 2.13 diff -C2 -d -r2.12 -r2.13 *** xxsubtype.c 17 Dec 2001 18:26:19 -0000 2.12 --- xxsubtype.c 12 Mar 2002 21:49:44 -0000 2.13 *************** *** 239,243 **** initxxsubtype(void) { ! PyObject *m, *d; /* Fill in deferred data addresses. This must be done before --- 239,243 ---- initxxsubtype(void) { ! PyObject *m; /* Fill in deferred data addresses. This must be done before *************** *** 264,279 **** return; - d = PyModule_GetDict(m); - if (d == NULL) - return; - Py_INCREF(&spamlist_type); ! if (PyDict_SetItemString(d, "spamlist", ! (PyObject *) &spamlist_type) < 0) return; Py_INCREF(&spamdict_type); ! if (PyDict_SetItemString(d, "spamdict", ! (PyObject *) &spamdict_type) < 0) return; } --- 264,275 ---- return; Py_INCREF(&spamlist_type); ! if (PyModule_AddObject(m, "spamlist", ! (PyObject *) &spamlist_type) < 0) return; Py_INCREF(&spamdict_type); ! if (PyModule_AddObject(m, "spamdict", ! (PyObject *) &spamdict_type) < 0) return; } From loewis@users.sourceforge.net Tue Mar 12 22:05:04 2002 From: loewis@users.sourceforge.net (Martin v. L?wis) Date: Tue, 12 Mar 2002 14:05:04 -0800 Subject: [Python-checkins] CVS: python/dist/src/Modules _localemodule.c,2.25,2.26 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory usw-pr-cvs1:/tmp/cvs-serv13806 Modified Files: _localemodule.c Log Message: Verify arguments for nl_langinfo. Fixes #528879. Index: _localemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/_localemodule.c,v retrieving revision 2.25 retrieving revision 2.26 diff -C2 -d -r2.25 -r2.26 *** _localemodule.c 28 Nov 2001 20:27:42 -0000 2.25 --- _localemodule.c 12 Mar 2002 22:05:02 -0000 2.26 *************** *** 1,4 **** /*********************************************************** ! Copyright (C) 1997 Martin von Loewis Permission to use, copy, modify, and distribute this software and its --- 1,4 ---- /*********************************************************** ! Copyright (C) 1997, 2002 Martin von Loewis Permission to use, copy, modify, and distribute this software and its *************** *** 416,419 **** --- 416,507 ---- #ifdef HAVE_LANGINFO_H + #define LANGINFO(X) {#X, X} + struct langinfo_constant{ + char* name; + int value; + } langinfo_constants[] = + { + /* These constants should exist on any langinfo implementation */ + LANGINFO(DAY_1), + LANGINFO(DAY_2), + LANGINFO(DAY_3), + LANGINFO(DAY_4), + LANGINFO(DAY_5), + LANGINFO(DAY_6), + LANGINFO(DAY_7), + + LANGINFO(ABDAY_1), + LANGINFO(ABDAY_2), + LANGINFO(ABDAY_3), + LANGINFO(ABDAY_4), + LANGINFO(ABDAY_5), + LANGINFO(ABDAY_6), + LANGINFO(ABDAY_7), + + LANGINFO(MON_1), + LANGINFO(MON_2), + LANGINFO(MON_3), + LANGINFO(MON_4), + LANGINFO(MON_5), + LANGINFO(MON_6), + LANGINFO(MON_7), + LANGINFO(MON_8), + LANGINFO(MON_9), + LANGINFO(MON_10), + LANGINFO(MON_11), + LANGINFO(MON_12), + + LANGINFO(ABMON_1), + LANGINFO(ABMON_2), + LANGINFO(ABMON_3), + LANGINFO(ABMON_4), + LANGINFO(ABMON_5), + LANGINFO(ABMON_6), + LANGINFO(ABMON_7), + LANGINFO(ABMON_8), + LANGINFO(ABMON_9), + LANGINFO(ABMON_10), + LANGINFO(ABMON_11), + LANGINFO(ABMON_12), + + #ifdef RADIXCHAR + /* The following are not available with glibc 2.0 */ + LANGINFO(RADIXCHAR), + LANGINFO(THOUSEP), + /* YESSTR and NOSTR are deprecated in glibc, since they are + a special case of message translation, which should be rather + done using gettext. So we don't expose it to Python in the + first place. + LANGINFO(YESSTR), + LANGINFO(NOSTR), + */ + LANGINFO(CRNCYSTR), + #endif + + LANGINFO(D_T_FMT), + LANGINFO(D_FMT), + LANGINFO(T_FMT), + LANGINFO(AM_STR), + LANGINFO(PM_STR), + + #ifdef CODESET + /* The following constants are available only with XPG4. */ + LANGINFO(CODESET), + LANGINFO(T_FMT_AMPM), + LANGINFO(ERA), + LANGINFO(ERA_D_FMT), + LANGINFO(ERA_D_T_FMT), + LANGINFO(ERA_T_FMT), + LANGINFO(ALT_DIGITS), + LANGINFO(YESEXPR), + LANGINFO(NOEXPR), + #endif + #ifdef _DATE_FMT + /* This is not available in all glibc versions that have CODESET. */ + LANGINFO(_DATE_FMT), + #endif + {0, 0} + }; + static char nl_langinfo__doc__[] = "nl_langinfo(key) -> string\n" *************** *** 424,433 **** PyLocale_nl_langinfo(PyObject* self, PyObject* args) { ! int item; if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item)) return NULL; ! return PyString_FromString(nl_langinfo(item)); } ! #endif --- 512,528 ---- PyLocale_nl_langinfo(PyObject* self, PyObject* args) { ! int item, i; if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item)) return NULL; ! /* Check whether this is a supported constant. GNU libc sometimes ! returns numeric values in the char* return value, which would ! crash PyString_FromString. */ ! for (i = 0; langinfo_constants[i].name; i++) ! if (langinfo_constants[i].value == item) ! return PyString_FromString(nl_langinfo(item)); ! PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant"); ! return NULL; } ! #endif /* HAVE_LANGINFO_H */ *************** *** 456,459 **** --- 551,557 ---- { PyObject *m, *d, *x; + #ifdef HAVE_LANGINFO_H + int i; + #endif m = Py_InitModule("_locale", PyLocale_Methods); *************** *** 502,586 **** Py_XD