From rhettinger at users.sourceforge.net Fri Jul 1 18:54:15 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 01 Jul 2005 09:54:15 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libdecimal.tex, 1.27, 1.28 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19113 Modified Files: libdecimal.tex Log Message: More info on rounding modes. Add sections for floating point notes. Index: libdecimal.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libdecimal.tex,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- libdecimal.tex 15 Jun 2005 16:53:31 -0000 1.27 +++ libdecimal.tex 1 Jul 2005 16:54:12 -0000 1.28 @@ -501,13 +501,15 @@ arithmetic operations in the context. The \var{rounding} option is one of: - \constant{ROUND_CEILING} (towards \constant{Infinity}), - \constant{ROUND_DOWN} (towards zero), - \constant{ROUND_FLOOR} (towards \constant{-Infinity}), - \constant{ROUND_HALF_DOWN} (towards zero), - \constant{ROUND_HALF_EVEN}, - \constant{ROUND_HALF_UP} (away from zero), or - \constant{ROUND_UP} (away from zero). + \begin{itemize} + \item \constant{ROUND_CEILING} (towards \constant{Infinity}), + \item \constant{ROUND_DOWN} (towards zero), + \item \constant{ROUND_FLOOR} (towards \constant{-Infinity}), + \item \constant{ROUND_HALF_DOWN} (to nearest with ties going towards zero), + \item \constant{ROUND_HALF_EVEN} (to nearest with ties going to nearest even integer), + \item \constant{ROUND_HALF_UP} (to nearest with ties going away from zero), or + \item \constant{ROUND_UP} (away from zero). + \end{itemize} The \var{traps} and \var{flags} fields list any signals to be set. Generally, new contexts should only set traps and leave the flags clear. @@ -834,6 +836,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Floating Point Notes \label{decimal-notes}} +\subsubsection{Mitigating round-off error with increased precision} + The use of decimal floating point eliminates decimal representation error (making it possible to represent \constant{0.1} exactly); however, some operations can still incur round-off error when non-zero digits exceed the @@ -881,6 +885,7 @@ Decimal("0.0060000") \end{verbatim} +\subsubsection{Special values} The number system for the \module{decimal} module provides special values including \constant{NaN}, \constant{sNaN}, \constant{-Infinity}, From rhettinger at users.sourceforge.net Fri Jul 1 18:56:56 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 01 Jul 2005 09:56:56 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libdecimal.tex, 1.24.2.2, 1.24.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20564 Modified Files: Tag: release24-maint libdecimal.tex Log Message: More info on rounding modes. Add sections for floating point notes. Index: libdecimal.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libdecimal.tex,v retrieving revision 1.24.2.2 retrieving revision 1.24.2.3 diff -u -d -r1.24.2.2 -r1.24.2.3 --- libdecimal.tex 15 Jun 2005 16:54:30 -0000 1.24.2.2 +++ libdecimal.tex 1 Jul 2005 16:56:53 -0000 1.24.2.3 @@ -501,13 +501,15 @@ arithmetic operations in the context. The \var{rounding} option is one of: - \constant{ROUND_CEILING} (towards \constant{Infinity}), - \constant{ROUND_DOWN} (towards zero), - \constant{ROUND_FLOOR} (towards \constant{-Infinity}), - \constant{ROUND_HALF_DOWN} (towards zero), - \constant{ROUND_HALF_EVEN}, - \constant{ROUND_HALF_UP} (away from zero), or - \constant{ROUND_UP} (away from zero). + \begin{itemize} + \item \constant{ROUND_CEILING} (towards \constant{Infinity}), + \item \constant{ROUND_DOWN} (towards zero), + \item \constant{ROUND_FLOOR} (towards \constant{-Infinity}), + \item \constant{ROUND_HALF_DOWN} (to nearest with ties going towards zero), + \item \constant{ROUND_HALF_EVEN} (to nearest with ties going to nearest even integer), + \item \constant{ROUND_HALF_UP} (to nearest with ties going away from zero), or + \item \constant{ROUND_UP} (away from zero). + \end{itemize} The \var{traps} and \var{flags} fields list any signals to be set. Generally, new contexts should only set traps and leave the flags clear. @@ -834,6 +836,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Floating Point Notes \label{decimal-notes}} +\subsubsection{Mitigating round-off error with increased precision} + The use of decimal floating point eliminates decimal representation error (making it possible to represent \constant{0.1} exactly); however, some operations can still incur round-off error when non-zero digits exceed the @@ -881,6 +885,7 @@ Decimal("0.0060000") \end{verbatim} +\subsubsection{Special values} The number system for the \module{decimal} module provides special values including \constant{NaN}, \constant{sNaN}, \constant{-Infinity}, From managed at forex-day-trading.com Fri Jul 1 17:04:19 2005 From: managed at forex-day-trading.com (Forex Managed Accounts) Date: Fri, 1 Jul 2005 11:04:19 -0400 Subject: [Python-checkins] When will the Real Estate Bubble Burst? - Live Meeting July 21st on Alternative Investments Message-ID: <0079fa74ffd637d749a833c56c53d199@frxserver1> An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/python-checkins/attachments/20050701/b100512e/attachment.htm From jackjansen at users.sourceforge.net Fri Jul 1 22:23:31 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Fri, 01 Jul 2005 13:23:31 -0700 Subject: [Python-checkins] python/dist/src/Tools/bgen/bgen bgenGenerator.py, 1.20, 1.21 bgenType.py, 1.17, 1.18 bgenVariable.py, 1.8, 1.9 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/bgen/bgen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2066 Modified Files: bgenGenerator.py bgenType.py bgenVariable.py Log Message: Added methods mkvaluePreCheck and getargsPreCheck, which are called (for each variable) before calling Py_BuildValue and PyArg_Parse. Index: bgenGenerator.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenGenerator.py,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- bgenGenerator.py 30 Jun 2005 15:00:13 -0000 1.20 +++ bgenGenerator.py 1 Jul 2005 20:23:27 -0000 1.21 @@ -194,6 +194,7 @@ if arg.flags == SelfMode: continue if arg.mode in (InMode, InOutMode): + arg.getargsPreCheck() fmt = fmt + arg.getargsFormat() args = arg.getargsArgs() if args: @@ -242,6 +243,7 @@ if not arg: continue if arg.flags == ErrorMode: continue if arg.mode in (OutMode, InOutMode): + arg.mkvaluePreCheck() fmt = fmt + arg.mkvalueFormat() lst = lst + sep + arg.mkvalueArgs() if fmt == "": Index: bgenType.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenType.py,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- bgenType.py 28 Jun 2005 15:14:35 -0000 1.17 +++ bgenType.py 1 Jul 2005 20:23:27 -0000 1.18 @@ -61,11 +61,18 @@ """ return "&" + name + def getargsPreCheck(self, name): + """Perform any actions needed before calling getargs(). + + This could include declaring temporary variables and such. + """ + def getargsCheck(self, name): """Perform any needed post-[new]getargs() checks. This is type-dependent; the default does not check for errors. - An example would be a check for a maximum string length.""" + An example would be a check for a maximum string length, or it + could do post-getargs() copying or conversion.""" def passInput(self, name): """Return an argument for passing a variable into a call. @@ -119,6 +126,12 @@ """ return name + def mkvaluePreCheck(self, name): + """Perform any actions needed before calling mkvalue(). + + This could include declaring temporary variables and such. + """ + def cleanup(self, name): """Clean up if necessary. Index: bgenVariable.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenVariable.py,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- bgenVariable.py 28 Jun 2005 15:14:35 -0000 1.8 +++ bgenVariable.py 1 Jul 2005 20:23:27 -0000 1.9 @@ -63,6 +63,9 @@ def getargsCheck(self): return self.type.getargsCheck(self.name) + def getargsPreCheck(self): + return self.type.getargsPreCheck(self.name) + def passArgument(self): """Return the string required to pass the variable as argument. @@ -95,6 +98,9 @@ """Call the type's mkvalueArgs method.""" return self.type.mkvalueArgs(self.name) + def mkvaluePreCheck(self): + return self.type.mkvaluePreCheck(self.name) + def cleanup(self): """Call the type's cleanup method.""" return self.type.cleanup(self.name) From rhettinger at users.sourceforge.net Sat Jul 2 00:55:45 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 01 Jul 2005 15:55:45 -0700 Subject: [Python-checkins] python/dist/src/Tools/scripts texcheck.py, 1.12, 1.13 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/scripts In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17417 Modified Files: texcheck.py Log Message: Teach texcheck about \textbar Index: texcheck.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/scripts/texcheck.py,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- texcheck.py 12 Jul 2004 13:29:10 -0000 1.12 +++ texcheck.py 1 Jul 2005 22:55:43 -0000 1.13 @@ -57,6 +57,7 @@ \email \kwindex \refexmodindex \filenq \e \menuselection \exindex \linev \newsgroup \verbatim \setshortversion \author \authoraddress \paragraph \subparagraph \cmemberline + \textbar """ def matchclose(c_lineno, c_symbol, openers, pairmap): From rhettinger at users.sourceforge.net Sat Jul 2 01:00:31 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 01 Jul 2005 16:00:31 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libsets.tex,1.17,1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19854 Modified Files: libsets.tex Log Message: Provide a comparison to the builtin set types. Index: libsets.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libsets.tex,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- libsets.tex 10 Apr 2005 17:32:35 -0000 1.17 +++ libsets.tex 1 Jul 2005 23:00:13 -0000 1.18 @@ -133,7 +133,7 @@ but not found in \class{ImmutableSet}: \begin{tableiii}{c|c|l}{code}{Operation}{Equivalent}{Result} - \lineiii{\var{s}.union_update(\var{t})} + \lineiii{\var{s}.update(\var{t})} {\var{s} \textbar= \var{t}} {return set \var{s} with elements added from \var{t}} \lineiii{\var{s}.intersection_update(\var{t})} @@ -161,12 +161,17 @@ {remove all elements from set \var{s}} \end{tableiii} -Note, the non-operator versions of \method{union_update()}, +Note, the non-operator versions of \method{update()}, \method{intersection_update()}, \method{difference_update()}, and \method{symmetric_difference_update()} will accept any iterable as an argument. \versionchanged[Formerly all arguments were required to be sets]{2.3.1} +Also note, the module also includes a \method{union_update()} method +which is an alias for \method{update()}. The method is included for +backwards compatability. Programmers should prefer the +\method{update()} method because it the one supported by the builtin +\class{set()} and \class{frozenset()} types. \subsection{Example \label{set-example}} @@ -231,3 +236,28 @@ where one thread is updating a set while another has temporarily wrapped it in \class{_TemporarilyImmutableSet}. In other words, sets of mutable sets are not thread-safe. + + +\subsection{Comparison to the built-in \class{set} types + \label{comparison-to-builtin-set}} + +The built-in \class{set} and \class{frozenset} types were designed based +on lessons learned from the \module{sets} module. The key differences are: + +\begin{itemize} +\item \class{Set} and \class{ImmutableSet} were renamed to \class{set} and + \class{frozenset}. +\item There is no equivalent to \class{BaseSet}. Instead, use + \code{isinstance(x, (set, frozenset))}. +\item The hash algorithm for the built-ins performs significantly better + (fewer collisions) for most datasets. +\item The built-in versions have more space efficient pickles. +\item The built-in versions do not have a \method{union_update()} method. + Instead, use the \method{update()} method which is equivalent. +\item The built-in versions do not have a \method{_repr(sort=True)} method. + Instead, use the built-in \function{repr()} and \function{sorted()} + functions: \code{repr(sorted(s))}. +\item The built-in version does not have a protocol for automatic conversion + to immutable. Many found this feature to be confusing and no one + in the community reported having found real uses for it. +\end{itemize} From rhettinger at users.sourceforge.net Sat Jul 2 01:01:49 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 01 Jul 2005 16:01:49 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libsets.tex, 1.15.4.2, 1.15.4.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20487 Modified Files: Tag: release24-maint libsets.tex Log Message: Provide a comparison to the builtin set types. Index: libsets.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libsets.tex,v retrieving revision 1.15.4.2 retrieving revision 1.15.4.3 diff -u -d -r1.15.4.2 -r1.15.4.3 --- libsets.tex 10 Apr 2005 17:36:26 -0000 1.15.4.2 +++ libsets.tex 1 Jul 2005 23:01:46 -0000 1.15.4.3 @@ -133,7 +133,7 @@ but not found in \class{ImmutableSet}: \begin{tableiii}{c|c|l}{code}{Operation}{Equivalent}{Result} - \lineiii{\var{s}.union_update(\var{t})} + \lineiii{\var{s}.update(\var{t})} {\var{s} \textbar= \var{t}} {return set \var{s} with elements added from \var{t}} \lineiii{\var{s}.intersection_update(\var{t})} @@ -161,12 +161,17 @@ {remove all elements from set \var{s}} \end{tableiii} -Note, the non-operator versions of \method{union_update()}, +Note, the non-operator versions of \method{update()}, \method{intersection_update()}, \method{difference_update()}, and \method{symmetric_difference_update()} will accept any iterable as an argument. \versionchanged[Formerly all arguments were required to be sets]{2.3.1} +Also note, the module also includes a \method{union_update()} method +which is an alias for \method{update()}. The method is included for +backwards compatability. Programmers should prefer the +\method{update()} method because it the one supported by the builtin +\class{set()} and \class{frozenset()} types. \subsection{Example \label{set-example}} @@ -231,3 +236,28 @@ where one thread is updating a set while another has temporarily wrapped it in \class{_TemporarilyImmutableSet}. In other words, sets of mutable sets are not thread-safe. + + +\subsection{Comparison to the built-in \class{set} types + \label{comparison-to-builtin-set}} + +The built-in \class{set} and \class{frozenset} types were designed based +on lessons learned from the \module{sets} module. The key differences are: + +\begin{itemize} +\item \class{Set} and \class{ImmutableSet} were renamed to \class{set} and + \class{frozenset}. +\item There is no equivalent to \class{BaseSet}. Instead, use + \code{isinstance(x, (set, frozenset))}. +\item The hash algorithm for the built-ins performs significantly better + (fewer collisions) for most datasets. +\item The built-in versions have more space efficient pickles. +\item The built-in versions do not have a \method{union_update()} method. + Instead, use the \method{update()} method which is equivalent. +\item The built-in versions do not have a \method{_repr(sort=True)} method. + Instead, use the built-in \function{repr()} and \function{sorted()} + functions: \code{repr(sorted(s))}. +\item The built-in version does not have a protocol for automatic conversion + to immutable. Many found this feature to be confusing and no one + in the community reported having found real uses for it. +\end{itemize} From rhettinger at users.sourceforge.net Sat Jul 2 01:18:39 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 01 Jul 2005 16:18:39 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libstdtypes.tex, 1.181, 1.182 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28915 Modified Files: libstdtypes.tex Log Message: Cross reference the set built-ins with the sets module. Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.181 retrieving revision 1.182 diff -u -d -r1.181 -r1.182 --- libstdtypes.tex 14 Jun 2005 08:45:43 -0000 1.181 +++ libstdtypes.tex 1 Jul 2005 23:18:36 -0000 1.182 @@ -1291,6 +1291,14 @@ \method{symmetric_difference_update()} methods will accept any iterable as an argument. +The design of the set types was based on lessons learned from the +\module{sets} module. + +\begin{seealso} + \seemodule[comparison-to-builtin-set]{sets}{Differences between + the \module{sets} module and the built-in set types.} +\end{seealso} + \subsection{Mapping Types --- class{dict} \label{typesmapping}} \obindex{mapping} From rhettinger at users.sourceforge.net Sat Jul 2 01:25:29 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 01 Jul 2005 16:25:29 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libstdtypes.tex, 1.170.2.10, 1.170.2.11 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32556 Modified Files: Tag: release24-maint libstdtypes.tex Log Message: Cross reference the set built-ins with the sets module. Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.170.2.10 retrieving revision 1.170.2.11 diff -u -d -r1.170.2.10 -r1.170.2.11 --- libstdtypes.tex 14 Jun 2005 08:47:19 -0000 1.170.2.10 +++ libstdtypes.tex 1 Jul 2005 23:25:27 -0000 1.170.2.11 @@ -1291,6 +1291,14 @@ \method{symmetric_difference_update()} methods will accept any iterable as an argument. +The design of the set types was based on lessons learned from the +\module{sets} module. + +\begin{seealso} + \seemodule[comparison-to-builtin-set]{sets}{Differences between + the \module{sets} module and the built-in set types.} +\end{seealso} + \subsection{Mapping Types --- class{dict} \label{typesmapping}} \obindex{mapping} From birkenfeld at users.sourceforge.net Sat Jul 2 12:27:34 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 03:27:34 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref3.tex,1.124,1.125 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11040/Doc/ref Modified Files: ref3.tex Log Message: Patch [ 1230615 ] Patch for (Doc) #1168746 Bug [ 1204734 ] incorrect description of __getattribute__ Index: ref3.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref3.tex,v retrieving revision 1.124 retrieving revision 1.125 diff -u -d -r1.124 -r1.125 --- ref3.tex 26 Apr 2005 05:18:53 -0000 1.124 +++ ref3.tex 2 Jul 2005 10:27:31 -0000 1.125 @@ -604,7 +604,7 @@ have reached the end of the set of values to be returned. \item[Built-in functions] -A built-in function object is a wrapper around a \C{} function. Examples +A built-in function object is a wrapper around a C function. Examples of built-in functions are \function{len()} and \function{math.sin()} (\module{math} is a standard built-in module). The number and type of the arguments are @@ -917,14 +917,16 @@ \ttindex{f_builtins} \ttindex{f_restricted}} -Special writable attributes: \member{f_trace}, if not \code{None}, is a -function called at the start of each source code line (this is used by -the debugger); \member{f_exc_type}, \member{f_exc_value}, -\member{f_exc_traceback} represent the most recent exception caught in -this frame; \member{f_lineno} is the current line number of the frame ---- writing to this from within a trace function jumps to the given line -(only for the bottom-most frame). A debugger can implement a Jump -command (aka Set Next Statement) by writing to f_lineno. +Special writable attributes: \member{f_trace}, if not \code{None}, is +a function called at the start of each source code line (this is used +by the debugger); \member{f_exc_type}, \member{f_exc_value}, +\member{f_exc_traceback} represent the last exception raised in the +parent frame provided another exception was ever raised in the current +frame (in all other cases they are None); \member{f_lineno} is the +current line number of the frame --- writing to this from within a +trace function jumps to the given line (only for the bottom-most +frame). A debugger can implement a Jump command (aka Set Next +Statement) by writing to f_lineno. \withsubitem{(frame attribute)}{ \ttindex{f_trace} \ttindex{f_exc_type} @@ -1335,8 +1337,9 @@ \begin{methoddesc}[object]{__getattribute__}{self, name} Called unconditionally to implement attribute accesses for instances -of the class. If the class also defines \method{__getattr__}, it will -never be called (unless called explicitly). +of the class. If the class also defines \method{__getattr__}, the latter +will not be called unless \method{__getattribute__()} either calls it +explicitly or raises an \exception{AttributeError}. This method should return the (computed) attribute value or raise an \exception{AttributeError} exception. In order to avoid infinite recursion in this method, its From birkenfeld at users.sourceforge.net Sat Jul 2 12:28:31 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 03:28:31 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref3.tex, 1.121.2.3, 1.121.2.4 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11540/Doc/ref Modified Files: Tag: release24-maint ref3.tex Log Message: backport patch [ 1230615 ] Patch for (Doc) #1168746 (frame.f_exc_*) backport bug [ 1204734 ] incorrect description of __getattribute__ Index: ref3.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref3.tex,v retrieving revision 1.121.2.3 retrieving revision 1.121.2.4 diff -u -d -r1.121.2.3 -r1.121.2.4 --- ref3.tex 26 Apr 2005 05:20:03 -0000 1.121.2.3 +++ ref3.tex 2 Jul 2005 10:28:29 -0000 1.121.2.4 @@ -604,7 +604,7 @@ have reached the end of the set of values to be returned. \item[Built-in functions] -A built-in function object is a wrapper around a \C{} function. Examples +A built-in function object is a wrapper around a C function. Examples of built-in functions are \function{len()} and \function{math.sin()} (\module{math} is a standard built-in module). The number and type of the arguments are @@ -917,14 +917,16 @@ \ttindex{f_builtins} \ttindex{f_restricted}} -Special writable attributes: \member{f_trace}, if not \code{None}, is a -function called at the start of each source code line (this is used by -the debugger); \member{f_exc_type}, \member{f_exc_value}, -\member{f_exc_traceback} represent the most recent exception caught in -this frame; \member{f_lineno} is the current line number of the frame ---- writing to this from within a trace function jumps to the given line -(only for the bottom-most frame). A debugger can implement a Jump -command (aka Set Next Statement) by writing to f_lineno. +Special writable attributes: \member{f_trace}, if not \code{None}, is +a function called at the start of each source code line (this is used +by the debugger); \member{f_exc_type}, \member{f_exc_value}, +\member{f_exc_traceback} represent the last exception raised in the +parent frame provided another exception was ever raised in the current +frame (in all other cases they are None); \member{f_lineno} is the +current line number of the frame --- writing to this from within a +trace function jumps to the given line (only for the bottom-most +frame). A debugger can implement a Jump command (aka Set Next +Statement) by writing to f_lineno. \withsubitem{(frame attribute)}{ \ttindex{f_trace} \ttindex{f_exc_type} @@ -1335,8 +1337,9 @@ \begin{methoddesc}[object]{__getattribute__}{self, name} Called unconditionally to implement attribute accesses for instances -of the class. If the class also defines \method{__getattr__}, it will -never be called (unless called explicitly). +of the class. If the class also defines \method{__getattr__}, the latter +will not be called unless \method{__getattribute__()} either calls it +explicitly or raises an \exception{AttributeError}. This method should return the (computed) attribute value or raise an \exception{AttributeError} exception. In order to avoid infinite recursion in this method, its From birkenfeld at users.sourceforge.net Sat Jul 2 12:44:36 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 03:44:36 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libweakref.tex, 1.27, 1.28 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20092/Doc/lib Modified Files: libweakref.tex Log Message: bug [ 1228904 ] weakref example broken Index: libweakref.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libweakref.tex,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- libweakref.tex 2 Jul 2004 18:57:41 -0000 1.27 +++ libweakref.tex 2 Jul 2005 10:44:32 -0000 1.28 @@ -255,13 +255,10 @@ import weakref class ExtendedRef(weakref.ref): - def __new__(cls, ob, callback=None, **annotations): - weakref.ref.__new__(cls, ob, callback) - self.__counter = 0 - def __init__(self, ob, callback=None, **annotations): super(ExtendedRef, self).__init__(ob, callback) - for k, v in annotations: + self.__counter = 0 + for k, v in annotations.iteritems(): setattr(self, k, v) def __call__(self): From birkenfeld at users.sourceforge.net Sat Jul 2 12:44:41 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 03:44:41 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libweakref.tex, 1.27, 1.27.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20243/Doc/lib Modified Files: Tag: release24-maint libweakref.tex Log Message: backport bug [ 1228904 ] weakref example broken Index: libweakref.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libweakref.tex,v retrieving revision 1.27 retrieving revision 1.27.4.1 diff -u -d -r1.27 -r1.27.4.1 --- libweakref.tex 2 Jul 2004 18:57:41 -0000 1.27 +++ libweakref.tex 2 Jul 2005 10:44:38 -0000 1.27.4.1 @@ -255,13 +255,10 @@ import weakref class ExtendedRef(weakref.ref): - def __new__(cls, ob, callback=None, **annotations): - weakref.ref.__new__(cls, ob, callback) - self.__counter = 0 - def __init__(self, ob, callback=None, **annotations): super(ExtendedRef, self).__init__(ob, callback) - for k, v in annotations: + self.__counter = 0 + for k, v in annotations.iteritems(): setattr(self, k, v) def __call__(self): From birkenfeld at users.sourceforge.net Sat Jul 2 20:37:43 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 11:37:43 -0700 Subject: [Python-checkins] python/dist/src/Lib/compiler transformer.py, 1.50, 1.51 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/compiler In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21255/Lib/compiler Modified Files: transformer.py Log Message: patch [ 1231538 ] Typo fix in compiler/transformer.py (WalkerEror) Index: transformer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/compiler/transformer.py,v retrieving revision 1.50 retrieving revision 1.51 diff -u -d -r1.50 -r1.51 --- transformer.py 9 Apr 2005 02:30:16 -0000 1.50 +++ transformer.py 2 Jul 2005 18:37:41 -0000 1.51 @@ -89,7 +89,7 @@ print nodes[kind], len(args), args raise else: - raise WalkerEror, "Can't find appropriate Node type: %s" % str(args) + raise WalkerError, "Can't find appropriate Node type: %s" % str(args) #return apply(ast.Node, args) class Transformer: @@ -165,7 +165,7 @@ if n == symbol.classdef: return self.classdef(node[1:]) - raise WalkerEror, ('unexpected node type', n) + raise WalkerError, ('unexpected node type', n) def single_input(self, node): ### do we want to do anything about being "interactive" ? @@ -316,31 +316,31 @@ return Stmt(stmts) def parameters(self, nodelist): - raise WalkerEror + raise WalkerError def varargslist(self, nodelist): - raise WalkerEror + raise WalkerError def fpdef(self, nodelist): - raise WalkerEror + raise WalkerError def fplist(self, nodelist): - raise WalkerEror + raise WalkerError def dotted_name(self, nodelist): - raise WalkerEror + raise WalkerError def comp_op(self, nodelist): - raise WalkerEror + raise WalkerError def trailer(self, nodelist): - raise WalkerEror + raise WalkerError def sliceop(self, nodelist): - raise WalkerEror + raise WalkerError def argument(self, nodelist): - raise WalkerEror + raise WalkerError # -------------------------------------------------------------- # From birkenfeld at users.sourceforge.net Sat Jul 2 20:38:15 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 11:38:15 -0700 Subject: [Python-checkins] python/dist/src/Lib/compiler transformer.py, 1.49, 1.49.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/compiler In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21455/Lib/compiler Modified Files: Tag: release24-maint transformer.py Log Message: backport patch [ 1231538 ] Typo fix in compiler/transformer.py (WalkerEror) Index: transformer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/compiler/transformer.py,v retrieving revision 1.49 retrieving revision 1.49.2.1 diff -u -d -r1.49 -r1.49.2.1 --- transformer.py 8 Nov 2004 12:17:34 -0000 1.49 +++ transformer.py 2 Jul 2005 18:38:12 -0000 1.49.2.1 @@ -89,7 +89,7 @@ print nodes[kind], len(args), args raise else: - raise WalkerEror, "Can't find appropriate Node type: %s" % str(args) + raise WalkerError, "Can't find appropriate Node type: %s" % str(args) #return apply(ast.Node, args) class Transformer: @@ -165,7 +165,7 @@ if n == symbol.classdef: return self.classdef(node[1:]) - raise WalkerEror, ('unexpected node type', n) + raise WalkerError, ('unexpected node type', n) def single_input(self, node): ### do we want to do anything about being "interactive" ? @@ -314,31 +314,31 @@ return Stmt(stmts) def parameters(self, nodelist): - raise WalkerEror + raise WalkerError def varargslist(self, nodelist): - raise WalkerEror + raise WalkerError def fpdef(self, nodelist): - raise WalkerEror + raise WalkerError def fplist(self, nodelist): - raise WalkerEror + raise WalkerError def dotted_name(self, nodelist): - raise WalkerEror + raise WalkerError def comp_op(self, nodelist): - raise WalkerEror + raise WalkerError def trailer(self, nodelist): - raise WalkerEror + raise WalkerError def sliceop(self, nodelist): - raise WalkerEror + raise WalkerError def argument(self, nodelist): - raise WalkerEror + raise WalkerError # -------------------------------------------------------------- # From birkenfeld at users.sourceforge.net Sat Jul 2 21:07:33 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 12:07:33 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libweakref.tex, 1.28, 1.29 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4005/Doc/lib Modified Files: libweakref.tex Log Message: Add doctest for examples in libweakref.tex to test_weakref. Index: libweakref.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libweakref.tex,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- libweakref.tex 2 Jul 2005 10:44:32 -0000 1.28 +++ libweakref.tex 2 Jul 2005 19:07:30 -0000 1.29 @@ -10,6 +10,8 @@ \versionadded{2.1} +% When making changes to the examples in this file, be sure to update +% Lib/test/test_weakref.py::libreftest too! The \module{weakref} module allows the Python programmer to create \dfn{weak references} to objects. @@ -228,7 +230,7 @@ o = r() if o is None: # referent has been garbage collected - print "Object has been allocated; can't frobnicate." + print "Object has been deallocated; can't frobnicate." else: print "Object is still live!" o.do_something_useful() @@ -265,7 +267,7 @@ """Return a pair containing the referent and the number of times the reference has been called. """ - ob = super(ExtendedRef, self)() + ob = super(ExtendedRef, self).__call__() if ob is not None: self.__counter += 1 ob = (ob, self.__counter) From birkenfeld at users.sourceforge.net Sat Jul 2 21:07:33 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 12:07:33 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_weakref.py, 1.43, 1.44 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4005/Lib/test Modified Files: test_weakref.py Log Message: Add doctest for examples in libweakref.tex to test_weakref. Index: test_weakref.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_weakref.py,v retrieving revision 1.43 retrieving revision 1.44 diff -u -d -r1.43 -r1.44 --- test_weakref.py 27 Mar 2005 03:04:53 -0000 1.43 +++ test_weakref.py 2 Jul 2005 19:07:30 -0000 1.44 @@ -1001,6 +1001,91 @@ def _reference(self): return self.__ref.copy() +libreftest = """ Doctest for examples in the library reference: libweakref.tex + +>>> import weakref +>>> class Dict(dict): +... pass +... +>>> obj = Dict(red=1, green=2, blue=3) # this object is weak referencable +>>> r = weakref.ref(obj) +>>> print r() +{'blue': 3, 'green': 2, 'red': 1} + +>>> import weakref +>>> class Object: +... pass +... +>>> o = Object() +>>> r = weakref.ref(o) +>>> o2 = r() +>>> o is o2 +True +>>> del o, o2 +>>> print r() +None + +>>> import weakref +>>> class ExtendedRef(weakref.ref): +... def __init__(self, ob, callback=None, **annotations): +... super(ExtendedRef, self).__init__(ob, callback) +... self.__counter = 0 +... for k, v in annotations.iteritems(): +... setattr(self, k, v) +... def __call__(self): +... '''Return a pair containing the referent and the number of +... times the reference has been called. +... ''' +... ob = super(ExtendedRef, self).__call__() +... if ob is not None: +... self.__counter += 1 +... ob = (ob, self.__counter) +... return ob +... +>>> class A: # not in docs from here, just testing the ExtendedRef +... pass +... +>>> a = A() +>>> r = ExtendedRef(a, foo=1, bar="baz") +>>> r.foo +1 +>>> r.bar +'baz' +>>> r()[1] +1 +>>> r()[1] +2 +>>> r()[0] is a +True + + +>>> import weakref +>>> _id2obj_dict = weakref.WeakValueDictionary() +>>> def remember(obj): +... oid = id(obj) +... _id2obj_dict[oid] = obj +... return oid +... +>>> def id2obj(oid): +... return _id2obj_dict[oid] +... +>>> a = A() # from here, just testing +>>> a_id = remember(a) +>>> id2obj(a_id) is a +True +>>> del a +>>> try: +... id2obj(a_id) +... except KeyError: +... print 'OK' +... else: +... print 'WeakValueDictionary error' +OK + +""" + +__test__ = {'libreftest' : libreftest} + def test_main(): test_support.run_unittest( ReferencesTestCase, @@ -1008,6 +1093,7 @@ WeakValueDictionaryTestCase, WeakKeyDictionaryTestCase, ) + test_support.run_doctest(sys.modules[__name__]) if __name__ == "__main__": From birkenfeld at users.sourceforge.net Sat Jul 2 21:09:44 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 12:09:44 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libweakref.tex, 1.27.4.1, 1.27.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4899/Doc/lib Modified Files: Tag: release24-maint libweakref.tex Log Message: backport doctest for weakref examples Index: libweakref.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libweakref.tex,v retrieving revision 1.27.4.1 retrieving revision 1.27.4.2 diff -u -d -r1.27.4.1 -r1.27.4.2 --- libweakref.tex 2 Jul 2005 10:44:38 -0000 1.27.4.1 +++ libweakref.tex 2 Jul 2005 19:09:42 -0000 1.27.4.2 @@ -10,6 +10,8 @@ \versionadded{2.1} +% When making changes to the examples in this file, be sure to update +% Lib/test/test_weakref.py::libreftest too! The \module{weakref} module allows the Python programmer to create \dfn{weak references} to objects. @@ -228,7 +230,7 @@ o = r() if o is None: # referent has been garbage collected - print "Object has been allocated; can't frobnicate." + print "Object has been deallocated; can't frobnicate." else: print "Object is still live!" o.do_something_useful() @@ -265,7 +267,7 @@ """Return a pair containing the referent and the number of times the reference has been called. """ - ob = super(ExtendedRef, self)() + ob = super(ExtendedRef, self).__call__() if ob is not None: self.__counter += 1 ob = (ob, self.__counter) From birkenfeld at users.sourceforge.net Sat Jul 2 21:09:44 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 02 Jul 2005 12:09:44 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_weakref.py, 1.42.4.1, 1.42.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4899/Lib/test Modified Files: Tag: release24-maint test_weakref.py Log Message: backport doctest for weakref examples Index: test_weakref.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_weakref.py,v retrieving revision 1.42.4.1 retrieving revision 1.42.4.2 diff -u -d -r1.42.4.1 -r1.42.4.2 --- test_weakref.py 31 Mar 2005 04:07:47 -0000 1.42.4.1 +++ test_weakref.py 2 Jul 2005 19:09:42 -0000 1.42.4.2 @@ -1001,6 +1001,91 @@ def _reference(self): return self.__ref.copy() +libreftest = """ Doctest for examples in the library reference: libweakref.tex + +>>> import weakref +>>> class Dict(dict): +... pass +... +>>> obj = Dict(red=1, green=2, blue=3) # this object is weak referencable +>>> r = weakref.ref(obj) +>>> print r() +{'blue': 3, 'green': 2, 'red': 1} + +>>> import weakref +>>> class Object: +... pass +... +>>> o = Object() +>>> r = weakref.ref(o) +>>> o2 = r() +>>> o is o2 +True +>>> del o, o2 +>>> print r() +None + +>>> import weakref +>>> class ExtendedRef(weakref.ref): +... def __init__(self, ob, callback=None, **annotations): +... super(ExtendedRef, self).__init__(ob, callback) +... self.__counter = 0 +... for k, v in annotations.iteritems(): +... setattr(self, k, v) +... def __call__(self): +... '''Return a pair containing the referent and the number of +... times the reference has been called. +... ''' +... ob = super(ExtendedRef, self).__call__() +... if ob is not None: +... self.__counter += 1 +... ob = (ob, self.__counter) +... return ob +... +>>> class A: # not in docs from here, just testing the ExtendedRef +... pass +... +>>> a = A() +>>> r = ExtendedRef(a, foo=1, bar="baz") +>>> r.foo +1 +>>> r.bar +'baz' +>>> r()[1] +1 +>>> r()[1] +2 +>>> r()[0] is a +True + + +>>> import weakref +>>> _id2obj_dict = weakref.WeakValueDictionary() +>>> def remember(obj): +... oid = id(obj) +... _id2obj_dict[oid] = obj +... return oid +... +>>> def id2obj(oid): +... return _id2obj_dict[oid] +... +>>> a = A() # from here, just testing +>>> a_id = remember(a) +>>> id2obj(a_id) is a +True +>>> del a +>>> try: +... id2obj(a_id) +... except KeyError: +... print 'OK' +... else: +... print 'WeakValueDictionary error' +OK + +""" + +__test__ = {'libreftest' : libreftest} + def test_main(): test_support.run_unittest( ReferencesTestCase, @@ -1008,6 +1093,7 @@ WeakValueDictionaryTestCase, WeakKeyDictionaryTestCase, ) + test_support.run_doctest(sys.modules[__name__]) if __name__ == "__main__": From birkenfeld at users.sourceforge.net Sun Jul 3 22:21:43 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:21:43 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libstdtypes.tex, 1.182, 1.183 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5425/Doc/lib Modified Files: libstdtypes.tex Log Message: bug [ 1162912 ] typesseq-mutable lacks note on combined key/cmp usage Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.182 retrieving revision 1.183 diff -u -d -r1.182 -r1.183 --- libstdtypes.tex 1 Jul 2005 23:18:36 -0000 1.182 +++ libstdtypes.tex 3 Jul 2005 20:21:40 -0000 1.183 @@ -1146,6 +1146,9 @@ because \var{cmp} is called multiple times for each list element while \var{key} and \var{reverse} touch each element only once. + \note{If both \var{key} and \var{cmp} are supplied the \var{key} + function is applied before the \var{cmp} function.} + \versionchanged[Support for \code{None} as an equivalent to omitting \var{cmp} was added]{2.3} From birkenfeld at users.sourceforge.net Sun Jul 3 22:22:15 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:22:15 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libstdtypes.tex, 1.170.2.11, 1.170.2.12 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5460/Doc/lib Modified Files: Tag: release24-maint libstdtypes.tex Log Message: backport bug [ 1162912 ] typesseq-mutable lacks note on combined key/cmp usage Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.170.2.11 retrieving revision 1.170.2.12 diff -u -d -r1.170.2.11 -r1.170.2.12 --- libstdtypes.tex 1 Jul 2005 23:25:27 -0000 1.170.2.11 +++ libstdtypes.tex 3 Jul 2005 20:22:13 -0000 1.170.2.12 @@ -1146,6 +1146,9 @@ because \var{cmp} is called multiple times for each list element while \var{key} and \var{reverse} touch each element only once. + \note{If both \var{key} and \var{cmp} are supplied the \var{key} + function is applied before the \var{cmp} function.} + \versionchanged[Support for \code{None} as an equivalent to omitting \var{cmp} was added]{2.3} From jackjansen at users.sourceforge.net Sun Jul 3 22:57:28 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:57:28 -0700 Subject: [Python-checkins] python/dist/src/Tools/bgen/bgen bgenObjectDefinition.py, 1.31, 1.32 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/bgen/bgen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23904 Modified Files: bgenObjectDefinition.py Log Message: Sigh, changed the argument names in the tp_init function: to make them be more in line with other methods "self" and "args" had to be renamed "_self" and "_args". Did "_kwds" too, for consistency. Index: bgenObjectDefinition.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenObjectDefinition.py,v retrieving revision 1.31 retrieving revision 1.32 diff -u -d -r1.31 -r1.32 --- bgenObjectDefinition.py 29 Jun 2005 14:17:05 -0000 1.31 +++ bgenObjectDefinition.py 3 Jul 2005 20:57:26 -0000 1.32 @@ -385,7 +385,7 @@ def output_tp_init(self): if self.output_tp_initBody: - Output("static int %s_tp_init(PyObject *self, PyObject *args, PyObject *kwds)", self.prefix) + Output("static int %s_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds)", self.prefix) OutLbrace() self.output_tp_initBody() OutRbrace() @@ -407,19 +407,19 @@ Output() def output_tp_newBody(self): - Output("PyObject *self;"); + Output("PyObject *_self;"); Output("%s itself;", self.itselftype); Output("char *kw[] = {\"itself\", 0};") Output() - Output("if (!PyArg_ParseTupleAndKeywords(args, kwds, \"O&\", kw, %s_Convert, &itself)) return NULL;", + Output("if (!PyArg_ParseTupleAndKeywords(_args, _kwds, \"O&\", kw, %s_Convert, &itself)) return NULL;", self.prefix); - Output("if ((self = type->tp_alloc(type, 0)) == NULL) return NULL;") - Output("((%s *)self)->ob_itself = itself;", self.objecttype) - Output("return self;") + Output("if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL;") + Output("((%s *)_self)->ob_itself = itself;", self.objecttype) + Output("return _self;") def output_tp_new(self): if self.output_tp_newBody: - Output("static PyObject *%s_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)", self.prefix) + Output("static PyObject *%s_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds)", self.prefix) OutLbrace() self.output_tp_newBody() OutRbrace() From jackjansen at users.sourceforge.net Sun Jul 3 22:58:11 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:58:11 -0700 Subject: [Python-checkins] python/dist/src/Tools/bgen/bgen bgenGenerator.py, 1.21, 1.22 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/bgen/bgen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24959 Modified Files: bgenGenerator.py Log Message: Factored out the code that creates argument lists and formats for PyArg_Parse and Py_BuildValue. Index: bgenGenerator.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenGenerator.py,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- bgenGenerator.py 1 Jul 2005 20:23:27 -0000 1.21 +++ bgenGenerator.py 3 Jul 2005 20:58:08 -0000 1.22 @@ -187,9 +187,21 @@ arg.declare() def getargs(self): + sep = ",\n" + ' '*len("if (!PyArg_ParseTuple(") + fmt, lst = self.getargsFormatArgs(sep) + Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst) + IndentLevel() + Output("return NULL;") + DedentLevel() + for arg in self.argumentList: + if arg.flags == SelfMode: + continue + if arg.mode in (InMode, InOutMode): + arg.getargsCheck() + + def getargsFormatArgs(self, sep): fmt = "" lst = "" - sep = ",\n" + ' '*len("if (!PyArg_ParseTuple(") for arg in self.argumentList: if arg.flags == SelfMode: continue @@ -199,15 +211,7 @@ args = arg.getargsArgs() if args: lst = lst + sep + args - Output("if (!PyArg_ParseTuple(_args, \"%s\"%s))", fmt, lst) - IndentLevel() - Output("return NULL;") - DedentLevel() - for arg in self.argumentList: - if arg.flags == SelfMode: - continue - if arg.mode in (InMode, InOutMode): - arg.getargsCheck() + return fmt, lst def precheck(self): pass @@ -236,16 +240,8 @@ arg.errorCheck() def returnvalue(self): - fmt = "" - lst = "" sep = ",\n" + ' '*len("return Py_BuildValue(") - for arg in self.argumentList: - if not arg: continue - if arg.flags == ErrorMode: continue - if arg.mode in (OutMode, InOutMode): - arg.mkvaluePreCheck() - fmt = fmt + arg.mkvalueFormat() - lst = lst + sep + arg.mkvalueArgs() + fmt, lst = self.mkvalueFormatArgs(sep) if fmt == "": Output("Py_INCREF(Py_None);") Output("_res = Py_None;"); @@ -258,6 +254,17 @@ arg.cleanup() Output("return _res;") + def mkvalueFormatArgs(self, sep): + fmt = "" + lst = "" + for arg in self.argumentList: + if not arg: continue + if arg.flags == ErrorMode: continue + if arg.mode in (OutMode, InOutMode): + arg.mkvaluePreCheck() + fmt = fmt + arg.mkvalueFormat() + lst = lst + sep + arg.mkvalueArgs() + return fmt, lst class MethodGenerator(FunctionGenerator): From jackjansen at users.sourceforge.net Sun Jul 3 22:59:46 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:59:46 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/snd _Sndmodule.c, 1.18, 1.19 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/snd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/snd Modified Files: _Sndmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Sndmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/snd/_Sndmodule.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- _Sndmodule.c 20 Nov 2003 13:30:59 -0000 1.18 +++ _Sndmodule.c 3 Jul 2005 20:59:43 -0000 1.19 @@ -21,16 +21,16 @@ static int SndCmd_Convert(PyObject *v, SndCommand *pc) { - int len; - pc->param1 = 0; - pc->param2 = 0; - if (PyTuple_Check(v)) { - if (PyArg_ParseTuple(v, "h|hl", &pc->cmd, &pc->param1, &pc->param2)) - return 1; - PyErr_Clear(); - return PyArg_ParseTuple(v, "Hhs#", &pc->cmd, &pc->param1, &pc->param2, &len); - } - return PyArg_Parse(v, "H", &pc->cmd); + int len; + pc->param1 = 0; + pc->param2 = 0; + if (PyTuple_Check(v)) { + if (PyArg_ParseTuple(v, "h|hl", &pc->cmd, &pc->param1, &pc->param2)) + return 1; + PyErr_Clear(); + return PyArg_ParseTuple(v, "Hhs#", &pc->cmd, &pc->param1, &pc->param2, &len); + } + return PyArg_Parse(v, "H", &pc->cmd); } static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd); /* Forward */ @@ -352,9 +352,9 @@ static int SPBObj_set_completionRoutine(SPBObject *self, PyObject *v, void *closure) { self->ob_spb.completionRoutine = NewSICompletionUPP(SPB_completion); - self->ob_completion = v; - Py_INCREF(v); - return 0; + self->ob_completion = v; + Py_INCREF(v); + return 0; return 0; } @@ -1056,62 +1056,62 @@ static int SndCh_CallCallBack(void *arg) { - SndChannelObject *p = (SndChannelObject *)arg; - PyObject *args; - PyObject *res; - args = Py_BuildValue("(O(hhl))", - p, p->ob_cmd.cmd, p->ob_cmd.param1, p->ob_cmd.param2); - res = PyEval_CallObject(p->ob_callback, args); - Py_DECREF(args); - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; + SndChannelObject *p = (SndChannelObject *)arg; + PyObject *args; + PyObject *res; + args = Py_BuildValue("(O(hhl))", + p, p->ob_cmd.cmd, p->ob_cmd.param1, p->ob_cmd.param2); + res = PyEval_CallObject(p->ob_callback, args); + Py_DECREF(args); + if (res == NULL) + return -1; + Py_DECREF(res); + return 0; } /* Routine passed to NewSndChannel -- schedule a call to SndCh_CallCallBack */ static pascal void SndCh_UserRoutine(SndChannelPtr chan, SndCommand *cmd) { - SndChannelObject *p = (SndChannelObject *)(chan->userInfo); - if (p->ob_callback != NULL) { - long A5 = SetA5(p->ob_A5); - p->ob_cmd = *cmd; - Py_AddPendingCall(SndCh_CallCallBack, (void *)p); - SetA5(A5); - } + SndChannelObject *p = (SndChannelObject *)(chan->userInfo); + if (p->ob_callback != NULL) { + long A5 = SetA5(p->ob_A5); + p->ob_cmd = *cmd; + Py_AddPendingCall(SndCh_CallCallBack, (void *)p); + SetA5(A5); + } } /* SPB callbacks - Schedule callbacks to Python */ static int SPB_CallCallBack(void *arg) { - SPBObject *p = (SPBObject *)arg; - PyObject *args; - PyObject *res; - - if ( p->ob_thiscallback == 0 ) return 0; - args = Py_BuildValue("(O)", p); - res = PyEval_CallObject(p->ob_thiscallback, args); - p->ob_thiscallback = 0; - Py_DECREF(args); - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; + SPBObject *p = (SPBObject *)arg; + PyObject *args; + PyObject *res; + + if ( p->ob_thiscallback == 0 ) return 0; + args = Py_BuildValue("(O)", p); + res = PyEval_CallObject(p->ob_thiscallback, args); + p->ob_thiscallback = 0; + Py_DECREF(args); + if (res == NULL) + return -1; + Py_DECREF(res); + return 0; } static pascal void SPB_completion(SPBPtr my_spb) { - SPBObject *p = (SPBObject *)(my_spb->userLong); - - if (p && p->ob_completion) { - long A5 = SetA5(p->ob_A5); - p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */ - Py_AddPendingCall(SPB_CallCallBack, (void *)p); - SetA5(A5); - } + SPBObject *p = (SPBObject *)(my_spb->userLong); + + if (p && p->ob_completion) { + long A5 = SetA5(p->ob_A5); + p->ob_thiscallback = p->ob_completion; /* Hope we cannot get two at the same time */ + Py_AddPendingCall(SPB_CallCallBack, (void *)p); + SetA5(A5); + } } From jackjansen at users.sourceforge.net Sun Jul 3 22:59:45 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:59:45 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/res _Resmodule.c, 1.22, 1.23 ressupport.py, 1.27, 1.28 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/res In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/res Modified Files: _Resmodule.c ressupport.py Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Resmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/res/_Resmodule.c,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- _Resmodule.c 20 Nov 2003 13:30:59 -0000 1.22 +++ _Resmodule.c 3 Jul 2005 20:59:43 -0000 1.23 @@ -32,7 +32,7 @@ static void PyMac_AutoDisposeHandle(Handle h) { - DisposeHandle(h); + DisposeHandle(h); } static PyObject *Res_Error; @@ -59,6 +59,7 @@ it->ob_freeit = NULL; return (PyObject *)it; } + int ResObj_Convert(PyObject *v, Handle *p_itself) { if (!ResObj_Check(v)) @@ -455,13 +456,13 @@ int onoff, old = 0; if (!PyArg_ParseTuple(_args, "i", &onoff)) - return NULL; + return NULL; if ( _self->ob_freeit ) - old = 1; + old = 1; if ( onoff ) - _self->ob_freeit = PyMac_AutoDisposeHandle; + _self->ob_freeit = PyMac_AutoDisposeHandle; else - _self->ob_freeit = NULL; + _self->ob_freeit = NULL; _res = Py_BuildValue("i", old); return _res; @@ -514,42 +515,42 @@ static PyObject *ResObj_get_data(ResourceObject *self, void *closure) { - PyObject *res; - char state; + PyObject *res; + char state; - state = HGetState(self->ob_itself); - HLock(self->ob_itself); - res = PyString_FromStringAndSize( - *self->ob_itself, - GetHandleSize(self->ob_itself)); - HUnlock(self->ob_itself); - HSetState(self->ob_itself, state); - return res; - + state = HGetState(self->ob_itself); + HLock(self->ob_itself); + res = PyString_FromStringAndSize( + *self->ob_itself, + GetHandleSize(self->ob_itself)); + HUnlock(self->ob_itself); + HSetState(self->ob_itself, state); + return res; + } static int ResObj_set_data(ResourceObject *self, PyObject *v, void *closure) { - char *data; - long size; - - if ( v == NULL ) - return -1; - if ( !PyString_Check(v) ) - return -1; - size = PyString_Size(v); - data = PyString_AsString(v); - /* XXXX Do I need the GetState/SetState calls? */ - SetHandleSize(self->ob_itself, size); - if ( MemError()) - return -1; - HLock(self->ob_itself); - memcpy((char *)*self->ob_itself, data, size); - HUnlock(self->ob_itself); - /* XXXX Should I do the Changed call immedeately? */ - return 0; - + char *data; + long size; + + if ( v == NULL ) + return -1; + if ( !PyString_Check(v) ) + return -1; + size = PyString_Size(v); + data = PyString_AsString(v); + /* XXXX Do I need the GetState/SetState calls? */ + SetHandleSize(self->ob_itself, size); + if ( MemError()) + return -1; + HLock(self->ob_itself); + memcpy((char *)*self->ob_itself, data, size); + HUnlock(self->ob_itself); + /* XXXX Should I do the Changed call immedeately? */ + return 0; + return 0; } @@ -572,26 +573,26 @@ #define ResObj_repr NULL #define ResObj_hash NULL -static int ResObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int ResObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { char *srcdata = NULL; int srclen = 0; Handle itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, ResObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, ResObj_Convert, &itself)) { - ((ResourceObject *)self)->ob_itself = itself; + ((ResourceObject *)_self)->ob_itself = itself; return 0; } PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s#", kw, &srcdata, &srclen)) return -1; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "|s#", kw, &srcdata, &srclen)) return -1; if ((itself = NewHandle(srclen)) == NULL) { PyErr_NoMemory(); return 0; } - ((ResourceObject *)self)->ob_itself = itself; + ((ResourceObject *)_self)->ob_itself = itself; if (srclen && srcdata) { HLock(itself); @@ -603,7 +604,7 @@ #define ResObj_tp_alloc PyType_GenericAlloc -static PyObject *ResObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *ResObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -1573,11 +1574,11 @@ ResourceObject *rv; if (!PyArg_ParseTuple(_args, "s#", &buf, &len)) - return NULL; + return NULL; h = NewHandle(len); if ( h == NULL ) { - PyErr_NoMemory(); - return NULL; + PyErr_NoMemory(); + return NULL; } HLock(h); memcpy(*h, buf, len); @@ -1679,35 +1680,35 @@ /* Alternative version of ResObj_New, which returns None for null argument */ PyObject *OptResObj_New(Handle itself) { - if (itself == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return ResObj_New(itself); + if (itself == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return ResObj_New(itself); } int OptResObj_Convert(PyObject *v, Handle *p_itself) { - PyObject *tmp; - - if ( v == Py_None ) { - *p_itself = NULL; - return 1; - } - if (ResObj_Check(v)) - { - *p_itself = ((ResourceObject *)v)->ob_itself; - return 1; - } - /* If it isn't a resource yet see whether it is convertible */ - if ( (tmp=PyObject_CallMethod(v, "as_Resource", "")) ) { - *p_itself = ((ResourceObject *)tmp)->ob_itself; - Py_DECREF(tmp); - return 1; - } - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "Resource required"); - return 0; + PyObject *tmp; + + if ( v == Py_None ) { + *p_itself = NULL; + return 1; + } + if (ResObj_Check(v)) + { + *p_itself = ((ResourceObject *)v)->ob_itself; + return 1; + } + /* If it isn't a resource yet see whether it is convertible */ + if ( (tmp=PyObject_CallMethod(v, "as_Resource", "")) ) { + *p_itself = ((ResourceObject *)tmp)->ob_itself; + Py_DECREF(tmp); + return 1; + } + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, "Resource required"); + return 0; } @@ -1718,10 +1719,10 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(Handle, ResObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Handle, ResObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(Handle, OptResObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Handle, OptResObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(Handle, ResObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Handle, ResObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(Handle, OptResObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Handle, OptResObj_Convert); m = Py_InitModule("_Res", Res_methods); Index: ressupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/res/ressupport.py,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- ressupport.py 18 Jul 2004 05:58:12 -0000 1.27 +++ ressupport.py 3 Jul 2005 20:59:43 -0000 1.28 @@ -182,20 +182,20 @@ Output("%s itself;", self.itselftype); Output("char *kw[] = {\"itself\", 0};") Output() - Output("if (PyArg_ParseTupleAndKeywords(args, kwds, \"O&\", kw, %s_Convert, &itself))", + Output("if (PyArg_ParseTupleAndKeywords(_args, _kwds, \"O&\", kw, %s_Convert, &itself))", self.prefix); OutLbrace() - Output("((%s *)self)->ob_itself = itself;", self.objecttype) + Output("((%s *)_self)->ob_itself = itself;", self.objecttype) Output("return 0;") OutRbrace() Output("PyErr_Clear();") - Output("if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|s#\", kw, &srcdata, &srclen)) return -1;") + Output("if (!PyArg_ParseTupleAndKeywords(_args, _kwds, \"|s#\", kw, &srcdata, &srclen)) return -1;") Output("if ((itself = NewHandle(srclen)) == NULL)") OutLbrace() Output("PyErr_NoMemory();") Output("return 0;") OutRbrace() - Output("((%s *)self)->ob_itself = itself;", self.objecttype) + Output("((%s *)_self)->ob_itself = itself;", self.objecttype) # XXXX Output("((%s *)self)->ob_freeit = PyMac_AutoDisposeHandle;") Output("if (srclen && srcdata)") OutLbrace() From jackjansen at users.sourceforge.net Sun Jul 3 22:59:45 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:59:45 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/qt _Qtmodule.c, 1.24, 1.25 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/qt In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/qt Modified Files: _Qtmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Qtmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/qt/_Qtmodule.c,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- _Qtmodule.c 11 Jan 2004 22:52:11 -0000 1.24 +++ _Qtmodule.c 3 Jul 2005 20:59:42 -0000 1.25 @@ -47,45 +47,45 @@ #endif /* Macro to allow us to GetNextInterestingTime without duration */ -#define GetMediaNextInterestingTimeOnly(media, flags, time, rate, rv) GetMediaNextInterestingTime(media, flags, time, rate, rv, NULL) - +#define GetMediaNextInterestingTimeOnly(media, flags, time, rate, rv) GetMediaNextInterestingTime(media, flags, time, rate, rv, NULL) + /* ** Parse/generate time records */ static PyObject * QtTimeRecord_New(TimeRecord *itself) { - if (itself->base) - return Py_BuildValue("O&lO&", PyMac_Buildwide, &itself->value, itself->scale, - TimeBaseObj_New, itself->base); - else - return Py_BuildValue("O&lO", PyMac_Buildwide, &itself->value, itself->scale, - Py_None); + if (itself->base) + return Py_BuildValue("O&lO&", PyMac_Buildwide, &itself->value, itself->scale, + TimeBaseObj_New, itself->base); + else + return Py_BuildValue("O&lO", PyMac_Buildwide, &itself->value, itself->scale, + Py_None); } static int QtTimeRecord_Convert(PyObject *v, TimeRecord *p_itself) { - PyObject *base = NULL; - if( !PyArg_ParseTuple(v, "O&l|O", PyMac_Getwide, &p_itself->value, &p_itself->scale, - &base) ) - return 0; - if ( base == NULL || base == Py_None ) - p_itself->base = NULL; - else - if ( !TimeBaseObj_Convert(base, &p_itself->base) ) - return 0; - return 1; + PyObject *base = NULL; + if( !PyArg_ParseTuple(v, "O&l|O", PyMac_Getwide, &p_itself->value, &p_itself->scale, + &base) ) + return 0; + if ( base == NULL || base == Py_None ) + p_itself->base = NULL; + else + if ( !TimeBaseObj_Convert(base, &p_itself->base) ) + return 0; + return 1; } static int QtMusicMIDIPacket_Convert(PyObject *v, MusicMIDIPacket *p_itself) { - int dummy; - - if( !PyArg_ParseTuple(v, "hls#", &p_itself->length, &p_itself->reserved, p_itself->data, dummy) ) - return 0; - return 1; + int dummy; + + if( !PyArg_ParseTuple(v, "hls#", &p_itself->length, &p_itself->reserved, p_itself->data, dummy) ) + return 0; + return 1; } @@ -108,14 +108,15 @@ { IdleManagerObject *it; if (itself == NULL) { - PyErr_SetString(Qt_Error,"Cannot create IdleManager from NULL pointer"); - return NULL; - } + PyErr_SetString(Qt_Error,"Cannot create IdleManager from NULL pointer"); + return NULL; + } it = PyObject_NEW(IdleManagerObject, &IdleManager_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int IdleManagerObj_Convert(PyObject *v, IdleManager *p_itself) { if (v == Py_None) @@ -154,16 +155,16 @@ #define IdleManagerObj_tp_alloc PyType_GenericAlloc -static PyObject *IdleManagerObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *IdleManagerObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; IdleManager itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, IdleManagerObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((IdleManagerObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, IdleManagerObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((IdleManagerObject *)_self)->ob_itself = itself; + return _self; } #define IdleManagerObj_tp_free PyObject_Del @@ -231,14 +232,15 @@ { MovieControllerObject *it; if (itself == NULL) { - PyErr_SetString(Qt_Error,"Cannot create MovieController from NULL pointer"); - return NULL; - } + PyErr_SetString(Qt_Error,"Cannot create MovieController from NULL pointer"); + return NULL; + } it = PyObject_NEW(MovieControllerObject, &MovieController_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int MovieCtlObj_Convert(PyObject *v, MovieController *p_itself) { if (v == Py_None) @@ -1273,16 +1275,16 @@ #define MovieCtlObj_tp_alloc PyType_GenericAlloc -static PyObject *MovieCtlObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *MovieCtlObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; MovieController itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, MovieCtlObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((MovieControllerObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, MovieCtlObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((MovieControllerObject *)_self)->ob_itself = itself; + return _self; } #define MovieCtlObj_tp_free PyObject_Del @@ -1350,14 +1352,15 @@ { TimeBaseObject *it; if (itself == NULL) { - PyErr_SetString(Qt_Error,"Cannot create TimeBase from NULL pointer"); - return NULL; - } + PyErr_SetString(Qt_Error,"Cannot create TimeBase from NULL pointer"); + return NULL; + } it = PyObject_NEW(TimeBaseObject, &TimeBase_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int TimeBaseObj_Convert(PyObject *v, TimeBase *p_itself) { if (v == Py_None) @@ -1766,16 +1769,16 @@ #define TimeBaseObj_tp_alloc PyType_GenericAlloc -static PyObject *TimeBaseObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *TimeBaseObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; TimeBase itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, TimeBaseObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((TimeBaseObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, TimeBaseObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((TimeBaseObject *)_self)->ob_itself = itself; + return _self; } #define TimeBaseObj_tp_free PyObject_Del @@ -1843,14 +1846,15 @@ { UserDataObject *it; if (itself == NULL) { - PyErr_SetString(Qt_Error,"Cannot create UserData from NULL pointer"); - return NULL; - } + PyErr_SetString(Qt_Error,"Cannot create UserData from NULL pointer"); + return NULL; + } it = PyObject_NEW(UserDataObject, &UserData_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int UserDataObj_Convert(PyObject *v, UserData *p_itself) { if (v == Py_None) @@ -2136,16 +2140,16 @@ #define UserDataObj_tp_alloc PyType_GenericAlloc -static PyObject *UserDataObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *UserDataObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; UserData itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, UserDataObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((UserDataObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, UserDataObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((UserDataObject *)_self)->ob_itself = itself; + return _self; } #define UserDataObj_tp_free PyObject_Del @@ -2213,14 +2217,15 @@ { MediaObject *it; if (itself == NULL) { - PyErr_SetString(Qt_Error,"Cannot create Media from NULL pointer"); - return NULL; - } + PyErr_SetString(Qt_Error,"Cannot create Media from NULL pointer"); + return NULL; + } it = PyObject_NEW(MediaObject, &Media_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int MediaObj_Convert(PyObject *v, Media *p_itself) { if (v == Py_None) @@ -3377,16 +3382,16 @@ #define MediaObj_tp_alloc PyType_GenericAlloc -static PyObject *MediaObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *MediaObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; Media itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, MediaObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((MediaObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, MediaObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((MediaObject *)_self)->ob_itself = itself; + return _self; } #define MediaObj_tp_free PyObject_Del @@ -3454,14 +3459,15 @@ { TrackObject *it; if (itself == NULL) { - PyErr_SetString(Qt_Error,"Cannot create Track from NULL pointer"); - return NULL; - } + PyErr_SetString(Qt_Error,"Cannot create Track from NULL pointer"); + return NULL; + } it = PyObject_NEW(TrackObject, &Track_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int TrackObj_Convert(PyObject *v, Track *p_itself) { if (v == Py_None) @@ -4724,16 +4730,16 @@ #define TrackObj_tp_alloc PyType_GenericAlloc -static PyObject *TrackObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *TrackObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; Track itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, TrackObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((TrackObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, TrackObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((TrackObject *)_self)->ob_itself = itself; + return _self; } #define TrackObj_tp_free PyObject_Del @@ -4801,14 +4807,15 @@ { MovieObject *it; if (itself == NULL) { - PyErr_SetString(Qt_Error,"Cannot create Movie from NULL pointer"); - return NULL; - } + PyErr_SetString(Qt_Error,"Cannot create Movie from NULL pointer"); + return NULL; + } it = PyObject_NEW(MovieObject, &Movie_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int MovieObj_Convert(PyObject *v, Movie *p_itself) { if (v == Py_None) @@ -7276,16 +7283,16 @@ #define MovieObj_tp_alloc PyType_GenericAlloc -static PyObject *MovieObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *MovieObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; Movie itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, MovieObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((MovieObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, MovieObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((MovieObject *)_self)->ob_itself = itself; + return _self; } #define MovieObj_tp_free PyObject_Del @@ -7353,14 +7360,15 @@ { SGOutputObject *it; if (itself == NULL) { - PyErr_SetString(Qt_Error,"Cannot create SGOutput from NULL pointer"); - return NULL; - } + PyErr_SetString(Qt_Error,"Cannot create SGOutput from NULL pointer"); + return NULL; + } it = PyObject_NEW(SGOutputObject, &SGOutput_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int SGOutputObj_Convert(PyObject *v, SGOutput *p_itself) { if (v == Py_None) @@ -7399,16 +7407,16 @@ #define SGOutputObj_tp_alloc PyType_GenericAlloc -static PyObject *SGOutputObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *SGOutputObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; SGOutput itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, SGOutputObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((SGOutputObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, SGOutputObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((SGOutputObject *)_self)->ob_itself = itself; + return _self; } #define SGOutputObj_tp_free PyObject_Del @@ -27993,18 +28001,18 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(Track, TrackObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Track, TrackObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(Movie, MovieObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Movie, MovieObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(MovieController, MovieCtlObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(MovieController, MovieCtlObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(TimeBase, TimeBaseObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(TimeBase, TimeBaseObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(UserData, UserDataObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(UserData, UserDataObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(Media, MediaObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Media, MediaObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(Track, TrackObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Track, TrackObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(Movie, MovieObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Movie, MovieObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(MovieController, MovieCtlObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(MovieController, MovieCtlObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(TimeBase, TimeBaseObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(TimeBase, TimeBaseObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(UserData, UserDataObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(UserData, UserDataObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(Media, MediaObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Media, MediaObj_Convert); m = Py_InitModule("_Qt", Qt_methods); From jackjansen at users.sourceforge.net Sun Jul 3 22:59:46 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:59:46 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/te _TEmodule.c, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/te In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/te Modified Files: _TEmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _TEmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/te/_TEmodule.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- _TEmodule.c 20 Nov 2003 13:30:59 -0000 1.17 +++ _TEmodule.c 3 Jul 2005 20:59:43 -0000 1.18 @@ -35,21 +35,21 @@ TextStyle_New(TextStylePtr itself) { - return Py_BuildValue("lllO&", (long)itself->tsFont, (long)itself->tsFace, (long)itself->tsSize, QdRGB_New, - &itself->tsColor); + return Py_BuildValue("lllO&", (long)itself->tsFont, (long)itself->tsFace, (long)itself->tsSize, QdRGB_New, + &itself->tsColor); } static int TextStyle_Convert(PyObject *v, TextStylePtr p_itself) { - long font, face, size; - - if( !PyArg_ParseTuple(v, "lllO&", &font, &face, &size, QdRGB_Convert, &p_itself->tsColor) ) - return 0; - p_itself->tsFont = (short)font; - p_itself->tsFace = (Style)face; - p_itself->tsSize = (short)size; - return 1; + long font, face, size; + + if( !PyArg_ParseTuple(v, "lllO&", &font, &face, &size, QdRGB_Convert, &p_itself->tsColor) ) + return 0; + p_itself->tsFont = (short)font; + p_itself->tsFace = (Style)face; + p_itself->tsSize = (short)size; + return 1; } static PyObject *TE_Error; @@ -69,14 +69,15 @@ { TEObject *it; if (itself == NULL) { - PyErr_SetString(TE_Error,"Cannot create null TE"); - return NULL; - } + PyErr_SetString(TE_Error,"Cannot create null TE"); + return NULL; + } it = PyObject_NEW(TEObject, &TE_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int TEObj_Convert(PyObject *v, TEHandle *p_itself) { if (!TEObj_Check(v)) @@ -983,16 +984,16 @@ #define TEObj_tp_alloc PyType_GenericAlloc -static PyObject *TEObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *TEObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; TEHandle itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, TEObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((TEObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, TEObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((TEObject *)_self)->ob_itself = itself; + return _self; } #define TEObj_tp_free PyObject_Del @@ -1307,8 +1308,8 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(TEHandle, TEObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(TEHandle, TEObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(TEHandle, TEObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(TEHandle, TEObj_Convert); m = Py_InitModule("_TE", TE_methods); From jackjansen at users.sourceforge.net Sun Jul 3 22:59:47 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:59:47 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/win _Winmodule.c, 1.22, 1.23 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/win In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/win Modified Files: _Winmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Winmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/win/_Winmodule.c,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- _Winmodule.c 3 Dec 2003 23:20:13 -0000 1.22 +++ _Winmodule.c 3 Jul 2005 20:59:44 -0000 1.23 @@ -36,7 +36,7 @@ static void PyMac_AutoDisposeWindow(WindowPtr w) { - DisposeWindow(w); + DisposeWindow(w); } static PyObject *Win_Error; @@ -69,6 +69,7 @@ } return (PyObject *)it; } + int WinObj_Convert(PyObject *v, WindowPtr *p_itself) { @@ -2309,13 +2310,13 @@ int onoff, old = 0; if (!PyArg_ParseTuple(_args, "i", &onoff)) - return NULL; + return NULL; if ( _self->ob_freeit ) - old = 1; + old = 1; if ( onoff ) - _self->ob_freeit = PyMac_AutoDisposeWindow; + _self->ob_freeit = PyMac_AutoDisposeWindow; else - _self->ob_freeit = NULL; + _self->ob_freeit = NULL; _res = Py_BuildValue("i", old); return _res; @@ -2590,16 +2591,16 @@ #define WinObj_tp_alloc PyType_GenericAlloc -static PyObject *WinObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *WinObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; WindowPtr itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, WinObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((WindowObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, WinObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((WindowObject *)_self)->ob_itself = itself; + return _self; } #define WinObj_tp_free PyObject_Del @@ -3121,7 +3122,7 @@ long ptr; if ( !PyArg_ParseTuple(_args, "i", &ptr) ) - return NULL; + return NULL; _res = WinObj_WhichWindow((WindowPtr)ptr); return _res; @@ -3208,21 +3209,21 @@ PyObject * WinObj_WhichWindow(WindowPtr w) { - PyObject *it; - - if (w == NULL) { - it = Py_None; - Py_INCREF(it); - } else { - it = (PyObject *) GetWRefCon(w); - if (it == NULL || !IsPointerValid((Ptr)it) || ((WindowObject *)it)->ob_itself != w || !WinObj_Check(it)) { - it = WinObj_New(w); - ((WindowObject *)it)->ob_freeit = NULL; - } else { - Py_INCREF(it); - } - } - return it; + PyObject *it; + + if (w == NULL) { + it = Py_None; + Py_INCREF(it); + } else { + it = (PyObject *) GetWRefCon(w); + if (it == NULL || !IsPointerValid((Ptr)it) || ((WindowObject *)it)->ob_itself != w || !WinObj_Check(it)) { + it = WinObj_New(w); + ((WindowObject *)it)->ob_freeit = NULL; + } else { + Py_INCREF(it); + } + } + return it; } @@ -3233,9 +3234,9 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(WindowPtr, WinObj_New); - PyMac_INIT_TOOLBOX_OBJECT_NEW(WindowPtr, WinObj_WhichWindow); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(WindowPtr, WinObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(WindowPtr, WinObj_New); + PyMac_INIT_TOOLBOX_OBJECT_NEW(WindowPtr, WinObj_WhichWindow); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(WindowPtr, WinObj_Convert); m = Py_InitModule("_Win", Win_methods); From jackjansen at users.sourceforge.net Sun Jul 3 22:59:46 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 13:59:46 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/waste wastemodule.c, 1.32, 1.33 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/waste In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/waste Modified Files: wastemodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: wastemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/waste/wastemodule.c,v retrieving revision 1.32 retrieving revision 1.33 diff -u -d -r1.32 -r1.33 --- wastemodule.c 20 Nov 2003 13:30:59 -0000 1.32 +++ wastemodule.c 3 Jul 2005 20:59:44 -0000 1.33 @@ -38,21 +38,21 @@ TextStyle_New(TextStylePtr itself) { - return Py_BuildValue("lllO&", (long)itself->tsFont, (long)itself->tsFace, (long)itself->tsSize, QdRGB_New, - &itself->tsColor); + return Py_BuildValue("lllO&", (long)itself->tsFont, (long)itself->tsFace, (long)itself->tsSize, QdRGB_New, + &itself->tsColor); } static int TextStyle_Convert(PyObject *v, TextStylePtr p_itself) { - long font, face, size; - - if( !PyArg_ParseTuple(v, "lllO&", &font, &face, &size, QdRGB_Convert, &p_itself->tsColor) ) - return 0; - p_itself->tsFont = (short)font; - p_itself->tsFace = (Style)face; - p_itself->tsSize = (short)size; - return 1; + long font, face, size; + + if( !PyArg_ParseTuple(v, "lllO&", &font, &face, &size, QdRGB_Convert, &p_itself->tsColor) ) + return 0; + p_itself->tsFont = (short)font; + p_itself->tsFace = (Style)face; + p_itself->tsSize = (short)size; + return 1; } /* @@ -62,33 +62,33 @@ RunInfo_New(WERunInfo *itself) { - return Py_BuildValue("llhhO&O&", itself->runStart, itself->runEnd, itself->runHeight, - itself->runAscent, TextStyle_New, &itself->runStyle, WEOObj_New, itself->runObject); + return Py_BuildValue("llhhO&O&", itself->runStart, itself->runEnd, itself->runHeight, + itself->runAscent, TextStyle_New, &itself->runStyle, WEOObj_New, itself->runObject); } /* Conversion of long points and rects */ int LongRect_Convert(PyObject *v, LongRect *r) { - return PyArg_Parse(v, "(llll)", &r->left, &r->top, &r->right, &r->bottom); + return PyArg_Parse(v, "(llll)", &r->left, &r->top, &r->right, &r->bottom); } PyObject * LongRect_New(LongRect *r) { - return Py_BuildValue("(llll)", r->left, r->top, r->right, r->bottom); + return Py_BuildValue("(llll)", r->left, r->top, r->right, r->bottom); } int LongPt_Convert(PyObject *v, LongPt *p) { - return PyArg_Parse(v, "(ll)", &p->h, &p->v); + return PyArg_Parse(v, "(ll)", &p->h, &p->v); } PyObject * LongPt_New(LongPt *p) { - return Py_BuildValue("(ll)", p->h, p->v); + return Py_BuildValue("(ll)", p->h, p->v); } /* Stuff for the callbacks: */ @@ -101,110 +101,110 @@ static OSErr any_handler(WESelector what, WEObjectReference who, PyObject *args, PyObject **rv) { - FlavorType tp; - PyObject *key, *func; - - if ( args == NULL ) return errAECorruptData; - - tp = WEGetObjectType(who); - - if( (key=Py_BuildValue("O&O&", PyMac_BuildOSType, tp, PyMac_BuildOSType, what)) == NULL) - return errAECorruptData; - if( (func = PyDict_GetItem(callbackdict, key)) == NULL ) { - Py_DECREF(key); - return errAEHandlerNotFound; - } - Py_INCREF(func); - *rv = PyEval_CallObject(func, args); - Py_DECREF(func); - Py_DECREF(key); - if ( *rv == NULL ) { - PySys_WriteStderr("--Exception in callback: "); - PyErr_Print(); - return errAEReplyNotArrived; - } - return 0; + FlavorType tp; + PyObject *key, *func; + + if ( args == NULL ) return errAECorruptData; + + tp = WEGetObjectType(who); + + if( (key=Py_BuildValue("O&O&", PyMac_BuildOSType, tp, PyMac_BuildOSType, what)) == NULL) + return errAECorruptData; + if( (func = PyDict_GetItem(callbackdict, key)) == NULL ) { + Py_DECREF(key); + return errAEHandlerNotFound; + } + Py_INCREF(func); + *rv = PyEval_CallObject(func, args); + Py_DECREF(func); + Py_DECREF(key); + if ( *rv == NULL ) { + PySys_WriteStderr("--Exception in callback: "); + PyErr_Print(); + return errAEReplyNotArrived; + } + return 0; } static pascal OSErr my_new_handler(Point *objectSize, WEObjectReference objref) { - PyObject *args=NULL, *rv=NULL; - OSErr err; - - args=Py_BuildValue("(O&)", WEOObj_New, objref); - err = any_handler(weNewHandler, objref, args, &rv); - if (!err) { - if (!PyMac_GetPoint(rv, objectSize) ) - err = errAECoercionFail; - } - if ( args ) { - Py_DECREF(args); - } - if ( rv ) { - Py_DECREF(rv); - } - return err; + PyObject *args=NULL, *rv=NULL; + OSErr err; + + args=Py_BuildValue("(O&)", WEOObj_New, objref); + err = any_handler(weNewHandler, objref, args, &rv); + if (!err) { + if (!PyMac_GetPoint(rv, objectSize) ) + err = errAECoercionFail; + } + if ( args ) { + Py_DECREF(args); + } + if ( rv ) { + Py_DECREF(rv); + } + return err; } static pascal OSErr my_dispose_handler(WEObjectReference objref) { - PyObject *args=NULL, *rv=NULL; - OSErr err; - - args=Py_BuildValue("(O&)", WEOObj_New, objref); - err = any_handler(weDisposeHandler, objref, args, &rv); - if ( args ) { - Py_DECREF(args); - } - if ( rv ) { - Py_DECREF(rv); - } - return err; + PyObject *args=NULL, *rv=NULL; + OSErr err; + + args=Py_BuildValue("(O&)", WEOObj_New, objref); + err = any_handler(weDisposeHandler, objref, args, &rv); + if ( args ) { + Py_DECREF(args); + } + if ( rv ) { + Py_DECREF(rv); + } + return err; } static pascal OSErr my_draw_handler(const Rect *destRect, WEObjectReference objref) { - PyObject *args=NULL, *rv=NULL; - OSErr err; - - args=Py_BuildValue("O&O&", PyMac_BuildRect, destRect, WEOObj_New, objref); - err = any_handler(weDrawHandler, objref, args, &rv); - if ( args ) { - Py_DECREF(args); - } - if ( rv ) { - Py_DECREF(rv); - } - return err; + PyObject *args=NULL, *rv=NULL; + OSErr err; + + args=Py_BuildValue("O&O&", PyMac_BuildRect, destRect, WEOObj_New, objref); + err = any_handler(weDrawHandler, objref, args, &rv); + if ( args ) { + Py_DECREF(args); + } + if ( rv ) { + Py_DECREF(rv); + } + return err; } static pascal Boolean my_click_handler(Point hitPt, EventModifiers modifiers, - unsigned long clickTime, WEObjectReference objref) + unsigned long clickTime, WEObjectReference objref) { - PyObject *args=NULL, *rv=NULL; - int retvalue; - OSErr err; - - args=Py_BuildValue("O&llO&", PyMac_BuildPoint, hitPt, - (long)modifiers, (long)clickTime, WEOObj_New, objref); - err = any_handler(weClickHandler, objref, args, &rv); - if (!err) - retvalue = PyInt_AsLong(rv); - else - retvalue = 0; - if ( args ) { - Py_DECREF(args); - } - if ( rv ) { - Py_DECREF(rv); - } - return retvalue; + PyObject *args=NULL, *rv=NULL; + int retvalue; + OSErr err; + + args=Py_BuildValue("O&llO&", PyMac_BuildPoint, hitPt, + (long)modifiers, (long)clickTime, WEOObj_New, objref); + err = any_handler(weClickHandler, objref, args, &rv); + if (!err) + retvalue = PyInt_AsLong(rv); + else + retvalue = 0; + if ( args ) { + Py_DECREF(args); + } + if ( rv ) { + Py_DECREF(rv); + } + return retvalue; } - + static PyObject *waste_Error; @@ -224,14 +224,15 @@ { WEOObject *it; if (itself == NULL) { - Py_INCREF(Py_None); - return Py_None; - } + Py_INCREF(Py_None); + return Py_None; + } it = PyObject_NEW(WEOObject, &WEO_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int WEOObj_Convert(PyObject *v, WEObjectReference *p_itself) { if (!WEOObj_Check(v)) @@ -400,16 +401,16 @@ #define WEOObj_tp_alloc PyType_GenericAlloc -static PyObject *WEOObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *WEOObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; WEObjectReference itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, WEOObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((WEOObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, WEOObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((WEOObject *)_self)->ob_itself = itself; + return _self; } #define WEOObj_tp_free PyObject_Del @@ -477,15 +478,16 @@ { wasteObject *it; if (itself == NULL) { - PyErr_SetString(waste_Error,"Cannot create null WE"); - return NULL; - } + PyErr_SetString(waste_Error,"Cannot create null WE"); + return NULL; + } it = PyObject_NEW(wasteObject, &waste_Type); if (it == NULL) return NULL; it->ob_itself = itself; WESetInfo(weRefCon, (void *)&it, itself); return (PyObject *)it; } + int wasteObj_Convert(PyObject *v, WEReference *p_itself) { if (!wasteObj_Check(v)) @@ -2149,16 +2151,16 @@ #define wasteObj_tp_alloc PyType_GenericAlloc -static PyObject *wasteObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *wasteObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; WEReference itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, wasteObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((wasteObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, wasteObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((wasteObject *)_self)->ob_itself = itself; + return _self; } #define wasteObj_tp_free PyObject_Del @@ -2418,42 +2420,42 @@ { PyObject *_res = NULL; - OSErr err; - // install the sample object handlers for pictures and sounds -#define kTypePicture 'PICT' -#define kTypeSound 'snd ' - - if ( !PyArg_ParseTuple(_args, "") ) return NULL; - - if ((err = WEInstallObjectHandler(kTypePicture, weNewHandler, - (UniversalProcPtr) NewWENewObjectProc(HandleNewPicture), NULL)) != noErr) - goto cleanup; - - if ((err = WEInstallObjectHandler(kTypePicture, weDisposeHandler, - (UniversalProcPtr) NewWEDisposeObjectProc(HandleDisposePicture), NULL)) != noErr) - goto cleanup; - - if ((err = WEInstallObjectHandler(kTypePicture, weDrawHandler, - (UniversalProcPtr) NewWEDrawObjectProc(HandleDrawPicture), NULL)) != noErr) - goto cleanup; - - if ((err = WEInstallObjectHandler(kTypeSound, weNewHandler, - (UniversalProcPtr) NewWENewObjectProc(HandleNewSound), NULL)) != noErr) - goto cleanup; - - if ((err = WEInstallObjectHandler(kTypeSound, weDrawHandler, - (UniversalProcPtr) NewWEDrawObjectProc(HandleDrawSound), NULL)) != noErr) - goto cleanup; - - if ((err = WEInstallObjectHandler(kTypeSound, weClickHandler, - (UniversalProcPtr) NewWEClickObjectProc(HandleClickSound), NULL)) != noErr) - goto cleanup; - Py_INCREF(Py_None); - _res = Py_None; - return _res; - + OSErr err; + // install the sample object handlers for pictures and sounds +#define kTypePicture 'PICT' +#define kTypeSound 'snd ' + + if ( !PyArg_ParseTuple(_args, "") ) return NULL; + + if ((err = WEInstallObjectHandler(kTypePicture, weNewHandler, + (UniversalProcPtr) NewWENewObjectProc(HandleNewPicture), NULL)) != noErr) + goto cleanup; + + if ((err = WEInstallObjectHandler(kTypePicture, weDisposeHandler, + (UniversalProcPtr) NewWEDisposeObjectProc(HandleDisposePicture), NULL)) != noErr) + goto cleanup; + + if ((err = WEInstallObjectHandler(kTypePicture, weDrawHandler, + (UniversalProcPtr) NewWEDrawObjectProc(HandleDrawPicture), NULL)) != noErr) + goto cleanup; + + if ((err = WEInstallObjectHandler(kTypeSound, weNewHandler, + (UniversalProcPtr) NewWENewObjectProc(HandleNewSound), NULL)) != noErr) + goto cleanup; + + if ((err = WEInstallObjectHandler(kTypeSound, weDrawHandler, + (UniversalProcPtr) NewWEDrawObjectProc(HandleDrawSound), NULL)) != noErr) + goto cleanup; + + if ((err = WEInstallObjectHandler(kTypeSound, weClickHandler, + (UniversalProcPtr) NewWEClickObjectProc(HandleClickSound), NULL)) != noErr) + goto cleanup; + Py_INCREF(Py_None); + _res = Py_None; + return _res; + cleanup: - return PyMac_Error(err); + return PyMac_Error(err); } @@ -2461,39 +2463,39 @@ { PyObject *_res = NULL; - OSErr err; - FlavorType objectType; - WESelector selector; - PyObject *py_handler; - UniversalProcPtr handler; - WEReference we = NULL; - PyObject *key; - - - if ( !PyArg_ParseTuple(_args, "O&O&O|O&", - PyMac_GetOSType, &objectType, - PyMac_GetOSType, &selector, - &py_handler, - WEOObj_Convert, &we) ) return NULL; - - if ( selector == weNewHandler ) handler = (UniversalProcPtr)upp_new_handler; - else if ( selector == weDisposeHandler ) handler = (UniversalProcPtr)upp_dispose_handler; - else if ( selector == weDrawHandler ) handler = (UniversalProcPtr)upp_draw_handler; - else if ( selector == weClickHandler ) handler = (UniversalProcPtr)upp_click_handler; - else return PyMac_Error(weUndefinedSelectorErr); - - if ((key = Py_BuildValue("O&O&", - PyMac_BuildOSType, objectType, - PyMac_BuildOSType, selector)) == NULL ) - return NULL; - - PyDict_SetItem(callbackdict, key, py_handler); - - err = WEInstallObjectHandler(objectType, selector, handler, we); - if ( err ) return PyMac_Error(err); - Py_INCREF(Py_None); - _res = Py_None; - return _res; + OSErr err; + FlavorType objectType; + WESelector selector; + PyObject *py_handler; + UniversalProcPtr handler; + WEReference we = NULL; + PyObject *key; + + + if ( !PyArg_ParseTuple(_args, "O&O&O|O&", + PyMac_GetOSType, &objectType, + PyMac_GetOSType, &selector, + &py_handler, + WEOObj_Convert, &we) ) return NULL; + + if ( selector == weNewHandler ) handler = (UniversalProcPtr)upp_new_handler; + else if ( selector == weDisposeHandler ) handler = (UniversalProcPtr)upp_dispose_handler; + else if ( selector == weDrawHandler ) handler = (UniversalProcPtr)upp_draw_handler; + else if ( selector == weClickHandler ) handler = (UniversalProcPtr)upp_click_handler; + else return PyMac_Error(weUndefinedSelectorErr); + + if ((key = Py_BuildValue("O&O&", + PyMac_BuildOSType, objectType, + PyMac_BuildOSType, selector)) == NULL ) + return NULL; + + PyDict_SetItem(callbackdict, key, py_handler); + + err = WEInstallObjectHandler(objectType, selector, handler, we); + if ( err ) return PyMac_Error(err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; } @@ -2535,18 +2537,18 @@ PyObject * ExistingwasteObj_New(w) - WEReference w; + WEReference w; { - PyObject *it = NULL; - - if (w == NULL) - it = NULL; - else - WEGetInfo(weRefCon, (void *)&it, w); - if (it == NULL || ((wasteObject *)it)->ob_itself != w) - it = Py_None; - Py_INCREF(it); - return it; + PyObject *it = NULL; + + if (w == NULL) + it = NULL; + else + WEGetInfo(weRefCon, (void *)&it, w); + if (it == NULL || ((wasteObject *)it)->ob_itself != w) + it = Py_None; + Py_INCREF(it); + return it; } @@ -2579,13 +2581,13 @@ Py_INCREF(&waste_Type); PyModule_AddObject(m, "wasteType", (PyObject *)&waste_Type); - callbackdict = PyDict_New(); - if (callbackdict == NULL || PyDict_SetItemString(d, "callbacks", callbackdict) != 0) - return; - upp_new_handler = NewWENewObjectProc(my_new_handler); - upp_dispose_handler = NewWEDisposeObjectProc(my_dispose_handler); - upp_draw_handler = NewWEDrawObjectProc(my_draw_handler); - upp_click_handler = NewWEClickObjectProc(my_click_handler); + callbackdict = PyDict_New(); + if (callbackdict == NULL || PyDict_SetItemString(d, "callbacks", callbackdict) != 0) + return; + upp_new_handler = NewWENewObjectProc(my_new_handler); + upp_dispose_handler = NewWEDisposeObjectProc(my_dispose_handler); + upp_draw_handler = NewWEDrawObjectProc(my_draw_handler); + upp_click_handler = NewWEClickObjectProc(my_click_handler); } From jackjansen at users.sourceforge.net Sun Jul 3 23:00:11 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:11 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/cg _CGmodule.c, 1.15, 1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cg In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/cg Modified Files: _CGmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _CGmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cg/_CGmodule.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- _CGmodule.c 3 Dec 2003 23:20:10 -0000 1.15 +++ _CGmodule.c 3 Jul 2005 20:59:37 -0000 1.16 @@ -26,67 +26,67 @@ PyObject *CGPoint_New(CGPoint *itself) { - return Py_BuildValue("(ff)", - itself->x, - itself->y); + return Py_BuildValue("(ff)", + itself->x, + itself->y); } int CGPoint_Convert(PyObject *v, CGPoint *p_itself) { - if( !PyArg_Parse(v, "(ff)", - &p_itself->x, - &p_itself->y) ) - return 0; - return 1; + if( !PyArg_Parse(v, "(ff)", + &p_itself->x, + &p_itself->y) ) + return 0; + return 1; } PyObject *CGRect_New(CGRect *itself) { - return Py_BuildValue("(ffff)", - itself->origin.x, - itself->origin.y, - itself->size.width, - itself->size.height); + return Py_BuildValue("(ffff)", + itself->origin.x, + itself->origin.y, + itself->size.width, + itself->size.height); } int CGRect_Convert(PyObject *v, CGRect *p_itself) { - if( !PyArg_Parse(v, "(ffff)", - &p_itself->origin.x, - &p_itself->origin.y, - &p_itself->size.width, - &p_itself->size.height) ) - return 0; - return 1; + if( !PyArg_Parse(v, "(ffff)", + &p_itself->origin.x, + &p_itself->origin.y, + &p_itself->size.width, + &p_itself->size.height) ) + return 0; + return 1; } PyObject *CGAffineTransform_New(CGAffineTransform *itself) { - return Py_BuildValue("(ffffff)", - itself->a, - itself->b, - itself->c, - itself->d, - itself->tx, - itself->ty); + return Py_BuildValue("(ffffff)", + itself->a, + itself->b, + itself->c, + itself->d, + itself->tx, + itself->ty); } int CGAffineTransform_Convert(PyObject *v, CGAffineTransform *p_itself) { - if( !PyArg_Parse(v, "(ffffff)", - &p_itself->a, - &p_itself->b, - &p_itself->c, - &p_itself->d, - &p_itself->tx, - &p_itself->ty) ) - return 0; - return 1; + if( !PyArg_Parse(v, "(ffffff)", + &p_itself->a, + &p_itself->b, + &p_itself->c, + &p_itself->d, + &p_itself->tx, + &p_itself->ty) ) + return 0; + return 1; } static PyObject *CG_Error; @@ -110,6 +110,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int CGContextRefObj_Convert(PyObject *v, CGContextRef *p_itself) { if (!CGContextRefObj_Check(v)) @@ -1191,16 +1192,16 @@ #define CGContextRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CGContextRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CGContextRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; CGContextRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CGContextRefObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((CGContextRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CGContextRefObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((CGContextRefObject *)_self)->ob_itself = itself; + return _self; } #define CGContextRefObj_tp_free PyObject_Del @@ -1261,11 +1262,11 @@ OSStatus _err; if (!PyArg_ParseTuple(_args, "O&", GrafObj_Convert, &port)) - return NULL; + return NULL; _err = CreateCGContextForPort(port, &ctx); if (_err != noErr) - if (_err != noErr) return PyMac_Error(_err); + if (_err != noErr) return PyMac_Error(_err); _res = Py_BuildValue("O&", CGContextRefObj_New, ctx); return _res; From jackjansen at users.sourceforge.net Sun Jul 3 23:00:11 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:11 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/app _Appmodule.c, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/app In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/app Modified Files: _Appmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Appmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/app/_Appmodule.c,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- _Appmodule.c 20 Nov 2003 13:30:55 -0000 1.19 +++ _Appmodule.c 3 Jul 2005 20:59:37 -0000 1.20 @@ -20,7 +20,7 @@ int ThemeButtonDrawInfo_Convert(PyObject *v, ThemeButtonDrawInfo *p_itself) { - return PyArg_Parse(v, "(iHH)", &p_itself->state, &p_itself->value, &p_itself->adornment); + return PyArg_Parse(v, "(iHH)", &p_itself->state, &p_itself->value, &p_itself->adornment); } @@ -45,6 +45,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int ThemeDrawingStateObj_Convert(PyObject *v, ThemeDrawingState *p_itself) { if (!ThemeDrawingStateObj_Check(v)) @@ -115,16 +116,16 @@ #define ThemeDrawingStateObj_tp_alloc PyType_GenericAlloc -static PyObject *ThemeDrawingStateObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *ThemeDrawingStateObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; ThemeDrawingState itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, ThemeDrawingStateObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((ThemeDrawingStateObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, ThemeDrawingStateObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((ThemeDrawingStateObject *)_self)->ob_itself = itself; + return _self; } #define ThemeDrawingStateObj_tp_free PyObject_Del From jackjansen at users.sourceforge.net Sun Jul 3 23:00:11 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:11 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/ae _AEmodule.c, 1.22, 1.23 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/ae In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/ae Modified Files: _AEmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _AEmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/ae/_AEmodule.c,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- _AEmodule.c 20 Nov 2003 13:30:55 -0000 1.22 +++ _AEmodule.c 3 Jul 2005 20:59:36 -0000 1.23 @@ -34,9 +34,9 @@ static pascal Boolean AEIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn) { - if ( PyOS_InterruptOccurred() ) - return 1; - return 0; + if ( PyOS_InterruptOccurred() ) + return 1; + return 0; } AEIdleUPP upp_AEIdleProc; @@ -64,6 +64,7 @@ it->ob_owned = 1; return (PyObject *)it; } + int AEDesc_Convert(PyObject *v, AEDesc *p_itself) { if (!AEDesc_Check(v)) @@ -829,20 +830,20 @@ static PyObject *AEDesc_get_data(AEDescObject *self, void *closure) { - PyObject *res; - Size size; - char *ptr; - OSErr err; - - size = AEGetDescDataSize(&self->ob_itself); - if ( (res = PyString_FromStringAndSize(NULL, size)) == NULL ) - return NULL; - if ( (ptr = PyString_AsString(res)) == NULL ) - return NULL; - if ( (err=AEGetDescData(&self->ob_itself, ptr, size)) < 0 ) - return PyMac_Error(err); - return res; - + PyObject *res; + Size size; + char *ptr; + OSErr err; + + size = AEGetDescDataSize(&self->ob_itself); + if ( (res = PyString_FromStringAndSize(NULL, size)) == NULL ) + return NULL; + if ( (ptr = PyString_AsString(res)) == NULL ) + return NULL; + if ( (err=AEGetDescData(&self->ob_itself, ptr, size)) < 0 ) + return PyMac_Error(err); + return res; + } #define AEDesc_set_data NULL @@ -863,16 +864,16 @@ #define AEDesc_tp_alloc PyType_GenericAlloc -static PyObject *AEDesc_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *AEDesc_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; AEDesc itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, AEDesc_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((AEDescObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, AEDesc_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((AEDescObject *)_self)->ob_itself = itself; + return _self; } #define AEDesc_tp_free PyObject_Del @@ -1383,44 +1384,44 @@ static pascal OSErr GenericEventHandler(const AppleEvent *request, AppleEvent *reply, refcontype refcon) { - PyObject *handler = (PyObject *)refcon; - AEDescObject *requestObject, *replyObject; - PyObject *args, *res; - if ((requestObject = (AEDescObject *)AEDesc_New((AppleEvent *)request)) == NULL) { - return -1; - } - if ((replyObject = (AEDescObject *)AEDesc_New(reply)) == NULL) { - Py_DECREF(requestObject); - return -1; - } - if ((args = Py_BuildValue("OO", requestObject, replyObject)) == NULL) { - Py_DECREF(requestObject); - Py_DECREF(replyObject); - return -1; - } - res = PyEval_CallObject(handler, args); - requestObject->ob_itself.descriptorType = 'null'; - requestObject->ob_itself.dataHandle = NULL; - replyObject->ob_itself.descriptorType = 'null'; - replyObject->ob_itself.dataHandle = NULL; - Py_DECREF(args); - if (res == NULL) { - PySys_WriteStderr("Exception in AE event handler function\n"); - PyErr_Print(); - return -1; - } - Py_DECREF(res); - return noErr; + PyObject *handler = (PyObject *)refcon; + AEDescObject *requestObject, *replyObject; + PyObject *args, *res; + if ((requestObject = (AEDescObject *)AEDesc_New((AppleEvent *)request)) == NULL) { + return -1; + } + if ((replyObject = (AEDescObject *)AEDesc_New(reply)) == NULL) { + Py_DECREF(requestObject); + return -1; + } + if ((args = Py_BuildValue("OO", requestObject, replyObject)) == NULL) { + Py_DECREF(requestObject); + Py_DECREF(replyObject); + return -1; + } + res = PyEval_CallObject(handler, args); + requestObject->ob_itself.descriptorType = 'null'; + requestObject->ob_itself.dataHandle = NULL; + replyObject->ob_itself.descriptorType = 'null'; + replyObject->ob_itself.dataHandle = NULL; + Py_DECREF(args); + if (res == NULL) { + PySys_WriteStderr("Exception in AE event handler function\n"); + PyErr_Print(); + return -1; + } + Py_DECREF(res); + return noErr; } PyObject *AEDesc_NewBorrowed(AEDesc *itself) { - PyObject *it; - - it = AEDesc_New(itself); - if (it) - ((AEDescObject *)it)->ob_owned = 0; - return (PyObject *)it; + PyObject *it; + + it = AEDesc_New(itself); + if (it) + ((AEDescObject *)it)->ob_owned = 0; + return (PyObject *)it; } @@ -1432,11 +1433,11 @@ - upp_AEIdleProc = NewAEIdleUPP(AEIdleProc); - upp_GenericEventHandler = NewAEEventHandlerUPP(GenericEventHandler); - PyMac_INIT_TOOLBOX_OBJECT_NEW(AEDesc *, AEDesc_New); - PyMac_INIT_TOOLBOX_OBJECT_NEW(AEDesc *, AEDesc_NewBorrowed); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(AEDesc, AEDesc_Convert); + upp_AEIdleProc = NewAEIdleUPP(AEIdleProc); + upp_GenericEventHandler = NewAEEventHandlerUPP(GenericEventHandler); + PyMac_INIT_TOOLBOX_OBJECT_NEW(AEDesc *, AEDesc_New); + PyMac_INIT_TOOLBOX_OBJECT_NEW(AEDesc *, AEDesc_NewBorrowed); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(AEDesc, AEDesc_Convert); m = Py_InitModule("_AE", AE_methods); From jackjansen at users.sourceforge.net Sun Jul 3 23:00:11 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:11 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/cm _Cmmodule.c, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cm In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/cm Modified Files: _Cmmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Cmmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cm/_Cmmodule.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- _Cmmodule.c 20 Nov 2003 13:30:56 -0000 1.17 +++ _Cmmodule.c 3 Jul 2005 20:59:38 -0000 1.18 @@ -36,21 +36,21 @@ CmpDesc_New(ComponentDescription *itself) { - return Py_BuildValue("O&O&O&ll", - PyMac_BuildOSType, itself->componentType, - PyMac_BuildOSType, itself->componentSubType, - PyMac_BuildOSType, itself->componentManufacturer, - itself->componentFlags, itself->componentFlagsMask); + return Py_BuildValue("O&O&O&ll", + PyMac_BuildOSType, itself->componentType, + PyMac_BuildOSType, itself->componentSubType, + PyMac_BuildOSType, itself->componentManufacturer, + itself->componentFlags, itself->componentFlagsMask); } static int CmpDesc_Convert(PyObject *v, ComponentDescription *p_itself) { - return PyArg_ParseTuple(v, "O&O&O&ll", - PyMac_GetOSType, &p_itself->componentType, - PyMac_GetOSType, &p_itself->componentSubType, - PyMac_GetOSType, &p_itself->componentManufacturer, - &p_itself->componentFlags, &p_itself->componentFlagsMask); + return PyArg_ParseTuple(v, "O&O&O&ll", + PyMac_GetOSType, &p_itself->componentType, + PyMac_GetOSType, &p_itself->componentSubType, + PyMac_GetOSType, &p_itself->componentManufacturer, + &p_itself->componentFlags, &p_itself->componentFlagsMask); } @@ -71,14 +71,15 @@ { ComponentInstanceObject *it; if (itself == NULL) { - PyErr_SetString(Cm_Error,"NULL ComponentInstance"); - return NULL; - } + PyErr_SetString(Cm_Error,"NULL ComponentInstance"); + return NULL; + } it = PyObject_NEW(ComponentInstanceObject, &ComponentInstance_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int CmpInstObj_Convert(PyObject *v, ComponentInstance *p_itself) { if (!CmpInstObj_Check(v)) @@ -260,16 +261,16 @@ #define CmpInstObj_tp_alloc PyType_GenericAlloc -static PyObject *CmpInstObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CmpInstObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; ComponentInstance itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CmpInstObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((ComponentInstanceObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CmpInstObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((ComponentInstanceObject *)_self)->ob_itself = itself; + return _self; } #define CmpInstObj_tp_free PyObject_Del @@ -337,21 +338,22 @@ { ComponentObject *it; if (itself == NULL) { - /* XXXX Or should we return None? */ - PyErr_SetString(Cm_Error,"No such component"); - return NULL; - } + /* XXXX Or should we return None? */ + PyErr_SetString(Cm_Error,"No such component"); + return NULL; + } it = PyObject_NEW(ComponentObject, &Component_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int CmpObj_Convert(PyObject *v, Component *p_itself) { if ( v == Py_None ) { - *p_itself = 0; - return 1; - } + *p_itself = 0; + return 1; + } if (!CmpObj_Check(v)) { PyErr_SetString(PyExc_TypeError, "Component required"); @@ -693,16 +695,16 @@ #define CmpObj_tp_alloc PyType_GenericAlloc -static PyObject *CmpObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CmpObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; Component itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CmpObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((ComponentObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CmpObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((ComponentObject *)_self)->ob_itself = itself; + return _self; } #define CmpObj_tp_free PyObject_Del @@ -913,10 +915,10 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(Component, CmpObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Component, CmpObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(ComponentInstance, CmpInstObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(ComponentInstance, CmpInstObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(Component, CmpObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(Component, CmpObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(ComponentInstance, CmpInstObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(ComponentInstance, CmpInstObj_Convert); m = Py_InitModule("_Cm", Cm_methods); From jackjansen at users.sourceforge.net Sun Jul 3 23:00:12 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:12 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/dlg _Dlgmodule.c, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/dlg In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/dlg Modified Files: _Dlgmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Dlgmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/dlg/_Dlgmodule.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- _Dlgmodule.c 20 Nov 2003 13:30:56 -0000 1.20 +++ _Dlgmodule.c 3 Jul 2005 20:59:39 -0000 1.21 @@ -34,55 +34,55 @@ EventRecord *event, short *itemHit) { - Boolean rv; - PyObject *args, *res; - PyObject *callback = Dlg_FilterProc_callback; - if (callback == NULL) - return 0; /* Default behavior */ - Dlg_FilterProc_callback = NULL; /* We'll restore it when call successful */ - args = Py_BuildValue("O&O&", DlgObj_WhichDialog, dialog, PyMac_BuildEventRecord, event); - if (args == NULL) - res = NULL; - else { - res = PyEval_CallObject(callback, args); - Py_DECREF(args); - } - if (res == NULL) { - PySys_WriteStderr("Exception in Dialog Filter\n"); - PyErr_Print(); - *itemHit = -1; /* Fake return item */ - return 1; /* We handled it */ - } - else { - Dlg_FilterProc_callback = callback; - if (PyInt_Check(res)) { - *itemHit = PyInt_AsLong(res); - rv = 1; - } - else - rv = PyObject_IsTrue(res); - } - Py_DECREF(res); - return rv; + Boolean rv; + PyObject *args, *res; + PyObject *callback = Dlg_FilterProc_callback; + if (callback == NULL) + return 0; /* Default behavior */ + Dlg_FilterProc_callback = NULL; /* We'll restore it when call successful */ + args = Py_BuildValue("O&O&", DlgObj_WhichDialog, dialog, PyMac_BuildEventRecord, event); + if (args == NULL) + res = NULL; + else { + res = PyEval_CallObject(callback, args); + Py_DECREF(args); + } + if (res == NULL) { + PySys_WriteStderr("Exception in Dialog Filter\n"); + PyErr_Print(); + *itemHit = -1; /* Fake return item */ + return 1; /* We handled it */ + } + else { + Dlg_FilterProc_callback = callback; + if (PyInt_Check(res)) { + *itemHit = PyInt_AsLong(res); + rv = 1; + } + else + rv = PyObject_IsTrue(res); + } + Py_DECREF(res); + return rv; } static ModalFilterUPP Dlg_PassFilterProc(PyObject *callback) { - PyObject *tmp = Dlg_FilterProc_callback; - static ModalFilterUPP UnivFilterUpp = NULL; - - Dlg_FilterProc_callback = NULL; - if (callback == Py_None) { - Py_XDECREF(tmp); - return NULL; - } - Py_INCREF(callback); - Dlg_FilterProc_callback = callback; - Py_XDECREF(tmp); - if ( UnivFilterUpp == NULL ) - UnivFilterUpp = NewModalFilterUPP(&Dlg_UnivFilterProc); - return UnivFilterUpp; + PyObject *tmp = Dlg_FilterProc_callback; + static ModalFilterUPP UnivFilterUpp = NULL; + + Dlg_FilterProc_callback = NULL; + if (callback == Py_None) { + Py_XDECREF(tmp); + return NULL; + } + Py_INCREF(callback); + Dlg_FilterProc_callback = callback; + Py_XDECREF(tmp); + if ( UnivFilterUpp == NULL ) + UnivFilterUpp = NewModalFilterUPP(&Dlg_UnivFilterProc); + return UnivFilterUpp; } static PyObject *Dlg_UserItemProc_callback = NULL; @@ -90,24 +90,24 @@ static pascal void Dlg_UnivUserItemProc(DialogPtr dialog, short item) { - PyObject *args, *res; + PyObject *args, *res; - if (Dlg_UserItemProc_callback == NULL) - return; /* Default behavior */ - Dlg_FilterProc_callback = NULL; /* We'll restore it when call successful */ - args = Py_BuildValue("O&h", DlgObj_WhichDialog, dialog, item); - if (args == NULL) - res = NULL; - else { - res = PyEval_CallObject(Dlg_UserItemProc_callback, args); - Py_DECREF(args); - } - if (res == NULL) { - PySys_WriteStderr("Exception in Dialog UserItem proc\n"); - PyErr_Print(); - } - Py_XDECREF(res); - return; + if (Dlg_UserItemProc_callback == NULL) + return; /* Default behavior */ + Dlg_FilterProc_callback = NULL; /* We'll restore it when call successful */ + args = Py_BuildValue("O&h", DlgObj_WhichDialog, dialog, item); + if (args == NULL) + res = NULL; + else { + res = PyEval_CallObject(Dlg_UserItemProc_callback, args); + Py_DECREF(args); + } + if (res == NULL) { + PySys_WriteStderr("Exception in Dialog UserItem proc\n"); + PyErr_Print(); + } + Py_XDECREF(res); + return; } #if 0 @@ -146,6 +146,7 @@ SetWRefCon(GetDialogWindow(itself), (long)it); return (PyObject *)it; } + int DlgObj_Convert(PyObject *v, DialogPtr *p_itself) { if (v == Py_None) { *p_itself = NULL; return 1; } @@ -958,16 +959,16 @@ #define DlgObj_tp_alloc PyType_GenericAlloc -static PyObject *DlgObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *DlgObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; DialogPtr itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, DlgObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((DialogObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, DlgObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((DialogObject *)_self)->ob_itself = itself; + return _self; } #define DlgObj_tp_free PyObject_Del @@ -1452,28 +1453,28 @@ { PyObject *_res = NULL; - PyObject *new = NULL; - - - if (!PyArg_ParseTuple(_args, "|O", &new)) - return NULL; + PyObject *new = NULL; - if (Dlg_UserItemProc_callback && new && new != Py_None) { - PyErr_SetString(Dlg_Error, "Another UserItemProc is already installed"); - return NULL; - } - - if (new == NULL || new == Py_None) { - new = NULL; - _res = Py_None; - Py_INCREF(Py_None); - } else { - Py_INCREF(new); - _res = Py_BuildValue("O&", ResObj_New, (Handle)NewUserItemUPP(Dlg_UnivUserItemProc)); - } - - Dlg_UserItemProc_callback = new; - return _res; + + if (!PyArg_ParseTuple(_args, "|O", &new)) + return NULL; + + if (Dlg_UserItemProc_callback && new && new != Py_None) { + PyErr_SetString(Dlg_Error, "Another UserItemProc is already installed"); + return NULL; + } + + if (new == NULL || new == Py_None) { + new = NULL; + _res = Py_None; + Py_INCREF(Py_None); + } else { + Py_INCREF(new); + _res = Py_BuildValue("O&", ResObj_New, (Handle)NewUserItemUPP(Dlg_UnivUserItemProc)); + } + + Dlg_UserItemProc_callback = new; + return _res; } @@ -1528,9 +1529,9 @@ WindowPtr DlgObj_ConvertToWindow(PyObject *self) { - if ( DlgObj_Check(self) ) - return GetDialogWindow(((DialogObject *)self)->ob_itself); - return NULL; + if ( DlgObj_Check(self) ) + return GetDialogWindow(((DialogObject *)self)->ob_itself); + return NULL; } #endif /* Return the object corresponding to the dialog, or None */ @@ -1538,29 +1539,29 @@ PyObject * DlgObj_WhichDialog(DialogPtr d) { - PyObject *it; - - if (d == NULL) { - it = Py_None; - Py_INCREF(it); - } else { - WindowPtr w = GetDialogWindow(d); - - it = (PyObject *) GetWRefCon(w); - if (it == NULL || ((DialogObject *)it)->ob_itself != d || !DlgObj_Check(it)) { + PyObject *it; + + if (d == NULL) { + it = Py_None; + Py_INCREF(it); + } else { + WindowPtr w = GetDialogWindow(d); + + it = (PyObject *) GetWRefCon(w); + if (it == NULL || ((DialogObject *)it)->ob_itself != d || !DlgObj_Check(it)) { #if 0 - /* Should do this, but we don't have an ob_freeit for dialogs yet. */ - it = WinObj_New(w); - ((WindowObject *)it)->ob_freeit = NULL; + /* Should do this, but we don't have an ob_freeit for dialogs yet. */ + it = WinObj_New(w); + ((WindowObject *)it)->ob_freeit = NULL; #else - it = Py_None; - Py_INCREF(it); + it = Py_None; + Py_INCREF(it); #endif - } else { - Py_INCREF(it); - } - } - return it; + } else { + Py_INCREF(it); + } + } + return it; } @@ -1571,9 +1572,9 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(DialogPtr, DlgObj_New); - PyMac_INIT_TOOLBOX_OBJECT_NEW(DialogPtr, DlgObj_WhichDialog); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(DialogPtr, DlgObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(DialogPtr, DlgObj_New); + PyMac_INIT_TOOLBOX_OBJECT_NEW(DialogPtr, DlgObj_WhichDialog); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(DialogPtr, DlgObj_Convert); m = Py_InitModule("_Dlg", Dlg_methods); From jackjansen at users.sourceforge.net Sun Jul 3 23:00:11 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:11 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/carbonevt _CarbonEvtmodule.c, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/carbonevt In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/carbonevt Modified Files: _CarbonEvtmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _CarbonEvtmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/carbonevt/_CarbonEvtmodule.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- _CarbonEvtmodule.c 6 Dec 2003 00:00:00 -0000 1.17 +++ _CarbonEvtmodule.c 3 Jul 2005 20:59:37 -0000 1.18 @@ -30,17 +30,17 @@ static PyObject* EventTypeSpec_New(EventTypeSpec *in) { - return Py_BuildValue("ll", in->eventClass, in->eventKind); + return Py_BuildValue("ll", in->eventClass, in->eventKind); } static int EventTypeSpec_Convert(PyObject *v, EventTypeSpec *out) { - if (PyArg_Parse(v, "(O&l)", - PyMac_GetOSType, &(out->eventClass), - &(out->eventKind))) - return 1; - return NULL; + if (PyArg_Parse(v, "(O&l)", + PyMac_GetOSType, &(out->eventClass), + &(out->eventKind))) + return 1; + return NULL; } /********** end EventTypeSpec *******/ @@ -51,15 +51,15 @@ static PyObject* HIPoint_New(HIPoint *in) { - return Py_BuildValue("ff", in->x, in->y); + return Py_BuildValue("ff", in->x, in->y); } static int HIPoint_Convert(PyObject *v, HIPoint *out) { - if (PyArg_ParseTuple(v, "ff", &(out->x), &(out->y))) - return 1; - return NULL; + if (PyArg_ParseTuple(v, "ff", &(out->x), &(out->y))) + return 1; + return NULL; } #endif @@ -70,15 +70,15 @@ static PyObject* EventHotKeyID_New(EventHotKeyID *in) { - return Py_BuildValue("ll", in->signature, in->id); + return Py_BuildValue("ll", in->signature, in->id); } static int EventHotKeyID_Convert(PyObject *v, EventHotKeyID *out) { - if (PyArg_ParseTuple(v, "ll", &out->signature, &out->id)) - return 1; - return NULL; + if (PyArg_ParseTuple(v, "ll", &out->signature, &out->id)) + return 1; + return NULL; } /********** end EventHotKeyID *******/ @@ -89,27 +89,27 @@ static pascal OSStatus myEventHandler(EventHandlerCallRef handlerRef, EventRef event, void *outPyObject) { - PyObject *retValue; - int status; + PyObject *retValue; + int status; - retValue = PyObject_CallFunction((PyObject *)outPyObject, "O&O&", - EventHandlerCallRef_New, handlerRef, - EventRef_New, event); - if (retValue == NULL) { - PySys_WriteStderr("Error in event handler callback:\n"); - PyErr_Print(); /* this also clears the error */ - status = noErr; /* complain? how? */ - } else { - if (retValue == Py_None) - status = noErr; - else if (PyInt_Check(retValue)) { - status = PyInt_AsLong(retValue); - } else - status = noErr; /* wrong object type, complain? */ - Py_DECREF(retValue); - } + retValue = PyObject_CallFunction((PyObject *)outPyObject, "O&O&", + EventHandlerCallRef_New, handlerRef, + EventRef_New, event); + if (retValue == NULL) { + PySys_WriteStderr("Error in event handler callback:\n"); + PyErr_Print(); /* this also clears the error */ + status = noErr; /* complain? how? */ + } else { + if (retValue == Py_None) + status = noErr; + else if (PyInt_Check(retValue)) { + status = PyInt_AsLong(retValue); + } else + status = noErr; /* wrong object type, complain? */ + Py_DECREF(retValue); + } - return status; + return status; } /******** end myEventHandler ***********/ @@ -136,6 +136,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int EventRef_Convert(PyObject *v, EventRef *p_itself) { if (!EventRef_Check(v)) @@ -399,16 +400,16 @@ #define EventRef_tp_alloc PyType_GenericAlloc -static PyObject *EventRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *EventRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; EventRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, EventRef_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((EventRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, EventRef_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((EventRefObject *)_self)->ob_itself = itself; + return _self; } #define EventRef_tp_free PyObject_Del @@ -480,6 +481,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int EventQueueRef_Convert(PyObject *v, EventQueueRef *p_itself) { if (!EventQueueRef_Check(v)) @@ -619,16 +621,16 @@ #define EventQueueRef_tp_alloc PyType_GenericAlloc -static PyObject *EventQueueRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *EventQueueRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; EventQueueRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, EventQueueRef_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((EventQueueRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, EventQueueRef_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((EventQueueRefObject *)_self)->ob_itself = itself; + return _self; } #define EventQueueRef_tp_free PyObject_Del @@ -700,6 +702,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int EventLoopRef_Convert(PyObject *v, EventLoopRef *p_itself) { if (!EventLoopRef_Check(v)) @@ -748,16 +751,16 @@ #define EventLoopRef_tp_alloc PyType_GenericAlloc -static PyObject *EventLoopRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *EventLoopRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; EventLoopRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, EventLoopRef_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((EventLoopRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, EventLoopRef_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((EventLoopRefObject *)_self)->ob_itself = itself; + return _self; } #define EventLoopRef_tp_free PyObject_Del @@ -829,6 +832,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int EventLoopTimerRef_Convert(PyObject *v, EventLoopTimerRef *p_itself) { if (!EventLoopTimerRef_Check(v)) @@ -895,16 +899,16 @@ #define EventLoopTimerRef_tp_alloc PyType_GenericAlloc -static PyObject *EventLoopTimerRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *EventLoopTimerRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; EventLoopTimerRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, EventLoopTimerRef_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((EventLoopTimerRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, EventLoopTimerRef_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((EventLoopTimerRefObject *)_self)->ob_itself = itself; + return _self; } #define EventLoopTimerRef_tp_free PyObject_Del @@ -978,6 +982,7 @@ it->ob_callback = NULL; return (PyObject *)it; } + int EventHandlerRef_Convert(PyObject *v, EventHandlerRef *p_itself) { if (!EventHandlerRef_Check(v)) @@ -1050,11 +1055,11 @@ OSStatus _err; if (_self->ob_itself == NULL) { - PyErr_SetString(CarbonEvents_Error, "Handler has been removed"); - return NULL; + PyErr_SetString(CarbonEvents_Error, "Handler has been removed"); + return NULL; } if (!PyArg_ParseTuple(_args, "")) - return NULL; + return NULL; _err = RemoveEventHandler(_self->ob_itself); if (_err != noErr) return PyMac_Error(_err); _self->ob_itself = NULL; @@ -1087,16 +1092,16 @@ #define EventHandlerRef_tp_alloc PyType_GenericAlloc -static PyObject *EventHandlerRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *EventHandlerRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; EventHandlerRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, EventHandlerRef_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((EventHandlerRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, EventHandlerRef_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((EventHandlerRefObject *)_self)->ob_itself = itself; + return _self; } #define EventHandlerRef_tp_free PyObject_Del @@ -1168,6 +1173,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int EventHandlerCallRef_Convert(PyObject *v, EventHandlerCallRef *p_itself) { if (!EventHandlerCallRef_Check(v)) @@ -1219,16 +1225,16 @@ #define EventHandlerCallRef_tp_alloc PyType_GenericAlloc -static PyObject *EventHandlerCallRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *EventHandlerCallRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; EventHandlerCallRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, EventHandlerCallRef_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((EventHandlerCallRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, EventHandlerCallRef_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((EventHandlerCallRefObject *)_self)->ob_itself = itself; + return _self; } #define EventHandlerCallRef_tp_free PyObject_Del @@ -1300,6 +1306,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int EventTargetRef_Convert(PyObject *v, EventTargetRef *p_itself) { if (!EventTargetRef_Check(v)) @@ -1340,15 +1347,15 @@ OSStatus _err; if (!PyArg_ParseTuple(_args, "O&O", EventTypeSpec_Convert, &inSpec, &callback)) - return NULL; + return NULL; _err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef); if (_err != noErr) return PyMac_Error(_err); _res = EventHandlerRef_New(outRef); if (_res != NULL) { - ((EventHandlerRefObject*)_res)->ob_callback = callback; - Py_INCREF(callback); + ((EventHandlerRefObject*)_res)->ob_callback = callback; + Py_INCREF(callback); } return _res; } @@ -1373,16 +1380,16 @@ #define EventTargetRef_tp_alloc PyType_GenericAlloc -static PyObject *EventTargetRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *EventTargetRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; EventTargetRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, EventTargetRef_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((EventTargetRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, EventTargetRef_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((EventTargetRefObject *)_self)->ob_itself = itself; + return _self; } #define EventTargetRef_tp_free PyObject_Del @@ -1454,6 +1461,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int EventHotKeyRef_Convert(PyObject *v, EventHotKeyRef *p_itself) { if (!EventHotKeyRef_Check(v)) @@ -1502,16 +1510,16 @@ #define EventHotKeyRef_tp_alloc PyType_GenericAlloc -static PyObject *EventHotKeyRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *EventHotKeyRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; EventHotKeyRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, EventHotKeyRef_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((EventHotKeyRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, EventHotKeyRef_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((EventHotKeyRefObject *)_self)->ob_itself = itself; + return _self; } #define EventHotKeyRef_tp_free PyObject_Del From jackjansen at users.sourceforge.net Sun Jul 3 23:00:11 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:11 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/cf _CFmodule.c, 1.27, 1.28 cfsupport.py, 1.28, 1.29 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/cf In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/cf Modified Files: _CFmodule.c cfsupport.py Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _CFmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cf/_CFmodule.c,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- _CFmodule.c 15 Jul 2004 14:25:48 -0000 1.27 +++ _CFmodule.c 3 Jul 2005 20:59:37 -0000 1.28 @@ -84,19 +84,19 @@ PyObject *CFRange_New(CFRange *itself) { - return Py_BuildValue("ll", (long)itself->location, (long)itself->length); + return Py_BuildValue("ll", (long)itself->location, (long)itself->length); } int CFRange_Convert(PyObject *v, CFRange *p_itself) { - long location, length; - - if( !PyArg_ParseTuple(v, "ll", &location, &length) ) - return 0; - p_itself->location = (CFIndex)location; - p_itself->length = (CFIndex)length; - return 1; + long location, length; + + if( !PyArg_ParseTuple(v, "ll", &location, &length) ) + return 0; + p_itself->location = (CFIndex)location; + p_itself->length = (CFIndex)length; + return 1; } /* Optional CFURL argument or None (passed as NULL) */ @@ -104,8 +104,8 @@ OptionalCFURLRefObj_Convert(PyObject *v, CFURLRef *p_itself) { if ( v == Py_None ) { - p_itself = NULL; - return 1; + p_itself = NULL; + return 1; } return CFURLRefObj_Convert(v, p_itself); } @@ -138,6 +138,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFTypeRefObj_Convert(PyObject *v, CFTypeRef *p_itself) { @@ -322,16 +323,16 @@ CFStringRef errorString; if (!PyArg_ParseTuple(_args, "l", &mutabilityOption)) - return NULL; + return NULL; _rv = CFPropertyListCreateFromXMLData((CFAllocatorRef)NULL, _self->ob_itself, mutabilityOption, &errorString); if (errorString) - CFRelease(errorString); + CFRelease(errorString); if (_rv == NULL) { - PyErr_SetString(PyExc_RuntimeError, "Parse error in XML data"); - return NULL; + PyErr_SetString(PyExc_RuntimeError, "Parse error in XML data"); + return NULL; } _res = Py_BuildValue("O&", CFTypeRefObj_New, _rv); @@ -399,14 +400,14 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFTypeRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFTypeRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFTypeRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFTypeRefObject *)self)->ob_itself = itself; + ((CFTypeRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -414,7 +415,7 @@ #define CFTypeRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFTypeRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFTypeRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -500,6 +501,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFArrayRefObj_Convert(PyObject *v, CFArrayRef *p_itself) { @@ -602,21 +604,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFArrayRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFArrayRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFArrayRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFArrayRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFArrayRefObj_Convert, &itself)) { - ((CFArrayRefObject *)self)->ob_itself = itself; + ((CFArrayRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFArrayRefObject *)self)->ob_itself = itself; + ((CFArrayRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -624,7 +626,7 @@ #define CFArrayRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFArrayRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFArrayRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -710,6 +712,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFMutableArrayRefObj_Convert(PyObject *v, CFMutableArrayRef *p_itself) { @@ -841,21 +844,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFMutableArrayRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFMutableArrayRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFMutableArrayRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFMutableArrayRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFMutableArrayRefObj_Convert, &itself)) { - ((CFMutableArrayRefObject *)self)->ob_itself = itself; + ((CFMutableArrayRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFMutableArrayRefObject *)self)->ob_itself = itself; + ((CFMutableArrayRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -863,7 +866,7 @@ #define CFMutableArrayRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFMutableArrayRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFMutableArrayRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -949,6 +952,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFDictionaryRefObj_Convert(PyObject *v, CFDictionaryRef *p_itself) { @@ -1033,21 +1037,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFDictionaryRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFDictionaryRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFDictionaryRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFDictionaryRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFDictionaryRefObj_Convert, &itself)) { - ((CFDictionaryRefObject *)self)->ob_itself = itself; + ((CFDictionaryRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFDictionaryRefObject *)self)->ob_itself = itself; + ((CFDictionaryRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -1055,7 +1059,7 @@ #define CFDictionaryRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFDictionaryRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFDictionaryRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -1141,6 +1145,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFMutableDictionaryRefObj_Convert(PyObject *v, CFMutableDictionaryRef *p_itself) { @@ -1209,21 +1214,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFMutableDictionaryRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFMutableDictionaryRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFMutableDictionaryRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFMutableDictionaryRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFMutableDictionaryRefObj_Convert, &itself)) { - ((CFMutableDictionaryRefObject *)self)->ob_itself = itself; + ((CFMutableDictionaryRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFMutableDictionaryRefObject *)self)->ob_itself = itself; + ((CFMutableDictionaryRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -1231,7 +1236,7 @@ #define CFMutableDictionaryRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFMutableDictionaryRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFMutableDictionaryRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -1317,6 +1322,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFDataRefObj_Convert(PyObject *v, CFDataRef *p_itself) { @@ -1439,21 +1445,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFDataRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFDataRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFDataRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFDataRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFDataRefObj_Convert, &itself)) { - ((CFDataRefObject *)self)->ob_itself = itself; + ((CFDataRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFDataRefObject *)self)->ob_itself = itself; + ((CFDataRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -1461,7 +1467,7 @@ #define CFDataRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFDataRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFDataRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -1547,6 +1553,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFMutableDataRefObj_Convert(PyObject *v, CFMutableDataRef *p_itself) { @@ -1703,21 +1710,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFMutableDataRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFMutableDataRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFMutableDataRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFMutableDataRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFMutableDataRefObj_Convert, &itself)) { - ((CFMutableDataRefObject *)self)->ob_itself = itself; + ((CFMutableDataRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFMutableDataRefObject *)self)->ob_itself = itself; + ((CFMutableDataRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -1725,7 +1732,7 @@ #define CFMutableDataRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFMutableDataRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFMutableDataRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -1811,6 +1818,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFStringRefObj_Convert(PyObject *v, CFStringRef *p_itself) { @@ -1818,19 +1826,19 @@ if (PyString_Check(v)) { char *cStr; if (!PyArg_Parse(v, "es", "ascii", &cStr)) - return NULL; - *p_itself = CFStringCreateWithCString((CFAllocatorRef)NULL, cStr, kCFStringEncodingASCII); - return 1; + return NULL; + *p_itself = CFStringCreateWithCString((CFAllocatorRef)NULL, cStr, kCFStringEncodingASCII); + return 1; } if (PyUnicode_Check(v)) { - /* We use the CF types here, if Python was configured differently that will give an error */ - CFIndex size = PyUnicode_GetSize(v); - UniChar *unichars = PyUnicode_AsUnicode(v); - if (!unichars) return 0; - *p_itself = CFStringCreateWithCharacters((CFAllocatorRef)NULL, unichars, size); - return 1; + /* We use the CF types here, if Python was configured differently that will give an error */ + CFIndex size = PyUnicode_GetSize(v); + UniChar *unichars = PyUnicode_AsUnicode(v); + if (!unichars) return 0; + *p_itself = CFStringCreateWithCharacters((CFAllocatorRef)NULL, unichars, size); + return 1; } - + if (!CFStringRefObj_Check(v)) { @@ -2335,10 +2343,10 @@ if( data == NULL ) return PyErr_NoMemory(); if ( CFStringGetCString(_self->ob_itself, data, size, 0) ) { - _res = (PyObject *)PyString_FromString(data); + _res = (PyObject *)PyString_FromString(data); } else { - PyErr_SetString(PyExc_RuntimeError, "CFStringGetCString could not fit the string"); - _res = NULL; + PyErr_SetString(PyExc_RuntimeError, "CFStringGetCString could not fit the string"); + _res = NULL; } free(data); return _res; @@ -2444,21 +2452,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFStringRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFStringRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFStringRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFStringRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFStringRefObj_Convert, &itself)) { - ((CFStringRefObject *)self)->ob_itself = itself; + ((CFStringRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFStringRefObject *)self)->ob_itself = itself; + ((CFStringRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -2466,7 +2474,7 @@ #define CFStringRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFStringRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFStringRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -2552,6 +2560,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFMutableStringRefObj_Convert(PyObject *v, CFMutableStringRef *p_itself) { @@ -2831,21 +2840,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFMutableStringRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFMutableStringRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFMutableStringRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFMutableStringRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFMutableStringRefObj_Convert, &itself)) { - ((CFMutableStringRefObject *)self)->ob_itself = itself; + ((CFMutableStringRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFMutableStringRefObject *)self)->ob_itself = itself; + ((CFMutableStringRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -2853,7 +2862,7 @@ #define CFMutableStringRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFMutableStringRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFMutableStringRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -2939,6 +2948,7 @@ it->ob_freeit = CFRelease; return (PyObject *)it; } + int CFURLRefObj_Convert(PyObject *v, CFURLRef *p_itself) { @@ -3482,21 +3492,21 @@ /* XXXX Or should we use CFHash?? */ return (int)self->ob_itself; } -static int CFURLRefObj_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int CFURLRefObj_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { CFURLRef itself; char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFURLRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFURLRefObj_Convert, &itself)) { - ((CFURLRefObject *)self)->ob_itself = itself; + ((CFURLRefObject *)_self)->ob_itself = itself; return 0; } /* Any CFTypeRef descendent is allowed as initializer too */ - if (PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CFTypeRefObj_Convert, &itself)) { - ((CFURLRefObject *)self)->ob_itself = itself; + ((CFURLRefObject *)_self)->ob_itself = itself; return 0; } return -1; @@ -3504,7 +3514,7 @@ #define CFURLRefObj_tp_alloc PyType_GenericAlloc -static PyObject *CFURLRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CFURLRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; @@ -4678,17 +4688,17 @@ CFTypeID typeid; if (!PyArg_ParseTuple(_args, "O&", PyCF_Python2CF, &rv)) - return NULL; + return NULL; typeid = CFGetTypeID(rv); if (typeid == CFStringGetTypeID()) - return Py_BuildValue("O&", CFStringRefObj_New, rv); + return Py_BuildValue("O&", CFStringRefObj_New, rv); if (typeid == CFArrayGetTypeID()) - return Py_BuildValue("O&", CFArrayRefObj_New, rv); + return Py_BuildValue("O&", CFArrayRefObj_New, rv); if (typeid == CFDictionaryGetTypeID()) - return Py_BuildValue("O&", CFDictionaryRefObj_New, rv); + return Py_BuildValue("O&", CFDictionaryRefObj_New, rv); if (typeid == CFURLGetTypeID()) - return Py_BuildValue("O&", CFURLRefObj_New, rv); + return Py_BuildValue("O&", CFURLRefObj_New, rv); _res = Py_BuildValue("O&", CFTypeRefObj_New, rv); return _res; @@ -4817,42 +4827,42 @@ /* Routines to convert any CF type to/from the corresponding CFxxxObj */ PyObject *CFObj_New(CFTypeRef itself) { - if (itself == NULL) - { - PyErr_SetString(PyExc_RuntimeError, "cannot wrap NULL"); - return NULL; - } - if (CFGetTypeID(itself) == CFArrayGetTypeID()) return CFArrayRefObj_New((CFArrayRef)itself); - if (CFGetTypeID(itself) == CFDictionaryGetTypeID()) return CFDictionaryRefObj_New((CFDictionaryRef)itself); - if (CFGetTypeID(itself) == CFDataGetTypeID()) return CFDataRefObj_New((CFDataRef)itself); - if (CFGetTypeID(itself) == CFStringGetTypeID()) return CFStringRefObj_New((CFStringRef)itself); - if (CFGetTypeID(itself) == CFURLGetTypeID()) return CFURLRefObj_New((CFURLRef)itself); - /* XXXX Or should we use PyCF_CF2Python here?? */ - return CFTypeRefObj_New(itself); + if (itself == NULL) + { + PyErr_SetString(PyExc_RuntimeError, "cannot wrap NULL"); + return NULL; + } + if (CFGetTypeID(itself) == CFArrayGetTypeID()) return CFArrayRefObj_New((CFArrayRef)itself); + if (CFGetTypeID(itself) == CFDictionaryGetTypeID()) return CFDictionaryRefObj_New((CFDictionaryRef)itself); + if (CFGetTypeID(itself) == CFDataGetTypeID()) return CFDataRefObj_New((CFDataRef)itself); + if (CFGetTypeID(itself) == CFStringGetTypeID()) return CFStringRefObj_New((CFStringRef)itself); + if (CFGetTypeID(itself) == CFURLGetTypeID()) return CFURLRefObj_New((CFURLRef)itself); + /* XXXX Or should we use PyCF_CF2Python here?? */ + return CFTypeRefObj_New(itself); } int CFObj_Convert(PyObject *v, CFTypeRef *p_itself) { - if (v == Py_None) { *p_itself = NULL; return 1; } - /* Check for other CF objects here */ + if (v == Py_None) { *p_itself = NULL; return 1; } + /* Check for other CF objects here */ - if (!CFTypeRefObj_Check(v) && - !CFArrayRefObj_Check(v) && - !CFMutableArrayRefObj_Check(v) && - !CFDictionaryRefObj_Check(v) && - !CFMutableDictionaryRefObj_Check(v) && - !CFDataRefObj_Check(v) && - !CFMutableDataRefObj_Check(v) && - !CFStringRefObj_Check(v) && - !CFMutableStringRefObj_Check(v) && - !CFURLRefObj_Check(v) ) - { - /* XXXX Or should we use PyCF_Python2CF here?? */ - PyErr_SetString(PyExc_TypeError, "CF object required"); - return 0; - } - *p_itself = ((CFTypeRefObject *)v)->ob_itself; - return 1; + if (!CFTypeRefObj_Check(v) && + !CFArrayRefObj_Check(v) && + !CFMutableArrayRefObj_Check(v) && + !CFDictionaryRefObj_Check(v) && + !CFMutableDictionaryRefObj_Check(v) && + !CFDataRefObj_Check(v) && + !CFMutableDataRefObj_Check(v) && + !CFStringRefObj_Check(v) && + !CFMutableStringRefObj_Check(v) && + !CFURLRefObj_Check(v) ) + { + /* XXXX Or should we use PyCF_Python2CF here?? */ + PyErr_SetString(PyExc_TypeError, "CF object required"); + return 0; + } + *p_itself = ((CFTypeRefObject *)v)->ob_itself; + return 1; } Index: cfsupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/cf/cfsupport.py,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- cfsupport.py 18 Jul 2004 05:58:08 -0000 1.28 +++ cfsupport.py 3 Jul 2005 20:59:37 -0000 1.29 @@ -315,18 +315,18 @@ Output("%s itself;", self.itselftype) Output("char *kw[] = {\"itself\", 0};") Output() - Output("if (PyArg_ParseTupleAndKeywords(args, kwds, \"O&\", kw, %s_Convert, &itself))", + Output("if (PyArg_ParseTupleAndKeywords(_args, _kwds, \"O&\", kw, %s_Convert, &itself))", self.prefix) OutLbrace() - Output("((%s *)self)->ob_itself = itself;", self.objecttype) + Output("((%s *)_self)->ob_itself = itself;", self.objecttype) Output("return 0;") OutRbrace() if self.prefix != 'CFTypeRefObj': Output() Output("/* Any CFTypeRef descendent is allowed as initializer too */") - Output("if (PyArg_ParseTupleAndKeywords(args, kwds, \"O&\", kw, CFTypeRefObj_Convert, &itself))") + Output("if (PyArg_ParseTupleAndKeywords(_args, _kwds, \"O&\", kw, CFTypeRefObj_Convert, &itself))") OutLbrace() - Output("((%s *)self)->ob_itself = itself;", self.objecttype) + Output("((%s *)_self)->ob_itself = itself;", self.objecttype) Output("return 0;") OutRbrace() Output("return -1;") From jackjansen at users.sourceforge.net Sun Jul 3 23:00:12 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:12 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/ctl _Ctlmodule.c, 1.28, 1.29 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/ctl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/ctl Modified Files: _Ctlmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Ctlmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/ctl/_Ctlmodule.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- _Ctlmodule.c 3 Dec 2003 23:20:11 -0000 1.28 +++ _Ctlmodule.c 3 Jul 2005 20:59:39 -0000 1.29 @@ -40,19 +40,19 @@ ControlFontStyle_New(ControlFontStyleRec *itself) { - return Py_BuildValue("hhhhhhO&O&", itself->flags, itself->font, - itself->size, itself->style, itself->mode, itself->just, - QdRGB_New, &itself->foreColor, QdRGB_New, &itself->backColor); + return Py_BuildValue("hhhhhhO&O&", itself->flags, itself->font, + itself->size, itself->style, itself->mode, itself->just, + QdRGB_New, &itself->foreColor, QdRGB_New, &itself->backColor); } #endif static int ControlFontStyle_Convert(PyObject *v, ControlFontStyleRec *itself) { - return PyArg_Parse(v, "(hhhhhhO&O&)", &itself->flags, - &itself->font, &itself->size, &itself->style, &itself->mode, - &itself->just, QdRGB_Convert, &itself->foreColor, - QdRGB_Convert, &itself->backColor); + return PyArg_Parse(v, "(hhhhhhO&O&)", &itself->flags, + &itself->font, &itself->size, &itself->style, &itself->mode, + &itself->just, QdRGB_Convert, &itself->foreColor, + QdRGB_Convert, &itself->backColor); } /* @@ -62,13 +62,13 @@ PyControlID_New(ControlID *itself) { - return Py_BuildValue("O&l", PyMac_BuildOSType, itself->signature, itself->id); + return Py_BuildValue("O&l", PyMac_BuildOSType, itself->signature, itself->id); } static int PyControlID_Convert(PyObject *v, ControlID *itself) { - return PyArg_Parse(v, "(O&l)", PyMac_GetOSType, &itself->signature, &itself->id); + return PyArg_Parse(v, "(O&l)", PyMac_GetOSType, &itself->signature, &itself->id); } /* @@ -77,40 +77,40 @@ static int DataBrowserTableViewColumnDesc_Convert(PyObject *v, DataBrowserTableViewColumnDesc *itself) { - return PyArg_Parse(v, "(lO&l)", - &itself->propertyID, - PyMac_GetOSType, &itself->propertyType, - &itself->propertyFlags); + return PyArg_Parse(v, "(lO&l)", + &itself->propertyID, + PyMac_GetOSType, &itself->propertyType, + &itself->propertyFlags); } static int ControlButtonContentInfo_Convert(PyObject *v, ControlButtonContentInfo *itself) { - return PyArg_Parse(v, "(hO&)", - &itself->contentType, - OptResObj_Convert, &itself->u.iconSuite); + return PyArg_Parse(v, "(hO&)", + &itself->contentType, + OptResObj_Convert, &itself->u.iconSuite); } static int DataBrowserListViewHeaderDesc_Convert(PyObject *v, DataBrowserListViewHeaderDesc *itself) { - itself->version = kDataBrowserListViewLatestHeaderDesc; - return PyArg_Parse(v, "(HHhO&HO&O&)", - &itself->minimumWidth, - &itself->maximumWidth, - &itself->titleOffset, - CFStringRefObj_Convert, &itself->titleString, - &itself->initialOrder, - ControlFontStyle_Convert, &itself->btnFontStyle, - ControlButtonContentInfo_Convert, &itself->btnContentInfo); + itself->version = kDataBrowserListViewLatestHeaderDesc; + return PyArg_Parse(v, "(HHhO&HO&O&)", + &itself->minimumWidth, + &itself->maximumWidth, + &itself->titleOffset, + CFStringRefObj_Convert, &itself->titleString, + &itself->initialOrder, + ControlFontStyle_Convert, &itself->btnFontStyle, + ControlButtonContentInfo_Convert, &itself->btnContentInfo); } static int DataBrowserListViewColumnDesc_Convert(PyObject *v, DataBrowserListViewColumnDesc *itself) { - return PyArg_Parse(v, "(O&O&)", - DataBrowserTableViewColumnDesc_Convert, &itself->propertyDesc, - DataBrowserListViewHeaderDesc_Convert, &itself->headerBtnDesc); + return PyArg_Parse(v, "(O&O&)", + DataBrowserTableViewColumnDesc_Convert, &itself->propertyDesc, + DataBrowserListViewHeaderDesc_Convert, &itself->headerBtnDesc); } /* TrackControl and HandleControlClick callback support */ @@ -125,8 +125,8 @@ static ControlUserPaneHitTestUPP myhittestproc_upp; static ControlUserPaneTrackingUPP mytrackingproc_upp; -static int settrackfunc(PyObject *); /* forward */ -static void clrtrackfunc(void); /* forward */ +static int settrackfunc(PyObject *); /* forward */ +static void clrtrackfunc(void); /* forward */ static int setcallback(PyObject *, OSType, PyObject *, UniversalProcPtr *); static PyObject *Ctl_Error; @@ -154,6 +154,7 @@ it->ob_callbackdict = NULL; return (PyObject *)it; } + int CtlObj_Convert(PyObject *v, ControlHandle *p_itself) { if (!CtlObj_Check(v)) @@ -3223,16 +3224,16 @@ { PyObject *_res = NULL; - if (!PyArg_ParseTuple(_args, "")) - return NULL; - if ( _self->ob_itself ) { - SetControlReference(_self->ob_itself, (long)0); /* Make it forget about us */ - DisposeControl(_self->ob_itself); - _self->ob_itself = NULL; - } - Py_INCREF(Py_None); - _res = Py_None; - return _res; + if (!PyArg_ParseTuple(_args, "")) + return NULL; + if ( _self->ob_itself ) { + SetControlReference(_self->ob_itself, (long)0); /* Make it forget about us */ + DisposeControl(_self->ob_itself); + _self->ob_itself = NULL; + } + Py_INCREF(Py_None); + _res = Py_None; + return _res; } @@ -3247,14 +3248,14 @@ if (!PyArg_ParseTuple(_args, "O&|O", PyMac_GetPoint, &startPoint, &callback)) - return NULL; + return NULL; if (callback && callback != Py_None) { - if (PyInt_Check(callback) && PyInt_AS_LONG(callback) == -1) - upp = (ControlActionUPP)-1; - else { - settrackfunc(callback); - upp = mytracker_upp; - } + if (PyInt_Check(callback) && PyInt_AS_LONG(callback) == -1) + upp = (ControlActionUPP)-1; + else { + settrackfunc(callback); + upp = mytracker_upp; + } } _rv = TrackControl(_self->ob_itself, startPoint, @@ -3280,14 +3281,14 @@ PyMac_GetPoint, &startPoint, &modifiers, &callback)) - return NULL; + return NULL; if (callback && callback != Py_None) { - if (PyInt_Check(callback) && PyInt_AS_LONG(callback) == -1) - upp = (ControlActionUPP)-1; - else { - settrackfunc(callback); - upp = mytracker_upp; - } + if (PyInt_Check(callback) && PyInt_AS_LONG(callback) == -1) + upp = (ControlActionUPP)-1; + else { + settrackfunc(callback); + upp = mytracker_upp; + } } _rv = HandleControlClick(_self->ob_itself, startPoint, @@ -3314,16 +3315,16 @@ &inPart, PyMac_GetOSType, &inTagName, &buffer, &bufferSize)) - return NULL; + return NULL; _err = SetControlData(_self->ob_itself, - inPart, - inTagName, - bufferSize, + inPart, + inTagName, + bufferSize, buffer); if (_err != noErr) - return PyMac_Error(_err); + return PyMac_Error(_err); _res = Py_None; return _res; @@ -3343,29 +3344,29 @@ if (!PyArg_ParseTuple(_args, "hO&", &inPart, PyMac_GetOSType, &inTagName)) - return NULL; + return NULL; /* allocate a buffer for the data */ _err = GetControlDataSize(_self->ob_itself, - inPart, - inTagName, + inPart, + inTagName, &bufferSize); if (_err != noErr) - return PyMac_Error(_err); + return PyMac_Error(_err); buffer = PyMem_NEW(char, bufferSize); if (buffer == NULL) - return PyErr_NoMemory(); + return PyErr_NoMemory(); _err = GetControlData(_self->ob_itself, - inPart, - inTagName, - bufferSize, + inPart, + inTagName, + bufferSize, buffer, &outSize); if (_err != noErr) { - PyMem_DEL(buffer); - return PyMac_Error(_err); + PyMem_DEL(buffer); + return PyMac_Error(_err); } _res = Py_BuildValue("s#", buffer, outSize); PyMem_DEL(buffer); @@ -3386,16 +3387,16 @@ &inPart, PyMac_GetOSType, &inTagName, OptResObj_Convert, &buffer)) - return NULL; + return NULL; _err = SetControlData(_self->ob_itself, - inPart, - inTagName, - sizeof(buffer), + inPart, + inTagName, + sizeof(buffer), (Ptr)&buffer); if (_err != noErr) - return PyMac_Error(_err); + return PyMac_Error(_err); _res = Py_None; return _res; @@ -3414,29 +3415,29 @@ if (!PyArg_ParseTuple(_args, "hO&", &inPart, PyMac_GetOSType, &inTagName)) - return NULL; + return NULL; /* Check it is handle-sized */ _err = GetControlDataSize(_self->ob_itself, - inPart, - inTagName, + inPart, + inTagName, &bufferSize); if (_err != noErr) - return PyMac_Error(_err); + return PyMac_Error(_err); if (bufferSize != sizeof(Handle)) { - PyErr_SetString(Ctl_Error, "GetControlDataSize() != sizeof(Handle)"); - return NULL; + PyErr_SetString(Ctl_Error, "GetControlDataSize() != sizeof(Handle)"); + return NULL; } _err = GetControlData(_self->ob_itself, - inPart, - inTagName, - sizeof(Handle), + inPart, + inTagName, + sizeof(Handle), (Ptr)&hdl, &bufferSize); if (_err != noErr) { - return PyMac_Error(_err); + return PyMac_Error(_err); } _res = Py_BuildValue("O&", OptResObj_New, hdl); return _res; @@ -3457,18 +3458,18 @@ &inPart, PyMac_GetOSType, &inTagName, &callback)) - return NULL; + return NULL; if ( setcallback((PyObject *)_self, inTagName, callback, &c_callback) < 0 ) - return NULL; + return NULL; _err = SetControlData(_self->ob_itself, - inPart, - inTagName, - sizeof(c_callback), + inPart, + inTagName, + sizeof(c_callback), (Ptr)&c_callback); if (_err != noErr) - return PyMac_Error(_err); + return PyMac_Error(_err); _res = Py_None; return _res; @@ -3848,16 +3849,16 @@ #define CtlObj_tp_alloc PyType_GenericAlloc -static PyObject *CtlObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *CtlObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; ControlHandle itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, CtlObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((ControlObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, CtlObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((ControlObject *)_self)->ob_itself = itself; + return _self; } #define CtlObj_tp_free PyObject_Del @@ -5379,26 +5380,26 @@ &size, &direction, &tabArrayObj)) - return NULL; + return NULL; i = PySequence_Length(tabArrayObj); if (i == -1) - return NULL; + return NULL; if (i > MAXTABS) { - PyErr_SetString(Ctl_Error, "Too many tabs"); - return NULL; + PyErr_SetString(Ctl_Error, "Too many tabs"); + return NULL; } numTabs = i; for (i=0; iob_itself = itself; - it->ob_callbackdict = NULL; - return (PyObject *)it; + ControlObject *it; + if (itself == NULL) return PyMac_Error(resNotFound); + it = PyObject_NEW(ControlObject, &Control_Type); + if (it == NULL) return NULL; + it->ob_itself = itself; + it->ob_callbackdict = NULL; + return (PyObject *)it; } static PyObject * CtlObj_WhichControl(ControlHandle c) { - PyObject *it; + PyObject *it; - if (c == NULL) - it = Py_None; - else { - it = (PyObject *) GetControlReference(c); - /* - ** If the refcon is zero or doesn't point back to the Python object - ** the control is not ours. Return a temporary object. - */ - if (it == NULL || ((ControlObject *)it)->ob_itself != c) - return CtlObj_NewUnmanaged(c); - } - Py_INCREF(it); - return it; + if (c == NULL) + it = Py_None; + else { + it = (PyObject *) GetControlReference(c); + /* + ** If the refcon is zero or doesn't point back to the Python object + ** the control is not ours. Return a temporary object. + */ + if (it == NULL || ((ControlObject *)it)->ob_itself != c) + return CtlObj_NewUnmanaged(c); + } + Py_INCREF(it); + return it; } static int settrackfunc(PyObject *obj) { - if (tracker) { - PyErr_SetString(Ctl_Error, "Tracker function in use"); - return 0; - } - tracker = obj; - Py_INCREF(tracker); - return 1; + if (tracker) { + PyErr_SetString(Ctl_Error, "Tracker function in use"); + return 0; + } + tracker = obj; + Py_INCREF(tracker); + return 1; } static void clrtrackfunc(void) { - Py_XDECREF(tracker); - tracker = 0; + Py_XDECREF(tracker); + tracker = 0; } static pascal void mytracker(ControlHandle ctl, short part) { - PyObject *args, *rv=0; + PyObject *args, *rv=0; - args = Py_BuildValue("(O&i)", CtlObj_WhichControl, ctl, (int)part); - if (args && tracker) { - rv = PyEval_CallObject(tracker, args); - Py_DECREF(args); - } - if (rv) - Py_DECREF(rv); - else { - PySys_WriteStderr("TrackControl or HandleControlClick: exception in tracker function\n"); - PyErr_Print(); - } + args = Py_BuildValue("(O&i)", CtlObj_WhichControl, ctl, (int)part); + if (args && tracker) { + rv = PyEval_CallObject(tracker, args); + Py_DECREF(args); + } + if (rv) + Py_DECREF(rv); + else { + PySys_WriteStderr("TrackControl or HandleControlClick: exception in tracker function\n"); + PyErr_Print(); + } } static int setcallback(PyObject *myself, OSType which, PyObject *callback, UniversalProcPtr *uppp) { - ControlObject *self = (ControlObject *)myself; - char keybuf[9]; - - if ( which == kMyControlActionProcTag ) - *uppp = (UniversalProcPtr)myactionproc_upp; - else if ( which == kControlUserPaneKeyDownProcTag ) - *uppp = (UniversalProcPtr)mykeydownproc_upp; - else if ( which == kControlUserPaneFocusProcTag ) - *uppp = (UniversalProcPtr)myfocusproc_upp; - else if ( which == kControlUserPaneDrawProcTag ) - *uppp = (UniversalProcPtr)mydrawproc_upp; - else if ( which == kControlUserPaneIdleProcTag ) - *uppp = (UniversalProcPtr)myidleproc_upp; - else if ( which == kControlUserPaneHitTestProcTag ) - *uppp = (UniversalProcPtr)myhittestproc_upp; - else if ( which == kControlUserPaneTrackingProcTag ) - *uppp = (UniversalProcPtr)mytrackingproc_upp; - else - return -1; - /* Only now do we test for clearing of the callback: */ - if ( callback == Py_None ) - *uppp = NULL; - /* Create the dict if it doesn't exist yet (so we don't get such a dict for every control) */ - if ( self->ob_callbackdict == NULL ) - if ( (self->ob_callbackdict = PyDict_New()) == NULL ) - return -1; - /* And store the Python callback */ - sprintf(keybuf, "%x", (unsigned)which); - if (PyDict_SetItemString(self->ob_callbackdict, keybuf, callback) < 0) - return -1; - return 0; + ControlObject *self = (ControlObject *)myself; + char keybuf[9]; + + if ( which == kMyControlActionProcTag ) + *uppp = (UniversalProcPtr)myactionproc_upp; + else if ( which == kControlUserPaneKeyDownProcTag ) + *uppp = (UniversalProcPtr)mykeydownproc_upp; + else if ( which == kControlUserPaneFocusProcTag ) + *uppp = (UniversalProcPtr)myfocusproc_upp; + else if ( which == kControlUserPaneDrawProcTag ) + *uppp = (UniversalProcPtr)mydrawproc_upp; + else if ( which == kControlUserPaneIdleProcTag ) + *uppp = (UniversalProcPtr)myidleproc_upp; + else if ( which == kControlUserPaneHitTestProcTag ) + *uppp = (UniversalProcPtr)myhittestproc_upp; + else if ( which == kControlUserPaneTrackingProcTag ) + *uppp = (UniversalProcPtr)mytrackingproc_upp; + else + return -1; + /* Only now do we test for clearing of the callback: */ + if ( callback == Py_None ) + *uppp = NULL; + /* Create the dict if it doesn't exist yet (so we don't get such a dict for every control) */ + if ( self->ob_callbackdict == NULL ) + if ( (self->ob_callbackdict = PyDict_New()) == NULL ) + return -1; + /* And store the Python callback */ + sprintf(keybuf, "%x", (unsigned)which); + if (PyDict_SetItemString(self->ob_callbackdict, keybuf, callback) < 0) + return -1; + return 0; } static PyObject * callcallback(ControlObject *self, OSType which, PyObject *arglist) { - char keybuf[9]; - PyObject *func, *rv; - - sprintf(keybuf, "%x", (unsigned)which); - if ( self->ob_callbackdict == NULL || - (func = PyDict_GetItemString(self->ob_callbackdict, keybuf)) == NULL ) { - PySys_WriteStderr("Control callback %x without callback object\n", (unsigned)which); - return NULL; - } - rv = PyEval_CallObject(func, arglist); - if ( rv == NULL ) { - PySys_WriteStderr("Exception in control callback %x handler\n", (unsigned)which); - PyErr_Print(); - } - return rv; + char keybuf[9]; + PyObject *func, *rv; + + sprintf(keybuf, "%x", (unsigned)which); + if ( self->ob_callbackdict == NULL || + (func = PyDict_GetItemString(self->ob_callbackdict, keybuf)) == NULL ) { + PySys_WriteStderr("Control callback %x without callback object\n", (unsigned)which); + return NULL; + } + rv = PyEval_CallObject(func, arglist); + if ( rv == NULL ) { + PySys_WriteStderr("Exception in control callback %x handler\n", (unsigned)which); + PyErr_Print(); + } + return rv; } static pascal void myactionproc(ControlHandle control, SInt16 part) { - ControlObject *ctl_obj; - PyObject *arglist, *rv; - - ctl_obj = (ControlObject *)CtlObj_WhichControl(control); - arglist = Py_BuildValue("Oh", ctl_obj, part); - rv = callcallback(ctl_obj, kMyControlActionProcTag, arglist); - Py_XDECREF(arglist); - Py_XDECREF(rv); + ControlObject *ctl_obj; + PyObject *arglist, *rv; + + ctl_obj = (ControlObject *)CtlObj_WhichControl(control); + arglist = Py_BuildValue("Oh", ctl_obj, part); + rv = callcallback(ctl_obj, kMyControlActionProcTag, arglist); + Py_XDECREF(arglist); + Py_XDECREF(rv); } static pascal ControlPartCode mykeydownproc(ControlHandle control, SInt16 keyCode, SInt16 charCode, SInt16 modifiers) { - ControlObject *ctl_obj; - PyObject *arglist, *rv; - short c_rv = 0; - - ctl_obj = (ControlObject *)CtlObj_WhichControl(control); - arglist = Py_BuildValue("Ohhh", ctl_obj, keyCode, charCode, modifiers); - rv = callcallback(ctl_obj, kControlUserPaneKeyDownProcTag, arglist); - Py_XDECREF(arglist); - if ( rv ) - if (!PyArg_Parse(rv, "h", &c_rv)) - PyErr_Clear(); - Py_XDECREF(rv); - return (ControlPartCode)c_rv; + ControlObject *ctl_obj; + PyObject *arglist, *rv; + short c_rv = 0; + + ctl_obj = (ControlObject *)CtlObj_WhichControl(control); + arglist = Py_BuildValue("Ohhh", ctl_obj, keyCode, charCode, modifiers); + rv = callcallback(ctl_obj, kControlUserPaneKeyDownProcTag, arglist); + Py_XDECREF(arglist); + if ( rv ) + if (!PyArg_Parse(rv, "h", &c_rv)) + PyErr_Clear(); + Py_XDECREF(rv); + return (ControlPartCode)c_rv; } static pascal ControlPartCode myfocusproc(ControlHandle control, ControlPartCode part) { - ControlObject *ctl_obj; - PyObject *arglist, *rv; - short c_rv = kControlFocusNoPart; - - ctl_obj = (ControlObject *)CtlObj_WhichControl(control); - arglist = Py_BuildValue("Oh", ctl_obj, part); - rv = callcallback(ctl_obj, kControlUserPaneFocusProcTag, arglist); - Py_XDECREF(arglist); - if ( rv ) - if (!PyArg_Parse(rv, "h", &c_rv)) - PyErr_Clear(); - Py_XDECREF(rv); - return (ControlPartCode)c_rv; + ControlObject *ctl_obj; + PyObject *arglist, *rv; + short c_rv = kControlFocusNoPart; + + ctl_obj = (ControlObject *)CtlObj_WhichControl(control); + arglist = Py_BuildValue("Oh", ctl_obj, part); + rv = callcallback(ctl_obj, kControlUserPaneFocusProcTag, arglist); + Py_XDECREF(arglist); + if ( rv ) + if (!PyArg_Parse(rv, "h", &c_rv)) + PyErr_Clear(); + Py_XDECREF(rv); + return (ControlPartCode)c_rv; } static pascal void mydrawproc(ControlHandle control, SInt16 part) { - ControlObject *ctl_obj; - PyObject *arglist, *rv; - - ctl_obj = (ControlObject *)CtlObj_WhichControl(control); - arglist = Py_BuildValue("Oh", ctl_obj, part); - rv = callcallback(ctl_obj, kControlUserPaneDrawProcTag, arglist); - Py_XDECREF(arglist); - Py_XDECREF(rv); + ControlObject *ctl_obj; + PyObject *arglist, *rv; + + ctl_obj = (ControlObject *)CtlObj_WhichControl(control); + arglist = Py_BuildValue("Oh", ctl_obj, part); + rv = callcallback(ctl_obj, kControlUserPaneDrawProcTag, arglist); + Py_XDECREF(arglist); + Py_XDECREF(rv); } static pascal void myidleproc(ControlHandle control) { - ControlObject *ctl_obj; - PyObject *arglist, *rv; - - ctl_obj = (ControlObject *)CtlObj_WhichControl(control); - arglist = Py_BuildValue("O", ctl_obj); - rv = callcallback(ctl_obj, kControlUserPaneIdleProcTag, arglist); - Py_XDECREF(arglist); - Py_XDECREF(rv); + ControlObject *ctl_obj; + PyObject *arglist, *rv; + + ctl_obj = (ControlObject *)CtlObj_WhichControl(control); + arglist = Py_BuildValue("O", ctl_obj); + rv = callcallback(ctl_obj, kControlUserPaneIdleProcTag, arglist); + Py_XDECREF(arglist); + Py_XDECREF(rv); } static pascal ControlPartCode myhittestproc(ControlHandle control, Point where) { - ControlObject *ctl_obj; - PyObject *arglist, *rv; - short c_rv = -1; + ControlObject *ctl_obj; + PyObject *arglist, *rv; + short c_rv = -1; - ctl_obj = (ControlObject *)CtlObj_WhichControl(control); - arglist = Py_BuildValue("OO&", ctl_obj, PyMac_BuildPoint, where); - rv = callcallback(ctl_obj, kControlUserPaneHitTestProcTag, arglist); - Py_XDECREF(arglist); - /* Ignore errors, nothing we can do about them */ - if ( rv ) - if (!PyArg_Parse(rv, "h", &c_rv)) - PyErr_Clear(); - Py_XDECREF(rv); - return (ControlPartCode)c_rv; + ctl_obj = (ControlObject *)CtlObj_WhichControl(control); + arglist = Py_BuildValue("OO&", ctl_obj, PyMac_BuildPoint, where); + rv = callcallback(ctl_obj, kControlUserPaneHitTestProcTag, arglist); + Py_XDECREF(arglist); + /* Ignore errors, nothing we can do about them */ + if ( rv ) + if (!PyArg_Parse(rv, "h", &c_rv)) + PyErr_Clear(); + Py_XDECREF(rv); + return (ControlPartCode)c_rv; } static pascal ControlPartCode mytrackingproc(ControlHandle control, Point startPt, ControlActionUPP actionProc) { - ControlObject *ctl_obj; - PyObject *arglist, *rv; - short c_rv = -1; + ControlObject *ctl_obj; + PyObject *arglist, *rv; + short c_rv = -1; - ctl_obj = (ControlObject *)CtlObj_WhichControl(control); - /* We cannot pass the actionProc without lots of work */ - arglist = Py_BuildValue("OO&", ctl_obj, PyMac_BuildPoint, startPt); - rv = callcallback(ctl_obj, kControlUserPaneTrackingProcTag, arglist); - Py_XDECREF(arglist); - if ( rv ) - if (!PyArg_Parse(rv, "h", &c_rv)) - PyErr_Clear(); - Py_XDECREF(rv); - return (ControlPartCode)c_rv; + ctl_obj = (ControlObject *)CtlObj_WhichControl(control); + /* We cannot pass the actionProc without lots of work */ + arglist = Py_BuildValue("OO&", ctl_obj, PyMac_BuildPoint, startPt); + rv = callcallback(ctl_obj, kControlUserPaneTrackingProcTag, arglist); + Py_XDECREF(arglist); + if ( rv ) + if (!PyArg_Parse(rv, "h", &c_rv)) + PyErr_Clear(); + Py_XDECREF(rv); + return (ControlPartCode)c_rv; } From jackjansen at users.sourceforge.net Sun Jul 3 23:00:12 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:12 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/drag _Dragmodule.c, 1.16, 1.17 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/drag In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/drag Modified Files: _Dragmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Dragmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/drag/_Dragmodule.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- _Dragmodule.c 20 Nov 2003 13:30:56 -0000 1.16 +++ _Dragmodule.c 3 Jul 2005 20:59:39 -0000 1.17 @@ -52,15 +52,16 @@ { DragObjObject *it; if (itself == NULL) { - PyErr_SetString(Drag_Error,"Cannot create null Drag"); - return NULL; - } + PyErr_SetString(Drag_Error,"Cannot create null Drag"); + return NULL; + } it = PyObject_NEW(DragObjObject, &DragObj_Type); if (it == NULL) return NULL; it->ob_itself = itself; it->sendproc = NULL; return (PyObject *)it; } + int DragObj_Convert(PyObject *v, DragRef *p_itself) { if (!DragObj_Check(v)) @@ -743,16 +744,16 @@ #define DragObj_tp_alloc PyType_GenericAlloc -static PyObject *DragObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *DragObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; DragRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, DragObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((DragObjObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, DragObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((DragObjObject *)_self)->ob_itself = itself; + return _self; } #define DragObj_tp_free PyObject_Del @@ -920,15 +921,15 @@ PyObject *callback; WindowPtr theWindow = NULL; OSErr _err; - + if ( !PyArg_ParseTuple(_args, "O|O&", &callback, WinObj_Convert, &theWindow) ) - return NULL; - Py_INCREF(callback); /* Cannot decref later, too bad */ + return NULL; + Py_INCREF(callback); /* Cannot decref later, too bad */ _err = InstallTrackingHandler(dragglue_TrackingHandlerUPP, theWindow, (void *)callback); - if (_err != noErr) return PyMac_Error(_err); - Py_INCREF(Py_None); - _res = Py_None; - return _res; + if (_err != noErr) return PyMac_Error(_err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; } @@ -939,15 +940,15 @@ PyObject *callback; WindowPtr theWindow = NULL; OSErr _err; - + if ( !PyArg_ParseTuple(_args, "O|O&", &callback, WinObj_Convert, &theWindow) ) - return NULL; - Py_INCREF(callback); /* Cannot decref later, too bad */ + return NULL; + Py_INCREF(callback); /* Cannot decref later, too bad */ _err = InstallReceiveHandler(dragglue_ReceiveHandlerUPP, theWindow, (void *)callback); - if (_err != noErr) return PyMac_Error(_err); - Py_INCREF(Py_None); - _res = Py_None; - return _res; + if (_err != noErr) return PyMac_Error(_err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; } @@ -957,14 +958,14 @@ WindowPtr theWindow = NULL; OSErr _err; - + if ( !PyArg_ParseTuple(_args, "|O&", WinObj_Convert, &theWindow) ) - return NULL; + return NULL; _err = RemoveTrackingHandler(dragglue_TrackingHandlerUPP, theWindow); - if (_err != noErr) return PyMac_Error(_err); - Py_INCREF(Py_None); - _res = Py_None; - return _res; + if (_err != noErr) return PyMac_Error(_err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; } @@ -974,14 +975,14 @@ WindowPtr theWindow = NULL; OSErr _err; - + if ( !PyArg_ParseTuple(_args, "|O&", WinObj_Convert, &theWindow) ) - return NULL; + return NULL; _err = RemoveReceiveHandler(dragglue_ReceiveHandlerUPP, theWindow); - if (_err != noErr) return PyMac_Error(_err); - Py_INCREF(Py_None); - _res = Py_None; - return _res; + if (_err != noErr) return PyMac_Error(_err); + Py_INCREF(Py_None); + _res = Py_None; + return _res; } @@ -1013,81 +1014,81 @@ dragglue_TrackingHandler(DragTrackingMessage theMessage, WindowPtr theWindow, void *handlerRefCon, DragReference theDrag) { - PyObject *args, *rv; - int i; - - args = Py_BuildValue("hO&O&", theMessage, DragObj_New, theDrag, WinObj_WhichWindow, theWindow); - if ( args == NULL ) - return -1; - rv = PyEval_CallObject((PyObject *)handlerRefCon, args); - Py_DECREF(args); - if ( rv == NULL ) { - PySys_WriteStderr("Drag: Exception in TrackingHandler\n"); - PyErr_Print(); - return -1; - } - i = -1; - if ( rv == Py_None ) - i = 0; - else - PyArg_Parse(rv, "l", &i); - Py_DECREF(rv); - return i; + PyObject *args, *rv; + int i; + + args = Py_BuildValue("hO&O&", theMessage, DragObj_New, theDrag, WinObj_WhichWindow, theWindow); + if ( args == NULL ) + return -1; + rv = PyEval_CallObject((PyObject *)handlerRefCon, args); + Py_DECREF(args); + if ( rv == NULL ) { + PySys_WriteStderr("Drag: Exception in TrackingHandler\n"); + PyErr_Print(); + return -1; + } + i = -1; + if ( rv == Py_None ) + i = 0; + else + PyArg_Parse(rv, "l", &i); + Py_DECREF(rv); + return i; } static pascal OSErr dragglue_ReceiveHandler(WindowPtr theWindow, void *handlerRefCon, DragReference theDrag) { - PyObject *args, *rv; - int i; - - args = Py_BuildValue("O&O&", DragObj_New, theDrag, WinObj_WhichWindow, theWindow); - if ( args == NULL ) - return -1; - rv = PyEval_CallObject((PyObject *)handlerRefCon, args); - Py_DECREF(args); - if ( rv == NULL ) { - PySys_WriteStderr("Drag: Exception in ReceiveHandler\n"); - PyErr_Print(); - return -1; - } - i = -1; - if ( rv == Py_None ) - i = 0; - else - PyArg_Parse(rv, "l", &i); - Py_DECREF(rv); - return i; + PyObject *args, *rv; + int i; + + args = Py_BuildValue("O&O&", DragObj_New, theDrag, WinObj_WhichWindow, theWindow); + if ( args == NULL ) + return -1; + rv = PyEval_CallObject((PyObject *)handlerRefCon, args); + Py_DECREF(args); + if ( rv == NULL ) { + PySys_WriteStderr("Drag: Exception in ReceiveHandler\n"); + PyErr_Print(); + return -1; + } + i = -1; + if ( rv == Py_None ) + i = 0; + else + PyArg_Parse(rv, "l", &i); + Py_DECREF(rv); + return i; } static pascal OSErr dragglue_SendData(FlavorType theType, void *dragSendRefCon, ItemReference theItem, DragReference theDrag) { - DragObjObject *self = (DragObjObject *)dragSendRefCon; - PyObject *args, *rv; - int i; - - if ( self->sendproc == NULL ) - return -1; - args = Py_BuildValue("O&l", PyMac_BuildOSType, theType, theItem); - if ( args == NULL ) - return -1; - rv = PyEval_CallObject(self->sendproc, args); - Py_DECREF(args); - if ( rv == NULL ) { - PySys_WriteStderr("Drag: Exception in SendDataHandler\n"); - PyErr_Print(); - return -1; - } - i = -1; - if ( rv == Py_None ) - i = 0; - else - PyArg_Parse(rv, "l", &i); - Py_DECREF(rv); - return i; + DragObjObject *self = (DragObjObject *)dragSendRefCon; + PyObject *args, *rv; + int i; + + if ( self->sendproc == NULL ) + return -1; + args = Py_BuildValue("O&l", PyMac_BuildOSType, theType, theItem); + if ( args == NULL ) + return -1; + rv = PyEval_CallObject(self->sendproc, args); + Py_DECREF(args); + if ( rv == NULL ) { + PySys_WriteStderr("Drag: Exception in SendDataHandler\n"); + PyErr_Print(); + return -1; + } + i = -1; + if ( rv == Py_None ) + i = 0; + else + PyArg_Parse(rv, "l", &i); + Py_DECREF(rv); + return i; } #if 0 @@ -1115,8 +1116,8 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(DragRef, DragObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(DragRef, DragObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(DragRef, DragObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(DragRef, DragObj_Convert); m = Py_InitModule("_Drag", Drag_methods); From jackjansen at users.sourceforge.net Sun Jul 3 23:00:13 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:13 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/fm _Fmmodule.c, 1.10, 1.11 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/fm In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/fm Modified Files: _Fmmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Fmmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/fm/_Fmmodule.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- _Fmmodule.c 20 Nov 2003 13:30:57 -0000 1.10 +++ _Fmmodule.c 3 Jul 2005 20:59:40 -0000 1.11 @@ -25,12 +25,12 @@ FMRec_New(FMetricRec *itself) { - return Py_BuildValue("O&O&O&O&O&", - PyMac_BuildFixed, itself->ascent, - PyMac_BuildFixed, itself->descent, - PyMac_BuildFixed, itself->leading, - PyMac_BuildFixed, itself->widMax, - ResObj_New, itself->wTabHandle); + return Py_BuildValue("O&O&O&O&O&", + PyMac_BuildFixed, itself->ascent, + PyMac_BuildFixed, itself->descent, + PyMac_BuildFixed, itself->leading, + PyMac_BuildFixed, itself->widMax, + ResObj_New, itself->wTabHandle); } #if 0 @@ -38,12 +38,12 @@ static int FMRec_Convert(PyObject *v, FMetricRec *p_itself) { - return PyArg_ParseTuple(v, "O&O&O&O&O&", - PyMac_GetFixed, &itself->ascent, - PyMac_GetFixed, &itself->descent, - PyMac_GetFixed, &itself->leading, - PyMac_GetFixed, &itself->widMax, - ResObj_Convert, &itself->wTabHandle); + return PyArg_ParseTuple(v, "O&O&O&O&O&", + PyMac_GetFixed, &itself->ascent, + PyMac_GetFixed, &itself->descent, + PyMac_GetFixed, &itself->leading, + PyMac_GetFixed, &itself->widMax, + ResObj_Convert, &itself->wTabHandle); } #endif From jackjansen at users.sourceforge.net Sun Jul 3 23:00:13 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:13 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/evt _Evtmodule.c, 1.10, 1.11 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/evt In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/evt Modified Files: _Evtmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Evtmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/evt/_Evtmodule.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- _Evtmodule.c 20 Nov 2003 13:30:57 -0000 1.10 +++ _Evtmodule.c 3 Jul 2005 20:59:39 -0000 1.11 @@ -455,7 +455,7 @@ &eventMask, &sleep, OptResObj_Convert, &mouseregion)) - return NULL; + return NULL; _rv = WaitNextEvent(eventMask, &theEvent, sleep, From jackjansen at users.sourceforge.net Sun Jul 3 23:00:13 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:13 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/launch _Launchmodule.c, 1.4, 1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/launch In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/launch Modified Files: _Launchmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Launchmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/launch/_Launchmodule.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- _Launchmodule.c 9 Dec 2003 14:51:21 -0000 1.4 +++ _Launchmodule.c 3 Jul 2005 20:59:40 -0000 1.5 @@ -27,21 +27,21 @@ static int OptCFStringRefObj_Convert(PyObject *v, CFStringRef *spec) { - if (v == Py_None) { - *spec = NULL; - return 1; - } - return CFStringRefObj_Convert(v, spec); + if (v == Py_None) { + *spec = NULL; + return 1; + } + return CFStringRefObj_Convert(v, spec); } PyObject * OptCFStringRefObj_New(CFStringRef it) { - if (it == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return CFStringRefObj_New(it); + if (it == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return CFStringRefObj_New(it); } /* @@ -50,13 +50,13 @@ PyObject * LSItemInfoRecord_New(LSItemInfoRecord *it) { - return Py_BuildValue("{s:is:O&s:O&s:O&s:O&s:i}", - "flags", it->flags, - "filetype", PyMac_BuildOSType, it->filetype, - "creator", PyMac_BuildOSType, it->creator, - "extension", OptCFStringRefObj_New, it->extension, - "iconFileName", OptCFStringRefObj_New, it->iconFileName, - "kindID", it->kindID); + return Py_BuildValue("{s:is:O&s:O&s:O&s:O&s:i}", + "flags", it->flags, + "filetype", PyMac_BuildOSType, it->filetype, + "creator", PyMac_BuildOSType, it->creator, + "extension", OptCFStringRefObj_New, it->extension, + "iconFileName", OptCFStringRefObj_New, it->iconFileName, + "kindID", it->kindID); } static PyObject *Launch_Error; From jackjansen at users.sourceforge.net Sun Jul 3 23:00:13 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:13 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/list _Listmodule.c, 1.18, 1.19 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/list In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/list Modified Files: _Listmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Listmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/list/_Listmodule.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- _Listmodule.c 20 Nov 2003 13:30:58 -0000 1.18 +++ _Listmodule.c 3 Jul 2005 20:59:40 -0000 1.19 @@ -50,9 +50,9 @@ { ListObject *it; if (itself == NULL) { - PyErr_SetString(List_Error,"Cannot create null List"); - return NULL; - } + PyErr_SetString(List_Error,"Cannot create null List"); + return NULL; + } it = PyObject_NEW(ListObject, &List_Type); if (it == NULL) return NULL; it->ob_itself = itself; @@ -61,6 +61,7 @@ SetListRefCon(itself, (long)it); return (PyObject *)it; } + int ListObj_Convert(PyObject *v, ListHandle *p_itself) { if (!ListObj_Check(v)) @@ -738,16 +739,16 @@ #define ListObj_tp_alloc PyType_GenericAlloc -static PyObject *ListObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *ListObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; ListHandle itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, ListObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((ListObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, ListObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((ListObject *)_self)->ob_itself = itself; + return _self; } #define ListObj_tp_free PyObject_Del @@ -826,10 +827,10 @@ &hasGrow, &scrollHoriz, &scrollVert)) - return NULL; + return NULL; - /* Carbon applications use the CreateCustomList API */ + /* Carbon applications use the CreateCustomList API */ theSpec.u.userProc = myListDefFunctionUPP; CreateCustomList(&rView, &dataBounds, @@ -845,7 +846,7 @@ _res = ListObj_New(outList); if (_res == NULL) - return NULL; + return NULL; Py_INCREF(listDefFunc); ((ListObject*)_res)->ob_ldef_func = listDefFunc; return _res; @@ -1024,7 +1025,7 @@ Handle h; ListObject *l; if (!PyArg_ParseTuple(_args, "O&", ResObj_Convert, &h)) - return NULL; + return NULL; l = (ListObject *)ListObj_New(as_List(h)); l->ob_must_be_disposed = 0; _res = Py_BuildValue("O", l); @@ -1066,34 +1067,34 @@ Cell theCell, SInt16 dataOffset, SInt16 dataLen, - ListHandle theList) + ListHandle theList) { - PyObject *listDefFunc, *args, *rv=NULL; - ListObject *self; - - self = (ListObject*)GetListRefCon(theList); - if (self == NULL || self->ob_itself != theList) - return; /* nothing we can do */ - listDefFunc = self->ob_ldef_func; - if (listDefFunc == NULL) - return; /* nothing we can do */ - args = Py_BuildValue("hbO&O&hhO", message, - selected, - PyMac_BuildRect, cellRect, - PyMac_BuildPoint, theCell, - dataOffset, - dataLen, - self); - if (args != NULL) { - rv = PyEval_CallObject(listDefFunc, args); - Py_DECREF(args); - } - if (rv == NULL) { - PySys_WriteStderr("error in list definition callback:\n"); - PyErr_Print(); - } else { - Py_DECREF(rv); - } + PyObject *listDefFunc, *args, *rv=NULL; + ListObject *self; + + self = (ListObject*)GetListRefCon(theList); + if (self == NULL || self->ob_itself != theList) + return; /* nothing we can do */ + listDefFunc = self->ob_ldef_func; + if (listDefFunc == NULL) + return; /* nothing we can do */ + args = Py_BuildValue("hbO&O&hhO", message, + selected, + PyMac_BuildRect, cellRect, + PyMac_BuildPoint, theCell, + dataOffset, + dataLen, + self); + if (args != NULL) { + rv = PyEval_CallObject(listDefFunc, args); + Py_DECREF(args); + } + if (rv == NULL) { + PySys_WriteStderr("error in list definition callback:\n"); + PyErr_Print(); + } else { + Py_DECREF(rv); + } } From jackjansen at users.sourceforge.net Sun Jul 3 23:00:13 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:13 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/file _Filemodule.c, 1.23, 1.24 filesupport.py, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/file In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/file Modified Files: _Filemodule.c filesupport.py Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Filemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/file/_Filemodule.c,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- _Filemodule.c 5 Nov 2004 07:02:58 -0000 1.23 +++ _Filemodule.c 3 Jul 2005 20:59:40 -0000 1.24 @@ -50,13 +50,13 @@ static int UTCDateTime_Convert(PyObject *v, UTCDateTime *ptr) { - return PyArg_Parse(v, "(HlH)", &ptr->highSeconds, &ptr->lowSeconds, &ptr->fraction); + return PyArg_Parse(v, "(HlH)", &ptr->highSeconds, &ptr->lowSeconds, &ptr->fraction); } static PyObject * UTCDateTime_New(UTCDateTime *ptr) { - return Py_BuildValue("(HlH)", ptr->highSeconds, ptr->lowSeconds, ptr->fraction); + return Py_BuildValue("(HlH)", ptr->highSeconds, ptr->lowSeconds, ptr->fraction); } /* @@ -65,21 +65,21 @@ static int myPyMac_GetOptFSSpecPtr(PyObject *v, FSSpec **spec) { - if (v == Py_None) { - *spec = NULL; - return 1; - } - return PyMac_GetFSSpec(v, *spec); + if (v == Py_None) { + *spec = NULL; + return 1; + } + return PyMac_GetFSSpec(v, *spec); } static int myPyMac_GetOptFSRefPtr(PyObject *v, FSRef **ref) { - if (v == Py_None) { - *ref = NULL; - return 1; - } - return PyMac_GetFSRef(v, *ref); + if (v == Py_None) { + *ref = NULL; + return 1; + } + return PyMac_GetFSRef(v, *ref); } /* @@ -89,7 +89,7 @@ PyMac_BuildHFSUniStr255(HFSUniStr255 *itself) { - return Py_BuildValue("u#", itself->unicode, itself->length); + return Py_BuildValue("u#", itself->unicode, itself->length); } static PyObject *File_Error; @@ -114,6 +114,7 @@ it->ob_itself = *itself; return (PyObject *)it; } + static int FSCatalogInfo_Convert(PyObject *v, FSCatalogInfo *p_itself) { if (!FSCatalogInfo_Check(v)) @@ -349,43 +350,43 @@ #define FSCatalogInfo_repr NULL #define FSCatalogInfo_hash NULL -static int FSCatalogInfo_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int FSCatalogInfo_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { static char *kw[] = { - "nodeFlags", - "volume", - "parentDirID", - "nodeID", - "createDate", - "contentModDate", - "atributeModDate", - "accessDate", - "backupDate", - "valence", - "dataLogicalSize", - "dataPhysicalSize", - "rsrcLogicalSize", - "rsrcPhysicalSize", - "sharingFlags", - "userPrivileges" - , 0}; + "nodeFlags", + "volume", + "parentDirID", + "nodeID", + "createDate", + "contentModDate", + "atributeModDate", + "accessDate", + "backupDate", + "valence", + "dataLogicalSize", + "dataPhysicalSize", + "rsrcLogicalSize", + "rsrcPhysicalSize", + "sharingFlags", + "userPrivileges" + , 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|HhllO&O&O&O&O&llllllb", kw, &((FSCatalogInfoObject *)self)->ob_itself.nodeFlags, - &((FSCatalogInfoObject *)self)->ob_itself.volume, - &((FSCatalogInfoObject *)self)->ob_itself.parentDirID, - &((FSCatalogInfoObject *)self)->ob_itself.nodeID, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.createDate, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.contentModDate, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.attributeModDate, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.accessDate, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.backupDate, - &((FSCatalogInfoObject *)self)->ob_itself.valence, - &((FSCatalogInfoObject *)self)->ob_itself.dataLogicalSize, - &((FSCatalogInfoObject *)self)->ob_itself.dataPhysicalSize, - &((FSCatalogInfoObject *)self)->ob_itself.rsrcLogicalSize, - &((FSCatalogInfoObject *)self)->ob_itself.rsrcPhysicalSize, - &((FSCatalogInfoObject *)self)->ob_itself.sharingFlags, - &((FSCatalogInfoObject *)self)->ob_itself.userPrivileges)) + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "|HhllO&O&O&O&O&llllllb", kw, &((FSCatalogInfoObject *)_self)->ob_itself.nodeFlags, + &((FSCatalogInfoObject *)_self)->ob_itself.volume, + &((FSCatalogInfoObject *)_self)->ob_itself.parentDirID, + &((FSCatalogInfoObject *)_self)->ob_itself.nodeID, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.createDate, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.contentModDate, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.attributeModDate, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.accessDate, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.backupDate, + &((FSCatalogInfoObject *)_self)->ob_itself.valence, + &((FSCatalogInfoObject *)_self)->ob_itself.dataLogicalSize, + &((FSCatalogInfoObject *)_self)->ob_itself.dataPhysicalSize, + &((FSCatalogInfoObject *)_self)->ob_itself.rsrcLogicalSize, + &((FSCatalogInfoObject *)_self)->ob_itself.rsrcPhysicalSize, + &((FSCatalogInfoObject *)_self)->ob_itself.sharingFlags, + &((FSCatalogInfoObject *)_self)->ob_itself.userPrivileges)) { return -1; } @@ -394,7 +395,7 @@ #define FSCatalogInfo_tp_alloc PyType_GenericAlloc -static PyObject *FSCatalogInfo_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *FSCatalogInfo_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; @@ -473,6 +474,7 @@ it->ob_itself = *itself; return (PyObject *)it; } + static int FInfo_Convert(PyObject *v, FInfo *p_itself) { if (!FInfo_Check(v)) @@ -564,14 +566,14 @@ #define FInfo_repr NULL #define FInfo_hash NULL -static int FInfo_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int FInfo_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { FInfo *itself = NULL; static char *kw[] = {"itself", 0}; - if (PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kw, FInfo_Convert, &itself)) + if (PyArg_ParseTupleAndKeywords(_args, _kwds, "|O&", kw, FInfo_Convert, &itself)) { - if (itself) memcpy(&((FInfoObject *)self)->ob_itself, itself, sizeof(FInfo)); + if (itself) memcpy(&((FInfoObject *)_self)->ob_itself, itself, sizeof(FInfo)); return 0; } return -1; @@ -579,7 +581,7 @@ #define FInfo_tp_alloc PyType_GenericAlloc -static PyObject *FInfo_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *FInfo_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; @@ -660,6 +662,7 @@ it->ob_freeit = NULL; return (PyObject *)it; } + static int Alias_Convert(PyObject *v, AliasHandle *p_itself) { if (!Alias_Check(v)) @@ -863,14 +866,14 @@ static PyObject *Alias_get_data(AliasObject *self, void *closure) { int size; - PyObject *rv; - - size = GetHandleSize((Handle)self->ob_itself); - HLock((Handle)self->ob_itself); - rv = PyString_FromStringAndSize(*(Handle)self->ob_itself, size); - HUnlock((Handle)self->ob_itself); - return rv; - + PyObject *rv; + + size = GetHandleSize((Handle)self->ob_itself); + HLock((Handle)self->ob_itself); + rv = PyString_FromStringAndSize(*(Handle)self->ob_itself, size); + HUnlock((Handle)self->ob_itself); + return rv; + } #define Alias_set_data NULL @@ -886,7 +889,7 @@ #define Alias_repr NULL #define Alias_hash NULL -static int Alias_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int Alias_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { AliasHandle itself = NULL; char *rawdata = NULL; @@ -894,7 +897,7 @@ Handle h; static char *kw[] = {"itself", "rawdata", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&s#", kw, Alias_Convert, &itself, &rawdata, &rawdatalen)) + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "|O&s#", kw, Alias_Convert, &itself, &rawdata, &rawdatalen)) return -1; if (itself && rawdata) { @@ -916,16 +919,16 @@ HLock(h); memcpy((char *)*h, rawdata, rawdatalen); HUnlock(h); - ((AliasObject *)self)->ob_itself = (AliasHandle)h; + ((AliasObject *)_self)->ob_itself = (AliasHandle)h; return 0; } - ((AliasObject *)self)->ob_itself = itself; + ((AliasObject *)_self)->ob_itself = itself; return 0; } #define Alias_tp_alloc PyType_GenericAlloc -static PyObject *Alias_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *Alias_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; @@ -1253,49 +1256,6 @@ return _res; } -static OSErr -_PyMac_GetFullPathname(FSSpec *fss, char *path, int len) -{ - FSRef fsr; - OSErr err; - - *path = '\0'; - err = FSpMakeFSRef(fss, &fsr); - if (err == fnfErr) { - /* FSSpecs can point to non-existing files, fsrefs can't. */ - FSSpec fss2; - int tocopy; - - err = FSMakeFSSpec(fss->vRefNum, fss->parID, "", &fss2); - if (err) - return err; - err = FSpMakeFSRef(&fss2, &fsr); - if (err) - return err; - err = (OSErr)FSRefMakePath(&fsr, path, len-1); - if (err) - return err; - /* This part is not 100% safe: we append the filename part, but - ** I'm not sure that we don't run afoul of the various 8bit - ** encodings here. Will have to look this up at some point... - */ - strcat(path, "/"); - tocopy = fss->name[0]; - if ((strlen(path) + tocopy) >= len) - tocopy = len - strlen(path) - 1; - if (tocopy > 0) - strncat(path, fss->name+1, tocopy); - } - else { - if (err) - return err; - err = (OSErr)FSRefMakePath(&fsr, path, len); - if (err) - return err; - } - return 0; -} - static PyObject *FSSpec_as_pathname(FSSpecObject *_self, PyObject *_args) { PyObject *_res = NULL; @@ -1304,11 +1264,11 @@ OSErr err; if (!PyArg_ParseTuple(_args, "")) - return NULL; - err = _PyMac_GetFullPathname(&_self->ob_itself, strbuf, sizeof(strbuf)); + return NULL; + err = PyMac_GetFullPathname(&_self->ob_itself, strbuf, sizeof(strbuf)); if ( err ) { - PyMac_Error(err); - return NULL; + PyMac_Error(err); + return NULL; } _res = PyString_FromString(strbuf); return _res; @@ -1320,9 +1280,9 @@ PyObject *_res = NULL; if (!PyArg_ParseTuple(_args, "")) - return NULL; - _res = Py_BuildValue("(iis#)", _self->ob_itself.vRefNum, _self->ob_itself.parID, - &_self->ob_itself.name[1], _self->ob_itself.name[0]); + return NULL; + _res = Py_BuildValue("(iis#)", _self->ob_itself.vRefNum, _self->ob_itself.parID, + &_self->ob_itself.name[1], _self->ob_itself.name[0]); return _res; } @@ -1384,22 +1344,22 @@ { char buf[512]; PyOS_snprintf(buf, sizeof(buf), "%s((%d, %ld, '%.*s'))", - self->ob_type->tp_name, - self->ob_itself.vRefNum, - self->ob_itself.parID, - self->ob_itself.name[0], self->ob_itself.name+1); + self->ob_type->tp_name, + self->ob_itself.vRefNum, + self->ob_itself.parID, + self->ob_itself.name[0], self->ob_itself.name+1); return PyString_FromString(buf); } #define FSSpec_hash NULL -static int FSSpec_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int FSSpec_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { PyObject *v = NULL; char *rawdata = NULL; int rawdatalen = 0; static char *kw[] = {"itself", "rawdata", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Os#", kw, &v, &rawdata, &rawdatalen)) + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "|Os#", kw, &v, &rawdata, &rawdatalen)) return -1; if (v && rawdata) { @@ -1418,16 +1378,16 @@ PyErr_SetString(PyExc_TypeError, "FSSpec rawdata incorrect size"); return -1; } - memcpy(&((FSSpecObject *)self)->ob_itself, rawdata, rawdatalen); + memcpy(&((FSSpecObject *)_self)->ob_itself, rawdata, rawdatalen); return 0; } - if (PyMac_GetFSSpec(v, &((FSSpecObject *)self)->ob_itself)) return 0; + if (PyMac_GetFSSpec(v, &((FSSpecObject *)_self)->ob_itself)) return 0; return -1; } #define FSSpec_tp_alloc PyType_GenericAlloc -static PyObject *FSSpec_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *FSSpec_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; @@ -1857,10 +1817,10 @@ UInt32 maxPathSize = MAXPATHNAME; if (!PyArg_ParseTuple(_args, "")) - return NULL; + return NULL; _err = FSRefMakePath(&_self->ob_itself, - path, - maxPathSize); + path, + maxPathSize); if (_err != noErr) return PyMac_Error(_err); _res = Py_BuildValue("s", path); return _res; @@ -1872,7 +1832,7 @@ PyObject *_res = NULL; if (!PyArg_ParseTuple(_args, "")) - return NULL; + return NULL; _res = FSRef_FSRefMakePath(_self, _args); return _res; @@ -1936,14 +1896,14 @@ #define FSRef_repr NULL #define FSRef_hash NULL -static int FSRef_tp_init(PyObject *self, PyObject *args, PyObject *kwds) +static int FSRef_tp_init(PyObject *_self, PyObject *_args, PyObject *_kwds) { PyObject *v = NULL; char *rawdata = NULL; int rawdatalen = 0; static char *kw[] = {"itself", "rawdata", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Os#", kw, &v, &rawdata, &rawdatalen)) + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "|Os#", kw, &v, &rawdata, &rawdatalen)) return -1; if (v && rawdata) { @@ -1962,16 +1922,16 @@ PyErr_SetString(PyExc_TypeError, "FSRef rawdata incorrect size"); return -1; } - memcpy(&((FSRefObject *)self)->ob_itself, rawdata, rawdatalen); + memcpy(&((FSRefObject *)_self)->ob_itself, rawdata, rawdatalen); return 0; } - if (PyMac_GetFSRef(v, &((FSRefObject *)self)->ob_itself)) return 0; + if (PyMac_GetFSRef(v, &((FSRefObject *)_self)->ob_itself)) return 0; return -1; } #define FSRef_tp_alloc PyType_GenericAlloc -static PyObject *FSRef_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *FSRef_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { PyObject *self; @@ -3032,13 +2992,13 @@ PyObject *obj; if (!PyArg_ParseTuple(_args, "O", &obj)) - return NULL; + return NULL; if (PyString_Check(obj)) { - Py_INCREF(obj); - return obj; + Py_INCREF(obj); + return obj; } if (PyUnicode_Check(obj)) - return PyUnicode_AsEncodedString(obj, "utf8", "strict"); + return PyUnicode_AsEncodedString(obj, "utf8", "strict"); _res = PyObject_CallMethod(obj, "as_pathname", NULL); return _res; @@ -3149,86 +3109,86 @@ int PyMac_GetFSSpec(PyObject *v, FSSpec *spec) { - Str255 path; - short refnum; - long parid; - OSErr err; - FSRef fsr; + Str255 path; + short refnum; + long parid; + OSErr err; + FSRef fsr; - if (FSSpec_Check(v)) { - *spec = ((FSSpecObject *)v)->ob_itself; - return 1; - } + if (FSSpec_Check(v)) { + *spec = ((FSSpecObject *)v)->ob_itself; + return 1; + } - if (PyArg_Parse(v, "(hlO&)", - &refnum, &parid, PyMac_GetStr255, &path)) { - err = FSMakeFSSpec(refnum, parid, path, spec); - if ( err && err != fnfErr ) { - PyMac_Error(err); - return 0; - } - return 1; - } - PyErr_Clear(); - /* Otherwise we try to go via an FSRef. On OSX we go all the way, - ** on OS9 we accept only a real FSRef object - */ - if ( PyMac_GetFSRef(v, &fsr) ) { - err = FSGetCatalogInfo(&fsr, kFSCatInfoNone, NULL, NULL, spec, NULL); - if (err != noErr) { - PyMac_Error(err); - return 0; - } - return 1; - } - return 0; + if (PyArg_Parse(v, "(hlO&)", + &refnum, &parid, PyMac_GetStr255, &path)) { + err = FSMakeFSSpec(refnum, parid, path, spec); + if ( err && err != fnfErr ) { + PyMac_Error(err); + return 0; + } + return 1; + } + PyErr_Clear(); + /* Otherwise we try to go via an FSRef. On OSX we go all the way, + ** on OS9 we accept only a real FSRef object + */ + if ( PyMac_GetFSRef(v, &fsr) ) { + err = FSGetCatalogInfo(&fsr, kFSCatInfoNone, NULL, NULL, spec, NULL); + if (err != noErr) { + PyMac_Error(err); + return 0; + } + return 1; + } + return 0; } int PyMac_GetFSRef(PyObject *v, FSRef *fsr) { - OSStatus err; - FSSpec fss; - - if (FSRef_Check(v)) { - *fsr = ((FSRefObject *)v)->ob_itself; - return 1; - } + OSStatus err; + FSSpec fss; - /* On OSX we now try a pathname */ - if ( PyString_Check(v) || PyUnicode_Check(v)) { - char *path = NULL; - if (!PyArg_Parse(v, "et", Py_FileSystemDefaultEncoding, &path)) - return NULL; - if ( (err=FSPathMakeRef(path, fsr, NULL)) ) { - PyMac_Error(err); - return 0; - } - return 1; - } - /* XXXX Should try unicode here too */ - /* Otherwise we try to go via an FSSpec */ - if (FSSpec_Check(v)) { - fss = ((FSSpecObject *)v)->ob_itself; - if ((err=FSpMakeFSRef(&fss, fsr)) == 0) - return 1; - PyMac_Error(err); - return 0; - } - PyErr_SetString(PyExc_TypeError, "FSRef, FSSpec or pathname required"); - return 0; + if (FSRef_Check(v)) { + *fsr = ((FSRefObject *)v)->ob_itself; + return 1; + } + + /* On OSX we now try a pathname */ + if ( PyString_Check(v) || PyUnicode_Check(v)) { + char *path = NULL; + if (!PyArg_Parse(v, "et", Py_FileSystemDefaultEncoding, &path)) + return 0; + if ( (err=FSPathMakeRef(path, fsr, NULL)) ) { + PyMac_Error(err); + return 0; + } + return 1; + } + /* XXXX Should try unicode here too */ + /* Otherwise we try to go via an FSSpec */ + if (FSSpec_Check(v)) { + fss = ((FSSpecObject *)v)->ob_itself; + if ((err=FSpMakeFSRef(&fss, fsr)) == 0) + return 1; + PyMac_Error(err); + return 0; + } + PyErr_SetString(PyExc_TypeError, "FSRef, FSSpec or pathname required"); + return 0; } extern PyObject * PyMac_BuildFSSpec(FSSpec *spec) { - return FSSpec_New(spec); + return FSSpec_New(spec); } extern PyObject * PyMac_BuildFSRef(FSRef *spec) { - return FSRef_New(spec); + return FSRef_New(spec); } Index: filesupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/file/filesupport.py,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- filesupport.py 18 Jul 2004 05:58:09 -0000 1.20 +++ filesupport.py 3 Jul 2005 20:59:40 -0000 1.21 @@ -254,7 +254,7 @@ if ( PyString_Check(v) || PyUnicode_Check(v)) { char *path = NULL; if (!PyArg_Parse(v, "et", Py_FileSystemDefaultEncoding, &path)) - return NULL; + return 0; if ( (err=FSPathMakeRef(path, fsr, NULL)) ) { PyMac_Error(err); return 0; @@ -389,22 +389,22 @@ ] # The same info, but in a different form INITFORMAT = "HhllO&O&O&O&O&llllllb" - INITARGS = """&((FSCatalogInfoObject *)self)->ob_itself.nodeFlags, - &((FSCatalogInfoObject *)self)->ob_itself.volume, - &((FSCatalogInfoObject *)self)->ob_itself.parentDirID, - &((FSCatalogInfoObject *)self)->ob_itself.nodeID, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.createDate, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.contentModDate, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.attributeModDate, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.accessDate, - UTCDateTime_Convert, &((FSCatalogInfoObject *)self)->ob_itself.backupDate, - &((FSCatalogInfoObject *)self)->ob_itself.valence, - &((FSCatalogInfoObject *)self)->ob_itself.dataLogicalSize, - &((FSCatalogInfoObject *)self)->ob_itself.dataPhysicalSize, - &((FSCatalogInfoObject *)self)->ob_itself.rsrcLogicalSize, - &((FSCatalogInfoObject *)self)->ob_itself.rsrcPhysicalSize, - &((FSCatalogInfoObject *)self)->ob_itself.sharingFlags, - &((FSCatalogInfoObject *)self)->ob_itself.userPrivileges""" + INITARGS = """&((FSCatalogInfoObject *)_self)->ob_itself.nodeFlags, + &((FSCatalogInfoObject *)_self)->ob_itself.volume, + &((FSCatalogInfoObject *)_self)->ob_itself.parentDirID, + &((FSCatalogInfoObject *)_self)->ob_itself.nodeID, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.createDate, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.contentModDate, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.attributeModDate, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.accessDate, + UTCDateTime_Convert, &((FSCatalogInfoObject *)_self)->ob_itself.backupDate, + &((FSCatalogInfoObject *)_self)->ob_itself.valence, + &((FSCatalogInfoObject *)_self)->ob_itself.dataLogicalSize, + &((FSCatalogInfoObject *)_self)->ob_itself.dataPhysicalSize, + &((FSCatalogInfoObject *)_self)->ob_itself.rsrcLogicalSize, + &((FSCatalogInfoObject *)_self)->ob_itself.rsrcPhysicalSize, + &((FSCatalogInfoObject *)_self)->ob_itself.sharingFlags, + &((FSCatalogInfoObject *)_self)->ob_itself.userPrivileges""" INITNAMES = """ "nodeFlags", "volume", @@ -442,7 +442,7 @@ def output_tp_initBody(self): Output("static char *kw[] = {%s, 0};", self.INITNAMES) Output() - Output("if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|%s\", kw, %s))", + Output("if (!PyArg_ParseTupleAndKeywords(_args, _kwds, \"|%s\", kw, %s))", self.INITFORMAT, self.INITARGS) OutLbrace() Output("return -1;") @@ -498,9 +498,9 @@ Output("%s *itself = NULL;", self.itselftype) Output("static char *kw[] = {\"itself\", 0};") Output() - Output("if (PyArg_ParseTupleAndKeywords(args, kwds, \"|O&\", kw, FInfo_Convert, &itself))") + Output("if (PyArg_ParseTupleAndKeywords(_args, _kwds, \"|O&\", kw, FInfo_Convert, &itself))") OutLbrace() - Output("if (itself) memcpy(&((%s *)self)->ob_itself, itself, sizeof(%s));", + Output("if (itself) memcpy(&((%s *)_self)->ob_itself, itself, sizeof(%s));", self.objecttype, self.itselftype) Output("return 0;") OutRbrace() @@ -540,7 +540,7 @@ Output("int rawdatalen = 0;") Output("static char *kw[] = {\"itself\", \"rawdata\", 0};") Output() - Output("if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|Os#\", kw, &v, &rawdata, &rawdatalen))") + Output("if (!PyArg_ParseTupleAndKeywords(_args, _kwds, \"|Os#\", kw, &v, &rawdata, &rawdatalen))") Output("return -1;") Output("if (v && rawdata)") OutLbrace() @@ -560,10 +560,10 @@ self.itselftype) Output("return -1;") OutRbrace() - Output("memcpy(&((%s *)self)->ob_itself, rawdata, rawdatalen);", self.objecttype) + Output("memcpy(&((%s *)_self)->ob_itself, rawdata, rawdatalen);", self.objecttype) Output("return 0;") OutRbrace() - Output("if (PyMac_GetFSSpec(v, &((%s *)self)->ob_itself)) return 0;", self.objecttype) + Output("if (PyMac_GetFSSpec(v, &((%s *)_self)->ob_itself)) return 0;", self.objecttype) Output("return -1;") def outputRepr(self): @@ -613,7 +613,7 @@ Output("int rawdatalen = 0;") Output("static char *kw[] = {\"itself\", \"rawdata\", 0};") Output() - Output("if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|Os#\", kw, &v, &rawdata, &rawdatalen))") + Output("if (!PyArg_ParseTupleAndKeywords(_args, _kwds, \"|Os#\", kw, &v, &rawdata, &rawdatalen))") Output("return -1;") Output("if (v && rawdata)") OutLbrace() @@ -633,10 +633,10 @@ self.itselftype) Output("return -1;") OutRbrace() - Output("memcpy(&((%s *)self)->ob_itself, rawdata, rawdatalen);", self.objecttype) + Output("memcpy(&((%s *)_self)->ob_itself, rawdata, rawdatalen);", self.objecttype) Output("return 0;") OutRbrace() - Output("if (PyMac_GetFSRef(v, &((%s *)self)->ob_itself)) return 0;", self.objecttype) + Output("if (PyMac_GetFSRef(v, &((%s *)_self)->ob_itself)) return 0;", self.objecttype) Output("return -1;") class AliasDefinition(PEP253Mixin, ObjectDefinition): @@ -689,7 +689,7 @@ Output("Handle h;") Output("static char *kw[] = {\"itself\", \"rawdata\", 0};") Output() - Output("if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|O&s#\", kw, %s_Convert, &itself, &rawdata, &rawdatalen))", + Output("if (!PyArg_ParseTupleAndKeywords(_args, _kwds, \"|O&s#\", kw, %s_Convert, &itself, &rawdata, &rawdatalen))", self.prefix) Output("return -1;") Output("if (itself && rawdata)") @@ -712,10 +712,10 @@ Output("HLock(h);") Output("memcpy((char *)*h, rawdata, rawdatalen);") Output("HUnlock(h);") - Output("((%s *)self)->ob_itself = (%s)h;", self.objecttype, self.itselftype) + Output("((%s *)_self)->ob_itself = (%s)h;", self.objecttype, self.itselftype) Output("return 0;") OutRbrace() - Output("((%s *)self)->ob_itself = itself;", self.objecttype) + Output("((%s *)_self)->ob_itself = itself;", self.objecttype) Output("return 0;") # Alias methods come in two flavors: those with the alias as arg1 and From jackjansen at users.sourceforge.net Sun Jul 3 23:00:13 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:13 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/ibcarbon _IBCarbon.c, 1.9, 1.10 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/ibcarbon In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/ibcarbon Modified Files: _IBCarbon.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _IBCarbon.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/ibcarbon/_IBCarbon.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- _IBCarbon.c 20 Nov 2003 13:30:57 -0000 1.9 +++ _IBCarbon.c 3 Jul 2005 20:59:40 -0000 1.10 @@ -34,6 +34,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int IBNibRefObj_Convert(PyObject *v, IBNibRef *p_itself) { if (!IBNibRefObj_Check(v)) @@ -145,16 +146,16 @@ #define IBNibRefObj_tp_alloc PyType_GenericAlloc -static PyObject *IBNibRefObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *IBNibRefObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; IBNibRef itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, IBNibRefObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((IBNibRefObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, IBNibRefObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((IBNibRefObject *)_self)->ob_itself = itself; + return _self; } #define IBNibRefObj_tp_free PyObject_Del From jackjansen at users.sourceforge.net Sun Jul 3 23:00:14 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:14 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/menu _Menumodule.c, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/menu In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/menu Modified Files: _Menumodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Menumodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/menu/_Menumodule.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- _Menumodule.c 6 Dec 2003 00:00:04 -0000 1.20 +++ _Menumodule.c 3 Jul 2005 20:59:40 -0000 1.21 @@ -24,7 +24,7 @@ extern int _MenuObj_Convert(PyObject *, MenuHandle *); #define MenuObj_New _MenuObj_New -#define MenuObj_Convert _MenuObj_Convert +#define MenuObj_Convert _MenuObj_Convert #endif #define as_Menu(h) ((MenuHandle)h) @@ -34,21 +34,21 @@ /* Alternative version of MenuObj_New, which returns None for NULL argument */ PyObject *OptMenuObj_New(MenuRef itself) { - if (itself == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return MenuObj_New(itself); + if (itself == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return MenuObj_New(itself); } /* Alternative version of MenuObj_Convert, which returns NULL for a None argument */ int OptMenuObj_Convert(PyObject *v, MenuRef *p_itself) { - if ( v == Py_None ) { - *p_itself = NULL; - return 1; - } - return MenuObj_Convert(v, p_itself); + if ( v == Py_None ) { + *p_itself = NULL; + return 1; + } + return MenuObj_Convert(v, p_itself); } static PyObject *Menu_Error; @@ -72,6 +72,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int MenuObj_Convert(PyObject *v, MenuHandle *p_itself) { if (!MenuObj_Check(v)) @@ -2536,16 +2537,16 @@ #define MenuObj_tp_alloc PyType_GenericAlloc -static PyObject *MenuObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *MenuObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; MenuHandle itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, MenuObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((MenuObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, MenuObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((MenuObject *)_self)->ob_itself = itself; + return _self; } #define MenuObj_tp_free PyObject_Del @@ -3445,8 +3446,8 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(MenuHandle, MenuObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(MenuHandle, MenuObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(MenuHandle, MenuObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(MenuHandle, MenuObj_Convert); m = Py_InitModule("_Menu", Menu_methods); From jackjansen at users.sourceforge.net Sun Jul 3 23:00:15 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:15 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/qdoffs _Qdoffsmodule.c, 1.15, 1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/qdoffs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/qdoffs Modified Files: _Qdoffsmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Qdoffsmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/qdoffs/_Qdoffsmodule.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- _Qdoffsmodule.c 20 Nov 2003 13:30:58 -0000 1.15 +++ _Qdoffsmodule.c 3 Jul 2005 20:59:42 -0000 1.16 @@ -50,6 +50,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int GWorldObj_Convert(PyObject *v, GWorldPtr *p_itself) { if (!GWorldObj_Check(v)) @@ -134,16 +135,16 @@ #define GWorldObj_tp_alloc PyType_GenericAlloc -static PyObject *GWorldObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *GWorldObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; GWorldPtr itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, GWorldObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((GWorldObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, GWorldObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((GWorldObject *)_self)->ob_itself = itself; + return _self; } #define GWorldObj_tp_free PyObject_Del @@ -605,7 +606,7 @@ char *cp; if ( !PyArg_ParseTuple(_args, "O&ii", ResObj_Convert, &pm, &from, &length) ) - return NULL; + return NULL; cp = GetPixBaseAddr(pm)+from; _res = PyString_FromStringAndSize(cp, length); return _res; @@ -621,7 +622,7 @@ char *cp, *icp; if ( !PyArg_ParseTuple(_args, "O&is#", ResObj_Convert, &pm, &from, &icp, &length) ) - return NULL; + return NULL; cp = GetPixBaseAddr(pm)+from; memcpy(cp, icp, length); Py_INCREF(Py_None); @@ -690,8 +691,8 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(GWorldPtr, GWorldObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GWorldPtr, GWorldObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(GWorldPtr, GWorldObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GWorldPtr, GWorldObj_Convert); m = Py_InitModule("_Qdoffs", Qdoffs_methods); From jackjansen at users.sourceforge.net Sun Jul 3 23:00:14 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:14 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/osa _OSAmodule.c, 1.3, 1.4 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/osa In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/osa Modified Files: _OSAmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _OSAmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/osa/_OSAmodule.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- _OSAmodule.c 10 Dec 2003 15:18:18 -0000 1.3 +++ _OSAmodule.c 3 Jul 2005 20:59:41 -0000 1.4 @@ -45,21 +45,22 @@ { OSAComponentInstanceObject *it; if (itself == NULL) { - PyErr_SetString(OSA_Error,"NULL ComponentInstance"); - return NULL; - } + PyErr_SetString(OSA_Error,"NULL ComponentInstance"); + return NULL; + } it = PyObject_NEW(OSAComponentInstanceObject, &OSAComponentInstance_Type); if (it == NULL) return NULL; it->ob_itself = itself; return (PyObject *)it; } + int OSAObj_Convert(PyObject *v, ComponentInstance *p_itself) { - if (CmpInstObj_Convert(v, p_itself)) - return 1; - PyErr_Clear(); - + if (CmpInstObj_Convert(v, p_itself)) + return 1; + PyErr_Clear(); + if (!OSAObj_Check(v)) { PyErr_SetString(PyExc_TypeError, "OSAComponentInstance required"); @@ -1133,16 +1134,16 @@ #define OSAObj_tp_alloc PyType_GenericAlloc -static PyObject *OSAObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *OSAObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; ComponentInstance itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, OSAObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((OSAComponentInstanceObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, OSAObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((OSAComponentInstanceObject *)_self)->ob_itself = itself; + return _self; } #define OSAObj_tp_free PyObject_Del @@ -1210,8 +1211,8 @@ /* - PyMac_INIT_TOOLBOX_OBJECT_NEW(ComponentInstance, OSAObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(ComponentInstance, OSAObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(ComponentInstance, OSAObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(ComponentInstance, OSAObj_Convert); */ From jackjansen at users.sourceforge.net Sun Jul 3 23:00:14 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:14 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/mlte _Mltemodule.c, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/mlte In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/mlte Modified Files: _Mltemodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Mltemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/mlte/_Mltemodule.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- _Mltemodule.c 3 Dec 2003 23:20:12 -0000 1.20 +++ _Mltemodule.c 3 Jul 2005 20:59:41 -0000 1.21 @@ -38,14 +38,14 @@ static int OptFSSpecPtr_Convert(PyObject *v, FSSpec **p_itself) { - static FSSpec fss; - if (v == Py_None) - { - *p_itself = NULL; - return 1; - } - *p_itself = &fss; - return PyMac_GetFSSpec(v, *p_itself); + static FSSpec fss; + if (v == Py_None) + { + *p_itself = NULL; + return 1; + } + *p_itself = &fss; + return PyMac_GetFSSpec(v, *p_itself); } /* @@ -54,15 +54,15 @@ static int OptRectPtr_Convert(PyObject *v, Rect **p_itself) { - static Rect r; - - if (v == Py_None) - { - *p_itself = NULL; - return 1; - } - *p_itself = &r; - return PyMac_GetRect(v, *p_itself); + static Rect r; + + if (v == Py_None) + { + *p_itself = NULL; + return 1; + } + *p_itself = &r; + return PyMac_GetRect(v, *p_itself); } /* @@ -70,13 +70,13 @@ */ static int OptGWorldObj_Convert(PyObject *v, GWorldPtr *p_itself) -{ - if (v == Py_None) - { - *p_itself = NULL; - return 1; - } - return GWorldObj_Convert(v, p_itself); +{ + if (v == Py_None) + { + *p_itself = NULL; + return 1; + } + return GWorldObj_Convert(v, p_itself); } @@ -102,6 +102,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int TXNObj_Convert(PyObject *v, TXNObject *p_itself) { if (!TXNObj_Check(v)) @@ -1255,16 +1256,16 @@ #define TXNObj_tp_alloc PyType_GenericAlloc -static PyObject *TXNObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *TXNObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; TXNObject itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, TXNObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((TXNObjectObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, TXNObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((TXNObjectObject *)_self)->ob_itself = itself; + return _self; } #define TXNObj_tp_free PyObject_Del @@ -1337,6 +1338,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int TXNFontMenuObj_Convert(PyObject *v, TXNFontMenuObject *p_itself) { if (!TXNFontMenuObj_Check(v)) @@ -1408,16 +1410,16 @@ #define TXNFontMenuObj_tp_alloc PyType_GenericAlloc -static PyObject *TXNFontMenuObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *TXNFontMenuObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; TXNFontMenuObject itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, TXNFontMenuObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((TXNFontMenuObjectObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, TXNFontMenuObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((TXNFontMenuObjectObject *)_self)->ob_itself = itself; + return _self; } #define TXNFontMenuObj_tp_free PyObject_Del @@ -1626,7 +1628,7 @@ TXNInitOptions iUsageFlags; PyMac_PRECHECK(TXNInitTextension); if (!PyArg_ParseTuple(_args, "l", &iUsageFlags)) - return NULL; + return NULL; _err = TXNInitTextension(iDefaultFonts, iCountDefaultFonts, iUsageFlags); @@ -1667,7 +1669,7 @@ - // PyMac_INIT_TOOLBOX_OBJECT_NEW(xxxx); + // PyMac_INIT_TOOLBOX_OBJECT_NEW(xxxx); m = Py_InitModule("_Mlte", Mlte_methods); From jackjansen at users.sourceforge.net Sun Jul 3 23:00:15 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sun, 03 Jul 2005 14:00:15 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/qd _Qdmodule.c, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/qd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25508/qd Modified Files: _Qdmodule.c Log Message: Updated (and regenerated) for name change in tp_init method arguments: they are now _self, _args and _kwds. Index: _Qdmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/qd/_Qdmodule.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- _Qdmodule.c 6 Dec 2003 00:00:14 -0000 1.20 +++ _Qdmodule.c 3 Jul 2005 20:59:42 -0000 1.21 @@ -41,19 +41,19 @@ PyObject *QdRGB_New(RGBColorPtr itself) { - return Py_BuildValue("lll", (long)itself->red, (long)itself->green, (long)itself->blue); + return Py_BuildValue("lll", (long)itself->red, (long)itself->green, (long)itself->blue); } int QdRGB_Convert(PyObject *v, RGBColorPtr p_itself) { - long red, green, blue; - - if( !PyArg_ParseTuple(v, "lll", &red, &green, &blue) ) - return 0; - p_itself->red = (unsigned short)red; - p_itself->green = (unsigned short)green; - p_itself->blue = (unsigned short)blue; - return 1; + long red, green, blue; + + if( !PyArg_ParseTuple(v, "lll", &red, &green, &blue) ) + return 0; + p_itself->red = (unsigned short)red; + p_itself->green = (unsigned short)green; + p_itself->blue = (unsigned short)blue; + return 1; } /* @@ -63,8 +63,8 @@ PyObject *QdFI_New(FontInfo *itself) { - return Py_BuildValue("hhhh", itself->ascent, itself->descent, - itself->widMax, itself->leading); + return Py_BuildValue("hhhh", itself->ascent, itself->descent, + itself->widMax, itself->leading); } static PyObject *Qd_Error; @@ -89,6 +89,7 @@ it->ob_itself = itself; return (PyObject *)it; } + int GrafObj_Convert(PyObject *v, GrafPtr *p_itself) { #if 1 @@ -1310,8 +1311,8 @@ static PyObject *GrafObj_get_visRgn(GrafPortObject *self, void *closure) { RgnHandle h=NewRgn(); /* XXXX wrong dispose routine */ - return Py_BuildValue("O&", ResObj_New, (Handle)GetPortVisibleRegion(self->ob_itself, h)); - + return Py_BuildValue("O&", ResObj_New, (Handle)GetPortVisibleRegion(self->ob_itself, h)); + } #define GrafObj_set_visRgn NULL @@ -1319,8 +1320,8 @@ static PyObject *GrafObj_get_clipRgn(GrafPortObject *self, void *closure) { RgnHandle h=NewRgn(); /* XXXX wrong dispose routine */ - return Py_BuildValue("O&", ResObj_New, (Handle)GetPortClipRegion(self->ob_itself, h)); - + return Py_BuildValue("O&", ResObj_New, (Handle)GetPortClipRegion(self->ob_itself, h)); + } #define GrafObj_set_clipRgn NULL @@ -1341,16 +1342,16 @@ #define GrafObj_tp_alloc PyType_GenericAlloc -static PyObject *GrafObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *GrafObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; GrafPtr itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, GrafObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((GrafPortObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, GrafObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((GrafPortObject *)_self)->ob_itself = itself; + return _self; } #define GrafObj_tp_free PyObject_Del @@ -1427,6 +1428,7 @@ it->referred_bitmap = NULL; return (PyObject *)it; } + int BMObj_Convert(PyObject *v, BitMapPtr *p_itself) { if (!BMObj_Check(v)) @@ -1453,7 +1455,7 @@ char *cp; if ( !PyArg_ParseTuple(_args, "ii", &from, &length) ) - return NULL; + return NULL; cp = _self->ob_itself->baseAddr+from; _res = PyString_FromStringAndSize(cp, length); return _res; @@ -1468,7 +1470,7 @@ char *cp, *icp; if ( !PyArg_ParseTuple(_args, "is#", &from, &icp, &length) ) - return NULL; + return NULL; cp = _self->ob_itself->baseAddr+from; memcpy(cp, icp, length); Py_INCREF(Py_None); @@ -1539,16 +1541,16 @@ #define BMObj_tp_alloc PyType_GenericAlloc -static PyObject *BMObj_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *BMObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds) { - PyObject *self; + PyObject *_self; BitMapPtr itself; char *kw[] = {"itself", 0}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kw, BMObj_Convert, &itself)) return NULL; - if ((self = type->tp_alloc(type, 0)) == NULL) return NULL; - ((BitMapObject *)self)->ob_itself = itself; - return self; + if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, BMObj_Convert, &itself)) return NULL; + if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL; + ((BitMapObject *)_self)->ob_itself = itself; + return _self; } #define BMObj_tp_free PyObject_Del @@ -5822,6 +5824,7 @@ { PyObject *_res = NULL; char *textBuf__in__; + int textBuf__len__; int textBuf__in_len__; short firstByte; short byteCount; @@ -5882,6 +5885,7 @@ PyObject *_res = NULL; short _rv; char *textBuf__in__; + int textBuf__len__; int textBuf__in_len__; short firstByte; short byteCount; @@ -6467,6 +6471,7 @@ { PyObject *_res = NULL; char *textBuf__in__; + int textBuf__len__; int textBuf__in_len__; short firstByte; short byteCount; @@ -6499,17 +6504,17 @@ char *data; if ( !PyArg_ParseTuple(_args, "O!iO&", &PyString_Type, &source, &rowbytes, PyMac_GetRect, - &bounds) ) - return NULL; + &bounds) ) + return NULL; data = PyString_AsString(source); if ((ptr=(BitMap *)malloc(sizeof(BitMap))) == NULL ) - return PyErr_NoMemory(); + return PyErr_NoMemory(); ptr->baseAddr = (Ptr)data; ptr->rowBytes = rowbytes; ptr->bounds = bounds; if ( (_res = BMObj_New(ptr)) == NULL ) { - free(ptr); - return NULL; + free(ptr); + return NULL; } ((BitMapObject *)_res)->referred_object = source; Py_INCREF(source); @@ -6526,16 +6531,16 @@ PyObject *source; if ( !PyArg_ParseTuple(_args, "O!", &PyString_Type, &source) ) - return NULL; + return NULL; if ( PyString_Size(source) != sizeof(BitMap) && PyString_Size(source) != sizeof(PixMap) ) { - PyErr_Format(PyExc_TypeError, - "Argument size was %d, should be %d (sizeof BitMap) or %d (sizeof PixMap)", - PyString_Size(source), sizeof(BitMap), sizeof(PixMap)); - return NULL; + PyErr_Format(PyExc_TypeError, + "Argument size was %d, should be %d (sizeof BitMap) or %d (sizeof PixMap)", + PyString_Size(source), sizeof(BitMap), sizeof(PixMap)); + return NULL; } ptr = (BitMapPtr)PyString_AsString(source); if ( (_res = BMObj_New(ptr)) == NULL ) { - return NULL; + return NULL; } ((BitMapObject *)_res)->referred_object = source; Py_INCREF(source); @@ -7088,15 +7093,15 @@ */ PyObject *BMObj_NewCopied(BitMapPtr itself) { - BitMapObject *it; - BitMapPtr itself_copy; - - if ((itself_copy=(BitMapPtr)malloc(sizeof(BitMap))) == NULL) - return PyErr_NoMemory(); - *itself_copy = *itself; - it = (BitMapObject *)BMObj_New(itself_copy); - it->referred_bitmap = itself_copy; - return (PyObject *)it; + BitMapObject *it; + BitMapPtr itself_copy; + + if ((itself_copy=(BitMapPtr)malloc(sizeof(BitMap))) == NULL) + return PyErr_NoMemory(); + *itself_copy = *itself; + it = (BitMapObject *)BMObj_New(itself_copy); + it->referred_bitmap = itself_copy; + return (PyObject *)it; } @@ -7108,12 +7113,12 @@ - PyMac_INIT_TOOLBOX_OBJECT_NEW(BitMapPtr, BMObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(BitMapPtr, BMObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(GrafPtr, GrafObj_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GrafPtr, GrafObj_Convert); - PyMac_INIT_TOOLBOX_OBJECT_NEW(RGBColorPtr, QdRGB_New); - PyMac_INIT_TOOLBOX_OBJECT_CONVERT(RGBColor, QdRGB_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(BitMapPtr, BMObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(BitMapPtr, BMObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(GrafPtr, GrafObj_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(GrafPtr, GrafObj_Convert); + PyMac_INIT_TOOLBOX_OBJECT_NEW(RGBColorPtr, QdRGB_New); + PyMac_INIT_TOOLBOX_OBJECT_CONVERT(RGBColor, QdRGB_Convert); m = Py_InitModule("_Qd", Qd_methods); From rhettinger at users.sourceforge.net Mon Jul 4 08:40:55 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sun, 03 Jul 2005 23:40:55 -0700 Subject: [Python-checkins] python/nondist/peps pep-0284.txt,1.3,1.4 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19468 Modified Files: pep-0284.txt Log Message: Update status to match pronouncement. Index: pep-0284.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0284.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- pep-0284.txt 18 Jun 2005 20:36:28 -0000 1.3 +++ pep-0284.txt 4 Jul 2005 06:40:53 -0000 1.4 @@ -4,7 +4,7 @@ Last-Modified: $Date$ Author: eppstein at ics.uci.edu (David Eppstein), greg at cosc.canterbury.ac.nz (Greg Ewing) -Status: Draft +Status: Rejected Type: Standards Track Created: 1-Mar-2002 Python-Version: 2.3 From birkenfeld at users.sourceforge.net Mon Jul 4 16:17:50 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 04 Jul 2005 07:17:50 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libstdtypes.tex, 1.183, 1.184 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5631/Doc/lib Modified Files: libstdtypes.tex Log Message: Revert patch for 1162912. Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.183 retrieving revision 1.184 diff -u -d -r1.183 -r1.184 --- libstdtypes.tex 3 Jul 2005 20:21:40 -0000 1.183 +++ libstdtypes.tex 4 Jul 2005 14:17:47 -0000 1.184 @@ -1146,9 +1146,6 @@ because \var{cmp} is called multiple times for each list element while \var{key} and \var{reverse} touch each element only once. - \note{If both \var{key} and \var{cmp} are supplied the \var{key} - function is applied before the \var{cmp} function.} - \versionchanged[Support for \code{None} as an equivalent to omitting \var{cmp} was added]{2.3} From birkenfeld at users.sourceforge.net Mon Jul 4 16:18:23 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 04 Jul 2005 07:18:23 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libstdtypes.tex, 1.170.2.12, 1.170.2.13 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5638/Doc/lib Modified Files: Tag: release24-maint libstdtypes.tex Log Message: Revert patch for 1162912. Index: libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.170.2.12 retrieving revision 1.170.2.13 diff -u -d -r1.170.2.12 -r1.170.2.13 --- libstdtypes.tex 3 Jul 2005 20:22:13 -0000 1.170.2.12 +++ libstdtypes.tex 4 Jul 2005 14:18:20 -0000 1.170.2.13 @@ -1146,9 +1146,6 @@ because \var{cmp} is called multiple times for each list element while \var{key} and \var{reverse} touch each element only once. - \note{If both \var{key} and \var{cmp} are supplied the \var{key} - function is applied before the \var{cmp} function.} - \versionchanged[Support for \code{None} as an equivalent to omitting \var{cmp} was added]{2.3} From birkenfeld at users.sourceforge.net Mon Jul 4 19:16:09 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 04 Jul 2005 10:16:09 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1308,1.1309 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27391/Misc Modified Files: NEWS Log Message: bug #1177468: don't cache /dev/urandom file descriptor in os.urandom Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1308 retrieving revision 1.1309 diff -u -d -r1.1308 -r1.1309 --- NEWS 29 Jun 2005 23:29:43 -0000 1.1308 +++ NEWS 4 Jul 2005 17:16:05 -0000 1.1309 @@ -150,6 +150,9 @@ Library ------- +- Bug #1177468: Don't cache the /dev/urandom file descriptor for os.urandom, + as this can cause problems with apps closing all file descriptors. + - Bug #839151: Fix an attempt to access sys.argv in the warnings module though this can be missing in embedded interpreters From birkenfeld at users.sourceforge.net Mon Jul 4 19:16:10 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 04 Jul 2005 10:16:10 -0700 Subject: [Python-checkins] python/dist/src/Lib os.py,1.86,1.87 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27391/Lib Modified Files: os.py Log Message: bug #1177468: don't cache /dev/urandom file descriptor in os.urandom Index: os.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/os.py,v retrieving revision 1.86 retrieving revision 1.87 diff -u -d -r1.86 -r1.87 --- os.py 17 Feb 2005 21:23:20 -0000 1.86 +++ os.py 4 Jul 2005 17:16:07 -0000 1.87 @@ -715,22 +715,18 @@ pass if not _exists("urandom"): - _urandomfd = None def urandom(n): """urandom(n) -> str Return a string of n random bytes suitable for cryptographic use. """ - global _urandomfd - if _urandomfd is None: - try: - _urandomfd = open("/dev/urandom", O_RDONLY) - except: - _urandomfd = NotImplementedError - if _urandomfd is NotImplementedError: + try: + _urandomfd = open("/dev/urandom", O_RDONLY) + except: raise NotImplementedError("/dev/urandom (or equivalent) not found") bytes = "" while len(bytes) < n: bytes += read(_urandomfd, n - len(bytes)) + close(_urandomfd) return bytes From birkenfeld at users.sourceforge.net Mon Jul 4 19:17:10 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 04 Jul 2005 10:17:10 -0700 Subject: [Python-checkins] python/dist/src/Lib os.py,1.83.2.2,1.83.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27858/Lib Modified Files: Tag: release24-maint os.py Log Message: backport bug #1177468: don't cache /dev/urandom file descriptor in os.urandom Index: os.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/os.py,v retrieving revision 1.83.2.2 retrieving revision 1.83.2.3 diff -u -d -r1.83.2.2 -r1.83.2.3 --- os.py 17 Feb 2005 21:23:42 -0000 1.83.2.2 +++ os.py 4 Jul 2005 17:16:52 -0000 1.83.2.3 @@ -708,22 +708,18 @@ pass if not _exists("urandom"): - _urandomfd = None def urandom(n): """urandom(n) -> str Return a string of n random bytes suitable for cryptographic use. """ - global _urandomfd - if _urandomfd is None: - try: - _urandomfd = open("/dev/urandom", O_RDONLY) - except: - _urandomfd = NotImplementedError - if _urandomfd is NotImplementedError: + try: + _urandomfd = open("/dev/urandom", O_RDONLY) + except: raise NotImplementedError("/dev/urandom (or equivalent) not found") bytes = "" while len(bytes) < n: bytes += read(_urandomfd, n - len(bytes)) + close(_urandomfd) return bytes From birkenfeld at users.sourceforge.net Mon Jul 4 19:17:26 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 04 Jul 2005 10:17:26 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS, 1.1193.2.58, 1.1193.2.59 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27858/Misc Modified Files: Tag: release24-maint NEWS Log Message: backport bug #1177468: don't cache /dev/urandom file descriptor in os.urandom Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.58 retrieving revision 1.1193.2.59 diff -u -d -r1.1193.2.58 -r1.1193.2.59 --- NEWS 26 Jun 2005 22:55:05 -0000 1.1193.2.58 +++ NEWS 4 Jul 2005 17:16:53 -0000 1.1193.2.59 @@ -39,6 +39,9 @@ Library ------- +- Bug #1177468: Don't cache the /dev/urandom file descriptor for os.urandom, + as this can cause problems with apps closing all file descriptors. + - Bug #839151: Fix an attempt to access sys.argv in the warnings module though this can be missing in embedded interpreters From pje at users.sourceforge.net Mon Jul 4 20:44:28 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 04 Jul 2005 11:44:28 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.16, 1.17 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9525 Modified Files: EasyInstall.txt Log Message: Add missing download links Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- EasyInstall.txt 27 Jun 2005 00:31:02 -0000 1.16 +++ EasyInstall.txt 4 Jul 2005 18:44:26 -0000 1.17 @@ -26,8 +26,12 @@ Windows `_. All others should just download `ez_setup.py `_, and run it; this will -download and install the correct version of ``setuptools`` for your Python -version. You may receive a message telling you about an obsolete version of +download and install the `Python 2.3 egg`_ or `Python 2.4 egg`_ for you. + +.. _Python 2.3 egg: http://peak.telecommunity.com/dist/setuptools-0.5a4-py2.3.egg +.. _Python 2.4 egg: http://peak.telecommunity.com/dist/setuptools-0.5a4-py2.4.egg + +You may receive a message telling you about an obsolete version of setuptools being present; if so, you must be sure to delete it entirely, along with the old ``pkg_resources`` module if it's present on ``sys.path``. @@ -74,7 +78,7 @@ easy_install /my_downloads/OtherPackage-3.2.1-py2.3.egg **Example 5**. Upgrade an already-installed package to the latest version -listed on PyPI: +listed on PyPI:: easy_install --upgrade PyProtocols From pje at users.sourceforge.net Mon Jul 4 20:45:05 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 04 Jul 2005 11:45:05 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools easy_install.py, 1.24, 1.25 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9903 Modified Files: easy_install.py Log Message: Fix typo Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/easy_install.py,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- easy_install.py 27 Jun 2005 00:31:02 -0000 1.24 +++ easy_install.py 4 Jul 2005 18:45:02 -0000 1.25 @@ -192,7 +192,7 @@ def add_output(self, path): if os.path.isdir(path): - for base, dirs, files in walk(path): + for base, dirs, files in os.walk(path): for filename in files: self.outputs.append(os.path.join(base,filename)) else: From pje at users.sourceforge.net Mon Jul 4 20:45:43 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 04 Jul 2005 11:45:43 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools dist.py, 1.8, 1.9 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10252/setuptools Modified Files: dist.py Log Message: Fix a problem using bdist_egg with non-setuptools distributions. Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- dist.py 27 Jun 2005 00:31:02 -0000 1.8 +++ dist.py 4 Jul 2005 18:45:41 -0000 1.9 @@ -89,6 +89,7 @@ self.requires = [] self.install_requires = [] self.extras_require = {} + self.dist_files = [] _Distribution.__init__(self,attrs) if not have_package_data: from setuptools.command.build_py import build_py @@ -120,7 +121,6 @@ - def finalize_options(self): _Distribution.finalize_options(self) From pje at users.sourceforge.net Mon Jul 4 20:45:44 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 04 Jul 2005 11:45:44 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command bdist_egg.py, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10252/setuptools/command Modified Files: bdist_egg.py Log Message: Fix a problem using bdist_egg with non-setuptools distributions. Index: bdist_egg.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/bdist_egg.py,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- bdist_egg.py 27 Jun 2005 00:31:03 -0000 1.19 +++ bdist_egg.py 4 Jul 2005 18:45:41 -0000 1.20 @@ -201,9 +201,8 @@ self.call_command('install_scripts', install_dir=script_dir) self.write_requirements() - - log.info("writing %s" % os.path.join(self.egg_info,'PKG-INFO')) + if not self.dry_run: metadata = self.distribution.metadata metadata.version, oldver = self.egg_version, metadata.version @@ -233,9 +232,7 @@ if os.path.exists(os.path.join(self.egg_info,'depends.txt')): log.warn( - "WARNING: 'depends.txt' will not be used by setuptools 0.6!" - ) - log.warn( + "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" "Use the install_requires/extras_require setup() args instead." ) # Make the archive @@ -244,6 +241,9 @@ if not self.keep_temp: remove_tree(self.bdist_dir, dry_run=self.dry_run) + getattr(self.distribution,'dist_files',[]).append( + ('bdist_egg',get_python_version(),self.egg_output)) + def tagged_version(self): version = self.distribution.get_version() if self.tag_build: From pierslauder at users.sourceforge.net Tue Jul 5 06:20:09 2005 From: pierslauder at users.sourceforge.net (pierslauder@users.sourceforge.net) Date: Mon, 04 Jul 2005 21:20:09 -0700 Subject: [Python-checkins] python/dist/src/Lib imaplib.py,1.76,1.77 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19841/dist/src/Lib Modified Files: imaplib.py Log Message: fixed tag generation to avoid null tags Index: imaplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/imaplib.py,v retrieving revision 1.76 retrieving revision 1.77 diff -u -d -r1.76 -r1.77 --- imaplib.py 1 Jun 2005 23:50:51 -0000 1.76 +++ imaplib.py 5 Jul 2005 04:20:07 -0000 1.77 @@ -20,7 +20,7 @@ # PROXYAUTH contributed by Rick Holbert November 2002. # GET/SETANNOTATION contributed by Tomas Lindroos June 2005. -__version__ = "2.56" +__version__ = "2.57" import binascii, os, random, re, socket, sys, time @@ -165,7 +165,7 @@ # Create unique tag for this session, # and compile tagged response matcher. - self.tagpre = Int2AP(random.randint(0, 31999)) + self.tagpre = Int2AP(random.randint(4096, 65535)) self.tagre = re.compile(r'(?P' + self.tagpre + r'\d+) (?P[A-Z]+) (?P.*)') From rhettinger at users.sourceforge.net Tue Jul 5 07:34:45 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Mon, 04 Jul 2005 22:34:45 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_set.py,1.17,1.18 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22257 Modified Files: test_set.py Log Message: Add test for hash commutativity. Index: test_set.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_set.py,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- test_set.py 18 Jun 2005 21:00:26 -0000 1.17 +++ test_set.py 5 Jul 2005 05:34:43 -0000 1.18 @@ -5,6 +5,7 @@ import copy import pickle import os +from random import randrange, shuffle class PassThru(Exception): pass @@ -399,6 +400,15 @@ self.assertEqual(hash(self.thetype('abcdeb')), hash(self.thetype('ebecda'))) + # make sure that all permutations give the same hash value + n = 100 + seq = [randrange(n) for i in xrange(n)] + results = set() + for i in xrange(200): + shuffle(seq) + results.add(hash(self.thetype(seq))) + self.assertEqual(len(results), 1) + def test_copy(self): dup = self.s.copy() self.assertEqual(id(self.s), id(dup)) From jackjansen at users.sourceforge.net Tue Jul 5 12:01:00 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Tue, 05 Jul 2005 03:01:00 -0700 Subject: [Python-checkins] python/dist/src/Tools/bgen/bgen bgenBuffer.py, 1.11, 1.12 bgenHeapBuffer.py, 1.6, 1.7 bgenType.py, 1.18, 1.19 bgenVariable.py, 1.9, 1.10 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/bgen/bgen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17531 Modified Files: bgenBuffer.py bgenHeapBuffer.py bgenType.py bgenVariable.py Log Message: Allow for (optional) const declaration. Index: bgenBuffer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenBuffer.py,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- bgenBuffer.py 28 Jun 2005 15:14:34 -0000 1.11 +++ bgenBuffer.py 5 Jul 2005 10:00:57 -0000 1.12 @@ -38,19 +38,26 @@ self.sizeformat = sizeformat or type2format[sizetype] self.label_needed = 0 - def getArgDeclarations(self, name, reference=False): + def getArgDeclarations(self, name, reference=False, constmode=False): if reference: raise RuntimeError, "Cannot pass buffer types by reference" - return (self.getBufferDeclarations(name) + + return (self.getBufferDeclarations(name, constmode) + self.getSizeDeclarations(name)) - def getBufferDeclarations(self, name): - return self.getInputBufferDeclarations(name) + self.getOutputBufferDeclarations(name) + def getBufferDeclarations(self, name, constmode=False): + return self.getInputBufferDeclarations(name, constmode) + \ + self.getOutputBufferDeclarations(name, constmode) - def getInputBufferDeclarations(self, name): - return ["%s *%s__in__" % (self.datatype, name)] + def getInputBufferDeclarations(self, name, constmode=False): + if constmode: + const = "const " + else: + const = "" + return ["%s%s *%s__in__" % (const, self.datatype, name)] - def getOutputBufferDeclarations(self, name): + def getOutputBufferDeclarations(self, name, constmode=False): + if constmode: + raise RuntimeError, "Cannot use const output buffer" return ["%s %s__out__[%s]" % (self.datatype, name, self.size)] def getSizeDeclarations(self, name): @@ -105,13 +112,13 @@ class InputOnlyBufferMixIn(InputOnlyMixIn): - def getOutputBufferDeclarations(self, name): + def getOutputBufferDeclarations(self, name, constmode=False): return [] class OutputOnlyBufferMixIn(OutputOnlyMixIn): - def getInputBufferDeclarations(self, name): + def getInputBufferDeclarations(self, name, constmode=False): return [] class OptionalInputBufferMixIn: @@ -186,8 +193,12 @@ FixedInputOutputBufferType.__init__(self, "sizeof(%s)" % type) self.typeName = self.type = type - def getInputBufferDeclarations(self, name): - return ["%s *%s__in__" % (self.type, name)] + def getInputBufferDeclarations(self, name, constmode=False): + if constmode: + const = "const " + else: + const = "" + return ["%s%s *%s__in__" % (const, self.type, name)] def getSizeDeclarations(self, name): return [] @@ -195,7 +206,9 @@ def getAuxDeclarations(self, name): return ["int %s__in_len__" % (name)] - def getOutputBufferDeclarations(self, name): + def getOutputBufferDeclarations(self, name, constmode=False): + if constmode: + raise RuntimeError, "Cannot use const output buffer" return ["%s %s__out__" % (self.type, name)] def getargsArgs(self, name): Index: bgenHeapBuffer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenHeapBuffer.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- bgenHeapBuffer.py 22 Jun 2005 20:35:23 -0000 1.6 +++ bgenHeapBuffer.py 5 Jul 2005 10:00:57 -0000 1.7 @@ -16,7 +16,9 @@ def __init__(self, datatype = 'char', sizetype = 'int', sizeformat = None): FixedInputOutputBufferType.__init__(self, "0", datatype, sizetype, sizeformat) - def getOutputBufferDeclarations(self, name): + def getOutputBufferDeclarations(self, name, constmode=False): + if constmode: + raise RuntimeError, "Cannot use const output buffer" return ["%s *%s__out__" % (self.datatype, name)] def getargsCheck(self, name): @@ -74,7 +76,7 @@ Call from Python with buffer size. """ - def getInputBufferDeclarations(self, name): + def getInputBufferDeclarations(self, name, constmode=False): return [] def getargsFormat(self): Index: bgenType.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenType.py,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- bgenType.py 1 Jul 2005 20:23:27 -0000 1.18 +++ bgenType.py 5 Jul 2005 10:00:57 -0000 1.19 @@ -29,13 +29,18 @@ for decl in self.getAuxDeclarations(name): Output("%s;", decl) - def getArgDeclarations(self, name, reference=False): + def getArgDeclarations(self, name, reference=False, constmode=False): """Return the main part of the declarations for this type: the items that will be passed as arguments in the C/C++ function call.""" if reference: - return ["%s& %s" % (self.typeName, name)] + ref = "&" else: - return ["%s %s" % (self.typeName, name)] + ref = "" + if constmode: + const = "const " + else: + const = "" + return ["%s%s%s %s" % (const, self.typeName, ref, name)] def getAuxDeclarations(self, name): """Return any auxiliary declarations needed for implementing this @@ -208,7 +213,7 @@ self.substitute = substitute self.typeName = None # Don't show this argument in __doc__ string - def getArgDeclarations(self, name, reference=False): + def getArgDeclarations(self, name, reference=False, constmode=False): return [] def getAuxDeclarations(self, name, reference=False): Index: bgenVariable.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenVariable.py,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- bgenVariable.py 1 Jul 2005 20:23:27 -0000 1.9 +++ bgenVariable.py 5 Jul 2005 10:00:57 -0000 1.10 @@ -45,9 +45,12 @@ elif self.flags != SelfMode: self.type.declare(self.name) - def getArgDeclarations(self): + def getArgDeclarations(self, constmode=False): refmode = (self.flags & RefMode) - return self.type.getArgDeclarations(self.name, reference=refmode) + if constmode: + constmode = (self.flags & ConstMode) + return self.type.getArgDeclarations(self.name, + reference=refmode, constmode=constmode) def getAuxDeclarations(self): return self.type.getAuxDeclarations(self.name) From mwh at users.sourceforge.net Tue Jul 5 17:22:16 2005 From: mwh at users.sourceforge.net (mwh@users.sourceforge.net) Date: Tue, 05 Jul 2005 08:22:16 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1309,1.1310 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9704/Misc Modified Files: NEWS Log Message: Fix bug [ 1232517 ] OverflowError in time.utime() causes strange traceback A needed error check was missing. (Actually, this error check may only have become necessary in fairly recent Python, not sure). Backport candidate. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1309 retrieving revision 1.1310 diff -u -d -r1.1309 -r1.1310 --- NEWS 4 Jul 2005 17:16:05 -0000 1.1309 +++ NEWS 5 Jul 2005 15:21:55 -0000 1.1310 @@ -12,6 +12,9 @@ Core and builtins ----------------- +- SF bug #1232517: An overflow error was not detected properly when + attempting to convert a large float to an int in os.utime(). + - SF bug #1224347: hex longs now print with lowercase letters just like their int counterparts. From mwh at users.sourceforge.net Tue Jul 5 17:22:31 2005 From: mwh at users.sourceforge.net (mwh@users.sourceforge.net) Date: Tue, 05 Jul 2005 08:22:31 -0700 Subject: [Python-checkins] python/dist/src/Modules posixmodule.c, 2.336, 2.337 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9704/Modules Modified Files: posixmodule.c Log Message: Fix bug [ 1232517 ] OverflowError in time.utime() causes strange traceback A needed error check was missing. (Actually, this error check may only have become necessary in fairly recent Python, not sure). Backport candidate. Index: posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.336 retrieving revision 2.337 diff -u -d -r2.336 -r2.337 --- posixmodule.c 2 Jun 2005 13:09:28 -0000 2.336 +++ posixmodule.c 5 Jul 2005 15:21:58 -0000 2.337 @@ -1991,6 +1991,8 @@ return -1; intval = PyInt_AsLong(intobj); Py_DECREF(intobj); + if (intval == -1 && PyErr_Occurred()) + return -1; *sec = intval; *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */ if (*usec < 0) From pje at users.sourceforge.net Wed Jul 6 03:37:43 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 18:37:43 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12500 Modified Files: EasyInstall.txt Log Message: Added ``egg_info`` command to ``setuptools``-based packages. This command just creates or updates the "projectname.egg-info" directory, without building an egg. It's used by the ``bdist_egg`` command now, and will be used by the ``test`` and ``develop`` commands later on. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- EasyInstall.txt 4 Jul 2005 18:44:26 -0000 1.17 +++ EasyInstall.txt 6 Jul 2005 01:37:41 -0000 1.18 @@ -481,6 +481,12 @@ * There's no automatic retry for borked Sourceforge mirrors, which can easily time out or be missing a file. +0.5a5 + * Added ``egg_info`` command to ``setuptools``-based packages. This command + just creates or updates the "projectname.egg-info" directory, without + building an egg. It's used by the ``bdist_egg`` command now, and will be + used by the ``test`` and ``develop`` commands later on. + 0.5a4 * Added ``--always-copy/-a`` option to always copy needed packages to the installation directory, even if they're already present elsewhere on From pje at users.sourceforge.net Wed Jul 6 03:37:43 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 18:37:43 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command egg_info.py, NONE, 1.1 bdist_egg.py, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12500/setuptools/command Modified Files: bdist_egg.py Added Files: egg_info.py Log Message: Added ``egg_info`` command to ``setuptools``-based packages. This command just creates or updates the "projectname.egg-info" directory, without building an egg. It's used by the ``bdist_egg`` command now, and will be used by the ``test`` and ``develop`` commands later on. --- NEW FILE: egg_info.py --- """setuptools.command.egg_info Create a distribution's .egg-info directory and contents""" # This module should be kept compatible with Python 2.3 import os from setuptools import Command from distutils.errors import * from distutils import log from pkg_resources import parse_requirements, safe_name, \ safe_version, yield_lines class egg_info(Command): description = "create a distribution's .egg-info directory" user_options = [ ('egg-base=', 'e', "directory containing .egg-info directories" " (default: top of the source tree)"), ('tag-svn-revision', 'r', "Add subversion revision ID to version number"), ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"), ('tag-build=', 'b', "Specify explicit tag to add to version number"), ] boolean_options = ['tag-date','tag-svn-revision'] def initialize_options (self): self.egg_name = None self.egg_version = None self.egg_base = None self.egg_info = None self.tag_build = None self.tag_svn_revision = 0 self.tag_date = 0 def finalize_options (self): self.egg_name = safe_name(self.distribution.get_name()) self.egg_version = self.tagged_version() try: list( parse_requirements('%s==%s' % (self.egg_name,self.egg_version)) ) except ValueError: raise DistutilsOptionError( "Invalid distribution name or version syntax: %s-%s" % (self.egg_name,self.egg_version) ) if self.egg_base is None: dirs = self.distribution.package_dir self.egg_base = (dirs or {}).get('',os.curdir) self.ensure_dirname('egg_base') self.egg_info = os.path.join(self.egg_base, self.egg_name+'.egg-info') def run(self): # Make the .egg-info directory, then write PKG-INFO and requires.txt self.mkpath(self.egg_info) log.info("writing %s" % os.path.join(self.egg_info,'PKG-INFO')) if not self.dry_run: metadata = self.distribution.metadata metadata.version, oldver = self.egg_version, metadata.version metadata.name, oldname = self.egg_name, metadata.name try: metadata.write_pkg_info(self.egg_info) finally: metadata.name, metadata.version = oldname, oldver self.write_requirements() if os.path.exists(os.path.join(self.egg_info,'depends.txt')): log.warn( "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" "Use the install_requires/extras_require setup() args instead." ) def write_requirements(self): dist = self.distribution if not getattr(dist,'install_requires',None) and \ not getattr(dist,'extras_require',None): return requires = os.path.join(self.egg_info,"requires.txt") log.info("writing %s", requires) if not self.dry_run: f = open(requires, 'wt') f.write('\n'.join(yield_lines(dist.install_requires))) for extra,reqs in dist.extras_require.items(): f.write('\n\n[%s]\n%s' % (extra, '\n'.join(yield_lines(reqs)))) f.close() def tagged_version(self): version = self.distribution.get_version() if self.tag_build: version+='-'+self.tag_build if self.tag_svn_revision and os.path.exists('.svn'): version += '-%s' % self.get_svn_revision() if self.tag_date: import time version += time.strftime("-%Y%m%d") return safe_version(version) def get_svn_revision(self): stdin, stdout = os.popen4("svn info"); stdin.close() result = stdout.read(); stdout.close() import re match = re.search(r'Last Changed Rev: (\d+)', result) if not match: raise RuntimeError("svn info error: %s" % result.strip()) return match.group(1) Index: bdist_egg.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/bdist_egg.py,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- bdist_egg.py 4 Jul 2005 18:45:41 -0000 1.20 +++ bdist_egg.py 6 Jul 2005 01:37:41 -0000 1.21 @@ -5,13 +5,10 @@ # This module should be kept compatible with Python 2.3 import os from setuptools import Command -from distutils.util import get_platform -from distutils.dir_util import create_tree, remove_tree, ensure_relative,mkpath +from distutils.dir_util import remove_tree, mkpath from distutils.sysconfig import get_python_version, get_python_lib -from distutils.errors import * from distutils import log -from pkg_resources import parse_requirements, get_platform, safe_name, \ - safe_version, Distribution, yield_lines +from pkg_resources import get_platform, Distribution def write_stub(resource, pyfile): @@ -39,17 +36,16 @@ + + + class bdist_egg(Command): + description = "create an \"egg\" distribution" + user_options = [ - ('egg-base=', 'e', "directory containing .egg-info directories" - " (default: top of the source tree)"), ('bdist-dir=', 'd', "temporary directory for creating the distribution"), - ('tag-svn-revision', None, - "Add subversion revision ID to version number"), - ('tag-date', None, "Add date stamp (e.g. 20050528) to version number"), - ('tag-build=', None, "Specify explicit tag to add to version number"), ('plat-name=', 'p', "platform name to embed in generated filenames " "(default: %s)" % get_platform()), @@ -61,48 +57,47 @@ ('skip-build', None, "skip rebuilding everything (for testing/debugging)"), ] + boolean_options = [ 'keep-temp', 'skip-build', 'relative','tag-date','tag-svn-revision' ] + + + + + + + + + + + + + + + + + + def initialize_options (self): - self.egg_name = None - self.egg_version = None - self.egg_base = None - self.egg_info = None self.bdist_dir = None self.plat_name = None self.keep_temp = 0 self.dist_dir = None self.skip_build = 0 - self.tag_build = None - self.tag_svn_revision = 0 - self.tag_date = 0 self.egg_output = None - def finalize_options (self): - self.egg_name = safe_name(self.distribution.get_name()) - self.egg_version = self.tagged_version() - try: - list( - parse_requirements('%s==%s' % (self.egg_name,self.egg_version)) - ) - except ValueError: - raise DistutilsOptionError( - "Invalid distribution name or version syntax: %s-%s" % - (self.egg_name,self.egg_version) - ) - if self.egg_base is None: - dirs = self.distribution.package_dir - self.egg_base = (dirs or {}).get('','.') - self.ensure_dirname('egg_base') - self.egg_info = os.path.join( - self.egg_base, self.egg_name+'.egg-info' - ) + + def finalize_options(self): + ei_cmd = self.get_finalized_command("egg_info") + self.egg_info = ei_cmd.egg_info + if self.bdist_dir is None: bdist_base = self.get_finalized_command('bdist').bdist_base self.bdist_dir = os.path.join(bdist_base, 'egg') + if self.plat_name is None: self.plat_name = get_platform() @@ -112,7 +107,7 @@ # Compute filename of the output egg basename = Distribution( - None, None, self.egg_name, self.egg_version, + None, None, ei_cmd.egg_name, ei_cmd.egg_version, get_python_version(), self.distribution.has_ext_modules() and self.plat_name ).egg_name() @@ -121,6 +116,11 @@ + + + + + def do_install_data(self): # Hack for packages that install data to install's --install-lib self.get_finalized_command('install').install_lib = self.bdist_dir @@ -146,26 +146,29 @@ finally: self.distribution.data_files = old + def get_outputs(self): return [self.egg_output] - def write_requirements(self): - dist = self.distribution - if not getattr(dist,'install_requires',None) and \ - not getattr(dist,'extras_require',None): return - requires = os.path.join(self.egg_info,"requires.txt") - log.info("writing %s", requires) - if not self.dry_run: - f = open(requires, 'wt') - f.write('\n'.join(yield_lines(dist.install_requires))) - for extra,reqs in dist.extras_require.items(): - f.write('\n\n[%s]\n%s' % (extra, '\n'.join(yield_lines(reqs)))) - f.close() - + + def call_command(self,cmdname,**kw): + """Invoke reinitialized command `cmdname` with keyword args""" + for dirname in INSTALL_DIRECTORY_ATTRS: + kw.setdefault(dirname,self.bdist_dir) + kw.setdefault('skip_build',self.skip_build) + kw.setdefault('dry_run', self.dry_run) + cmd = self.reinitialize_command(cmdname, **kw) + self.run_command(cmdname) + return cmd + + def run(self): + # Generate metadata first + self.run_command("egg_info") + # We run install_lib before install_data, because some data hacks # pull their data path from the install_lib command. - + log.info("installing library code to %s" % self.bdist_dir) cmd = self.call_command('install_lib', warn_dir=0) @@ -193,24 +196,12 @@ archive_root = self.bdist_dir egg_info = os.path.join(archive_root,'EGG-INFO') self.mkpath(egg_info) - self.mkpath(self.egg_info) if self.distribution.scripts: script_dir = os.path.join(egg_info, 'scripts') log.info("installing scripts to %s" % script_dir) self.call_command('install_scripts', install_dir=script_dir) - self.write_requirements() - log.info("writing %s" % os.path.join(self.egg_info,'PKG-INFO')) - - if not self.dry_run: - metadata = self.distribution.metadata - metadata.version, oldver = self.egg_version, metadata.version - metadata.name, oldname = self.egg_name, metadata.name - try: - metadata.write_pkg_info(self.egg_info) - finally: - metadata.name, metadata.version = oldname, oldver native_libs = os.path.join(self.egg_info,"native_libs.txt") if ext_outputs: @@ -235,49 +226,17 @@ "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" "Use the install_requires/extras_require setup() args instead." ) + # Make the archive make_zipfile(self.egg_output, archive_root, verbose=self.verbose, dry_run=self.dry_run) if not self.keep_temp: remove_tree(self.bdist_dir, dry_run=self.dry_run) + # Add to 'Distribution.dist_files' so that the "upload" command works getattr(self.distribution,'dist_files',[]).append( ('bdist_egg',get_python_version(),self.egg_output)) - def tagged_version(self): - version = self.distribution.get_version() - if self.tag_build: - version+='-'+self.tag_build - - if self.tag_svn_revision and os.path.exists('.svn'): - version += '-%s' % self.get_svn_revision() - - if self.tag_date: - import time - version += time.strftime("-%Y%m%d") - - return safe_version(version) - - def get_svn_revision(self): - stdin, stdout = os.popen4("svn info"); stdin.close() - result = stdout.read(); stdout.close() - import re - match = re.search(r'Last Changed Rev: (\d+)', result) - if not match: - raise RuntimeError("svn info error: %s" % result.strip()) - return match.group(1) - - def call_command(self,cmdname,**kw): - """Invoke reinitialized command `cmdname` with keyword args""" - for dirname in INSTALL_DIRECTORY_ATTRS: - kw.setdefault(dirname,self.bdist_dir) - kw.setdefault('skip_build',self.skip_build) - kw.setdefault('dry_run', self.dry_run) - cmd = self.reinitialize_command(cmdname, **kw) - self.run_command(cmdname) - return cmd - - From pje at users.sourceforge.net Wed Jul 6 03:54:10 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 18:54:10 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command test.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21756/setuptools/command Modified Files: test.py Log Message: Enhanced the ``test`` command so that it doesn't install the package, but instead builds any C extensions in-place, updates the ``.egg-info`` metadata, adds the source directory to ``sys.path``, and runs the tests directly on the source. This avoids an "unmanaged" installation of the package to ``site-packages`` or elsewhere. (Also, fix a breaking test of older dependency support; this should probably be removed altogether, as long as nobody's using it.) Index: test.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/test.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- test.py 19 Mar 2004 20:53:14 -0000 1.1 +++ test.py 6 Jul 2005 01:54:07 -0000 1.2 @@ -1,4 +1,4 @@ -from distutils.cmd import Command +from setuptools import Command from distutils.errors import DistutilsOptionError import sys @@ -40,35 +40,35 @@ def run(self): + # Ensure metadata is up-to-date + self.run_command('egg_info') - # Install before testing - self.run_command('install') + # Build extensions in-place + self.reinitialize_command('build_ext', inplace=1) + self.run_command('build_ext') if self.test_suite: cmd = ' '.join(self.test_args) - if self.dry_run: self.announce('skipping "unittest %s" (dry run)' % cmd) else: self.announce('running "unittest %s"' % cmd) - import unittest - unittest.main(None, None, [unittest.__file__]+self.test_args) - - - - - - - - - - - - - - - + self.run_tests() + def run_tests(self): + import unittest, pkg_resources + old_path = sys.path[:] + ei_cmd = self.get_finalized_command("egg_info") + try: + # put the egg on sys.path, and require() it + sys.path.insert(0, ei_cmd.egg_base) + pkg_resources.require( + "%s==%s" % (ei_cmd.egg_name, ei_cmd.egg_version) + ) + unittest.main(None, None, [unittest.__file__]+self.test_args) + finally: + sys.path[:] = old_path + # XXX later this might need to save/restore the WorkingSet From pje at users.sourceforge.net Wed Jul 6 03:54:10 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 18:54:10 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.18, 1.19 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21756 Modified Files: EasyInstall.txt Log Message: Enhanced the ``test`` command so that it doesn't install the package, but instead builds any C extensions in-place, updates the ``.egg-info`` metadata, adds the source directory to ``sys.path``, and runs the tests directly on the source. This avoids an "unmanaged" installation of the package to ``site-packages`` or elsewhere. (Also, fix a breaking test of older dependency support; this should probably be removed altogether, as long as nobody's using it.) Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- EasyInstall.txt 6 Jul 2005 01:37:41 -0000 1.18 +++ EasyInstall.txt 6 Jul 2005 01:54:07 -0000 1.19 @@ -484,8 +484,14 @@ 0.5a5 * Added ``egg_info`` command to ``setuptools``-based packages. This command just creates or updates the "projectname.egg-info" directory, without - building an egg. It's used by the ``bdist_egg`` command now, and will be - used by the ``test`` and ``develop`` commands later on. + building an egg. It's used by the ``bdist_egg`` and ``test`` commands now, + and will be used by the ``develop`` command later on. + + * Enhanced the ``test`` command so that it doesn't install the package, but + instead builds any C extensions in-place, updates the ``.egg-info`` + metadata, adds the source directory to ``sys.path``, and runs the tests + directly on the source. This avoids an "unmanaged" installation of the + package to ``site-packages`` or elsewhere. 0.5a4 * Added ``--always-copy/-a`` option to always copy needed packages to the From pje at users.sourceforge.net Wed Jul 6 03:54:10 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 18:54:10 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/tests __init__.py, 1.6, 1.7 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21756/setuptools/tests Modified Files: __init__.py Log Message: Enhanced the ``test`` command so that it doesn't install the package, but instead builds any C extensions in-place, updates the ``.egg-info`` metadata, adds the source directory to ``sys.path``, and runs the tests directly on the source. This avoids an "unmanaged" installation of the package to ``site-packages`` or elsewhere. (Also, fix a breaking test of older dependency support; this should probably be removed altogether, as long as nobody's using it.) Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/__init__.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- __init__.py 2 Apr 2005 02:43:21 -0000 1.6 +++ __init__.py 6 Jul 2005 01:54:08 -0000 1.7 @@ -122,19 +122,19 @@ def testDependsCmd(self): - path1 = convert_path('foo/bar/baz') - path2 = convert_path('foo/bar/baz/spam') + path = convert_path('foo/bar/baz') dist = makeSetup( - extra_path='spam', - script_args=['install','--install-lib',path1] + script_args=['install','--install-lib',path] ) cmd = dist.get_command_obj('depends') cmd.ensure_finalized() self.assertEqual(cmd.temp, dist.get_command_obj('build').build_temp) - self.assertEqual(cmd.search_path, [path2,path1]+sys.path) + self.assertEqual(cmd.search_path, [path+os.path.sep,path]+sys.path) + + From pje at users.sourceforge.net Wed Jul 6 04:10:51 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 19:10:51 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools dist.py, 1.9, 1.10 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29898/setuptools Modified Files: dist.py Log Message: Made ``easy_install`` a standard ``setuptools`` command, moving it from the ``easy_install`` module to ``setuptools.command.easy_install``. Note that if you were importing or extending it, you must now change your imports accordingly. ``easy_install.py`` is still installed as a script, but not as a module. Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- dist.py 4 Jul 2005 18:45:41 -0000 1.9 +++ dist.py 6 Jul 2005 02:10:48 -0000 1.10 @@ -395,7 +395,7 @@ self.run_command(cmd) def install_eggs(self): - from easy_install import easy_install + from setuptools.command.easy_install import easy_install cmd = easy_install(self, args="x") cmd.ensure_finalized() # finalize before bdist_egg munges install cmd self.run_command('bdist_egg') From pje at users.sourceforge.net Wed Jul 6 04:10:50 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 19:10:50 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, NONE, 1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29898/setuptools/command Added Files: easy_install.py Log Message: Made ``easy_install`` a standard ``setuptools`` command, moving it from the ``easy_install`` module to ``setuptools.command.easy_install``. Note that if you were importing or extending it, you must now change your imports accordingly. ``easy_install.py`` is still installed as a script, but not as a module. --- NEW FILE: easy_install.py --- #!python """\ Easy Install ------------ A tool for doing automatic download/extract/build of distutils-based Python packages. For detailed documentation, see the accompanying EasyInstall.txt file, or visit the `EasyInstall home page`__. __ http://peak.telecommunity.com/DevCenter/EasyInstall """ import sys, os.path, zipimport, shutil, tempfile, zipfile from setuptools import Command from setuptools.sandbox import run_setup from distutils import log, dir_util from distutils.sysconfig import get_python_lib from distutils.errors import DistutilsArgError, DistutilsOptionError from setuptools.archive_util import unpack_archive from setuptools.package_index import PackageIndex, parse_bdist_wininst from setuptools.package_index import URL_SCHEME from setuptools.command import bdist_egg from pkg_resources import * __all__ = [ 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', 'main', 'get_exe_prefixes', ] def samefile(p1,p2): if hasattr(os.path,'samefile') and ( os.path.exists(p1) and os.path.exists(p2) ): return os.path.samefile(p1,p2) return ( os.path.normpath(os.path.normcase(p1)) == os.path.normpath(os.path.normcase(p2)) ) class easy_install(Command): """Manage a download/build/install process""" description = "Find/get/install Python packages" command_consumes_arguments = True user_options = [ ("zip-ok", "z", "install package as a zipfile"), ("multi-version", "m", "make apps have to require() a version"), ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"), ("install-dir=", "d", "install package to DIR"), ("script-dir=", "s", "install scripts to DIR"), ("exclude-scripts", "x", "Don't install scripts"), ("always-copy", "a", "Copy all needed packages to install dir"), ("index-url=", "i", "base URL of Python Package Index"), ("find-links=", "f", "additional URL(s) to search for packages"), ("build-directory=", "b", "download/extract/build in DIR; keep the results"), ('optimize=', 'O', "also compile with optimization: -O1 for \"python -O\", " "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), ('record=', None, "filename in which to record list of installed files"), ] boolean_options = [ 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy' ] create_index = PackageIndex def initialize_options(self): self.zip_ok = None self.install_dir = self.script_dir = self.exclude_scripts = None self.index_url = None self.find_links = None self.build_directory = None self.args = None self.optimize = self.record = None self.upgrade = self.always_copy = self.multi_version = None # Options not specifiable via command line self.package_index = None self.pth_file = None def finalize_options(self): # If a non-default installation directory was specified, default the # script directory to match it. if self.script_dir is None: self.script_dir = self.install_dir # Let install_dir get set by install_lib command, which in turn # gets its info from the install command, and takes into account # --prefix and --home and all that other crud. self.set_undefined_options('install_lib', ('install_dir','install_dir') ) # Likewise, set default script_dir from 'install_scripts.install_dir' self.set_undefined_options('install_scripts', ('install_dir', 'script_dir') ) # default --record from the install command self.set_undefined_options('install', ('record', 'record')) site_packages = get_python_lib() instdir = self.install_dir if instdir is None or samefile(site_packages,instdir): instdir = site_packages if self.pth_file is None: self.pth_file = PthDistributions( os.path.join(instdir,'easy-install.pth') ) self.install_dir = instdir elif self.multi_version is None: self.multi_version = True elif not self.multi_version: # explicit false set from Python code; raise an error raise DistutilsArgError( "Can't do single-version installs outside site-packages" ) self.index_url = self.index_url or "http://www.python.org/pypi" self.shadow_path = sys.path[:] for path_item in self.install_dir, self.script_dir: if path_item not in self.shadow_path: self.shadow_path.insert(0, self.install_dir) if self.package_index is None: self.package_index = self.create_index( self.index_url, search_path = self.shadow_path ) self.local_index = AvailableDistributions(self.shadow_path) if self.find_links is not None: if isinstance(self.find_links, basestring): self.find_links = self.find_links.split() else: self.find_links = [] self.set_undefined_options('install_lib', ('optimize','optimize')) if not isinstance(self.optimize,int): try: self.optimize = int(self.optimize) if not (0 <= self.optimize <= 2): raise ValueError except ValueError: raise DistutilsOptionError("--optimize must be 0, 1, or 2") if not self.args: raise DistutilsArgError( "No urls, filenames, or requirements specified (see --help)") elif len(self.args)>1 and self.build_directory is not None: raise DistutilsArgError( "Build directory can only be set when using one URL" ) self.outputs = [] def alloc_tmp(self): if self.build_directory is None: return tempfile.mkdtemp(prefix="easy_install-") tmpdir = os.path.realpath(self.build_directory) if not os.path.isdir(tmpdir): os.makedirs(tmpdir) return tmpdir def run(self): if self.verbose<>self.distribution.verbose: log.set_verbosity(self.verbose) try: for link in self.find_links: self.package_index.scan_url(link) for spec in self.args: self.easy_install(spec) if self.record: from distutils import file_util self.execute( file_util.write_file, (self.record, self.outputs), "writing list of installed files to '%s'" % self.record ) finally: log.set_verbosity(self.distribution.verbose) def add_output(self, path): if os.path.isdir(path): for base, dirs, files in os.walk(path): for filename in files: self.outputs.append(os.path.join(base,filename)) else: self.outputs.append(path) def easy_install(self, spec): tmpdir = self.alloc_tmp() download = None try: if not isinstance(spec,Requirement): if URL_SCHEME(spec): # It's a url, download it to tmpdir and process download = self.package_index.download(spec, tmpdir) return self.install_item(None, download, tmpdir, True) elif os.path.exists(spec): # Existing file or directory, just process it directly return self.install_item(None, spec, tmpdir, True) else: try: spec = Requirement.parse(spec) except ValueError: raise RuntimeError( "Not a URL, existing file, or requirement spec: %r" % (spec,) ) if isinstance(spec, Requirement): download = self.package_index.fetch(spec, tmpdir, self.upgrade) else: spec = None if download is None: raise RuntimeError( "Could not find distribution for %r" % spec ) return self.install_item(spec, download, tmpdir) finally: if self.build_directory is None: shutil.rmtree(tmpdir) def install_item(self, spec, download, tmpdir, install_needed=False): # Installation is also needed if file in tmpdir or is not an egg install_needed = install_needed or os.path.dirname(download) == tmpdir install_needed = install_needed or not download.endswith('.egg') log.info("Processing %s", os.path.basename(download)) if install_needed or self.always_copy: dists = self.install_eggs(download, self.zip_ok, tmpdir) for dist in dists: self.process_distribution(spec, dist) else: dists = [self.egg_distribution(download)] self.process_distribution(spec, dists[0], "Using") if spec is not None: for dist in dists: if dist in spec: return dist def process_distribution(self, requirement, dist, *info): self.update_pth(dist) self.package_index.add(dist) self.local_index.add(dist) self.install_egg_scripts(dist) log.warn(self.installation_report(dist, *info)) if requirement is None: requirement = Requirement.parse('%s==%s'%(dist.name,dist.version)) if dist in requirement: log.info("Processing dependencies for %s", requirement) try: self.local_index.resolve( [requirement], self.shadow_path, self.easy_install ) except DistributionNotFound, e: raise RuntimeError( "Could not find required distribution %s" % e.args ) except VersionConflict, e: raise RuntimeError( "Installed distribution %s conflicts with requirement %s" % e.args ) def install_egg_scripts(self, dist): metadata = dist.metadata if self.exclude_scripts or not metadata.metadata_isdir('scripts'): return from distutils.command.build_scripts import first_line_re for script_name in metadata.metadata_listdir('scripts'): target = os.path.join(self.script_dir, script_name) log.info("Installing %s script to %s", script_name,self.script_dir) script_text = metadata.get_metadata('scripts/'+script_name) script_text = script_text.replace('\r','\n') first, rest = script_text.split('\n',1) match = first_line_re.match(first) options = '' if match: options = match.group(1) or '' if options: options = ' '+options spec = '%s==%s' % (dist.name,dist.version) script_text = '\n'.join([ "#!%s%s" % (os.path.normpath(sys.executable),options), "# EASY-INSTALL-SCRIPT: %r,%r" % (spec, script_name), "import pkg_resources", "pkg_resources.run_main(%r, %r)" % (spec, script_name) ]) if not self.dry_run: f = open(target,"w") f.write(script_text) f.close() try: os.chmod(target,0755) except (AttributeError, os.error): pass def install_eggs(self, dist_filename, zip_ok, tmpdir): # .egg dirs or files are already built, so just return them if dist_filename.lower().endswith('.egg'): return [self.install_egg(dist_filename, True, tmpdir)] if dist_filename.lower().endswith('.exe'): return [self.install_exe(dist_filename, tmpdir)] # Anything else, try to extract and build if os.path.isfile(dist_filename): unpack_archive(dist_filename, tmpdir, self.unpack_progress) # Find the setup.py file from glob import glob setup_script = os.path.join(tmpdir, 'setup.py') if not os.path.exists(setup_script): setups = glob(os.path.join(tmpdir, '*', 'setup.py')) if not setups: raise RuntimeError( "Couldn't find a setup script in %s" % dist_filename ) if len(setups)>1: raise RuntimeError( "Multiple setup scripts in %s" % dist_filename ) setup_script = setups[0] self.build_egg(tmpdir, setup_script) dist_dir = os.path.join(os.path.dirname(setup_script),'dist') eggs = [] for egg in glob(os.path.join(dist_dir,'*.egg')): eggs.append(self.install_egg(egg, zip_ok, tmpdir)) if not eggs and not self.dry_run: log.warn("No eggs found in %s (setup script problem?)", dist_dir) return eggs def egg_distribution(self, egg_path): if os.path.isdir(egg_path): metadata = PathMetadata(egg_path,os.path.join(egg_path,'EGG-INFO')) else: metadata = EggMetadata(zipimport.zipimporter(egg_path)) return Distribution.from_filename(egg_path,metadata=metadata) def install_egg(self, egg_path, zip_ok, tmpdir): destination = os.path.join(self.install_dir,os.path.basename(egg_path)) destination = os.path.abspath(destination) if not self.dry_run: ensure_directory(destination) if not samefile(egg_path, destination): if os.path.isdir(destination): dir_util.remove_tree(destination, dry_run=self.dry_run) elif os.path.isfile(destination): self.execute(os.unlink,(destination,),"Removing "+destination) if os.path.isdir(egg_path): if egg_path.startswith(tmpdir): f,m = shutil.move, "Moving" else: f,m = shutil.copytree, "Copying" elif zip_ok: if egg_path.startswith(tmpdir): f,m = shutil.move, "Moving" else: f,m = shutil.copy2, "Copying" else: self.mkpath(destination) f,m = self.unpack_and_compile, "Extracting" self.execute(f, (egg_path, destination), (m+" %s to %s") % (os.path.basename(egg_path),os.path.dirname(destination))) self.add_output(destination) return self.egg_distribution(destination) def install_exe(self, dist_filename, tmpdir): # See if it's valid, get data cfg = extract_wininst_cfg(dist_filename) if cfg is None: raise RuntimeError( "%s is not a valid distutils Windows .exe" % dist_filename ) # Create a dummy distribution object until we build the real distro dist = Distribution(None, name=cfg.get('metadata','name'), version=cfg.get('metadata','version'), platform="win32" ) # Convert the .exe to an unpacked egg egg_path = dist.path = os.path.join(tmpdir, dist.egg_name()+'.egg') egg_tmp = egg_path+'.tmp' self.exe_to_egg(dist_filename, egg_tmp) # Write EGG-INFO/PKG-INFO pkg_inf = os.path.join(egg_tmp, 'EGG-INFO', 'PKG-INFO') f = open(pkg_inf,'w') f.write('Metadata-Version: 1.0\n') for k,v in cfg.items('metadata'): if k<>'target_version': f.write('%s: %s\n' % (k.replace('_','-').title(), v)) f.close() # Build .egg file from tmpdir bdist_egg.make_zipfile( egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run ) # install the .egg return self.install_egg(egg_path, self.zip_ok, tmpdir) def exe_to_egg(self, dist_filename, egg_tmp): """Extract a bdist_wininst to the directories an egg would use""" # Check for .pth file and set up prefix translations prefixes = get_exe_prefixes(dist_filename) to_compile = [] native_libs = [] def process(src,dst): for old,new in prefixes: if src.startswith(old): src = new+src[len(old):] dst = os.path.join(egg_tmp, *src.split('/')) dl = dst.lower() if dl.endswith('.pyd') or dl.endswith('.dll'): native_libs.append(src) elif dl.endswith('.py') and old!='SCRIPTS/': to_compile.append(dst) return dst if not src.endswith('.pth'): log.warn("WARNING: can't process %s", src) return None # extract, tracking .pyd/.dll->native_libs and .py -> to_compile unpack_archive(dist_filename, egg_tmp, process) for res in native_libs: if res.lower().endswith('.pyd'): # create stubs for .pyd's parts = res.split('/') resource, parts[-1] = parts[-1], parts[-1][:-1] pyfile = os.path.join(egg_tmp, *parts) to_compile.append(pyfile) bdist_egg.write_stub(resource, pyfile) self.byte_compile(to_compile) # compile .py's if native_libs: # write EGG-INFO/native_libs.txt nl_txt = os.path.join(egg_tmp, 'EGG-INFO', 'native_libs.txt') ensure_directory(nl_txt) open(nl_txt,'w').write('\n'.join(native_libs)+'\n') def installation_report(self, dist, what="Installed"): """Helpful installation message for display to package users""" msg = "\n%(what)s %(eggloc)s" if self.multi_version: msg += """ Because this distribution was installed --multi-version or --install-dir, before you can import modules from this package in an application, you will need to 'import pkg_resources' and then use a 'require()' call similar to one of these examples, in order to select the desired version: pkg_resources.require("%(name)s") # latest installed version pkg_resources.require("%(name)s==%(version)s") # this exact version pkg_resources.require("%(name)s>=%(version)s") # this version or higher """ if not samefile(get_python_lib(),self.install_dir): msg += """ Note also that the installation directory must be on sys.path at runtime for this to work. (e.g. by being the application's script directory, by being on PYTHONPATH, or by being added to sys.path by your code.) """ eggloc = dist.path name = dist.name version = dist.version return msg % locals() def build_egg(self, tmpdir, setup_script): sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) args = ['bdist_egg'] if self.verbose>2: v = 'v' * self.verbose - 1 args.insert(0,'-'+v) elif self.verbose<2: args.insert(0,'-q') if self.dry_run: args.insert(0,'-n') log.info("Running %s %s", setup_script[len(tmpdir)+1:], ' '.join(args)) try: try: run_setup(setup_script, args) except SystemExit, v: raise RuntimeError( "Setup script exited with %s" % (v.args[0],) ) finally: log.set_verbosity(self.verbose) # restore our log verbosity def update_pth(self,dist): if self.pth_file is None: return for d in self.pth_file.get(dist.key,()): # drop old entries if self.multi_version or d.path != dist.path: log.info("Removing %s from easy-install.pth file", d) self.pth_file.remove(d) if d.path in self.shadow_path: self.shadow_path.remove(d.path) if not self.multi_version: if dist.path in self.pth_file.paths: log.info( "%s is already the active version in easy-install.pth", dist ) else: log.info("Adding %s to easy-install.pth file", dist) self.pth_file.add(dist) # add new entry if dist.path not in self.shadow_path: self.shadow_path.append(dist.path) self.pth_file.save() if dist.name=='setuptools': # Ensure that setuptools itself never becomes unavailable! f = open(os.path.join(self.install_dir,'setuptools.pth'), 'w') f.write(dist.path+'\n') f.close() def unpack_progress(self, src, dst): # Progress filter for unpacking log.debug("Unpacking %s to %s", src, dst) return dst # only unpack-and-compile skips files for dry run def unpack_and_compile(self, egg_path, destination): to_compile = [] def pf(src,dst): if dst.endswith('.py'): to_compile.append(dst) self.unpack_progress(src,dst) return not self.dry_run and dst or None unpack_archive(egg_path, destination, pf) self.byte_compile(to_compile) def byte_compile(self, to_compile): from distutils.util import byte_compile try: # try to make the byte compile messages quieter log.set_verbosity(self.verbose - 1) byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) if self.optimize: byte_compile( to_compile, optimize=self.optimize, force=1, dry_run=self.dry_run ) finally: log.set_verbosity(self.verbose) # restore original verbosity def extract_wininst_cfg(dist_filename): """Extract configuration data from a bdist_wininst .exe Returns a ConfigParser.RawConfigParser, or None """ f = open(dist_filename,'rb') try: endrec = zipfile._EndRecData(f) if endrec is None: return None prepended = (endrec[9] - endrec[5]) - endrec[6] if prepended < 12: # no wininst data here return None f.seek(prepended-12) import struct, StringIO, ConfigParser tag, cfglen, bmlen = struct.unpack("0x1234567A: return None # not a valid tag f.seek(prepended-(12+cfglen+bmlen)) cfg = ConfigParser.RawConfigParser({'version':'','target_version':''}) try: cfg.readfp(StringIO.StringIO(f.read(cfglen))) except ConfigParser.Error: return None if not cfg.has_section('metadata') or not cfg.has_section('Setup'): return None return cfg finally: f.close() def get_exe_prefixes(exe_filename): """Get exe->egg path translations for a given .exe file""" prefixes = [ ('PURELIB/', ''), ('PLATLIB/', ''), ('SCRIPTS/', 'EGG-INFO/scripts/') ] z = zipfile.ZipFile(exe_filename) try: for info in z.infolist(): name = info.filename if not name.endswith('.pth'): continue parts = name.split('/') if len(parts)<>2: continue if parts[0] in ('PURELIB','PLATLIB'): pth = z.read(name).strip() prefixes[0] = ('PURELIB/%s/' % pth), '' prefixes[1] = ('PLATLIB/%s/' % pth), '' break finally: z.close() return prefixes class PthDistributions(AvailableDistributions): """A .pth file with Distribution paths in it""" dirty = False def __init__(self, filename): self.filename = filename; self._load() AvailableDistributions.__init__( self, list(yield_lines(self.paths)), None, None ) def _load(self): self.paths = [] if os.path.isfile(self.filename): self.paths = [line.rstrip() for line in open(self.filename,'rt')] while self.paths and not self.paths[-1].strip(): self.paths.pop() def save(self): """Write changed .pth file back to disk""" if self.dirty: data = '\n'.join(self.paths+['']) f = open(self.filename,'wt') f.write(data) f.close() self.dirty = False def add(self,dist): """Add `dist` to the distribution map""" if dist.path not in self.paths: self.paths.append(dist.path); self.dirty = True AvailableDistributions.add(self,dist) def remove(self,dist): """Remove `dist` from the distribution map""" while dist.path in self.paths: self.paths.remove(dist.path); self.dirty = True AvailableDistributions.remove(self,dist) def main(argv, **kw): from setuptools import setup try: setup(script_args = ['-q','easy_install', '-v']+argv, **kw) except RuntimeError, v: print >>sys.stderr,"error:",v sys.exit(1) From pje at users.sourceforge.net Wed Jul 6 04:10:51 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 19:10:51 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.19, 1.20 easy_install.py, 1.25, 1.26 ez_setup.py, 1.7, 1.8 setup.py, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29898 Modified Files: EasyInstall.txt easy_install.py ez_setup.py setup.py Log Message: Made ``easy_install`` a standard ``setuptools`` command, moving it from the ``easy_install`` module to ``setuptools.command.easy_install``. Note that if you were importing or extending it, you must now change your imports accordingly. ``easy_install.py`` is still installed as a script, but not as a module. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- EasyInstall.txt 6 Jul 2005 01:54:07 -0000 1.19 +++ EasyInstall.txt 6 Jul 2005 02:10:47 -0000 1.20 @@ -493,12 +493,18 @@ directly on the source. This avoids an "unmanaged" installation of the package to ``site-packages`` or elsewhere. + * Made ``easy_install`` a standard ``setuptools`` command, moving it from + the ``easy_install`` module to ``setuptools.command.easy_install``. Note + that if you were importing or extending it, you must now change your imports + accordingly. ``easy_install.py`` is still installed as a script, but not as + a module. + 0.5a4 * Added ``--always-copy/-a`` option to always copy needed packages to the installation directory, even if they're already present elsewhere on sys.path. (In previous versions, this was the default behavior, but now you must request it.) - + * Added ``--upgrade/-U`` option to force checking PyPI for latest available version(s) of all packages requested by name and version, even if a matching version is available locally. @@ -522,7 +528,7 @@ * Setup scripts using setuptools now always install using ``easy_install`` internally, for ease of uninstallation and upgrading. Note: you *must* remove any ``extra_path`` argument from your setup script, as it conflicts - with the proper functioning of the ``easy_install`` command. (Also, added + with the proper functioning of the ``easy_install`` command. (Also, added the ``--record`` option to ``easy_install`` for the benefit of tools that run ``setup.py install --record=filename`` on behalf of another packaging system.) @@ -535,7 +541,7 @@ 0.5a3 * Fixed not setting script permissions to allow execution. - + * Improved sandboxing so that setup scripts that want a temporary directory (e.g. pychecker) can still run in the sandbox. Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/easy_install.py,v retrieving revision 1.25 retrieving revision 1.26 diff -u -d -r1.25 -r1.26 --- easy_install.py 4 Jul 2005 18:45:02 -0000 1.25 +++ easy_install.py 6 Jul 2005 02:10:47 -0000 1.26 @@ -11,810 +11,9 @@ __ http://peak.telecommunity.com/DevCenter/EasyInstall """ -import sys, os.path, zipimport, shutil, tempfile, zipfile - -from setuptools import Command -from setuptools.sandbox import run_setup -from distutils import log, dir_util -from distutils.sysconfig import get_python_lib -from distutils.errors import DistutilsArgError, DistutilsOptionError -from setuptools.archive_util import unpack_archive -from setuptools.package_index import PackageIndex, parse_bdist_wininst -from setuptools.package_index import URL_SCHEME -from setuptools.command import bdist_egg -from pkg_resources import * - -__all__ = [ - 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', - 'main', 'get_exe_prefixes', -] - -def samefile(p1,p2): - if hasattr(os.path,'samefile') and ( - os.path.exists(p1) and os.path.exists(p2) - ): - return os.path.samefile(p1,p2) - return ( - os.path.normpath(os.path.normcase(p1)) == - os.path.normpath(os.path.normcase(p2)) - ) - -class easy_install(Command): - """Manage a download/build/install process""" - - description = "Find/get/install Python packages" - command_consumes_arguments = True - user_options = [ - ("zip-ok", "z", "install package as a zipfile"), - ("multi-version", "m", "make apps have to require() a version"), - ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"), - ("install-dir=", "d", "install package to DIR"), - ("script-dir=", "s", "install scripts to DIR"), - ("exclude-scripts", "x", "Don't install scripts"), - ("always-copy", "a", "Copy all needed packages to install dir"), - ("index-url=", "i", "base URL of Python Package Index"), - ("find-links=", "f", "additional URL(s) to search for packages"), - ("build-directory=", "b", - "download/extract/build in DIR; keep the results"), - ('optimize=', 'O', - "also compile with optimization: -O1 for \"python -O\", " - "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), - ('record=', None, - "filename in which to record list of installed files"), - ] - boolean_options = [ - 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy' - ] - create_index = PackageIndex - - def initialize_options(self): - self.zip_ok = None - self.install_dir = self.script_dir = self.exclude_scripts = None - self.index_url = None - self.find_links = None - self.build_directory = None - self.args = None - self.optimize = self.record = None - self.upgrade = self.always_copy = self.multi_version = None - # Options not specifiable via command line - self.package_index = None - self.pth_file = None - - def finalize_options(self): - # If a non-default installation directory was specified, default the - # script directory to match it. - if self.script_dir is None: - self.script_dir = self.install_dir - - # Let install_dir get set by install_lib command, which in turn - # gets its info from the install command, and takes into account - # --prefix and --home and all that other crud. - self.set_undefined_options('install_lib', - ('install_dir','install_dir') - ) - # Likewise, set default script_dir from 'install_scripts.install_dir' - self.set_undefined_options('install_scripts', - ('install_dir', 'script_dir') - ) - # default --record from the install command - self.set_undefined_options('install', ('record', 'record')) - - site_packages = get_python_lib() - instdir = self.install_dir - - if instdir is None or samefile(site_packages,instdir): - instdir = site_packages - if self.pth_file is None: - self.pth_file = PthDistributions( - os.path.join(instdir,'easy-install.pth') - ) - self.install_dir = instdir - - elif self.multi_version is None: - self.multi_version = True - - elif not self.multi_version: - # explicit false set from Python code; raise an error - raise DistutilsArgError( - "Can't do single-version installs outside site-packages" - ) - - self.index_url = self.index_url or "http://www.python.org/pypi" - - self.shadow_path = sys.path[:] - - for path_item in self.install_dir, self.script_dir: - if path_item not in self.shadow_path: - self.shadow_path.insert(0, self.install_dir) - - if self.package_index is None: - self.package_index = self.create_index( - self.index_url, search_path = self.shadow_path - ) - - self.local_index = AvailableDistributions(self.shadow_path) - - if self.find_links is not None: - if isinstance(self.find_links, basestring): - self.find_links = self.find_links.split() - else: - self.find_links = [] - - self.set_undefined_options('install_lib', ('optimize','optimize')) - - if not isinstance(self.optimize,int): - try: - self.optimize = int(self.optimize) - if not (0 <= self.optimize <= 2): raise ValueError - except ValueError: - raise DistutilsOptionError("--optimize must be 0, 1, or 2") - - if not self.args: - raise DistutilsArgError( - "No urls, filenames, or requirements specified (see --help)") - - elif len(self.args)>1 and self.build_directory is not None: - raise DistutilsArgError( - "Build directory can only be set when using one URL" - ) - - self.outputs = [] - - - - def alloc_tmp(self): - if self.build_directory is None: - return tempfile.mkdtemp(prefix="easy_install-") - tmpdir = os.path.realpath(self.build_directory) - if not os.path.isdir(tmpdir): - os.makedirs(tmpdir) - return tmpdir - - - def run(self): - if self.verbose<>self.distribution.verbose: - log.set_verbosity(self.verbose) - try: - for link in self.find_links: - self.package_index.scan_url(link) - for spec in self.args: - self.easy_install(spec) - if self.record: - from distutils import file_util - self.execute( - file_util.write_file, (self.record, self.outputs), - "writing list of installed files to '%s'" % - self.record - ) - finally: - log.set_verbosity(self.distribution.verbose) - - - def add_output(self, path): - if os.path.isdir(path): - for base, dirs, files in os.walk(path): - for filename in files: - self.outputs.append(os.path.join(base,filename)) - else: - self.outputs.append(path) - - - - - - - def easy_install(self, spec): - tmpdir = self.alloc_tmp() - download = None - - try: - if not isinstance(spec,Requirement): - if URL_SCHEME(spec): - # It's a url, download it to tmpdir and process - download = self.package_index.download(spec, tmpdir) - return self.install_item(None, download, tmpdir, True) - - elif os.path.exists(spec): - # Existing file or directory, just process it directly - return self.install_item(None, spec, tmpdir, True) - else: - try: - spec = Requirement.parse(spec) - except ValueError: - raise RuntimeError( - "Not a URL, existing file, or requirement spec: %r" - % (spec,) - ) - - if isinstance(spec, Requirement): - download = self.package_index.fetch(spec, tmpdir, self.upgrade) - else: - spec = None - - if download is None: - raise RuntimeError( - "Could not find distribution for %r" % spec - ) - - return self.install_item(spec, download, tmpdir) - - finally: - if self.build_directory is None: - shutil.rmtree(tmpdir) - - - - def install_item(self, spec, download, tmpdir, install_needed=False): - # Installation is also needed if file in tmpdir or is not an egg - install_needed = install_needed or os.path.dirname(download) == tmpdir - install_needed = install_needed or not download.endswith('.egg') - log.info("Processing %s", os.path.basename(download)) - if install_needed or self.always_copy: - dists = self.install_eggs(download, self.zip_ok, tmpdir) - for dist in dists: - self.process_distribution(spec, dist) - else: - dists = [self.egg_distribution(download)] - self.process_distribution(spec, dists[0], "Using") - if spec is not None: - for dist in dists: - if dist in spec: - return dist - - def process_distribution(self, requirement, dist, *info): - self.update_pth(dist) - self.package_index.add(dist) - self.local_index.add(dist) - self.install_egg_scripts(dist) - log.warn(self.installation_report(dist, *info)) - if requirement is None: - requirement = Requirement.parse('%s==%s'%(dist.name,dist.version)) - if dist in requirement: - log.info("Processing dependencies for %s", requirement) - try: - self.local_index.resolve( - [requirement], self.shadow_path, self.easy_install - ) - except DistributionNotFound, e: - raise RuntimeError( - "Could not find required distribution %s" % e.args - ) - except VersionConflict, e: - raise RuntimeError( - "Installed distribution %s conflicts with requirement %s" - % e.args - ) - - def install_egg_scripts(self, dist): - metadata = dist.metadata - if self.exclude_scripts or not metadata.metadata_isdir('scripts'): - return - - from distutils.command.build_scripts import first_line_re - - for script_name in metadata.metadata_listdir('scripts'): - target = os.path.join(self.script_dir, script_name) - - log.info("Installing %s script to %s", script_name,self.script_dir) - - script_text = metadata.get_metadata('scripts/'+script_name) - script_text = script_text.replace('\r','\n') - first, rest = script_text.split('\n',1) - - match = first_line_re.match(first) - options = '' - if match: - options = match.group(1) or '' - if options: - options = ' '+options - - spec = '%s==%s' % (dist.name,dist.version) - - script_text = '\n'.join([ - "#!%s%s" % (os.path.normpath(sys.executable),options), - "# EASY-INSTALL-SCRIPT: %r,%r" % (spec, script_name), - "import pkg_resources", - "pkg_resources.run_main(%r, %r)" % (spec, script_name) - ]) - if not self.dry_run: - f = open(target,"w") - f.write(script_text) - f.close() - try: - os.chmod(target,0755) - except (AttributeError, os.error): - pass - - - def install_eggs(self, dist_filename, zip_ok, tmpdir): - # .egg dirs or files are already built, so just return them - if dist_filename.lower().endswith('.egg'): - return [self.install_egg(dist_filename, True, tmpdir)] - - if dist_filename.lower().endswith('.exe'): - return [self.install_exe(dist_filename, tmpdir)] - - # Anything else, try to extract and build - if os.path.isfile(dist_filename): - unpack_archive(dist_filename, tmpdir, self.unpack_progress) - - # Find the setup.py file - from glob import glob - setup_script = os.path.join(tmpdir, 'setup.py') - if not os.path.exists(setup_script): - setups = glob(os.path.join(tmpdir, '*', 'setup.py')) - if not setups: - raise RuntimeError( - "Couldn't find a setup script in %s" % dist_filename - ) - if len(setups)>1: - raise RuntimeError( - "Multiple setup scripts in %s" % dist_filename - ) - setup_script = setups[0] - - self.build_egg(tmpdir, setup_script) - dist_dir = os.path.join(os.path.dirname(setup_script),'dist') - - eggs = [] - for egg in glob(os.path.join(dist_dir,'*.egg')): - eggs.append(self.install_egg(egg, zip_ok, tmpdir)) - - if not eggs and not self.dry_run: - log.warn("No eggs found in %s (setup script problem?)", dist_dir) - - return eggs - - - - def egg_distribution(self, egg_path): - if os.path.isdir(egg_path): - metadata = PathMetadata(egg_path,os.path.join(egg_path,'EGG-INFO')) - else: - metadata = EggMetadata(zipimport.zipimporter(egg_path)) - return Distribution.from_filename(egg_path,metadata=metadata) - - def install_egg(self, egg_path, zip_ok, tmpdir): - destination = os.path.join(self.install_dir,os.path.basename(egg_path)) - destination = os.path.abspath(destination) - - if not self.dry_run: - ensure_directory(destination) - - if not samefile(egg_path, destination): - if os.path.isdir(destination): - dir_util.remove_tree(destination, dry_run=self.dry_run) - elif os.path.isfile(destination): - self.execute(os.unlink,(destination,),"Removing "+destination) - - if os.path.isdir(egg_path): - if egg_path.startswith(tmpdir): - f,m = shutil.move, "Moving" - else: - f,m = shutil.copytree, "Copying" - elif zip_ok: - if egg_path.startswith(tmpdir): - f,m = shutil.move, "Moving" - else: - f,m = shutil.copy2, "Copying" - else: - self.mkpath(destination) - f,m = self.unpack_and_compile, "Extracting" - - self.execute(f, (egg_path, destination), - (m+" %s to %s") % - (os.path.basename(egg_path),os.path.dirname(destination))) - - self.add_output(destination) - return self.egg_distribution(destination) - - def install_exe(self, dist_filename, tmpdir): - # See if it's valid, get data - cfg = extract_wininst_cfg(dist_filename) - if cfg is None: - raise RuntimeError( - "%s is not a valid distutils Windows .exe" % dist_filename - ) - - # Create a dummy distribution object until we build the real distro - dist = Distribution(None, - name=cfg.get('metadata','name'), - version=cfg.get('metadata','version'), - platform="win32" - ) - - # Convert the .exe to an unpacked egg - egg_path = dist.path = os.path.join(tmpdir, dist.egg_name()+'.egg') - egg_tmp = egg_path+'.tmp' - self.exe_to_egg(dist_filename, egg_tmp) - - # Write EGG-INFO/PKG-INFO - pkg_inf = os.path.join(egg_tmp, 'EGG-INFO', 'PKG-INFO') - f = open(pkg_inf,'w') - f.write('Metadata-Version: 1.0\n') - for k,v in cfg.items('metadata'): - if k<>'target_version': - f.write('%s: %s\n' % (k.replace('_','-').title(), v)) - f.close() - - # Build .egg file from tmpdir - bdist_egg.make_zipfile( - egg_path, egg_tmp, - verbose=self.verbose, dry_run=self.dry_run - ) - - # install the .egg - return self.install_egg(egg_path, self.zip_ok, tmpdir) - - - - - def exe_to_egg(self, dist_filename, egg_tmp): - """Extract a bdist_wininst to the directories an egg would use""" - - # Check for .pth file and set up prefix translations - prefixes = get_exe_prefixes(dist_filename) - to_compile = [] - native_libs = [] - - def process(src,dst): - for old,new in prefixes: - if src.startswith(old): - src = new+src[len(old):] - dst = os.path.join(egg_tmp, *src.split('/')) - dl = dst.lower() - if dl.endswith('.pyd') or dl.endswith('.dll'): - native_libs.append(src) - elif dl.endswith('.py') and old!='SCRIPTS/': - to_compile.append(dst) - return dst - if not src.endswith('.pth'): - log.warn("WARNING: can't process %s", src) - return None - - # extract, tracking .pyd/.dll->native_libs and .py -> to_compile - unpack_archive(dist_filename, egg_tmp, process) - - for res in native_libs: - if res.lower().endswith('.pyd'): # create stubs for .pyd's - parts = res.split('/') - resource, parts[-1] = parts[-1], parts[-1][:-1] - pyfile = os.path.join(egg_tmp, *parts) - to_compile.append(pyfile) - bdist_egg.write_stub(resource, pyfile) - - self.byte_compile(to_compile) # compile .py's - - if native_libs: # write EGG-INFO/native_libs.txt - nl_txt = os.path.join(egg_tmp, 'EGG-INFO', 'native_libs.txt') - ensure_directory(nl_txt) - open(nl_txt,'w').write('\n'.join(native_libs)+'\n') - - def installation_report(self, dist, what="Installed"): - """Helpful installation message for display to package users""" - - msg = "\n%(what)s %(eggloc)s" - if self.multi_version: - msg += """ - -Because this distribution was installed --multi-version or --install-dir, -before you can import modules from this package in an application, you -will need to 'import pkg_resources' and then use a 'require()' call -similar to one of these examples, in order to select the desired version: - - pkg_resources.require("%(name)s") # latest installed version - pkg_resources.require("%(name)s==%(version)s") # this exact version - pkg_resources.require("%(name)s>=%(version)s") # this version or higher -""" - if not samefile(get_python_lib(),self.install_dir): - msg += """ - -Note also that the installation directory must be on sys.path at runtime for -this to work. (e.g. by being the application's script directory, by being on -PYTHONPATH, or by being added to sys.path by your code.) -""" - eggloc = dist.path - name = dist.name - version = dist.version - return msg % locals() - - - - - - - - - - - - - - - def build_egg(self, tmpdir, setup_script): - sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) - - args = ['bdist_egg'] - if self.verbose>2: - v = 'v' * self.verbose - 1 - args.insert(0,'-'+v) - elif self.verbose<2: - args.insert(0,'-q') - if self.dry_run: - args.insert(0,'-n') - - log.info("Running %s %s", setup_script[len(tmpdir)+1:], ' '.join(args)) - try: - try: - run_setup(setup_script, args) - except SystemExit, v: - raise RuntimeError( - "Setup script exited with %s" % (v.args[0],) - ) - finally: - log.set_verbosity(self.verbose) # restore our log verbosity - - - - - - - - - - - - - - - - - - - - def update_pth(self,dist): - if self.pth_file is None: - return - - for d in self.pth_file.get(dist.key,()): # drop old entries - if self.multi_version or d.path != dist.path: - log.info("Removing %s from easy-install.pth file", d) - self.pth_file.remove(d) - if d.path in self.shadow_path: - self.shadow_path.remove(d.path) - - if not self.multi_version: - if dist.path in self.pth_file.paths: - log.info( - "%s is already the active version in easy-install.pth", - dist - ) - else: - log.info("Adding %s to easy-install.pth file", dist) - self.pth_file.add(dist) # add new entry - if dist.path not in self.shadow_path: - self.shadow_path.append(dist.path) - - self.pth_file.save() - - if dist.name=='setuptools': - # Ensure that setuptools itself never becomes unavailable! - f = open(os.path.join(self.install_dir,'setuptools.pth'), 'w') - f.write(dist.path+'\n') - f.close() - - - def unpack_progress(self, src, dst): - # Progress filter for unpacking - log.debug("Unpacking %s to %s", src, dst) - return dst # only unpack-and-compile skips files for dry run - - - - - - def unpack_and_compile(self, egg_path, destination): - to_compile = [] - - def pf(src,dst): - if dst.endswith('.py'): - to_compile.append(dst) - self.unpack_progress(src,dst) - return not self.dry_run and dst or None - - unpack_archive(egg_path, destination, pf) - self.byte_compile(to_compile) - - - def byte_compile(self, to_compile): - from distutils.util import byte_compile - try: - # try to make the byte compile messages quieter - log.set_verbosity(self.verbose - 1) - - byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) - if self.optimize: - byte_compile( - to_compile, optimize=self.optimize, force=1, - dry_run=self.dry_run - ) - finally: - log.set_verbosity(self.verbose) # restore original verbosity - - - - - - - - - - - - - - -def extract_wininst_cfg(dist_filename): - """Extract configuration data from a bdist_wininst .exe - - Returns a ConfigParser.RawConfigParser, or None - """ - f = open(dist_filename,'rb') - try: - endrec = zipfile._EndRecData(f) - if endrec is None: - return None - - prepended = (endrec[9] - endrec[5]) - endrec[6] - if prepended < 12: # no wininst data here - return None - f.seek(prepended-12) - - import struct, StringIO, ConfigParser - tag, cfglen, bmlen = struct.unpack("0x1234567A: - return None # not a valid tag - - f.seek(prepended-(12+cfglen+bmlen)) - cfg = ConfigParser.RawConfigParser({'version':'','target_version':''}) - try: - cfg.readfp(StringIO.StringIO(f.read(cfglen))) - except ConfigParser.Error: - return None - if not cfg.has_section('metadata') or not cfg.has_section('Setup'): - return None - return cfg - - finally: - f.close() - - - - - - - - -def get_exe_prefixes(exe_filename): - """Get exe->egg path translations for a given .exe file""" - - prefixes = [ - ('PURELIB/', ''), - ('PLATLIB/', ''), - ('SCRIPTS/', 'EGG-INFO/scripts/') - ] - z = zipfile.ZipFile(exe_filename) - try: - for info in z.infolist(): - name = info.filename - if not name.endswith('.pth'): - continue - parts = name.split('/') - if len(parts)<>2: - continue - if parts[0] in ('PURELIB','PLATLIB'): - pth = z.read(name).strip() - prefixes[0] = ('PURELIB/%s/' % pth), '' - prefixes[1] = ('PLATLIB/%s/' % pth), '' - break - finally: - z.close() - - return prefixes - - - - - - - - - - - - - - - -class PthDistributions(AvailableDistributions): - """A .pth file with Distribution paths in it""" - - dirty = False - - def __init__(self, filename): - self.filename = filename; self._load() - AvailableDistributions.__init__( - self, list(yield_lines(self.paths)), None, None - ) - - def _load(self): - self.paths = [] - if os.path.isfile(self.filename): - self.paths = [line.rstrip() for line in open(self.filename,'rt')] - while self.paths and not self.paths[-1].strip(): self.paths.pop() - - def save(self): - """Write changed .pth file back to disk""" - if self.dirty: - data = '\n'.join(self.paths+['']) - f = open(self.filename,'wt') - f.write(data) - f.close() - self.dirty = False - - def add(self,dist): - """Add `dist` to the distribution map""" - if dist.path not in self.paths: - self.paths.append(dist.path); self.dirty = True - AvailableDistributions.add(self,dist) - - def remove(self,dist): - """Remove `dist` from the distribution map""" - while dist.path in self.paths: - self.paths.remove(dist.path); self.dirty = True - AvailableDistributions.remove(self,dist) - - - - -def main(argv, cmds={'easy_install':easy_install}): - from setuptools import setup - try: - setup(cmdclass = cmds, script_args = ['-q','easy_install', '-v']+argv) - except RuntimeError, v: - print >>sys.stderr,"error:",v - sys.exit(1) - +import sys +from setuptools.command.easy_install import * if __name__ == '__main__': main(sys.argv[1:]) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- ez_setup.py 27 Jun 2005 00:31:02 -0000 1.7 +++ ez_setup.py 6 Jul 2005 02:10:48 -0000 1.8 @@ -132,7 +132,7 @@ try: egg = download_setuptools(version, to_dir=tmpdir) sys.path.insert(0,egg) - from easy_install import main + from setuptools.command.easy_install import main main(list(argv)+[egg]) finally: shutil.rmtree(tmpdir) @@ -146,12 +146,12 @@ try: pkg_resources.require(req) except pkg_resources.VersionConflict: - from easy_install import main + from setuptools.command.easy_install import main main(list(argv)+[req]) sys.exit(0) # try to force an exit else: if argv: - from easy_install import main + from setuptools.command.easy_install import main main(argv) else: print "Setuptools successfully installed or upgraded." Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- setup.py 27 Jun 2005 00:31:02 -0000 1.17 +++ setup.py 6 Jul 2005 02:10:48 -0000 1.18 @@ -40,7 +40,7 @@ packages = find_packages(), - py_modules = ['pkg_resources', 'easy_install'], + py_modules = ['pkg_resources'], scripts = ['easy_install.py'], classifiers = [f.strip() for f in """ From pje at users.sourceforge.net Wed Jul 6 05:46:18 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 20:46:18 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.20, 1.21 pkg_resources.py, 1.35, 1.36 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13765 Modified Files: EasyInstall.txt pkg_resources.py Log Message: Added ``develop`` command to ``setuptools``-based packages. This command installs an ``.egg-link`` pointing to the package's source directory, and script wrappers that ``execfile()`` the source versions of the package's scripts. This lets you put your development checkout(s) on sys.path without having to actually install them. (To uninstall the link, use use ``setup.py develop --uninstall``.) Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- EasyInstall.txt 6 Jul 2005 02:10:47 -0000 1.20 +++ EasyInstall.txt 6 Jul 2005 03:46:15 -0000 1.21 @@ -482,10 +482,17 @@ time out or be missing a file. 0.5a5 + * Added ``develop`` command to ``setuptools``-based packages. This command + installs an ``.egg-link`` pointing to the package's source directory, and + script wrappers that ``execfile()`` the source versions of the package's + scripts. This lets you put your development checkout(s) on sys.path without + having to actually install them. (To uninstall the link, use + use ``setup.py develop --uninstall``.) + * Added ``egg_info`` command to ``setuptools``-based packages. This command just creates or updates the "projectname.egg-info" directory, without - building an egg. It's used by the ``bdist_egg`` and ``test`` commands now, - and will be used by the ``develop`` command later on. + building an egg. (It's used by the ``bdist_egg``, ``test``, and ``develop`` + commands.) * Enhanced the ``test`` command so that it doesn't install the package, but instead builds any C extensions in-place, updates the ``.egg-info`` Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.35 retrieving revision 1.36 diff -u -d -r1.35 -r1.36 --- pkg_resources.py 27 Jun 2005 00:31:02 -0000 1.35 +++ pkg_resources.py 6 Jul 2005 03:46:16 -0000 1.36 @@ -984,10 +984,8 @@ def find_nothing(importer,path_item): return () - register_finder(object,find_nothing) - def find_on_path(importer,path_item): """Yield distributions accessible on a sys.path directory""" if not os.path.exists(path_item): @@ -1004,25 +1002,27 @@ # scan for .egg and .egg-info in directory for entry in os.listdir(path_item): fullpath = os.path.join(path_item, entry) - if entry.lower().endswith('.egg'): + lower = entry.lower() + if lower.endswith('.egg'): for dist in find_on_path(importer,fullpath): yield dist - elif entry.lower().endswith('.egg-info'): + elif lower.endswith('.egg-info'): if os.path.isdir(fullpath): # development egg metadata = PathMetadata(path_item, fullpath) dist_name = os.path.splitext(entry)[0] yield Distribution(path_item,metadata,name=dist_name) - elif path_item.lower().endswith('.egg'): - # packed egg + elif lower.endswith('.egg-link'): + for line in file(fullpath): + if not line.strip(): continue + for item in find_distributions(line.rstrip()): + yield item + elif path_item.lower().endswith('.egg'): # packed egg metadata = EggMetadata(zipimport.zipimporter(path_item)) yield Distribution.from_filename(path_item, metadata=metadata) register_finder(ImpWrapper,find_on_path) - - - _namespace_handlers = {} _namespace_packages = {} From pje at users.sourceforge.net Wed Jul 6 05:46:19 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 20:46:19 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command develop.py, NONE, 1.1 __init__.py, 1.3, 1.4 easy_install.py, 1.1, 1.2 test.py, 1.2, 1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13765/setuptools/command Modified Files: __init__.py easy_install.py test.py Added Files: develop.py Log Message: Added ``develop`` command to ``setuptools``-based packages. This command installs an ``.egg-link`` pointing to the package's source directory, and script wrappers that ``execfile()`` the source versions of the package's scripts. This lets you put your development checkout(s) on sys.path without having to actually install them. (To uninstall the link, use use ``setup.py develop --uninstall``.) --- NEW FILE: develop.py --- from setuptools.command.easy_install import easy_install from distutils.util import convert_path from pkg_resources import Distribution, PathMetadata from distutils import log import sys, os class develop(easy_install): """Set up package for development""" description = "install package in 'development mode'" user_options = [ ("install-dir=", "d", "link package from DIR"), ("script-dir=", "s", "create script wrappers in DIR"), ("multi-version", "m", "make apps have to require() a version"), ("exclude-scripts", "x", "Don't install scripts"), ("always-copy", "a", "Copy all needed dependencies to install dir"), ("uninstall", "u", "Uninstall this source package"), ] boolean_options = [ 'multi-version', 'exclude-scripts', 'always-copy', 'uninstall' ] command_consumes_arguments = False # override base def initialize_options(self): self.uninstall = None easy_install.initialize_options(self) def finalize_options(self): ei = self.get_finalized_command("egg_info") self.args = [ei.egg_name] easy_install.finalize_options(self) self.egg_link = os.path.join(self.install_dir, ei.egg_name+'.egg-link') self.egg_base = ei.egg_base self.egg_path = os.path.abspath(ei.egg_base) # Make a distribution for the package's source self.dist = Distribution( self.egg_path, PathMetadata(self.egg_path, os.path.abspath(ei.egg_info)), name = ei.egg_name ) def run(self): if self.uninstall: self.multi_version = True self.uninstall_link() else: self.install_for_development() def install_for_development(self): # Ensure metadata is up-to-date self.run_command('egg_info') ei = self.get_finalized_command("egg_info") # Build extensions in-place self.reinitialize_command('build_ext', inplace=1) self.run_command('build_ext') # create an .egg-link in the installation dir, pointing to our egg log.info("Creating %s (link to %s)", self.egg_link, self.egg_base) if not self.dry_run: f = open(self.egg_link,"w") f.write(self.egg_path) f.close() # postprocess the installed distro, fixing up .pth, installing scripts, # and handling requirements self.process_distribution(None, self.dist) def uninstall_link(self): if os.path.exists(self.egg_link): log.info("Removing %s (link to %s)", self.egg_link, self.egg_base) contents = [line.rstrip() for line in file(self.egg_link)] if contents != [self.egg_path]: log.warn("Link points to %s: uninstall aborted", contents) return if not self.dry_run: os.unlink(self.egg_link) self.update_pth(self.dist) # remove any .pth link to us if self.distribution.scripts: log.warn("Note: you must uninstall or replace scripts manually!") def install_egg_scripts(self, dist): if dist is not self.dist: # Installing a dependency, so fall back to normal behavior return easy_install.install_egg_scripts(self,dist) # create wrapper scripts in the script dir, pointing to dist.scripts for script_name in self.distribution.scripts or []: script_path = os.path.abspath(convert_path(script_name)) script_name = os.path.basename(script_path) f = open(script_path,'rU') script_text = f.read() f.close() self.install_script(dist, script_name, script_text, script_path) Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/__init__.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- __init__.py 21 Mar 2005 19:50:46 -0000 1.3 +++ __init__.py 6 Jul 2005 03:46:16 -0000 1.4 @@ -1,6 +1,6 @@ import distutils.command -__all__ = ['test', 'depends', 'bdist_egg'] +__all__ = ['test', 'develop', 'bdist_egg'] # Make our commands available as though they were part of the distutils Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- easy_install.py 6 Jul 2005 02:10:48 -0000 1.1 +++ easy_install.py 6 Jul 2005 03:46:16 -0000 1.2 @@ -126,7 +126,7 @@ for path_item in self.install_dir, self.script_dir: if path_item not in self.shadow_path: self.shadow_path.insert(0, self.install_dir) - + if self.package_index is None: self.package_index = self.create_index( self.index_url, search_path = self.shadow_path @@ -207,12 +207,12 @@ tmpdir = self.alloc_tmp() download = None - try: + try: if not isinstance(spec,Requirement): if URL_SCHEME(spec): # It's a url, download it to tmpdir and process download = self.package_index.download(spec, tmpdir) - return self.install_item(None, download, tmpdir, True) + return self.install_item(None, download, tmpdir, True) elif os.path.exists(spec): # Existing file or directory, just process it directly @@ -290,40 +290,81 @@ if self.exclude_scripts or not metadata.metadata_isdir('scripts'): return - from distutils.command.build_scripts import first_line_re - for script_name in metadata.metadata_listdir('scripts'): - target = os.path.join(self.script_dir, script_name) + self.install_script( + dist, script_name, + metadata.get_metadata('scripts/'+script_name).replace('\r','\n') + ) + + + + + + + + + + + + + + + + + + + + + + + - log.info("Installing %s script to %s", script_name,self.script_dir) - script_text = metadata.get_metadata('scripts/'+script_name) - script_text = script_text.replace('\r','\n') - first, rest = script_text.split('\n',1) - match = first_line_re.match(first) - options = '' - if match: - options = match.group(1) or '' - if options: - options = ' '+options - spec = '%s==%s' % (dist.name,dist.version) - script_text = '\n'.join([ - "#!%s%s" % (os.path.normpath(sys.executable),options), - "# EASY-INSTALL-SCRIPT: %r,%r" % (spec, script_name), - "import pkg_resources", - "pkg_resources.run_main(%r, %r)" % (spec, script_name) - ]) - if not self.dry_run: - f = open(target,"w") - f.write(script_text) - f.close() - try: - os.chmod(target,0755) - except (AttributeError, os.error): - pass + + + + def install_script(self, dist, script_name, script_text, dev_path=None): + log.info("Installing %s script to %s", script_name,self.script_dir) + target = os.path.join(self.script_dir, script_name) + first, rest = script_text.split('\n',1) + from distutils.command.build_scripts import first_line_re + match = first_line_re.match(first) + options = '' + if match: + options = match.group(1) or '' + if options: + options = ' '+options + spec = '%s==%s' % (dist.name,dist.version) + executable = os.path.normpath(sys.executable) + + if dev_path: + script_text = ( + "#!%(executable)s%(options)s\n" + "# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r\n" + "from pkg_resources import require; require(%(spec)r)\n" + "del require\n" + "__file__ = %(dev_path)r\n" + "execfile(__file__)\n" + ) % locals() + else: + script_text = ( + "#!%(executable)s%(options)s\n" + "# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r\n" + "import pkg_resources\n" + "pkg_resources.run_main(%(spec)r, %(script_name)r)\n" + ) % locals() + + if not self.dry_run: + f = open(target,"w") + f.write(script_text) + f.close() + try: + os.chmod(target,0755) + except (AttributeError, os.error): + pass def install_eggs(self, dist_filename, zip_ok, tmpdir): @@ -373,7 +414,7 @@ else: metadata = EggMetadata(zipimport.zipimporter(egg_path)) return Distribution.from_filename(egg_path,metadata=metadata) - + def install_egg(self, egg_path, zip_ok, tmpdir): destination = os.path.join(self.install_dir,os.path.basename(egg_path)) destination = os.path.abspath(destination) @@ -443,7 +484,7 @@ verbose=self.verbose, dry_run=self.dry_run ) - # install the .egg + # install the .egg return self.install_egg(egg_path, self.zip_ok, tmpdir) @@ -474,7 +515,7 @@ # extract, tracking .pyd/.dll->native_libs and .py -> to_compile unpack_archive(dist_filename, egg_tmp, process) - + for res in native_libs: if res.lower().endswith('.pyd'): # create stubs for .pyd's parts = res.split('/') @@ -482,9 +523,9 @@ pyfile = os.path.join(egg_tmp, *parts) to_compile.append(pyfile) bdist_egg.write_stub(resource, pyfile) - + self.byte_compile(to_compile) # compile .py's - + if native_libs: # write EGG-INFO/native_libs.txt nl_txt = os.path.join(egg_tmp, 'EGG-INFO', 'native_libs.txt') ensure_directory(nl_txt) @@ -599,6 +640,7 @@ if dist.name=='setuptools': # Ensure that setuptools itself never becomes unavailable! + # XXX should this check for latest version? f = open(os.path.join(self.install_dir,'setuptools.pth'), 'w') f.write(dist.path+'\n') f.close() @@ -612,7 +654,6 @@ - def unpack_and_compile(self, egg_path, destination): to_compile = [] @@ -632,7 +673,7 @@ # try to make the byte compile messages quieter log.set_verbosity(self.verbose - 1) - byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) + byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) if self.optimize: byte_compile( to_compile, optimize=self.optimize, force=1, @@ -667,7 +708,7 @@ prepended = (endrec[9] - endrec[5]) - endrec[6] if prepended < 12: # no wininst data here - return None + return None f.seek(prepended-12) import struct, StringIO, ConfigParser @@ -683,7 +724,7 @@ return None if not cfg.has_section('metadata') or not cfg.has_section('Setup'): return None - return cfg + return cfg finally: f.close() Index: test.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/test.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- test.py 6 Jul 2005 01:54:07 -0000 1.2 +++ test.py 6 Jul 2005 03:46:16 -0000 1.3 @@ -4,9 +4,9 @@ class test(Command): - """Command to run unit tests after installation""" + """Command to run unit tests after in-place build""" - description = "run unit tests after installation" + description = "run unit tests after in-place build" user_options = [ ('test-module=','m', "Run 'test_suite' in specified module"), From pje at users.sourceforge.net Wed Jul 6 05:47:07 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 20:47:07 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.10, 1.11 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14165/setuptools Modified Files: __init__.py Log Message: Bump version to 0.5a5. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- __init__.py 27 Jun 2005 00:31:02 -0000 1.10 +++ __init__.py 6 Jul 2005 03:47:04 -0000 1.11 @@ -8,7 +8,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a4' +__version__ = '0.5a5' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', From pje at users.sourceforge.net Wed Jul 6 05:47:07 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 05 Jul 2005 20:47:07 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.21, 1.22 ez_setup.py, 1.8, 1.9 setup.py, 1.18, 1.19 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14165 Modified Files: EasyInstall.txt ez_setup.py setup.py Log Message: Bump version to 0.5a5. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- EasyInstall.txt 6 Jul 2005 03:46:15 -0000 1.21 +++ EasyInstall.txt 6 Jul 2005 03:47:04 -0000 1.22 @@ -23,13 +23,13 @@ ------------------------- Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py `_, and run it; this will download and install the `Python 2.3 egg`_ or `Python 2.4 egg`_ for you. -.. _Python 2.3 egg: http://peak.telecommunity.com/dist/setuptools-0.5a4-py2.3.egg -.. _Python 2.4 egg: http://peak.telecommunity.com/dist/setuptools-0.5a4-py2.4.egg +.. _Python 2.3 egg: http://peak.telecommunity.com/dist/setuptools-0.5a5-py2.3.egg +.. _Python 2.4 egg: http://peak.telecommunity.com/dist/setuptools-0.5a5-py2.4.egg You may receive a message telling you about an obsolete version of setuptools being present; if so, you must be sure to delete it entirely, along @@ -66,7 +66,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a4" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a5" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- ez_setup.py 6 Jul 2005 02:10:48 -0000 1.8 +++ ez_setup.py 6 Jul 2005 03:47:04 -0000 1.9 @@ -14,7 +14,7 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a4" +DEFAULT_VERSION = "0.5a5" DEFAULT_URL = "http://peak.telecommunity.com/dist/" import sys, os Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- setup.py 6 Jul 2005 02:10:48 -0000 1.18 +++ setup.py 6 Jul 2005 03:47:04 -0000 1.19 @@ -1,7 +1,7 @@ #!/usr/bin/env python """Distutils setup file, used to install or test 'setuptools'""" -VERSION = "0.5a4" +VERSION = "0.5a5" from setuptools import setup, find_packages, Require setup( From loewis at users.sourceforge.net Wed Jul 6 21:34:14 2005 From: loewis at users.sourceforge.net (loewis@users.sourceforge.net) Date: Wed, 06 Jul 2005 12:34:14 -0700 Subject: [Python-checkins] python/dist/src/PCbuild readme.txt,1.58,1.59 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26083 Modified Files: readme.txt Log Message: Link to #1233049 for building against openssl 0.9.8. Index: readme.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/readme.txt,v retrieving revision 1.58 retrieving revision 1.59 diff -u -d -r1.58 -r1.59 --- readme.txt 31 Aug 2004 16:22:09 -0000 1.58 +++ readme.txt 6 Jul 2005 19:34:10 -0000 1.59 @@ -260,6 +260,7 @@ not openssl-engine-0.9.7d.tar.gz + (see #1233049 for using 0.9.8). Unpack into the "dist" directory, retaining the folder name from the archive - for example, the latest stable OpenSSL will install as dist/openssl-0.9.7d From pje at users.sourceforge.net Thu Jul 7 03:51:49 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 18:51:49 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.22, 1.23 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7746 Modified Files: EasyInstall.txt Log Message: Add a note about interaction between exemaker and easy_install Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- EasyInstall.txt 6 Jul 2005 03:47:04 -0000 1.22 +++ EasyInstall.txt 7 Jul 2005 01:51:46 -0000 1.23 @@ -481,6 +481,16 @@ * There's no automatic retry for borked Sourceforge mirrors, which can easily time out or be missing a file. + * Wrapping ``easy_install.py`` with the Exemaker utility may cause failures + when building packages that want to compile themselves with optimization + enabled. This is because Exemaker sets ``sys.executable`` to point to the + ``easy_install`` wrapper, instead of to the Python executable, and the + ``distutils.util.byte_compile()`` function expects to be able to invoke + ``sys.executable`` to run a short Python script. Unfortunately, this can't + be directly fixed by EasyInstall; it has to be fixed in the distutils or + in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any + rate don't expect it to work with all packages. + 0.5a5 * Added ``develop`` command to ``setuptools``-based packages. This command installs an ``.egg-link`` pointing to the package's source directory, and From pje at users.sourceforge.net Thu Jul 7 03:52:23 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 18:52:23 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools ez_setup.py, 1.9, 1.10 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8100 Modified Files: ez_setup.py Log Message: Backward-compatibility fix, so ez_setup can upgrade older versions of setuptools. Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- ez_setup.py 6 Jul 2005 03:47:04 -0000 1.9 +++ ez_setup.py 7 Jul 2005 01:52:21 -0000 1.10 @@ -66,7 +66,7 @@ egg = download_setuptools(version, download_base, to_dir) sys.path.insert(0, egg) import setuptools; setuptools.bootstrap_install_from = egg - + import pkg_resources try: pkg_resources.require("setuptools>="+version) @@ -102,7 +102,7 @@ src = urllib2.urlopen(url) # Read/write all in one block, so we don't create a corrupt file # if the download is interrupted. - data = src.read() + data = src.read() dst = open(saveto,"wb") dst.write(data) finally: @@ -146,7 +146,10 @@ try: pkg_resources.require(req) except pkg_resources.VersionConflict: - from setuptools.command.easy_install import main + try: + from setuptools.command.easy_install import main + except ImportError: + from easy_install import main main(list(argv)+[req]) sys.exit(0) # try to force an exit else: @@ -159,6 +162,3 @@ if __name__=='__main__': main(sys.argv[1:]) - - - From pje at users.sourceforge.net Thu Jul 7 03:54:00 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 18:54:00 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.36, 1.37 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8889 Modified Files: pkg_resources.py Log Message: Fix for .py scripts that might be imported (e.g. the "py" library's hideous '_findpy.py' hack.) Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.36 retrieving revision 1.37 diff -u -d -r1.36 -r1.37 --- pkg_resources.py 6 Jul 2005 03:46:16 -0000 1.36 +++ pkg_resources.py 7 Jul 2005 01:53:57 -0000 1.37 @@ -22,7 +22,7 @@ 'InvalidOption', 'Distribution', 'Requirement', 'yield_lines', 'get_importer', 'find_distributions', 'find_on_path', 'register_finder', 'split_sections', 'declare_namespace', 'register_namespace_handler', - 'safe_name', 'safe_version', 'run_main', 'BINARY_DIST', + 'safe_name', 'safe_version', 'run_main', 'BINARY_DIST', 'run_script', ] import sys, os, zipimport, time, re, imp @@ -102,15 +102,15 @@ # XXX all the tricky cases go here return False -def run_main(dist_spec, script_name): +def run_script(dist_spec, script_name): """Locate distribution `dist_spec` and run its `script_name` script""" - import __main__ - __main__.__dict__.clear() - __main__.__dict__.update({'__name__':'__main__'}) - require(dist_spec)[0].metadata.run_script(script_name, __main__.__dict__) - - + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + require(dist_spec)[0].metadata.run_script(script_name, ns) +run_main = run_script # backward compatibility From pje at users.sourceforge.net Thu Jul 7 03:58:01 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 18:58:01 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command develop.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11447/setuptools/command Modified Files: develop.py Log Message: Don't modify .pth files when in --dry-run/-n mode. Index: develop.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/develop.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- develop.py 6 Jul 2005 03:46:16 -0000 1.1 +++ develop.py 7 Jul 2005 01:57:59 -0000 1.2 @@ -4,41 +4,6 @@ from distutils import log import sys, os - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class develop(easy_install): """Set up package for development""" @@ -59,10 +24,21 @@ command_consumes_arguments = False # override base + def run(self): + if self.uninstall: + self.multi_version = True + self.uninstall_link() + else: + self.install_for_development() + def initialize_options(self): self.uninstall = None easy_install.initialize_options(self) + + + + def finalize_options(self): ei = self.get_finalized_command("egg_info") self.args = [ei.egg_name] @@ -78,15 +54,6 @@ name = ei.egg_name ) - - - def run(self): - if self.uninstall: - self.multi_version = True - self.uninstall_link() - else: - self.install_for_development() - def install_for_development(self): # Ensure metadata is up-to-date self.run_command('egg_info') @@ -108,6 +75,11 @@ # and handling requirements self.process_distribution(None, self.dist) + + + + + def uninstall_link(self): if os.path.exists(self.egg_link): log.info("Removing %s (link to %s)", self.egg_link, self.egg_base) @@ -117,10 +89,12 @@ return if not self.dry_run: os.unlink(self.egg_link) - self.update_pth(self.dist) # remove any .pth link to us + if not self.dry_run: + self.update_pth(self.dist) # remove any .pth link to us if self.distribution.scripts: log.warn("Note: you must uninstall or replace scripts manually!") + def install_egg_scripts(self, dist): if dist is not self.dist: # Installing a dependency, so fall back to normal behavior @@ -147,18 +121,3 @@ - - - - - - - - - - - - - - - From pje at users.sourceforge.net Thu Jul 7 04:01:58 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 19:01:58 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command egg_info.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14083/setuptools/command Modified Files: egg_info.py Log Message: Slightly changed the format of the generated version when you use ``--tag-build`` on the "egg_info" command, so that you can make tagged revisions compare *lower* than the version specified in setup.py (e.g. by using ``--tag-build=dev``). Index: egg_info.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/egg_info.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- egg_info.py 6 Jul 2005 01:37:41 -0000 1.1 +++ egg_info.py 7 Jul 2005 02:01:54 -0000 1.2 @@ -124,7 +124,7 @@ def tagged_version(self): version = self.distribution.get_version() if self.tag_build: - version+='-'+self.tag_build + version+=self.tag_build if self.tag_svn_revision and os.path.exists('.svn'): version += '-%s' % self.get_svn_revision() From pje at users.sourceforge.net Thu Jul 7 04:03:27 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 19:03:27 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools dist.py, 1.10, 1.11 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14617/setuptools Modified Files: dist.py Log Message: Beefed up the "sdist" command so that if you don't have a MANIFEST.in, it will include all files under revision control (CVS or Subversion) in the current directory, and it will regenerate the list every time you create a source distribution, not just when you tell it to. This should make the default "do what you mean" more often than the distutils' default behavior did, while still retaining the old behavior in the presence of MANIFEST.in. Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- dist.py 6 Jul 2005 02:10:48 -0000 1.10 +++ dist.py 7 Jul 2005 02:03:24 -0000 1.11 @@ -5,6 +5,7 @@ from setuptools.depends import Require from setuptools.command.build_ext import build_ext from setuptools.command.install import install +from setuptools.command.sdist import sdist from setuptools.command.install_lib import install_lib from distutils.errors import DistutilsOptionError, DistutilsPlatformError from distutils.errors import DistutilsSetupError @@ -79,7 +80,6 @@ distribution for the included and excluded features. """ - def __init__ (self, attrs=None): have_package_data = hasattr(self, "package_data") if not have_package_data: @@ -98,7 +98,7 @@ self.cmdclass.setdefault('build_ext',build_ext) self.cmdclass.setdefault('install',install) self.cmdclass.setdefault('install_lib',install_lib) - + self.cmdclass.setdefault('sdist',sdist) From pje at users.sourceforge.net Thu Jul 7 04:03:27 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 19:03:27 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command sdist.py, NONE, 1.1 easy_install.py, 1.2, 1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14617/setuptools/command Modified Files: easy_install.py Added Files: sdist.py Log Message: Beefed up the "sdist" command so that if you don't have a MANIFEST.in, it will include all files under revision control (CVS or Subversion) in the current directory, and it will regenerate the list every time you create a source distribution, not just when you tell it to. This should make the default "do what you mean" more often than the distutils' default behavior did, while still retaining the old behavior in the presence of MANIFEST.in. --- NEW FILE: sdist.py --- from distutils.command.sdist import sdist as _sdist from distutils.util import convert_path import os,re entities = [ ("<","<"), (">", ">"), (""", '"'), ("'", "'"), ("&", "&") ] def unescape(data): for old,new in entities: data = data.replace(old,new) return data patterns = [ (convert_path('CVS/Entries'), re.compile(r"^\w?/([^/]+)/", re.M), None), (convert_path('.svn/entries'), re.compile(r'name="([^"]+)"'), unescape), ] def joinpath(prefix,suffix): if not prefix: return suffix return os.path.join(prefix,suffix) def walk_revctrl(dirname='', memo=None): """Find all files under revision control""" if memo is None: memo = {} if dirname in memo: # Don't rescan a scanned directory return for path, pattern, postproc in patterns: path = joinpath(dirname,path) if os.path.isfile(path): f = open(path,'rU') data = f.read() f.close() for match in pattern.finditer(data): path = match.group(1) if postproc: path = postproc(path) path = joinpath(dirname,path) if os.path.isfile(path): yield path elif os.path.isdir(path): for item in walk_revctrl(path, memo): yield item class sdist(_sdist): """Smart sdist that finds anything supported by revision control""" def finalize_options(self): _sdist.finalize_options(self) if not os.path.isfile(self.template): self.force_manifest = 1 # always regen if no template def add_defaults(self): _sdist.add_defaults(self) self.filelist.extend(walk_revctrl()) Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- easy_install.py 6 Jul 2005 03:46:16 -0000 1.2 +++ easy_install.py 7 Jul 2005 02:03:25 -0000 1.3 @@ -354,7 +354,7 @@ "#!%(executable)s%(options)s\n" "# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r\n" "import pkg_resources\n" - "pkg_resources.run_main(%(spec)r, %(script_name)r)\n" + "pkg_resources.run_script(%(spec)r, %(script_name)r)\n" ) % locals() if not self.dry_run: From pje at users.sourceforge.net Thu Jul 7 04:06:02 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 19:06:02 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.23, 1.24 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15947 Modified Files: EasyInstall.txt Log Message: Update revision history. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- EasyInstall.txt 7 Jul 2005 01:51:46 -0000 1.23 +++ EasyInstall.txt 7 Jul 2005 02:05:56 -0000 1.24 @@ -491,6 +491,22 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. +0.5a6 + * Beefed up the "sdist" command so that if you don't have a MANIFEST.in, it + will include all files under revision control (CVS or Subversion) in the + current directory, and it will regenerate the list every time you create a + source distribution, not just when you tell it to. This should make the + default "do what you mean" more often than the distutils' default behavior + did, while still retaining the old behavior in the presence of MANIFEST.in. + + * Fixed the "develop" command always updating .pth files, even if you + specified ``-n`` or ``--dry-run``. + + * Slightly changed the format of the generated version when you use + ``--tag-build`` on the "egg_info" command, so that you can make tagged + revisions compare *lower* than the version specified in setup.py (e.g. by + using ``--tag-build=dev``). + 0.5a5 * Added ``develop`` command to ``setuptools``-based packages. This command installs an ``.egg-link`` pointing to the package's source directory, and From pje at users.sourceforge.net Thu Jul 7 04:10:17 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 19:10:17 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.11, 1.12 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18057/setuptools Modified Files: __init__.py Log Message: Bump release version Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- __init__.py 6 Jul 2005 03:47:04 -0000 1.11 +++ __init__.py 7 Jul 2005 02:10:14 -0000 1.12 @@ -8,7 +8,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a5' +__version__ = '0.5a6' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', From pje at users.sourceforge.net Thu Jul 7 04:10:27 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 06 Jul 2005 19:10:27 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.24, 1.25 ez_setup.py, 1.10, 1.11 setup.py, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18057 Modified Files: EasyInstall.txt ez_setup.py setup.py Log Message: Bump release version Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- EasyInstall.txt 7 Jul 2005 02:05:56 -0000 1.24 +++ EasyInstall.txt 7 Jul 2005 02:10:14 -0000 1.25 @@ -23,13 +23,13 @@ ------------------------- Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py `_, and run it; this will download and install the `Python 2.3 egg`_ or `Python 2.4 egg`_ for you. -.. _Python 2.3 egg: http://peak.telecommunity.com/dist/setuptools-0.5a5-py2.3.egg -.. _Python 2.4 egg: http://peak.telecommunity.com/dist/setuptools-0.5a5-py2.4.egg +.. _Python 2.3 egg: http://peak.telecommunity.com/dist/setuptools-0.5a6-py2.3.egg +.. _Python 2.4 egg: http://peak.telecommunity.com/dist/setuptools-0.5a6-py2.4.egg You may receive a message telling you about an obsolete version of setuptools being present; if so, you must be sure to delete it entirely, along @@ -66,7 +66,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a5" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a6" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- ez_setup.py 7 Jul 2005 01:52:21 -0000 1.10 +++ ez_setup.py 7 Jul 2005 02:10:14 -0000 1.11 @@ -14,7 +14,7 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a5" +DEFAULT_VERSION = "0.5a6" DEFAULT_URL = "http://peak.telecommunity.com/dist/" import sys, os Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- setup.py 6 Jul 2005 03:47:04 -0000 1.19 +++ setup.py 7 Jul 2005 02:10:14 -0000 1.20 @@ -1,7 +1,7 @@ #!/usr/bin/env python """Distutils setup file, used to install or test 'setuptools'""" -VERSION = "0.5a5" +VERSION = "0.5a6" from setuptools import setup, find_packages, Require setup( From pje at users.sourceforge.net Thu Jul 7 17:36:24 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 08:36:24 -0700 Subject: [Python-checkins] python/dist/src/Lib/distutils/command upload.py, 1.8, 1.9 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/distutils/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2945 Modified Files: upload.py Log Message: Fix "upload" command garbling and truncating files on Windows. If it's a binary file, use 'rb'! Index: upload.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/distutils/command/upload.py,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- upload.py 28 Mar 2005 01:08:03 -0000 1.8 +++ upload.py 7 Jul 2005 15:36:21 -0000 1.9 @@ -71,7 +71,7 @@ dry_run=self.dry_run) # Fill in the data - content = open(filename).read() + content = open(filename,'rb').read() data = { ':action':'file_upload', 'protcol_version':'1', From pje at users.sourceforge.net Thu Jul 7 18:28:45 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 09:28:45 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.25, 1.26 ez_setup.py, 1.11, 1.12 setup.py, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv755 Modified Files: EasyInstall.txt ez_setup.py setup.py Log Message: Add upload support to setuptools, and make default downloads of setuptools come from PyPI/python.org rather than from telecommunity.com. Bump to version 0.5a7. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.25 retrieving revision 1.26 diff -u -d -r1.25 -r1.26 --- EasyInstall.txt 7 Jul 2005 02:10:14 -0000 1.25 +++ EasyInstall.txt 7 Jul 2005 16:28:43 -0000 1.26 @@ -23,13 +23,10 @@ ------------------------- Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py `_, and run it; this will -download and install the `Python 2.3 egg`_ or `Python 2.4 egg`_ for you. - -.. _Python 2.3 egg: http://peak.telecommunity.com/dist/setuptools-0.5a6-py2.3.egg -.. _Python 2.4 egg: http://peak.telecommunity.com/dist/setuptools-0.5a6-py2.4.egg +download and install the appropriate egg for you. You may receive a message telling you about an obsolete version of setuptools being present; if so, you must be sure to delete it entirely, along @@ -66,7 +63,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a6" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a7" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: @@ -491,6 +488,11 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. +0.5a7 + * Added "upload" support for egg and source distributions, including a bug + fix for "upload" and a temporary workaround for lack of .egg support in + PyPI. + 0.5a6 * Beefed up the "sdist" command so that if you don't have a MANIFEST.in, it will include all files under revision control (CVS or Subversion) in the Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- ez_setup.py 7 Jul 2005 02:10:14 -0000 1.11 +++ ez_setup.py 7 Jul 2005 16:28:43 -0000 1.12 @@ -14,8 +14,8 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a6" -DEFAULT_URL = "http://peak.telecommunity.com/dist/" +DEFAULT_VERSION = "0.5a7" +DEFAULT_URL = "http://www.python.org/packages/source/s/setuptools/" import sys, os @@ -91,7 +91,7 @@ """ import urllib2, shutil egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) - url = download_base + egg_name + url = download_base + egg_name + '.zip' # XXX saveto = os.path.join(to_dir, egg_name) src = dst = None Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- setup.py 7 Jul 2005 02:10:14 -0000 1.20 +++ setup.py 7 Jul 2005 16:28:43 -0000 1.21 @@ -1,7 +1,7 @@ #!/usr/bin/env python """Distutils setup file, used to install or test 'setuptools'""" -VERSION = "0.5a6" +VERSION = "0.5a7" from setuptools import setup, find_packages, Require setup( @@ -26,8 +26,7 @@ "close. See the home page and download page for details and docs.", keywords = "CPAN PyPI distutils eggs package management", - url = "http://peak.telecommunity.com/DevCenter/PythonEggs", - download_url = "http://peak.telecommunity.com/DevCenter/EasyInstall", + url = "http://peak.telecommunity.com/DevCenter/EasyInstall", test_suite = 'setuptools.tests.test_suite', requires = [ @@ -39,6 +38,7 @@ + packages = find_packages(), py_modules = ['pkg_resources'], scripts = ['easy_install.py'], From pje at users.sourceforge.net Thu Jul 7 18:28:45 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 09:28:45 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.12, 1.13 package_index.py, 1.8, 1.9 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv755/setuptools Modified Files: __init__.py package_index.py Log Message: Add upload support to setuptools, and make default downloads of setuptools come from PyPI/python.org rather than from telecommunity.com. Bump to version 0.5a7. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- __init__.py 7 Jul 2005 02:10:14 -0000 1.12 +++ __init__.py 7 Jul 2005 16:28:43 -0000 1.13 @@ -8,7 +8,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a6' +__version__ = '0.5a7' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', Index: package_index.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/package_index.py,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- package_index.py 27 Jun 2005 00:31:03 -0000 1.8 +++ package_index.py 7 Jul 2005 16:28:43 -0000 1.9 @@ -44,7 +44,9 @@ path = urlparse.urlparse(url)[2] base = urllib2.unquote(path.split('/')[-1]) - + if base.endswith('.egg.zip'): + base = base[:-4] # strip the .zip + if base.endswith('.egg'): dist = Distribution.from_filename(base, metadata) dist.path = url @@ -58,10 +60,10 @@ ) # Try source distro extensions (.zip, .tgz, etc.) - # + # for ext in EXTENSIONS: if base.endswith(ext): - base = base[:-len(ext)] + base = base[:-len(ext)] return interpret_distro_name(url, base, metadata) return [] # no extension matched @@ -78,8 +80,6 @@ - - def interpret_distro_name(url, base, metadata, py_version=None, distro_type=SOURCE_DIST, platform=None ): @@ -139,7 +139,7 @@ dists = list(distros_for_url(url)) if dists: self.debug("Found link: %s", url) - if dists or not retrieve or url in self.fetched_urls: + if dists or not retrieve or url in self.fetched_urls: for dist in dists: self.add(dist) # don't need the actual page @@ -164,7 +164,7 @@ def process_index(self,url,page): """Process the contents of a PyPI page""" - + def scan(link): # Process a URL to see if it's for a package page if link.startswith(self.index_url): @@ -226,7 +226,7 @@ for dist in self.get(requirement.key, ()): if dist in requirement: return dist - self.debug("%s does not match %s", requirement, dist) + self.debug("%s does not match %s", requirement, dist) return super(PackageIndex, self).obtain(requirement,installer) @@ -388,6 +388,9 @@ else: name = "__downloaded__" # default if URL has no path contents + if name.endswith('.egg.zip'): + name = name[:-4] # strip the extra .zip before download + filename = os.path.join(tmpdir,name) # Download the file @@ -405,9 +408,6 @@ self.process_url(url, True) - - - def _download_html(self, url, headers, filename, tmpdir): # Check for a sourceforge URL sf_url = url.startswith('http://prdownloads.') @@ -445,7 +445,7 @@ def info(self, msg, *args): log.info(msg, *args) - + def warn(self, msg, *args): log.warn(msg, *args) From pje at users.sourceforge.net Thu Jul 7 18:28:46 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 09:28:46 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command upload.py, NONE, 1.1 sdist.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv755/setuptools/command Modified Files: sdist.py Added Files: upload.py Log Message: Add upload support to setuptools, and make default downloads of setuptools come from PyPI/python.org rather than from telecommunity.com. Bump to version 0.5a7. --- NEW FILE: upload.py --- """distutils.command.upload Implements the Distutils 'upload' subcommand (upload package to PyPI).""" from distutils.errors import * from distutils.core import Command from distutils.spawn import spawn from distutils import log from md5 import md5 import os import socket import platform import ConfigParser import httplib import base64 import urlparse import cStringIO as StringIO class upload(Command): description = "upload binary package to PyPI" DEFAULT_REPOSITORY = 'http://www.python.org/pypi' user_options = [ ('repository=', 'r', "url of repository [default: %s]" % DEFAULT_REPOSITORY), ('show-response', None, 'display full response text from server'), ('sign', 's', 'sign files to upload using gpg'), ] boolean_options = ['show-response', 'sign'] def initialize_options(self): self.username = '' self.password = '' self.repository = '' self.show_response = 0 self.sign = False def finalize_options(self): if os.environ.has_key('HOME'): rc = os.path.join(os.environ['HOME'], '.pypirc') if os.path.exists(rc): self.announce('Using PyPI login from %s' % rc) config = ConfigParser.ConfigParser({ 'username':'', 'password':'', 'repository':''}) config.read(rc) if not self.repository: self.repository = config.get('server-login', 'repository') if not self.username: self.username = config.get('server-login', 'username') if not self.password: self.password = config.get('server-login', 'password') if not self.repository: self.repository = self.DEFAULT_REPOSITORY def run(self): if not self.distribution.dist_files: raise DistutilsOptionError("No dist file created in earlier command") for command, pyversion, filename in self.distribution.dist_files: self.upload_file(command, pyversion, filename) def upload_file(self, command, pyversion, filename): # Sign if requested if self.sign: spawn(("gpg", "--detach-sign", "-a", filename), dry_run=self.dry_run) # Fill in the data content = open(filename,'rb').read() basename = os.path.basename(filename) if basename.endswith('.egg'): basename += '.zip' if command=='bdist_egg': command='sdist' data = { ':action':'file_upload', 'protcol_version':'1', 'name':self.distribution.get_name(), 'version':self.distribution.get_version(), 'content':(basename,content), 'filetype':command, 'pyversion':pyversion, 'md5_digest':md5(content).hexdigest(), } comment = '' if command == 'bdist_rpm': dist, version, id = platform.dist() if dist: comment = 'built for %s %s' % (dist, version) elif command == 'bdist_dumb': comment = 'built for %s' % platform.platform(terse=1) data['comment'] = comment if self.sign: data['gpg_signature'] = (os.path.basename(filename) + ".asc", open(filename+".asc").read()) # set up the authentication auth = "Basic " + base64.encodestring(self.username + ":" + self.password).strip() # Build up the MIME payload for the POST data boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' sep_boundary = '\n--' + boundary end_boundary = sep_boundary + '--' body = StringIO.StringIO() for key, value in data.items(): # handle multiple entries for the same name if type(value) != type([]): value = [value] for value in value: if type(value) is tuple: fn = ';filename="%s"' % value[0] value = value[1] else: fn = "" value = str(value) body.write(sep_boundary) body.write('\nContent-Disposition: form-data; name="%s"'%key) body.write(fn) body.write("\n\n") body.write(value) if value and value[-1] == '\r': body.write('\n') # write an extra newline (lurve Macs) body.write(end_boundary) body.write("\n") body = body.getvalue() self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO) # build the Request # We can't use urllib2 since we need to send the Basic # auth right with the first request schema, netloc, url, params, query, fragments = \ urlparse.urlparse(self.repository) assert not params and not query and not fragments if schema == 'http': http = httplib.HTTPConnection(netloc) elif schema == 'https': http = httplib.HTTPSConnection(netloc) else: raise AssertionError, "unsupported schema "+schema data = '' loglevel = log.INFO try: http.connect() http.putrequest("POST", url) http.putheader('Content-type', 'multipart/form-data; boundary=%s'%boundary) http.putheader('Content-length', str(len(body))) http.putheader('Authorization', auth) http.endheaders() http.send(body) except socket.error, e: self.announce(e.msg, log.ERROR) return r = http.getresponse() if r.status == 200: self.announce('Server response (%s): %s' % (r.status, r.reason), log.INFO) else: self.announce('Upload failed (%s): %s' % (r.status, r.reason), log.ERROR) if self.show_response: print '-'*75, r.read(), '-'*75 Index: sdist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/sdist.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- sdist.py 7 Jul 2005 02:03:25 -0000 1.1 +++ sdist.py 7 Jul 2005 16:28:43 -0000 1.2 @@ -63,8 +63,34 @@ for item in walk_revctrl(path, memo): yield item + + + + + + + + + + + + + + + + + class sdist(_sdist): """Smart sdist that finds anything supported by revision control""" + + def run(self): + _sdist.run(self) + dist_files = getattr(self.distribution,'dist_files',[]) + for file in self.archive_files: + data = ('sdist', '', file) + if data not in dist_files: + dist_files.append(data) + def finalize_options(self): _sdist.finalize_options(self) if not os.path.isfile(self.template): @@ -80,3 +106,18 @@ + + + + + + + + + + + + + + + From pje at users.sourceforge.net Thu Jul 7 18:38:34 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 09:38:34 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools ez_setup.py, 1.12, 1.13 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7042 Modified Files: ez_setup.py Log Message: Fix problems upgrading an already-installed setuptools version. Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- ez_setup.py 7 Jul 2005 16:28:43 -0000 1.12 +++ ez_setup.py 7 Jul 2005 16:38:31 -0000 1.13 @@ -150,7 +150,7 @@ from setuptools.command.easy_install import main except ImportError: from easy_install import main - main(list(argv)+[req]) + main(list(argv)+[download_setuptools()]) sys.exit(0) # try to force an exit else: if argv: From pje at users.sourceforge.net Fri Jul 8 06:46:00 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 21:46:00 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command egg_info.py, 1.2, 1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15749/setuptools/command Modified Files: egg_info.py Log Message: The "egg_info" command now always sets the distribution metadata to "safe" forms of the distribution name and version, so that distribution files will be generated with parseable names (i.e., ones that don't include '-' in the name or version). Also, this means that if you use the various ``--tag`` options of "egg_info", any distributions generated will use the tags in the version, not just egg distributions. Index: egg_info.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/egg_info.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- egg_info.py 7 Jul 2005 02:01:54 -0000 1.2 +++ egg_info.py 8 Jul 2005 04:45:58 -0000 1.3 @@ -60,13 +60,13 @@ self.ensure_dirname('egg_base') self.egg_info = os.path.join(self.egg_base, self.egg_name+'.egg-info') - - - - - - - + # Set package version and name for the benefit of dumber commands + # (e.g. sdist, bdist_wininst, etc.) We escape '-' so filenames will + # be more machine-parseable. + # + metadata = self.distribution.metadata + metadata.version = self.egg_version.replace('-','_') + metadata.name = self.egg_name.replace('-','_') @@ -90,6 +90,8 @@ metadata.version, oldver = self.egg_version, metadata.version metadata.name, oldname = self.egg_name, metadata.name try: + # write unescaped data to PKG-INFO, so older pkg_resources + # can still parse it metadata.write_pkg_info(self.egg_info) finally: metadata.name, metadata.version = oldname, oldver @@ -119,8 +121,6 @@ f.close() - - def tagged_version(self): version = self.distribution.get_version() if self.tag_build: From pje at users.sourceforge.net Fri Jul 8 06:46:00 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 21:46:00 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.37, 1.38 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15749 Modified Files: pkg_resources.py Log Message: The "egg_info" command now always sets the distribution metadata to "safe" forms of the distribution name and version, so that distribution files will be generated with parseable names (i.e., ones that don't include '-' in the name or version). Also, this means that if you use the various ``--tag`` options of "egg_info", any distributions generated will use the tags in the version, not just egg distributions. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.37 retrieving revision 1.38 diff -u -d -r1.37 -r1.38 --- pkg_resources.py 7 Jul 2005 01:53:57 -0000 1.37 +++ pkg_resources.py 8 Jul 2005 04:45:57 -0000 1.38 @@ -1299,7 +1299,7 @@ except AttributeError: for line in self._get_metadata('PKG-INFO'): if line.lower().startswith('version:'): - self._version = line.split(':',1)[1].strip() + self._version = safe_version(line.split(':',1)[1].strip()) return self._version else: raise AttributeError( From pje at users.sourceforge.net Fri Jul 8 06:48:22 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 21:48:22 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.26, 1.27 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16463 Modified Files: EasyInstall.txt Log Message: * Added "rotate" command to delete old distribution files, given a set of patterns to match and the number of files to keep. (Keeps the most recently-modified distribution files matching each pattern.) * Added "saveopts" command that saves all command-line options for the current invocation to the local, global, or per-user configuration file. Useful for setting defaults without having to hand-edit a configuration file. * Added a "setopt" command that sets a single option in a specified distutils configuration file. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.26 retrieving revision 1.27 diff -u -d -r1.26 -r1.27 --- EasyInstall.txt 7 Jul 2005 16:28:43 -0000 1.26 +++ EasyInstall.txt 8 Jul 2005 04:48:20 -0000 1.27 @@ -488,6 +488,25 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. +0.5a8 + * The "egg_info" command now always sets the distribution metadata to "safe" + forms of the distribution name and version, so that distribution files will + be generated with parseable names (i.e., ones that don't include '-' in the + name or version). Also, this means that if you use the various ``--tag`` + options of "egg_info", any distributions generated will use the tags in the + version, not just egg distributions. + + * Added "rotate" command to delete old distribution files, given a set of + patterns to match and the number of files to keep. (Keeps the most + recently-modified distribution files matching each pattern.) + + * Added "saveopts" command that saves all command-line options for the current + invocation to the local, global, or per-user configuration file. Useful for + setting defaults without having to hand-edit a configuration file. + + * Added a "setopt" command that sets a single option in a specified distutils + configuration file. + 0.5a7 * Added "upload" support for egg and source distributions, including a bug fix for "upload" and a temporary workaround for lack of .egg support in From pje at users.sourceforge.net Fri Jul 8 06:48:22 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 21:48:22 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command rotate.py, NONE, 1.1 saveopts.py, NONE, 1.1 setopt.py, NONE, 1.1 __init__.py, 1.4, 1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16463/setuptools/command Modified Files: __init__.py Added Files: rotate.py saveopts.py setopt.py Log Message: * Added "rotate" command to delete old distribution files, given a set of patterns to match and the number of files to keep. (Keeps the most recently-modified distribution files matching each pattern.) * Added "saveopts" command that saves all command-line options for the current invocation to the local, global, or per-user configuration file. Useful for setting defaults without having to hand-edit a configuration file. * Added a "setopt" command that sets a single option in a specified distutils configuration file. --- NEW FILE: rotate.py --- import distutils, os from setuptools import Command from distutils.util import convert_path from distutils import log from distutils.errors import * class rotate(Command): """Delete older distributions""" description = "Delete older distributions, keeping N newest files" user_options = [ ('match=', 'm', "patterns to match (required)"), ('dist-dir=', 'd', "directory where the distributions are"), ('keep=', 'k', "number of matching distributions to keep"), ] boolean_options = [] def initialize_options(self): self.match = None self.dist_dir = None self.keep = None def finalize_options(self): if self.match is None: raise DistutilsOptionError( "Must specify one or more (comma-separated) match patterns " "(e.g. '.zip' or '.egg')" ) if self.keep is None: raise DistutilsOptionError("Must specify number of files to keep") try: self.keep = int(self.keep) except ValueError: raise DistutilsOptionError("--keep must be an integer") if isinstance(self.match, basestring): self.match = [ convert_path(p.strip()) for p in self.match.split(',') ] self.set_undefined_options('bdist',('dist_dir', 'dist_dir')) def run(self): self.run_command("egg_info") from glob import glob for pattern in self.match: pattern = self.distribution.get_name()+'*'+pattern files = glob(os.path.join(self.dist_dir,pattern)) files = [(os.path.getmtime(f),f) for f in files] files.sort() files.reverse() log.info("%d file(s) matching %s", len(files), pattern) files = files[self.keep:] for (t,f) in files: log.info("Deleting %s", f) if not self.dry_run: os.unlink(f) --- NEW FILE: saveopts.py --- import distutils, os from setuptools import Command from setuptools.command.setopt import edit_config, option_base class saveopts(option_base): """Save command-line options to a file""" description = "save supplied options to setup.cfg or other config file" user_options = option_base.user_options + [ ] boolean_options = option_base.boolean_options + [ ] def run(self): dist = self.distribution commands = dist.command_options.keys() settings = {} for cmd in commands: if cmd=='saveopts': continue for opt,(src,val) in dist.get_option_dict(cmd).items(): if src=="command line": settings.setdefault(cmd,{})[opt] = val edit_config(self.filename, settings, self.dry_run) --- NEW FILE: setopt.py --- import distutils, os from setuptools import Command from distutils.util import convert_path from distutils import log from distutils.errors import * __all__ = ['config_file', 'edit_config', 'option_base', 'setopt'] def config_file(kind="local"): """Get the filename of the distutils, local, global, or per-user config `kind` must be one of "local", "global", or "user" """ if kind=='local': return 'setup.cfg' if kind=='global': return os.path.join( os.path.dirname(distutils.__file__),'distutils.cfg' ) if kind=='user': dot = os.name=='posix' and '.' or '' return os.path.expanduser(convert_path("~/%spydistutils.cfg" % dot)) raise ValueError( "config_file() type must be 'local', 'global', or 'user'", kind ) def edit_config(filename, settings, dry_run=False): """Edit a configuration file to include `settings` `settings` is a dictionary of dictionaries or ``None`` values, keyed by command/section name. A ``None`` value means to delete the entire section, while a dictionary lists settings to be changed or deleted in that section. A setting of ``None`` means to delete that setting. """ from ConfigParser import RawConfigParser log.debug("Reading configuration from %s", filename) opts = RawConfigParser() opts.read([filename]) for section, options in settings.items(): if options is None: log.debug("Deleting section [%s] from %s", section, filename) opts.remove_section(section) else: if not opts.has_section(section): log.debug("Adding new section [%s] to %s", section, filename) opts.add_section(section) for option,value in options.items(): if value is None: log.debug("Deleting %s.%s from %s", section, option, filename ) opts.remove_option(section,option) else: log.debug( "Setting %s.%s to %r in %s", section, option, value, filename ) opts.set(section,option,value) log.info("Writing %s", filename) if not dry_run: f = open(filename,'w') opts.write(f) f.close() class option_base(Command): """Abstract base class for commands that mess with config files""" user_options = [ ('filename=', 'f', "set the file to use (default=setup.cfg)"), ('global-config', 'g', "save options to the site-wide distutils.cfg file"), ('user-config', 'u', "save options to the current user's pydistutils.cfg file"), ] boolean_options = [ 'global-config', 'user-config', ] def initialize_options(self): self.global_config = None self.user_config = None self.filename = None def finalize_options(self): filenames = [] if self.global_config: filenames.append(config_file('global')) if self.user_config: filenames.append(config_file('user')) if self.filename is not None: filenames.append(self.filename) if not filenames: filenames.append(config_file('local')) if len(filenames)>1: raise DistutilsOptionError( "Must specify only one configuration file option", filenames ) self.filename, = filenames class setopt(option_base): """Save command-line options to a file""" description = "set an option in setup.cfg or another config file" user_options = option_base.user_options + [ ('command=', 'c', 'command to set an option for'), ('option=', 'o', 'option to set'), ('set-value=', 's', 'value of the option'), ('remove', 'r', 'unset the value'), ] boolean_options = option_base.boolean_options + ['remove'] def initialize_options(self): option_base.initialize_options(self) self.command = None self.option = None self.set_value = None self.remove = None def finalize_options(self): option_base.finalize_options(self) if self.command is None or self.option is None: raise DistutilsOptionError("Must specify --command *and* --option") if self.set_value is None and not self.remove: raise DistutilsOptionError("Must specify --set-value or --remove") def run(self): edit_config( self.filename, { self.command: {self.option.replace('-','_'):self.set_value} }, self.dry_run ) Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/__init__.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- __init__.py 6 Jul 2005 03:46:16 -0000 1.4 +++ __init__.py 8 Jul 2005 04:48:20 -0000 1.5 @@ -1,6 +1,6 @@ import distutils.command -__all__ = ['test', 'develop', 'bdist_egg'] +__all__ = ['test', 'develop', 'bdist_egg', 'saveopts', 'setopt', 'rotate'] # Make our commands available as though they were part of the distutils From pje at users.sourceforge.net Fri Jul 8 07:09:25 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 22:09:25 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools dist.py, 1.11, 1.12 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27246/setuptools Modified Files: dist.py Log Message: Added support for defining command aliases in distutils configuration files, under the "[aliases]" section. To prevent recursion and to allow aliases to call the command of the same name, a given alias can be expanded only once per command-line invocation. You can define new aliases with the "alias" command, either for the local, global, or per-user configuration. Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- dist.py 7 Jul 2005 02:03:24 -0000 1.11 +++ dist.py 8 Jul 2005 05:09:23 -0000 1.12 @@ -372,10 +372,19 @@ self.global_options = self.__class__.global_options self.negative_opt = self.__class__.negative_opt - # Handle commands that want to consume all remaining arguments + # First, expand any aliases command = args[0] + aliases = self.get_option_dict('aliases') + while command in aliases: + src,alias = aliases[command] + del aliases[command] # ensure each alias can expand only once! + import shlex + args[:1] = shlex.split(alias,True) + command = args[0] + nargs = _Distribution._parse_command_opts(self, parser, args) + # Handle commands that want to consume all remaining arguments cmd_class = self.get_command_class(command) if getattr(cmd_class,'command_consumes_arguments',None): self.get_option_dict(command)['args'] = ("command line", nargs) @@ -384,6 +393,21 @@ return nargs + + + + + + + + + + + + + + + def has_dependencies(self): return not not self.requires @@ -408,6 +432,23 @@ self.have_run['install'] = 1 setuptools.bootstrap_install_from = None + + + + + + + + + + + + + + + + + def get_cmdline_options(self): """Return a '{cmd: {opt:val}}' map of all command-line options From pje at users.sourceforge.net Fri Jul 8 07:09:25 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 22:09:25 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.27, 1.28 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27246 Modified Files: EasyInstall.txt Log Message: Added support for defining command aliases in distutils configuration files, under the "[aliases]" section. To prevent recursion and to allow aliases to call the command of the same name, a given alias can be expanded only once per command-line invocation. You can define new aliases with the "alias" command, either for the local, global, or per-user configuration. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- EasyInstall.txt 8 Jul 2005 04:48:20 -0000 1.27 +++ EasyInstall.txt 8 Jul 2005 05:09:23 -0000 1.28 @@ -495,7 +495,13 @@ name or version). Also, this means that if you use the various ``--tag`` options of "egg_info", any distributions generated will use the tags in the version, not just egg distributions. - + + * Added support for defining command aliases in distutils configuration files, + under the "[aliases]" section. To prevent recursion and to allow aliases to + call the command of the same name, a given alias can be expanded only once + per command-line invocation. You can define new aliases with the "alias" + command, either for the local, global, or per-user configuration. + * Added "rotate" command to delete old distribution files, given a set of patterns to match and the number of files to keep. (Keeps the most recently-modified distribution files matching each pattern.) From pje at users.sourceforge.net Fri Jul 8 07:09:26 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 22:09:26 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command alias.py, NONE, 1.1 __init__.py, 1.5, 1.6 saveopts.py, 1.1, 1.2 sdist.py, 1.2, 1.3 setopt.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27246/setuptools/command Modified Files: __init__.py saveopts.py sdist.py setopt.py Added Files: alias.py Log Message: Added support for defining command aliases in distutils configuration files, under the "[aliases]" section. To prevent recursion and to allow aliases to call the command of the same name, a given alias can be expanded only once per command-line invocation. You can define new aliases with the "alias" command, either for the local, global, or per-user configuration. --- NEW FILE: alias.py --- import distutils, os from setuptools import Command from distutils.util import convert_path from distutils import log from distutils.errors import * from setuptools.command.setopt import edit_config, option_base class alias(option_base): """Abstract base class for commands that mess with config files""" description = "set an option in setup.cfg or another config file" user_options = [ ('alias=', 'a', 'the name of the new pseudo-command'), ('command=', 'c', 'command(s) and options to invoke when used'), ('remove', 'r', 'remove (unset) the alias'), ] + option_base.user_options boolean_options = option_base.boolean_options + ['remove'] def initialize_options(self): option_base.initialize_options(self) self.alias = None self.command = None self.remove = None def finalize_options(self): option_base.finalize_options(self) if self.alias is None: raise DistutilsOptionError("Must specify name (--alias/-a)") if self.command is None and not self.remove: raise DistutilsOptionError("Must specify --command or --remove") def run(self): edit_config( self.filename, {'aliases': {self.alias:self.command}}, self.dry_run ) Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/__init__.py,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- __init__.py 8 Jul 2005 04:48:20 -0000 1.5 +++ __init__.py 8 Jul 2005 05:09:23 -0000 1.6 @@ -1,6 +1,8 @@ import distutils.command -__all__ = ['test', 'develop', 'bdist_egg', 'saveopts', 'setopt', 'rotate'] +__all__ = [ + 'test', 'develop', 'bdist_egg', 'saveopts', 'setopt', 'rotate', 'alias' +] # Make our commands available as though they were part of the distutils Index: saveopts.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/saveopts.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- saveopts.py 8 Jul 2005 04:48:20 -0000 1.1 +++ saveopts.py 8 Jul 2005 05:09:23 -0000 1.2 @@ -7,21 +7,19 @@ description = "save supplied options to setup.cfg or other config file" - user_options = option_base.user_options + [ - ] - - boolean_options = option_base.boolean_options + [ - ] - def run(self): dist = self.distribution commands = dist.command_options.keys() settings = {} + for cmd in commands: + if cmd=='saveopts': - continue + continue # don't save our own options! + for opt,(src,val) in dist.get_option_dict(cmd).items(): if src=="command line": settings.setdefault(cmd,{})[opt] = val + edit_config(self.filename, settings, self.dry_run) Index: sdist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/sdist.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- sdist.py 7 Jul 2005 16:28:43 -0000 1.2 +++ sdist.py 8 Jul 2005 05:09:23 -0000 1.3 @@ -84,6 +84,7 @@ """Smart sdist that finds anything supported by revision control""" def run(self): + self.run_command('egg_info') _sdist.run(self) dist_files = getattr(self.distribution,'dist_files',[]) for file in self.archive_files: @@ -120,4 +121,3 @@ - Index: setopt.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/setopt.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- setopt.py 8 Jul 2005 04:48:20 -0000 1.1 +++ setopt.py 8 Jul 2005 05:09:23 -0000 1.2 @@ -84,12 +84,12 @@ """Abstract base class for commands that mess with config files""" user_options = [ - ('filename=', 'f', - "set the file to use (default=setup.cfg)"), ('global-config', 'g', "save options to the site-wide distutils.cfg file"), ('user-config', 'u', "save options to the current user's pydistutils.cfg file"), + ('filename=', 'f', + "configuration file to use (default=setup.cfg)"), ] boolean_options = [ @@ -126,12 +126,12 @@ description = "set an option in setup.cfg or another config file" - user_options = option_base.user_options + [ + user_options = [ ('command=', 'c', 'command to set an option for'), ('option=', 'o', 'option to set'), ('set-value=', 's', 'value of the option'), - ('remove', 'r', 'unset the value'), - ] + ('remove', 'r', 'remove (unset) the value'), + ] + option_base.user_options boolean_options = option_base.boolean_options + ['remove'] From pje at users.sourceforge.net Fri Jul 8 07:11:23 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 07 Jul 2005 22:11:23 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command alias.py, 1.1, 1.2 rotate.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28614/setuptools/command Modified Files: alias.py rotate.py Log Message: Fix a couple of command descriptions. Index: alias.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/alias.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- alias.py 8 Jul 2005 05:09:23 -0000 1.1 +++ alias.py 8 Jul 2005 05:11:20 -0000 1.2 @@ -6,9 +6,9 @@ from setuptools.command.setopt import edit_config, option_base class alias(option_base): - """Abstract base class for commands that mess with config files""" + """Define a shortcut that invokes one or more commands""" - description = "set an option in setup.cfg or another config file" + description = "define a shortcut to invoke one or more commands" user_options = [ ('alias=', 'a', 'the name of the new pseudo-command'), Index: rotate.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/rotate.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- rotate.py 8 Jul 2005 04:48:20 -0000 1.1 +++ rotate.py 8 Jul 2005 05:11:20 -0000 1.2 @@ -7,7 +7,7 @@ class rotate(Command): """Delete older distributions""" - description = "Delete older distributions, keeping N newest files" + description = "delete older distributions, keeping N newest files" user_options = [ ('match=', 'm', "patterns to match (required)"), ('dist-dir=', 'd', "directory where the distributions are"), From pje at users.sourceforge.net Fri Jul 8 17:11:26 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 08:11:26 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command alias.py, 1.2, 1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2382/setuptools/command Modified Files: alias.py Log Message: Restructured the 'alias' command to take arguments instead of options, and to display the definition of the named alias or of all aliases. Index: alias.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/alias.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- alias.py 8 Jul 2005 05:11:20 -0000 1.2 +++ alias.py 8 Jul 2005 15:11:19 -0000 1.3 @@ -3,37 +3,80 @@ from distutils.util import convert_path from distutils import log from distutils.errors import * -from setuptools.command.setopt import edit_config, option_base +from setuptools.command.setopt import edit_config, option_base, config_file class alias(option_base): """Define a shortcut that invokes one or more commands""" description = "define a shortcut to invoke one or more commands" + command_consumes_arguments = True user_options = [ - ('alias=', 'a', 'the name of the new pseudo-command'), - ('command=', 'c', 'command(s) and options to invoke when used'), ('remove', 'r', 'remove (unset) the alias'), ] + option_base.user_options boolean_options = option_base.boolean_options + ['remove'] + def initialize_options(self): option_base.initialize_options(self) - self.alias = None - self.command = None + self.args = None self.remove = None + def finalize_options(self): option_base.finalize_options(self) - if self.alias is None: - raise DistutilsOptionError("Must specify name (--alias/-a)") - if self.command is None and not self.remove: - raise DistutilsOptionError("Must specify --command or --remove") + if self.remove and len(self.args)<>1: + raise DistutilsOptionError( + "Must specify exactly one argument (the alias name) when " + "using --remove" + ) + + + + + + + def run(self): - edit_config( - self.filename, {'aliases': {self.alias:self.command}}, - self.dry_run - ) + aliases = self.distribution.get_option_dict('aliases') + + if not self.args: + print "Command Aliases" + print "---------------" + for alias in aliases: + print "setup.py alias", format_alias(alias, aliases) + return + + elif len(self.args)==1: + alias, = self.args + if self.remove: + command = None + elif alias in aliases: + print "setup.py alias", format_alias(alias, aliases) + return + else: + print "No alias definition found for %r" % alias + return + else: + alias = self.args[0] + command = ' '.join(map(repr,self.args[1:])) + + edit_config(self.filename, {'aliases': {alias:command}}, self.dry_run) + + +def format_alias(name, aliases): + source, command = aliases[name] + if source == config_file('global'): + source = '--global-config ' + elif source == config_file('user'): + source = '--user-config ' + elif source == config_file('local'): + source = '' + else: + source = '--filename=%r' % source + return source+name+' '+command + + From pje at users.sourceforge.net Fri Jul 8 17:13:24 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 08:13:24 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools setuptools.txt, NONE, 1.1 EasyInstall.txt, 1.28, 1.29 setup.py, 1.21, 1.22 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3165 Modified Files: EasyInstall.txt setup.py Added Files: setuptools.txt Log Message: Partial first draft documentation for setuptools. Split revision history between setuptools and easy_install docs. Pull project's long_description from the documentation, for a more informative PyPI project page. --- NEW FILE: setuptools.txt --- ====================================================== Building and Distributing Packages with ``setuptools`` ====================================================== ``setuptools`` is a collection of enhancements to the Python ``distutils`` (for Python 2.3 and up) that allow you to more easily build and distribute Python packages, especially ones that have dependencies on other packages. Packages built and distributed using ``setuptools`` look to the user like ordinary Python packages based on the ``distutils``. Your users don't need to install or even know about setuptools in order to use them, and you don't have to include the entire setuptools package in your distributions. By including just a single `bootstrap module`_ (a 5K .py file), your package will automatically download and install ``setuptools`` if the user is building your package from source and doesn't have a suitable version already installed. .. _bootstrap module: http://peak.telecommunity.com/dist/ez_setup.py Feature Highlights: * Automatically find/download/install/upgrade dependencies at build time using the `EasyInstall tool `_, which supports downloading via HTTP, FTP, Subversion, and SourceForge, and automatically scans web pages linked from PyPI to find download links. (It's the closest thing to CPAN currently available for Python.) * Create `Python Eggs `_ - a single-file importable distribution format * Include data files inside your package directories, where your code can actually use them. (Python 2.4 distutils includes this feature already, but setuptools provides the feature for Python 2.3 packages also.) * Automatically include all packages in your source tree, without listing them individually in setup.py * Automatically include all relevant files in your source distributions, without needing to create a MANIFEST.in and without having to force MANIFEST regeneration * Transparent Pyrex support, so that your setup.py can list .pyx files and still work even when the end-user doesn't have Pyrex installed (as long as you include the Pyrex-generated C in your source distribution) * Command aliases - create project-specific, per-user, or site-wide shortcut names for commonly used commands and options * PyPI upload support - upload your source distributions and eggs to PyPI * Put your package in "development mode", such that it's available on sys.path, yet you can still edit it directly from your source checkout. .. contents:: **Table of Contents** ----------------- Developer's Guide ----------------- Installing ``setuptools`` ========================= Windows users can just download and run the `setuptools binary installer for Windows `_. All others should just download `ez_setup.py`_ and run it; this will download and install the appropriate egg for your Python version. .. _ez_setup.py: `bootstrap module`_ You may receive a message telling you about an obsolete version of setuptools being present; if so, you must be sure to delete it entirely, along with the old ``pkg_resources`` module if it's present on ``sys.path``. Basic Use ========= For basic use of setuptools, just import things from setuptools instead of the distutils. Here's a minimal setup script using setuptools:: from setuptools import setup, find_packages setup( name = "HelloWorld", version = "0.1", packages = find_packages(), ) As you can see, it doesn't take much to use setuptools in a project. Just by doing the above, this project will be able to produce eggs, upload to PyPI, and automatically include all packages in the directory where the setup.py lives. See the sections below on `Enhanced Commands`_ and `New Commands`_ to see what commands you can give to this setup.py. Of course, before you release your project to PyPI, you'll want to add a bit more information to your setup script to help people find or learn about your project. And maybe your project will have grown by then to include a few dependencies, and perhaps some data files and scripts:: from setuptools import setup, find_packages setup( name = "HelloWorld", version = "0.1", packages = find_packages(), scripts = ['say_hello.py'], # Project uses reStructuredText, so ensure that the docutils get # installed or upgraded on the target machine install_requires = ['docutils>=0.3'], package_data = { # If any package contains *.txt or *.rst files, include them: '': ['*.txt', '*.rst'], # And include any *.msg files found in the 'hello' package, too: 'hello': ['*.msg'], } # metadata for upload to PyPI author = "Me", author_email = "me at example.com", description = "This is an Example Package", license = "PSF", keywords = "hello world example examples", url = "http://example.com/HelloWorld/", # project home page, if any # could also include long_description, download_url, classifiers, etc. ) In the following sections, we'll explain what most of these Declaring Dependencies ====================== ``setuptools`` supports automatically installing dependencies when a package is installed, and including information about dependencies in Python Eggs (so that package management tools like EasyInstall can use the information). ``setuptools`` and ``pkg_resources`` use a common syntax for specifying a project's required dependencies. This syntax consists of a project's PyPI name, optionally followed by a comma-separated list of "extras" in square brackets, optionally followed by a comma-separated list of version specifiers. A version specifier is one of the operators ``<``, ``>``, ``<=``, ``>=``, ``==`` or ``!=``, followed by a version identifier. Tokens may be separated by whitespace, but any whitespace or nonstandard characters within a project name or version identifier must be replaced with ``-``. Here are some example requirement specifiers:: docutils >= 0.3 # comment lines and \ continuations are allowed in requirement strings BazSpam ==1.1, ==1.2, ==1.3, ==1.4, ==1.5, \ ==1.6, ==1.7 # and so are line-end comments PEAK[FastCGI, reST]>=0.5a4 setuptools==0.5a7 The simplest way to include requirement specifiers is to use the ``install_requires`` argument to ``setup()``. It takes a string or list of strings containing requirement specifiers. If you include more than one requirement in a string, each requirement must begin on a new line. This has three effects: 1. When your project is installed, either by using EasyInstall, ``setup.py install``, or ``setup.py develop``, all of the dependencies not already installed will be located (via PyPI), downloaded, built (if necessary), and installed. 2. Any scripts in your project will be installed with wrappers that verify the availability of the specified dependencies at runtime, and ensure that the correct versions are added to ``sys.path`` (e.g. if multiple versions have been installed). 3. Python Egg distributions will include a metadata file listing the dependencies. Note, by the way, that if you declare your dependencies in ``setup.py``, you do *not* need to use the ``require()`` function in your scripts or modules, as long as you either install the project or use ``setup.py develop`` to do development work on it. (See `"Development Mode"`_ below for more details on using ``setup.py develop``.) Declaring "Extras" (optional features with their own dependencies) ------------------------------------------------------------------ Sometimes a project has "recommended" dependencies, that are not required for all uses of the project. For example, a project might offer optional PDF output if ReportLab is installed, and reStructuredText support if docutils is installed. These optional features are called "extras", and setuptools allows you to define their requirements as well. In this way, other projects that require these optional features can force the additional requirements to be installed, by naming the desired extras in their ``install_requires``. For example, let's say that Project A offers optional PDF and reST support:: setup( name="Project-A", ... extras_require = { 'PDF': ["ReportLab>=1.2", "RXP"], 'reST': ["docutils>=0.3"], } ) And that project B needs project A, *with* PDF support:: setup( name="Project-B", install_requires = ["Project-A[PDF]"], ... ) This will cause ReportLab to be installed along with project A, if project B is installed -- even if project A was already installed. In this way, a project can encapsulate groups of optional "downstream dependencies" under a feature name, so that packages that depend on it don't have to know what the downstream dependencies are. If a later version of Project A builds in PDF support and no longer needs ReportLab, or if it ends up needing other dependencies besides ReportLab in order to provide PDF support, Project B's setup information does not need to change, but the right packages will still be installed if needed. As you can see, the ``extras_require`` argument takes a dictionary mapping names of "extra" features, to strings or lists of strings describing those features' requirements. These requirements will *not* be automatically installed unless another package depends on them (directly or indirectly) by including the desired "extras" in square brackets after the associated project name. (Or if the extras were listed in a requirement spec on the EasyInstall command line.) Note, by the way, that if a project ends up not needing any other packages to support a feature, it should keep an empty requirements list for that feature in its ``extras_require`` argument, so that packages depending on that feature don't break (due to an invalid feature name). For example, if Project A above builds in PDF support and no longer needs ReportLab, it should change its setup to this:: setup( name="Project-A", ... extras_require = { 'PDF': [], 'reST': ["docutils>=0.3"], } ) so that Package B doesn't have to remove the ``[PDF]`` from its requirement specifier. Distributing a ``setuptools``-based package =========================================== Your users might not have ``setuptools`` installed on their machines, or even if they do, it might not be the right version. Fixing this is easy; just download `ez_setup.py`_, and put it in the same directory as your ``setup.py`` script. (Be sure to add it to your revision control system, too.) Then add these two lines to the very top of your setup script, before the script imports anything from setuptools:: import ez_setup ez_setup.use_setuptools() That's it. The ``ez_setup`` module will automatically download a matching version of ``setuptools`` from PyPI, if it isn't present on the target system. Whenever you install an updated version of setuptools, you should also update your projects' ``ez_setup.py`` files, so that a matching version gets installed on the target machine(s). If you're using Subversion, you may wish to use "externals" to make all your projects share a single ``ez_setup.py``, so that you only have to update it in one place to update all your projects. By the way, setuptools supports the new PyPI "upload" command, so you can use ``setup.py sdist upload`` or ``setup.py bdist_egg upload`` to upload your source or egg distributions respectively. Your project's current version must be registered with PyPI first, of course; you can use ``setup.py register`` to do that. Or you can do it all in one step, e.g. ``setup.py register sdist bdist_egg upload`` will register the package, build source and egg distributions, and then upload them both to PyPI, where they'll be easily found by other projects that depend on them. Including Data Files ==================== The distutils have traditionally allowed installation of "data files", which are placed in a platform-specific location. However, the most common use case for data files distributed with a package is for use *by* the package, usually by including the data files in the package directory. Setuptools supports this by allowing a ``package_data`` argument to ``setup()``, e.g.:: from setuptools import setup, find_packages setup( ... package_data = { # If any package contains *.txt or *.rst files, include them: '': ['*.txt', '*.rst'], # And include any *.msg files found in the 'hello' package, too: 'hello': ['*.msg'], } ) The ``package_data`` argument is a dictionary that maps from package names to lists of glob patterns. The globs may include subdirectory names, if the data files are contained in a subdirectory of the package. For example, if the package tree looks like this:: setup.py src/ mypkg/ __init__.py mypkg.txt data/ somefile.dat otherdata.dat The setuptools setup file might look like this:: from setuptools import setup, find_packages setup( ... packages = find_packages('src'), # include all packages under src package_dir = {'':'src'}, # tell distutils packages are under src package_data = { # If any package contains *.txt files, include them: '': ['*.txt'], # And include any *.dat files found in the 'data' subdirectory # of the 'mypkg' package, also: 'mypkg': ['data/*.dat'], } ) Notice that if you list patterns in ``package_data`` under the empty string, these patterns are used to find files in every package, even ones that also have their own patterns listed. Thus, in the above example, the ``mypkg.txt`` file gets included even though it's not listed in the patterns for ``mypkg``. Also notice that if you use paths, you *must* use a forward slash (``/``) as the path separator, even if you are on Windows. Setuptools automatically converts slashes to appropriate platform-specific separators at build time. (Note: although the ``package_data`` argument was previously only available in ``setuptools``, it was also added to the Python ``distutils`` package as of Python 2.4; there is `some documentation for the feature`__ available on the python.org website.) __ http://docs.python.org/dist/node11.html Accessing Data Files at Runtime ------------------------------- Typically, existing programs manipulate a package's ``__file__`` attribute in order to find the location of data files. However, this manipulation isn't compatible with PEP 302-based import hooks, including importing from zip files and Python Eggs. It is strongly recommended that, if you are using data files, you should use the `Resource Management API`_ of ``pkg_resources`` to access them. The ``pkg_resources`` module is distributed as part of setuptools, so if you're using setuptools to distribute your package, there is no reason not to use its resource management API. See also `Accessing Package Resources`_ for a quick example of converting code that uses ``__file__`` to use ``pkg_resources`` instead. .. _Resource Management API: http://peak.telecommunity.com/DevCenter/PythonEggs#resource-management .. _Accessing Package Resources: http://peak.telecommunity.com/DevCenter/PythonEggs#accessing-package-resources .. XXX put doc about zip_safe flag here, once it's implemented "Development Mode" ================== Sorry, this section isn't written yet, and neither is anything below this point except the changelog. You might want to `subscribe to changes in this page `_ to see when the documentation is added or updated. Tagging and "Daily Build" or "Snapshot" Releases ------------------------------------------------ XXX Using ``find_packages()`` ========================= XXX Building Extensions written with Pyrex ====================================== XXX ----------------- Enhanced Commands ----------------- ``build_ext`` - automatic support for Pyrex extensions ====================================================== XXX ``bdist, sdist`` - added support for "daily" or "special" build tagging ======================================================================= XXX ``sdist`` - auto-include files from CVS or Subversion ====================================================== XXX ``upload`` - support uploading Python Eggs ========================================== XXX ------------ New Commands ------------ ``alias`` - Define shortcuts for commonly used commands ======================================================= XXX ``bdist_egg`` - Create a Python Egg for the package =================================================== XXX ``develop`` - "Install" the source package in-place =================================================== XXX ``egg_info`` - Create egg metadata and set build tags ===================================================== XXX ``easy_install`` - Find, download, and install other packages ============================================================= XXX ``test`` - Build package and run a unittest suite ================================================= XXX ``rotate`` - Delete outdated distribution files =============================================== XXX ``saveopts`` - Save used options to a configuration file ======================================================== XXX ``setopt`` - Set a distutils or setuptools option in a config file ================================================================== XXX ------------------------------------ Extending and Reusing ``setuptools`` ------------------------------------ Subclassing ``Command`` ======================= XXX Utility Modules =============== ``ez_setup`` ------------ XXX ``setuptools.archive_util`` --------------------------- XXX ``setuptools.sandbox`` ---------------------- XXX ``setuptools.package_index`` ---------------------------- XXX ---------------------------- Release Notes/Change History ---------------------------- 0.5a8 * The "egg_info" command now always sets the distribution metadata to "safe" forms of the distribution name and version, so that distribution files will be generated with parseable names (i.e., ones that don't include '-' in the name or version). Also, this means that if you use the various ``--tag`` options of "egg_info", any distributions generated will use the tags in the version, not just egg distributions. * Added support for defining command aliases in distutils configuration files, under the "[aliases]" section. To prevent recursion and to allow aliases to call the command of the same name, a given alias can be expanded only once per command-line invocation. You can define new aliases with the "alias" command, either for the local, global, or per-user configuration. * Added "rotate" command to delete old distribution files, given a set of patterns to match and the number of files to keep. (Keeps the most recently-modified distribution files matching each pattern.) * Added "saveopts" command that saves all command-line options for the current invocation to the local, global, or per-user configuration file. Useful for setting defaults without having to hand-edit a configuration file. * Added a "setopt" command that sets a single option in a specified distutils configuration file. 0.5a7 * Added "upload" support for egg and source distributions, including a bug fix for "upload" and a temporary workaround for lack of .egg support in PyPI. 0.5a6 * Beefed up the "sdist" command so that if you don't have a MANIFEST.in, it will include all files under revision control (CVS or Subversion) in the current directory, and it will regenerate the list every time you create a source distribution, not just when you tell it to. This should make the default "do what you mean" more often than the distutils' default behavior did, while still retaining the old behavior in the presence of MANIFEST.in. * Fixed the "develop" command always updating .pth files, even if you specified ``-n`` or ``--dry-run``. * Slightly changed the format of the generated version when you use ``--tag-build`` on the "egg_info" command, so that you can make tagged revisions compare *lower* than the version specified in setup.py (e.g. by using ``--tag-build=dev``). 0.5a5 * Added ``develop`` command to ``setuptools``-based packages. This command installs an ``.egg-link`` pointing to the package's source directory, and script wrappers that ``execfile()`` the source versions of the package's scripts. This lets you put your development checkout(s) on sys.path without having to actually install them. (To uninstall the link, use use ``setup.py develop --uninstall``.) * Added ``egg_info`` command to ``setuptools``-based packages. This command just creates or updates the "projectname.egg-info" directory, without building an egg. (It's used by the ``bdist_egg``, ``test``, and ``develop`` commands.) * Enhanced the ``test`` command so that it doesn't install the package, but instead builds any C extensions in-place, updates the ``.egg-info`` metadata, adds the source directory to ``sys.path``, and runs the tests directly on the source. This avoids an "unmanaged" installation of the package to ``site-packages`` or elsewhere. * Made ``easy_install`` a standard ``setuptools`` command, moving it from the ``easy_install`` module to ``setuptools.command.easy_install``. Note that if you were importing or extending it, you must now change your imports accordingly. ``easy_install.py`` is still installed as a script, but not as a module. 0.5a4 * Setup scripts using setuptools can now list their dependencies directly in the setup.py file, without having to manually create a ``depends.txt`` file. The ``install_requires`` and ``extras_require`` arguments to ``setup()`` are used to create a dependencies file automatically. If you are manually creating ``depends.txt`` right now, please switch to using these setup arguments as soon as practical, because ``depends.txt`` support will be removed in the 0.6 release cycle. For documentation on the new arguments, see the ``setuptools.dist.Distribution`` class. * Setup scripts using setuptools now always install using ``easy_install`` internally, for ease of uninstallation and upgrading. Note: you *must* remove any ``extra_path`` argument from your setup script, as it conflicts with the proper functioning of the ``easy_install`` command. * ``pkg_resources.AvailableDistributions.resolve()`` and related methods now accept an ``installer`` argument: a callable taking one argument, a ``Requirement`` instance. The callable must return a ``Distribution`` object, or ``None`` if no distribution is found. This feature is used by EasyInstall to resolve dependencies by recursively invoking itself. 0.5a1 * Added support for "self-installation" bootstrapping. Packages can now include ``ez_setup.py`` in their source distribution, and add the following to their ``setup.py``, in order to automatically bootstrap installation of setuptools as part of their setup process:: from ez_setup import use_setuptools use_setuptools() from setuptools import setup # etc... 0.4a4 * Fix problems with ``resource_listdir()``, ``resource_isdir()`` and resource directory extraction for zipped eggs. 0.4a3 * Fixed scripts not being able to see a ``__file__`` variable in ``__main__`` * Fixed a problem with ``resource_isdir()`` implementation that was introduced in 0.4a2. 0.4a2 * Added ``ez_setup.py`` installer/bootstrap script to make initial setuptools installation easier, and to allow distributions using setuptools to avoid having to include setuptools in their source distribution. * All downloads are now managed by the ``PackageIndex`` class (which is now subclassable and replaceable), so that embedders can more easily override download logic, give download progress reports, etc. The class has also been moved to the new ``setuptools.package_index`` module. * The ``Installer`` class no longer handles downloading, manages a temporary directory, or tracks the ``zip_ok`` option. Downloading is now handled by ``PackageIndex``, and ``Installer`` has become an ``easy_install`` command class based on ``setuptools.Command``. * There is a new ``setuptools.sandbox.run_setup()`` API to invoke a setup script in a directory sandbox, and a new ``setuptools.archive_util`` module with an ``unpack_archive()`` API. These were split out of EasyInstall to allow reuse by other tools and applications. * ``setuptools.Command`` now supports reinitializing commands using keyword arguments to set/reset options. Also, ``Command`` subclasses can now set their ``command_consumes_arguments`` attribute to ``True`` in order to receive an ``args`` option containing the rest of the command line. 0.4a1 * Fixed a bug in requirements processing for exact versions (i.e. ``==`` and ``!=``) when only one condition was included. * Added ``safe_name()`` and ``safe_version()`` APIs to clean up handling of arbitrary distribution names and versions found on PyPI. 0.3a4 * ``pkg_resources`` now supports resource directories, not just the resources in them. In particular, there are ``resource_listdir()`` and ``resource_isdir()`` APIs. * ``pkg_resources`` now supports "egg baskets" -- .egg zipfiles which contain multiple distributions in subdirectories whose names end with ``.egg``. Having such a "basket" in a directory on ``sys.path`` is equivalent to having the individual eggs in that directory, but the contained eggs can be individually added (or not) to ``sys.path``. Currently, however, there is no automated way to create baskets. * Namespace package manipulation is now protected by the Python import lock. 0.3a2 * Added new options to ``bdist_egg`` to allow tagging the egg's version number with a subversion revision number, the current date, or an explicit tag value. Run ``setup.py bdist_egg --help`` to get more information. * Misc. bug fixes 0.3a1 Initial release. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- EasyInstall.txt 8 Jul 2005 05:09:23 -0000 1.28 +++ EasyInstall.txt 8 Jul 2005 15:13:14 -0000 1.29 @@ -2,8 +2,9 @@ Easy Install ============ -Easy Install is a python module (``easy_install``) that lets you automatically -download, build, install, and manage Python packages. +Easy Install is a python module (``easy_install``) bundled with ``setuptools`` +that lets you automatically download, build, install, and manage Python +packages. (Please share your experiences with us! Whether you encountered success or difficulty installing a particular package, please add your notes to the @@ -26,7 +27,8 @@ Windows `_. All others should just download `ez_setup.py `_, and run it; this will -download and install the appropriate egg for you. +download and install the appropriate ``setuptools`` egg for your Python +version. You may receive a message telling you about an obsolete version of setuptools being present; if so, you must be sure to delete it entirely, along @@ -488,71 +490,7 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. -0.5a8 - * The "egg_info" command now always sets the distribution metadata to "safe" - forms of the distribution name and version, so that distribution files will - be generated with parseable names (i.e., ones that don't include '-' in the - name or version). Also, this means that if you use the various ``--tag`` - options of "egg_info", any distributions generated will use the tags in the - version, not just egg distributions. - - * Added support for defining command aliases in distutils configuration files, - under the "[aliases]" section. To prevent recursion and to allow aliases to - call the command of the same name, a given alias can be expanded only once - per command-line invocation. You can define new aliases with the "alias" - command, either for the local, global, or per-user configuration. - - * Added "rotate" command to delete old distribution files, given a set of - patterns to match and the number of files to keep. (Keeps the most - recently-modified distribution files matching each pattern.) - - * Added "saveopts" command that saves all command-line options for the current - invocation to the local, global, or per-user configuration file. Useful for - setting defaults without having to hand-edit a configuration file. - - * Added a "setopt" command that sets a single option in a specified distutils - configuration file. - -0.5a7 - * Added "upload" support for egg and source distributions, including a bug - fix for "upload" and a temporary workaround for lack of .egg support in - PyPI. - -0.5a6 - * Beefed up the "sdist" command so that if you don't have a MANIFEST.in, it - will include all files under revision control (CVS or Subversion) in the - current directory, and it will regenerate the list every time you create a - source distribution, not just when you tell it to. This should make the - default "do what you mean" more often than the distutils' default behavior - did, while still retaining the old behavior in the presence of MANIFEST.in. - - * Fixed the "develop" command always updating .pth files, even if you - specified ``-n`` or ``--dry-run``. - - * Slightly changed the format of the generated version when you use - ``--tag-build`` on the "egg_info" command, so that you can make tagged - revisions compare *lower* than the version specified in setup.py (e.g. by - using ``--tag-build=dev``). - 0.5a5 - * Added ``develop`` command to ``setuptools``-based packages. This command - installs an ``.egg-link`` pointing to the package's source directory, and - script wrappers that ``execfile()`` the source versions of the package's - scripts. This lets you put your development checkout(s) on sys.path without - having to actually install them. (To uninstall the link, use - use ``setup.py develop --uninstall``.) - - * Added ``egg_info`` command to ``setuptools``-based packages. This command - just creates or updates the "projectname.egg-info" directory, without - building an egg. (It's used by the ``bdist_egg``, ``test``, and ``develop`` - commands.) - - * Enhanced the ``test`` command so that it doesn't install the package, but - instead builds any C extensions in-place, updates the ``.egg-info`` - metadata, adds the source directory to ``sys.path``, and runs the tests - directly on the source. This avoids an "unmanaged" installation of the - package to ``site-packages`` or elsewhere. - * Made ``easy_install`` a standard ``setuptools`` command, moving it from the ``easy_install`` module to ``setuptools.command.easy_install``. Note that if you were importing or extending it, you must now change your imports @@ -569,15 +507,6 @@ version(s) of all packages requested by name and version, even if a matching version is available locally. - * Setup scripts using setuptools can now list their dependencies directly in - the setup.py file, without having to manually create a ``depends.txt`` file. - The ``install_requires`` and ``extras_require`` arguments to ``setup()`` - are used to create a dependencies file automatically. If you are manually - creating ``depends.txt`` right now, please switch to using these setup - arguments as soon as practical, because ``depends.txt`` support will be - removed in the 0.6 release cycle. For documentation on the new arguments, - see the ``setuptools.dist.Distribution`` class. - * Added automatic installation of dependencies declared by a distribution being installed. These dependencies must be listed in the distribution's ``EGG-INFO`` directory, so the distribution has to have declared its @@ -585,19 +514,9 @@ declare, you'll still have to deal with them yourself. (E.g., by asking EasyInstall to find and install them.) - * Setup scripts using setuptools now always install using ``easy_install`` - internally, for ease of uninstallation and upgrading. Note: you *must* - remove any ``extra_path`` argument from your setup script, as it conflicts - with the proper functioning of the ``easy_install`` command. (Also, added - the ``--record`` option to ``easy_install`` for the benefit of tools that - run ``setup.py install --record=filename`` on behalf of another packaging - system.) - - * ``pkg_resources.AvailableDistributions.resolve()`` and related methods now - accept an ``installer`` argument: a callable taking one argument, a - ``Requirement`` instance. The callable must return a ``Distribution`` - object, or ``None`` if no distribution is found. This feature is used by - EasyInstall to resolve dependencies by recursively invoking itself. + * Added the ``--record`` option to ``easy_install`` for the benefit of tools + that run ``setup.py install --record=filename`` on behalf of another + packaging system.) 0.5a3 * Fixed not setting script permissions to allow execution. @@ -612,17 +531,6 @@ * Added support for converting ``.win32.exe`` installers to eggs on the fly. EasyInstall will now recognize such files by name and install them. - * Added support for "self-installation" bootstrapping. Packages can now - include ``ez_setup.py`` in their source distribution, and add the following - to their ``setup.py``, in order to automatically bootstrap installation of - setuptools as part of their setup process:: - - from ez_setup import use_setuptools - use_setuptools() - - from setuptools import setup - # etc... - * Fixed a problem with picking the "best" version to install (versions were being sorted as strings, rather than as parsed values) @@ -633,15 +541,7 @@ * Support downloading packages that were uploaded to PyPI (by scanning all links on package pages, not just the homepage/download links). - * Fix problems with ``resource_listdir()``, ``resource_isdir()`` and resource - directory extraction for zipped eggs. - 0.4a3 - * Fixed scripts not being able to see a ``__file__`` variable in ``__main__`` - - * Fixed a problem with ``resource_isdir()`` implementation that was introduced - in 0.4a2. - * Add progress messages to the search/download process so that you can tell what URLs it's reading to find download links. (Hopefully, this will help people report out-of-date and broken links to package authors, and to tell @@ -656,57 +556,14 @@ * Renamed ``--scan-url/-s`` to ``--find-links/-f`` to free up ``-s`` for the script installation directory option. - * Added ``ez_setup.py`` installer/bootstrap script to make initial setuptools - installation easier, and to allow distributions using setuptools to avoid - having to include setuptools in their source distribution. - * Use ``urllib2`` instead of ``urllib``, to allow use of ``https:`` URLs if Python includes SSL support. - * All downloads are now managed by the ``PackageIndex`` class (which is now - subclassable and replaceable), so that embedders can more easily override - download logic, give download progress reports, etc. The class has also - been moved to the new ``setuptools.package_index`` module. - - * The ``Installer`` class no longer handles downloading, manages a temporary - directory, or tracks the ``zip_ok`` option. Downloading is now handled - by ``PackageIndex``, and ``Installer`` has become an ``easy_install`` - command class based on ``setuptools.Command``. - - * There is a new ``setuptools.sandbox.run_setup()`` API to invoke a setup - script in a directory sandbox, and a new ``setuptools.archive_util`` module - with an ``unpack_archive()`` API. These were split out of EasyInstall to - allow reuse by other tools and applications. - - * ``setuptools.Command`` now supports reinitializing commands using keyword - arguments to set/reset options. Also, ``Command`` subclasses can now set - their ``command_consumes_arguments`` attribute to ``True`` in order to - receive an ``args`` option containing the rest of the command line. - 0.4a1 * Added ``--scan-url`` and ``--index-url`` options, to scan download pages and search PyPI for needed packages. - * Fixed a bug in requirements processing for exact versions (i.e. ``==`` and - ``!=``) when only one condition was included. - - * Added ``safe_name()`` and ``safe_version()`` APIs to clean up handling of - arbitrary distribution names and versions found on PyPI. - 0.3a4 - * ``pkg_resources`` now supports resource directories, not just the resources - in them. In particular, there are ``resource_listdir()`` and - ``resource_isdir()`` APIs. - - * ``pkg_resources`` now supports "egg baskets" -- .egg zipfiles which contain - multiple distributions in subdirectories whose names end with ``.egg``. - Having such a "basket" in a directory on ``sys.path`` is equivalent to - having the individual eggs in that directory, but the contained eggs can - be individually added (or not) to ``sys.path``. Currently, however, there - is no automated way to create baskets. - - * Namespace package manipulation is now protected by the Python import lock. - * Restrict ``--build-directory=DIR/-b DIR`` option to only be used with single URL installs, to avoid running the wrong setup.py. @@ -723,15 +580,10 @@ * Added more workarounds for packages with quirky ``install_data`` hacks - 0.3a2 * Added subversion download support for ``svn:`` and ``svn+`` URLs, as well as automatic recognition of HTTP subversion URLs (Contributed by Ian Bicking) - * Added new options to ``bdist_egg`` to allow tagging the egg's version number - with a subversion revision number, the current date, or an explicit tag - value. Run ``setup.py bdist_egg --help`` to get more information. - * Misc. bug fixes 0.3a1 Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- setup.py 7 Jul 2005 16:28:43 -0000 1.21 +++ setup.py 8 Jul 2005 15:13:14 -0000 1.22 @@ -1,33 +1,34 @@ #!/usr/bin/env python """Distutils setup file, used to install or test 'setuptools'""" +def get_description(): + # Get our long description from the documentation + f = file('setuptools.txt') + lines = [] + for line in f: + if not line.strip(): + break # skip to first blank line + for line in f: + if line.startswith('.. contents::'): + break # read to table of contents + lines.append(line) + f.close() + return ''.join(lines) + VERSION = "0.5a7" -from setuptools import setup, find_packages, Require +from setuptools import setup, find_packages, Require setup( name="setuptools", version=VERSION, - description="Download, build, install, upgrade, and uninstall Python " "packages -- easily!", - author="Phillip J. Eby", author_email="peak at eby-sarna.com", license="PSF or ZPL", - long_description = - "Setuptools enhances the distutils with support for Python Eggs " - "(http://peak.telecommunity.com/DevCenter/PythonEggs) and more. Its " - "'EasyInstall' tool " - "(http://peak.telecommunity.com/DevCenter/EasyInstall) lets you " - "download and install (or cleanly upgrade) Python packages on your " - "system, from source distributions, subversion checkouts, SourceForge " - "download mirrors, or from Python Eggs. Been looking for a CPAN " - "clone for Python? When combined with PyPI, this gets pretty darn " - "close. See the home page and download page for details and docs.", - + long_description = get_description(), keywords = "CPAN PyPI distutils eggs package management", url = "http://peak.telecommunity.com/DevCenter/EasyInstall", - test_suite = 'setuptools.tests.test_suite', requires = [ Require('Distutils','1.0.3','distutils', @@ -38,7 +39,6 @@ - packages = find_packages(), py_modules = ['pkg_resources'], scripts = ['easy_install.py'], From pje at users.sourceforge.net Fri Jul 8 17:49:56 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 08:49:56 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command alias.py, 1.3, 1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22808/setuptools/command Modified Files: alias.py Log Message: Cleaner argument quoting in command aliases. Index: alias.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/alias.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- alias.py 8 Jul 2005 15:11:19 -0000 1.3 +++ alias.py 8 Jul 2005 15:49:53 -0000 1.4 @@ -5,6 +5,15 @@ from distutils.errors import * from setuptools.command.setopt import edit_config, option_base, config_file +def shquote(arg): + """Quote an argument for later parsing by shlex.split()""" + for c in '"', "'", "\\", "#": + if c in arg: return repr(arg) + if arg.split()<>[arg]: + return repr(arg) + return arg + + class alias(option_base): """Define a shortcut that invokes one or more commands""" @@ -17,13 +26,11 @@ boolean_options = option_base.boolean_options + ['remove'] - def initialize_options(self): option_base.initialize_options(self) self.args = None self.remove = None - def finalize_options(self): option_base.finalize_options(self) if self.remove and len(self.args)<>1: @@ -32,13 +39,6 @@ "using --remove" ) - - - - - - - def run(self): aliases = self.distribution.get_option_dict('aliases') @@ -61,7 +61,7 @@ return else: alias = self.args[0] - command = ' '.join(map(repr,self.args[1:])) + command = ' '.join(map(shquote,self.args[1:])) edit_config(self.filename, {'aliases': {alias:command}}, self.dry_run) From pje at users.sourceforge.net Fri Jul 8 17:50:34 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 08:50:34 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command setopt.py, 1.2, 1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23000/setuptools/command Modified Files: setopt.py Log Message: Delete empty sections when their last option is deleted. Index: setopt.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/setopt.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- setopt.py 8 Jul 2005 05:09:23 -0000 1.2 +++ setopt.py 8 Jul 2005 15:50:32 -0000 1.3 @@ -51,10 +51,9 @@ log.debug("Reading configuration from %s", filename) opts = RawConfigParser() opts.read([filename]) - for section, options in settings.items(): if options is None: - log.debug("Deleting section [%s] from %s", section, filename) + log.info("Deleting section [%s] from %s", section, filename) opts.remove_section(section) else: if not opts.has_section(section): @@ -66,6 +65,10 @@ section, option, filename ) opts.remove_option(section,option) + if not opts.options(section): + log.info("Deleting empty [%s] section from %s", + section, filename) + opts.remove_section(section) else: log.debug( "Setting %s.%s to %r in %s", @@ -75,10 +78,7 @@ log.info("Writing %s", filename) if not dry_run: - f = open(filename,'w') - opts.write(f) - f.close() - + f = open(filename,'w'); opts.write(f); f.close() class option_base(Command): """Abstract base class for commands that mess with config files""" From pje at users.sourceforge.net Fri Jul 8 17:52:12 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 08:52:12 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.13, 1.14 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23997/setuptools Modified Files: __init__.py Log Message: Doc and other updates for 0.5a8 release. Add project aliases for source and binary register+upload. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- __init__.py 7 Jul 2005 16:28:43 -0000 1.13 +++ __init__.py 8 Jul 2005 15:52:05 -0000 1.14 @@ -8,7 +8,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a7' +__version__ = '0.5a8' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', From pje at users.sourceforge.net Fri Jul 8 17:52:12 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 08:52:12 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools setup.cfg, NONE, 1.1 EasyInstall.txt, 1.29, 1.30 ez_setup.py, 1.13, 1.14 setup.py, 1.22, 1.23 setuptools.txt, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23997 Modified Files: EasyInstall.txt ez_setup.py setup.py setuptools.txt Added Files: setup.cfg Log Message: Doc and other updates for 0.5a8 release. Add project aliases for source and binary register+upload. --- NEW FILE: setup.cfg --- [aliases] source = register sdist binary binary = bdist_egg upload --show-response Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.29 retrieving revision 1.30 diff -u -d -r1.29 -r1.30 --- EasyInstall.txt 8 Jul 2005 15:13:14 -0000 1.29 +++ EasyInstall.txt 8 Jul 2005 15:52:03 -0000 1.30 @@ -13,6 +13,11 @@ can do that from the `User Preferences `_ page. Thanks!) +(Also, if you'd like to learn about how you can use ``setuptools`` to make your +own packages work better with EasyInstall, or provide EasyInstall-like features +without requiring your users to use EasyInstall directly, you'll probably want +to check out the full `setuptools`_ documentation as well.) + .. contents:: **Table of Contents** @@ -24,7 +29,7 @@ ------------------------- Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py `_, and run it; this will download and install the appropriate ``setuptools`` egg for your Python @@ -65,7 +70,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a7" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a8" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: @@ -490,6 +495,12 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. +0.5a8 + * There is now a separate documentation page for `setuptools`_; revision + history that's not specific to EasyInstall has been moved to that page. + + .. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools + 0.5a5 * Made ``easy_install`` a standard ``setuptools`` command, moving it from the ``easy_install`` module to ``setuptools.command.easy_install``. Note @@ -587,7 +598,7 @@ * Misc. bug fixes 0.3a1 - Initial release. + * Initial release. Future Plans Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- ez_setup.py 7 Jul 2005 16:38:31 -0000 1.13 +++ ez_setup.py 8 Jul 2005 15:52:05 -0000 1.14 @@ -14,7 +14,7 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a7" +DEFAULT_VERSION = "0.5a8" DEFAULT_URL = "http://www.python.org/packages/source/s/setuptools/" import sys, os Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- setup.py 8 Jul 2005 15:13:14 -0000 1.22 +++ setup.py 8 Jul 2005 15:52:05 -0000 1.23 @@ -15,7 +15,7 @@ f.close() return ''.join(lines) -VERSION = "0.5a7" +VERSION = "0.5a8" from setuptools import setup, find_packages, Require setup( @@ -28,7 +28,7 @@ license="PSF or ZPL", long_description = get_description(), keywords = "CPAN PyPI distutils eggs package management", - url = "http://peak.telecommunity.com/DevCenter/EasyInstall", + url = "http://peak.telecommunity.com/DevCenter/setuptools", test_suite = 'setuptools.tests.test_suite', requires = [ Require('Distutils','1.0.3','distutils', Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- setuptools.txt 8 Jul 2005 15:13:14 -0000 1.1 +++ setuptools.txt 8 Jul 2005 15:52:05 -0000 1.2 @@ -63,7 +63,7 @@ ========================= Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py`_ and run it; this will download and install the appropriate egg for your Python version. @@ -695,5 +695,5 @@ * Misc. bug fixes 0.3a1 - Initial release. + * Initial release. From birkenfeld at users.sourceforge.net Fri Jul 8 23:36:39 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 08 Jul 2005 14:36:39 -0700 Subject: [Python-checkins] python/dist/src/Doc/tut tut.tex,1.274,1.275 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10989/Doc/tut Modified Files: tut.tex Log Message: bug [ 969757 ] function and method objects confounded in Tutorial Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.274 retrieving revision 1.275 diff -u -d -r1.274 -r1.275 --- tut.tex 28 Jun 2005 00:16:08 -0000 1.274 +++ tut.tex 8 Jul 2005 21:36:36 -0000 1.275 @@ -3888,7 +3888,7 @@ \end{verbatim} then \code{MyClass.i} and \code{MyClass.f} are valid attribute -references, returning an integer and a method object, respectively. +references, returning an integer and a function object, respectively. Class attributes can also be assigned to, so you can change the value of \code{MyClass.i} by assignment. \member{__doc__} is also a valid attribute, returning the docstring belonging to the class: \code{"A From birkenfeld at users.sourceforge.net Fri Jul 8 23:36:44 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 08 Jul 2005 14:36:44 -0700 Subject: [Python-checkins] python/dist/src/Doc/tut tut.tex, 1.261.2.9, 1.261.2.10 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/tut In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11018/Doc/tut Modified Files: Tag: release24-maint tut.tex Log Message: backport bug [ 969757 ] function and method objects confounded in Tutorial Index: tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.261.2.9 retrieving revision 1.261.2.10 diff -u -d -r1.261.2.9 -r1.261.2.10 --- tut.tex 28 Jun 2005 00:18:10 -0000 1.261.2.9 +++ tut.tex 8 Jul 2005 21:36:42 -0000 1.261.2.10 @@ -3888,7 +3888,7 @@ \end{verbatim} then \code{MyClass.i} and \code{MyClass.f} are valid attribute -references, returning an integer and a method object, respectively. +references, returning an integer and a function object, respectively. Class attributes can also be assigned to, so you can change the value of \code{MyClass.i} by assignment. \member{__doc__} is also a valid attribute, returning the docstring belonging to the class: \code{"A From birkenfeld at users.sourceforge.net Sat Jul 9 00:25:36 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 08 Jul 2005 15:25:36 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS, 1.1193.2.59, 1.1193.2.60 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5062/Misc Modified Files: Tag: release24-maint NEWS Log Message: backport bug [ 1234979 ] Lock.acquire treats only 1 as True Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.59 retrieving revision 1.1193.2.60 diff -u -d -r1.1193.2.59 -r1.1193.2.60 --- NEWS 4 Jul 2005 17:16:53 -0000 1.1193.2.59 +++ NEWS 8 Jul 2005 22:25:17 -0000 1.1193.2.60 @@ -29,6 +29,9 @@ Extension Modules ----------------- +- Bug #1234979: For the argument of thread.Lock.acquire, the Windows + implemented treated all integer values except 1 as false. + - Bug #1194181: bz2.BZ2File didn't handle mode 'U' correctly. - Bug #1166660: The readline module could segfault if hook functions From birkenfeld at users.sourceforge.net Sat Jul 9 00:25:50 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 08 Jul 2005 15:25:50 -0700 Subject: [Python-checkins] python/dist/src/Python thread_nt.h, 2.23, 2.23.10.1 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5062/Python Modified Files: Tag: release24-maint thread_nt.h Log Message: backport bug [ 1234979 ] Lock.acquire treats only 1 as True Index: thread_nt.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/thread_nt.h,v retrieving revision 2.23 retrieving revision 2.23.10.1 diff -u -d -r2.23 -r2.23.10.1 --- thread_nt.h 4 Jul 2003 04:40:45 -0000 2.23 +++ thread_nt.h 8 Jul 2005 22:25:17 -0000 2.23.10.1 @@ -299,7 +299,7 @@ dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); - success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag == 1 ? INFINITE : 0)) == WAIT_OBJECT_0 ; + success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag ? INFINITE : 0)) == WAIT_OBJECT_0 ; dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); From birkenfeld at users.sourceforge.net Sat Jul 9 00:26:15 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 08 Jul 2005 15:26:15 -0700 Subject: [Python-checkins] python/dist/src/Python thread_nt.h,2.23,2.24 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5550/Python Modified Files: thread_nt.h Log Message: bug [ 1234979 ] Lock.acquire treats only 1 as True Index: thread_nt.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/thread_nt.h,v retrieving revision 2.23 retrieving revision 2.24 diff -u -d -r2.23 -r2.24 --- thread_nt.h 4 Jul 2003 04:40:45 -0000 2.23 +++ thread_nt.h 8 Jul 2005 22:26:12 -0000 2.24 @@ -299,7 +299,7 @@ dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); - success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag == 1 ? INFINITE : 0)) == WAIT_OBJECT_0 ; + success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag ? INFINITE : 0)) == WAIT_OBJECT_0 ; dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); From birkenfeld at users.sourceforge.net Sat Jul 9 00:26:15 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 08 Jul 2005 15:26:15 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1310,1.1311 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5550/Misc Modified Files: NEWS Log Message: bug [ 1234979 ] Lock.acquire treats only 1 as True Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1310 retrieving revision 1.1311 diff -u -d -r1.1310 -r1.1311 --- NEWS 5 Jul 2005 15:21:55 -0000 1.1310 +++ NEWS 8 Jul 2005 22:26:13 -0000 1.1311 @@ -103,6 +103,9 @@ Extension Modules ----------------- +- Bug #1234979: For the argument of thread.Lock.acquire, the Windows + implemented treated all integer values except 1 as false. + - Bug #1194181: bz2.BZ2File didn't handle mode 'U' correctly. - Patch #1212117: os.stat().st_flags is now accessible as a attribute From pje at users.sourceforge.net Sat Jul 9 06:21:36 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 21:21:36 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command sdist.py, 1.3, 1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30120/setuptools/command Modified Files: sdist.py Log Message: Include ``svn:externals`` directories in source distributions as well as normal subversion-controlled files and directories. Index: sdist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/sdist.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- sdist.py 8 Jul 2005 05:09:23 -0000 1.3 +++ sdist.py 9 Jul 2005 04:21:22 -0000 1.4 @@ -6,15 +6,23 @@ ("<","<"), (">", ">"), (""", '"'), ("'", "'"), ("&", "&") ] + def unescape(data): for old,new in entities: data = data.replace(old,new) return data -patterns = [ - (convert_path('CVS/Entries'), re.compile(r"^\w?/([^/]+)/", re.M), None), - (convert_path('.svn/entries'), re.compile(r'name="([^"]+)"'), unescape), -] +def re_finder(pattern, postproc=None): + def find(dirname, filename): + f = open(filename,'rU') + data = f.read() + f.close() + for match in pattern.finditer(data): + path = match.group(1) + if postproc: + path = postproc(path) + yield joinpath(dirname,path) + return find def joinpath(prefix,suffix): if not prefix: @@ -31,14 +39,6 @@ - - - - - - - - def walk_revctrl(dirname='', memo=None): """Find all files under revision control""" if memo is None: @@ -46,38 +46,47 @@ if dirname in memo: # Don't rescan a scanned directory return - for path, pattern, postproc in patterns: + for path, finder in finders: path = joinpath(dirname,path) if os.path.isfile(path): - f = open(path,'rU') - data = f.read() - f.close() - for match in pattern.finditer(data): - path = match.group(1) - if postproc: - path = postproc(path) - path = joinpath(dirname,path) + for path in finder(dirname,path): if os.path.isfile(path): yield path elif os.path.isdir(path): for item in walk_revctrl(path, memo): yield item +def externals_finder(dirname, filename): + """Find any 'svn:externals' directories""" + found = False + f = open(filename,'rb') + for line in iter(f.readline, ''): # can't use direct iter! + parts = line.split() + if len(parts)==2: + kind,length = parts + data = f.read(int(length)) + if kind=='K' and data=='svn:externals': + found = True + elif kind=='V' and found: + f.close() + break + else: + f.close() + return + for line in data.splitlines(): + parts = line.split() + if parts: + yield joinpath(dirname, parts[0]) - - - - - - - - - - - - +finders = [ + (convert_path('CVS/Entries'), + re_finder(re.compile(r"^\w?/([^/]+)/", re.M))), + (convert_path('.svn/entries'), + re_finder(re.compile(r'name="([^"]+)"'), unescape)), + (convert_path('.svn/dir-props'), externals_finder), +] class sdist(_sdist): @@ -112,12 +121,3 @@ - - - - - - - - - From pje at users.sourceforge.net Sat Jul 9 06:24:40 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 21:24:40 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.14, 1.15 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32506/setuptools Modified Files: __init__.py Log Message: Added ``exclude=patternlist`` option to ``setuptools.find_packages()`` Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- __init__.py 8 Jul 2005 15:52:05 -0000 1.14 +++ __init__.py 9 Jul 2005 04:24:38 -0000 1.15 @@ -1,5 +1,4 @@ """Extensions to the 'distutils' for large or complex distributions""" - import distutils.core, setuptools.command from setuptools.dist import Distribution, Feature from setuptools.extension import Extension @@ -9,7 +8,6 @@ import os.path __version__ = '0.5a8' - __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', 'find_packages' @@ -17,16 +15,17 @@ bootstrap_install_from = None -def find_packages(where='.'): +def find_packages(where='.', exclude=()): """Return a list all Python packages found within directory 'where' 'where' should be supplied as a "cross-platform" (i.e. URL-style) path; it - will be converted to the appropriate local path syntax. + will be converted to the appropriate local path syntax. 'exclude' is a + sequence of package names to exclude; '*' can be used as a wildcard in the + names, such that 'foo.*' will exclude all subpackages of 'foo' (but not + 'foo' itself). """ - out = [] stack=[(convert_path(where), '')] - while stack: where,prefix = stack.pop(0) for name in os.listdir(where): @@ -35,10 +34,11 @@ os.path.isfile(os.path.join(fn,'__init__.py')) ): out.append(prefix+name); stack.append((fn,prefix+name+'.')) + for pat in exclude: + from fnmatch import fnmatchcase + out = [item for item in out if not fnmatchcase(item,pat)] return out - - def setup(**attrs): """Do package setup From pje at users.sourceforge.net Sat Jul 9 06:25:52 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 21:25:52 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command bdist_egg.py, 1.21, 1.22 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv738/setuptools/command Modified Files: bdist_egg.py Log Message: Fix typos in option specs for bdist_egg. Index: bdist_egg.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/bdist_egg.py,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- bdist_egg.py 6 Jul 2005 01:37:41 -0000 1.21 +++ bdist_egg.py 9 Jul 2005 04:25:49 -0000 1.22 @@ -52,14 +52,14 @@ ('keep-temp', 'k', "keep the pseudo-installation tree around after " + "creating the distribution archive"), - ('dist-dir=', 'd', + ('dist-dir=', 'b', "directory to put final built distributions in"), ('skip-build', None, "skip rebuilding everything (for testing/debugging)"), ] boolean_options = [ - 'keep-temp', 'skip-build', 'relative','tag-date','tag-svn-revision' + 'keep-temp', 'skip-build', ] From pje at users.sourceforge.net Sat Jul 9 06:26:24 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 21:26:24 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command upload.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv916/setuptools/command Modified Files: upload.py Log Message: Add informative comment when uploading eggs, to help distinguish them from source archives. Index: upload.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/upload.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- upload.py 7 Jul 2005 16:28:43 -0000 1.1 +++ upload.py 9 Jul 2005 04:26:21 -0000 1.2 @@ -75,8 +75,10 @@ basename = os.path.basename(filename) if basename.endswith('.egg'): basename += '.zip' + comment = '' if command=='bdist_egg': command='sdist' + comment='Binary egg for use with setuptools' data = { ':action':'file_upload', 'protcol_version':'1', @@ -87,7 +89,6 @@ 'pyversion':pyversion, 'md5_digest':md5(content).hexdigest(), } - comment = '' if command == 'bdist_rpm': dist, version, id = platform.dist() if dist: From pje at users.sourceforge.net Sat Jul 9 06:27:41 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Fri, 08 Jul 2005 21:27:41 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools setup.py, 1.23, 1.24 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1406 Modified Files: setup.py Log Message: Remove old-style requirements from setup.py, to avoid confusing people who look to it for an example of setuptools use. Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- setup.py 8 Jul 2005 15:52:05 -0000 1.23 +++ setup.py 9 Jul 2005 04:27:38 -0000 1.24 @@ -17,7 +17,8 @@ VERSION = "0.5a8" -from setuptools import setup, find_packages, Require +from setuptools import setup, find_packages + setup( name="setuptools", version=VERSION, @@ -30,19 +31,14 @@ keywords = "CPAN PyPI distutils eggs package management", url = "http://peak.telecommunity.com/DevCenter/setuptools", test_suite = 'setuptools.tests.test_suite', - requires = [ - Require('Distutils','1.0.3','distutils', - "http://www.python.org/sigs/distutils-sig/" - ), - Require('PyUnit', None, 'unittest', "http://pyunit.sf.net/"), - ], - - packages = find_packages(), py_modules = ['pkg_resources'], scripts = ['easy_install.py'], + + + classifiers = [f.strip() for f in """ Development Status :: 3 - Alpha Intended Audience :: Developers @@ -80,3 +76,7 @@ + + + + From birkenfeld at users.sourceforge.net Sat Jul 9 17:26:35 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 09 Jul 2005 08:26:35 -0700 Subject: [Python-checkins] python/dist/src/Python thread_wince.h,2.7,2.8 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16410/Python Modified Files: thread_wince.h Log Message: bug 1234979 addition Index: thread_wince.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/thread_wince.h,v retrieving revision 2.7 retrieving revision 2.8 diff -u -d -r2.7 -r2.8 --- thread_wince.h 16 Oct 2001 21:13:49 -0000 2.7 +++ thread_wince.h 9 Jul 2005 15:26:33 -0000 2.8 @@ -140,13 +140,13 @@ dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); #ifndef DEBUG - waitResult = WaitForSingleObject(aLock, (waitflag == 1 ? INFINITE : 0)); + waitResult = WaitForSingleObject(aLock, (waitflag ? INFINITE : 0)); #else /* To aid in debugging, we regularly wake up. This allows us to break into the debugger */ while (TRUE) { waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0); - if (waitflag==0 || (waitflag==1 && waitResult == WAIT_OBJECT_0)) + if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0)) break; } #endif From birkenfeld at users.sourceforge.net Sat Jul 9 17:27:07 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 09 Jul 2005 08:27:07 -0700 Subject: [Python-checkins] python/dist/src/Python thread_wince.h, 2.7, 2.7.30.1 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16465/Python Modified Files: Tag: release24-maint thread_wince.h Log Message: bug 1234979 addition Index: thread_wince.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/thread_wince.h,v retrieving revision 2.7 retrieving revision 2.7.30.1 diff -u -d -r2.7 -r2.7.30.1 --- thread_wince.h 16 Oct 2001 21:13:49 -0000 2.7 +++ thread_wince.h 9 Jul 2005 15:27:05 -0000 2.7.30.1 @@ -140,13 +140,13 @@ dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); #ifndef DEBUG - waitResult = WaitForSingleObject(aLock, (waitflag == 1 ? INFINITE : 0)); + waitResult = WaitForSingleObject(aLock, (waitflag ? INFINITE : 0)); #else /* To aid in debugging, we regularly wake up. This allows us to break into the debugger */ while (TRUE) { waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0); - if (waitflag==0 || (waitflag==1 && waitResult == WAIT_OBJECT_0)) + if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0)) break; } #endif From pje at users.sourceforge.net Sat Jul 9 18:25:56 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 09:25:56 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command egg_info.py, 1.3, 1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17594/setuptools/command Modified Files: egg_info.py Log Message: Changed --tag-svn-revision to include an "r" in front of the revision number for better readability. Index: egg_info.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/egg_info.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- egg_info.py 8 Jul 2005 04:45:58 -0000 1.3 +++ egg_info.py 9 Jul 2005 16:25:54 -0000 1.4 @@ -127,7 +127,7 @@ version+=self.tag_build if self.tag_svn_revision and os.path.exists('.svn'): - version += '-%s' % self.get_svn_revision() + version += '-r%s' % self.get_svn_revision() if self.tag_date: import time From pje at users.sourceforge.net Sat Jul 9 18:27:33 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 09:27:33 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools setuptools.txt, 1.2, 1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18808 Modified Files: setuptools.txt Log Message: Added command reference to documentation. Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- setuptools.txt 8 Jul 2005 15:52:05 -0000 1.2 +++ setuptools.txt 9 Jul 2005 16:27:23 -0000 1.3 @@ -28,17 +28,18 @@ a single-file importable distribution format * Include data files inside your package directories, where your code can - actually use them. (Python 2.4 distutils includes this feature already, but - setuptools provides the feature for Python 2.3 packages also.) + actually use them. (Python 2.4 distutils also supports this feature, but + setuptools provides the feature for Python 2.3 packages also, and supports + accessing data files in zipped packages too.) * Automatically include all packages in your source tree, without listing them individually in setup.py * Automatically include all relevant files in your source distributions, - without needing to create a MANIFEST.in and without having to force MANIFEST - regeneration + without needing to create a ``MANIFEST.in`` file, and without having to force + regeneration of the ``MANIFEST`` file when your source tree changes. -* Transparent Pyrex support, so that your setup.py can list .pyx files and +* Transparent Pyrex support, so that your setup.py can list ``.pyx`` files and still work even when the end-user doesn't have Pyrex installed (as long as you include the Pyrex-generated C in your source distribution) @@ -47,8 +48,8 @@ * PyPI upload support - upload your source distributions and eggs to PyPI -* Put your package in "development mode", such that it's available on sys.path, - yet you can still edit it directly from your source checkout. +* Deploy your project in "development mode", such that it's available on + ``sys.path``, yet can still be edited directly from its source checkout. .. contents:: **Table of Contents** @@ -90,8 +91,8 @@ As you can see, it doesn't take much to use setuptools in a project. Just by doing the above, this project will be able to produce eggs, upload to PyPI, and automatically include all packages in the directory where the -setup.py lives. See the sections below on `Enhanced Commands`_ and `New -Commands`_ to see what commands you can give to this setup.py. +setup.py lives. See the `Command Reference`_ section below to see what +commands you can give to this setup script. Of course, before you release your project to PyPI, you'll want to add a bit more information to your setup script to help people find or learn about your @@ -127,7 +128,10 @@ # could also include long_description, download_url, classifiers, etc. ) -In the following sections, we'll explain what most of these +In the sections that follow, we'll explain what most of these ``setup()`` +arguments do (except for the metadata ones), and the various ways you might use +them in your own project(s). + Declaring Dependencies ====================== @@ -268,9 +272,7 @@ version of ``setuptools`` from PyPI, if it isn't present on the target system. Whenever you install an updated version of setuptools, you should also update your projects' ``ez_setup.py`` files, so that a matching version gets installed -on the target machine(s). If you're using Subversion, you may wish to use -"externals" to make all your projects share a single ``ez_setup.py``, so that -you only have to update it in one place to update all your projects. +on the target machine(s). By the way, setuptools supports the new PyPI "upload" command, so you can use ``setup.py sdist upload`` or ``setup.py bdist_egg upload`` to upload your @@ -282,6 +284,43 @@ found by other projects that depend on them. +Managing Multiple Projects +-------------------------- + +If you're managing several projects that need to use ``ez_setup``, and you are +using Subversion as your revision control system, you can use the +"svn:externals" property to share a single copy of ``ez_setup`` between +projects, so that it will always be up-to-date whenever you check out or update +an individual project, without having to manually update each project to use +a new version. + +However, because Subversion only supports using directories as externals, you +have to turn ``ez_setup.py`` into ``ez_setup/__init__.py`` in order to do this, +then create "externals" definitions that map the ``ez_setup`` directory into +each project. Also, if any of your projects use ``find_packages()`` on their +setup directory, you will need to exclude the resulting ``ez_setup`` package, +to keep it from being included in your distributions, e.g.:: + + setup( + ... + packages = find_packages(exclude=['ez_setup']), + ) + +Of course, the ``ez_setup`` package will still be included in your packages' +source distributions, as it needs to be. + +For your convenience, you may use the following external definition, which will +track the latest version of setuptools:: + + ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup + +You can set this by executing this command in your project directory:: + + svn propedit svn:externals . + +And then adding the line shown above to the file that comes up for editing. + + Including Data Files ==================== @@ -373,16 +412,63 @@ "Development Mode" ================== -Sorry, this section isn't written yet, and neither is anything below this -point except the changelog. You might want to `subscribe to changes in this -page `_ to see when the documentation is added or -updated. +Under normal circumstances, the ``distutils`` assume that you are going to +build a distribution of your project, not use it in its "raw" or "unbuilt" +form. If you were to use the ``distutils`` that way, you would have to rebuild +and reinstall your project every time you made a change to it during +development. + +Another problem that sometimes comes up with the ``distutils`` is that you may +need to do development on two related projects at the same time. You may need +to put both projects' packages in the same directory to run them, but need to +keep them separate for revision control purposes. How can you do this? + +Setuptools allows you to deploy your projects for use in a common directory or +staging area, but without copying any files. Thus, you can edit each project's +code in its checkout directory, and only need to run build commands when you +change a project's C extensions or similarly compiled files. You can even +deploy a project into another project's checkout directory, if that's your +preferred way of working (as opposed to using a common independent staging area +or the site-packages directory). + +To do this, use the ``setup.py develop`` command. It works very similarly to +``setup.py install`` or the EasyInstall tool, except that it doesn't actually +install anything. Instead, it creates a special ``.egg-link`` file in the +deployment directory, that links to your project's source code. And, if your +deployment directory is Python's ``site-packages`` directory, it will also +update the ``easy-install.pth`` file to include your project's source code, +thereby making it available on ``sys.path`` for all programs using that Python +installation. + +In addition, the ``develop`` command creates wrapper scripts in the target +script directory that will run your in-development scripts after ensuring that +all your ``install_requires`` packages are available on ``sys.path``. + +You can deploy the same project to multiple staging areas, e.g. if you have +multiple projects on the same machine that are sharing the same project you're +doing development work. + +When you're done with a given development task, you can remove the project +source from a staging area using ``setup.py develop --uninstall``, specifying +the desired staging area if it's not the default. + +There are several options to control the precise behavior of the ``develop`` +command; see the section on the `develop`_ command below for more details. Tagging and "Daily Build" or "Snapshot" Releases ------------------------------------------------- +================================================ -XXX +Sorry, this section isn't written yet, and neither are the next few sections, +until you get to the `Command Reference`_ section below. You might want to +`subscribe to changes in this page `_ to see when +new documentation is added or updated. + + +Generating Source Distributions +=============================== + +XXX ``sdist`` - auto-include files from CVS or Subversion Using ``find_packages()`` @@ -398,98 +484,525 @@ ----------------- -Enhanced Commands +Command Reference ----------------- +.. _alias: -``build_ext`` - automatic support for Pyrex extensions -====================================================== +``alias`` - Define shortcuts for commonly used commands +======================================================= -XXX +Sometimes, you need to use the same commands over and over, but you can't +necessarily set them as defaults. For example, if you produce both development +snapshot releases and "stable" releases of a project, you may want to put +the distributions in different places, or use different ``egg_info`` tagging +options, etc. In these cases, it doesn't make sense to set the options in +a distutils configuration file, because the values of the options changed based +on what you're trying to do. +Setuptools therefore allows you to define "aliases" - shortcut names for +an arbitrary string of commands and options, using ``setup.py alias aliasname +expansion``, where aliasname is the name of the new alias, and the remainder of +the command line supplies its expansion. For example, this command defines +a sitewide alias called "daily", that sets various ``egg_info`` tagging +options:: -``bdist, sdist`` - added support for "daily" or "special" build tagging -======================================================================= + setup.py alias --global-config daily egg_info --tag-svn-revision \ + --tag-build=development -XXX +Once the alias is defined, it can then be used with other setup commands, +e.g.:: + setup.py daily bdist_egg # generate a daily-build .egg file + setup.py daily sdist # generate a daily-build source distro + setup.py daily sdist bdist_egg # generate both -``sdist`` - auto-include files from CVS or Subversion -====================================================== +The above commands are interpreted as if the word ``daily`` were replaced with +``egg_info --tag-svn-revision --tag-build=development``. -XXX +Note that setuptools will expand each alias *at most once* in a given command +line. This serves two purposes. First, if you accidentally create an alias +loop, it will have no effect; you'll instead get an error message about an +unknown command. Second, it allows you to define an alias for a command, that +uses that command. For example, this (project-local) alias:: + setup.py alias bdist_egg bdist_egg rotate -k1 -m.egg -``upload`` - support uploading Python Eggs -========================================== +redefines the ``bdist_egg`` command so that it always runs the ``rotate`` +command afterwards to delete all but the newest egg file. It doesn't loop +indefinitely on ``bdist_egg`` because the alias is only expanded once when +used. -XXX +You can remove a defined alias with the ``--remove`` (or ``-r``) option, e.g.:: + setup.py alias --global-config --remove daily +would delete the "daily" alias we defined above. ------------- -New Commands ------------- +Aliases can be defined on a project-specific, per-user, or sitewide basis. The +default is to define or remove a project-specific alias, but you can use any of +the `configuration file options`_ (listed under the `saveopts`_ command, below) +to determine which distutils configuration file an aliases will be added to +(or removed from). +Note that if you omit the "expansion" argument to the ``alias`` command, +you'll get output showing that alias' current definition (and what +configuration file it's defined in). If you omit the alias name as well, +you'll get a listing of all current aliases along with their configuration +file locations. -``alias`` - Define shortcuts for commonly used commands -======================================================= -XXX +``bdist_egg`` - Create a Python Egg for the project +=================================================== +This command generates a Python Egg (``.egg`` file) for the project. Python +Eggs are the preferred binary distribution format for EasyInstall, because they +are cross-platform (for "pure" packages), directly importable, and contain +project metadata including scripts and information about the project's +dependencies. They can be simply downloaded and added to ``sys.path`` +directly, or they can be placed in a directory on ``sys.path`` and then +automatically discovered by the egg runtime system. -``bdist_egg`` - Create a Python Egg for the package -=================================================== +This command runs the `egg_info`_ command (if it hasn't already run) to update +the project's metadata (``.egg-info``) directory. If you have added any extra +metadata files to the ``.egg-info`` directory, those files will be included in +the new egg file's metadata directory, for use by the egg runtime system or by +any applications or frameworks that use that metadata. -XXX +You won't usually need to specify any special options for this command; just +use ``bdist_egg`` and you're done. But there are a couple of options that may +be occasionally useful: +``--dist-dir=DIR, -d DIR`` + Set the directory where the ``.egg`` file will be placed. If you don't + supply this, then the ``--dist-dir`` setting of the ``bdist`` command + will be used, which is usually a directory named ``dist`` in the project + directory. -``develop`` - "Install" the source package in-place -=================================================== +``--plat-name=PLATFORM, -p PLATFORM`` + Set the platform name string that will be embedded in the egg's filename + (assuming the egg contains C extensions). This can be used to override + the distutils default platform name with something more meaningful. Keep + in mind, however, that the egg runtime system expects to see eggs with + distutils platform names, so it may ignore or reject eggs with non-standard + platform names. Similarly, the EasyInstall program may ignore them when + searching web pages for download links. However, if you are + cross-compiling or doing some other unusual things, you might find a use + for this option. + +There are also some options you will probably never need, but which are there +because they were copied from similar ``bdist`` commands used as an example for +creating this one. They may be useful for testing and debugging, however, +which is why we kept them: + +``--keep-temp, -k`` + Keep the contents of the ``--bdist-dir`` tree around after creating the + ``.egg`` file. + +``--bdist-dir=DIR, -b DIR`` + Set the temporary directory for creating the distribution. The entire + contents of this directory are zipped to create the ``.egg`` file, after + running various installation commands to copy the package's modules, data, + and extensions here. + +``--skip-build`` + Skip doing any "build" commands; just go straight to the + install-and-compress phases. + + +.. _develop: + +``develop`` - Deploy the project source in "Development Mode" +============================================================= + +This command allows you to deploy your project's source for use in one or more +"staging areas" where it will be available for importing. This deployment is +done in such a way that changes to the project source are immediately available +in the staging area(s), without needing to run a build or install step after +each change. + +The ``develop`` command works by creating an ``.egg-link`` file (named for the +project) in the given staging area. If the staging area is Python's +``site-packages`` directory, it also updates an ``easy-install.pth`` file so +that the project is on ``sys.path`` by default for all programs run using that +Python installation. + +The ``develop`` command also installs wrapper scripts in the staging area (or +a separate directory, as specified) that will ensure the project's dependencies +are available on ``sys.path`` before running the project's source scripts. +And, it ensures that any missing project dependencies are available in the +staging area, by downloading and installing them if necessary. + +Last, but not least, the ``develop`` command invokes the ``build_ext -i`` +command to ensure any C extensions in the project have been built and are +up-to-date, and the ``egg_info`` command to ensure the project's metadata is +updated (so that the runtime and wrappers know what the project's dependencies +are). If you make changes to the project's metadata or C extensions, you +should rerun the ``develop`` command (or ``egg_info``, or ``build_ext -i``) in +order to keep the project up-to-date. If you add or rename any of the +project's scripts, you should re-run ``develop`` against all relevant staging +areas to update the wrapper scripts. Most other kinds of changes to your +project should not require any build operations or rerunning ``develop``. + +Here are the options that the ``develop`` command accepts. Note that they +affect the project's dependencies as well as the project itself, so if you have +dependencies that need to be installed and you use ``--exclude-scripts`` (for +example), the dependencies' scripts will not be installed either! For this +reason, you may want to use EasyInstall to install the project's dependencies +before using the ``develop`` command, if you need finer control over the +installation options for dependencies. + +``--uninstall, -u`` + Un-deploy the current project. You may use the ``--install-dir`` or ``-d`` + option to designate the staging area. The created ``.egg-link`` file will + be removed, if present and it is still pointing to the project directory. + The project directory will be removed from ``easy-install.pth`` if the + staging area is Python's ``site-packages`` directory. + + Note that this option currently does *not* uninstall script wrappers! You + must uninstall them yourself, or overwrite them by using EasyInstall to + activate a different version of the package. You can also avoid installing + script wrappers in the first place, if you use the ``--exclude-scripts`` + (aka ``-x``) option when you run ``develop`` to deploy the project. + +``--multi-version, -m`` + "Multi-version" mode. Specifying this option prevents ``develop`` from + adding an ``easy-install.pth`` entry for the project(s) being deployed, and + if an entry for any version of a project already exists, the entry will be + removed upon successful deployment. In multi-version mode, no specific + version of the package is available for importing, unless you use + ``pkg_resources.require()`` to put it on ``sys.path``, or you are running + a wrapper script generated by ``setuptools`` or EasyInstall. (In which + case the wrapper script calls ``require()`` for you.) + + Note that if you install to a directory other than ``site-packages``, + this option is automatically in effect, because ``.pth`` files can only be + used in ``site-packages`` (at least in Python 2.3 and 2.4). So, if you use + the ``--install-dir`` or ``-d`` option (or they are set via configuration + file(s)) your project and its dependencies will be deployed in multi- + version mode. + +``--install-dir=DIR, -d DIR`` + Set the installation directory (staging area). If this option is not + directly specified on the command line or in a distutils configuration + file, the distutils default installation location is used. Normally, this + will be the ``site-packages`` directory, but if you are using distutils + configuration files, setting things like ``prefix`` or ``install_lib``, + then those settings are taken into account when computing the default + staging area. + +``--script-dir=DIR, -s DIR`` + Set the script installation directory. If you don't supply this option + (via the command line or a configuration file), but you *have* supplied + an ``--install-dir`` (via command line or config file), then this option + defaults to the same directory, so that the scripts will be able to find + their associated package installation. Otherwise, this setting defaults + to the location where the distutils would normally install scripts, taking + any distutils configuration file settings into account. + +``--exclude-scripts, -x`` + Don't deploy script wrappers. This is useful if you don't want to disturb + existing versions of the scripts in the staging area. + +``--always-copy, -a`` + Copy all needed distributions to the staging area, even if they + are already present in another directory on ``sys.path``. By default, if + a requirement can be met using a distribution that is already available in + a directory on ``sys.path``, it will not be copied to the staging area. -XXX +.. _egg_info: ``egg_info`` - Create egg metadata and set build tags ===================================================== -XXX +This command performs two operations: it updates a project's ``.egg-info`` +metadata directory (used by the ``bdist_egg``, ``develop``, and ``test`` +commands), and it allows you to temporarily change a project's version string, +to support "daily builds" or "snapshot" releases. It is run automatically by +the ``sdist``, ``bdist_egg``, ``develop``, and ``test`` commands in order to +update the project's metadata, but you can also specify it explicitly in order +to temporarily change the project's version string. +The following options can be used to modify the project's version string for +all remaining commands on the setup command line. The options are processed +in the order shown, so if you use more than one, the request tags will be added +in the following order: -``easy_install`` - Find, download, and install other packages -============================================================= +``--tag-build=NAME, -b NAME`` + Append NAME to the project's version string. Due to the way setuptools + processes "pre-release" version suffixes beginning with the letters "a" + through "e" (like "alpha", "beta", and "candidate"), you will usually want + to use a tag like "build" or "dev", as this will cause the version number + to be considered *lower* than the project's default version. (If you + want to make the version number *higher* than the default version, you can + always leave off --tag-build and use one or both of the following options.) -XXX +``--tag-svn-revision, -r`` + If the current directory is a Subversion checkout (i.e. has a ``.svn`` + subdirectory, this appends a string of the form "-rNNNN" to the project's + version string, where NNNN is the revision number of the most recent + modification to the current directory, as obtained from the ``svn info`` + command. +``--tag-date, -d`` + Add a date stamp of the form "-YYYYMMDD" (e.g. "-20050528") to the + project's version number. -``test`` - Build package and run a unittest suite -================================================= +For advanced uses, there is one other option that can be set, to change the +location of the project's ``.egg-info`` directory. Commands that need to find +the project's source directory or metadata should get it from this setting: -XXX +``--egg-base=SOURCEDIR, -e SOURCEDIR`` + Specify the directory that should contain the .egg-info directory. This + should normally be the root of your project's source tree (which is not + necessarily the same as your project directory; some projects use a ``src`` + or ``lib`` subdirectory as the source root). You should not normally need + to specify this directory, as it is normally determined from the + ``package_dir`` argument to the ``setup()`` function, if any. If there is + no ``package_dir`` set, this option defaults to the current directory. ``rotate`` - Delete outdated distribution files =============================================== -XXX +As you develop new versions of your project, your distribution (``dist``) +directory will gradually fill up with older source and/or binary distribution +files. The ``rotate`` command lets you automatically clean these up, keeping +only the N most-recently modified files matching a given pattern. + +``--match=PATTERNLIST, -m PATTERNLIST`` + Comma-separated list of glob patterns to match. This option is *required*. + The project name and ``-*`` is prepended to the supplied patterns, in order + to match only distributions belonging to the current project (in case you + have a shared distribution directory for multiple projects). Typically, + you will use a glob pattern like ``.zip`` or ``.egg`` to match files of + the specified type. Note that each supplied pattern is treated as a + distinct group of files for purposes of selecting files to delete. + +``--keep=COUNT, -k COUNT`` + Number of matching distributions to keep. For each group of files + identified by a pattern specified with the ``--match`` option, delete all + but the COUNT most-recently-modified files in that group. This option is + *required*. + +``--dist-dir=DIR, -d DIR`` + Directory where the distributions are. This defaults to the value of the + ``bdist`` command's ``--dist-dir`` option, which will usually be the + project's ``dist`` subdirectory. + +**Example 1**: Delete all .tar.gz files from the distribution directory, except +for the 3 most recently modified ones:: + + setup.py rotate --match=.tar.gz --keep=3 + +**Example 2**: Delete all Python 2.3 or Python 2.4 eggs from the distribution +directory, except the most recently modified one for each Python version:: + + setup.py rotate --match=-py2.3*.egg,-py2.4*.egg --keep=1 +.. _saveopts: + ``saveopts`` - Save used options to a configuration file ======================================================== -XXX +Finding and editing ``distutils`` configuration files can be a pain, especially +since you also have to translate the configuration options from command-line +form to the proper configuration file format. You can avoid these hassles by +using the ``saveopts`` command. Just add it to the command line to save the +options you used. For example, this command builds the project using +the ``mingw32`` C compiler, then saves the --compiler setting as the default +for future builds (even those run implicitly by the ``install`` command):: + + setup.py build --compiler=mingw32 saveopts +The ``saveopts`` command saves all options for every commmand specified on the +command line to the project's local ``setup.cfg`` file, unless you use one of +the `configuration file options`_ to change where the options are saved. For +example, this command does the same as above, but saves the compiler setting +to the site-wide (global) distutils configuration:: + + setup.py build --compiler=mingw32 saveopts -g + +Note that it doesn't matter where you place the ``saveopts`` command on the +command line; it will still save all the options specified for all commands. +For example, this is another valid way to spell the last example:: + + setup.py saveopts -g build --compiler=mingw32 + +Note, however, that all of the commands specified are always run, regardless of +where ``saveopts`` is placed on the command line. + + +Configuration File Options +-------------------------- + +Normally, settings such as options and aliases are saved to the project's +local ``setup.cfg`` file. But you can override this and save them to the +global or per-user configuration files, or to a manually-specified filename. + +``--global-config, -g`` + Save settings to the global ``distutils.cfg`` file inside the ``distutils`` + package directory. You must have write access to that directory to use + this option. You also can't combine this option with ``-u`` or ``-f``. + +``--user-config, -u`` + Save settings to the current user's ``~/.pydistutils.cfg`` (POSIX) or + ``$HOME/pydistutils.cfg`` (Windows) file. You can't combine this option + with ``-g`` or ``-f``. + +``--filename=FILENAME, -f FILENAME`` + Save settings to the specified configuration file to use. You can't + combine this option with ``-g`` or ``-u``. Note that if you specify a + non-standard filename, the ``distutils`` and ``setuptools`` will not + use the file's contents. This option is mainly included for use in + testing. + +These options are used by other ``setuptools`` commands that modify +configuration files, such as the `alias`_ and `setopt`_ commands. + + +.. _setopt: ``setopt`` - Set a distutils or setuptools option in a config file ================================================================== -XXX +This command is mainly for use by scripts, but it can also be used as a quick +and dirty way to change a distutils configuration option without having to +remember what file the options are in and then open an editor. + +**Example 1**. Set the default C compiler to ``mingw32`` (using long option +names):: + + setup.py setopt --command=build --option=compiler --set-value=mingw32 + +**Example 2**. Remove any setting for the distutils default package +installation directory (short option names):: + + setup.py setopt -c install -o install_lib -r + + +Options for the ``setopt`` command: + +``--command=COMMAND, -c COMMAND`` + Command to set the option for. This option is required. + +``--option=OPTION, -o OPTION`` + The name of the option to set. This option is required. + +``--set-value=VALUE, -s VALUE`` + The value to set the option to. Not needed if ``-r`` or ``--remove`` is + set. + +``--remove, -r`` + Remove (unset) the option, instead of setting it. + +In addition to the above options, you may use any of the `configuration file +options`_ (listed under the `saveopts`_ command, above) to determine which +distutils configuration file the option will be added to (or removed from). + + +``test`` - Build package and run a unittest suite +================================================= + +When doing test-driven development, or running automated builds that need +testing before they are deployed for downloading or use, it's often useful +to be able to run a project's unit tests without actually deploying the project +anywhere, even using the ``develop`` command. The ``test`` command runs a +project's unit tests without actually deploying it, by temporarily putting the +project's source on ``sys.path``, after first running ``build_ext -i`` and +``egg_info`` to ensure that any C extensions and project metadata are +up-to-date. + +To use this command, your project's tests must be wrapped in a ``unittest`` +test suite by either a function, a ``TestCase`` class or method, or a module +containing ``TestCase`` classes. Note that many test systems including +``doctest`` support wrapping their non-``unittest`` tests in ``TestSuite`` +objects. So, if you are using a test package that does not support this, we +suggest you encourage its developers to implement test suite support, as this +is a convenient and standard way to aggregate a collection of tests to be run +under a common test harness. + +By default, tests will be run in the "verbose" mode of the ``unittest`` +package's text test runner, but you can get the "quiet" mode (just dots) if +you supply the ``-q`` or ``--quiet`` option, either as a global option to +the setup script (e.g. ``setup.py -q test``) or as an option for the ``test`` +command itself (e.g. ``setup.py test -q``). There is one other option +available: + +``--test-suite=NAME, -s NAME`` + Specify the test suite (or module, class, or method) to be run + (e.g. ``some_module.test_suite``). The default for this option can be + set by giving a ``test_suite`` argument to the ``setup()`` function, e.g.:: + + setup( + # ... + test_suite = "my_package.tests.test_all" + ) + + If you did not set a ``test_suite`` in your ``setup()`` call, and do not + provide a ``--test-suite`` option, an error will occur. + + +``upload`` - Upload source and/or egg distributions to PyPI +=========================================================== + +PyPI now supports uploading project files for redistribution; uploaded files +are easily found by EasyInstall, even if you don't have download links on your +project's home page. + +Although Python 2.5 will support uploading all types of distributions to PyPI, +setuptools only supports source distributions and eggs. (This is partly +because PyPI's upload support is currently broken for various other file +types.) To upload files, you must include the ``upload`` command *after* the +``sdist`` or ``bdist_egg`` commands on the setup command line. For example:: + + setup.py bdist_egg upload # create an egg and upload it + setup.py sdist upload # create a source distro and upload it + setup.py sdist bdist_egg upload # create and upload both + +Note that to upload files for a project, the corresponding version must already +be registered with PyPI, using the distutils ``register`` command. It's +usually a good idea to include the ``register`` command at the start of the +command line, so that any registration problems can be found and fixed before +building and uploading the distributions, e.g.:: + + setup.py register sdist bdist_egg upload + +This will update PyPI's listing for your project's current version. + +Note, by the way, that the metadata in your ``setup()`` call determines what +will be listed in PyPI for your package. Try to fill out as much of it as +possible, as it will save you a lot of trouble manually adding and updating +your PyPI listings. Just put it in ``setup.py`` and use the ``register`` +comamnd to keep PyPI up to date. + +The ``upload`` command has a few options worth noting: + +``--sign, -s`` + Sign each uploaded file using GPG (GNU Privacy Guard). The ``gpg`` program + must be available for execution on the system ``PATH``. + +``--show-response`` + Display the full response text from server; this is useful for debugging + PyPI problems. + +``--repository=URL, -r URL`` + The URL of the repository to upload to. Defaults to + http://www.python.org/pypi (i.e., the main PyPI installation). ------------------------------------ Extending and Reusing ``setuptools`` ------------------------------------ +Sorry, this section isn't written yet, and neither is a lot of what's below +this point, except for the change log. You might want to `subscribe to changes +in this page `_ to see when new documentation is +added or updated. + + Subclassing ``Command`` ======================= @@ -527,6 +1040,15 @@ Release Notes/Change History ---------------------------- +0.5a9 + * Include ``svn:externals`` directories in source distributions as well as + normal subversion-controlled files and directories. + + * Added ``exclude=patternlist`` option to ``setuptools.find_packages()`` + + * Changed --tag-svn-revision to include an "r" in front of the revision number + for better readability. + 0.5a8 * The "egg_info" command now always sets the distribution metadata to "safe" forms of the distribution name and version, so that distribution files will From gregorykjohnson at users.sourceforge.net Sat Jul 9 21:15:02 2005 From: gregorykjohnson at users.sourceforge.net (gregorykjohnson@users.sourceforge.net) Date: Sat, 09 Jul 2005 12:15:02 -0700 Subject: [Python-checkins] python/nondist/sandbox/mailbox - New directory Message-ID: Update of /cvsroot/python/python/nondist/sandbox/mailbox In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14529/mailbox Log Message: Directory /cvsroot/python/python/nondist/sandbox/mailbox added to the repository From gregorykjohnson at users.sourceforge.net Sat Jul 9 22:15:28 2005 From: gregorykjohnson at users.sourceforge.net (gregorykjohnson@users.sourceforge.net) Date: Sat, 09 Jul 2005 13:15:28 -0700 Subject: [Python-checkins] python/nondist/sandbox/mailbox README, NONE, 1.1 libmailbox.tex, NONE, 1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/mailbox In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10425 Added Files: README libmailbox.tex Log Message: Initial commit for Summer of Code mailbox project. There's only documentation for now. Code will follow. --- NEW FILE: README --- This is a backward-compatible rewrite of the mailbox module to support mailbox modification and mailbox-format-specific message attributes. It's being written as part of Google's Summer of Code program[1] by Gregory K. Johnson with mentoring from A.M. Kuchling. Greg's project proposal[2] is available online, and summaries[3] of all of the accepted proposals for Python are on the Python Wiki. [1] http://code.google.com/summerofcode.html [2] http://gkj.freeshell.org/summer_of_code/ [3] http://wiki.python.org/moin/SummerOfCode --- NEW FILE: libmailbox.tex --- \section{\module{mailbox} --- Manipulate mailboxes in various formats} \declaremodule{}{mailbox} \moduleauthor{Gregory K.~Johnson}{gkj at gregorykjohnson.com} \sectionauthor{Gregory K.~Johnson}{gkj at gregorykjohnson.com} \modulesynopsis{Manipulate mailboxes in various formats} The \module{mailbox} module defines objects for accessing and manipulating Maildir, mbox, MH, Babyl, and MMDF mailboxes and the messages they contain. (These formats are commonly used on \UNIX{} to store email messages on disk.) \class{Mailbox} and \class{Message} are the two main classes offered by the module. \class{Mailbox} offers a dictionary-like mapping from keys to messages. \class{Message} extends the \module{email.Message} module's \class{Message} class with format-specific state and behavior. Both \class{Mailbox} and \class{Message} are extended by format-specific subclasses and are generally not instantiated directly. A \class{Mailbox} instance's keys are immutable objects, issued by the \class{Mailbox} instance, that are used to select messages from it. They remain meaningful for the life of the \class{Mailbox} instance, even if the mailbox is modified. Each time the value corresponding to a key is requested, a new message representation is created. Typically, messages are representated as \class{Message} instances, but a custom factory function may be specified. A message representation is independent of the particular \class{Mailbox} instance that created it (if any). For message modifications to be reflected in a mailbox, the modified message representation must be explicitly assigned back into the \class{Mailbox} instance's mapping. \begin{seealso} \seemodule{email}{Represent and manipulate messages.} \seemodule{poplib}{Access mail via POP3.} \seemodule{imaplib}{Access mail via IMAP4.} \seemodule{smtplib}{Transfer mail via SMTP.} \end{seealso} \subsection{\class{Mailbox} objects} \label{mailbox-objects} The \class{Mailbox} interface is dictionary-like, with small keys corresponding to messages. Keys are issued by the \class{Mailbox} instance with which they will be used and are only meaningful to that \class{Mailbox} instance. (\strong{Implementation note:} \class{mbox}, \class{MH}, \class{Babyl}, and \class{MMDF} instances use integers as keys, and \class{Maildir} instances uses short strings.) A key continues to identify a message even if the corresponding message is modified by replacing it with another message. Because keys are issued by a \class{Mailbox} instance rather than being chosen, the conventional method for adding an item to a mapping (assigning a value to a new key) cannot be used. Instead, messages may be added to a \class{Mailbox} instance using the set-like method \method{add()}. For uniformity, \method{remove()} and \method{discard()} are also available. \class{Mailbox} semantics differ from dictionary semantics in important ways. Each time a message is requested, a new message representation (typically a \class{Message} instance) is generated based upon the current state of the underlying message. Similarly, when a message representation is assigned into a \class{Mailbox} instance's mapping, the message representation's contents are copied into the mailbox. In neither case is a reference to the message representation kept by the \class{Mailbox} instance. Also unlike dictionaries, the default \class{Mailbox} iterator iterates over message representations, not keys. Moreover, modification of a mailbox during iteration is safe and well-defined. Messages added to the mailbox after an iterator is created will not be seen by the iterator, and messages removed from the mailbox before the iterator yields them will be silently skipped. All three kinds of iterator---key, value, and item---have this behavior. \class{Mailbox} itself is not intended to be instantiated. Rather, it is intended to define an interface and to be inherited from by format-specific subclasses. You may directly instantiate a subclass, or alternatively you may use the module-level \function{open()} function to instantiate the appropriate subclass. \begin{funcdesc}{open}{path\optional{, format, factory}} Instantiate and return an instance of the appropriate \class{Mailbox} subclass for the mailbox at \var{path}. The mailbox is created if it does not already exist. If \var{format} is specified, it should be one of "Maildir", "mbox", "MH", "Babyl", or "MMDF" (case insensitive). If \var{format} is not specified, then the format of the mailbox will be automatically detected. Automatic detection involves inspecting the mailbox at \var{path} if such a mailbox exists or if no such mailbox exists inspecting \var{path} itself and assuming Maildir format if \var{path} ends with the system's path separator (e.g., "/" or "\textbackslash") or mbox format otherwise. Parameter \var{factory} is a callable object that accepts a file-like object containing a raw message as its parameter and returns a message representation. If \var{factory} is not specified, \class{Message} instances are used to represent messages. For historic reasons, some subclasses of \class{Mailbox} take instantiation arguments with different purposes, names, or default values. The \function{open()} function is intended to present a convenient, uniform interface for \class{Mailbox} instantiation while maintaining backward compatibility. \end{funcdesc} \class{Mailbox} instances have the following methods: \begin{methoddesc}[Mailbox]{add}{message} Add \var{message} to the mailbox and return the key that has been assigned to it. Parameter \var{message} may be a \class{Message} instance, an \class{email.Message.Message} instance, a string, or a file-like object. If \var{message} is an instance of the appropriate format-specific \class{Message} subclass (e.g., if it's an \class{mboxMessage} instance and this is an \class{mbox} instance), its format-specific information will be used. Otherwise, reasonable defaults for format-specific information will be used. \end{methoddesc} \begin{methoddesc}[Mailbox]{remove}{key} Delete the message corresponding to \var{key} from the mailbox. Raise a \exception{KeyError} exception if no such message exists. The behavior of \method{discard()} may be preferred to that of \method{remove()} if the underlying mailbox format supports concurrent modification by other processes, as is the case for Maildir. \end{methoddesc} \begin{methoddesc}[Mailbox]{discard}{key} Delete the message corresponding to \var{key} from the mailbox, or do nothing if no such message exists. \end{methoddesc} \begin{methoddesc}[Mailbox]{iterkeys}{} Return an iterator over all keys. \end{methoddesc} \begin{methoddesc}[Mailbox]{keys}{} Return a list of all keys. \end{methoddesc} \begin{methoddesc}[Mailbox]{itervalues}{} Return an iterator over representations of all messages. The messages are represented as \class{Message} instances unless a custom message factory was specified when the \class{Mailbox} instance was initialized. \end{methoddesc} \begin{methoddesc}[Mailbox]{values}{} Return a list of representations of all messages. The messages are represented as \class{Message} instances unless a custom message factory was specified when the \class{Mailbox} instance was initialized. \warning{This may require a large amount of memory.} \end{methoddesc} \begin{methoddesc}[Mailbox]{iteritems}{} Return an iterator over (\var{key}, \var{message}) pairs, where \var{key} is a key and \var{message} is a message representation. The messages are represented as \class{Message} instances unless a custom message factory was specified when the \class{Mailbox} instance was initialized. \end{methoddesc} \begin{methoddesc}[Mailbox]{items}{} Return a list of (\var{key}, \var{message}) pairs, where \var{key} is a key and \var{message} is a message representation. The messages are represented as \class{Message} instances unless a custom message factory was specified when the \class{Mailbox} instance was initialized. \warning{This may require a large amount of memory.} \end{methoddesc} \begin{methoddesc}[Mailbox]{get}{key\optional{, default=None}} Return a representation of the message corresponding to \var{key}, or \var{default} if no such message exists. The message is represented as a \class{Message} instance unless a custom message factory was specified when the \class{Mailbox} instance was initialized. \end{methoddesc} \begin{methoddesc}[Mailbox]{get_message}{key\optional{, default=None}} Return a \class{Message} representation of the message corresponding to \var{key}, or \var{default} if no such message exists. \end{methoddesc} \begin{methoddesc}[Mailbox]{get_string}{key\optional{, default=None}} Return a string representation of the message corresponding to \var{key}, or \var{default} if no such message exists. \end{methoddesc} \begin{methoddesc}[Mailbox]{get_file}{key\optional{, default=None}} Return a file-like representation of the message corresponding to \var{key}, or \var{default} if no such message exists. \note{Unlike other representations of messages, file-like representations are not independent of the \class{Mailbox} instance that created them or of the underlying mailbox. If the mailbox is modified, the file-like representation may become unusable. More specific documentation is provided by each subclass.} \end{methoddesc} \begin{methoddesc}[Mailbox]{has_key}{key} Return \code{True} if \var{key} corresponds to a message, \code{False} otherwise. \end{methoddesc} \begin{methoddesc}[Mailbox]{__iter__}{} Synonymous with \method{itervalues()}. \note{This is unlike the default iteration behavior of dictionaries.} \end{methoddesc} \begin{methoddesc}[Mailbox]{__getitem__}{key} Like \method{get()}, except raises a \exception{KeyError} exception if the message corresponding to \var{key} does not exist. \end{methoddesc} \begin{methoddesc}[Mailbox]{__setitem__}{key, message} Replace the message corresponding to \var{key} with the message represented by \var{message}. Raise a \exception{KeyError} exception if no message already corresponds to the given key. As with \method{add()}, parameter \var{message} may be a \class{Message} instance, an \class{email.Message.Message} instance, a string, or a file-like object. If \var{message} is an instance of the appropriate format-specific \class{Message} subclass (e.g., if it's an \class{mboxMessage} instance and this is an \class{mbox} instance), its format-specific information will be used. Otherwise, reasonable defaults for format-specific information will be used. \end{methoddesc} \begin{methoddesc}[Mailbox]{__delitem__}{key} Synonymous with \method{remove()}. \end{methoddesc} \begin{methoddesc}[Mailbox]{__contains__}{key} Synonymous with \method{has_key()}. \end{methoddesc} \begin{methoddesc}[Mailbox]{__len__}{} Return a count of messages in the mailbox. \end{methoddesc} \begin{methoddesc}[Mailbox]{clear}{} Delete all messages from the mailbox. \end{methoddesc} \begin{methoddesc}[Mailbox]{pop}{key\optional{, default}} Return a representation of the message corresponding to \var{key} and delete the message. If no such message exists, return \var{default} if it was supplied or if \var{default} was not supplied raise a \exception{KeyError} exception. The message is represented as a \class{Message} instance unless a custom message factory was specified when the \class{Mailbox} instance was initialized. \end{methoddesc} \begin{methoddesc}[Mailbox]{popitem}{} Return an arbitrary (\var{key}, \var{message}) pair, where \var{key} is a key and \var{message} is a message representation, and delete the corresponding message from the mailbox. If the mailbox is empty, raise a \exception{KeyError} exception. The message is represented as a \class{Message} instance unless a custom message factory was specified when the \class{Mailbox} instance was initialized. \end{methoddesc} \begin{methoddesc}[Mailbox]{update}{arg} If \var{arg} is a mailbox-like \var{key}-to-\var{message} mapping or an iterable of (\var{key}, \var{message}) pairs, update the mailbox so that, for each given \var{key} and \var{message}, the message corresponding to \var{key} is set to \var{message} as if by using \method{__setitem__()}. \note{Keyword arguments are not supported, unlike with dictionaries.} \end{methoddesc} \subsubsection{\class{Maildir}} \label{mailbox-maildir} \subsubsection{\class{mbox}} \label{mailbox-mbox} \subsubsection{\class{MH}} \label{mailbox-mh} \subsubsection{\class{Babyl}} \label{mailbox-babyl} \subsubsection{\class{MMDF}} \label{mailbox-mmdf} \subsection{\class{Message} objects} \label{mailbox-message-objects} \subsubsection{\class{MaildirMessage}} \label{mailbox-maildirmessage} \subsubsection{\class{mboxMessage}} \label{mailbox-mboxmessage} \subsubsection{\class{MHMessage}} \label{mailbox-mhmessage} \subsubsection{\class{BabylMessage}} \label{mailbox-babylmessage} \subsubsection{\class{MMDFMessage}} \label{mailbox-mmdfmessage} \subsection{Deprecated classes} \label{mailbox-deprecated-classes} \subsection{Examples} \label{mailbox-examples} From pje at users.sourceforge.net Sun Jul 10 06:49:41 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 21:49:41 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools archive_util.py, 1.2, 1.3 dist.py, 1.12, 1.13 package_index.py, 1.9, 1.10 sandbox.py, 1.3, 1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19865/setuptools Modified Files: archive_util.py dist.py package_index.py sandbox.py Log Message: Detect and handle conflicts with "unmanaged" packages when installing packages managed by EasyInstall. Also, add an option to exclude source files from .egg distributions. Index: archive_util.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/archive_util.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- archive_util.py 15 Jun 2005 02:11:09 -0000 1.2 +++ archive_util.py 10 Jul 2005 04:49:31 -0000 1.3 @@ -8,8 +8,9 @@ import zipfile, tarfile, os from pkg_resources import ensure_directory +from distutils.errors import DistutilsError -class UnrecognizedFormat(RuntimeError): +class UnrecognizedFormat(DistutilsError): """Couldn't recognize the archive type""" def default_filter(src,dst): @@ -38,7 +39,6 @@ - def unpack_archive(filename, extract_dir, progress_filter=default_filter, drivers=None ): Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- dist.py 8 Jul 2005 05:09:23 -0000 1.12 +++ dist.py 10 Jul 2005 04:49:31 -0000 1.13 @@ -420,13 +420,16 @@ def install_eggs(self): from setuptools.command.easy_install import easy_install - cmd = easy_install(self, args="x") + cmd = easy_install(self, args="x", ignore_conflicts_at_my_risk=1) cmd.ensure_finalized() # finalize before bdist_egg munges install cmd + self.run_command('bdist_egg') args = [self.get_command_obj('bdist_egg').egg_output] + if setuptools.bootstrap_install_from: # Bootstrap self-installation of setuptools args.insert(0, setuptools.bootstrap_install_from) + cmd.args = args cmd.run() self.have_run['install'] = 1 @@ -446,9 +449,6 @@ - - - def get_cmdline_options(self): """Return a '{cmd: {opt:val}}' map of all command-line options Index: package_index.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/package_index.py,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- package_index.py 7 Jul 2005 16:28:43 -0000 1.9 +++ package_index.py 10 Jul 2005 04:49:31 -0000 1.10 @@ -3,6 +3,7 @@ import sys, os.path, re, urlparse, urllib2 from pkg_resources import * from distutils import log +from distutils.errors import DistutilsError HREF = re.compile(r"""href\s*=\s*['"]?([^'"> ]+)""", re.I) URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):',re.I).match @@ -38,7 +39,6 @@ - def distros_for_url(url, metadata=None): """Yield egg or source distribution objects that might be found at a URL""" @@ -272,7 +272,7 @@ try: spec = Requirement.parse(spec) except ValueError: - raise RuntimeError( + raise DistutilsError( "Not a URL, existing file, or requirement spec: %r" % (spec,) ) @@ -336,7 +336,7 @@ try: fp = self.open_url(url) if isinstance(fp, urllib2.HTTPError): - raise RuntimeError( + raise DistutilsError( "Can't download %s: %s %s" % (url, fp.code,fp.msg) ) @@ -373,7 +373,7 @@ except urllib2.HTTPError, v: return v except urllib2.URLError, v: - raise RuntimeError("Download error: %s" % v.reason) + raise DistutilsError("Download error: %s" % v.reason) def _download_url(self, scheme, url, tmpdir): @@ -432,7 +432,7 @@ return self._download_sourceforge(url, page, tmpdir) break # not an index page file.close() - raise RuntimeError("Unexpected HTML page found at "+url) + raise DistutilsError("Unexpected HTML page found at "+url) def _download_svn(self, url, filename): @@ -457,7 +457,7 @@ mirror_regex = re.compile(r'HREF=(/.*?\?use_mirror=[^>]*)') urls = [m.group(1) for m in mirror_regex.finditer(sf_page)] if not urls: - raise RuntimeError( + raise DistutilsError( "URL looks like a Sourceforge mirror page, but no URLs found" ) @@ -481,7 +481,7 @@ scheme = URL_SCHEME(download_url) return self._download_url(scheme.group(1), download_url, tmpdir) else: - raise RuntimeError( + raise DistutilsError( 'No META HTTP-EQUIV="refresh" found in Sourceforge page at %s' % url ) Index: sandbox.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/sandbox.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- sandbox.py 25 Jun 2005 19:33:06 -0000 1.3 +++ sandbox.py 10 Jul 2005 04:49:31 -0000 1.4 @@ -1,7 +1,7 @@ import os, sys, __builtin__, tempfile _os = sys.modules[os.name] _open = open - +from distutils.errors import DistutilsError __all__ = [ "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", ] @@ -188,7 +188,7 @@ return (src,dst) -class SandboxViolation(RuntimeError): +class SandboxViolation(DistutilsError): """A setup script attempted to modify the filesystem outside the sandbox""" def __str__(self): From pje at users.sourceforge.net Sun Jul 10 06:49:41 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 21:49:41 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command bdist_egg.py, 1.22, 1.23 easy_install.py, 1.3, 1.4 egg_info.py, 1.4, 1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19865/setuptools/command Modified Files: bdist_egg.py easy_install.py egg_info.py Log Message: Detect and handle conflicts with "unmanaged" packages when installing packages managed by EasyInstall. Also, add an option to exclude source files from .egg distributions. Index: bdist_egg.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/bdist_egg.py,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- bdist_egg.py 9 Jul 2005 04:25:49 -0000 1.22 +++ bdist_egg.py 10 Jul 2005 04:49:31 -0000 1.23 @@ -49,6 +49,8 @@ ('plat-name=', 'p', "platform name to embed in generated filenames " "(default: %s)" % get_platform()), + ('exclude-source-files', None, + "remove all .py files from the generated egg"), ('keep-temp', 'k', "keep the pseudo-installation tree around after " + "creating the distribution archive"), @@ -59,7 +61,7 @@ ] boolean_options = [ - 'keep-temp', 'skip-build', + 'keep-temp', 'skip-build', 'exclude-source-files' ] @@ -78,8 +80,6 @@ - - def initialize_options (self): self.bdist_dir = None self.plat_name = None @@ -87,7 +87,7 @@ self.dist_dir = None self.skip_build = 0 self.egg_output = None - + self.exclude_source_files = None def finalize_options(self): @@ -227,6 +227,8 @@ "Use the install_requires/extras_require setup() args instead." ) + if self.exclude_source_files: self.zap_pyfiles() + # Make the archive make_zipfile(self.egg_output, archive_root, verbose=self.verbose, dry_run=self.dry_run) @@ -242,6 +244,45 @@ + def zap_pyfiles(self): + log.info("Removing .py files from temporary directory") + for base,dirs,files in os.walk(self.bdist_dir): + if 'EGG-INFO' in dirs: + dirs.remove('EGG-INFO') + for name in files: + if name.endswith('.py'): + path = os.path.join(base,name) + log.debug("Deleting %s", path) + os.unlink(path) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Attribute names of options for commands that might need to be convinced to Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- easy_install.py 7 Jul 2005 02:03:25 -0000 1.3 +++ easy_install.py 10 Jul 2005 04:49:31 -0000 1.4 @@ -17,7 +17,7 @@ from setuptools.sandbox import run_setup from distutils import log, dir_util from distutils.sysconfig import get_python_lib -from distutils.errors import DistutilsArgError, DistutilsOptionError +from distutils.errors import DistutilsArgError, DistutilsOptionError, DistutilsError from setuptools.archive_util import unpack_archive from setuptools.package_index import PackageIndex, parse_bdist_wininst from setuptools.package_index import URL_SCHEME @@ -43,7 +43,9 @@ """Manage a download/build/install process""" description = "Find/get/install Python packages" + command_consumes_arguments = True + user_options = [ ("zip-ok", "z", "install package as a zipfile"), ("multi-version", "m", "make apps have to require() a version"), @@ -54,6 +56,10 @@ ("always-copy", "a", "Copy all needed packages to install dir"), ("index-url=", "i", "base URL of Python Package Index"), ("find-links=", "f", "additional URL(s) to search for packages"), + ("delete-conflicting", "D", "delete old packages that get in the way"), + ("ignore-conflicts-at-my-risk", None, + "install even if old packages are in the way, even though it " + "most likely means the new package won't work."), ("build-directory=", "b", "download/extract/build in DIR; keep the results"), ('optimize=', 'O', @@ -62,11 +68,18 @@ ('record=', None, "filename in which to record list of installed files"), ] + boolean_options = [ - 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy' + 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy', + 'delete-conflicting', 'ignore-conflicts-at-my-risk', ] + create_index = PackageIndex + + + + def initialize_options(self): self.zip_ok = None self.install_dir = self.script_dir = self.exclude_scripts = None @@ -79,6 +92,34 @@ # Options not specifiable via command line self.package_index = None self.pth_file = None + self.delete_conflicting = None + self.ignore_conflicts_at_my_risk = None + + + def delete_blockers(self, blockers): + for filename in blockers: + log.info("Deleting %s", filename) + if not self.dry_run: + if os.path.isdir(filename): + shutil.rmtree(filename) + else: + os.unlink(filename) + + + + + + + + + + + + + + + + def finalize_options(self): # If a non-default installation directory was specified, default the @@ -122,16 +163,13 @@ self.index_url = self.index_url or "http://www.python.org/pypi" self.shadow_path = sys.path[:] - for path_item in self.install_dir, self.script_dir: if path_item not in self.shadow_path: self.shadow_path.insert(0, self.install_dir) - if self.package_index is None: self.package_index = self.create_index( self.index_url, search_path = self.shadow_path ) - self.local_index = AvailableDistributions(self.shadow_path) if self.find_links is not None: @@ -149,6 +187,11 @@ except ValueError: raise DistutilsOptionError("--optimize must be 0, 1, or 2") + if self.delete_conflicting and self.ignore_conflicts_at_my_risk: + raise DistutilsOptionError( + "Can't use both --delete-conflicting and " + "--ignore-conflicts-at-my-risk at the same time" + ) if not self.args: raise DistutilsArgError( "No urls, filenames, or requirements specified (see --help)") @@ -160,8 +203,6 @@ self.outputs = [] - - def alloc_tmp(self): if self.build_directory is None: return tempfile.mkdtemp(prefix="easy_install-") @@ -221,7 +262,7 @@ try: spec = Requirement.parse(spec) except ValueError: - raise RuntimeError( + raise DistutilsError( "Not a URL, existing file, or requirement spec: %r" % (spec,) ) @@ -232,7 +273,7 @@ spec = None if download is None: - raise RuntimeError( + raise DistutilsError( "Could not find distribution for %r" % spec ) @@ -254,7 +295,7 @@ for dist in dists: self.process_distribution(spec, dist) else: - dists = [self.egg_distribution(download)] + dists = [self.check_conflicts(self.egg_distribution(download))] self.process_distribution(spec, dists[0], "Using") if spec is not None: for dist in dists: @@ -276,11 +317,11 @@ [requirement], self.shadow_path, self.easy_install ) except DistributionNotFound, e: - raise RuntimeError( + raise DistutilsError( "Could not find required distribution %s" % e.args ) except VersionConflict, e: - raise RuntimeError( + raise DistutilsError( "Installed distribution %s conflicts with requirement %s" % e.args ) @@ -385,11 +426,11 @@ if not os.path.exists(setup_script): setups = glob(os.path.join(tmpdir, '*', 'setup.py')) if not setups: - raise RuntimeError( + raise DistutilsError( "Couldn't find a setup script in %s" % dist_filename ) if len(setups)>1: - raise RuntimeError( + raise DistutilsError( "Multiple setup scripts in %s" % dist_filename ) setup_script = setups[0] @@ -418,10 +459,10 @@ def install_egg(self, egg_path, zip_ok, tmpdir): destination = os.path.join(self.install_dir,os.path.basename(egg_path)) destination = os.path.abspath(destination) - if not self.dry_run: ensure_directory(destination) + self.check_conflicts(self.egg_distribution(egg_path)) if not samefile(egg_path, destination): if os.path.isdir(destination): dir_util.remove_tree(destination, dry_run=self.dry_run) @@ -453,7 +494,7 @@ # See if it's valid, get data cfg = extract_wininst_cfg(dist_filename) if cfg is None: - raise RuntimeError( + raise DistutilsError( "%s is not a valid distutils Windows .exe" % dist_filename ) @@ -495,18 +536,23 @@ # Check for .pth file and set up prefix translations prefixes = get_exe_prefixes(dist_filename) + to_compile = [] native_libs = [] + top_level = {} def process(src,dst): for old,new in prefixes: if src.startswith(old): src = new+src[len(old):] - dst = os.path.join(egg_tmp, *src.split('/')) + parts = src.split('/') + dst = os.path.join(egg_tmp, *parts) dl = dst.lower() if dl.endswith('.pyd') or dl.endswith('.dll'): + top_level[os.path.splitext(parts[0])[0]] = 1 native_libs.append(src) elif dl.endswith('.py') and old!='SCRIPTS/': + top_level[os.path.splitext(parts[0])[0]] = 1 to_compile.append(dst) return dst if not src.endswith('.pth'): @@ -526,10 +572,87 @@ self.byte_compile(to_compile) # compile .py's - if native_libs: # write EGG-INFO/native_libs.txt - nl_txt = os.path.join(egg_tmp, 'EGG-INFO', 'native_libs.txt') - ensure_directory(nl_txt) - open(nl_txt,'w').write('\n'.join(native_libs)+'\n') + for name in 'top_level','native_libs': + if locals()[name]: + txt = os.path.join(egg_tmp, 'EGG-INFO', name+'.txt') + ensure_directory(txt) + open(txt,'w').write('\n'.join(locals()[name])+'\n') + + def check_conflicts(self, dist): + """Verify that there are no conflicting "old-style" packages""" + + from imp import find_module, get_suffixes + from glob import glob + + blockers = [] + names = dict.fromkeys(dist._get_metadata('top_level.txt')) # XXX private attr + + exts = {'.pyc':1, '.pyo':1} # get_suffixes() might leave one out + for ext,mode,typ in get_suffixes(): + exts[ext] = 1 + + for path,files in expand_paths([self.install_dir, get_python_lib()]): + for filename in files: + base,ext = os.path.splitext(filename) + if base in names: + if not ext: + # no extension, check for package + try: + f, filename, descr = find_module(base, [path]) + except ImportError: + continue + else: + if f: f.close() + if filename not in blockers: + blockers.append(filename) + elif ext in exts: + blockers.append(os.path.join(path,filename)) + + if blockers: + self.found_conflicts(dist, blockers) + + return dist + + def found_conflicts(self, dist, blockers): + if self.delete_conflicting: + log.warn("Attempting to delete conflicting packages:") + return self.delete_blockers(blockers) + + msg = """\ +------------------------------------------------------------------------- +CONFLICT WARNING: + +The following modules or packages have the same names as modules or +packages being installed, and will be *before* the installed packages in +Python's search path. You MUST remove all of the relevant files and +directories before you will be able to use the package(s) you are +installing: + + %s + +""" % '\n '.join(blockers) + + if self.ignore_conflicts_at_my_risk: + msg += """\ +(Note: you can run EasyInstall on '%s' with the +--delete-conflicting option to attempt deletion of the above files +and/or directories.) +""" % dist.name + else: + msg += """\ +Note: you can attempt this installation again with EasyInstall, and use +either the --delete-conflicting (-D) option or the +--ignore-conflicts-at-my-risk option, to either delete the above files +and directories, or to ignore the conflicts, respectively. Note that if +you ignore the conflicts, the installed package(s) may not work. +""" + msg += """\ +------------------------------------------------------------------------- +""" + sys.stderr.write(msg) + sys.stderr.flush() + if not self.ignore_conflicts_at_my_risk: + raise DistutilsError("Installation aborted due to conflicts") def installation_report(self, dist, what="Installed"): """Helpful installation message for display to package users""" @@ -589,7 +712,7 @@ try: run_setup(setup_script, args) except SystemExit, v: - raise RuntimeError( + raise DistutilsError( "Setup script exited with %s" % (v.args[0],) ) finally: @@ -695,6 +818,47 @@ +def expand_paths(inputs): + """Yield sys.path directories that might contain "old-style" packages""" + + seen = {} + + for dirname in inputs: + if dirname in seen: + continue + + seen[dirname] = 1 + if not os.path.isdir(dirname): + continue + + files = os.listdir(dirname) + yield dirname, files + + for name in files: + if not name.endswith('.pth'): + # We only care about the .pth files + continue + if name in ('easy-install.pth','setuptools.pth'): + # Ignore .pth files that we control + continue + + # Read the .pth file + f = open(os.path.join(dirname,name)) + lines = list(yield_lines(f)) + f.close() + + # Yield existing non-dupe, non-import directory lines from it + for line in lines: + if not line.startswith("import"): + line = line.rstrip() + if line not in seen: + seen[line] = 1 + if not os.path.isdir(line): + continue + yield line, os.listdir(line) + + + def extract_wininst_cfg(dist_filename): """Extract configuration data from a bdist_wininst .exe @@ -820,11 +984,11 @@ def main(argv, **kw): from setuptools import setup - try: - setup(script_args = ['-q','easy_install', '-v']+argv, **kw) - except RuntimeError, v: - print >>sys.stderr,"error:",v - sys.exit(1) + setup(script_args = ['-q','easy_install', '-v']+argv, **kw) + + + + Index: egg_info.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/egg_info.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- egg_info.py 9 Jul 2005 16:25:54 -0000 1.4 +++ egg_info.py 10 Jul 2005 04:49:31 -0000 1.5 @@ -97,6 +97,7 @@ metadata.name, metadata.version = oldname, oldver self.write_requirements() + self.write_toplevel_names() if os.path.exists(os.path.join(self.egg_info,'depends.txt')): log.warn( "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" @@ -106,7 +107,6 @@ def write_requirements(self): dist = self.distribution - if not getattr(dist,'install_requires',None) and \ not getattr(dist,'extras_require',None): return @@ -125,14 +125,11 @@ version = self.distribution.get_version() if self.tag_build: version+=self.tag_build - if self.tag_svn_revision and os.path.exists('.svn'): version += '-r%s' % self.get_svn_revision() - if self.tag_date: import time version += time.strftime("-%Y%m%d") - return safe_version(version) @@ -142,23 +139,26 @@ import re match = re.search(r'Last Changed Rev: (\d+)', result) if not match: - raise RuntimeError("svn info error: %s" % result.strip()) + raise DistutilsError("svn info error: %s" % result.strip()) return match.group(1) - - - - - - - - - - - - - - + def write_toplevel_names(self): + pkgs = dict.fromkeys(self.distribution.packages or ()) + pkgs.update(dict.fromkeys(self.distribution.py_modules or ())) + for ext in self.distribution.ext_modules or (): + if isinstance(ext,tuple): + name,buildinfo = ext + else: + name = ext.name + pkgs[name]=1 + pkgs = dict.fromkeys([k.split('.',1)[0] for k in pkgs]) + toplevel = os.path.join(self.egg_info,"top_level.txt") + log.info("writing list of top-level names to %s" % toplevel) + if not self.dry_run: + f = open(toplevel, 'wt') + f.write('\n'.join(pkgs)) + f.write('\n') + f.close() From pje at users.sourceforge.net Sun Jul 10 06:49:41 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 21:49:41 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.30, 1.31 setuptools.txt, 1.3, 1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19865 Modified Files: EasyInstall.txt setuptools.txt Log Message: Detect and handle conflicts with "unmanaged" packages when installing packages managed by EasyInstall. Also, add an option to exclude source files from .egg distributions. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -r1.30 -r1.31 --- EasyInstall.txt 8 Jul 2005 15:52:03 -0000 1.30 +++ EasyInstall.txt 10 Jul 2005 04:49:30 -0000 1.31 @@ -268,6 +268,36 @@ more documentation on using distutils configuration files. +Dealing with Installation Conflicts +----------------------------------- + +EasyInstall installs distributions in a "managed" way, such that each +distribution can be independently activated or deactivated on ``sys.path``. +However, packages that were not installed by EasyInstall are "unmanaged", +in that they usually live all in one directory and cannot be independently +activated or deactivated. + +As a result, if you are using EasyInstall to upgrade an existing package, or +to install a package with the same name as an existing package, EasyInstall +will warn you of the conflict. (This is an improvement over ``setup.py +install``, becuase the ``distutils`` just install new packages on top of old +ones, possibly combining two unrelated packages or leaving behind modules that +have been deleted in the newer version of the package.) + +By default, EasyInstall will stop the installation if it detects a conflict +between an existing, "unmanaged" package, and a module or package in any of +the distributions you're installing. It will display a list of all of the +existing files and directories that would need to be deleted for the new +package to be able to function correctly. You can then either delete these +conflicting files and directories yourself and re-run EasyInstall, or you can +just use the ``--delete-conflicting`` or ``--ignore-conflicts-at-my-risk`` +options, as described under `Command-Line Options`_, below. + +Of course, once you've replaced all of your existing "unmanaged" packages with +versions managed by EasyInstall, you won't have any more conflicts to worry +about! + + Reference Manual ================ @@ -424,6 +454,23 @@ every time you use EasyInstall (unless overridden on the command line) and thus may make startup slower. +``--delete-conflicting, -D`` (New in 0.5a9) + If you are replacing a package that was previously installed *without* + using EasyInstall, the old version may end up on ``sys.path`` before the + version being installed with EasyInstall. EasyInstall will normally abort + the installation of a package if it detects such a conflict, and ask you to + manually remove the conflicting files or directories. If you specify this + option, however, EasyInstall will attempt to delete the files or + directories itself, and then proceed with the installation. + +``--ignore-conflicts-at-my-risk`` (New in 0.5a9) + Ignore conflicting packages and proceed with installation anyway, even + though it means the package probably won't work properly. If the + conflicting package is in a directory you can't write to, this may be your + only option, but you will need to take more invasive measures to get the + installed package to work, like manually adding it to ``PYTHONPATH`` or to + ``sys.path`` at runtime. + ``--index-url=URL, -u URL`` (New in 0.4a1) Specifies the base URL of the Python Package Index. The default is http://www.python.org/pypi if not specified. When a package is requested @@ -495,6 +542,20 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. +0.5a9 + * EasyInstall now automatically detects when an "unmanaged" package or + module is going to be on ``sys.path`` ahead of a package you're installing, + thereby preventing the newer version from being imported. By default, it + will abort installation to alert you of the problem, but there are also + new options (``--delete-conflicting`` and ``--ignore-conflicts-at-my-risk``) + available to change the default behavior. (Note: this new feature doesn't + take effect for egg files that were built with older ``setuptools`` + versions, because they lack the new metadata file required to implement it.) + + * The ``easy_install`` distutils command now uses ``DistutilsError`` as its + base error type for errors that should just issue a message to stderr and + exit the program without a traceback. + 0.5a8 * There is now a separate documentation page for `setuptools`_; revision history that's not specific to EasyInstall has been moved to that page. Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- setuptools.txt 9 Jul 2005 16:27:23 -0000 1.3 +++ setuptools.txt 10 Jul 2005 04:49:31 -0000 1.4 @@ -570,7 +570,7 @@ any applications or frameworks that use that metadata. You won't usually need to specify any special options for this command; just -use ``bdist_egg`` and you're done. But there are a couple of options that may +use ``bdist_egg`` and you're done. But there are a few options that may be occasionally useful: ``--dist-dir=DIR, -d DIR`` @@ -590,6 +590,19 @@ cross-compiling or doing some other unusual things, you might find a use for this option. +``--exclude-source-files`` + Don't include any modules' ``.py`` files in the egg, just compiled Python, + C, and data files. (Note that this doesn't affect any ``.py`` files in the + EGG-INFO directory or its subdirectories, since for example there may be + scripts with a ``.py`` extension which must still be retained.) We don't + recommend that you use this option except for packages that are being + bundled for proprietary end-user applications, or for "embedded" scenarios + where space is at an absolute premium. On the other hand, if your package + is going to be installed and used in compressed form, you might as well + exclude the source because Python's ``traceback`` module doesn't currently + understand how to display zipped source code anyway, or how to deal with + files that are in a different place from where their code was compiled. + There are also some options you will probably never need, but which are there because they were copied from similar ``bdist`` commands used as an example for creating this one. They may be useful for testing and debugging, however, @@ -726,8 +739,8 @@ The following options can be used to modify the project's version string for all remaining commands on the setup command line. The options are processed -in the order shown, so if you use more than one, the request tags will be added -in the following order: +in the order shown, so if you use more than one, the requested tags will be +added in the following order: ``--tag-build=NAME, -b NAME`` Append NAME to the project's version string. Due to the way setuptools @@ -1049,6 +1062,23 @@ * Changed --tag-svn-revision to include an "r" in front of the revision number for better readability. + * Added ability to build eggs without including source files (except for any + scripts, of course), using the ``--exclude-source-files`` option to + ``bdist_egg``. + + * ``setup.py install`` now automatically detects when an "unmanaged" package + or module is going to be on ``sys.path`` ahead of a package being installed, + thereby preventing the newer version from being imported. If this occurs, + a warning message is output to ``sys.stderr``, but installation proceeds + anyway. The warning message informs the user what files or directories + need deleting, and advises them they can also use EasyInstall (with the + ``--delete-conflicting`` option) to do it automatically. + + * The ``egg_info`` command now adds a ``top_level.txt`` file to the metadata + directory that lists all top-level modules and packages in the distribution. + This is used by the ``easy_install`` command to find possibly-conflicting + "unmanaged" packages when installing the distribution. + 0.5a8 * The "egg_info" command now always sets the distribution metadata to "safe" forms of the distribution name and version, so that distribution files will From pje at users.sourceforge.net Sun Jul 10 07:06:34 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 22:06:34 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.31, 1.32 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27810 Modified Files: EasyInstall.txt Log Message: Allow EasyInstall to accept a directory containing a setup script as one of its arguments. Fix swapped short option names for --bdist-dir and --dist-dir in bdist_egg. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.31 retrieving revision 1.32 diff -u -d -r1.31 -r1.32 --- EasyInstall.txt 10 Jul 2005 04:49:30 -0000 1.31 +++ EasyInstall.txt 10 Jul 2005 05:06:30 -0000 1.32 @@ -556,6 +556,9 @@ base error type for errors that should just issue a message to stderr and exit the program without a traceback. + * EasyInstall can now be given a path to a directory containing a setup + script, and it will attempt to build and install the package there. + 0.5a8 * There is now a separate documentation page for `setuptools`_; revision history that's not specific to EasyInstall has been moved to that page. From pje at users.sourceforge.net Sun Jul 10 07:06:34 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 22:06:34 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command bdist_egg.py, 1.23, 1.24 easy_install.py, 1.4, 1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27810/setuptools/command Modified Files: bdist_egg.py easy_install.py Log Message: Allow EasyInstall to accept a directory containing a setup script as one of its arguments. Fix swapped short option names for --bdist-dir and --dist-dir in bdist_egg. Index: bdist_egg.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/bdist_egg.py,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- bdist_egg.py 10 Jul 2005 04:49:31 -0000 1.23 +++ bdist_egg.py 10 Jul 2005 05:06:31 -0000 1.24 @@ -44,7 +44,7 @@ description = "create an \"egg\" distribution" user_options = [ - ('bdist-dir=', 'd', + ('bdist-dir=', 'b', "temporary directory for creating the distribution"), ('plat-name=', 'p', "platform name to embed in generated filenames " @@ -54,7 +54,7 @@ ('keep-temp', 'k', "keep the pseudo-installation tree around after " + "creating the distribution archive"), - ('dist-dir=', 'b', + ('dist-dir=', 'd', "directory to put final built distributions in"), ('skip-build', None, "skip rebuilding everything (for testing/debugging)"), Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- easy_install.py 10 Jul 2005 04:49:31 -0000 1.4 +++ easy_install.py 10 Jul 2005 05:06:31 -0000 1.5 @@ -419,6 +419,8 @@ # Anything else, try to extract and build if os.path.isfile(dist_filename): unpack_archive(dist_filename, tmpdir, self.unpack_progress) + elif os.path.isdir(dist_filename): + tmpdir = dist_filename # ugh # Find the setup.py file from glob import glob @@ -436,7 +438,7 @@ setup_script = setups[0] self.build_egg(tmpdir, setup_script) - dist_dir = os.path.join(os.path.dirname(setup_script),'dist') + dist_dir = os.path.join(os.path.dirname(setup_script),'dist') # XXX eggs = [] for egg in glob(os.path.join(dist_dir,'*.egg')): @@ -447,8 +449,6 @@ return eggs - - def egg_distribution(self, egg_path): if os.path.isdir(egg_path): metadata = PathMetadata(egg_path,os.path.join(egg_path,'EGG-INFO')) From pje at users.sourceforge.net Sun Jul 10 07:29:46 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 22:29:46 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools setuptools.txt, 1.4, 1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4863 Modified Files: setuptools.txt Log Message: EasyInstall now builds eggs in a temporary directory alongside the setup script it's running. This avoids it getting confused by projects with non-standard distribution locations, and projects that may have various eggs already sitting in their distribution directory. It should probably also do something like this for the build directory to ensure a clean, fresh build, but it seems like overkill, since it only affects local projects, not stuff that EasyInstall downloaded in the first place. Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- setuptools.txt 10 Jul 2005 04:49:31 -0000 1.4 +++ setuptools.txt 10 Jul 2005 05:29:43 -0000 1.5 @@ -1079,6 +1079,8 @@ This is used by the ``easy_install`` command to find possibly-conflicting "unmanaged" packages when installing the distribution. + * Fixed the swapped ``-d`` and ``-b`` options of ``bdist_egg``. + 0.5a8 * The "egg_info" command now always sets the distribution metadata to "safe" forms of the distribution name and version, so that distribution files will From pje at users.sourceforge.net Sun Jul 10 07:29:46 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 09 Jul 2005 22:29:46 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.5, 1.6 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4863/setuptools/command Modified Files: easy_install.py Log Message: EasyInstall now builds eggs in a temporary directory alongside the setup script it's running. This avoids it getting confused by projects with non-standard distribution locations, and projects that may have various eggs already sitting in their distribution directory. It should probably also do something like this for the build directory to ensure a clean, fresh build, but it seems like overkill, since it only affects local projects, not stuff that EasyInstall downloaded in the first place. Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- easy_install.py 10 Jul 2005 05:06:31 -0000 1.5 +++ easy_install.py 10 Jul 2005 05:29:44 -0000 1.6 @@ -12,7 +12,7 @@ """ import sys, os.path, zipimport, shutil, tempfile, zipfile - +from glob import glob from setuptools import Command from setuptools.sandbox import run_setup from distutils import log, dir_util @@ -412,21 +412,21 @@ # .egg dirs or files are already built, so just return them if dist_filename.lower().endswith('.egg'): return [self.install_egg(dist_filename, True, tmpdir)] - - if dist_filename.lower().endswith('.exe'): + elif dist_filename.lower().endswith('.exe'): return [self.install_exe(dist_filename, tmpdir)] # Anything else, try to extract and build + setup_base = tmpdir if os.path.isfile(dist_filename): unpack_archive(dist_filename, tmpdir, self.unpack_progress) elif os.path.isdir(dist_filename): - tmpdir = dist_filename # ugh + setup_base = os.path.abspath(dist_filename) # Find the setup.py file - from glob import glob - setup_script = os.path.join(tmpdir, 'setup.py') + setup_script = os.path.join(setup_base, 'setup.py') + if not os.path.exists(setup_script): - setups = glob(os.path.join(tmpdir, '*', 'setup.py')) + setups = glob(os.path.join(setup_base, '*', 'setup.py')) if not setups: raise DistutilsError( "Couldn't find a setup script in %s" % dist_filename @@ -437,17 +437,17 @@ ) setup_script = setups[0] - self.build_egg(tmpdir, setup_script) - dist_dir = os.path.join(os.path.dirname(setup_script),'dist') # XXX + # Now run it, and return the result + return self.build_and_install(setup_script, setup_base, zip_ok) + + + + + + - eggs = [] - for egg in glob(os.path.join(dist_dir,'*.egg')): - eggs.append(self.install_egg(egg, zip_ok, tmpdir)) - if not eggs and not self.dry_run: - log.warn("No eggs found in %s (setup script problem?)", dist_dir) - return eggs def egg_distribution(self, egg_path): if os.path.isdir(egg_path): @@ -695,10 +695,10 @@ - def build_egg(self, tmpdir, setup_script): + def build_and_install(self, setup_script, setup_base, zip_ok): sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) - args = ['bdist_egg'] + args = ['bdist_egg', '--dist-dir'] if self.verbose>2: v = 'v' * self.verbose - 1 args.insert(0,'-'+v) @@ -707,33 +707,33 @@ if self.dry_run: args.insert(0,'-n') - log.info("Running %s %s", setup_script[len(tmpdir)+1:], ' '.join(args)) + dist_dir = tempfile.mkdtemp(prefix='egg-dist-tmp-', dir=setup_base) try: + args.append(dist_dir) + log.info( + "Running %s %s", setup_script[len(setup_base)+1:], + ' '.join(args) + ) try: run_setup(setup_script, args) except SystemExit, v: raise DistutilsError( "Setup script exited with %s" % (v.args[0],) ) - finally: - log.set_verbosity(self.verbose) # restore our log verbosity - - - - - - - - - - - - - - + eggs = [] + for egg in glob(os.path.join(dist_dir,'*.egg')): + eggs.append(self.install_egg(egg, zip_ok, setup_base)) + if not eggs and not self.dry_run: + log.warn("No eggs found in %s (setup script problem?)", + dist_dir) + + return eggs + finally: + shutil.rmtree(dist_dir) + log.set_verbosity(self.verbose) # restore our log verbosity def update_pth(self,dist): From pje at users.sourceforge.net Sun Jul 10 17:24:15 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 08:24:15 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.32, 1.33 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3647 Modified Files: EasyInstall.txt Log Message: Add an example of using the new "directory w/setup.py" feature Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.32 retrieving revision 1.33 diff -u -d -r1.32 -r1.33 --- EasyInstall.txt 10 Jul 2005 05:06:30 -0000 1.32 +++ EasyInstall.txt 10 Jul 2005 15:24:12 -0000 1.33 @@ -86,6 +86,11 @@ easy_install --upgrade PyProtocols +**Example 6**. Install a source distribution that's already downloaded and +extracted in the current directory (New in 0.5a9):: + + easy_install . + Easy Install accepts URLs, filenames, PyPI package names (i.e., ``distutils`` "distribution" names), and package+version specifiers. In each case, it will attempt to locate the latest available version that meets your criteria. From pje at users.sourceforge.net Sun Jul 10 17:43:13 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 08:43:13 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.6, 1.7 egg_info.py, 1.5, 1.6 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13460/setuptools/command Modified Files: easy_install.py egg_info.py Log Message: Implement ``namespace_packages`` keyword to ``setup()``. Added keyword summary to setuptools doc. Begin work on ``zip_safe`` flag. Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- easy_install.py 10 Jul 2005 05:29:44 -0000 1.6 +++ easy_install.py 10 Jul 2005 15:43:08 -0000 1.7 @@ -21,7 +21,7 @@ from setuptools.archive_util import unpack_archive from setuptools.package_index import PackageIndex, parse_bdist_wininst from setuptools.package_index import URL_SCHEME -from setuptools.command import bdist_egg +from setuptools.command import bdist_egg, egg_info from pkg_resources import * __all__ = [ @@ -697,6 +697,7 @@ def build_and_install(self, setup_script, setup_base, zip_ok): sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) + sys.modules.setdefault('distutils.command.bdist_egg', egg_info) args = ['bdist_egg', '--dist-dir'] if self.verbose>2: @@ -735,7 +736,6 @@ shutil.rmtree(dist_dir) log.set_verbosity(self.verbose) # restore our log verbosity - def update_pth(self,dist): if self.pth_file is None: return Index: egg_info.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/egg_info.py,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- egg_info.py 10 Jul 2005 04:49:31 -0000 1.5 +++ egg_info.py 10 Jul 2005 15:43:08 -0000 1.6 @@ -9,7 +9,7 @@ from distutils import log from pkg_resources import parse_requirements, safe_name, \ safe_version, yield_lines - +from setuptools.dist import iter_distribution_names class egg_info(Command): @@ -83,8 +83,8 @@ def run(self): # Make the .egg-info directory, then write PKG-INFO and requires.txt self.mkpath(self.egg_info) + log.info("writing %s" % os.path.join(self.egg_info,'PKG-INFO')) - log.info("writing %s" % os.path.join(self.egg_info,'PKG-INFO')) if not self.dry_run: metadata = self.distribution.metadata metadata.version, oldver = self.egg_version, metadata.version @@ -96,15 +96,16 @@ finally: metadata.name, metadata.version = oldname, oldver + self.write_namespace_packages() self.write_requirements() self.write_toplevel_names() + if os.path.exists(os.path.join(self.egg_info,'depends.txt')): log.warn( "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" "Use the install_requires/extras_require setup() args instead." ) - def write_requirements(self): dist = self.distribution if not getattr(dist,'install_requires',None) and \ @@ -120,7 +121,6 @@ f.write('\n\n[%s]\n%s' % (extra, '\n'.join(yield_lines(reqs)))) f.close() - def tagged_version(self): version = self.distribution.get_version() if self.tag_build: @@ -144,16 +144,12 @@ def write_toplevel_names(self): - pkgs = dict.fromkeys(self.distribution.packages or ()) - pkgs.update(dict.fromkeys(self.distribution.py_modules or ())) - for ext in self.distribution.ext_modules or (): - if isinstance(ext,tuple): - name,buildinfo = ext - else: - name = ext.name - pkgs[name]=1 - pkgs = dict.fromkeys([k.split('.',1)[0] for k in pkgs]) - toplevel = os.path.join(self.egg_info,"top_level.txt") + pkgs = dict.fromkeys( + [k.split('.',1)[0] + for k in iter_distribution_names(self.distribution) + ] + ) + toplevel = os.path.join(self.egg_info, "top_level.txt") log.info("writing list of top-level names to %s" % toplevel) if not self.dry_run: f = open(toplevel, 'wt') @@ -162,3 +158,48 @@ f.close() + + + + + def write_namespace_packages(self): + nsp = getattr(self.distribution,'namespace_packages',None) + if nsp is None: + return + + filename = os.path.join(self.egg_info,"namespace_packages.txt") + + if nsp: + log.info("writing %s", filename) + if not self.dry_run: + f = open(filename, 'wt') + f.write('\n'.join(nsp)) + f.write('\n') + f.close() + + elif os.path.exists(filename): + log.info("deleting %s", filename) + if not self.dry_run: + os.unlink(filename) + + + + + + + + + + + + + + + + + + + + + + From pje at users.sourceforge.net Sun Jul 10 17:43:13 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 08:43:13 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools setuptools.txt, 1.5, 1.6 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13460 Modified Files: setuptools.txt Log Message: Implement ``namespace_packages`` keyword to ``setup()``. Added keyword summary to setuptools doc. Begin work on ``zip_safe`` flag. Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- setuptools.txt 10 Jul 2005 05:29:43 -0000 1.5 +++ setuptools.txt 10 Jul 2005 15:43:07 -0000 1.6 @@ -133,6 +133,56 @@ them in your own project(s). +New and Changed ``setup()`` Keywords +==================================== + +The following keyword arguments to ``setup()`` are added or changed by +``setuptools``. All of them are optional; you do not have to supply them +unless you need the associated ``setuptools`` feature. + +``package_data`` + A dictionary mapping package names to lists of glob patterns. For a + complete description and examples, see the section below on `Including + Data Files`_. + +``zip_safe`` + A boolean (True or False) flag specifying whether the project can be + safely installed and run from a zip file. If this argument is not + supplied, the ``bdist_egg`` command will have to analyze all of your + project's contents for possible problems each time it buids an egg. + +``install_requires`` + A string or list of strings specifying what other distributions need to + be installed when this one is. See the section below on `Declaring + Dependencies`_ for details and examples of the format of this argument. + +``extras_require`` + A dictionary mapping names of "extras" (optional features of your project) + to strings or lists of strings specifying what other distributions must be + installed to support those features. See the section below on `Declaring + Dependencies`_ for details and examples of the format of this argument. + +``test_suite`` + A string naming a ``unittest.TestCase`` subclass (or a module containing + one or more of them, or a method of such a subclass), or naming a function + that can be called with no arguments and returns a ``unittest.TestSuite``. + Specifying this argument enables use of the `test`_ command to run the + specified test suite, e.g. via ``setup.py test``. See the section on the + `test`_ command below for more details. + +``namespace_packages`` + A list of strings naming the project's "namespace packages". A namespace + package is a package that may be split across multiple project + distributions. For example, Zope 3's ``zope`` package is a namespace + package, because subpackages like ``zope.interface`` and ``zope.publisher`` + may be distributed separately. The egg runtime system can automatically + merge such subpackages into a single parent package at runtime, as long + as you declare them in each project that contains any subpackages of the + namespace package, and as long as the namespace package's ``__init__.py`` + does not contain any code. See the section below on `Namespace Packages`_ + for more information. + + Declaring Dependencies ====================== @@ -406,7 +456,11 @@ .. _Resource Management API: http://peak.telecommunity.com/DevCenter/PythonEggs#resource-management .. _Accessing Package Resources: http://peak.telecommunity.com/DevCenter/PythonEggs#accessing-package-resources -.. XXX put doc about zip_safe flag here, once it's implemented + +Setting the ``zip_safe`` flag +----------------------------- + +XXX put doc about zip_safe flag here, once it's implemented "Development Mode" @@ -483,6 +537,62 @@ XXX +Namespace Packages +================== + +Sometimes, a large package is more useful if distributed as a collection of +smaller eggs. However, Python does not normally allow the contents of a +package to be retrieved from more than one location. "Namespace packages" +are a solution for this problem. When you declare a package to be a namespace +package, it means that the package has no meaningful contents in its +``__init__.py``, and that it is merely a container for modules and subpackages. + +The ``pkg_resources`` runtime will automatically ensure that the contents of +namespace packages that are spread over multiple eggs or directories are +combined into a single virtual package. + +The ``namespace_packages`` argument to ``setup()`` lets you declare your +project's namespace packages, so that they will be included in your project's +metadata. Then, the runtime will automatically detect this when it adds the +distribution to ``sys.path``, and ensure that the packages are properly merged. + +The argument should list the namespace packages that the egg participates in. +For example, the ZopeInterface project might do this:: + + setup( + # ... + namespace_packages = ['zope'] + ) + +because it contains a ``zope.interface`` package that lives in the ``zope`` +namespace package. Similarly, a project for a standalone ``zope.publisher`` +would also declare the ``zope`` namespace package. + +Namespace packages don't have to be top-level packages. For example, Zope 3's +``zope.app`` package is a namespace package, and in the future PEAK's +``peak.util`` package will be too. + +Note, by the way, that your project's source tree must include the namespace +packages' ``__init__.py`` files (and the ``__init__.py`` of any parent +packages), in a normal Python package layout. These ``__init__.py`` files +should not contain any code or data, because only *one* egg's ``__init__.py`` +files will be used to construct the parent packages in memory at runtime, and +there is no guarantee which egg will be used. + +For example, if both ``zope.interface`` and ``zope.publisher`` have been +installed from separate distributions, it is unspecified which of the two +distributions' ``zope/__init__.py`` files will be used to create the ``zope`` +package in memory. Therefore, it is better not to have any code or data in +a namespace package's ``__init__`` module, so as to prevent any complications. + +(This is one reason the concept is called a "namespace package": it is a +package that exists *only* to provide a namespace under which other modules or +packages are gathered. In Java, for example, namespace packages are often used +just to avoid naming collisions between different projects, using package names +like ``org.apache`` as a namespace for packages that are part of apache.org +projects.) + + ----------------- Command Reference ----------------- @@ -916,6 +1026,8 @@ distutils configuration file the option will be added to (or removed from). +.. _test: + ``test`` - Build package and run a unittest suite ================================================= @@ -1079,6 +1191,8 @@ This is used by the ``easy_install`` command to find possibly-conflicting "unmanaged" packages when installing the distribution. + * Added ``zip_safe`` and ``namespace_packages`` arguments to ``setup()``. + * Fixed the swapped ``-d`` and ``-b`` options of ``bdist_egg``. 0.5a8 From pje at users.sourceforge.net Sun Jul 10 17:43:13 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 08:43:13 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools dist.py, 1.13, 1.14 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13460/setuptools Modified Files: dist.py Log Message: Implement ``namespace_packages`` keyword to ``setup()``. Added keyword summary to setuptools doc. Begin work on ``zip_safe`` flag. Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- dist.py 10 Jul 2005 04:49:31 -0000 1.13 +++ dist.py 10 Jul 2005 15:43:08 -0000 1.14 @@ -90,6 +90,8 @@ self.install_requires = [] self.extras_require = {} self.dist_files = [] + self.zip_safe = None + self.namespace_packages = None _Distribution.__init__(self,attrs) if not have_package_data: from setuptools.command.build_py import build_py @@ -100,19 +102,17 @@ self.cmdclass.setdefault('install_lib',install_lib) self.cmdclass.setdefault('sdist',sdist) + def parse_command_line(self): + """Process features after parsing command line options""" + result = _Distribution.parse_command_line(self) + if self.features: + self._finalize_features() + return result - - - - - - - - - - - + def _feature_attrname(self,name): + """Convert feature name to corresponding option attribute name""" + return 'with_'+name.replace('-','_') @@ -123,10 +123,8 @@ def finalize_options(self): _Distribution.finalize_options(self) - if self.features: self._set_global_opts_from_features() - if self.extra_path: raise DistutilsSetupError( "The 'extra_path' parameter is not needed when using " @@ -148,19 +146,21 @@ "strings or lists of strings containing valid project/version " "requirement specifiers." ) - - def parse_command_line(self): - """Process features after parsing command line options""" - result = _Distribution.parse_command_line(self) - if self.features: - self._finalize_features() - return result - - - def _feature_attrname(self,name): - """Convert feature name to corresponding option attribute name""" - return 'with_'+name.replace('-','_') - + if self.namespace_packages is not None: + try: + assert ''.join(self.namespace_packages)!=self.namespace_packages + except (TypeError,ValueError,AttributeError,AssertionError): + raise DistutilsSetupError( + "'namespace_packages' must be a sequence of strings" + ) + for nsp in self.namespace_packages: + for name in iter_distribution_names(self): + if name.startswith(nsp+'.'): break + else: + raise DistutilsSetupError( + "Distribution contains no modules or packages for " + + "namespace package %r" % nsp + ) def _set_global_opts_from_features(self): """Add --with-X/--without-X options based on optional features""" @@ -490,6 +490,47 @@ return d +def iter_distribution_names(distribution): + """Yield all packages, modules, and extensions declared by distribution""" + + for pkg in distribution.packages or (): + yield pkg + + for module in distribution.py_modules or (): + yield module + + for ext in distribution.ext_modules or (): + if isinstance(ext,tuple): + name,buildinfo = ext + yield name + else: + yield ext.name + + + + + + + + + + + + + + + + + + + + + + + + + + class Feature: """A subset of the distribution that can be excluded if unneeded/wanted From pje at users.sourceforge.net Sun Jul 10 18:24:29 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 09:24:29 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command bdist_egg.py, 1.24, 1.25 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1678/setuptools/command Modified Files: bdist_egg.py Log Message: First-pass implementation of zippability analysis; scans for impure distribution or use of __file__/__path__ and selected 'inspect' operations. Currently, the analysis is a bit overconservative; when the runtime is more robust, it should probably allow extensions to be zipped by default. Index: bdist_egg.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/bdist_egg.py,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- bdist_egg.py 10 Jul 2005 05:06:31 -0000 1.24 +++ bdist_egg.py 10 Jul 2005 16:24:26 -0000 1.25 @@ -3,13 +3,13 @@ Build .egg distributions""" # This module should be kept compatible with Python 2.3 -import os +import os, marshal from setuptools import Command from distutils.dir_util import remove_tree, mkpath from distutils.sysconfig import get_python_version, get_python_lib from distutils import log from pkg_resources import get_platform, Distribution - +from types import CodeType def write_stub(resource, pyfile): f = open(pyfile,'w') @@ -175,11 +175,12 @@ ext_outputs = cmd._mutate_outputs( self.distribution.has_ext_modules(), 'build_ext', 'build_lib', '' ) - + self.stubs = [] to_compile = [] for (p,ext_name) in enumerate(ext_outputs): filename,ext = os.path.splitext(ext_name) pyfile = os.path.join(self.bdist_dir, filename + '.py') + self.stubs.append(pyfile) log.info("creating stub loader for %s" % ext_name) if not self.dry_run: write_stub(os.path.basename(ext_name), pyfile) @@ -202,7 +203,6 @@ log.info("installing scripts to %s" % script_dir) self.call_command('install_scripts', install_dir=script_dir) - native_libs = os.path.join(self.egg_info,"native_libs.txt") if ext_outputs: log.info("writing %s" % native_libs) @@ -221,6 +221,10 @@ if os.path.isfile(path): self.copy_file(path,os.path.join(egg_info,filename)) + # Write a zip safety flag file + flag = self.zip_safe() and 'zip-safe' or 'not-zip-safe' + open(os.path.join(archive_root,'EGG-INFO',flag),'w').close() + if os.path.exists(os.path.join(self.egg_info,'depends.txt')): log.warn( "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" @@ -240,49 +244,86 @@ ('bdist_egg',get_python_version(),self.egg_output)) - - - - def zap_pyfiles(self): log.info("Removing .py files from temporary directory") - for base,dirs,files in os.walk(self.bdist_dir): - if 'EGG-INFO' in dirs: - dirs.remove('EGG-INFO') + for base,dirs,files in self.walk_contents(): for name in files: if name.endswith('.py'): path = os.path.join(base,name) log.debug("Deleting %s", path) os.unlink(path) + def walk_contents(self): + """Walk files about to be archived, skipping the metadata directory""" + walker = os.walk(self.bdist_dir) + base,dirs,files = walker.next() + if 'EGG-INFO' in dirs: + dirs.remove('EGG-INFO') + yield base,dirs,files + for bdf in walker: + yield bdf + + def zip_safe(self): + safe = getattr(self.distribution,'zip_safe',None) + if safe is not None: + return safe + log.warn("zip_safe flag not set; analyzing archive contents...") + safe = True + for base, dirs, files in self.walk_contents(): + for name in files: + if name.endswith('.py') or name.endswith('.pyw'): + continue + elif name.endswith('.pyc') or name.endswith('.pyo'): + # always scan, even if we already know we're not safe + safe = self.scan_module(base, name) and safe + elif safe: + log.warn( + "Distribution contains data or extensions; assuming " + "it's unsafe (set zip_safe=True in setup() to change" + ) + safe = False # XXX + return safe + def scan_module(self, base, name): + """Check whether module possibly uses unsafe-for-zipfile stuff""" + filename = os.path.join(base,name) + if filename[:-1] in self.stubs: + return True # Extension module + pkg = base[len(self.bdist_dir)+1:].replace(os.sep,'.') + module = pkg+(pkg and '.' or '')+os.path.splitext(name)[0] + f = open(filename,'rb'); f.read(8) # skip magic & date + code = marshal.load(f); f.close() + safe = True + symbols = dict.fromkeys(iter_symbols(code)) + for bad in ['__file__', '__path__']: + if bad in symbols: + log.warn("%s: module references %s", module, bad) + safe = False + if 'inspect' in symbols: + for bad in [ + 'getsource', 'getabsfile', 'getsourcefile', 'getfile' + 'getsourcelines', 'findsource', 'getcomments', 'getframeinfo', + 'getinnerframes', 'getouterframes', 'stack', 'trace' + ]: + if bad in symbols: + log.warn("%s: module MAY be using inspect.%s", module, bad) + safe = False + return safe - - - - - - - - - - - - - - - - - - - - - +def iter_symbols(code): + """Yield names and strings used by `code` and its nested code objects""" + for name in code.co_names: yield name + for const in code.co_consts: + if isinstance(const,basestring): + yield const + elif isinstance(const,CodeType): + for name in iter_symbols(const): + yield name # Attribute names of options for commands that might need to be convinced to From tim_one at users.sourceforge.net Sun Jul 10 22:37:53 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 10 Jul 2005 13:37:53 -0700 Subject: [Python-checkins] python/dist/src/Tools/bgen/bgen bgenBuffer.py, 1.12, 1.13 bgenGenerator.py, 1.22, 1.23 bgenHeapBuffer.py, 1.7, 1.8 bgenObjectDefinition.py, 1.33, 1.34 bgenType.py, 1.19, 1.20 bgenVariable.py, 1.10, 1.11 scantools.py, 1.40, 1.41 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/bgen/bgen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8194/Tools/bgen/bgen Modified Files: bgenBuffer.py bgenGenerator.py bgenHeapBuffer.py bgenObjectDefinition.py bgenType.py bgenVariable.py scantools.py Log Message: Whitespace normalization. Index: bgenBuffer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenBuffer.py,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- bgenBuffer.py 5 Jul 2005 10:00:57 -0000 1.12 +++ bgenBuffer.py 10 Jul 2005 20:37:50 -0000 1.13 @@ -41,23 +41,23 @@ def getArgDeclarations(self, name, reference=False, constmode=False): if reference: raise RuntimeError, "Cannot pass buffer types by reference" - return (self.getBufferDeclarations(name, constmode) + + return (self.getBufferDeclarations(name, constmode) + self.getSizeDeclarations(name)) def getBufferDeclarations(self, name, constmode=False): return self.getInputBufferDeclarations(name, constmode) + \ - self.getOutputBufferDeclarations(name, constmode) + self.getOutputBufferDeclarations(name, constmode) def getInputBufferDeclarations(self, name, constmode=False): - if constmode: - const = "const " - else: - const = "" + if constmode: + const = "const " + else: + const = "" return ["%s%s *%s__in__" % (const, self.datatype, name)] def getOutputBufferDeclarations(self, name, constmode=False): - if constmode: - raise RuntimeError, "Cannot use const output buffer" + if constmode: + raise RuntimeError, "Cannot use const output buffer" return ["%s %s__out__[%s]" % (self.datatype, name, self.size)] def getSizeDeclarations(self, name): @@ -194,21 +194,21 @@ self.typeName = self.type = type def getInputBufferDeclarations(self, name, constmode=False): - if constmode: - const = "const " - else: - const = "" + if constmode: + const = "const " + else: + const = "" return ["%s%s *%s__in__" % (const, self.type, name)] def getSizeDeclarations(self, name): return [] - + def getAuxDeclarations(self, name): return ["int %s__in_len__" % (name)] def getOutputBufferDeclarations(self, name, constmode=False): - if constmode: - raise RuntimeError, "Cannot use const output buffer" + if constmode: + raise RuntimeError, "Cannot use const output buffer" return ["%s %s__out__" % (self.type, name)] def getargsArgs(self, name): Index: bgenGenerator.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenGenerator.py,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- bgenGenerator.py 3 Jul 2005 20:58:08 -0000 1.22 +++ bgenGenerator.py 10 Jul 2005 20:37:50 -0000 1.23 @@ -32,7 +32,7 @@ def checkgenerate(self): return True - + def generate(self): if not self.checkgenerate(): return @@ -234,7 +234,7 @@ return "%s = " % self.rv.name else: return "" - + def checkit(self): for arg in self.argumentList: arg.errorCheck() Index: bgenHeapBuffer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenHeapBuffer.py,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- bgenHeapBuffer.py 5 Jul 2005 10:00:57 -0000 1.7 +++ bgenHeapBuffer.py 10 Jul 2005 20:37:50 -0000 1.8 @@ -17,8 +17,8 @@ FixedInputOutputBufferType.__init__(self, "0", datatype, sizetype, sizeformat) def getOutputBufferDeclarations(self, name, constmode=False): - if constmode: - raise RuntimeError, "Cannot use const output buffer" + if constmode: + raise RuntimeError, "Cannot use const output buffer" return ["%s *%s__out__" % (self.datatype, name)] def getargsCheck(self, name): Index: bgenObjectDefinition.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenObjectDefinition.py,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- bgenObjectDefinition.py 8 Jul 2005 15:03:37 -0000 1.33 +++ bgenObjectDefinition.py 10 Jul 2005 20:37:50 -0000 1.34 @@ -220,7 +220,7 @@ Output("""Py_INCREF(&%s);""", self.typename) Output("PyModule_AddObject(m, \"%s\", (PyObject *)&%s);", self.name, self.typename); self.outputTypeObjectInitializerCompat() - + def outputTypeObjectInitializerCompat(self): Output("/* Backward-compatible name */") Output("""Py_INCREF(&%s);""", self.typename); Index: bgenType.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenType.py,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- bgenType.py 5 Jul 2005 10:00:57 -0000 1.19 +++ bgenType.py 10 Jul 2005 20:37:50 -0000 1.20 @@ -47,7 +47,7 @@ type, such as helper variables used to hold sizes, etc. These declarations are not part of the C/C++ function call interface.""" return [] - + def getargs(self): return self.getargsFormat(), self.getargsArgs() @@ -68,10 +68,10 @@ def getargsPreCheck(self, name): """Perform any actions needed before calling getargs(). - + This could include declaring temporary variables and such. """ - + def getargsCheck(self, name): """Perform any needed post-[new]getargs() checks. @@ -133,10 +133,10 @@ def mkvaluePreCheck(self, name): """Perform any actions needed before calling mkvalue(). - + This could include declaring temporary variables and such. """ - + def cleanup(self, name): """Clean up if necessary. Index: bgenVariable.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/bgenVariable.py,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- bgenVariable.py 5 Jul 2005 10:00:57 -0000 1.10 +++ bgenVariable.py 10 Jul 2005 20:37:51 -0000 1.11 @@ -48,10 +48,10 @@ def getArgDeclarations(self, constmode=False): refmode = (self.flags & RefMode) if constmode: - constmode = (self.flags & ConstMode) + constmode = (self.flags & ConstMode) return self.type.getArgDeclarations(self.name, - reference=refmode, constmode=constmode) - + reference=refmode, constmode=constmode) + def getAuxDeclarations(self): return self.type.getAuxDeclarations(self.name) Index: scantools.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/scantools.py,v retrieving revision 1.40 retrieving revision 1.41 diff -u -d -r1.40 -r1.41 --- scantools.py 29 Jun 2005 14:17:05 -0000 1.40 +++ scantools.py 10 Jul 2005 20:37:51 -0000 1.41 @@ -626,7 +626,7 @@ def destination(self, type, name, arglist): return "FunctionGenerator", "functions" - + def generatemodifiers(self, classname, name, modifiers): pass From tim_one at users.sourceforge.net Mon Jul 11 00:30:57 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 10 Jul 2005 15:30:57 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1311,1.1312 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv537/Misc Modified Files: NEWS Log Message: SF bug 1185883: PyObject_Realloc can't safely take over a block currently managed by C, because it's possible for the block to be smaller than the new requested size, and at the end of allocated VM. Trying to copy over nbytes bytes to a Python small-object block can segfault then, and there's no portable way to avoid this (we would have to know how many bytes starting at p are addressable, and std C has no means to determine that). Bugfix candidate. Should be backported to 2.4, but I'm out of time. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1311 retrieving revision 1.1312 diff -u -d -r1.1311 -r1.1312 --- NEWS 8 Jul 2005 22:26:13 -0000 1.1311 +++ NEWS 10 Jul 2005 22:30:52 -0000 1.1312 @@ -12,6 +12,15 @@ Core and builtins ----------------- +- SF bug #1185883: Python's small-object memory allocator took over + a block managed by the platform C library whenever a realloc specified + a small new size. However, there's no portable way to know then how + much of the address space following the pointer is valid, so no + portable way to copy data from the C-managed block into Python's + small-object space without risking a memory fault. Python's small-object + realloc now leaves such blocks under the control of the platform C + realloc. + - SF bug #1232517: An overflow error was not detected properly when attempting to convert a large float to an int in os.utime(). @@ -59,7 +68,7 @@ - Bug #1165306: instancemethod_new allowed the creation of a method with im_class == im_self == NULL, which caused a crash when called. -- Move exception finalisation later in the shutdown process - this +- Move exception finalisation later in the shutdown process - this fixes the crash seen in bug #1165761 - Added two new builtins, any() and all(). @@ -74,7 +83,7 @@ - Bug #1155938: new style classes did not check that __init__() was returning None. -- Patch #802188: Report characters after line continuation character +- Patch #802188: Report characters after line continuation character ('\') with a specific error message. - Bug #723201: Raise a TypeError for passing bad objects to 'L' format. @@ -82,7 +91,7 @@ - Bug #1124295: the __name__ attribute of file objects was inadvertently made inaccessible in restricted mode. -- Bug #1074011: closing sys.std{out,err} now causes a flush() and +- Bug #1074011: closing sys.std{out,err} now causes a flush() and an ferror() call. - min() and max() now support key= arguments with the same meaning as in @@ -103,7 +112,7 @@ Extension Modules ----------------- -- Bug #1234979: For the argument of thread.Lock.acquire, the Windows +- Bug #1234979: For the argument of thread.Lock.acquire, the Windows implemented treated all integer values except 1 as false. - Bug #1194181: bz2.BZ2File didn't handle mode 'U' correctly. @@ -128,7 +137,7 @@ - Patches #925152, #1118602: Avoid reading after the end of the buffer in pyexpat.GetInputContext. -- Patches #749830, #1144555: allow UNIX mmap size to default to current +- Patches #749830, #1144555: allow UNIX mmap size to default to current file size. - Added functional.partial(). See PEP309. @@ -201,7 +210,7 @@ - Bug #1163325: Decimal infinities failed to hash. Attempting to hash a NaN raised an InvalidOperation instead of a TypeError. -- Patch #918101: Add tarfile open mode r|* for auto-detection of the +- Patch #918101: Add tarfile open mode r|* for auto-detection of the stream compression; add, for symmetry reasons, r:* as a synonym of r. - Patch #1043890: Add extractall method to tarfile. @@ -212,7 +221,7 @@ - Patch #1103407: Properly deal with tarfile iterators when untarring symbolic links on Windows. -- Patch #645894: Use getrusage for computing the time consumption in +- Patch #645894: Use getrusage for computing the time consumption in profile.py if available. - Patch #1046831: Use get_python_version where appropriate in sysconfig.py. @@ -250,7 +259,7 @@ + Dialects are now validated by the underlying C code, better reflecting it's capabilities, and improving it's compliance with - PEP 305. + PEP 305. + Dialect parameter parsing has been re-implemented to improve error reporting. + quotechar=None and quoting=QUOTE_NONE now work the way PEP 305 From tim_one at users.sourceforge.net Mon Jul 11 00:30:58 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 10 Jul 2005 15:30:58 -0700 Subject: [Python-checkins] python/dist/src/Objects obmalloc.c,2.53,2.54 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv537/Objects Modified Files: obmalloc.c Log Message: SF bug 1185883: PyObject_Realloc can't safely take over a block currently managed by C, because it's possible for the block to be smaller than the new requested size, and at the end of allocated VM. Trying to copy over nbytes bytes to a Python small-object block can segfault then, and there's no portable way to avoid this (we would have to know how many bytes starting at p are addressable, and std C has no means to determine that). Bugfix candidate. Should be backported to 2.4, but I'm out of time. Index: obmalloc.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/obmalloc.c,v retrieving revision 2.53 retrieving revision 2.54 diff -u -d -r2.53 -r2.54 --- obmalloc.c 6 Jun 2004 19:21:34 -0000 2.53 +++ obmalloc.c 10 Jul 2005 22:30:55 -0000 2.54 @@ -139,9 +139,9 @@ * getpagesize() call or deduced from various header files. To make * things simpler, we assume that it is 4K, which is OK for most systems. * It is probably better if this is the native page size, but it doesn't - * have to be. In theory, if SYSTEM_PAGE_SIZE is larger than the native page - * size, then `POOL_ADDR(p)->arenaindex' could rarely cause a segmentation - * violation fault. 4K is apparently OK for all the platforms that python + * have to be. In theory, if SYSTEM_PAGE_SIZE is larger than the native page + * size, then `POOL_ADDR(p)->arenaindex' could rarely cause a segmentation + * violation fault. 4K is apparently OK for all the platforms that python * currently targets. */ #define SYSTEM_PAGE_SIZE (4 * 1024) @@ -841,30 +841,26 @@ } return bp; } - /* We're not managing this block. */ - if (nbytes <= SMALL_REQUEST_THRESHOLD) { - /* Take over this block -- ask for at least one byte so - * we really do take it over (PyObject_Malloc(0) goes to - * the system malloc). - */ - bp = PyObject_Malloc(nbytes ? nbytes : 1); - if (bp != NULL) { - memcpy(bp, p, nbytes); - free(p); - } - else if (nbytes == 0) { - /* Meet the doc's promise that nbytes==0 will - * never return a NULL pointer when p isn't NULL. - */ - bp = p; - } - - } - else { - assert(nbytes != 0); - bp = realloc(p, nbytes); - } - return bp; + /* We're not managing this block. If nbytes <= + * SMALL_REQUEST_THRESHOLD, it's tempting to try to take over this + * block. However, if we do, we need to copy the valid data from + * the C-managed block to one of our blocks, and there's no portable + * way to know how much of the memory space starting at p is valid. + * As bug 1185883 pointed out the hard way, it's possible that the + * C-managed block is "at the end" of allocated VM space, so that + * a memory fault can occur if we try to copy nbytes bytes starting + * at p. Instead we punt: let C continue to manage this block. + */ + if (nbytes) + return realloc(p, nbytes); + /* C doesn't define the result of realloc(p, 0) (it may or may not + * return NULL then), but Python's docs promise that nbytes==0 never + * returns NULL. We don't pass 0 to realloc(), to avoid that endcase + * to begin with. Even then, we can't be sure that realloc() won't + * return NULL. + */ + bp = realloc(p, 1); + return bp ? bp : p; } #else /* ! WITH_PYMALLOC */ From bcannon at users.sourceforge.net Mon Jul 11 05:20:42 2005 From: bcannon at users.sourceforge.net (bcannon@users.sourceforge.net) Date: Sun, 10 Jul 2005 20:20:42 -0700 Subject: [Python-checkins] python/dist/src/Python compile.txt, 1.1.2.15, 1.1.2.16 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24085/Python Modified Files: Tag: ast-branch compile.txt Log Message: Flesh out file list to include things that were broken out of Python/compile.c . Index: compile.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/compile.txt,v retrieving revision 1.1.2.15 retrieving revision 1.1.2.16 diff -u -d -r1.1.2.15 -r1.1.2.16 --- compile.txt 19 Apr 2005 05:42:00 -0000 1.1.2.15 +++ compile.txt 11 Jul 2005 03:20:39 -0000 1.1.2.16 @@ -271,13 +271,12 @@ is to convert the AST to Python bytecode without having jump targets resolved to specific offsets (this is calculated when the CFG goes to final bytecode). Essentially, this transforms the AST into Python -bytecode, but with control flow represented by the edges of the CFG. +bytecode with control flow represented by the edges of the CFG. Conversion is done in two passes. The first creates the namespace (variables can be classified as local, free/cell for closures, or -global) creates CFG with the namespace info. With that done the second -pass is done which essentially flattens the CFG into a list and -calculates jump offsets for final output of bytecode. +global). With that done, the second pass essentially flattens the CFG +into a list and calculates jump offsets for final output of bytecode. The conversion process is initiated by a call to the function in Python/newcompile.c:: @@ -436,6 +435,10 @@ - newcompile.c New version of compile.c that handles the emitting of bytecode. + - symtable.c + Generates symbol table from AST. + + + Include/ - Python-ast.h @@ -449,9 +452,27 @@ - ast.h Declares PyAST_FromNode() external (from ../Python/ast.c). + - code.h + Header file for ../Objects/codeobject.c; contains definition of + PyCodeObject. + + - symtable.h + Header for ../Python/symtable.c . struct symtable and + PySTEntryObject are defined here. + ++ Objects/ + + - codeobject.c + Contains PyCodeObject-related code (originally in + ../Python/compile.c). + ToDo ---- +*** NOTE: all bugs and patches should be filed on SF under the group + "AST" for easy searching. It also does not hurt to put + "[AST]" at the beginning of the subject line of the tracker + item. + Stdlib support - AST->Python access? @@ -459,7 +480,8 @@ + Documentation - flesh out this doc * byte stream output - * explanation of how symbol table pass works + * explanation of how the symbol table pass works + * code object (PyCodeObject) + Universal - make sure entire test suite passes - fix memory leaks From bcannon at users.sourceforge.net Mon Jul 11 05:37:14 2005 From: bcannon at users.sourceforge.net (bcannon@users.sourceforge.net) Date: Sun, 10 Jul 2005 20:37:14 -0700 Subject: [Python-checkins] python/dist/src/Objects codeobject.c, 1.1.2.2, 1.1.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv480/Objects Modified Files: Tag: ast-branch codeobject.c Log Message: When comparing code objects, also take into account which line they start on. This fixes bug #1190011 where code objects were comparing equal. Fixed with code from HEAD that fixed the same problem. Thanks Nick Coghlan for pulling the code from mwh's fix. Index: codeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/Attic/codeobject.c,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -d -r1.1.2.2 -r1.1.2.3 --- codeobject.c 23 Aug 2002 18:20:24 -0000 1.1.2.2 +++ codeobject.c 11 Jul 2005 03:37:11 -0000 1.1.2.3 @@ -239,6 +239,8 @@ if (cmp) return cmp; cmp = co->co_flags - cp->co_flags; if (cmp) return cmp; + cmp = co->co_firstlineno - cp->co_firstlineno; + if (cmp) return cmp; cmp = PyObject_Compare(co->co_code, cp->co_code); if (cmp) return cmp; cmp = PyObject_Compare(co->co_consts, cp->co_consts); From bcannon at users.sourceforge.net Mon Jul 11 05:43:59 2005 From: bcannon at users.sourceforge.net (bcannon@users.sourceforge.net) Date: Sun, 10 Jul 2005 20:43:59 -0700 Subject: [Python-checkins] python/dist/src/Python newcompile.c, 1.1.2.108, 1.1.2.109 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4319/Python Modified Files: Tag: ast-branch newcompile.c Log Message: Factor out argument parsing and fix to handle tuple unpacking. Fixes bug #1186353. Thanks Nick Coghlan. Index: newcompile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/newcompile.c,v retrieving revision 1.1.2.108 retrieving revision 1.1.2.109 diff -u -d -r1.1.2.108 -r1.1.2.109 --- newcompile.c 2 Jun 2005 05:14:34 -0000 1.1.2.108 +++ newcompile.c 11 Jul 2005 03:43:56 -0000 1.1.2.109 @@ -1380,6 +1380,30 @@ } static int +compiler_arguments(struct compiler *c, arguments_ty args) +{ + int i; + int n = asdl_seq_LEN(args->args); + /* Correctly handle nested argument lists */ + for (i = 0; i < n; i++) { + expr_ty arg = asdl_seq_GET(args->args, i); + if (arg->kind == Tuple_kind) { + PyObject *id = PyString_FromFormat(".%d", i); + if (id == NULL) { + return 0; + } + if (!compiler_nameop(c, id, Load)) { + Py_DECREF(id); + return 0; + } + Py_DECREF(id); + VISIT(c, expr, arg); + } + } + return 1; +} + +static int compiler_function(struct compiler *c, stmt_ty s) { PyCodeObject *co; @@ -1407,21 +1431,7 @@ return 0; /* unpack nested arguments */ - n = asdl_seq_LEN(args->args); - for (i = 0; i < n; i++) { - expr_ty arg = asdl_seq_GET(args->args, i); - if (arg->kind == Tuple_kind) { - PyObject *id = PyString_FromFormat(".%d", i); - if (id == NULL) - return 0; - if (!compiler_nameop(c, id, Load)) { - Py_DECREF(id); - return 0; - } - Py_DECREF(id); - VISIT(c, expr, arg); - } - } + compiler_arguments(c, args); c->u->u_argcount = asdl_seq_LEN(args->args); n = asdl_seq_LEN(s->v.FunctionDef.body); @@ -1513,6 +1523,10 @@ VISIT_SEQ(c, expr, args->defaults); if (!compiler_enter_scope(c, name, (void *)e, c->u->u_lineno)) return 0; + + /* unpack nested arguments */ + compiler_arguments(c, args); + c->u->u_argcount = asdl_seq_LEN(args->args); VISIT(c, expr, e->v.Lambda.body); ADDOP(c, RETURN_VALUE); From bcannon at users.sourceforge.net Mon Jul 11 05:52:50 2005 From: bcannon at users.sourceforge.net (bcannon@users.sourceforge.net) Date: Sun, 10 Jul 2005 20:52:50 -0700 Subject: [Python-checkins] python/dist/src/Python symtable.c, 2.10.8.33, 2.10.8.34 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9074/Python Modified Files: Tag: ast-branch symtable.c Log Message: Fix genexps so that scoping handled properly. Also added checks for error returns from symtable_exit_block(). Fixes bug #1186195 and applies the attached patch. Thanks Nick Coghlan. Index: symtable.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v retrieving revision 2.10.8.33 retrieving revision 2.10.8.34 diff -u -d -r2.10.8.33 -r2.10.8.34 --- symtable.c 19 Apr 2005 19:05:14 -0000 2.10.8.33 +++ symtable.c 11 Jul 2005 03:52:47 -0000 2.10.8.34 @@ -157,6 +157,7 @@ static int symtable_exit_block(struct symtable *st, void *ast); static int symtable_visit_stmt(struct symtable *st, stmt_ty s); static int symtable_visit_expr(struct symtable *st, expr_ty s); +static int symtable_visit_genexp(struct symtable *st, expr_ty s); static int symtable_visit_arguments(struct symtable *st, arguments_ty); static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty); static int symtable_visit_alias(struct symtable *st, alias_ty); @@ -236,7 +237,8 @@ "this compiler does not handle Suites"); return NULL; } - symtable_exit_block(st, (void *)mod); + if (!symtable_exit_block(st, (void *)mod)) + return NULL; if (symtable_analyze(st)) return st; error: @@ -737,8 +739,12 @@ return 1; } -/* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use - the ASDL name to synthesize the name of the C type and the visit function. +/* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument. + They use the ASDL name to synthesize the name of the C type and the visit + function. + + VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is + useful if the first node in the sequence requires special treatment. */ #define VISIT(ST, TYPE, V) \ @@ -755,6 +761,16 @@ } \ } +#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \ + int i; \ + asdl_seq *seq = (SEQ); /* avoid variable capture */ \ + for (i = (START); i < asdl_seq_LEN(seq); i++) { \ + TYPE ## _ty elt = asdl_seq_GET(seq, i); \ + if (!symtable_visit_ ## TYPE((ST), elt)) \ + return 0; \ + } \ +} + static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { @@ -934,7 +950,8 @@ return 0; VISIT(st, arguments, e->v.Lambda.args); VISIT(st, expr, e->v.Lambda.body); - symtable_exit_block(st, (void *)e); + if (!symtable_exit_block(st, (void *)e)) + return 0; break; } case Dict_kind: @@ -955,19 +972,9 @@ break; } case GeneratorExp_kind: { - identifier tmp; - - /* XXX this is correct/complete */ - tmp = PyString_FromString(""); - if (!symtable_enter_block(st, tmp, FunctionBlock, - (void *)e, 0)) - return 0; - if (!symtable_implicit_arg(st, 0)) + if (!symtable_visit_genexp(st, e)) { return 0; - VISIT(st, expr, e->v.GeneratorExp.elt); - VISIT_SEQ(st, comprehension, e->v.GeneratorExp.generators); - st->st_cur->ste_generator = 1; - symtable_exit_block(st, (void *)e); + } break; } case Compare_kind: @@ -1170,3 +1177,29 @@ return 1; } +static int +symtable_visit_genexp(struct symtable *st, expr_ty e) +{ + identifier tmp; + comprehension_ty outermost = ((comprehension_ty) + (asdl_seq_GET(e->v.GeneratorExp.generators, 0))); + /* Outermost iterator is evaluated in current scope */ + VISIT(st, expr, outermost->iter); + /* Create generator scope for the rest */ + tmp = PyString_FromString(""); + if (!symtable_enter_block(st, tmp, FunctionBlock, (void *)e, 0)) { + return 0; + } + st->st_cur->ste_generator = 1; + /* Outermost iter is received as an argument */ + if (!symtable_implicit_arg(st, 0)) { + return 0; + } + VISIT(st, expr, outermost->target); + VISIT_SEQ(st, expr, outermost->ifs); + VISIT_SEQ_TAIL(st, comprehension, e->v.GeneratorExp.generators, 1); + VISIT(st, expr, e->v.GeneratorExp.elt); + if (!symtable_exit_block(st, (void *)e)) + return 0; + return 1; +} From bcannon at users.sourceforge.net Mon Jul 11 06:03:14 2005 From: bcannon at users.sourceforge.net (bcannon@users.sourceforge.net) Date: Sun, 10 Jul 2005 21:03:14 -0700 Subject: [Python-checkins] python/dist/src/Objects codeobject.c, 1.1.2.3, 1.1.2.4 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14339/Objects Modified Files: Tag: ast-branch codeobject.c Log Message: Make sure that code_compare() returns -1, 0, or 1 only. Prevents a warning that pops up when you run regrtest. Index: codeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/Attic/codeobject.c,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -d -r1.1.2.3 -r1.1.2.4 --- codeobject.c 11 Jul 2005 03:37:11 -0000 1.1.2.3 +++ codeobject.c 11 Jul 2005 04:03:11 -0000 1.1.2.4 @@ -234,13 +234,13 @@ cmp = PyObject_Compare(co->co_name, cp->co_name); if (cmp) return cmp; cmp = co->co_argcount - cp->co_argcount; - if (cmp) return cmp; + if (cmp) goto normalize; cmp = co->co_nlocals - cp->co_nlocals; - if (cmp) return cmp; + if (cmp) goto normalize; cmp = co->co_flags - cp->co_flags; - if (cmp) return cmp; + if (cmp) goto normalize; cmp = co->co_firstlineno - cp->co_firstlineno; - if (cmp) return cmp; + if (cmp) goto normalize; cmp = PyObject_Compare(co->co_code, cp->co_code); if (cmp) return cmp; cmp = PyObject_Compare(co->co_consts, cp->co_consts); @@ -253,6 +253,14 @@ if (cmp) return cmp; cmp = PyObject_Compare(co->co_cellvars, cp->co_cellvars); return cmp; + + normalize: + if (cmp > 0) + return 1; + else if (cmp < 0) + return -1; + else + return 0; } static long From pje at users.sourceforge.net Mon Jul 11 06:12:51 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 21:12:51 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command bdist_egg.py, 1.25, 1.26 easy_install.py, 1.7, 1.8 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17477/setuptools/command Modified Files: bdist_egg.py easy_install.py Log Message: Enhanced "zip safety" analysis (including scan of win32.exe's) and have EasyInstall act on zip safety flags. Add a lot more docs for setuptools. Index: bdist_egg.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/bdist_egg.py,v retrieving revision 1.25 retrieving revision 1.26 diff -u -d -r1.25 -r1.26 --- bdist_egg.py 10 Jul 2005 16:24:26 -0000 1.25 +++ bdist_egg.py 11 Jul 2005 04:12:48 -0000 1.26 @@ -221,9 +221,7 @@ if os.path.isfile(path): self.copy_file(path,os.path.join(egg_info,filename)) - # Write a zip safety flag file - flag = self.zip_safe() and 'zip-safe' or 'not-zip-safe' - open(os.path.join(archive_root,'EGG-INFO',flag),'w').close() + write_safety_flag(archive_root, self.zip_safe()) if os.path.exists(os.path.join(self.egg_info,'depends.txt')): log.warn( @@ -231,8 +229,9 @@ "Use the install_requires/extras_require setup() args instead." ) - if self.exclude_source_files: self.zap_pyfiles() - + if self.exclude_source_files: + self.zap_pyfiles() + # Make the archive make_zipfile(self.egg_output, archive_root, verbose=self.verbose, dry_run=self.dry_run) @@ -244,77 +243,119 @@ ('bdist_egg',get_python_version(),self.egg_output)) + def zap_pyfiles(self): log.info("Removing .py files from temporary directory") - for base,dirs,files in self.walk_contents(): + for base,dirs,files in walk_egg(self.bdist_dir): for name in files: if name.endswith('.py'): path = os.path.join(base,name) log.debug("Deleting %s", path) os.unlink(path) - def walk_contents(self): - """Walk files about to be archived, skipping the metadata directory""" - walker = os.walk(self.bdist_dir) - base,dirs,files = walker.next() - if 'EGG-INFO' in dirs: - dirs.remove('EGG-INFO') - - yield base,dirs,files - for bdf in walker: - yield bdf - def zip_safe(self): safe = getattr(self.distribution,'zip_safe',None) if safe is not None: return safe log.warn("zip_safe flag not set; analyzing archive contents...") - safe = True - for base, dirs, files in self.walk_contents(): - for name in files: - if name.endswith('.py') or name.endswith('.pyw'): - continue - elif name.endswith('.pyc') or name.endswith('.pyo'): - # always scan, even if we already know we're not safe - safe = self.scan_module(base, name) and safe - elif safe: - log.warn( - "Distribution contains data or extensions; assuming " - "it's unsafe (set zip_safe=True in setup() to change" - ) - safe = False # XXX - return safe + return analyze_egg(self.bdist_dir, self.stubs) + + + + + + + + + + + + + + - def scan_module(self, base, name): - """Check whether module possibly uses unsafe-for-zipfile stuff""" - filename = os.path.join(base,name) - if filename[:-1] in self.stubs: - return True # Extension module - pkg = base[len(self.bdist_dir)+1:].replace(os.sep,'.') - module = pkg+(pkg and '.' or '')+os.path.splitext(name)[0] - f = open(filename,'rb'); f.read(8) # skip magic & date - code = marshal.load(f); f.close() - safe = True - symbols = dict.fromkeys(iter_symbols(code)) - for bad in ['__file__', '__path__']: - if bad in symbols: - log.warn("%s: module references %s", module, bad) - safe = False - if 'inspect' in symbols: - for bad in [ - 'getsource', 'getabsfile', 'getsourcefile', 'getfile' - 'getsourcelines', 'findsource', 'getcomments', 'getframeinfo', - 'getinnerframes', 'getouterframes', 'stack', 'trace' - ]: - if bad in symbols: - log.warn("%s: module MAY be using inspect.%s", module, bad) - safe = False - return safe + + + + + + +def walk_egg(egg_dir): + """Walk an unpacked egg's contents, skipping the metadata directory""" + walker = os.walk(egg_dir) + base,dirs,files = walker.next() + if 'EGG-INFO' in dirs: + dirs.remove('EGG-INFO') + yield base,dirs,files + for bdf in walker: + yield bdf + +def analyze_egg(egg_dir, stubs): + safe = True + for base, dirs, files in walk_egg(egg_dir): + for name in files: + if name.endswith('.py') or name.endswith('.pyw'): + continue + elif name.endswith('.pyc') or name.endswith('.pyo'): + # always scan, even if we already know we're not safe + safe = scan_module(egg_dir, base, name, stubs) and safe + '''elif safe: + log.warn( + "Distribution contains data or extensions; assuming " + "it's unsafe (set zip_safe=True in setup() to change" + ) + safe = False # XXX''' + return safe + +def write_safety_flag(egg_dir, safe): + # Write a zip safety flag file + flag = safe and 'zip-safe' or 'not-zip-safe' + open(os.path.join(egg_dir,'EGG-INFO',flag),'w').close() + + + + + + + + + + +def scan_module(egg_dir, base, name, stubs): + """Check whether module possibly uses unsafe-for-zipfile stuff""" + + filename = os.path.join(base,name) + if filename[:-1] in stubs: + return True # Extension module + + pkg = base[len(egg_dir)+1:].replace(os.sep,'.') + module = pkg+(pkg and '.' or '')+os.path.splitext(name)[0] + + f = open(filename,'rb'); f.read(8) # skip magic & date + code = marshal.load(f); f.close() + safe = True + + symbols = dict.fromkeys(iter_symbols(code)) + for bad in ['__file__', '__path__']: + if bad in symbols: + log.warn("%s: module references %s", module, bad) + safe = False + if 'inspect' in symbols: + for bad in [ + 'getsource', 'getabsfile', 'getsourcefile', 'getfile' + 'getsourcelines', 'findsource', 'getcomments', 'getframeinfo', + 'getinnerframes', 'getouterframes', 'stack', 'trace' + ]: + if bad in symbols: + log.warn("%s: module MAY be using inspect.%s", module, bad) + safe = False + return safe + def iter_symbols(code): """Yield names and strings used by `code` and its nested code objects""" for name in code.co_names: yield name Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- easy_install.py 10 Jul 2005 15:43:08 -0000 1.7 +++ easy_install.py 11 Jul 2005 04:12:48 -0000 1.8 @@ -67,6 +67,7 @@ "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), ('record=', None, "filename in which to record list of installed files"), + ('always-unzip', 'Z', "don't install as a zipfile, no matter what") ] boolean_options = [ @@ -74,12 +75,11 @@ 'delete-conflicting', 'ignore-conflicts-at-my-risk', ] + negative_opt = {'always-unzip': 'zip-ok'} create_index = PackageIndex - - def initialize_options(self): self.zip_ok = None self.install_dir = self.script_dir = self.exclude_scripts = None @@ -291,7 +291,7 @@ install_needed = install_needed or not download.endswith('.egg') log.info("Processing %s", os.path.basename(download)) if install_needed or self.always_copy: - dists = self.install_eggs(download, self.zip_ok, tmpdir) + dists = self.install_eggs(download, tmpdir) for dist in dists: self.process_distribution(spec, dist) else: @@ -337,14 +337,14 @@ metadata.get_metadata('scripts/'+script_name).replace('\r','\n') ) - - - - - - - - + def should_unzip(self, dist): + if self.zip_ok is not None: + return not self.zip_ok + if dist.metadata.has_metadata('not-zip-safe'): + return True + if not dist.metadata.has_metadata('zip-safe'): + return True + return False @@ -408,10 +408,10 @@ pass - def install_eggs(self, dist_filename, zip_ok, tmpdir): + def install_eggs(self, dist_filename, tmpdir): # .egg dirs or files are already built, so just return them if dist_filename.lower().endswith('.egg'): - return [self.install_egg(dist_filename, True, tmpdir)] + return [self.install_egg(dist_filename, tmpdir)] elif dist_filename.lower().endswith('.exe'): return [self.install_exe(dist_filename, tmpdir)] @@ -438,7 +438,7 @@ setup_script = setups[0] # Now run it, and return the result - return self.build_and_install(setup_script, setup_base, zip_ok) + return self.build_and_install(setup_script, setup_base) @@ -456,13 +456,14 @@ metadata = EggMetadata(zipimport.zipimporter(egg_path)) return Distribution.from_filename(egg_path,metadata=metadata) - def install_egg(self, egg_path, zip_ok, tmpdir): + def install_egg(self, egg_path, tmpdir): destination = os.path.join(self.install_dir,os.path.basename(egg_path)) destination = os.path.abspath(destination) if not self.dry_run: ensure_directory(destination) - self.check_conflicts(self.egg_distribution(egg_path)) + dist = self.egg_distribution(egg_path) + self.check_conflicts(dist) if not samefile(egg_path, destination): if os.path.isdir(destination): dir_util.remove_tree(destination, dry_run=self.dry_run) @@ -474,14 +475,13 @@ f,m = shutil.move, "Moving" else: f,m = shutil.copytree, "Copying" - elif zip_ok: - if egg_path.startswith(tmpdir): - f,m = shutil.move, "Moving" - else: - f,m = shutil.copy2, "Copying" - else: + elif self.should_unzip(dist): self.mkpath(destination) f,m = self.unpack_and_compile, "Extracting" + elif egg_path.startswith(tmpdir): + f,m = shutil.move, "Moving" + else: + f,m = shutil.copy2, "Copying" self.execute(f, (egg_path, destination), (m+" %s to %s") % @@ -526,17 +526,15 @@ ) # install the .egg - return self.install_egg(egg_path, self.zip_ok, tmpdir) + return self.install_egg(egg_path, tmpdir) def exe_to_egg(self, dist_filename, egg_tmp): """Extract a bdist_wininst to the directories an egg would use""" - # Check for .pth file and set up prefix translations prefixes = get_exe_prefixes(dist_filename) - to_compile = [] native_libs = [] top_level = {} @@ -561,16 +559,18 @@ # extract, tracking .pyd/.dll->native_libs and .py -> to_compile unpack_archive(dist_filename, egg_tmp, process) - + stubs = [] for res in native_libs: if res.lower().endswith('.pyd'): # create stubs for .pyd's parts = res.split('/') resource, parts[-1] = parts[-1], parts[-1][:-1] pyfile = os.path.join(egg_tmp, *parts) - to_compile.append(pyfile) + to_compile.append(pyfile); stubs.append(pyfile) bdist_egg.write_stub(resource, pyfile) self.byte_compile(to_compile) # compile .py's + bdist_egg.write_safety_flag(egg_tmp, + bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag for name in 'top_level','native_libs': if locals()[name]: @@ -695,7 +695,7 @@ - def build_and_install(self, setup_script, setup_base, zip_ok): + def build_and_install(self, setup_script, setup_base): sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) sys.modules.setdefault('distutils.command.bdist_egg', egg_info) @@ -724,7 +724,7 @@ eggs = [] for egg in glob(os.path.join(dist_dir,'*.egg')): - eggs.append(self.install_egg(egg, zip_ok, setup_base)) + eggs.append(self.install_egg(egg, setup_base)) if not eggs and not self.dry_run: log.warn("No eggs found in %s (setup script problem?)", From pje at users.sourceforge.net Mon Jul 11 06:12:50 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 21:12:50 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.33, 1.34 setuptools.txt, 1.6, 1.7 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17477 Modified Files: EasyInstall.txt setuptools.txt Log Message: Enhanced "zip safety" analysis (including scan of win32.exe's) and have EasyInstall act on zip safety flags. Add a lot more docs for setuptools. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- EasyInstall.txt 10 Jul 2005 15:24:12 -0000 1.33 +++ EasyInstall.txt 11 Jul 2005 04:12:47 -0000 1.34 @@ -303,6 +303,53 @@ about! +Compressed Installation +----------------------- + +EasyInstall tries to install packages in zipped form, if it can. Zipping +packages can significantly increase Python's overall import performance if +you're installing to``site-packages`` and not using the ``--multi`` option, +because Python processes zipfile entries on ``sys.path`` much faster than it +does directories. + +As of version 0.5a9, EasyInstall analyzes packages to determine whether they +can be safely installed as a zipfile, and then acts on its analysis. (Previous +versions would not install a package as a zipfile unless you used the +``--zip-ok`` option.) + +The current analysis approach is very conservative; it currenly looks for: + + * Any use of the ``__file__`` or ``__path__`` variables (which should be + replaced with ``pkg_resources`` API calls) + + * Possible use of ``inspect`` functions that expect to manipulate source files + (e.g. ``inspect.getsource()``) + + * Any data files or C extensions (this restriction will be removed in a future + release, once the ``pkg_resources`` runtime has been hardened for multi-user + environments) + +If any of the above are found in the package being installed, EasyInstall will +assume that the package cannot be safely run from a zipfile, and unzip it to +a directory instead. You can override this analysis with the ``-zip-ok`` flag, +which will tell EasyInstall to install the package as a zipfile anyway. Or, +you can use the ``--always-unzip`` flag, in which case EasyInstall will always +unzip, even if its analysis says the package is safe to run as a zipfile. + +Normally, however, it is simplest to let EasyInstall handle the determination +of whether to zip or unzip, and only specify overrides when needed to work +around a problem. If you find you need to override EasyInstall's guesses, you +may want to contact the package author and the EasyInstall maintainers, so that +they can make appropriate changes in future versions. + +(Note: If a package uses ``setuptools`` in its setup script, the package author +has the option to declare the package safe or unsafe for zipped usage via the +``zip_safe`` argument to ``setup()``. If the package author makes such a +declaration, EasyInstall believes the package's author and does not perform its +own analysis. However, your command-line option, if any, will still override +the package author's choice.) + + Reference Manual ================ @@ -348,27 +395,26 @@ -------------------- ``--zip-ok, -z`` - Enable installing the package as a zip file. This can significantly - increase Python's overall import performance if you're installing to - ``site-packages`` and not using the ``--multi`` option, because Python - process zipfile entries on ``sys.path`` much faster than it does - directories. So, if you don't use this option, and you install a lot of - packages, some of them may be slower to import. + Install all packages as zip files, even if they are marked as unsafe for + running as a zipfile. This can be useful when EasyInstall's analysis + of a non-setuptools package is too conservative, but keep in mind that + the package may not work correctly. (Changed in 0.5a9; previously this + option was required in order for zipped installation to happen at all.) - But, this option is disabled by default, unless you're installing from an - already-built binary zipfile (``.egg`` file). This is to avoid problems - when using packages that dosn't support running from a zip file. Such - packages usually access data files in their package directories using the - Python ``__file__`` or ``__path__`` attribute, instead of the - ``pkg_resources`` API. So, if you find that a package doesn't work properly - when used with this option, you may want to suggest to the author that they - switch to using the ``pkg_resources`` resource API, which will allow their - package to work whether it's installed as a zipfile or not. +``--always-unzip, -Z`` + Don't install any packages as zip files, even if the packages are marked + as safe for running as a zipfile. This can be useful if a package does + something unsafe, but not in a way that EasyInstall can easily detect. + EasyInstall's default analysis is currently very conservative, however, so + you should only use this option if you've had problems with a particular + package, and *after* reporting the problem to the package's maintainer and + to the EasyInstall maintainers. - (Note: this option only affects the installation of newly-built packages - that are not already installed in the target directory; if you want to - convert an existing installed version from zipped to unzipped or vice - versa, you'll need to delete the existing version first.) + (Note: the ``-z/-Z`` options only affect the installation of newly-built + or downloaded packages that are not already installed in the target + directory; if you want to convert an existing installed version from + zipped to unzipped or vice versa, you'll need to delete the existing + version first, and re-run EasyInstall.) ``--multi-version, -m`` "Multi-version" mode. Specifying this option prevents ``easy_install`` from @@ -564,6 +610,15 @@ * EasyInstall can now be given a path to a directory containing a setup script, and it will attempt to build and install the package there. + * EasyInstall now performs a safety analysis on module contents to determine + whether a package is likely to run in zipped form, and displays + information about what modules may be doing introspection that would break + when running as a zipfile. + + * Added the ``--always-unzip/-Z`` option, to force unzipping of packages that + would ordinarily be considered safe to unzip, and changed the meaning of + ``--zip-ok/-z`` to "always leave everything zipped". + 0.5a8 * There is now a separate documentation page for `setuptools`_; revision history that's not specific to EasyInstall has been moved to that page. Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- setuptools.txt 10 Jul 2005 15:43:07 -0000 1.6 +++ setuptools.txt 11 Jul 2005 04:12:47 -0000 1.7 @@ -183,6 +183,48 @@ for more information. +Using ``find_packages()`` +------------------------- + +For simple projects, it's usually easy enough to manually add packages to +the ``packages`` argument of ``setup()``. However, for very large projects +(Twisted, PEAK, Zope, Chandler, etc.), it can be a big burden to keep the +package list updated. That's what ``setuptools.find_packages()`` is for. + +``find_packages()`` takes a source directory, and a list of package names or +patterns to exclude. If omitted, the source directory defaults to the same +directory as the setup script. Some projects use a ``src`` or ``lib`` +directory as the root of their source tree, and those projects would of course +use ``"src"`` or ``"lib"`` as the first argument to ``find_packages()``. (And +such projects also need something like ``package_dir = {'':'src'}`` in their +``setup()`` arguments, but that's just a normal distutils thing.) + +Anyway, ``find_packages()`` walks the target directory, and finds Python +packages by looking for ``__init__.py`` files. It then filters the list of +packages using the exclusion patterns. + +Exclusion patterns are package names, optionally including wildcards. For +example, ``find_packages(exclude=["*.tests"])`` will exclude all packages whose +last name part is ``tests``. Or, ``find_packages(exclude=["*.tests", +"*.tests.*"])`` will also exclude any subpackages of packages named ``tests``, +but it still won't exclude a top-level ``tests`` package or the children +thereof. In fact, if you really want no ``tests`` packages at all, you'll need +something like this:: + + find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) + +in order to cover all the bases. Really, the exclusion patterns are intended +to cover simpler use cases than this, like excluding a single, specified +package and its subpackages. + +Regardless of the target directory or exclusions, the ``find_packages()`` +function returns a list of package names suitable for use as the ``packages`` +argument to ``setup()``, and so is usually the easiest way to set that +argument in your setup script. Especially since it frees you from having to +remember to modify your setup script whenever your project grows additional +top-level packages or subpackages. + + Declaring Dependencies ====================== @@ -305,71 +347,6 @@ specifier. -Distributing a ``setuptools``-based package -=========================================== - -Your users might not have ``setuptools`` installed on their machines, or even -if they do, it might not be the right version. Fixing this is easy; just -download `ez_setup.py`_, and put it in the same directory as your ``setup.py`` -script. (Be sure to add it to your revision control system, too.) Then add -these two lines to the very top of your setup script, before the script imports -anything from setuptools:: - - import ez_setup - ez_setup.use_setuptools() - -That's it. The ``ez_setup`` module will automatically download a matching -version of ``setuptools`` from PyPI, if it isn't present on the target system. -Whenever you install an updated version of setuptools, you should also update -your projects' ``ez_setup.py`` files, so that a matching version gets installed -on the target machine(s). - -By the way, setuptools supports the new PyPI "upload" command, so you can use -``setup.py sdist upload`` or ``setup.py bdist_egg upload`` to upload your -source or egg distributions respectively. Your project's current version must -be registered with PyPI first, of course; you can use ``setup.py register`` to -do that. Or you can do it all in one step, e.g. ``setup.py register sdist -bdist_egg upload`` will register the package, build source and egg -distributions, and then upload them both to PyPI, where they'll be easily -found by other projects that depend on them. - - -Managing Multiple Projects --------------------------- - -If you're managing several projects that need to use ``ez_setup``, and you are -using Subversion as your revision control system, you can use the -"svn:externals" property to share a single copy of ``ez_setup`` between -projects, so that it will always be up-to-date whenever you check out or update -an individual project, without having to manually update each project to use -a new version. - -However, because Subversion only supports using directories as externals, you -have to turn ``ez_setup.py`` into ``ez_setup/__init__.py`` in order to do this, -then create "externals" definitions that map the ``ez_setup`` directory into -each project. Also, if any of your projects use ``find_packages()`` on their -setup directory, you will need to exclude the resulting ``ez_setup`` package, -to keep it from being included in your distributions, e.g.:: - - setup( - ... - packages = find_packages(exclude=['ez_setup']), - ) - -Of course, the ``ez_setup`` package will still be included in your packages' -source distributions, as it needs to be. - -For your convenience, you may use the following external definition, which will -track the latest version of setuptools:: - - ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup - -You can set this by executing this command in your project directory:: - - svn propedit svn:externals . - -And then adding the line shown above to the file that comes up for editing. - Including Data Files ==================== @@ -457,12 +434,6 @@ .. _Accessing Package Resources: http://peak.telecommunity.com/DevCenter/PythonEggs#accessing-package-resources -Setting the ``zip_safe`` flag ------------------------------ - -XXX put doc about zip_safe flag here, once it's implemented - - "Development Mode" ================== @@ -510,35 +481,128 @@ command; see the section on the `develop`_ command below for more details. -Tagging and "Daily Build" or "Snapshot" Releases -================================================ +Distributing a ``setuptools``-based package +=========================================== -Sorry, this section isn't written yet, and neither are the next few sections, -until you get to the `Command Reference`_ section below. You might want to -`subscribe to changes in this page `_ to see when -new documentation is added or updated. +Using ``setuptools``... Without bundling it! +--------------------------------------------- -Generating Source Distributions -=============================== +Your users might not have ``setuptools`` installed on their machines, or even +if they do, it might not be the right version. Fixing this is easy; just +download `ez_setup.py`_, and put it in the same directory as your ``setup.py`` +script. (Be sure to add it to your revision control system, too.) Then add +these two lines to the very top of your setup script, before the script imports +anything from setuptools:: -XXX ``sdist`` - auto-include files from CVS or Subversion + import ez_setup + ez_setup.use_setuptools() +That's it. The ``ez_setup`` module will automatically download a matching +version of ``setuptools`` from PyPI, if it isn't present on the target system. +Whenever you install an updated version of setuptools, you should also update +your projects' ``ez_setup.py`` files, so that a matching version gets installed +on the target machine(s). -Using ``find_packages()`` -========================= +By the way, setuptools supports the new PyPI "upload" command, so you can use +``setup.py sdist upload`` or ``setup.py bdist_egg upload`` to upload your +source or egg distributions respectively. Your project's current version must +be registered with PyPI first, of course; you can use ``setup.py register`` to +do that. Or you can do it all in one step, e.g. ``setup.py register sdist +bdist_egg upload`` will register the package, build source and egg +distributions, and then upload them both to PyPI, where they'll be easily +found by other projects that depend on them. -XXX +Managing Multiple Projects +-------------------------- -Building Extensions written with Pyrex -====================================== +If you're managing several projects that need to use ``ez_setup``, and you are +using Subversion as your revision control system, you can use the +"svn:externals" property to share a single copy of ``ez_setup`` between +projects, so that it will always be up-to-date whenever you check out or update +an individual project, without having to manually update each project to use +a new version. -XXX +However, because Subversion only supports using directories as externals, you +have to turn ``ez_setup.py`` into ``ez_setup/__init__.py`` in order to do this, +then create "externals" definitions that map the ``ez_setup`` directory into +each project. Also, if any of your projects use ``find_packages()`` on their +setup directory, you will need to exclude the resulting ``ez_setup`` package, +to keep it from being included in your distributions, e.g.:: + + setup( + ... + packages = find_packages(exclude=['ez_setup']), + ) + +Of course, the ``ez_setup`` package will still be included in your packages' +source distributions, as it needs to be. + +For your convenience, you may use the following external definition, which will +track the latest version of setuptools:: + + ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup + +You can set this by executing this command in your project directory:: + + svn propedit svn:externals . + +And then adding the line shown above to the file that comes up for editing. + + +Setting the ``zip_safe`` flag +----------------------------- + +For maximum performance, Python packages are best installed as zip files. +Not all packages, however, are capable of running in compressed form, because +they may expect to be able to access either source code or data files as +normal operating system files. So, ``setuptools`` can install your project +as a zipfile or a directory, and its default choice is determined by the +project's ``zip_safe`` flag. + +You can pass a True or False value for the ``zip_safe`` argument to the +``setup()`` function, or you can omit it. If you omit it, the ``bdist_egg`` +command will analyze your project's contents to see if it can detect any +conditions that would prevent it from working in a zipfile. It will output +notices to the console about any such conditions that it finds. + +Currently, this analysis is extremely conservative: it will consider the +project unsafe if it contains any C extensions or datafiles whatsoever. This +does *not* mean that the project can't or won't work as a zipfile! It just +means that the ``bdist_egg`` authors aren't yet comfortable asserting that +the project *will* work. If the project contains no C or data files, and does +no ``__file__`` or ``__path__`` introspection or source code manipulation, then +there is an extremely solid chance the project will work when installed as a +zipfile. (And if the project uses ``pkg_resources`` for all its data file +access, then C extensions and other data files shouldn't be a problem at all. +See the `Accessing Data Files at Runtime`_ section above for more information.) + +However, if ``bdist_egg`` can't be *sure* that your package will work, but +you've checked over all the warnings it issued, and you are either satisfied it +*will* work (or if you want to try it for yourself), then you should set +``zip_safe`` to ``True`` in your ``setup()`` call. If it turns out that it +doesn't work, you can always change it to ``False``, which will force +``setuptools`` to install your project as a directory rather than as a zipfile. + +Of course, the end-user can still override either decision, if they are using +EasyInstall to install your package. And, if you want to override for testing +purposes, you can just run ``setup.py easy_install --zip-ok .`` or ``setup.py +easy_install --always-unzip .`` in your project directory. to install the +package as a zipfile or directory, respectively. + +In the future, as we gain more experience with different packages and become +more satisfied with the robustness of the ``pkg_resources`` runtime, the +"zip safety" analysis may become less conservative. However, we strongly +recommend that you determine for yourself whether your project functions +correctly when installed as a zipfile, correct any problems if you can, and +then make an explicit declaration of ``True`` or ``False`` for the ``zip_safe`` +flag, so that it will not be necessary for ``bdist_egg`` or ``EasyInstall`` to +try to guess whether your project can work as a zipfile. Namespace Packages -================== +------------------ Sometimes, a large package is more useful if distributed as a collection of smaller eggs. However, Python does not normally allow the contents of a @@ -593,6 +657,109 @@ projects.) +Tagging and "Daily Build" or "Snapshot" Releases +------------------------------------------------ + +When a set of related projects are under development, it may be important to +track finer-grained version increments than you would normally use for e.g. +"stable" releases. While stable releases might be measured in dotted numbers +with alpha/beta/etc. status codes, development versions of a project often +need to be tracked by revision or build number or even build date. This is +especially true when projects in development need to refer to one another, and +therefore may literally need an up-to-the-minute version of something! + +To support these scenarios, ``setuptools`` allows you to "tag" your source and +egg distributions by adding one or more of the following to the project's +"official" version identifier: + +* An identifying string, such as "build" or "dev", or a manually-tracked build + or revision number (``--tag-build=STRING, -bSTRING``) + +* A "last-modified revision number" string generated automatically from + Subversion's metadata (assuming your project is being built from a Subversion + "working copy") (``--tag-svn-revision, -r``) + +* An 8-character representation of the build date (``--tag-date, -d``) + +You can add these tags by adding ``egg_info`` and the desired options to +the command line ahead of the ``sdist`` or ``bdist`` commands that you want +to generate a daily build or snapshot for. See the section below on the +`egg_info`_ command for more details. + +Also, if you are creating builds frequently, and either building them in a +downloadable location or are copying them to a distribution server, you should +probably also check out the `rotate`_ command, which lets you automatically +delete all but the N most-recently-modified distributions matching a glob +pattern. So, you can use a command line like:: + + setup.py egg_info -rbDEV bdist_egg rotate -m.egg -k3 + +to build an egg whose version info includes 'DEV-rNNNN' (where NNNN is the +most recent Subversion revision that affected the source tree), and then +delete any egg files from the distribution directory except for the three +that were built most recently. + +If you have to manage automated builds for multiple packages, each with +different tagging and rotation policies, you may also want to check out the +`alias`_ command, which would let each package define an alias like ``daily`` +that would perform the necessary tag, build, and rotate commands. Then, a +simpler scriptor cron job could just run ``setup.py daily`` in each project +directory. (And, you could also define sitewide or per-user default versions +of the ``daily`` alias, so that projects that didn't define their own would +use the appropriate defaults.) + + +Generating Source Distributions +------------------------------- + +``setuptools`` enhances the distutils' default algorithm for source file +selection, so that all files managed by CVS or Subversion in your project tree +are included in any source distribution you build. This is a big improvement +over having to manually write a ``MANIFEST.in`` file and try to keep it in +sync with your project. So, if you are using CVS or Subversion, and your +source distributions only need to include files that you're tracking in +revision control, don't create a a ``MANIFEST.in`` file for your project. +(And, if you already have one, you might consider deleting it the next time +you would otherwise have to change it.) + +Unlike the distutils, ``setuptools`` regenerates the source distribution +``MANIFEST`` file every time you build a source distribution, as long as you +*don't* have a ``MANIFEST.in`` file. If you do have a ``MANIFEST.in`` (e.g. +because you aren't using CVS or Subversion), then you'll have to follow the +normal distutils procedures for managing what files get included in a source +distribution, and setuptools' enhanced algorithms will *not* be used. + +(Note, by the way, that if you're using some other revision control system, you +might consider submitting a patch to the ``setuptools.command.sdist`` module +so we can include support for it, too.) + + +Distributing Extensions compiled with Pyrex +------------------------------------------- + +``setuptools`` includes transparent support for building Pyrex extensions, as +long as you define your extensions using ``setuptools.Extension``, *not* +``distutils.Extension``. You must also not import anything from Pyrex in +your setup script. + +If you follow these rules, you can safely list ``.pyx`` files as the source +of your ``Extension`` objects in the setup script. ``setuptools`` will detect +at build time whether Pyrex is installed or not. If it is, then ``setuptools`` +will use it. If not, then ``setuptools`` will silently change the +``Extension`` objects to refer to the ``.c`` counterparts of the ``.pyx`` +files, so that the normal distutils C compilation process will occur. + +Of course, for this to work, your source distributions must include the C +code generated by Pyrex, as well as your original ``.pyx`` files. This means +that you will probably want to include current ``.c`` files in your revision +control system, rebuilding them whenever you check changes in for the ``.pyx`` +source files. This will ensure that people tracking your project in CVS or +Subversion will be able to build it even if they don't have Pyrex installed, +and that your source releases will be similarly usable with or without Pyrex. + + + + ----------------- Command Reference ----------------- @@ -1192,6 +1359,8 @@ "unmanaged" packages when installing the distribution. * Added ``zip_safe`` and ``namespace_packages`` arguments to ``setup()``. + Added package analysis to determine zip-safety if the ``zip_safe`` flag + is not given, and advise the author regarding what code might need changing. * Fixed the swapped ``-d`` and ``-b`` options of ``bdist_egg``. From pje at users.sourceforge.net Mon Jul 11 06:22:00 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 21:22:00 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.15, 1.16 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22652/setuptools Modified Files: __init__.py Log Message: Update to 0.5a9, add zip_safe flag, and fix a doc error. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- __init__.py 9 Jul 2005 04:24:38 -0000 1.15 +++ __init__.py 11 Jul 2005 04:21:57 -0000 1.16 @@ -7,7 +7,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a8' +__version__ = '0.5a9' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', 'find_packages' From pje at users.sourceforge.net Mon Jul 11 06:22:00 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 10 Jul 2005 21:22:00 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.34, 1.35 ez_setup.py, 1.14, 1.15 setup.py, 1.24, 1.25 setuptools.txt, 1.7, 1.8 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22652 Modified Files: EasyInstall.txt ez_setup.py setup.py setuptools.txt Log Message: Update to 0.5a9, add zip_safe flag, and fix a doc error. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- EasyInstall.txt 11 Jul 2005 04:12:47 -0000 1.34 +++ EasyInstall.txt 11 Jul 2005 04:21:56 -0000 1.35 @@ -29,7 +29,7 @@ ------------------------- Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py `_, and run it; this will download and install the appropriate ``setuptools`` egg for your Python @@ -70,7 +70,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a8" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a9" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- ez_setup.py 8 Jul 2005 15:52:05 -0000 1.14 +++ ez_setup.py 11 Jul 2005 04:21:56 -0000 1.15 @@ -14,7 +14,7 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a8" +DEFAULT_VERSION = "0.5a9" DEFAULT_URL = "http://www.python.org/packages/source/s/setuptools/" import sys, os Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- setup.py 9 Jul 2005 04:27:38 -0000 1.24 +++ setup.py 11 Jul 2005 04:21:57 -0000 1.25 @@ -15,7 +15,7 @@ f.close() return ''.join(lines) -VERSION = "0.5a8" +VERSION = "0.5a9" from setuptools import setup, find_packages @@ -35,7 +35,7 @@ packages = find_packages(), py_modules = ['pkg_resources'], scripts = ['easy_install.py'], - + zip_safe = True, Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- setuptools.txt 11 Jul 2005 04:12:47 -0000 1.7 +++ setuptools.txt 11 Jul 2005 04:21:57 -0000 1.8 @@ -64,7 +64,7 @@ ========================= Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py`_ and run it; this will download and install the appropriate egg for your Python version. @@ -1053,6 +1053,8 @@ no ``package_dir`` set, this option defaults to the current directory. +.. _rotate: + ``rotate`` - Delete outdated distribution files =============================================== From birkenfeld at users.sourceforge.net Mon Jul 11 07:57:13 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 10 Jul 2005 22:57:13 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS, 1.1193.2.60, 1.1193.2.61 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6037/Misc Modified Files: Tag: release24-maint NEWS Log Message: Backport: SF bug 1185883: PyObject_Realloc can't safely take over a block currently managed by C, because it's possible for the block to be smaller than the new requested size, and at the end of allocated VM. Trying to copy over nbytes bytes to a Python small-object block can segfault then, and there's no portable way to avoid this (we would have to know how many bytes starting at p are addressable, and std C has no means to determine that). Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.60 retrieving revision 1.1193.2.61 diff -u -d -r1.1193.2.60 -r1.1193.2.61 --- NEWS 8 Jul 2005 22:25:17 -0000 1.1193.2.60 +++ NEWS 11 Jul 2005 05:57:10 -0000 1.1193.2.61 @@ -12,6 +12,15 @@ Core and builtins ----------------- +- SF bug #1185883: Python's small-object memory allocator took over + a block managed by the platform C library whenever a realloc specified + a small new size. However, there's no portable way to know then how + much of the address space following the pointer is valid, so no + portable way to copy data from the C-managed block into Python's + small-object space without risking a memory fault. Python's small-object + realloc now leaves such blocks under the control of the platform C + realloc. + - Fix garbage collection for set and frozenset objects. SF patch #1200018. - It is now safe to call PyGILState_Release() before From birkenfeld at users.sourceforge.net Mon Jul 11 07:57:14 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 10 Jul 2005 22:57:14 -0700 Subject: [Python-checkins] python/dist/src/Objects obmalloc.c, 2.53, 2.53.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6037/Objects Modified Files: Tag: release24-maint obmalloc.c Log Message: Backport: SF bug 1185883: PyObject_Realloc can't safely take over a block currently managed by C, because it's possible for the block to be smaller than the new requested size, and at the end of allocated VM. Trying to copy over nbytes bytes to a Python small-object block can segfault then, and there's no portable way to avoid this (we would have to know how many bytes starting at p are addressable, and std C has no means to determine that). Index: obmalloc.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/obmalloc.c,v retrieving revision 2.53 retrieving revision 2.53.4.1 diff -u -d -r2.53 -r2.53.4.1 --- obmalloc.c 6 Jun 2004 19:21:34 -0000 2.53 +++ obmalloc.c 11 Jul 2005 05:57:11 -0000 2.53.4.1 @@ -139,9 +139,9 @@ * getpagesize() call or deduced from various header files. To make * things simpler, we assume that it is 4K, which is OK for most systems. * It is probably better if this is the native page size, but it doesn't - * have to be. In theory, if SYSTEM_PAGE_SIZE is larger than the native page - * size, then `POOL_ADDR(p)->arenaindex' could rarely cause a segmentation - * violation fault. 4K is apparently OK for all the platforms that python + * have to be. In theory, if SYSTEM_PAGE_SIZE is larger than the native page + * size, then `POOL_ADDR(p)->arenaindex' could rarely cause a segmentation + * violation fault. 4K is apparently OK for all the platforms that python * currently targets. */ #define SYSTEM_PAGE_SIZE (4 * 1024) @@ -841,30 +841,26 @@ } return bp; } - /* We're not managing this block. */ - if (nbytes <= SMALL_REQUEST_THRESHOLD) { - /* Take over this block -- ask for at least one byte so - * we really do take it over (PyObject_Malloc(0) goes to - * the system malloc). - */ - bp = PyObject_Malloc(nbytes ? nbytes : 1); - if (bp != NULL) { - memcpy(bp, p, nbytes); - free(p); - } - else if (nbytes == 0) { - /* Meet the doc's promise that nbytes==0 will - * never return a NULL pointer when p isn't NULL. - */ - bp = p; - } - - } - else { - assert(nbytes != 0); - bp = realloc(p, nbytes); - } - return bp; + /* We're not managing this block. If nbytes <= + * SMALL_REQUEST_THRESHOLD, it's tempting to try to take over this + * block. However, if we do, we need to copy the valid data from + * the C-managed block to one of our blocks, and there's no portable + * way to know how much of the memory space starting at p is valid. + * As bug 1185883 pointed out the hard way, it's possible that the + * C-managed block is "at the end" of allocated VM space, so that + * a memory fault can occur if we try to copy nbytes bytes starting + * at p. Instead we punt: let C continue to manage this block. + */ + if (nbytes) + return realloc(p, nbytes); + /* C doesn't define the result of realloc(p, 0) (it may or may not + * return NULL then), but Python's docs promise that nbytes==0 never + * returns NULL. We don't pass 0 to realloc(), to avoid that endcase + * to begin with. Even then, we can't be sure that realloc() won't + * return NULL. + */ + bp = realloc(p, 1); + return bp ? bp : p; } #else /* ! WITH_PYMALLOC */ From pje at users.sourceforge.net Tue Jul 12 07:31:38 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 11 Jul 2005 22:31:38 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools package_index.py, 1.10, 1.11 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26083/setuptools Modified Files: package_index.py Log Message: Fix bugs and implement features reported/requested by folks on the Distutils-SIG. Index: package_index.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/package_index.py,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- package_index.py 10 Jul 2005 04:49:31 -0000 1.10 +++ package_index.py 12 Jul 2005 05:31:36 -0000 1.11 @@ -44,27 +44,32 @@ path = urlparse.urlparse(url)[2] base = urllib2.unquote(path.split('/')[-1]) - if base.endswith('.egg.zip'): - base = base[:-4] # strip the .zip + return distros_for_filename(url, base, metadata) - if base.endswith('.egg'): - dist = Distribution.from_filename(base, metadata) - dist.path = url + +def distros_for_filename(url_or_path, basename, metadata=None): + """Yield egg or source distribution objects based on basename""" + if basename.endswith('.egg.zip'): + basename = basename[:-4] # strip the .zip + + if basename.endswith('.egg'): + dist = Distribution.from_filename(basename, metadata) + dist.path = url_or_path return [dist] # only one, unambiguous interpretation - if base.endswith('.exe'): - win_base, py_ver = parse_bdist_wininst(base) + if basename.endswith('.exe'): + win_base, py_ver = parse_bdist_wininst(basename) if win_base is not None: return interpret_distro_name( - url, win_base, metadata, py_ver, BINARY_DIST, "win32" + url_or_path, win_base, metadata, py_ver, BINARY_DIST, "win32" ) # Try source distro extensions (.zip, .tgz, etc.) # for ext in EXTENSIONS: - if base.endswith(ext): - base = base[:-len(ext)] - return interpret_distro_name(url, base, metadata) + if basename.endswith(ext): + basename = basename[:-len(ext)] + return interpret_distro_name(url_or_path, basename, metadata) return [] # no extension matched @@ -75,12 +80,7 @@ - - - - - -def interpret_distro_name(url, base, metadata, +def interpret_distro_name(url_or_path, basename, metadata, py_version=None, distro_type=SOURCE_DIST, platform=None ): @@ -96,10 +96,10 @@ # in the long run PyPI and the distutils should go for "safe" names and # versions in distribution archive names (sdist and bdist). - parts = base.split('-') + parts = basename.split('-') for p in range(1,len(parts)+1): yield Distribution( - url, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), + url_or_path, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), py_version=py_version, distro_type = distro_type, platform = platform ) @@ -132,12 +132,35 @@ self.package_pages = {} def process_url(self, url, retrieve=False): + """Evaluate a URL as a possible download, and maybe retrieve it""" + if url in self.scanned_urls and not retrieve: return self.scanned_urls[url] = True - dists = list(distros_for_url(url)) - if dists: self.debug("Found link: %s", url) + + if not URL_SCHEME(url): + # process filenames or directories + if os.path.isfile(url): + dists = list( + distros_for_filename( + os.path.realpath(url), os.path.basename(url) + ) + ) + elif os.path.isdir(url): + url = os.path.realpath(url) + for item in os.listdir(url): + self.process_url(os.path.join(url,item)) + return + else: + self.warn("Not found: %s", url) + return + else: + dists = list(distros_for_url(url)) + + if dists: + self.debug("Found link: %s", url) + if dists or not retrieve or url in self.fetched_urls: for dist in dists: @@ -148,6 +171,7 @@ self.info("Reading %s", url) f = self.open_url(url) self.fetched_urls[url] = self.fetched_urls[f.url] = True + if 'html' not in f.headers['content-type'].lower(): f.close() # not html, we can't process it return @@ -162,6 +186,23 @@ link = urlparse.urljoin(base, match.group(1)) self.process_url(link) + + + + + + + + + + + + + + + + + def process_index(self,url,page): """Process the contents of a PyPI page""" From pje at users.sourceforge.net Tue Jul 12 07:31:38 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 11 Jul 2005 22:31:38 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.35, 1.36 pkg_resources.py, 1.38, 1.39 setup.py, 1.25, 1.26 setuptools.txt, 1.8, 1.9 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26083 Modified Files: EasyInstall.txt pkg_resources.py setup.py setuptools.txt Log Message: Fix bugs and implement features reported/requested by folks on the Distutils-SIG. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.35 retrieving revision 1.36 diff -u -d -r1.35 -r1.36 --- EasyInstall.txt 11 Jul 2005 04:21:56 -0000 1.35 +++ EasyInstall.txt 12 Jul 2005 05:31:36 -0000 1.36 @@ -495,15 +495,18 @@ the PEAK downloads page, but ignore the other download links on that page. If all requested packages can be found using links on the specified download pages, the Python Package Index will *not* be consulted. You can - use ``file:`` URLs to reference a local filename. + use a ``file:`` URL to reference a local HTML file containing links, or you + can just use the name of a directory containing "distribution files" + (source archives, eggs, Windows installers, etc.), and EasyInstall will + then be aware of the files available there. - You may specify multiple URLs with this option, separated by whitespace. - Note that on the command line, you will probably have to surround the URLs - with quotes, so that they are recognized as a single option value. You can - also specify URLs in a configuration file; see `Configuration Files`_, - above; but note that this means the specified pages will be downloaded - every time you use EasyInstall (unless overridden on the command line) and - thus may make startup slower. + You may specify multiple URLs or directories with this option, separated by + whitespace. Note that on the command line, you will probably have to + surround the URL list with quotes, so that it is recognized as a single + option value. You can also specify URLs in a configuration file; see + `Configuration Files`_, above; but note that this means the specified pages + will be downloaded every time you use EasyInstall (unless overridden on the + command line) and thus may make startup slower. ``--delete-conflicting, -D`` (New in 0.5a9) If you are replacing a package that was previously installed *without* @@ -593,6 +596,13 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. +0.5a10 + * Put the ``easy_install`` module back in as a module, as it's needed for + ``python -m`` to run it! + + * Allow ``--find-links/-f`` to accept local directories or filenames as well + as URLs. + 0.5a9 * EasyInstall now automatically detects when an "unmanaged" package or module is going to be on ``sys.path`` ahead of a package you're installing, Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.38 retrieving revision 1.39 diff -u -d -r1.38 -r1.39 --- pkg_resources.py 8 Jul 2005 04:45:57 -0000 1.38 +++ pkg_resources.py 12 Jul 2005 05:31:36 -0000 1.39 @@ -69,17 +69,17 @@ def get_provider(moduleName): """Return an IResourceProvider for the named module""" - module = sys.modules[moduleName] + try: + module = sys.modules[moduleName] + except KeyError: + __import__(moduleName) + module = sys.modules[moduleName] loader = getattr(module, '__loader__', None) return _find_adapter(_provider_factories, loader)(module) - - - - def get_platform(): """Return this platform's string for platform-specific distributions @@ -984,6 +984,7 @@ def find_nothing(importer,path_item): return () + register_finder(object,find_nothing) def find_on_path(importer,path_item): @@ -1004,7 +1005,7 @@ fullpath = os.path.join(path_item, entry) lower = entry.lower() if lower.endswith('.egg'): - for dist in find_on_path(importer,fullpath): + for dist in find_distributions(fullpath): yield dist elif lower.endswith('.egg-info'): if os.path.isdir(fullpath): @@ -1017,12 +1018,11 @@ if not line.strip(): continue for item in find_distributions(line.rstrip()): yield item - elif path_item.lower().endswith('.egg'): # packed egg - metadata = EggMetadata(zipimport.zipimporter(path_item)) - yield Distribution.from_filename(path_item, metadata=metadata) register_finder(ImpWrapper,find_on_path) + + _namespace_handlers = {} _namespace_packages = {} Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.25 retrieving revision 1.26 diff -u -d -r1.25 -r1.26 --- setup.py 11 Jul 2005 04:21:57 -0000 1.25 +++ setup.py 12 Jul 2005 05:31:36 -0000 1.26 @@ -33,7 +33,7 @@ test_suite = 'setuptools.tests.test_suite', packages = find_packages(), - py_modules = ['pkg_resources'], + py_modules = ['pkg_resources', 'easy_install'], scripts = ['easy_install.py'], zip_safe = True, Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- setuptools.txt 11 Jul 2005 04:21:57 -0000 1.8 +++ setuptools.txt 12 Jul 2005 05:31:36 -0000 1.9 @@ -1334,6 +1334,17 @@ Release Notes/Change History ---------------------------- +0.5a10 + * Fix a problem with ``pkg_resources`` being confused by non-existent eggs on + ``sys.path`` (e.g. if a user deletes an egg without removing it from the + ``easy-install.pth`` file. + + * Fix a problem with "basket" support in ``pkg_resources``, where egg-finding + never actually went inside ``.egg`` files. + + * Made ``pkg_resources`` import the module you request resources from, if it's + not already imported. + 0.5a9 * Include ``svn:externals`` directories in source distributions as well as normal subversion-controlled files and directories. From pje at users.sourceforge.net Tue Jul 12 07:32:08 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 11 Jul 2005 22:32:08 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.16, 1.17 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26625/setuptools Modified Files: __init__.py Log Message: Bump version #. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- __init__.py 11 Jul 2005 04:21:57 -0000 1.16 +++ __init__.py 12 Jul 2005 05:32:05 -0000 1.17 @@ -7,7 +7,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a9' +__version__ = '0.5a10' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', 'find_packages' From pje at users.sourceforge.net Tue Jul 12 07:32:08 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 11 Jul 2005 22:32:08 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.36, 1.37 ez_setup.py, 1.15, 1.16 setup.py, 1.26, 1.27 setuptools.txt, 1.9, 1.10 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26625 Modified Files: EasyInstall.txt ez_setup.py setup.py setuptools.txt Log Message: Bump version #. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.36 retrieving revision 1.37 diff -u -d -r1.36 -r1.37 --- EasyInstall.txt 12 Jul 2005 05:31:36 -0000 1.36 +++ EasyInstall.txt 12 Jul 2005 05:32:05 -0000 1.37 @@ -29,7 +29,7 @@ ------------------------- Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py `_, and run it; this will download and install the appropriate ``setuptools`` egg for your Python @@ -70,7 +70,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a9" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a10" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- ez_setup.py 11 Jul 2005 04:21:56 -0000 1.15 +++ ez_setup.py 12 Jul 2005 05:32:05 -0000 1.16 @@ -14,7 +14,7 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a9" +DEFAULT_VERSION = "0.5a10" DEFAULT_URL = "http://www.python.org/packages/source/s/setuptools/" import sys, os Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.26 retrieving revision 1.27 diff -u -d -r1.26 -r1.27 --- setup.py 12 Jul 2005 05:31:36 -0000 1.26 +++ setup.py 12 Jul 2005 05:32:05 -0000 1.27 @@ -15,7 +15,7 @@ f.close() return ''.join(lines) -VERSION = "0.5a9" +VERSION = "0.5a10" from setuptools import setup, find_packages Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- setuptools.txt 12 Jul 2005 05:31:36 -0000 1.9 +++ setuptools.txt 12 Jul 2005 05:32:05 -0000 1.10 @@ -64,7 +64,7 @@ ========================= Windows users can just download and run the `setuptools binary installer for -Windows `_. +Windows `_. All others should just download `ez_setup.py`_ and run it; this will download and install the appropriate egg for your Python version. From pje at users.sourceforge.net Tue Jul 12 07:35:01 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Mon, 11 Jul 2005 22:35:01 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.37, 1.38 setuptools.txt, 1.10, 1.11 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27994 Modified Files: EasyInstall.txt setuptools.txt Log Message: Drop links to the Windows installer; it was installing an "unmanaged" version of setuptools! Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.37 retrieving revision 1.38 diff -u -d -r1.37 -r1.38 --- EasyInstall.txt 12 Jul 2005 05:32:05 -0000 1.37 +++ EasyInstall.txt 12 Jul 2005 05:34:58 -0000 1.38 @@ -28,12 +28,9 @@ Installing "Easy Install" ------------------------- -Windows users can just download and run the `setuptools binary installer for -Windows `_. -All others should just download `ez_setup.py -`_, and run it; this will -download and install the appropriate ``setuptools`` egg for your Python -version. +Download `ez_setup.py `_, and +run it; this will download and install the appropriate ``setuptools`` egg for +your Python version. You may receive a message telling you about an obsolete version of setuptools being present; if so, you must be sure to delete it entirely, along Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- setuptools.txt 12 Jul 2005 05:32:05 -0000 1.10 +++ setuptools.txt 12 Jul 2005 05:34:58 -0000 1.11 @@ -63,10 +63,8 @@ Installing ``setuptools`` ========================= -Windows users can just download and run the `setuptools binary installer for -Windows `_. -All others should just download `ez_setup.py`_ and run it; this will -download and install the appropriate egg for your Python version. +Download `ez_setup.py`_ and run it; this will download and install the +appropriate egg for your Python version. .. _ez_setup.py: `bootstrap module`_ From birkenfeld at users.sourceforge.net Tue Jul 12 09:28:22 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Tue, 12 Jul 2005 00:28:22 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libtarfile.tex,1.9,1.10 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19125/Doc/lib Modified Files: libtarfile.tex Log Message: bug [ 1235266 ] debug info file descriptor of tarfile is inconsistent Index: libtarfile.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libtarfile.tex,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- libtarfile.tex 5 Mar 2005 12:47:41 -0000 1.9 +++ libtarfile.tex 12 Jul 2005 07:28:20 -0000 1.10 @@ -299,7 +299,7 @@ \begin{memberdesc}{debug=0} To be set from \code{0} (no debug messages; the default) up to \code{3} (all debug messages). The messages are written to - \code{sys.stdout}. + \code{sys.stderr}. \end{memberdesc} \begin{memberdesc}{errorlevel} From birkenfeld at users.sourceforge.net Tue Jul 12 09:28:27 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Tue, 12 Jul 2005 00:28:27 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libtarfile.tex, 1.7, 1.7.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19113/Doc/lib Modified Files: Tag: release24-maint libtarfile.tex Log Message: backport bug [ 1235266 ] debug info file descriptor of tarfile is inconsistent Index: libtarfile.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libtarfile.tex,v retrieving revision 1.7 retrieving revision 1.7.2.1 diff -u -d -r1.7 -r1.7.2.1 --- libtarfile.tex 11 Sep 2004 16:50:05 -0000 1.7 +++ libtarfile.tex 12 Jul 2005 07:28:25 -0000 1.7.2.1 @@ -281,7 +281,7 @@ \begin{memberdesc}{debug=0} To be set from \code{0} (no debug messages; the default) up to \code{3} (all debug messages). The messages are written to - \code{sys.stdout}. + \code{sys.stderr}. \end{memberdesc} \begin{memberdesc}{errorlevel} From mwh at users.sourceforge.net Tue Jul 12 12:21:21 2005 From: mwh at users.sourceforge.net (mwh@users.sourceforge.net) Date: Tue, 12 Jul 2005 03:21:21 -0700 Subject: [Python-checkins] python/dist/src/Objects abstract.c,2.136,2.137 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10231/Objects Modified Files: abstract.c Log Message: Fix: [ 1229429 ] missing Py_DECREF in PyObject_CallMethod Add a test in test_enumerate, which is a bit random, but suffices (reversed_new calls PyObject_CallMethod under some circumstances). Index: abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.136 retrieving revision 2.137 diff -u -d -r2.136 -r2.137 --- abstract.c 26 Apr 2005 03:45:25 -0000 2.136 +++ abstract.c 12 Jul 2005 10:21:02 -0000 2.137 @@ -1797,7 +1797,9 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...) { va_list va; - PyObject *args, *func = 0, *retval; + PyObject *args = NULL; + PyObject *func = NULL; + PyObject *retval = NULL; if (o == NULL || name == NULL) return null_error(); @@ -1808,8 +1810,10 @@ return 0; } - if (!PyCallable_Check(func)) - return type_error("call of non-callable attribute"); + if (!PyCallable_Check(func)) { + type_error("call of non-callable attribute"); + goto exit; + } if (format && *format) { va_start(va, format); @@ -1820,23 +1824,24 @@ args = PyTuple_New(0); if (!args) - return NULL; + goto exit; if (!PyTuple_Check(args)) { PyObject *a; a = PyTuple_New(1); if (a == NULL) - return NULL; + goto exit; if (PyTuple_SetItem(a, 0, args) < 0) - return NULL; + goto exit; args = a; } retval = PyObject_Call(func, args, NULL); - Py_DECREF(args); - Py_DECREF(func); + exit: + Py_XDECREF(args); + Py_XDECREF(func); return retval; } From mwh at users.sourceforge.net Tue Jul 12 12:21:22 2005 From: mwh at users.sourceforge.net (mwh@users.sourceforge.net) Date: Tue, 12 Jul 2005 03:21:22 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_enumerate.py, 1.14, 1.15 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10231/Lib/test Modified Files: test_enumerate.py Log Message: Fix: [ 1229429 ] missing Py_DECREF in PyObject_CallMethod Add a test in test_enumerate, which is a bit random, but suffices (reversed_new calls PyObject_CallMethod under some circumstances). Index: test_enumerate.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_enumerate.py,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- test_enumerate.py 29 Sep 2004 11:40:50 -0000 1.14 +++ test_enumerate.py 12 Jul 2005 10:21:19 -0000 1.15 @@ -1,4 +1,5 @@ import unittest +import sys from test import test_support @@ -175,6 +176,25 @@ self.assertRaises(TypeError, reversed) self.assertRaises(TypeError, reversed, [], 'extra') + def test_bug1229429(self): + # this bug was never in reversed, it was in + # PyObject_CallMethod, and reversed_new calls that sometimes. + if not hasattr(sys, "getrefcount"): + return + def f(): + pass + r = f.__reversed__ = object() + rc = sys.getrefcount(r) + for i in range(10): + try: + reversed(f) + except TypeError: + pass + else: + self.fail("non-callable __reversed__ didn't raise!") + self.assertEqual(rc, sys.getrefcount(r)) + + def test_main(verbose=None): testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig, TestReversed) From mwh at users.sourceforge.net Tue Jul 12 12:21:34 2005 From: mwh at users.sourceforge.net (mwh@users.sourceforge.net) Date: Tue, 12 Jul 2005 03:21:34 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1312,1.1313 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10231/Misc Modified Files: NEWS Log Message: Fix: [ 1229429 ] missing Py_DECREF in PyObject_CallMethod Add a test in test_enumerate, which is a bit random, but suffices (reversed_new calls PyObject_CallMethod under some circumstances). Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1312 retrieving revision 1.1313 diff -u -d -r1.1312 -r1.1313 --- NEWS 10 Jul 2005 22:30:52 -0000 1.1312 +++ NEWS 12 Jul 2005 10:21:01 -0000 1.1313 @@ -12,6 +12,9 @@ Core and builtins ----------------- +- SF bug #1229429: PyObject_CallMethod failed to decrement some + reference counts in some error exit cases. + - SF bug #1185883: Python's small-object memory allocator took over a block managed by the platform C library whenever a realloc specified a small new size. However, there's no portable way to know then how From birkenfeld at users.sourceforge.net Tue Jul 12 15:18:01 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Tue, 12 Jul 2005 06:18:01 -0700 Subject: [Python-checkins] python/dist/src/Doc/ext run-func.c,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3287/Doc/ext Modified Files: run-func.c Log Message: bug [ 1232768 ] Mistakes in online docs under "5.3 Pure Embedding" Index: run-func.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/run-func.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- run-func.c 17 Dec 2002 00:40:38 -0000 1.4 +++ run-func.c 12 Jul 2005 13:17:59 -0000 1.5 @@ -20,11 +20,8 @@ Py_DECREF(pName); if (pModule != NULL) { - pDict = PyModule_GetDict(pModule); - /* pDict is a borrowed reference */ - - pFunc = PyDict_GetItemString(pDict, argv[2]); - /* pFun: Borrowed reference */ + pFunc = PyDict_GetItemString(pModule, argv[2]); + /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { pArgs = PyTuple_New(argc - 3); @@ -46,18 +43,19 @@ Py_DECREF(pValue); } else { + Py_DECREF(pFunc); Py_DECREF(pModule); PyErr_Print(); fprintf(stderr,"Call failed\n"); return 1; } - /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */ } else { if (PyErr_Occurred()) PyErr_Print(); fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]); } + Py_XDECREF(pFunc); Py_DECREF(pModule); } else { From birkenfeld at users.sourceforge.net Tue Jul 12 15:18:06 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Tue, 12 Jul 2005 06:18:06 -0700 Subject: [Python-checkins] python/dist/src/Doc/ext run-func.c,1.4,1.4.20.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3346/Doc/ext Modified Files: Tag: release24-maint run-func.c Log Message: backport bug [ 1232768 ] Mistakes in online docs under "5.3 Pure Embedding" Index: run-func.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/run-func.c,v retrieving revision 1.4 retrieving revision 1.4.20.1 diff -u -d -r1.4 -r1.4.20.1 --- run-func.c 17 Dec 2002 00:40:38 -0000 1.4 +++ run-func.c 12 Jul 2005 13:18:04 -0000 1.4.20.1 @@ -20,11 +20,8 @@ Py_DECREF(pName); if (pModule != NULL) { - pDict = PyModule_GetDict(pModule); - /* pDict is a borrowed reference */ - - pFunc = PyDict_GetItemString(pDict, argv[2]); - /* pFun: Borrowed reference */ + pFunc = PyDict_GetItemString(pModule, argv[2]); + /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { pArgs = PyTuple_New(argc - 3); @@ -46,18 +43,19 @@ Py_DECREF(pValue); } else { + Py_DECREF(pFunc); Py_DECREF(pModule); PyErr_Print(); fprintf(stderr,"Call failed\n"); return 1; } - /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */ } else { if (PyErr_Occurred()) PyErr_Print(); fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]); } + Py_XDECREF(pFunc); Py_DECREF(pModule); } else { From birkenfeld at users.sourceforge.net Tue Jul 12 15:20:51 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Tue, 12 Jul 2005 06:20:51 -0700 Subject: [Python-checkins] python/dist/src/Doc/ext run-func.c,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5448/Doc/ext Modified Files: run-func.c Log Message: Oops. Index: run-func.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/run-func.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- run-func.c 12 Jul 2005 13:17:59 -0000 1.5 +++ run-func.c 12 Jul 2005 13:20:49 -0000 1.6 @@ -20,7 +20,7 @@ Py_DECREF(pName); if (pModule != NULL) { - pFunc = PyDict_GetItemString(pModule, argv[2]); + pFunc = PyDict_GetAttrString(pModule, argv[2]); /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { From birkenfeld at users.sourceforge.net Tue Jul 12 15:20:58 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Tue, 12 Jul 2005 06:20:58 -0700 Subject: [Python-checkins] python/dist/src/Doc/ext run-func.c, 1.4.20.1, 1.4.20.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5458/Doc/ext Modified Files: Tag: release24-maint run-func.c Log Message: Oops. Index: run-func.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/run-func.c,v retrieving revision 1.4.20.1 retrieving revision 1.4.20.2 diff -u -d -r1.4.20.1 -r1.4.20.2 --- run-func.c 12 Jul 2005 13:18:04 -0000 1.4.20.1 +++ run-func.c 12 Jul 2005 13:20:56 -0000 1.4.20.2 @@ -20,7 +20,7 @@ Py_DECREF(pName); if (pModule != NULL) { - pFunc = PyDict_GetItemString(pModule, argv[2]); + pFunc = PyDict_GetAttrString(pModule, argv[2]); /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { From gvanrossum at users.sourceforge.net Tue Jul 12 18:27:57 2005 From: gvanrossum at users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Tue, 12 Jul 2005 09:27:57 -0700 Subject: [Python-checkins] python/nondist/peps pep-0343.txt,1.27,1.28 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30940 Modified Files: pep-0343.txt Log Message: Rename @with_template and class Wrapper to @contextmanager and class ContextManager. Mark open issues as resolved. Index: pep-0343.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0343.txt,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- pep-0343.txt 28 Jun 2005 07:39:09 -0000 1.27 +++ pep-0343.txt 12 Jul 2005 16:27:53 -0000 1.28 @@ -111,7 +111,7 @@ example, it was impossible to do this for the opening example. The idea was to define the template like this: - @with_template + @contextmanager def opening(filename): f = open(filename) try: @@ -258,7 +258,7 @@ that makes it possible to use a generator that yields exactly once to control a with-statement. Here's a sketch of such a decorator: - class Wrapper(object): + class ContextManager(object): def __init__(self, gen): self.gen = gen @@ -285,16 +285,16 @@ else: raise RuntimeError("generator caught exception") - def with_template(func): + def contextmanager(func): def helper(*args, **kwds): - return Wrapper(func(*args, **kwds)) + return ContextManager(func(*args, **kwds)) return helper This decorator could be used as follows: - @with_template + @contextmanager def opening(filename): - f = open(filename) # IOError here is untouched by Wrapper + f = open(filename) # IOError is untouched by ContextManager try: yield f finally: @@ -332,18 +332,20 @@ is entered). OTOH such mistakes are easily diagnosed; for example, the - with_template decorator above raises RuntimeError when the second + contextmanager decorator above raises RuntimeError when the second with-statement calls f.__enter__() again. -Open Issues +Resolved Open Issues - Discussion on python-dev has revealed some open issues. I list - them here, with my preferred resolution and its motivation. The - PEP as currently written reflects this preferred resolution. + Discussion on python-dev revealed some open issues. I list them + here, with my preferred resolution and its motivation. The PEP + has been accepted without these being challenged, so the issues + are now resolved. - 1. The __exit__() method of the with_template decorator class catches - StopIteration and considers it equivalent to re-raising the exception - passed to throw(). Is allowing StopIteration right here? + 1. The __exit__() method of the contextmanager decorator class + catches StopIteration and considers it equivalent to re-raising + the exception passed to throw(). Is allowing StopIteration + right here? This is so that a generator doing cleanup depending on the exception thrown (like the transactional() example below) can @@ -368,7 +370,7 @@ 1. A template for ensuring that a lock, acquired at the start of a block, is released when the block is left: - @with_template + @contextmanager def locking(lock): lock.acquire() try: @@ -390,7 +392,7 @@ 2. A template for opening a file that ensures the file is closed when the block is left: - @with_template + @contextmanager def opening(filename, mode="r"): f = open(filename, mode) try: @@ -407,7 +409,7 @@ 3. A template for committing or rolling back a database transaction: - @with_template + @contextmanager def transactional(db): db.begin() try: @@ -433,7 +435,7 @@ 5. Redirect stdout temporarily: - @with_template + @contextmanager def redirecting_stdout(new_stdout): save_stdout = sys.stdout sys.stdout = new_stdout @@ -454,7 +456,7 @@ 6. A variant on opening() that also returns an error condition: - @with_template + @contextmanager def opening_w_error(filename, mode="r"): try: f = open(filename, mode) @@ -491,7 +493,7 @@ import decimal - @with_template + @contextmanager def extra_precision(places=2): c = decimal.getcontext() saved_prec = c.prec @@ -520,7 +522,7 @@ 9. Here's a more general Decimal-context-switching template: - @with_template + @contextmanager def decimal_context(newctx=None): oldctx = decimal.getcontext() if newctx is None: @@ -545,7 +547,7 @@ 10. A generic "object-closing" template: - @with_template + @contextmanager def closing(obj): try: yield obj From gvanrossum at users.sourceforge.net Tue Jul 12 18:28:59 2005 From: gvanrossum at users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Tue, 12 Jul 2005 09:28:59 -0700 Subject: [Python-checkins] python/nondist/peps pep-0343.txt,1.28,1.29 Message-ID: Update of /cvsroot/python/python/nondist/peps In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31380 Modified Files: pep-0343.txt Log Message: Rename class ContextManager to ContextWrapper, per Nick's proposal. Index: pep-0343.txt =================================================================== RCS file: /cvsroot/python/python/nondist/peps/pep-0343.txt,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- pep-0343.txt 12 Jul 2005 16:27:53 -0000 1.28 +++ pep-0343.txt 12 Jul 2005 16:28:56 -0000 1.29 @@ -258,7 +258,7 @@ that makes it possible to use a generator that yields exactly once to control a with-statement. Here's a sketch of such a decorator: - class ContextManager(object): + class ContextWrapper(object): def __init__(self, gen): self.gen = gen @@ -287,14 +287,14 @@ def contextmanager(func): def helper(*args, **kwds): - return ContextManager(func(*args, **kwds)) + return ContextWrapper(func(*args, **kwds)) return helper This decorator could be used as follows: @contextmanager def opening(filename): - f = open(filename) # IOError is untouched by ContextManager + f = open(filename) # IOError is untouched by ContextWrapper try: yield f finally: From jackjansen at users.sourceforge.net Tue Jul 12 23:25:08 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Tue, 12 Jul 2005 14:25:08 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/file _Filemodule.c, 1.24, 1.25 filesupport.py, 1.21, 1.22 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/file In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8264 Modified Files: _Filemodule.c filesupport.py Log Message: Fix for #1236090: FSSpec.as_pathname() crashes. Turns out patch #1035255 was incomplete, it only patched _Filemodule.c and not filesupport.py. So regenerating caused as_pathname() to go into an infinite loop. Index: _Filemodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/file/_Filemodule.c,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- _Filemodule.c 3 Jul 2005 20:59:40 -0000 1.24 +++ _Filemodule.c 12 Jul 2005 21:24:52 -0000 1.25 @@ -92,6 +92,50 @@ return Py_BuildValue("u#", itself->unicode, itself->length); } +static OSErr +_PyMac_GetFullPathname(FSSpec *fss, char *path, int len) +{ + FSRef fsr; + OSErr err; + + *path = '\0'; + err = FSpMakeFSRef(fss, &fsr); + if (err == fnfErr) { + /* FSSpecs can point to non-existing files, fsrefs can't. */ + FSSpec fss2; + int tocopy; + + err = FSMakeFSSpec(fss->vRefNum, fss->parID, "", &fss2); + if (err) + return err; + err = FSpMakeFSRef(&fss2, &fsr); + if (err) + return err; + err = (OSErr)FSRefMakePath(&fsr, path, len-1); + if (err) + return err; + /* This part is not 100% safe: we append the filename part, but + ** I'm not sure that we don't run afoul of the various 8bit + ** encodings here. Will have to look this up at some point... + */ + strcat(path, "/"); + tocopy = fss->name[0]; + if ((strlen(path) + tocopy) >= len) + tocopy = len - strlen(path) - 1; + if (tocopy > 0) + strncat(path, fss->name+1, tocopy); + } + else { + if (err) + return err; + err = (OSErr)FSRefMakePath(&fsr, path, len); + if (err) + return err; + } + return 0; +} + + static PyObject *File_Error; /* ------------------- Object type FSCatalogInfo -------------------- */ @@ -1265,7 +1309,7 @@ if (!PyArg_ParseTuple(_args, "")) return NULL; - err = PyMac_GetFullPathname(&_self->ob_itself, strbuf, sizeof(strbuf)); + err = _PyMac_GetFullPathname(&_self->ob_itself, strbuf, sizeof(strbuf)); if ( err ) { PyMac_Error(err); return NULL; Index: filesupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/file/filesupport.py,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- filesupport.py 3 Jul 2005 20:59:40 -0000 1.21 +++ filesupport.py 12 Jul 2005 21:25:05 -0000 1.22 @@ -198,6 +198,53 @@ return Py_BuildValue("u#", itself->unicode, itself->length); } + +/* +** Get pathname for a given FSSpec +*/ +static OSErr +_PyMac_GetFullPathname(FSSpec *fss, char *path, int len) +{ + FSRef fsr; + OSErr err; + + *path = '\0'; + err = FSpMakeFSRef(fss, &fsr); + if (err == fnfErr) { + /* FSSpecs can point to non-existing files, fsrefs can't. */ + FSSpec fss2; + int tocopy; + + err = FSMakeFSSpec(fss->vRefNum, fss->parID, "", &fss2); + if (err) + return err; + err = FSpMakeFSRef(&fss2, &fsr); + if (err) + return err; + err = (OSErr)FSRefMakePath(&fsr, path, len-1); + if (err) + return err; + /* This part is not 100% safe: we append the filename part, but + ** I'm not sure that we don't run afoul of the various 8bit + ** encodings here. Will have to look this up at some point... + */ + strcat(path, "/"); + tocopy = fss->name[0]; + if ((strlen(path) + tocopy) >= len) + tocopy = len - strlen(path) - 1; + if (tocopy > 0) + strncat(path, fss->name+1, tocopy); + } + else { + if (err) + return err; + err = (OSErr)FSRefMakePath(&fsr, path, len); + if (err) + return err; + } + return 0; +} + """ finalstuff = finalstuff + """ @@ -798,7 +845,7 @@ if (!PyArg_ParseTuple(_args, "")) return NULL; -err = PyMac_GetFullPathname(&_self->ob_itself, strbuf, sizeof(strbuf)); +err = _PyMac_GetFullPathname(&_self->ob_itself, strbuf, sizeof(strbuf)); if ( err ) { PyMac_Error(err); return NULL; From doerwalter at users.sourceforge.net Tue Jul 12 23:53:46 2005 From: doerwalter at users.sourceforge.net (doerwalter@users.sourceforge.net) Date: Tue, 12 Jul 2005 14:53:46 -0700 Subject: [Python-checkins] python/dist/src/Parser tokenizer.c,2.77,2.78 Message-ID: Update of /cvsroot/python/python/dist/src/Parser In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25927/Parser Modified Files: tokenizer.c Log Message: Apply SF patch #1101726: Fix buffer overrun in tokenizer.c when a source file with a PEP 263 encoding declaration results in long decoded line. Index: tokenizer.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Parser/tokenizer.c,v retrieving revision 2.77 retrieving revision 2.78 diff -u -d -r2.77 -r2.78 --- tokenizer.c 3 Mar 2005 11:45:45 -0000 2.77 +++ tokenizer.c 12 Jul 2005 21:53:43 -0000 2.78 @@ -334,7 +334,19 @@ } /* Read a line of text from TOK into S, using the stream in TOK. - Return NULL on failure, else S. */ + Return NULL on failure, else S. + + On entry, tok->decoding_buffer will be one of: + 1) NULL: need to call tok->decoding_readline to get a new line + 2) PyUnicodeObject *: decoding_feof has called tok->decoding_readline and + stored the result in tok->decoding_buffer + 3) PyStringObject *: previous call to fp_readl did not have enough room + (in the s buffer) to copy entire contents of the line read + by tok->decoding_readline. tok->decoding_buffer has the overflow. + In this case, fp_readl is called in a loop (with an expanded buffer) + until the buffer ends with a '\n' (or until the end of the file is + reached): see tok_nextc and its calls to decoding_fgets. +*/ static char * fp_readl(char *s, int size, struct tok_state *tok) @@ -344,32 +356,45 @@ Py_FatalError("fp_readl should not be called in this build."); return NULL; /* Keep compiler happy (not reachable) */ #else - PyObject* utf8; + PyObject* utf8 = NULL; PyObject* buf = tok->decoding_buffer; + char *str; + int utf8len; + + /* Ask for one less byte so we can terminate it */ + assert(size > 0); + size--; + if (buf == NULL) { - /* Ask for one less byte so we can terminate it */ - PyObject *args = Py_BuildValue("(i)", size-1); - if (args == NULL) - return error_ret(tok); - buf = PyObject_Call(tok->decoding_readline, args, NULL); - Py_DECREF(args); + buf = PyObject_CallObject(tok->decoding_readline, NULL); if (buf == NULL) return error_ret(tok); } else { tok->decoding_buffer = NULL; + if (PyString_CheckExact(buf)) + utf8 = buf; } - utf8 = PyUnicode_AsUTF8String(buf); - Py_DECREF(buf); - if (utf8 == NULL) - return error_ret(tok); - else { - const char* str = PyString_AsString(utf8); - assert(strlen(str) < (size_t)size); /* XXX */ - strcpy(s, str); - Py_DECREF(utf8); - if (s[0] == '\0') return NULL; /* EOF */ - return s; + if (utf8 == NULL) { + utf8 = PyUnicode_AsUTF8String(buf); + Py_DECREF(buf); + if (utf8 == NULL) + return error_ret(tok); + } + str = PyString_AsString(utf8); + utf8len = PyString_GET_SIZE(utf8); + if (utf8len > size) { + tok->decoding_buffer = PyString_FromStringAndSize(str+size, utf8len-size); + if (tok->decoding_buffer == NULL) { + Py_DECREF(utf8); + return error_ret(tok); + } + utf8len = size; } + memcpy(s, str, utf8len); + s[utf8len] = '\0'; + Py_DECREF(utf8); + if (utf8len == 0) return NULL; /* EOF */ + return s; #endif } @@ -491,14 +516,7 @@ } else { PyObject* buf = tok->decoding_buffer; if (buf == NULL) { - PyObject *args = PyTuple_New(0); - if (args == NULL) { - error_ret(tok); - return 1; - } - buf = PyObject_Call(tok->decoding_readline, - args, NULL); - Py_DECREF(args); + buf = PyObject_CallObject(tok->decoding_readline, NULL); if (buf == NULL) { error_ret(tok); return 1; From doerwalter at users.sourceforge.net Tue Jul 12 23:58:40 2005 From: doerwalter at users.sourceforge.net (doerwalter@users.sourceforge.net) Date: Tue, 12 Jul 2005 14:58:40 -0700 Subject: [Python-checkins] python/dist/src/Parser tokenizer.c, 2.76, 2.76.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Parser In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28082/Parser Modified Files: Tag: release24-maint tokenizer.c Log Message: Backport checkin: Apply SF patch #1101726: Fix buffer overrun in tokenizer.c when a source file with a PEP 263 encoding declaration results in long decoded line. Index: tokenizer.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Parser/tokenizer.c,v retrieving revision 2.76 retrieving revision 2.76.2.1 diff -u -d -r2.76 -r2.76.2.1 --- tokenizer.c 4 Aug 2004 17:36:41 -0000 2.76 +++ tokenizer.c 12 Jul 2005 21:58:38 -0000 2.76.2.1 @@ -334,7 +334,19 @@ } /* Read a line of text from TOK into S, using the stream in TOK. - Return NULL on failure, else S. */ + Return NULL on failure, else S. + + On entry, tok->decoding_buffer will be one of: + 1) NULL: need to call tok->decoding_readline to get a new line + 2) PyUnicodeObject *: decoding_feof has called tok->decoding_readline and + stored the result in tok->decoding_buffer + 3) PyStringObject *: previous call to fp_readl did not have enough room + (in the s buffer) to copy entire contents of the line read + by tok->decoding_readline. tok->decoding_buffer has the overflow. + In this case, fp_readl is called in a loop (with an expanded buffer) + until the buffer ends with a '\n' (or until the end of the file is + reached): see tok_nextc and its calls to decoding_fgets. +*/ static char * fp_readl(char *s, int size, struct tok_state *tok) @@ -344,32 +356,45 @@ Py_FatalError("fp_readl should not be called in this build."); return NULL; /* Keep compiler happy (not reachable) */ #else - PyObject* utf8; + PyObject* utf8 = NULL; PyObject* buf = tok->decoding_buffer; + char *str; + int utf8len; + + /* Ask for one less byte so we can terminate it */ + assert(size > 0); + size--; + if (buf == NULL) { - /* Ask for one less byte so we can terminate it */ - PyObject *args = Py_BuildValue("(i)", size-1); - if (args == NULL) - return error_ret(tok); - buf = PyObject_Call(tok->decoding_readline, args, NULL); - Py_DECREF(args); + buf = PyObject_CallObject(tok->decoding_readline, NULL); if (buf == NULL) return error_ret(tok); } else { tok->decoding_buffer = NULL; + if (PyString_CheckExact(buf)) + utf8 = buf; } - utf8 = PyUnicode_AsUTF8String(buf); - Py_DECREF(buf); - if (utf8 == NULL) - return error_ret(tok); - else { - const char* str = PyString_AsString(utf8); - assert(strlen(str) < (size_t)size); /* XXX */ - strcpy(s, str); - Py_DECREF(utf8); - if (s[0] == '\0') return NULL; /* EOF */ - return s; + if (utf8 == NULL) { + utf8 = PyUnicode_AsUTF8String(buf); + Py_DECREF(buf); + if (utf8 == NULL) + return error_ret(tok); + } + str = PyString_AsString(utf8); + utf8len = PyString_GET_SIZE(utf8); + if (utf8len > size) { + tok->decoding_buffer = PyString_FromStringAndSize(str+size, utf8len-size); + if (tok->decoding_buffer == NULL) { + Py_DECREF(utf8); + return error_ret(tok); + } + utf8len = size; } + memcpy(s, str, utf8len); + s[utf8len] = '\0'; + Py_DECREF(utf8); + if (utf8len == 0) return NULL; /* EOF */ + return s; #endif } @@ -491,14 +516,7 @@ } else { PyObject* buf = tok->decoding_buffer; if (buf == NULL) { - PyObject *args = PyTuple_New(0); - if (args == NULL) { - error_ret(tok); - return 1; - } - buf = PyObject_Call(tok->decoding_readline, - args, NULL); - Py_DECREF(args); + buf = PyObject_CallObject(tok->decoding_readline, NULL); if (buf == NULL) { error_ret(tok); return 1; From pje at users.sourceforge.net Wed Jul 13 01:22:08 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 12 Jul 2005 16:22:08 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools ez_setup.py, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8905 Modified Files: ez_setup.py Log Message: Add a message explaining that you can use -U setuptools to reinstall or upgrade setuptools. Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- ez_setup.py 12 Jul 2005 16:09:00 -0000 1.17 +++ ez_setup.py 12 Jul 2005 23:22:06 -0000 1.18 @@ -157,8 +157,8 @@ from setuptools.command.easy_install import main main(argv) else: - print "Setuptools successfully installed or upgraded." - + print "Setuptools version",version,"or greater has been installed." + print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' if __name__=='__main__': main(sys.argv[1:]) From pje at users.sourceforge.net Wed Jul 13 01:22:48 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 12 Jul 2005 16:22:48 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools setup.py, 1.28, 1.29 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9201 Modified Files: setup.py Log Message: Fixed not being able to use python -m easy_install. Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- setup.py 12 Jul 2005 16:09:00 -0000 1.28 +++ setup.py 12 Jul 2005 23:22:32 -0000 1.29 @@ -35,7 +35,7 @@ packages = find_packages(), py_modules = ['pkg_resources', 'easy_install'], scripts = ['easy_install.py'], - zip_safe = True, + zip_safe = False, # We want 'python -m easy_install' to work :( From pje at users.sourceforge.net Wed Jul 13 01:43:24 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 12 Jul 2005 16:43:24 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command bdist_egg.py, 1.26, 1.27 easy_install.py, 1.8, 1.9 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20931/setuptools/command Modified Files: bdist_egg.py easy_install.py Log Message: Update zip-safety scanner to check for modules that might be used as ``python -m`` scripts. Misc. fixes for win32.exe support, including changes to support Python 2.4's changed ``bdist_wininst`` format. Index: bdist_egg.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/bdist_egg.py,v retrieving revision 1.26 retrieving revision 1.27 diff -u -d -r1.26 -r1.27 --- bdist_egg.py 11 Jul 2005 04:12:48 -0000 1.26 +++ bdist_egg.py 12 Jul 2005 23:43:21 -0000 1.27 @@ -332,14 +332,11 @@ filename = os.path.join(base,name) if filename[:-1] in stubs: return True # Extension module - pkg = base[len(egg_dir)+1:].replace(os.sep,'.') module = pkg+(pkg and '.' or '')+os.path.splitext(name)[0] - f = open(filename,'rb'); f.read(8) # skip magic & date code = marshal.load(f); f.close() safe = True - symbols = dict.fromkeys(iter_symbols(code)) for bad in ['__file__', '__path__']: if bad in symbols: @@ -353,7 +350,11 @@ ]: if bad in symbols: log.warn("%s: module MAY be using inspect.%s", module, bad) - safe = False + safe = False + if '__name__' in symbols and '__main__' in symbols and '.' not in module: + if get_python_version()>="2.4": + log.warn("%s: top-level module may be 'python -m' script", module) + safe = False return safe def iter_symbols(code): @@ -366,7 +367,6 @@ for name in iter_symbols(const): yield name - # Attribute names of options for commands that might need to be convinced to # install to the egg build directory Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- easy_install.py 11 Jul 2005 04:12:48 -0000 1.8 +++ easy_install.py 12 Jul 2005 23:43:22 -0000 1.9 @@ -508,10 +508,12 @@ # Convert the .exe to an unpacked egg egg_path = dist.path = os.path.join(tmpdir, dist.egg_name()+'.egg') egg_tmp = egg_path+'.tmp' + pkg_inf = os.path.join(egg_tmp, 'EGG-INFO', 'PKG-INFO') + ensure_directory(pkg_inf) # make sure EGG-INFO dir exists + self.exe_to_egg(dist_filename, egg_tmp) # Write EGG-INFO/PKG-INFO - pkg_inf = os.path.join(egg_tmp, 'EGG-INFO', 'PKG-INFO') f = open(pkg_inf,'w') f.write('Metadata-Version: 1.0\n') for k,v in cfg.items('metadata'): @@ -529,8 +531,6 @@ return self.install_egg(egg_path, tmpdir) - - def exe_to_egg(self, dist_filename, egg_tmp): """Extract a bdist_wininst to the directories an egg would use""" # Check for .pth file and set up prefix translations @@ -575,9 +575,9 @@ for name in 'top_level','native_libs': if locals()[name]: txt = os.path.join(egg_tmp, 'EGG-INFO', name+'.txt') - ensure_directory(txt) open(txt,'w').write('\n'.join(locals()[name])+'\n') + def check_conflicts(self, dist): """Verify that there are no conflicting "old-style" packages""" @@ -708,7 +708,7 @@ if self.dry_run: args.insert(0,'-n') - dist_dir = tempfile.mkdtemp(prefix='egg-dist-tmp-', dir=setup_base) + dist_dir = tempfile.mkdtemp(prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script)) try: args.append(dist_dir) log.info( @@ -877,13 +877,13 @@ import struct, StringIO, ConfigParser tag, cfglen, bmlen = struct.unpack("0x1234567A: + if tag not in (0x1234567A, 0x1234567B): return None # not a valid tag f.seek(prepended-(12+cfglen+bmlen)) cfg = ConfigParser.RawConfigParser({'version':'','target_version':''}) try: - cfg.readfp(StringIO.StringIO(f.read(cfglen))) + cfg.readfp(StringIO.StringIO(f.read(cfglen).split(chr(0),1)[0])) except ConfigParser.Error: return None if not cfg.has_section('metadata') or not cfg.has_section('Setup'): From pje at users.sourceforge.net Wed Jul 13 02:09:28 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 12 Jul 2005 17:09:28 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.39, 1.40 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2330 Modified Files: pkg_resources.py Log Message: Updated extraction/cache mechanism for zipped resources to avoid inter- process and inter-thread races during extraction. The default cache location can now be set via the ``PYTHON_EGGS_CACHE`` environment variable, and the default Windows cache is now a ``Python-Eggs`` subdirectory of the current user's "Application Data" directory, if the ``PYTHON_EGGS_CACHE`` variable isn't set. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- pkg_resources.py 12 Jul 2005 05:31:36 -0000 1.39 +++ pkg_resources.py 13 Jul 2005 00:09:25 -0000 1.40 @@ -23,6 +23,7 @@ 'get_importer', 'find_distributions', 'find_on_path', 'register_finder', 'split_sections', 'declare_namespace', 'register_namespace_handler', 'safe_name', 'safe_version', 'run_main', 'BINARY_DIST', 'run_script', + 'get_default_cache', ] import sys, os, zipimport, time, re, imp @@ -38,7 +39,6 @@ - class ResolutionError(Exception): """Abstract base for dependency resolution errors""" @@ -421,16 +421,15 @@ obtain an extraction location, and only for names they intend to extract, as it tracks the generated names for possible cleanup later. """ - extract_path = self.extraction_path - extract_path = extract_path or os.path.expanduser('~/.python-eggs') - target_path = os.path.join(extract_path, archive_name, *names) + extract_path = self.extraction_path or get_default_cache() + target_path = os.path.join(extract_path, archive_name+'-tmp', *names) ensure_directory(target_path) self.cached_files[target_path] = 1 return target_path - def postprocess(self, filename): - """Perform any platform-specific postprocessing of file `filename` + def postprocess(self, tempname, filename): + """Perform any platform-specific postprocessing of `tempname` This is where Mac header rewrites should be done; other platforms don't have anything special they should do. @@ -438,6 +437,10 @@ Resource providers should call this method ONLY after successfully extracting a compressed resource. They must NOT call it on resources that are already in the filesystem. + + `tempname` is the current (temporary) name of the file, and `filename` + is the name it will be renamed to by the caller after this routine + returns. """ # XXX @@ -446,9 +449,6 @@ - - - def set_extraction_path(self, path): """Set the base path where resources will be extracted to, if needed. @@ -490,6 +490,48 @@ +def get_default_cache(): + """Determine the default cache location + + This returns the ``PYTHON_EGG_CACHE`` environment variable, if set. + Otherwise, on Windows, it returns a "Python-Eggs" subdirectory of the + "Application Data" directory. On all other systems, it's "~/.python-eggs". + """ + try: + return os.environ['PYTHON_EGG_CACHE'] + except KeyError: + pass + + if os.name!='nt': + return os.path.expanduser('~/.python-eggs') + + app_data = 'Application Data' # XXX this may be locale-specific! + app_homes = [ + (('APPDATA',), None), # best option, should be locale-safe + (('USERPROFILE',), app_data), + (('HOMEDRIVE','HOMEPATH'), app_data), + (('HOMEPATH',), app_data), + (('HOME',), None), + (('WINDIR',), app_data), # 95/98/ME + ] + + for keys, subdir in app_homes: + dirname = '' + for key in keys: + if key in os.environ: + dirname = os.path.join(os.environ[key]) + else: + break + else: + if subdir: + dirname = os.path.join(dirname,subdir) + return os.path.join(dirname, 'Python-Eggs') + else: + raise RuntimeError( + "Please set the PYTHON_EGG_CACHE enviroment variable" + ) + + def require(*requirements): """Ensure that distributions matching `requirements` are on ``sys.path`` @@ -719,7 +761,7 @@ "resource_filename() only supported for .egg, not .zip" ) - # should lock for extraction here + # no need to lock for extraction, since we use temp names eagers = self._get_eager_resources() if resource_name in eagers: for name in eagers: @@ -757,14 +799,26 @@ # size and stamp match, don't bother extracting return real_path - # print "extracting", zip_path + from tempfile import mkstemp + outf, tmpnam = mkstemp(".$extract", dir=os.path.dirname(real_path)) + os.write(outf, self.loader.get_data(zip_path)) + os.close(outf) + os.utime(tmpnam, (timestamp,timestamp)) + manager.postprocess(tmpnam, real_path) + try: + os.rename(tmpnam, real_path) + except os.error: + if os.path.isfile(real_path): + stat = os.stat(real_path) + if stat.st_size==size and stat.st_mtime==timestamp: + # size and stamp match, somebody did it just ahead of us + # so we're done + return real_path + raise - data = self.loader.get_data(zip_path) - open(real_path, 'wb').write(data) - os.utime(real_path, (timestamp,timestamp)) - manager.postprocess(real_path) return real_path + def _get_eager_resources(self): if self.eagers is None: eagers = [] @@ -774,9 +828,6 @@ self.eagers = eagers return self.eagers - - - def _index(self): try: return self._dirindex @@ -806,6 +857,9 @@ def _listdir(self,path): return list(self._index().get(self._dir_name(path), ())) + + + def _dir_name(self,path): if path.startswith(self.module_path+os.sep): path = path[len(self.module_path+os.sep):] @@ -818,6 +872,35 @@ register_loader_type(zipimport.zipimporter, ZipProvider) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + class PathMetadata(DefaultProvider): """Metadata provider for egg directories From pje at users.sourceforge.net Wed Jul 13 02:10:02 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 12 Jul 2005 17:10:02 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.39, 1.40 ez_setup.py, 1.18, 1.19 setup.py, 1.29, 1.30 setuptools.txt, 1.12, 1.13 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3110 Modified Files: EasyInstall.txt ez_setup.py setup.py setuptools.txt Log Message: Prep for 0.5a12 release; update docs. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- EasyInstall.txt 12 Jul 2005 16:08:59 -0000 1.39 +++ EasyInstall.txt 13 Jul 2005 00:10:00 -0000 1.40 @@ -67,7 +67,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a11" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a12" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: @@ -593,6 +593,14 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. +0.5a12 + * Fix ``python -m easy_install`` not working due to setuptools being installed + as a zipfile. Update safety scanner to check for modules that might be used + as ``python -m`` scripts. + + * Misc. fixes for win32.exe support, including changes to support Python 2.4's + changed ``bdist_wininst`` format. + 0.5a10 * Put the ``easy_install`` module back in as a module, as it's needed for ``python -m`` to run it! Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- ez_setup.py 12 Jul 2005 23:22:06 -0000 1.18 +++ ez_setup.py 13 Jul 2005 00:10:00 -0000 1.19 @@ -14,7 +14,7 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a11" +DEFAULT_VERSION = "0.5a12" DEFAULT_URL = "http://www.python.org/packages/source/s/setuptools/" import sys, os Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.29 retrieving revision 1.30 diff -u -d -r1.29 -r1.30 --- setup.py 12 Jul 2005 23:22:32 -0000 1.29 +++ setup.py 13 Jul 2005 00:10:00 -0000 1.30 @@ -15,7 +15,7 @@ f.close() return ''.join(lines) -VERSION = "0.5a11" +VERSION = "0.5a12" from setuptools import setup, find_packages Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- setuptools.txt 12 Jul 2005 16:09:00 -0000 1.12 +++ setuptools.txt 13 Jul 2005 00:10:00 -0000 1.13 @@ -1332,6 +1332,18 @@ Release Notes/Change History ---------------------------- +0.5a12 + * The zip-safety scanner now checks for modules that might be used with + ``python -m``, and marks them as unsafe for zipping, since Python 2.4 can't + handle ``-m`` on zipped modules. + + * Updated extraction/cache mechanism for zipped resources to avoid inter- + process and inter-thread races during extraction. The default cache + location can now be set via the ``PYTHON_EGGS_CACHE`` environment variable, + and the default Windows cache is now a ``Python-Eggs`` subdirectory of the + current user's "Application Data" directory, if the ``PYTHON_EGGS_CACHE`` + variable isn't set. + 0.5a11 * Fix breakage of the "develop" command that was caused by the addition of ``--always-unzip`` to the ``easy_install`` command. From pje at users.sourceforge.net Wed Jul 13 02:10:02 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Tue, 12 Jul 2005 17:10:02 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.18, 1.19 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3110/setuptools Modified Files: __init__.py Log Message: Prep for 0.5a12 release; update docs. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- __init__.py 12 Jul 2005 16:09:00 -0000 1.18 +++ __init__.py 13 Jul 2005 00:10:00 -0000 1.19 @@ -7,7 +7,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a11' +__version__ = '0.5a12' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', 'find_packages' From birkenfeld at users.sourceforge.net Thu Jul 14 08:40:49 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Wed, 13 Jul 2005 23:40:49 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_urllib2.py, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25167/Lib/test Modified Files: test_urllib2.py Log Message: RFE [ 1216944 ] Add Error Code Dictionary to urllib2 Index: test_urllib2.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_urllib2.py,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- test_urllib2.py 7 Aug 2004 17:40:50 -0000 1.19 +++ test_urllib2.py 14 Jul 2005 06:40:47 -0000 1.20 @@ -40,6 +40,10 @@ buf = f.read() f.close() + + def test_statudict(self): + # test the new-in-2.5 httpresponses dictionary + self.assertEquals(urllib2.httpresponses[404], "Not Found") class MockOpener: From birkenfeld at users.sourceforge.net Thu Jul 14 08:40:50 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Wed, 13 Jul 2005 23:40:50 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1313,1.1314 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25167/Misc Modified Files: NEWS Log Message: RFE [ 1216944 ] Add Error Code Dictionary to urllib2 Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1313 retrieving revision 1.1314 diff -u -d -r1.1313 -r1.1314 --- NEWS 12 Jul 2005 10:21:01 -0000 1.1313 +++ NEWS 14 Jul 2005 06:40:47 -0000 1.1314 @@ -168,6 +168,9 @@ Library ------- +- urllib2 has now an attribute 'httpresponses' mapping from HTTP status code + to W3C name (404 -> 'Not Found'). RFE #1216944. + - Bug #1177468: Don't cache the /dev/urandom file descriptor for os.urandom, as this can cause problems with apps closing all file descriptors. From birkenfeld at users.sourceforge.net Thu Jul 14 08:40:49 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Wed, 13 Jul 2005 23:40:49 -0700 Subject: [Python-checkins] python/dist/src/Lib urllib2.py,1.82,1.83 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25167/Lib Modified Files: urllib2.py Log Message: RFE [ 1216944 ] Add Error Code Dictionary to urllib2 Index: urllib2.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/urllib2.py,v retrieving revision 1.82 retrieving revision 1.83 diff -u -d -r1.82 -r1.83 --- urllib2.py 26 Jun 2005 22:01:35 -0000 1.82 +++ urllib2.py 14 Jul 2005 06:40:46 -0000 1.83 @@ -1293,3 +1293,52 @@ if inspect.isclass(ph): ph = ph() opener.add_handler(ph) + +# Mapping status codes to official W3C names +httpresponses = { + 100: 'Continue', + 101: 'Switching Protocols', + + 200: 'OK', + 201: 'Created', + 202: 'Accepted', + 203: 'Non-Authoritative Information', + 204: 'No Content', + 205: 'Reset Content', + 206: 'Partial Content', + + 300: 'Multiple Choices', + 301: 'Moved Permanently', + 302: 'Found', + 303: 'See Other', + 304: 'Not Modified', + 305: 'Use Proxy', + 306: '(Unused)', + 307: 'Temporary Redirect', + + 400: 'Bad Request', + 401: 'Unauthorized', + 402: 'Payment Required', + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 406: 'Not Acceptable', + 407: 'Proxy Authentication Required', + 408: 'Request Timeout', + 409: 'Conflict', + 410: 'Gone', + 411: 'Length Required', + 412: 'Precondition Failed', + 413: 'Request Entity Too Large', + 414: 'Request-URI Too Long', + 415: 'Unsupported Media Type', + 416: 'Requested Range Not Satisfiable', + 417: 'Expectation Failed', + + 500: 'Internal Server Error', + 501: 'Not Implemented', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + 504: 'Gateway Timeout', + 505: 'HTTP Version Not Supported', +} From birkenfeld at users.sourceforge.net Thu Jul 14 08:40:49 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Wed, 13 Jul 2005 23:40:49 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib liburllib2.tex, 1.22, 1.23 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25167/Doc/lib Modified Files: liburllib2.tex Log Message: RFE [ 1216944 ] Add Error Code Dictionary to urllib2 Index: liburllib2.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/liburllib2.tex,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- liburllib2.tex 13 Apr 2005 01:08:23 -0000 1.22 +++ liburllib2.tex 14 Jul 2005 06:40:47 -0000 1.23 @@ -71,6 +71,15 @@ \end{funcdesc} +The following attribute is defined: + +\begin{datadesc}{httpresponses} +A mapping between HTTP status codes and the W3C names. + +Example: \code{urllib2.httpresponses[404]} is \code{'Not Found'}. +\versionadded{2.5} +\end{datadesc} + The following exceptions are raised as appropriate: \begin{excdesc}{URLError} From rhettinger at users.sourceforge.net Thu Jul 14 19:34:03 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Thu, 14 Jul 2005 10:34:03 -0700 Subject: [Python-checkins] python/dist/src/Misc developers.txt,1.15,1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27943 Modified Files: developers.txt Log Message: Brett requests that Flovis's permissions be dropped. Index: developers.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/developers.txt,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- developers.txt 8 Jul 2005 14:47:38 -0000 1.15 +++ developers.txt 14 Jul 2005 17:34:00 -0000 1.16 @@ -50,6 +50,8 @@ Permissions Dropped on Request ------------------------------ +- Flovis Bruynooghe sent a drop request. 14 July 2005 RDH + - Paul Prescod sent a drop request. 30 Apr 2005 RDH - Finn Bock sent a drop request. 13 Apr 2005 RDH From pje at users.sourceforge.net Fri Jul 15 06:10:14 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 14 Jul 2005 21:10:14 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.40, 1.41 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29492 Modified Files: EasyInstall.txt Log Message: Fix formatting error. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.40 retrieving revision 1.41 diff -u -d -r1.40 -r1.41 --- EasyInstall.txt 13 Jul 2005 00:10:00 -0000 1.40 +++ EasyInstall.txt 15 Jul 2005 04:10:12 -0000 1.41 @@ -603,7 +603,7 @@ 0.5a10 * Put the ``easy_install`` module back in as a module, as it's needed for - ``python -m`` to run it! + ``python -m`` to run it! * Allow ``--find-links/-f`` to accept local directories or filenames as well as URLs. From pje at users.sourceforge.net Fri Jul 15 06:11:40 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 14 Jul 2005 21:11:40 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.40, 1.41 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29688 Modified Files: pkg_resources.py Log Message: Fix a problem extracting resources from nested packages. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.40 retrieving revision 1.41 diff -u -d -r1.40 -r1.41 --- pkg_resources.py 13 Jul 2005 00:09:25 -0000 1.40 +++ pkg_resources.py 15 Jul 2005 04:11:37 -0000 1.41 @@ -531,7 +531,6 @@ "Please set the PYTHON_EGG_CACHE enviroment variable" ) - def require(*requirements): """Ensure that distributions matching `requirements` are on ``sys.path`` @@ -717,6 +716,7 @@ old = path path, base = os.path.split(path) self.prefix.append(base) + self.prefix.reverse() def _has(self, path): return os.path.exists(path) @@ -736,7 +736,6 @@ register_loader_type(type(None), DefaultProvider) - class ZipProvider(DefaultProvider): """Resource support for zips and eggs""" From rhettinger at users.sourceforge.net Fri Jul 15 08:53:37 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Thu, 14 Jul 2005 23:53:37 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1314,1.1315 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19320/Misc Modified Files: NEWS Log Message: textwrap now processes text chucks at O(n) speed instead of O(n**2). Patch #1209527 (Contributed by Connelly). Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1314 retrieving revision 1.1315 diff -u -d -r1.1314 -r1.1315 --- NEWS 14 Jul 2005 06:40:47 -0000 1.1314 +++ NEWS 15 Jul 2005 06:53:34 -0000 1.1315 @@ -168,6 +168,9 @@ Library ------- +- textwrap now processes text chucks at O(n) speed instead of O(n**2). + Patch #1209527 (Contributed by Connelly). + - urllib2 has now an attribute 'httpresponses' mapping from HTTP status code to W3C name (404 -> 'Not Found'). RFE #1216944. From rhettinger at users.sourceforge.net Fri Jul 15 08:53:37 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Thu, 14 Jul 2005 23:53:37 -0700 Subject: [Python-checkins] python/dist/src/Lib textwrap.py,1.37,1.38 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19320/Lib Modified Files: textwrap.py Log Message: textwrap now processes text chucks at O(n) speed instead of O(n**2). Patch #1209527 (Contributed by Connelly). Index: textwrap.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/textwrap.py,v retrieving revision 1.37 retrieving revision 1.38 diff -u -d -r1.37 -r1.38 --- textwrap.py 5 Mar 2005 02:53:16 -0000 1.37 +++ textwrap.py 15 Jul 2005 06:53:35 -0000 1.38 @@ -161,7 +161,7 @@ else: i += 1 - def _handle_long_word(self, chunks, cur_line, cur_len, width): + def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): """_handle_long_word(chunks : [string], cur_line : [string], cur_len : int, width : int) @@ -174,14 +174,14 @@ # If we're allowed to break long words, then do so: put as much # of the next chunk onto the current line as will fit. if self.break_long_words: - cur_line.append(chunks[0][0:space_left]) - chunks[0] = chunks[0][space_left:] + cur_line.append(reversed_chunks[-1][:space_left]) + reversed_chunks[-1] = reversed_chunks[-1][space_left:] # Otherwise, we have to preserve the long word intact. Only add # it to the current line if there's nothing already there -- # that minimizes how much we violate the width constraint. elif not cur_line: - cur_line.append(chunks.pop(0)) + cur_line.append(reversed_chunks.pop()) # If we're not allowed to break long words, and there's already # text on the current line, do nothing. Next time through the @@ -206,6 +206,10 @@ if self.width <= 0: raise ValueError("invalid width %r (must be > 0)" % self.width) + # Arrange in reverse order so items can be efficiently popped + # from a stack of chucks. + chunks.reverse() + while chunks: # Start the list of chunks that will make up the current line. @@ -224,15 +228,15 @@ # First chunk on line is whitespace -- drop it, unless this # is the very beginning of the text (ie. no lines started yet). - if chunks[0].strip() == '' and lines: - del chunks[0] + if chunks[-1].strip() == '' and lines: + del chunks[-1] while chunks: - l = len(chunks[0]) + l = len(chunks[-1]) # Can at least squeeze this chunk onto the current line. if cur_len + l <= width: - cur_line.append(chunks.pop(0)) + cur_line.append(chunks.pop()) cur_len += l # Nope, this line is full. @@ -241,7 +245,7 @@ # The current line is full, and the next chunk is too big to # fit on *any* line (not just this one). - if chunks and len(chunks[0]) > width: + if chunks and len(chunks[-1]) > width: self._handle_long_word(chunks, cur_line, cur_len, width) # If the last chunk on this line is all whitespace, drop it. From alli-cat_thequeen at bigfoot.com Fri Jul 15 11:48:25 2005 From: alli-cat_thequeen at bigfoot.com (Mack Dunn) Date: Fri, 15 Jul 2005 11:48:25 +0200 Subject: [Python-checkins] Additional Agreement #312-191 Message-ID: The best software in one place? It not dream, it is real http://www.gosoft10.info All that needs to be made, download the program and use it. Here the most popular software of all times is collected Download and use!!! From birkenfeld at users.sourceforge.net Fri Jul 15 11:13:23 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 15 Jul 2005 02:13:23 -0700 Subject: [Python-checkins] python/dist/src/Lib threading.py,1.48,1.49 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13609/Lib Modified Files: threading.py Log Message: bug [ 1238170 ] threading.Thread uses {} as default argument Index: threading.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/threading.py,v retrieving revision 1.48 retrieving revision 1.49 diff -u -d -r1.48 -r1.49 --- threading.py 27 Jan 2005 22:48:30 -0000 1.48 +++ threading.py 15 Jul 2005 09:13:21 -0000 1.49 @@ -374,9 +374,11 @@ __exc_info = _sys.exc_info def __init__(self, group=None, target=None, name=None, - args=(), kwargs={}, verbose=None): + args=(), kwargs=None, verbose=None): assert group is None, "group argument must be None for now" _Verbose.__init__(self, verbose) + if kwargs is None: + kwargs = {} self.__target = target self.__name = str(name or _newname()) self.__args = args From birkenfeld at users.sourceforge.net Fri Jul 15 11:13:25 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 15 Jul 2005 02:13:25 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1315,1.1316 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13609/Misc Modified Files: NEWS Log Message: bug [ 1238170 ] threading.Thread uses {} as default argument Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1315 retrieving revision 1.1316 diff -u -d -r1.1315 -r1.1316 --- NEWS 15 Jul 2005 06:53:34 -0000 1.1315 +++ NEWS 15 Jul 2005 09:13:21 -0000 1.1316 @@ -168,6 +168,9 @@ Library ------- +- Bug #1238170: threading.Thread.__init__ no longer has "kwargs={}" as a + parameter, but uses the usual "kwargs=None". + - textwrap now processes text chucks at O(n) speed instead of O(n**2). Patch #1209527 (Contributed by Connelly). From pje at users.sourceforge.net Sat Jul 16 18:17:32 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 09:17:32 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21218/setuptools Modified Files: __init__.py Log Message: prep for 0.5a13 release Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- __init__.py 13 Jul 2005 00:10:00 -0000 1.19 +++ __init__.py 16 Jul 2005 16:17:29 -0000 1.20 @@ -7,7 +7,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a12' +__version__ = '0.5a13' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', 'find_packages' From pje at users.sourceforge.net Sat Jul 16 18:17:32 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 09:17:32 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.41, 1.42 ez_setup.py, 1.19, 1.20 setup.py, 1.30, 1.31 setuptools.txt, 1.13, 1.14 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21218 Modified Files: EasyInstall.txt ez_setup.py setup.py setuptools.txt Log Message: prep for 0.5a13 release Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.41 retrieving revision 1.42 diff -u -d -r1.41 -r1.42 --- EasyInstall.txt 15 Jul 2005 04:10:12 -0000 1.41 +++ EasyInstall.txt 16 Jul 2005 16:17:29 -0000 1.42 @@ -67,7 +67,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a12" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a13" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- ez_setup.py 13 Jul 2005 00:10:00 -0000 1.19 +++ ez_setup.py 16 Jul 2005 16:17:29 -0000 1.20 @@ -14,7 +14,7 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a12" +DEFAULT_VERSION = "0.5a13" DEFAULT_URL = "http://www.python.org/packages/source/s/setuptools/" import sys, os Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -r1.30 -r1.31 --- setup.py 13 Jul 2005 00:10:00 -0000 1.30 +++ setup.py 16 Jul 2005 16:17:29 -0000 1.31 @@ -15,7 +15,7 @@ f.close() return ''.join(lines) -VERSION = "0.5a12" +VERSION = "0.5a13" from setuptools import setup, find_packages Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- setuptools.txt 13 Jul 2005 00:10:00 -0000 1.13 +++ setuptools.txt 16 Jul 2005 16:17:29 -0000 1.14 @@ -1332,6 +1332,9 @@ Release Notes/Change History ---------------------------- +0.5a13 + * Fixed a bug in resource extraction from nested packages in a zipped egg. + 0.5a12 * The zip-safety scanner now checks for modules that might be used with ``python -m``, and marks them as unsafe for zipping, since Python 2.4 can't From pje at users.sourceforge.net Sat Jul 16 18:43:04 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 09:43:04 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command egg_info.py, 1.6, 1.7 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26365/setuptools/command Modified Files: egg_info.py Log Message: Fix only detecting the revision number of the setup directory, not the highest revision number for the project as a whole. Index: egg_info.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/egg_info.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- egg_info.py 10 Jul 2005 15:43:08 -0000 1.6 +++ egg_info.py 16 Jul 2005 16:43:02 -0000 1.7 @@ -134,13 +134,16 @@ def get_svn_revision(self): - stdin, stdout = os.popen4("svn info"); stdin.close() + stdin, stdout = os.popen4("svn info -R"); stdin.close() result = stdout.read(); stdout.close() import re - match = re.search(r'Last Changed Rev: (\d+)', result) - if not match: + revisions = [ + int(match.group(1)) + for match in re.finditer(r'Last Changed Rev: (\d+)', result) + ] + if not revisions: raise DistutilsError("svn info error: %s" % result.strip()) - return match.group(1) + return str(max(revisions)) def write_toplevel_names(self): @@ -159,9 +162,6 @@ - - - def write_namespace_packages(self): nsp = getattr(self.distribution,'namespace_packages',None) if nsp is None: From pje at users.sourceforge.net Sat Jul 16 19:25:38 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 10:25:38 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.41, 1.42 setuptools.txt, 1.14, 1.15 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32676 Modified Files: pkg_resources.py setuptools.txt Log Message: Fixed some problems using ``pkg_resources`` w/PEP 302 loaders other than ``zipimport``. Fixed ``pkg_resources.resource_exists()`` not working correctly. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.41 retrieving revision 1.42 diff -u -d -r1.41 -r1.42 --- pkg_resources.py 15 Jul 2005 04:11:37 -0000 1.41 +++ pkg_resources.py 16 Jul 2005 17:25:35 -0000 1.42 @@ -377,7 +377,7 @@ def resource_exists(self, package_name, resource_name): """Does the named resource exist in the named package?""" - return get_provider(package_name).has_resource(self, resource_name) + return get_provider(package_name).has_resource(resource_name) def resource_isdir(self, package_name, resource_name): """Does the named resource exist in the named package?""" @@ -587,7 +587,7 @@ return self._fn(self.module_path, resource_name) def get_resource_stream(self, manager, resource_name): - return open(self._fn(self.module_path, resource_name), 'rb') + return StringIO(self.get_resource_string(manager, resource_name)) def get_resource_string(self, manager, resource_name): return self._get(self._fn(self.module_path, resource_name)) @@ -667,34 +667,6 @@ register_loader_type(object, NullProvider) - - - - - - - - - - - - - - - - - - - - - - - - - - - - class DefaultProvider(NullProvider): """Provides access to package resources in the filesystem""" @@ -721,12 +693,17 @@ def _has(self, path): return os.path.exists(path) + + def _isdir(self,path): return os.path.isdir(path) def _listdir(self,path): return os.listdir(path) + def get_resource_stream(self, manager, resource_name): + return open(self._fn(self.module_path, resource_name), 'rb') + def _get(self, path): stream = open(path, 'rb') try: @@ -736,6 +713,29 @@ register_loader_type(type(None), DefaultProvider) + + + + + + + + + + + + + + + + + + + + + + + class ZipProvider(DefaultProvider): """Resource support for zips and eggs""" Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- setuptools.txt 16 Jul 2005 16:17:29 -0000 1.14 +++ setuptools.txt 16 Jul 2005 17:25:35 -0000 1.15 @@ -1332,6 +1332,16 @@ Release Notes/Change History ---------------------------- +0.6a1 + * Fixed the ``--tag-svn-revision`` option of ``egg_info`` not finding the + latest revision number; it was using the revision number of the directory + containing ``setup.py``, not the highest revision number in the project. + + * Fixed some problems using ``pkg_resources`` w/PEP 302 loaders other than + ``zipimport``. + + * Fixed ``pkg_resources.resource_exists()`` not working correctly. + 0.5a13 * Fixed a bug in resource extraction from nested packages in a zipped egg. From pje at users.sourceforge.net Sat Jul 16 23:57:52 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 14:57:52 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.42, 1.43 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12306 Modified Files: EasyInstall.txt Log Message: Added ``--site-dirs`` option to allow adding custom "site" directories. Made ``easy-install.pth`` work in platform-specific alternate site directories (e.g. ``~/Library/Python/2.x/site-packages``). Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.42 retrieving revision 1.43 diff -u -d -r1.42 -r1.43 --- EasyInstall.txt 16 Jul 2005 16:17:29 -0000 1.42 +++ EasyInstall.txt 16 Jul 2005 21:57:50 -0000 1.43 @@ -575,6 +575,31 @@ is included for compatibility with tools that expect to pass this option to "setup.py install". +``--site-dirs=DIRLIST, -S DIRLIST`` (New in 0.6a1) + Specify one or more custom "site" directories (separated by commas). + "Site" directories are directories where ``.pth`` files are processed, such + as the main Python ``site-packages`` directory. By default, EasyInstall + only knows about Python-defined "site" directories, not those that may be + added by an OS distribution or site administrator calling + ``site.addsitedir()``. You should not normally need to use this option + directly, as your system administrator should configure it in the + ``distutils.cfg`` file of the Python installation. For example, if the + administrator wants to make each user's ``~/lib/python2.3`` directory be a + "site" directory, he or she should create an ``altinstall.pth`` file in the + normal site-packages directory, containing this:: + + import os; addsitedir(os.path.expanduser('~/lib/python2.3')) + + and a ``distutils.cfg`` file inside the ``distutils`` package directory, + containing this:: + + [easy_install] + site_dirs = ~/lib/python23 + + This will ensure that EasyInstall knows about the additional "site" + directory, thereby allowing individual users to install their own + Python packages via EasyInstall. + Release Notes/Change History ============================ @@ -593,6 +618,11 @@ in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any rate don't expect it to work with all packages. +0.6a1 + * Added ``--site-dirs`` option to allow adding custom "site" directories. + Made ``easy-install.pth`` work in platform-specific alternate site + directories (e.g. ``~/Library/Python/2.x/site-packages``). + 0.5a12 * Fix ``python -m easy_install`` not working due to setuptools being installed as a zipfile. Update safety scanner to check for modules that might be used From pje at users.sourceforge.net Sat Jul 16 23:57:52 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 14:57:52 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.9, 1.10 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12306/setuptools/command Modified Files: easy_install.py Log Message: Added ``--site-dirs`` option to allow adding custom "site" directories. Made ``easy-install.pth`` work in platform-specific alternate site directories (e.g. ``~/Library/Python/2.x/site-packages``). Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- easy_install.py 12 Jul 2005 23:43:22 -0000 1.9 +++ easy_install.py 16 Jul 2005 21:57:50 -0000 1.10 @@ -67,7 +67,8 @@ "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), ('record=', None, "filename in which to record list of installed files"), - ('always-unzip', 'Z', "don't install as a zipfile, no matter what") + ('always-unzip', 'Z', "don't install as a zipfile, no matter what"), + ('site-dirs=','S',"list of directories where .pth files work"), ] boolean_options = [ @@ -79,7 +80,6 @@ create_index = PackageIndex - def initialize_options(self): self.zip_ok = None self.install_dir = self.script_dir = self.exclude_scripts = None @@ -94,7 +94,7 @@ self.pth_file = None self.delete_conflicting = None self.ignore_conflicts_at_my_risk = None - + self.site_dirs = None def delete_blockers(self, blockers): for filename in blockers: @@ -139,17 +139,28 @@ ) # default --record from the install command self.set_undefined_options('install', ('record', 'record')) + normpath = map(normalize,sys.path) + self.all_site_dirs = get_site_dirs() + if self.site_dirs is not None: + site_dirs = [ + os.path.expanduser(s.strip()) for s in self.site_dirs.split(',') + ] + for d in site_dirs: + if not os.path.isdir(d): + log.warn("%s (in --site-dirs) does not exist", d) + elif normalize(d) not in normpath: + raise DistutilsOptionError( + d+" (in --site-dirs) is not on sys.path" + ) + else: + self.all_site_dirs.append(normalize(d)) - site_packages = get_python_lib() - instdir = self.install_dir - - if instdir is None or samefile(site_packages,instdir): - instdir = site_packages + instdir = self.install_dir or self.all_site_dirs[-1] + if normalize(instdir) in self.all_site_dirs: if self.pth_file is None: self.pth_file = PthDistributions( os.path.join(instdir,'easy-install.pth') ) - self.install_dir = instdir elif self.multi_version is None: self.multi_version = True @@ -157,15 +168,15 @@ elif not self.multi_version: # explicit false set from Python code; raise an error raise DistutilsArgError( - "Can't do single-version installs outside site-packages" + "Can't do single-version installs outside 'site-package' dirs" ) + self.install_dir = normalize(instdir) self.index_url = self.index_url or "http://www.python.org/pypi" - - self.shadow_path = sys.path[:] + self.shadow_path = map(normalize,sys.path) for path_item in self.install_dir, self.script_dir: - if path_item not in self.shadow_path: - self.shadow_path.insert(0, self.install_dir) + if normalize(path_item) not in self.shadow_path: + self.shadow_path.insert(0, normalize(path_item)) if self.package_index is None: self.package_index = self.create_index( self.index_url, search_path = self.shadow_path @@ -179,7 +190,6 @@ self.find_links = [] self.set_undefined_options('install_lib', ('optimize','optimize')) - if not isinstance(self.optimize,int): try: self.optimize = int(self.optimize) @@ -192,6 +202,7 @@ "Can't use both --delete-conflicting and " "--ignore-conflicts-at-my-risk at the same time" ) + if not self.args: raise DistutilsArgError( "No urls, filenames, or requirements specified (see --help)") @@ -203,6 +214,7 @@ self.outputs = [] + def alloc_tmp(self): if self.build_directory is None: return tempfile.mkdtemp(prefix="easy_install-") @@ -231,6 +243,7 @@ log.set_verbosity(self.distribution.verbose) + def add_output(self, path): if os.path.isdir(path): for base, dirs, files in os.walk(path): @@ -244,6 +257,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + def easy_install(self, spec): tmpdir = self.alloc_tmp() download = None @@ -591,7 +632,7 @@ for ext,mode,typ in get_suffixes(): exts[ext] = 1 - for path,files in expand_paths([self.install_dir, get_python_lib()]): + for path,files in expand_paths([self.install_dir]+self.all_site_dirs): for filename in files: base,ext = os.path.splitext(filename) if base in names: @@ -670,7 +711,7 @@ pkg_resources.require("%(name)s==%(version)s") # this exact version pkg_resources.require("%(name)s>=%(version)s") # this version or higher """ - if not samefile(get_python_lib(),self.install_dir): + if self.install_dir not in map(normalize,sys.path): msg += """ Note also that the installation directory must be on sys.path at runtime for @@ -708,7 +749,7 @@ if self.dry_run: args.insert(0,'-n') - dist_dir = tempfile.mkdtemp(prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script)) + dist_dir = tempfile.mkdtemp(prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script)) try: args.append(dist_dir) log.info( @@ -729,7 +770,7 @@ if not eggs and not self.dry_run: log.warn("No eggs found in %s (setup script problem?)", dist_dir) - + return eggs finally: @@ -741,14 +782,14 @@ return for d in self.pth_file.get(dist.key,()): # drop old entries - if self.multi_version or d.path != dist.path: + if self.multi_version or normalize(d.path) != normalize(dist.path): log.info("Removing %s from easy-install.pth file", d) self.pth_file.remove(d) - if d.path in self.shadow_path: + if normalize(d.path) in self.shadow_path: self.shadow_path.remove(d.path) if not self.multi_version: - if dist.path in self.pth_file.paths: + if normalize(dist.path) in map(normalize,self.pth_file.paths): log.info( "%s is already the active version in easy-install.pth", dist @@ -756,8 +797,8 @@ else: log.info("Adding %s to easy-install.pth file", dist) self.pth_file.add(dist) # add new entry - if dist.path not in self.shadow_path: - self.shadow_path.append(dist.path) + if normalize(dist.path) not in self.shadow_path: + self.shadow_path.append(normalize(dist.path)) self.pth_file.save() @@ -818,12 +859,54 @@ +def get_site_dirs(): + # return a list of 'site' dirs, based on 'site' module's code to do this + sitedirs = [] + prefixes = [sys.prefix] + if sys.exec_prefix != sys.prefix: + prefixes.append(sys.exec_prefix) + for prefix in prefixes: + if prefix: + if sys.platform in ('os2emx', 'riscos'): + sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) + elif os.sep == '/': + sitedirs.extend([os.path.join(prefix, + "lib", + "python" + sys.version[:3], + "site-packages"), + os.path.join(prefix, "lib", "site-python")]) + else: + sitedirs.extend( + [prefix, os.path.join(prefix, "lib", "site-packages")] + ) + if sys.platform == 'darwin': + # for framework builds *only* we add the standard Apple + # locations. Currently only per-user, but /Library and + # /Network/Library could be added too + if 'Python.framework' in prefix: + home = os.environ.get('HOME') + if home: + sitedirs.append( + os.path.join(home, + 'Library', + 'Python', + sys.version[:3], + 'site-packages')) + + sitedirs = filter(os.path.isdir, sitedirs) + sitedirs = map(normalize, sitedirs) + return sitedirs or [normalize(get_python_lib())] # ensure at least one + + + + def expand_paths(inputs): """Yield sys.path directories that might contain "old-style" packages""" seen = {} for dirname in inputs: + dirname = normalize(dirname) if dirname in seen: continue @@ -850,7 +933,7 @@ # Yield existing non-dupe, non-import directory lines from it for line in lines: if not line.startswith("import"): - line = line.rstrip() + line = normalize(line.rstrip()) if line not in seen: seen[line] = 1 if not os.path.isdir(line): @@ -858,7 +941,6 @@ yield line, os.listdir(line) - def extract_wininst_cfg(dist_filename): """Extract configuration data from a bdist_wininst .exe @@ -987,8 +1069,8 @@ setup(script_args = ['-q','easy_install', '-v']+argv, **kw) - - +def normalize(path): + return os.path.normcase(os.path.realpath(path)) From jackjansen at users.sourceforge.net Sun Jul 17 02:15:49 2005 From: jackjansen at users.sourceforge.net (jackjansen@users.sourceforge.net) Date: Sat, 16 Jul 2005 17:15:49 -0700 Subject: [Python-checkins] python/dist/src/Tools/bgen/bgen scantools.py, 1.41, 1.42 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/bgen/bgen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5315 Modified Files: scantools.py Log Message: Added an option to the scanner to generated marked-up HTML from the input file. This should make it a lot easier (I hope) to get the regular expressions right. Index: scantools.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/scantools.py,v retrieving revision 1.41 retrieving revision 1.42 diff -u -d -r1.41 -r1.42 --- scantools.py 10 Jul 2005 20:37:51 -0000 1.41 +++ scantools.py 17 Jul 2005 00:15:46 -0000 1.42 @@ -32,6 +32,76 @@ Error = "scantools.Error" +BEGINHTMLREPORT=""" + + + +Bgen scan report + + +

Bgen scan report

+

Legend

+

This scan report is intended to help you debug the regular expressions +used by the bgen scanner. It consists of the original ".h" header file(s) +marked up to show you what the regular expressions in the bgen parser matched +for each line. NOTE: comments in the original source files may or may not be +shown.

+

The typographic conventions of this file are as follows:

+
+
comment stripping
+
comment stripping is /* marked up */ and the line is repeated if needed
+

If anything here does not appear to happen correctly look at +comment1_pat and comment2_pat.

+
+
constant definitions
+
#define name value
+

Highlights name and value of the constant. Governed by sym_pat.

+
+
function declaration
+
char *rindex(const char *s, int c);
+

Highlights type, name and argument list. type_pat, +name_pat and args_pat are combined into whole_pat, which +is what is used here.

+ +
incomplete match for function declaration
+
char *foo;
+

The beginning of this looked promising, but it did not match a function declaration. +In other words, it matched head_pat but not whole_pat. If the next +declaration has also been gobbled up you need to look at end_pat.

+
+
unrecognized input
+
#include "type.h"
+

If there are function declarations the scanner has missed (i.e. things +are in this class but you want them to be declarations) you need to adapt +head_pat. +

+
+

Output

+
+
+"""
+ENDHTMLREPORT="""
+
+ + +""" + class Scanner: # Set to 1 in subclass to debug your scanner patterns. @@ -232,9 +302,11 @@ self.specmine = 0 self.defsmine = 0 self.scanmine = 0 + self.htmlmine = 0 self.specfile = sys.stdout self.defsfile = None self.scanfile = sys.stdin + self.htmlfile = None self.lineno = 0 self.line = "" @@ -286,6 +358,7 @@ self.closespec() self.closedefs() self.closescan() + self.closehtml() def closespec(self): tmp = self.specmine and self.specfile @@ -301,6 +374,12 @@ tmp = self.scanmine and self.scanfile self.scanfile = None if tmp: tmp.close() + + def closehtml(self): + if self.htmlfile: self.htmlfile.write(ENDHTMLREPORT) + tmp = self.htmlmine and self.htmlfile + self.htmlfile = None + if tmp: tmp.close() def setoutput(self, spec, defs = None): self.closespec() @@ -324,6 +403,19 @@ self.defsfile = file self.defsmine = mine + def sethtmloutput(self, htmlfile): + self.closehtml() + if htmlfile: + if type(htmlfile) == StringType: + file = self.openoutput(htmlfile) + mine = 1 + else: + file = htmlfile + mine = 0 + self.htmlfile = file + self.htmlmine = mine + self.htmlfile.write(BEGINHTMLREPORT) + def openoutput(self, filename): try: file = open(filename, 'w') @@ -408,11 +500,17 @@ self.report("LINE: %r" % (line,)) match = self.comment1.match(line) if match: + self.htmlreport(line, klass='commentstripping', ranges=[( + match.start('rest'), match.end('rest'), 'notcomment')]) line = match.group('rest') if self.debug: self.report("\tafter comment1: %r" % (line,)) match = self.comment2.match(line) while match: + if match: + self.htmlreport(line, klass='commentstripping', ranges=[ + (match.start('rest1'), match.end('rest1'), 'notcomment'), + (match.start('rest2'), match.end('rest2'), 'notcomment')]) line = match.group('rest1')+match.group('rest2') if self.debug: self.report("\tafter comment2: %r" % (line,)) @@ -422,7 +520,7 @@ if match: if self.debug: self.report("\tmatches sym.") - self.dosymdef(match) + self.dosymdef(match, line) continue match = self.head.match(line) if match: @@ -430,19 +528,26 @@ self.report("\tmatches head.") self.dofuncspec() continue + self.htmlreport(line, klass='unmatched') except EOFError: self.error("Uncaught EOF error") self.reportusedtypes() - def dosymdef(self, match): + def dosymdef(self, match, line): name, defn = match.group('name', 'defn') + self.htmlreport(line, klass='constant', ranges=[ + (match.start('name'), match.end('name'), 'name'), + (match.start('defn'), match.end('defn'), 'value')]) defn = escape8bit(defn) if self.debug: self.report("\tsym: name=%r, defn=%r" % (name, defn)) if not name in self.blacklistnames: - self.defsfile.write("%s = %s\n" % (name, defn)) + oline = "%s = %s\n" % (name, defn) + self.defsfile.write(oline) + self.htmlreport(oline, klass="pyconstant") else: self.defsfile.write("# %s = %s\n" % (name, defn)) + self.htmlreport("** no output: name is blacklisted", klass="blconstant") # XXXX No way to handle greylisted names def dofuncspec(self): @@ -473,19 +578,30 @@ if not match: self.report("Bad raw spec: %r", raw) if self.debug: - if not self.type.search(raw): + match = self.type.search(raw) + if not match: self.report("(Type already doesn't match)") + self.htmlreport(raw, klass='incomplete', ranges=[( + match.start('type'), match.end('type'), 'type')]) else: self.report("(but type matched)") + self.htmlreport(raw, klass='incomplete') return type, name, args = match.group('type', 'name', 'args') + ranges=[ + (match.start('type'), match.end('type'), 'type'), + (match.start('name'), match.end('name'), 'name'), + (match.start('args'), match.end('args'), 'arglist')] + self.htmlreport(raw, klass='declaration', ranges=ranges) modifiers = self.getmodifiers(match) type = self.pythonizename(type) name = self.pythonizename(name) if self.checkduplicate(name): + self.htmlreport("*** no output generated: duplicate name", klass="blacklisted") return self.report("==> %s %s <==", type, name) if self.blacklisted(type, name): + self.htmlreport("*** no output generated: function name or return type blacklisted", klass="blacklisted") self.report("*** %s %s blacklisted", type, name) return returnlist = [(type, name, 'ReturnMode')] @@ -494,6 +610,7 @@ arglist = self.extractarglist(args) arglist = self.repairarglist(name, arglist) if self.unmanageable(type, name, arglist): + self.htmlreport("*** no output generated: some argument blacklisted", klass="blacklisted") ##for arg in arglist: ## self.report(" %r", arg) self.report("*** %s %s unmanageable", type, name) @@ -611,8 +728,12 @@ classname, listname = self.destination(tp, name, arglist, modifiers) else: classname, listname = self.destination(tp, name, arglist) - if not classname or not listname: return - if not self.specfile: return + if not classname or not listname: + self.htmlreport("*** no output generated: self.destination() returned None", klass="blacklisted") + return + if not self.specfile: + self.htmlreport("*** no output generated: no output file specified", klass="blacklisted") + return self.specfile.write("f = %s(%s, %r,\n" % (classname, tp, name)) for atype, aname, amode in arglist: self.typeused(atype, amode) @@ -623,6 +744,12 @@ self.generatemodifiers(classname, name, modifiers) self.specfile.write(")\n") self.specfile.write("%s.append(f)\n\n" % listname) + if self.htmlfile: + oline = "Adding to %s:\n%s(returntype=%s, name=%r" % (listname, classname, tp, name) + for atype, aname, amode in arglist: + oline += ",\n (%s, %r, %s)" % (atype, aname, amode) + oline += ")\n" + self.htmlreport(oline, klass="pydeclaration") def destination(self, type, name, arglist): return "FunctionGenerator", "functions" @@ -646,6 +773,34 @@ return 1 return 0 + def htmlreport(self, line, klass=None, ranges=None): + if not self.htmlfile: return + if ranges is None: + ranges = [] + if klass: + ranges.insert(0, (0, len(line), klass)) + oline = '' + i = 0 + for c in line: + for b, e, name in ranges: + if b == i: + oline += '' % name + if e == i: + oline += '' + i += 1 + + if c == '<': oline += '<' + elif c == '>': oline += '>' + else: oline += c + for b, e, name in ranges: + if b >= i: + oline += '' % name + if e >= i: + oline += '' + if not line or line[-1] != '\n': + oline += '\n' + self.htmlfile.write(oline) + class Scanner_PreUH3(Scanner): """Scanner for Universal Headers before release 3""" def initpatterns(self): From perky at users.sourceforge.net Sun Jul 17 03:25:10 2005 From: perky at users.sourceforge.net (perky@users.sourceforge.net) Date: Sat, 16 Jul 2005 18:25:10 -0700 Subject: [Python-checkins] python/dist/src/Lib/plat-freebsd7 - New directory Message-ID: Update of /cvsroot/python/python/dist/src/Lib/plat-freebsd7 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19229/plat-freebsd7 Log Message: Directory /cvsroot/python/python/dist/src/Lib/plat-freebsd7 added to the repository From perky at users.sourceforge.net Sun Jul 17 04:37:02 2005 From: perky at users.sourceforge.net (perky@users.sourceforge.net) Date: Sat, 16 Jul 2005 19:37:02 -0700 Subject: [Python-checkins] python/dist/src/Lib/plat-freebsd7 IN.py, NONE, 1.1 regen, NONE, 1.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/plat-freebsd7 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29720/Lib/plat-freebsd7 Added Files: IN.py regen Log Message: Add support for FreeBSD 7. --- NEW FILE: IN.py --- # Generated by h2py from /usr/include/netinet/in.h # Included from sys/cdefs.h __GNUCLIKE_ASM = 3 __GNUCLIKE_ASM = 2 __GNUCLIKE___TYPEOF = 1 __GNUCLIKE___OFFSETOF = 1 __GNUCLIKE___SECTION = 1 __GNUCLIKE_ATTRIBUTE_MODE_DI = 1 __GNUCLIKE_CTOR_SECTION_HANDLING = 1 __GNUCLIKE_BUILTIN_CONSTANT_P = 1 __GNUCLIKE_BUILTIN_VARARGS = 1 __GNUCLIKE_BUILTIN_VAALIST = 1 __GNUC_VA_LIST_COMPATIBILITY = 1 __GNUCLIKE_BUILTIN_STDARG = 1 __GNUCLIKE_BUILTIN_NEXT_ARG = 1 __GNUCLIKE_BUILTIN_MEMCPY = 1 __CC_SUPPORTS_INLINE = 1 __CC_SUPPORTS___INLINE = 1 __CC_SUPPORTS___INLINE__ = 1 __CC_SUPPORTS___FUNC__ = 1 __CC_SUPPORTS_WARNING = 1 __CC_SUPPORTS_VARADIC_XXX = 1 __CC_SUPPORTS_DYNAMIC_ARRAY_INIT = 1 __CC_INT_IS_32BIT = 1 def __P(protos): return protos def __STRING(x): return #x def __XSTRING(x): return __STRING(x) def __P(protos): return () def __STRING(x): return "x" def __aligned(x): return __attribute__((__aligned__(x))) def __section(x): return __attribute__((__section__(x))) def __aligned(x): return __attribute__((__aligned__(x))) def __section(x): return __attribute__((__section__(x))) def __nonnull(x): return __attribute__((__nonnull__(x))) def __predict_true(exp): return __builtin_expect((exp), 1) def __predict_false(exp): return __builtin_expect((exp), 0) def __predict_true(exp): return (exp) def __predict_false(exp): return (exp) def __FBSDID(s): return __IDSTRING(__CONCAT(__rcsid_,__LINE__),s) def __RCSID(s): return __IDSTRING(__CONCAT(__rcsid_,__LINE__),s) def __RCSID_SOURCE(s): return __IDSTRING(__CONCAT(__rcsid_source_,__LINE__),s) def __SCCSID(s): return __IDSTRING(__CONCAT(__sccsid_,__LINE__),s) def __COPYRIGHT(s): return __IDSTRING(__CONCAT(__copyright_,__LINE__),s) _POSIX_C_SOURCE = 199009 _POSIX_C_SOURCE = 199209 __XSI_VISIBLE = 600 _POSIX_C_SOURCE = 200112 __XSI_VISIBLE = 500 _POSIX_C_SOURCE = 199506 _POSIX_C_SOURCE = 198808 __POSIX_VISIBLE = 200112 __ISO_C_VISIBLE = 1999 __POSIX_VISIBLE = 199506 __ISO_C_VISIBLE = 1990 __POSIX_VISIBLE = 199309 __ISO_C_VISIBLE = 1990 __POSIX_VISIBLE = 199209 __ISO_C_VISIBLE = 1990 __POSIX_VISIBLE = 199009 __ISO_C_VISIBLE = 1990 __POSIX_VISIBLE = 198808 __ISO_C_VISIBLE = 0 __POSIX_VISIBLE = 0 __XSI_VISIBLE = 0 __BSD_VISIBLE = 0 __ISO_C_VISIBLE = 1990 __POSIX_VISIBLE = 0 __XSI_VISIBLE = 0 __BSD_VISIBLE = 0 __ISO_C_VISIBLE = 1999 __POSIX_VISIBLE = 200112 __XSI_VISIBLE = 600 __BSD_VISIBLE = 1 __ISO_C_VISIBLE = 1999 # Included from sys/_types.h # Included from machine/_types.h # Included from machine/endian.h _QUAD_HIGHWORD = 1 _QUAD_LOWWORD = 0 _LITTLE_ENDIAN = 1234 _BIG_ENDIAN = 4321 _PDP_ENDIAN = 3412 _BYTE_ORDER = _LITTLE_ENDIAN LITTLE_ENDIAN = _LITTLE_ENDIAN BIG_ENDIAN = _BIG_ENDIAN PDP_ENDIAN = _PDP_ENDIAN BYTE_ORDER = _BYTE_ORDER def __word_swap_int_var(x): return \ def __word_swap_int_const(x): return \ def __word_swap_int(x): return __word_swap_int_var(x) def __byte_swap_int_var(x): return \ def __byte_swap_int_const(x): return \ def __byte_swap_int(x): return __byte_swap_int_var(x) def __byte_swap_word_var(x): return \ def __byte_swap_word_const(x): return \ def __byte_swap_word(x): return __byte_swap_word_var(x) def __htonl(x): return __bswap32(x) def __htons(x): return __bswap16(x) def __ntohl(x): return __bswap32(x) def __ntohs(x): return __bswap16(x) IPPROTO_IP = 0 IPPROTO_ICMP = 1 IPPROTO_TCP = 6 IPPROTO_UDP = 17 def htonl(x): return __htonl(x) def htons(x): return __htons(x) def ntohl(x): return __ntohl(x) def ntohs(x): return __ntohs(x) IPPROTO_RAW = 255 INET_ADDRSTRLEN = 16 IPPROTO_HOPOPTS = 0 IPPROTO_IGMP = 2 IPPROTO_GGP = 3 IPPROTO_IPV4 = 4 IPPROTO_IPIP = IPPROTO_IPV4 IPPROTO_ST = 7 IPPROTO_EGP = 8 IPPROTO_PIGP = 9 IPPROTO_RCCMON = 10 IPPROTO_NVPII = 11 IPPROTO_PUP = 12 IPPROTO_ARGUS = 13 IPPROTO_EMCON = 14 IPPROTO_XNET = 15 IPPROTO_CHAOS = 16 IPPROTO_MUX = 18 IPPROTO_MEAS = 19 IPPROTO_HMP = 20 IPPROTO_PRM = 21 IPPROTO_IDP = 22 IPPROTO_TRUNK1 = 23 IPPROTO_TRUNK2 = 24 IPPROTO_LEAF1 = 25 IPPROTO_LEAF2 = 26 IPPROTO_RDP = 27 IPPROTO_IRTP = 28 IPPROTO_TP = 29 IPPROTO_BLT = 30 IPPROTO_NSP = 31 IPPROTO_INP = 32 IPPROTO_SEP = 33 IPPROTO_3PC = 34 IPPROTO_IDPR = 35 IPPROTO_XTP = 36 IPPROTO_DDP = 37 IPPROTO_CMTP = 38 IPPROTO_TPXX = 39 IPPROTO_IL = 40 IPPROTO_IPV6 = 41 IPPROTO_SDRP = 42 IPPROTO_ROUTING = 43 IPPROTO_FRAGMENT = 44 IPPROTO_IDRP = 45 IPPROTO_RSVP = 46 IPPROTO_GRE = 47 IPPROTO_MHRP = 48 IPPROTO_BHA = 49 IPPROTO_ESP = 50 IPPROTO_AH = 51 IPPROTO_INLSP = 52 IPPROTO_SWIPE = 53 IPPROTO_NHRP = 54 IPPROTO_MOBILE = 55 IPPROTO_TLSP = 56 IPPROTO_SKIP = 57 IPPROTO_ICMPV6 = 58 IPPROTO_NONE = 59 IPPROTO_DSTOPTS = 60 IPPROTO_AHIP = 61 IPPROTO_CFTP = 62 IPPROTO_HELLO = 63 IPPROTO_SATEXPAK = 64 IPPROTO_KRYPTOLAN = 65 IPPROTO_RVD = 66 IPPROTO_IPPC = 67 IPPROTO_ADFS = 68 IPPROTO_SATMON = 69 IPPROTO_VISA = 70 IPPROTO_IPCV = 71 IPPROTO_CPNX = 72 IPPROTO_CPHB = 73 IPPROTO_WSN = 74 IPPROTO_PVP = 75 IPPROTO_BRSATMON = 76 IPPROTO_ND = 77 IPPROTO_WBMON = 78 IPPROTO_WBEXPAK = 79 IPPROTO_EON = 80 IPPROTO_VMTP = 81 IPPROTO_SVMTP = 82 IPPROTO_VINES = 83 IPPROTO_TTP = 84 IPPROTO_IGP = 85 IPPROTO_DGP = 86 IPPROTO_TCF = 87 IPPROTO_IGRP = 88 IPPROTO_OSPFIGP = 89 IPPROTO_SRPC = 90 IPPROTO_LARP = 91 IPPROTO_MTP = 92 IPPROTO_AX25 = 93 IPPROTO_IPEIP = 94 IPPROTO_MICP = 95 IPPROTO_SCCSP = 96 IPPROTO_ETHERIP = 97 IPPROTO_ENCAP = 98 IPPROTO_APES = 99 IPPROTO_GMTP = 100 IPPROTO_IPCOMP = 108 IPPROTO_PIM = 103 IPPROTO_CARP = 112 IPPROTO_PGM = 113 IPPROTO_PFSYNC = 240 IPPROTO_OLD_DIVERT = 254 IPPROTO_MAX = 256 IPPROTO_DONE = 257 IPPROTO_DIVERT = 258 IPPROTO_SPACER = 32767 IPPORT_RESERVED = 1024 IPPORT_HIFIRSTAUTO = 49152 IPPORT_HILASTAUTO = 65535 IPPORT_RESERVEDSTART = 600 IPPORT_MAX = 65535 def IN_CLASSA(i): return (((u_int32_t)(i) & (-2147483648)) == 0) IN_CLASSA_NET = (-16777216) IN_CLASSA_NSHIFT = 24 IN_CLASSA_HOST = 0x00ffffff IN_CLASSA_MAX = 128 def IN_CLASSB(i): return (((u_int32_t)(i) & (-1073741824)) == (-2147483648)) IN_CLASSB_NET = (-65536) IN_CLASSB_NSHIFT = 16 IN_CLASSB_HOST = 0x0000ffff IN_CLASSB_MAX = 65536 def IN_CLASSC(i): return (((u_int32_t)(i) & (-536870912)) == (-1073741824)) IN_CLASSC_NET = (-256) IN_CLASSC_NSHIFT = 8 IN_CLASSC_HOST = 0x000000ff def IN_CLASSD(i): return (((u_int32_t)(i) & (-268435456)) == (-536870912)) IN_CLASSD_NET = (-268435456) IN_CLASSD_NSHIFT = 28 IN_CLASSD_HOST = 0x0fffffff def IN_MULTICAST(i): return IN_CLASSD(i) def IN_EXPERIMENTAL(i): return (((u_int32_t)(i) & (-268435456)) == (-268435456)) def IN_BADCLASS(i): return (((u_int32_t)(i) & (-268435456)) == (-268435456)) INADDR_NONE = (-1) IN_LOOPBACKNET = 127 IP_OPTIONS = 1 IP_HDRINCL = 2 IP_TOS = 3 IP_TTL = 4 IP_RECVOPTS = 5 IP_RECVRETOPTS = 6 IP_RECVDSTADDR = 7 IP_SENDSRCADDR = IP_RECVDSTADDR IP_RETOPTS = 8 IP_MULTICAST_IF = 9 IP_MULTICAST_TTL = 10 IP_MULTICAST_LOOP = 11 IP_ADD_MEMBERSHIP = 12 IP_DROP_MEMBERSHIP = 13 IP_MULTICAST_VIF = 14 IP_RSVP_ON = 15 IP_RSVP_OFF = 16 IP_RSVP_VIF_ON = 17 IP_RSVP_VIF_OFF = 18 IP_PORTRANGE = 19 IP_RECVIF = 20 IP_IPSEC_POLICY = 21 IP_FAITH = 22 IP_ONESBCAST = 23 IP_FW_TABLE_ADD = 40 IP_FW_TABLE_DEL = 41 IP_FW_TABLE_FLUSH = 42 IP_FW_TABLE_GETSIZE = 43 IP_FW_TABLE_LIST = 44 IP_FW_ADD = 50 IP_FW_DEL = 51 IP_FW_FLUSH = 52 IP_FW_ZERO = 53 IP_FW_GET = 54 IP_FW_RESETLOG = 55 IP_DUMMYNET_CONFIGURE = 60 IP_DUMMYNET_DEL = 61 IP_DUMMYNET_FLUSH = 62 IP_DUMMYNET_GET = 64 IP_RECVTTL = 65 IP_DEFAULT_MULTICAST_TTL = 1 IP_DEFAULT_MULTICAST_LOOP = 1 IP_MAX_MEMBERSHIPS = 20 IP_PORTRANGE_DEFAULT = 0 IP_PORTRANGE_HIGH = 1 IP_PORTRANGE_LOW = 2 IPPROTO_MAXID = (IPPROTO_AH + 1) IPCTL_FORWARDING = 1 IPCTL_SENDREDIRECTS = 2 IPCTL_DEFTTL = 3 IPCTL_DEFMTU = 4 IPCTL_RTEXPIRE = 5 IPCTL_RTMINEXPIRE = 6 IPCTL_RTMAXCACHE = 7 IPCTL_SOURCEROUTE = 8 IPCTL_DIRECTEDBROADCAST = 9 IPCTL_INTRQMAXLEN = 10 IPCTL_INTRQDROPS = 11 IPCTL_STATS = 12 IPCTL_ACCEPTSOURCEROUTE = 13 IPCTL_FASTFORWARDING = 14 IPCTL_KEEPFAITH = 15 IPCTL_GIF_TTL = 16 IPCTL_MAXID = 17 def in_nullhost(x): return ((x).s_addr == INADDR_ANY) # Included from netinet6/in6.h __KAME_VERSION = "20010528/FreeBSD" IPV6PORT_RESERVED = 1024 IPV6PORT_ANONMIN = 49152 IPV6PORT_ANONMAX = 65535 IPV6PORT_RESERVEDMIN = 600 IPV6PORT_RESERVEDMAX = (IPV6PORT_RESERVED-1) INET6_ADDRSTRLEN = 46 IPV6_ADDR_INT32_ONE = 1 IPV6_ADDR_INT32_TWO = 2 IPV6_ADDR_INT32_MNL = (-16711680) IPV6_ADDR_INT32_MLL = (-16646144) IPV6_ADDR_INT32_SMP = 0x0000ffff IPV6_ADDR_INT16_ULL = 0xfe80 IPV6_ADDR_INT16_USL = 0xfec0 IPV6_ADDR_INT16_MLL = 0xff02 IPV6_ADDR_INT32_ONE = 0x01000000 IPV6_ADDR_INT32_TWO = 0x02000000 IPV6_ADDR_INT32_MNL = 0x000001ff IPV6_ADDR_INT32_MLL = 0x000002ff IPV6_ADDR_INT32_SMP = (-65536) IPV6_ADDR_INT16_ULL = 0x80fe IPV6_ADDR_INT16_USL = 0xc0fe IPV6_ADDR_INT16_MLL = 0x02ff def IN6_IS_ADDR_UNSPECIFIED(a): return \ def IN6_IS_ADDR_LOOPBACK(a): return \ def IN6_IS_ADDR_V4COMPAT(a): return \ def IN6_IS_ADDR_V4MAPPED(a): return \ IPV6_ADDR_SCOPE_NODELOCAL = 0x01 IPV6_ADDR_SCOPE_INTFACELOCAL = 0x01 IPV6_ADDR_SCOPE_LINKLOCAL = 0x02 IPV6_ADDR_SCOPE_SITELOCAL = 0x05 IPV6_ADDR_SCOPE_ORGLOCAL = 0x08 IPV6_ADDR_SCOPE_GLOBAL = 0x0e __IPV6_ADDR_SCOPE_NODELOCAL = 0x01 __IPV6_ADDR_SCOPE_INTFACELOCAL = 0x01 __IPV6_ADDR_SCOPE_LINKLOCAL = 0x02 __IPV6_ADDR_SCOPE_SITELOCAL = 0x05 __IPV6_ADDR_SCOPE_ORGLOCAL = 0x08 __IPV6_ADDR_SCOPE_GLOBAL = 0x0e def IN6_IS_ADDR_LINKLOCAL(a): return \ def IN6_IS_ADDR_SITELOCAL(a): return \ def IN6_IS_ADDR_MC_NODELOCAL(a): return \ def IN6_IS_ADDR_MC_INTFACELOCAL(a): return \ def IN6_IS_ADDR_MC_LINKLOCAL(a): return \ def IN6_IS_ADDR_MC_SITELOCAL(a): return \ def IN6_IS_ADDR_MC_ORGLOCAL(a): return \ def IN6_IS_ADDR_MC_GLOBAL(a): return \ def IN6_IS_ADDR_MC_NODELOCAL(a): return \ def IN6_IS_ADDR_MC_LINKLOCAL(a): return \ def IN6_IS_ADDR_MC_SITELOCAL(a): return \ def IN6_IS_ADDR_MC_ORGLOCAL(a): return \ def IN6_IS_ADDR_MC_GLOBAL(a): return \ def IN6_IS_SCOPE_LINKLOCAL(a): return \ def IFA6_IS_DEPRECATED(a): return \ def IFA6_IS_INVALID(a): return \ IPV6_OPTIONS = 1 IPV6_RECVOPTS = 5 IPV6_RECVRETOPTS = 6 IPV6_RECVDSTADDR = 7 IPV6_RETOPTS = 8 IPV6_SOCKOPT_RESERVED1 = 3 IPV6_UNICAST_HOPS = 4 IPV6_MULTICAST_IF = 9 IPV6_MULTICAST_HOPS = 10 IPV6_MULTICAST_LOOP = 11 IPV6_JOIN_GROUP = 12 IPV6_LEAVE_GROUP = 13 IPV6_PORTRANGE = 14 ICMP6_FILTER = 18 IPV6_2292PKTINFO = 19 IPV6_2292HOPLIMIT = 20 IPV6_2292NEXTHOP = 21 IPV6_2292HOPOPTS = 22 IPV6_2292DSTOPTS = 23 IPV6_2292RTHDR = 24 IPV6_2292PKTOPTIONS = 25 IPV6_CHECKSUM = 26 IPV6_V6ONLY = 27 IPV6_BINDV6ONLY = IPV6_V6ONLY IPV6_IPSEC_POLICY = 28 IPV6_FAITH = 29 IPV6_FW_ADD = 30 IPV6_FW_DEL = 31 IPV6_FW_FLUSH = 32 IPV6_FW_ZERO = 33 IPV6_FW_GET = 34 IPV6_RTHDRDSTOPTS = 35 IPV6_RECVPKTINFO = 36 IPV6_RECVHOPLIMIT = 37 IPV6_RECVRTHDR = 38 IPV6_RECVHOPOPTS = 39 IPV6_RECVDSTOPTS = 40 IPV6_RECVRTHDRDSTOPTS = 41 IPV6_USE_MIN_MTU = 42 IPV6_RECVPATHMTU = 43 IPV6_PATHMTU = 44 IPV6_REACHCONF = 45 IPV6_PKTINFO = 46 IPV6_HOPLIMIT = 47 IPV6_NEXTHOP = 48 IPV6_HOPOPTS = 49 IPV6_DSTOPTS = 50 IPV6_RTHDR = 51 IPV6_PKTOPTIONS = 52 IPV6_RECVTCLASS = 57 IPV6_AUTOFLOWLABEL = 59 IPV6_TCLASS = 61 IPV6_DONTFRAG = 62 IPV6_PREFER_TEMPADDR = 63 IPV6_RTHDR_LOOSE = 0 IPV6_RTHDR_STRICT = 1 IPV6_RTHDR_TYPE_0 = 0 IPV6_DEFAULT_MULTICAST_HOPS = 1 IPV6_DEFAULT_MULTICAST_LOOP = 1 IPV6_PORTRANGE_DEFAULT = 0 IPV6_PORTRANGE_HIGH = 1 IPV6_PORTRANGE_LOW = 2 IPV6PROTO_MAXID = (IPPROTO_PIM + 1) IPV6CTL_FORWARDING = 1 IPV6CTL_SENDREDIRECTS = 2 IPV6CTL_DEFHLIM = 3 IPV6CTL_DEFMTU = 4 IPV6CTL_FORWSRCRT = 5 IPV6CTL_STATS = 6 IPV6CTL_MRTSTATS = 7 IPV6CTL_MRTPROTO = 8 IPV6CTL_MAXFRAGPACKETS = 9 IPV6CTL_SOURCECHECK = 10 IPV6CTL_SOURCECHECK_LOGINT = 11 IPV6CTL_ACCEPT_RTADV = 12 IPV6CTL_KEEPFAITH = 13 IPV6CTL_LOG_INTERVAL = 14 IPV6CTL_HDRNESTLIMIT = 15 IPV6CTL_DAD_COUNT = 16 IPV6CTL_AUTO_FLOWLABEL = 17 IPV6CTL_DEFMCASTHLIM = 18 IPV6CTL_GIF_HLIM = 19 IPV6CTL_KAME_VERSION = 20 IPV6CTL_USE_DEPRECATED = 21 IPV6CTL_RR_PRUNE = 22 IPV6CTL_MAPPED_ADDR = 23 IPV6CTL_V6ONLY = 24 IPV6CTL_RTEXPIRE = 25 IPV6CTL_RTMINEXPIRE = 26 IPV6CTL_RTMAXCACHE = 27 IPV6CTL_USETEMPADDR = 32 IPV6CTL_TEMPPLTIME = 33 IPV6CTL_TEMPVLTIME = 34 IPV6CTL_AUTO_LINKLOCAL = 35 IPV6CTL_RIP6STATS = 36 IPV6CTL_PREFER_TEMPADDR = 37 IPV6CTL_ADDRCTLPOLICY = 38 IPV6CTL_MAXFRAGS = 41 IPV6CTL_MAXID = 42 --- NEW FILE: regen --- #! /bin/sh set -v python ../../Tools/scripts/h2py.py -i '(u_long)' /usr/include/netinet/in.h From perky at users.sourceforge.net Sun Jul 17 04:37:13 2005 From: perky at users.sourceforge.net (perky@users.sourceforge.net) Date: Sat, 16 Jul 2005 19:37:13 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1316,1.1317 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29720/Misc Modified Files: NEWS Log Message: Add support for FreeBSD 7. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1316 retrieving revision 1.1317 diff -u -d -r1.1316 -r1.1317 --- NEWS 15 Jul 2005 09:13:21 -0000 1.1316 +++ NEWS 17 Jul 2005 02:37:01 -0000 1.1317 @@ -432,6 +432,11 @@ --- +New platforms +------------- + +- FreeBSD 7 support is added. + Tools/Demos ----------- From perky at users.sourceforge.net Sun Jul 17 04:37:32 2005 From: perky at users.sourceforge.net (perky@users.sourceforge.net) Date: Sat, 16 Jul 2005 19:37:32 -0700 Subject: [Python-checkins] python/dist/src setup.py,1.218,1.219 Message-ID: Update of /cvsroot/python/python/dist/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29720 Modified Files: setup.py Log Message: Add support for FreeBSD 7. Index: setup.py =================================================================== RCS file: /cvsroot/python/python/dist/src/setup.py,v retrieving revision 1.218 retrieving revision 1.219 diff -u -d -r1.218 -r1.219 --- setup.py 25 Apr 2005 07:13:42 -0000 1.218 +++ setup.py 17 Jul 2005 02:37:00 -0000 1.219 @@ -821,7 +821,8 @@ # Linux-specific modules exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) ) - if platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6'): + if platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6', + 'freebsd7'): exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) ) if platform == 'sunos5': From perky at users.sourceforge.net Sun Jul 17 04:37:33 2005 From: perky at users.sourceforge.net (perky@users.sourceforge.net) Date: Sat, 16 Jul 2005 19:37:33 -0700 Subject: [Python-checkins] python/dist/src/Lib posixfile.py,1.28,1.29 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29720/Lib Modified Files: posixfile.py Log Message: Add support for FreeBSD 7. Index: posixfile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/posixfile.py,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- posixfile.py 6 Feb 2005 06:57:07 -0000 1.28 +++ posixfile.py 17 Jul 2005 02:37:00 -0000 1.29 @@ -179,7 +179,8 @@ if sys.platform in ('netbsd1', 'openbsd2', 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', - 'freebsd6', 'bsdos2', 'bsdos3', 'bsdos4'): + 'freebsd6', 'freebsd7', + 'bsdos2', 'bsdos3', 'bsdos4'): flock = struct.pack('lxxxxlxxxxlhh', \ l_start, l_len, os.getpid(), l_type, l_whence) elif sys.platform in ('aix3', 'aix4'): From perky at users.sourceforge.net Sun Jul 17 04:37:33 2005 From: perky at users.sourceforge.net (perky@users.sourceforge.net) Date: Sat, 16 Jul 2005 19:37:33 -0700 Subject: [Python-checkins] python/dist/src/Lib/test regrtest.py, 1.169, 1.170 test_fcntl.py, 1.27, 1.28 test_socket.py, 1.78, 1.79 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29720/Lib/test Modified Files: regrtest.py test_fcntl.py test_socket.py Log Message: Add support for FreeBSD 7. Index: regrtest.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/regrtest.py,v retrieving revision 1.169 retrieving revision 1.170 diff -u -d -r1.169 -r1.170 --- regrtest.py 14 Jun 2005 09:31:28 -0000 1.169 +++ regrtest.py 17 Jul 2005 02:37:00 -0000 1.170 @@ -1073,6 +1073,7 @@ } _expectations['freebsd5'] = _expectations['freebsd4'] _expectations['freebsd6'] = _expectations['freebsd4'] +_expectations['freebsd7'] = _expectations['freebsd4'] class _ExpectedSkips: def __init__(self): Index: test_fcntl.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_fcntl.py,v retrieving revision 1.27 retrieving revision 1.28 diff -u -d -r1.27 -r1.28 --- test_fcntl.py 4 Apr 2005 15:21:04 -0000 1.27 +++ test_fcntl.py 17 Jul 2005 02:37:00 -0000 1.28 @@ -22,6 +22,7 @@ if sys.platform in ('netbsd1', 'Darwin1.2', 'darwin', 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', 'freebsd6', + 'freebsd7', 'bsdos2', 'bsdos3', 'bsdos4', 'openbsd', 'openbsd2', 'openbsd3'): if struct.calcsize('l') == 8: Index: test_socket.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_socket.py,v retrieving revision 1.78 retrieving revision 1.79 diff -u -d -r1.78 -r1.79 --- test_socket.py 11 Mar 2005 00:04:17 -0000 1.78 +++ test_socket.py 17 Jul 2005 02:37:00 -0000 1.79 @@ -312,7 +312,7 @@ # I've ordered this by protocols that have both a tcp and udp # protocol, at least for modern Linuxes. if sys.platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6', - 'darwin'): + 'freebsd7', 'darwin'): # avoid the 'echo' service on this platform, as there is an # assumption breaking non-standard port/protocol entry services = ('daytime', 'qotd', 'domain') From pje at users.sourceforge.net Sun Jul 17 06:42:43 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 21:42:43 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools package_index.py, 1.11, 1.12 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16754/setuptools Modified Files: package_index.py Log Message: Renamings for consistent terminology; distributions and requirements now both have 'project_name' attributes, instead of one having 'name' and the other 'distname'. Requirements no longer have 'options', they have 'extras'. This is the beginning of the terminology/architecture refactoring described at: http://mail.python.org/pipermail/distutils-sig/2005-June/004652.html Index: package_index.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/package_index.py,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- package_index.py 12 Jul 2005 05:31:36 -0000 1.11 +++ package_index.py 17 Jul 2005 04:42:41 -0000 1.12 @@ -245,12 +245,12 @@ def find_packages(self, requirement): - self.scan_url(self.index_url + requirement.distname+'/') + self.scan_url(self.index_url + requirement.project_name+'/') if not self.package_pages.get(requirement.key): # We couldn't find the target package, so search the index page too self.warn( "Couldn't find index page for %r (maybe misspelled?)", - requirement.distname + requirement.project_name ) if self.index_url not in self.fetched_urls: self.warn( From pje at users.sourceforge.net Sun Jul 17 06:42:43 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 21:42:43 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.42, 1.43 setuptools.txt, 1.15, 1.16 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16754 Modified Files: pkg_resources.py setuptools.txt Log Message: Renamings for consistent terminology; distributions and requirements now both have 'project_name' attributes, instead of one having 'name' and the other 'distname'. Requirements no longer have 'options', they have 'extras'. This is the beginning of the terminology/architecture refactoring described at: http://mail.python.org/pipermail/distutils-sig/2005-June/004652.html Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.42 retrieving revision 1.43 diff -u -d -r1.42 -r1.43 --- pkg_resources.py 16 Jul 2005 17:25:35 -0000 1.42 +++ pkg_resources.py 17 Jul 2005 04:42:41 -0000 1.43 @@ -355,7 +355,7 @@ # Oops, the "best" so far conflicts with a dependency raise VersionConflict(dist,req) # XXX put more info here - requirements.extend(dist.depends(req.options)[::-1]) + requirements.extend(dist.depends(req.extras)[::-1]) processed[req] = True return to_install # return list of distros to install @@ -911,7 +911,7 @@ base_dir = os.path.dirname(egg_info) metadata = PathMetadata(base_dir, egg_info) dist_name = os.path.splitext(os.path.basename(egg_info))[0] - dist = Distribution(basedir,name=dist_name,metadata=metadata) + dist = Distribution(basedir,project_name=dist_name,metadata=metadata) # Unpacked egg directories: @@ -1094,7 +1094,7 @@ # development egg metadata = PathMetadata(path_item, fullpath) dist_name = os.path.splitext(entry)[0] - yield Distribution(path_item,metadata,name=dist_name) + yield Distribution(path_item,metadata,project_name=dist_name) elif lower.endswith('.egg-link'): for line in file(fullpath): if not line.strip(): continue @@ -1314,11 +1314,11 @@ """Wrap an actual or potential sys.path entry w/metadata""" def __init__(self, - path_str, metadata=None, name=None, version=None, + path_str, metadata=None, project_name=None, version=None, py_version=PY_MAJOR, platform=None, distro_type = EGG_DIST ): - if name: - self.name = safe_name(name) + if project_name: + self.project_name = safe_name(project_name) if version is not None: self._version = safe_version(version) self.py_version = py_version @@ -1340,11 +1340,11 @@ if ext.lower()==".egg": match = EGG_NAME(basename) if match: - name,version,py_version,platform = match.group( + project_name,version,py_version,platform = match.group( 'name','ver','pyver','plat' ) return cls( - filename, metadata, name=name, version=version, + filename, metadata, project_name=project_name, version=version, py_version=py_version, platform=platform ) from_filename = classmethod(from_filename) @@ -1360,7 +1360,7 @@ try: return self._key except AttributeError: - self._key = key = self.name.lower() + self._key = key = self.project_name.lower() return key key = property(key) @@ -1436,7 +1436,7 @@ def egg_name(self): """Return what this distribution's standard .egg filename should be""" filename = "%s-%s-py%s" % ( - self.name.replace('-','_'), self.version.replace('-','_'), + self.project_name.replace('-','_'), self.version.replace('-','_'), self.py_version or PY_MAJOR ) @@ -1450,7 +1450,7 @@ def __str__(self): version = getattr(self,'version',None) or "[unknown version]" - return "%s %s" % (self.name,version) + return "%s %s" % (self.project_name,version) @@ -1520,7 +1520,7 @@ match = DISTRO(line) if not match: raise ValueError("Missing distribution spec", line) - distname = match.group(1) + project_name = match.group(1) p = match.end() options = [] @@ -1531,7 +1531,7 @@ line, p, specs = scan_list(VERSION,LINE_END,line,p,(1,2),"version spec") specs = [(op,val.replace('_','-')) for op,val in specs] - yield Requirement(distname.replace('_','-'), specs, options) + yield Requirement(project_name.replace('_','-'), specs, options) def _sort_dists(dists): @@ -1558,25 +1558,25 @@ class Requirement: - def __init__(self, distname, specs=(), options=()): - self.distname = distname - self.key = distname.lower() + def __init__(self, project_name, specs=(), extras=()): + self.project_name = project_name + self.key = project_name.lower() index = [(parse_version(v),state_machine[op],op,v) for op,v in specs] index.sort() self.specs = [(op,ver) for parsed,trans,op,ver in index] - self.index, self.options = index, tuple(options) + self.index, self.extras = index, tuple(extras) self.hashCmp = ( self.key, tuple([(op,parsed) for parsed,trans,op,ver in index]), - ImmutableSet(map(str.lower,options)) + ImmutableSet(map(str.lower,extras)) ) self.__hash = hash(self.hashCmp) def __str__(self): - return self.distname + ','.join([''.join(s) for s in self.specs]) + return self.project_name + ','.join([''.join(s) for s in self.specs]) def __repr__(self): return "Requirement(%r, %r, %r)" % \ - (self.distname,self.specs,self.options) + (self.project_name,self.specs,self.extras) def __eq__(self,other): return isinstance(other,Requirement) and self.hashCmp==other.hashCmp Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- setuptools.txt 16 Jul 2005 17:25:35 -0000 1.15 +++ setuptools.txt 17 Jul 2005 04:42:41 -0000 1.16 @@ -701,7 +701,7 @@ different tagging and rotation policies, you may also want to check out the `alias`_ command, which would let each package define an alias like ``daily`` that would perform the necessary tag, build, and rotate commands. Then, a -simpler scriptor cron job could just run ``setup.py daily`` in each project +simpler script or cron job could just run ``setup.py daily`` in each project directory. (And, you could also define sitewide or per-user default versions of the ``daily`` alias, so that projects that didn't define their own would use the appropriate defaults.) From pje at users.sourceforge.net Sun Jul 17 06:42:44 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 21:42:44 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/tests test_resources.py, 1.13, 1.14 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16754/setuptools/tests Modified Files: test_resources.py Log Message: Renamings for consistent terminology; distributions and requirements now both have 'project_name' attributes, instead of one having 'name' and the other 'distname'. Requirements no longer have 'options', they have 'extras'. This is the beginning of the terminology/architecture refactoring described at: http://mail.python.org/pipermail/distutils-sig/2005-June/004652.html Index: test_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/test_resources.py,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- test_resources.py 5 Jun 2005 21:33:51 -0000 1.13 +++ test_resources.py 17 Jul 2005 04:42:42 -0000 1.14 @@ -73,7 +73,7 @@ self.assertEqual(ad.best_match(req,path).version, '1.4') def checkFooPkg(self,d): - self.assertEqual(d.name, "FooPkg") + self.assertEqual(d.project_name, "FooPkg") self.assertEqual(d.key, "foopkg") self.assertEqual(d.version, "1.3-1") self.assertEqual(d.py_version, "2.4") @@ -83,7 +83,7 @@ def testDistroBasics(self): d = Distribution( "/some/path", - name="FooPkg",version="1.3-1",py_version="2.4",platform="win32" + project_name="FooPkg",version="1.3-1",py_version="2.4",platform="win32" ) self.checkFooPkg(d) self.failUnless(d.installed_on(["/some/path"])) @@ -99,7 +99,7 @@ def testDistroMetadata(self): d = Distribution( - "/some/path", name="FooPkg", py_version="2.4", platform="win32", + "/some/path", project_name="FooPkg", py_version="2.4", platform="win32", metadata = Metadata( ('PKG-INFO',"Metadata-Version: 1.0\nVersion: 1.3-1\n") ) @@ -250,8 +250,8 @@ r3 = Requirement.parse("Twisted[BAR,FOO]>=1.2.0") self.assertEqual(r1,r2) self.assertEqual(r1,r3) - self.assertEqual(r1.options, ("foo","bar")) - self.assertEqual(r2.options, ("bar","FOO")) + self.assertEqual(r1.extras, ("foo","bar")) + self.assertEqual(r2.extras, ("bar","FOO")) self.assertEqual(hash(r1), hash(r2)) self.assertEqual( hash(r1), hash(("twisted", ((">=",parse_version("1.2")),), From pje at users.sourceforge.net Sun Jul 17 06:42:44 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 16 Jul 2005 21:42:44 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command develop.py, 1.3, 1.4 easy_install.py, 1.10, 1.11 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16754/setuptools/command Modified Files: develop.py easy_install.py Log Message: Renamings for consistent terminology; distributions and requirements now both have 'project_name' attributes, instead of one having 'name' and the other 'distname'. Requirements no longer have 'options', they have 'extras'. This is the beginning of the terminology/architecture refactoring described at: http://mail.python.org/pipermail/distutils-sig/2005-June/004652.html Index: develop.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/develop.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- develop.py 12 Jul 2005 16:09:00 -0000 1.3 +++ develop.py 17 Jul 2005 04:42:41 -0000 1.4 @@ -51,7 +51,7 @@ self.dist = Distribution( self.egg_path, PathMetadata(self.egg_path, os.path.abspath(ei.egg_info)), - name = ei.egg_name + project_name = ei.egg_name ) def install_for_development(self): Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- easy_install.py 16 Jul 2005 21:57:50 -0000 1.10 +++ easy_install.py 17 Jul 2005 04:42:41 -0000 1.11 @@ -350,7 +350,7 @@ self.install_egg_scripts(dist) log.warn(self.installation_report(dist, *info)) if requirement is None: - requirement = Requirement.parse('%s==%s'%(dist.name,dist.version)) + requirement = Requirement.parse('%s==%s'%(dist.project_name,dist.version)) if dist in requirement: log.info("Processing dependencies for %s", requirement) try: @@ -419,7 +419,7 @@ options = match.group(1) or '' if options: options = ' '+options - spec = '%s==%s' % (dist.name,dist.version) + spec = '%s==%s' % (dist.project_name,dist.version) executable = os.path.normpath(sys.executable) if dev_path: @@ -541,7 +541,7 @@ # Create a dummy distribution object until we build the real distro dist = Distribution(None, - name=cfg.get('metadata','name'), + project_name=cfg.get('metadata','name'), version=cfg.get('metadata','version'), platform="win32" ) @@ -678,7 +678,7 @@ (Note: you can run EasyInstall on '%s' with the --delete-conflicting option to attempt deletion of the above files and/or directories.) -""" % dist.name +""" % dist.project_name else: msg += """\ Note: you can attempt this installation again with EasyInstall, and use @@ -719,7 +719,7 @@ PYTHONPATH, or by being added to sys.path by your code.) """ eggloc = dist.path - name = dist.name + name = dist.project_name version = dist.version return msg % locals() @@ -802,7 +802,7 @@ self.pth_file.save() - if dist.name=='setuptools': + if dist.project_name=='setuptools': # Ensure that setuptools itself never becomes unavailable! # XXX should this check for latest version? f = open(os.path.join(self.install_dir,'setuptools.pth'), 'w') From montanaro at users.sourceforge.net Sun Jul 17 13:47:48 2005 From: montanaro at users.sourceforge.net (montanaro@users.sourceforge.net) Date: Sun, 17 Jul 2005 04:47:48 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib emailutil.tex,1.11,1.12 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20654 Modified Files: emailutil.tex Log Message: Note that usegmt is new in 2.4. Closes #1239681. Index: emailutil.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailutil.tex,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- emailutil.tex 1 Nov 2004 03:59:24 -0000 1.11 +++ emailutil.tex 17 Jul 2005 11:47:46 -0000 1.12 @@ -103,7 +103,8 @@ Optional \var{usegmt} is a flag that when \code{True}, outputs a date string with the timezone as an ascii string \code{GMT}, rather than a numeric \code{-0000}. This is needed for some protocols (such -as HTTP). This only applies when \var{localtime} is \code{False} +as HTTP). This only applies when \var{localtime} is \code{False}. +New in Python 2.4. \end{funcdesc} \begin{funcdesc}{make_msgid}{\optional{idstring}} From montanaro at users.sourceforge.net Sun Jul 17 13:49:09 2005 From: montanaro at users.sourceforge.net (montanaro@users.sourceforge.net) Date: Sun, 17 Jul 2005 04:49:09 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib emailutil.tex, 1.11, 1.11.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20765 Modified Files: Tag: release24-maint emailutil.tex Log Message: backport Index: emailutil.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailutil.tex,v retrieving revision 1.11 retrieving revision 1.11.2.1 diff -u -d -r1.11 -r1.11.2.1 --- emailutil.tex 1 Nov 2004 03:59:24 -0000 1.11 +++ emailutil.tex 17 Jul 2005 11:48:54 -0000 1.11.2.1 @@ -103,7 +103,8 @@ Optional \var{usegmt} is a flag that when \code{True}, outputs a date string with the timezone as an ascii string \code{GMT}, rather than a numeric \code{-0000}. This is needed for some protocols (such -as HTTP). This only applies when \var{localtime} is \code{False} +as HTTP). This only applies when \var{localtime} is \code{False}. +New in Python 2.4. \end{funcdesc} \begin{funcdesc}{make_msgid}{\optional{idstring}} From montanaro at users.sourceforge.net Sun Jul 17 17:35:00 2005 From: montanaro at users.sourceforge.net (montanaro@users.sourceforge.net) Date: Sun, 17 Jul 2005 08:35:00 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib emailutil.tex,1.12,1.13 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24118 Modified Files: emailutil.tex Log Message: use macro Index: emailutil.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailutil.tex,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- emailutil.tex 17 Jul 2005 11:47:46 -0000 1.12 +++ emailutil.tex 17 Jul 2005 15:34:58 -0000 1.13 @@ -104,7 +104,7 @@ date string with the timezone as an ascii string \code{GMT}, rather than a numeric \code{-0000}. This is needed for some protocols (such as HTTP). This only applies when \var{localtime} is \code{False}. -New in Python 2.4. +\versionadded{2.4} \end{funcdesc} \begin{funcdesc}{make_msgid}{\optional{idstring}} From montanaro at users.sourceforge.net Sun Jul 17 17:35:43 2005 From: montanaro at users.sourceforge.net (montanaro@users.sourceforge.net) Date: Sun, 17 Jul 2005 08:35:43 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib emailutil.tex, 1.11.2.1, 1.11.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24249 Modified Files: Tag: release24-maint emailutil.tex Log Message: use macro Index: emailutil.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/emailutil.tex,v retrieving revision 1.11.2.1 retrieving revision 1.11.2.2 diff -u -d -r1.11.2.1 -r1.11.2.2 --- emailutil.tex 17 Jul 2005 11:48:54 -0000 1.11.2.1 +++ emailutil.tex 17 Jul 2005 15:35:41 -0000 1.11.2.2 @@ -104,7 +104,7 @@ date string with the timezone as an ascii string \code{GMT}, rather than a numeric \code{-0000}. This is needed for some protocols (such as HTTP). This only applies when \var{localtime} is \code{False}. -New in Python 2.4. +\versionadded{2.4} \end{funcdesc} \begin{funcdesc}{make_msgid}{\optional{idstring}} From pje at users.sourceforge.net Sun Jul 17 21:01:18 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 12:01:18 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.11, 1.12 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30805/setuptools/command Modified Files: easy_install.py Log Message: ``Distribution`` objects now implement the ``IResourceProvider`` and ``IMetadataProvider`` interfaces, so you don't need to reference the (no longer available) ``metadata`` attribute to get at these interfaces. Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- easy_install.py 17 Jul 2005 04:42:41 -0000 1.11 +++ easy_install.py 17 Jul 2005 19:01:15 -0000 1.12 @@ -368,22 +368,21 @@ ) def install_egg_scripts(self, dist): - metadata = dist.metadata - if self.exclude_scripts or not metadata.metadata_isdir('scripts'): + if self.exclude_scripts or not dist.metadata_isdir('scripts'): return - for script_name in metadata.metadata_listdir('scripts'): + for script_name in dist.metadata_listdir('scripts'): self.install_script( dist, script_name, - metadata.get_metadata('scripts/'+script_name).replace('\r','\n') + dist.get_metadata('scripts/'+script_name).replace('\r','\n') ) def should_unzip(self, dist): if self.zip_ok is not None: return not self.zip_ok - if dist.metadata.has_metadata('not-zip-safe'): + if dist.has_metadata('not-zip-safe'): return True - if not dist.metadata.has_metadata('zip-safe'): + if not dist.has_metadata('zip-safe'): return True return False @@ -408,6 +407,7 @@ + def install_script(self, dist, script_name, script_text, dev_path=None): log.info("Installing %s script to %s", script_name,self.script_dir) target = os.path.join(self.script_dir, script_name) From pje at users.sourceforge.net Sun Jul 17 21:01:19 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 12:01:19 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.43, 1.44 setuptools.txt, 1.16, 1.17 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30805 Modified Files: pkg_resources.py setuptools.txt Log Message: ``Distribution`` objects now implement the ``IResourceProvider`` and ``IMetadataProvider`` interfaces, so you don't need to reference the (no longer available) ``metadata`` attribute to get at these interfaces. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.43 retrieving revision 1.44 diff -u -d -r1.43 -r1.44 --- pkg_resources.py 17 Jul 2005 04:42:41 -0000 1.43 +++ pkg_resources.py 17 Jul 2005 19:01:14 -0000 1.44 @@ -23,7 +23,7 @@ 'get_importer', 'find_distributions', 'find_on_path', 'register_finder', 'split_sections', 'declare_namespace', 'register_namespace_handler', 'safe_name', 'safe_version', 'run_main', 'BINARY_DIST', 'run_script', - 'get_default_cache', + 'get_default_cache', 'EmptyProvider', 'empty_provider', ] import sys, os, zipimport, time, re, imp @@ -108,7 +108,7 @@ name = ns['__name__'] ns.clear() ns['__name__'] = name - require(dist_spec)[0].metadata.run_script(script_name, ns) + require(dist_spec)[0].run_script(script_name, ns) run_main = run_script # backward compatibility @@ -714,18 +714,18 @@ register_loader_type(type(None), DefaultProvider) +class EmptyProvider(NullProvider): + """Provider that returns nothing for all requests""" + _isdir = _has = lambda self,path: False + _get = lambda self,path: '' + _listdir = lambda self,path: [] + module_path = None + def __init__(self): + pass - - - - - - - - - +empty_provider = EmptyProvider() @@ -1325,7 +1325,7 @@ self.platform = platform self.path = path_str self.distro_type = distro_type - self.metadata = metadata + self._provider = metadata or empty_provider def installed_on(self,path=None): """Is this distro installed on `path`? (defaults to ``sys.path``)""" @@ -1419,8 +1419,8 @@ return deps def _get_metadata(self,name): - if self.metadata is not None and self.metadata.has_metadata(name): - for line in self.metadata.get_metadata_lines(name): + if self.has_metadata(name): + for line in self.get_metadata_lines(name): yield line def install_on(self,path=None): @@ -1452,11 +1452,11 @@ version = getattr(self,'version',None) or "[unknown version]" return "%s %s" % (self.project_name,version) - - - - - + def __getattr__(self,attr): + """Delegate all unrecognized public attributes to .metadata provider""" + if attr.startswith('_'): + raise AttributeError,attr + return getattr(self._provider, attr) Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- setuptools.txt 17 Jul 2005 04:42:41 -0000 1.16 +++ setuptools.txt 17 Jul 2005 19:01:15 -0000 1.17 @@ -1342,6 +1342,16 @@ * Fixed ``pkg_resources.resource_exists()`` not working correctly. + * Many ``pkg_resources`` API changes: + + * ``Distribution`` objects now implement the ``IResourceProvider`` and + ``IMetadataProvider`` interfaces, so you don't need to reference the (no + longer available) ``metadata`` attribute to get at these interfaces. + + * ``Distribution`` and ``Requirement`` both have a ``project_name`` + attribute for the project name they refer to. (Previously these were + ``name`` and ``distname`` attributes.) + 0.5a13 * Fixed a bug in resource extraction from nested packages in a zipped egg. From pje at users.sourceforge.net Sun Jul 17 21:01:24 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 12:01:24 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/tests test_resources.py, 1.14, 1.15 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30805/setuptools/tests Modified Files: test_resources.py Log Message: ``Distribution`` objects now implement the ``IResourceProvider`` and ``IMetadataProvider`` interfaces, so you don't need to reference the (no longer available) ``metadata`` attribute to get at these interfaces. Index: test_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/test_resources.py,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- test_resources.py 17 Jul 2005 04:42:42 -0000 1.14 +++ test_resources.py 17 Jul 2005 19:01:15 -0000 1.15 @@ -3,7 +3,7 @@ import pkg_resources, sys from sets import ImmutableSet -class Metadata: +class Metadata(EmptyProvider): """Mock object to return metadata as if from an on-disk distribution""" def __init__(self,*pairs): From pje at users.sourceforge.net Sun Jul 17 21:54:41 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 12:54:41 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools package_index.py, 1.12, 1.13 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8964/setuptools Modified Files: package_index.py Log Message: The ``path`` attribute of ``Distribution`` objects is now ``location``, because it isn't necessarily a filesystem path (and hasn't been for some time now). ``Distribution`` objects now have an ``as_requirement()`` method that returns a ``Requirement`` for the distribution's project name and version. Index: package_index.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/package_index.py,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- package_index.py 17 Jul 2005 04:42:41 -0000 1.12 +++ package_index.py 17 Jul 2005 19:54:38 -0000 1.13 @@ -52,10 +52,8 @@ if basename.endswith('.egg.zip'): basename = basename[:-4] # strip the .zip - if basename.endswith('.egg'): - dist = Distribution.from_filename(basename, metadata) - dist.path = url_or_path - return [dist] # only one, unambiguous interpretation + if basename.endswith('.egg'): # only one, unambiguous interpretation + return [Distribution.from_location(url_or_path, basename, metadata)] if basename.endswith('.exe'): win_base, py_ver = parse_bdist_wininst(basename) @@ -80,6 +78,8 @@ + + def interpret_distro_name(url_or_path, basename, metadata, py_version=None, distro_type=SOURCE_DIST, platform=None ): From pje at users.sourceforge.net Sun Jul 17 21:54:40 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 12:54:40 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.44, 1.45 setuptools.txt, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8964 Modified Files: pkg_resources.py setuptools.txt Log Message: The ``path`` attribute of ``Distribution`` objects is now ``location``, because it isn't necessarily a filesystem path (and hasn't been for some time now). ``Distribution`` objects now have an ``as_requirement()`` method that returns a ``Requirement`` for the distribution's project name and version. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.44 retrieving revision 1.45 diff -u -d -r1.44 -r1.45 --- pkg_resources.py 17 Jul 2005 19:01:14 -0000 1.44 +++ pkg_resources.py 17 Jul 2005 19:54:37 -0000 1.45 @@ -311,7 +311,7 @@ path = sys.path distros = self.get(requirement.key, ()) - find = dict([(dist.path,dist) for dist in distros]).get + find = dict([(dist.location,dist) for dist in distros]).get for item in path: dist = find(item) @@ -1314,16 +1314,15 @@ """Wrap an actual or potential sys.path entry w/metadata""" def __init__(self, - path_str, metadata=None, project_name=None, version=None, + location, metadata=None, project_name=None, version=None, py_version=PY_MAJOR, platform=None, distro_type = EGG_DIST ): - if project_name: - self.project_name = safe_name(project_name) + self.project_name = safe_name(project_name or 'Unknown') if version is not None: self._version = safe_version(version) self.py_version = py_version self.platform = platform - self.path = path_str + self.location = location self.distro_type = distro_type self._provider = metadata or empty_provider @@ -1331,23 +1330,24 @@ """Is this distro installed on `path`? (defaults to ``sys.path``)""" if path is None: path = sys.path - return self.path in path + return self.location in path #@classmethod - def from_filename(cls,filename,metadata=None): - name,version,py_version,platform = [None]*4 - basename,ext = os.path.splitext(os.path.basename(filename)) + def from_location(cls,location,basename,metadata=None): + project_name, version, py_version, platform = [None]*4 + basename, ext = os.path.splitext(basename) if ext.lower()==".egg": match = EGG_NAME(basename) if match: - project_name,version,py_version,platform = match.group( + project_name, version, py_version, platform = match.group( 'name','ver','pyver','plat' ) return cls( - filename, metadata, project_name=project_name, version=version, + location, metadata, project_name=project_name, version=version, py_version=py_version, platform=platform ) - from_filename = classmethod(from_filename) + from_location = classmethod(from_location) + @@ -1405,17 +1405,18 @@ _dep_map = property(_dep_map) - def depends(self,options=()): + def depends(self,extras=()): """List of Requirements needed for this distro if `options` are used""" dm = self._dep_map deps = [] deps.extend(dm.get(None,())) - - for opt in options: + for ext in extras: try: - deps.extend(dm[opt.lower()]) + deps.extend(dm[ext.lower()]) except KeyError: - raise InvalidOption("No such option", self, opt) + raise InvalidOption( + "%s has no such extra feature %r" % (self, ext) + ) return deps def _get_metadata(self,name): @@ -1426,13 +1427,12 @@ def install_on(self,path=None): """Ensure distribution is importable on `path` (default=sys.path)""" if path is None: path = sys.path - if self.path not in path: - path.append(self.path) + if self.location not in path: + path.append(self.location) if path is sys.path: - fixup_namespace_packages(self.path) + fixup_namespace_packages(self.location) map(declare_namespace, self._get_metadata('namespace_packages.txt')) - def egg_name(self): """Return what this distribution's standard .egg filename should be""" filename = "%s-%s-py%s" % ( @@ -1446,7 +1446,7 @@ return filename def __repr__(self): - return "%s (%s)" % (self,self.path) + return "%s (%s)" % (self,self.location) def __str__(self): version = getattr(self,'version',None) or "[unknown version]" @@ -1458,10 +1458,13 @@ raise AttributeError,attr return getattr(self._provider, attr) + #@classmethod + def from_filename(cls,filename,metadata=None): + return cls.from_location(filename, os.path.basename(filename), metadata) + from_filename = classmethod(from_filename) - - - + def as_requirement(self): + return Requirement.parse('%s==%s' % (dist.project_name, dist.version)) Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- setuptools.txt 17 Jul 2005 19:01:15 -0000 1.17 +++ setuptools.txt 17 Jul 2005 19:54:38 -0000 1.18 @@ -1352,6 +1352,13 @@ attribute for the project name they refer to. (Previously these were ``name`` and ``distname`` attributes.) + * The ``path`` attribute of ``Distribution`` objects is now ``location``, + because it isn't necessarily a filesystem path (and hasn't been for some + time now). + + * ``Distribution`` objects now have an ``as_requirement()`` method that + returns a ``Requirement`` for the distribution's project name and version. + 0.5a13 * Fixed a bug in resource extraction from nested packages in a zipped egg. From pje at users.sourceforge.net Sun Jul 17 21:54:41 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 12:54:41 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.12, 1.13 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8964/setuptools/command Modified Files: easy_install.py Log Message: The ``path`` attribute of ``Distribution`` objects is now ``location``, because it isn't necessarily a filesystem path (and hasn't been for some time now). ``Distribution`` objects now have an ``as_requirement()`` method that returns a ``Requirement`` for the distribution's project name and version. Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- easy_install.py 17 Jul 2005 19:01:15 -0000 1.12 +++ easy_install.py 17 Jul 2005 19:54:38 -0000 1.13 @@ -1,6 +1,5 @@ #!python """\ - Easy Install ------------ @@ -17,7 +16,8 @@ from setuptools.sandbox import run_setup from distutils import log, dir_util from distutils.sysconfig import get_python_lib -from distutils.errors import DistutilsArgError, DistutilsOptionError, DistutilsError +from distutils.errors import DistutilsArgError, DistutilsOptionError, \ + DistutilsError from setuptools.archive_util import unpack_archive from setuptools.package_index import PackageIndex, parse_bdist_wininst from setuptools.package_index import URL_SCHEME @@ -350,7 +350,7 @@ self.install_egg_scripts(dist) log.warn(self.installation_report(dist, *info)) if requirement is None: - requirement = Requirement.parse('%s==%s'%(dist.project_name,dist.version)) + requirement = dist.as_requirement() if dist in requirement: log.info("Processing dependencies for %s", requirement) try: @@ -419,7 +419,7 @@ options = match.group(1) or '' if options: options = ' '+options - spec = '%s==%s' % (dist.project_name,dist.version) + spec = dist.as_requirement() executable = os.path.normpath(sys.executable) if dev_path: @@ -547,7 +547,7 @@ ) # Convert the .exe to an unpacked egg - egg_path = dist.path = os.path.join(tmpdir, dist.egg_name()+'.egg') + egg_path = dist.location = os.path.join(tmpdir, dist.egg_name()+'.egg') egg_tmp = egg_path+'.tmp' pkg_inf = os.path.join(egg_tmp, 'EGG-INFO', 'PKG-INFO') ensure_directory(pkg_inf) # make sure EGG-INFO dir exists @@ -718,7 +718,7 @@ this to work. (e.g. by being the application's script directory, by being on PYTHONPATH, or by being added to sys.path by your code.) """ - eggloc = dist.path + eggloc = dist.location name = dist.project_name version = dist.version return msg % locals() @@ -782,14 +782,14 @@ return for d in self.pth_file.get(dist.key,()): # drop old entries - if self.multi_version or normalize(d.path) != normalize(dist.path): + if self.multi_version or normalize(d.location) != normalize(dist.location): log.info("Removing %s from easy-install.pth file", d) self.pth_file.remove(d) - if normalize(d.path) in self.shadow_path: - self.shadow_path.remove(d.path) + if normalize(d.location) in self.shadow_path: + self.shadow_path.remove(d.location) if not self.multi_version: - if normalize(dist.path) in map(normalize,self.pth_file.paths): + if normalize(dist.location) in map(normalize,self.pth_file.paths): log.info( "%s is already the active version in easy-install.pth", dist @@ -797,8 +797,8 @@ else: log.info("Adding %s to easy-install.pth file", dist) self.pth_file.add(dist) # add new entry - if normalize(dist.path) not in self.shadow_path: - self.shadow_path.append(normalize(dist.path)) + if normalize(dist.location) not in self.shadow_path: + self.shadow_path.append(normalize(dist.location)) self.pth_file.save() @@ -806,7 +806,7 @@ # Ensure that setuptools itself never becomes unavailable! # XXX should this check for latest version? f = open(os.path.join(self.install_dir,'setuptools.pth'), 'w') - f.write(dist.path+'\n') + f.write(dist.location+'\n') f.close() @@ -1051,14 +1051,14 @@ def add(self,dist): """Add `dist` to the distribution map""" - if dist.path not in self.paths: - self.paths.append(dist.path); self.dirty = True + if dist.location not in self.paths: + self.paths.append(dist.location); self.dirty = True AvailableDistributions.add(self,dist) def remove(self,dist): """Remove `dist` from the distribution map""" - while dist.path in self.paths: - self.paths.remove(dist.path); self.dirty = True + while dist.location in self.paths: + self.paths.remove(dist.location); self.dirty = True AvailableDistributions.remove(self,dist) From birkenfeld at users.sourceforge.net Sun Jul 17 22:05:29 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 13:05:29 -0700 Subject: [Python-checkins] python/dist/src/Doc/api utilities.tex,1.21,1.22 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12022/Doc/api Modified Files: utilities.tex Log Message: bug [ 1061920 ] "k" specifier in PyArg_ParseTuple incomplete documentated Index: utilities.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/utilities.tex,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- utilities.tex 13 Feb 2005 22:50:02 -0000 1.21 +++ utilities.tex 17 Jul 2005 20:05:25 -0000 1.22 @@ -539,7 +539,7 @@ Convert a Python integer to a C \ctype{long int}. \item[\samp{k} (integer) {[unsigned long]}] - Convert a Python integer to a C \ctype{unsigned long} without + Convert a Python integer or long integer to a C \ctype{unsigned long} without overflow checking. \versionadded{2.3} \item[\samp{L} (integer) {[PY_LONG_LONG]}] @@ -548,7 +548,7 @@ \ctype{_int64} on Windows). \item[\samp{K} (integer) {[unsigned PY_LONG_LONG]}] - Convert a Python integer to a C \ctype{unsigned long long} + Convert a Python integer or long integer to a C \ctype{unsigned long long} without overflow checking. This format is only available on platforms that support \ctype{unsigned long long} (or \ctype{unsigned _int64} on Windows). \versionadded{2.3} From birkenfeld at users.sourceforge.net Sun Jul 17 22:05:30 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 13:05:30 -0700 Subject: [Python-checkins] python/dist/src/Doc/api utilities.tex, 1.20.2.1, 1.20.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/api In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12097/Doc/api Modified Files: Tag: release24-maint utilities.tex Log Message: backport bug [ 1061920 ] "k" specifier in PyArg_ParseTuple incomplete documentated Index: utilities.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/utilities.tex,v retrieving revision 1.20.2.1 retrieving revision 1.20.2.2 diff -u -d -r1.20.2.1 -r1.20.2.2 --- utilities.tex 13 Feb 2005 22:56:35 -0000 1.20.2.1 +++ utilities.tex 17 Jul 2005 20:05:26 -0000 1.20.2.2 @@ -539,7 +539,7 @@ Convert a Python integer to a C \ctype{long int}. \item[\samp{k} (integer) {[unsigned long]}] - Convert a Python integer to a C \ctype{unsigned long} without + Convert a Python integer or long integer to a C \ctype{unsigned long} without overflow checking. \versionadded{2.3} \item[\samp{L} (integer) {[PY_LONG_LONG]}] @@ -548,7 +548,7 @@ \ctype{_int64} on Windows). \item[\samp{K} (integer) {[unsigned PY_LONG_LONG]}] - Convert a Python integer to a C \ctype{unsigned long long} + Convert a Python integer or long integer to a C \ctype{unsigned long long} without overflow checking. This format is only available on platforms that support \ctype{unsigned long long} (or \ctype{unsigned _int64} on Windows). \versionadded{2.3} From birkenfeld at users.sourceforge.net Sun Jul 17 22:26:52 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 13:26:52 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS, 1.1193.2.61, 1.1193.2.62 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15834/Misc Modified Files: Tag: release24-maint NEWS Log Message: backport Bug #1015140: disambiguated the term "article id" in nntplib docs and docstrings to either "article number" or "message id". Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.61 retrieving revision 1.1193.2.62 diff -u -d -r1.1193.2.61 -r1.1193.2.62 --- NEWS 11 Jul 2005 05:57:10 -0000 1.1193.2.61 +++ NEWS 17 Jul 2005 20:26:33 -0000 1.1193.2.62 @@ -51,6 +51,9 @@ Library ------- +- Bug #1015140: disambiguated the term "article id" in nntplib docs and + docstrings to either "article number" or "message id". + - Bug #1177468: Don't cache the /dev/urandom file descriptor for os.urandom, as this can cause problems with apps closing all file descriptors. From birkenfeld at users.sourceforge.net Sun Jul 17 22:27:05 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 13:27:05 -0700 Subject: [Python-checkins] python/dist/src/Lib nntplib.py,1.39,1.39.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15834/Lib Modified Files: Tag: release24-maint nntplib.py Log Message: backport Bug #1015140: disambiguated the term "article id" in nntplib docs and docstrings to either "article number" or "message id". Index: nntplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/nntplib.py,v retrieving revision 1.39 retrieving revision 1.39.2.1 diff -u -d -r1.39 -r1.39.2.1 --- nntplib.py 3 Aug 2004 14:36:32 -0000 1.39 +++ nntplib.py 17 Jul 2005 20:26:33 -0000 1.39.2.1 @@ -281,7 +281,7 @@ - time: string 'hhmmss' indicating the time Return: - resp: server response if successful - - list: list of article ids""" + - list: list of message ids""" cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time return self.longcmd(cmd, file) @@ -391,7 +391,7 @@ Returns: - resp: server response if successful - nr: the article number - - id: the article id""" + - id: the message id""" return self.statcmd('STAT ' + id) From birkenfeld at users.sourceforge.net Sun Jul 17 22:27:06 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 13:27:06 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libnntplib.tex, 1.32, 1.32.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15834/Doc/lib Modified Files: Tag: release24-maint libnntplib.tex Log Message: backport Bug #1015140: disambiguated the term "article id" in nntplib docs and docstrings to either "article number" or "message id". Index: libnntplib.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libnntplib.tex,v retrieving revision 1.32 retrieving revision 1.32.2.1 diff -u -d -r1.32 -r1.32.2.1 --- libnntplib.tex 3 Aug 2004 14:36:32 -0000 1.32 +++ libnntplib.tex 17 Jul 2005 20:26:33 -0000 1.32.2.1 @@ -156,7 +156,7 @@ Send a \samp{NEWNEWS} command. Here, \var{group} is a group name or \code{'*'}, and \var{date} and \var{time} have the same meaning as for \method{newgroups()}. Return a pair \code{(\var{response}, -\var{articles})} where \var{articles} is a list of article ids. +\var{articles})} where \var{articles} is a list of message ids. If the \var{file} parameter is supplied, then the output of the \samp{NEWNEWS} command is stored in a file. If \var{file} is a string, then the method will open a file object with that name, write to it @@ -228,7 +228,7 @@ in \character{<} and \character{>}) or an article number (as a string). Return a triple \code{(\var{response}, \var{number}, \var{id})} where \var{number} is the article number (as a string) and \var{id} is the -article id (enclosed in \character{<} and \character{>}). +message id (enclosed in \character{<} and \character{>}). \end{methoddesc} \begin{methoddesc}{next}{} @@ -275,7 +275,7 @@ the form \code{'\var{first}-\var{last}'} where \var{first} and \var{last} are the first and last article numbers to search. Return a pair \code{(\var{response}, \var{list})}, where \var{list} is a list of -pairs \code{(\var{id}, \var{text})}, where \var{id} is an article id +pairs \code{(\var{id}, \var{text})}, where \var{id} is an article number (as a string) and \var{text} is the text of the requested header for that article. If the \var{file} parameter is supplied, then the output of the @@ -295,7 +295,9 @@ \end{methoddesc} \begin{methoddesc}{ihave}{id, file} -Send an \samp{IHAVE} command. If the response is not an error, treat +Send an \samp{IHAVE} command. \var{id} is a message id (enclosed in +\character{<} and \character{>}). +If the response is not an error, treat \var{file} exactly as for the \method{post()} method. \end{methoddesc} From birkenfeld at users.sourceforge.net Sun Jul 17 22:27:43 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 13:27:43 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1317,1.1318 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16057/Misc Modified Files: NEWS Log Message: - Bug #1015140: disambiguated the term "article id" in nntplib docs and docstrings to either "article number" or "message id". Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1317 retrieving revision 1.1318 diff -u -d -r1.1317 -r1.1318 --- NEWS 17 Jul 2005 02:37:01 -0000 1.1317 +++ NEWS 17 Jul 2005 20:27:40 -0000 1.1318 @@ -168,6 +168,9 @@ Library ------- +- Bug #1015140: disambiguated the term "article id" in nntplib docs and + docstrings to either "article number" or "message id". + - Bug #1238170: threading.Thread.__init__ no longer has "kwargs={}" as a parameter, but uses the usual "kwargs=None". From birkenfeld at users.sourceforge.net Sun Jul 17 22:27:43 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 13:27:43 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libnntplib.tex, 1.32, 1.33 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16057/Doc/lib Modified Files: libnntplib.tex Log Message: - Bug #1015140: disambiguated the term "article id" in nntplib docs and docstrings to either "article number" or "message id". Index: libnntplib.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libnntplib.tex,v retrieving revision 1.32 retrieving revision 1.33 diff -u -d -r1.32 -r1.33 --- libnntplib.tex 3 Aug 2004 14:36:32 -0000 1.32 +++ libnntplib.tex 17 Jul 2005 20:27:41 -0000 1.33 @@ -156,7 +156,7 @@ Send a \samp{NEWNEWS} command. Here, \var{group} is a group name or \code{'*'}, and \var{date} and \var{time} have the same meaning as for \method{newgroups()}. Return a pair \code{(\var{response}, -\var{articles})} where \var{articles} is a list of article ids. +\var{articles})} where \var{articles} is a list of message ids. If the \var{file} parameter is supplied, then the output of the \samp{NEWNEWS} command is stored in a file. If \var{file} is a string, then the method will open a file object with that name, write to it @@ -228,7 +228,7 @@ in \character{<} and \character{>}) or an article number (as a string). Return a triple \code{(\var{response}, \var{number}, \var{id})} where \var{number} is the article number (as a string) and \var{id} is the -article id (enclosed in \character{<} and \character{>}). +message id (enclosed in \character{<} and \character{>}). \end{methoddesc} \begin{methoddesc}{next}{} @@ -275,7 +275,7 @@ the form \code{'\var{first}-\var{last}'} where \var{first} and \var{last} are the first and last article numbers to search. Return a pair \code{(\var{response}, \var{list})}, where \var{list} is a list of -pairs \code{(\var{id}, \var{text})}, where \var{id} is an article id +pairs \code{(\var{id}, \var{text})}, where \var{id} is an article number (as a string) and \var{text} is the text of the requested header for that article. If the \var{file} parameter is supplied, then the output of the @@ -295,7 +295,9 @@ \end{methoddesc} \begin{methoddesc}{ihave}{id, file} -Send an \samp{IHAVE} command. If the response is not an error, treat +Send an \samp{IHAVE} command. \var{id} is a message id (enclosed in +\character{<} and \character{>}). +If the response is not an error, treat \var{file} exactly as for the \method{post()} method. \end{methoddesc} From birkenfeld at users.sourceforge.net Sun Jul 17 22:27:43 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 13:27:43 -0700 Subject: [Python-checkins] python/dist/src/Lib nntplib.py,1.39,1.40 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16057/Lib Modified Files: nntplib.py Log Message: - Bug #1015140: disambiguated the term "article id" in nntplib docs and docstrings to either "article number" or "message id". Index: nntplib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/nntplib.py,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- nntplib.py 3 Aug 2004 14:36:32 -0000 1.39 +++ nntplib.py 17 Jul 2005 20:27:40 -0000 1.40 @@ -281,7 +281,7 @@ - time: string 'hhmmss' indicating the time Return: - resp: server response if successful - - list: list of article ids""" + - list: list of message ids""" cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time return self.longcmd(cmd, file) @@ -391,7 +391,7 @@ Returns: - resp: server response if successful - nr: the article number - - id: the article id""" + - id: the message id""" return self.statcmd('STAT ' + id) From birkenfeld at users.sourceforge.net Sun Jul 17 23:00:28 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 14:00:28 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libthreading.tex, 1.21, 1.22 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22244/Doc/lib Modified Files: libthreading.tex Log Message: [ 912943 ] 7.5.6 Thread Objects is too vague Index: libthreading.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libthreading.tex,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- libthreading.tex 2 Jun 2005 16:59:18 -0000 1.21 +++ libthreading.tex 17 Jul 2005 21:00:26 -0000 1.22 @@ -594,7 +594,12 @@ When the \var{timeout} argument is present and not \code{None}, it should be a floating point number specifying a timeout for the -operation in seconds (or fractions thereof). +operation in seconds (or fractions thereof). As \method{join()} always +returns \code{None}, you must call \method{isAlive()} to decide whether +a timeout happened. + +When the \var{timeout} argument is not present or \code{None}, the +operation will block until the thread terminates. A thread can be \method{join()}ed many times. From birkenfeld at users.sourceforge.net Sun Jul 17 23:00:34 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 14:00:34 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libthreading.tex, 1.20.4.1, 1.20.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22261/Doc/lib Modified Files: Tag: release24-maint libthreading.tex Log Message: backport [ 912943 ] 7.5.6 Thread Objects is too vague Index: libthreading.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libthreading.tex,v retrieving revision 1.20.4.1 retrieving revision 1.20.4.2 diff -u -d -r1.20.4.1 -r1.20.4.2 --- libthreading.tex 2 Jun 2005 17:01:08 -0000 1.20.4.1 +++ libthreading.tex 17 Jul 2005 21:00:31 -0000 1.20.4.2 @@ -594,7 +594,12 @@ When the \var{timeout} argument is present and not \code{None}, it should be a floating point number specifying a timeout for the -operation in seconds (or fractions thereof). +operation in seconds (or fractions thereof). As \method{join()} always +returns \code{None}, you must call \method{isAlive()} to decide whether +a timeout happened. + +When the \var{timeout} argument is not present or \code{None}, the +operation will block until the thread terminates. A thread can be \method{join()}ed many times. From birkenfeld at users.sourceforge.net Sun Jul 17 23:10:29 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 14:10:29 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libos.tex,1.162,1.163 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24332/Doc/lib Modified Files: libos.tex Log Message: bug [ 872769 ] os.access() documentation should stress race conditions Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.162 retrieving revision 1.163 diff -u -d -r1.162 -r1.163 --- libos.tex 27 Jun 2005 23:23:43 -0000 1.162 +++ libos.tex 17 Jul 2005 21:10:11 -0000 1.163 @@ -680,6 +680,11 @@ \constant{False} if not. See the \UNIX{} man page \manpage{access}{2} for more information. Availability: Macintosh, \UNIX, Windows. + +\note{Using \function{access()} to check if a user is authorized to e.g. +open a file before actually doing so using \function{open()} creates a +security hole, because the user might exploit the short time interval +between checking and opening the file to manipulate it.} \end{funcdesc} \begin{datadesc}{F_OK} From birkenfeld at users.sourceforge.net Sun Jul 17 23:10:29 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 14:10:29 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libos.tex, 1.146.2.8, 1.146.2.9 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24349/Doc/lib Modified Files: Tag: release24-maint libos.tex Log Message: bug [ 872769 ] os.access() documentation should stress race conditions Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.146.2.8 retrieving revision 1.146.2.9 diff -u -d -r1.146.2.8 -r1.146.2.9 --- libos.tex 27 Jun 2005 23:22:22 -0000 1.146.2.8 +++ libos.tex 17 Jul 2005 21:10:07 -0000 1.146.2.9 @@ -667,6 +667,11 @@ \constant{False} if not. See the \UNIX{} man page \manpage{access}{2} for more information. Availability: Macintosh, \UNIX, Windows. + +\note{Using \function{access()} to check if a user is authorized to e.g. +open a file before actually doing so using \function{open()} creates a +security hole, because the user might exploit the short time interval +between checking and opening the file to manipulate it.} \end{funcdesc} \begin{datadesc}{F_OK} From birkenfeld at users.sourceforge.net Sun Jul 17 23:18:27 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 14:18:27 -0700 Subject: [Python-checkins] python/dist/src/Doc/ext noddy2.c,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26151 Modified Files: noddy2.c Log Message: bug [ 1021621 ] use first_name, not first, in code samples Index: noddy2.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/noddy2.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- noddy2.c 14 Jul 2004 19:07:24 -0000 1.5 +++ noddy2.c 17 Jul 2005 21:18:25 -0000 1.6 @@ -3,8 +3,8 @@ typedef struct { PyObject_HEAD - PyObject *first; - PyObject *last; + PyObject *first; /* first name */ + PyObject *last; /* last name */ int number; } Noddy; From birkenfeld at users.sourceforge.net Sun Jul 17 23:19:56 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 17 Jul 2005 14:19:56 -0700 Subject: [Python-checkins] python/dist/src/Doc/ext noddy2.c,1.5,1.5.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ext In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26374/Doc/ext Modified Files: Tag: release24-maint noddy2.c Log Message: backport bug [ 1021621 ] use first_name, not first, in code samples Index: noddy2.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ext/noddy2.c,v retrieving revision 1.5 retrieving revision 1.5.4.1 diff -u -d -r1.5 -r1.5.4.1 --- noddy2.c 14 Jul 2004 19:07:24 -0000 1.5 +++ noddy2.c 17 Jul 2005 21:19:44 -0000 1.5.4.1 @@ -3,8 +3,8 @@ typedef struct { PyObject_HEAD - PyObject *first; - PyObject *last; + PyObject *first; /* first name */ + PyObject *last; /* last name */ int number; } Noddy; From tim_one at users.sourceforge.net Mon Jul 18 01:16:20 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 17 Jul 2005 16:16:20 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_enumerate.py, 1.15, 1.16 test_urllib2.py, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15365/Lib/test Modified Files: test_enumerate.py test_urllib2.py Log Message: Whitespace normalization. Index: test_enumerate.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_enumerate.py,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- test_enumerate.py 12 Jul 2005 10:21:19 -0000 1.15 +++ test_enumerate.py 17 Jul 2005 23:16:18 -0000 1.16 @@ -193,7 +193,7 @@ else: self.fail("non-callable __reversed__ didn't raise!") self.assertEqual(rc, sys.getrefcount(r)) - + def test_main(verbose=None): testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig, Index: test_urllib2.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_urllib2.py,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- test_urllib2.py 14 Jul 2005 06:40:47 -0000 1.20 +++ test_urllib2.py 17 Jul 2005 23:16:18 -0000 1.21 @@ -40,7 +40,7 @@ buf = f.read() f.close() - + def test_statudict(self): # test the new-in-2.5 httpresponses dictionary self.assertEquals(urllib2.httpresponses[404], "Not Found") From tim_one at users.sourceforge.net Mon Jul 18 01:16:20 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 17 Jul 2005 16:16:20 -0700 Subject: [Python-checkins] python/dist/src/Lib/plat-freebsd7 IN.py,1.1,1.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/plat-freebsd7 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15365/Lib/plat-freebsd7 Modified Files: IN.py Log Message: Whitespace normalization. Index: IN.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/plat-freebsd7/IN.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- IN.py 17 Jul 2005 02:37:00 -0000 1.1 +++ IN.py 17 Jul 2005 23:16:18 -0000 1.2 @@ -23,13 +23,13 @@ __CC_SUPPORTS_VARADIC_XXX = 1 __CC_SUPPORTS_DYNAMIC_ARRAY_INIT = 1 __CC_INT_IS_32BIT = 1 -def __P(protos): return protos +def __P(protos): return protos -def __STRING(x): return #x +def __STRING(x): return #x -def __XSTRING(x): return __STRING(x) +def __XSTRING(x): return __STRING(x) -def __P(protos): return () +def __P(protos): return () def __STRING(x): return "x" From tim_one at users.sourceforge.net Mon Jul 18 01:16:20 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 17 Jul 2005 16:16:20 -0700 Subject: [Python-checkins] python/dist/src/Tools/bgen/bgen scantools.py, 1.42, 1.43 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/bgen/bgen In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15365/Tools/bgen/bgen Modified Files: scantools.py Log Message: Whitespace normalization. Index: scantools.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/bgen/bgen/scantools.py,v retrieving revision 1.42 retrieving revision 1.43 diff -u -d -r1.42 -r1.43 --- scantools.py 17 Jul 2005 00:15:46 -0000 1.42 +++ scantools.py 17 Jul 2005 23:16:18 -0000 1.43 @@ -374,7 +374,7 @@ tmp = self.scanmine and self.scanfile self.scanfile = None if tmp: tmp.close() - + def closehtml(self): if self.htmlfile: self.htmlfile.write(ENDHTMLREPORT) tmp = self.htmlmine and self.htmlfile @@ -415,7 +415,7 @@ self.htmlfile = file self.htmlmine = mine self.htmlfile.write(BEGINHTMLREPORT) - + def openoutput(self, filename): try: file = open(filename, 'w') @@ -728,10 +728,10 @@ classname, listname = self.destination(tp, name, arglist, modifiers) else: classname, listname = self.destination(tp, name, arglist) - if not classname or not listname: + if not classname or not listname: self.htmlreport("*** no output generated: self.destination() returned None", klass="blacklisted") return - if not self.specfile: + if not self.specfile: self.htmlreport("*** no output generated: no output file specified", klass="blacklisted") return self.specfile.write("f = %s(%s, %r,\n" % (classname, tp, name)) @@ -800,7 +800,7 @@ if not line or line[-1] != '\n': oline += '\n' self.htmlfile.write(oline) - + class Scanner_PreUH3(Scanner): """Scanner for Universal Headers before release 3""" def initpatterns(self): From tim_one at users.sourceforge.net Mon Jul 18 01:16:20 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 17 Jul 2005 16:16:20 -0700 Subject: [Python-checkins] python/dist/src/Lib urllib2.py,1.83,1.84 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15365/Lib Modified Files: urllib2.py Log Message: Whitespace normalization. Index: urllib2.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/urllib2.py,v retrieving revision 1.83 retrieving revision 1.84 diff -u -d -r1.83 -r1.84 --- urllib2.py 14 Jul 2005 06:40:46 -0000 1.83 +++ urllib2.py 17 Jul 2005 23:16:17 -0000 1.84 @@ -1298,7 +1298,7 @@ httpresponses = { 100: 'Continue', 101: 'Switching Protocols', - + 200: 'OK', 201: 'Created', 202: 'Accepted', @@ -1306,7 +1306,7 @@ 204: 'No Content', 205: 'Reset Content', 206: 'Partial Content', - + 300: 'Multiple Choices', 301: 'Moved Permanently', 302: 'Found', @@ -1315,7 +1315,7 @@ 305: 'Use Proxy', 306: '(Unused)', 307: 'Temporary Redirect', - + 400: 'Bad Request', 401: 'Unauthorized', 402: 'Payment Required', @@ -1334,7 +1334,7 @@ 415: 'Unsupported Media Type', 416: 'Requested Range Not Satisfiable', 417: 'Expectation Failed', - + 500: 'Internal Server Error', 501: 'Not Implemented', 502: 'Bad Gateway', From tim_one at users.sourceforge.net Mon Jul 18 01:16:20 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 17 Jul 2005 16:16:20 -0700 Subject: [Python-checkins] python/dist/src/Mac/Modules/file filesupport.py, 1.22, 1.23 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Modules/file In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15365/Mac/Modules/file Modified Files: filesupport.py Log Message: Whitespace normalization. Index: filesupport.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Modules/file/filesupport.py,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- filesupport.py 12 Jul 2005 21:25:05 -0000 1.22 +++ filesupport.py 17 Jul 2005 23:16:18 -0000 1.23 @@ -205,44 +205,44 @@ static OSErr _PyMac_GetFullPathname(FSSpec *fss, char *path, int len) { - FSRef fsr; - OSErr err; + FSRef fsr; + OSErr err; - *path = '\0'; - err = FSpMakeFSRef(fss, &fsr); - if (err == fnfErr) { - /* FSSpecs can point to non-existing files, fsrefs can't. */ - FSSpec fss2; - int tocopy; + *path = '\0'; + err = FSpMakeFSRef(fss, &fsr); + if (err == fnfErr) { + /* FSSpecs can point to non-existing files, fsrefs can't. */ + FSSpec fss2; + int tocopy; - err = FSMakeFSSpec(fss->vRefNum, fss->parID, "", &fss2); - if (err) - return err; - err = FSpMakeFSRef(&fss2, &fsr); - if (err) - return err; - err = (OSErr)FSRefMakePath(&fsr, path, len-1); - if (err) - return err; - /* This part is not 100% safe: we append the filename part, but - ** I'm not sure that we don't run afoul of the various 8bit - ** encodings here. Will have to look this up at some point... - */ - strcat(path, "/"); - tocopy = fss->name[0]; - if ((strlen(path) + tocopy) >= len) - tocopy = len - strlen(path) - 1; - if (tocopy > 0) - strncat(path, fss->name+1, tocopy); - } - else { - if (err) - return err; - err = (OSErr)FSRefMakePath(&fsr, path, len); - if (err) - return err; - } - return 0; + err = FSMakeFSSpec(fss->vRefNum, fss->parID, "", &fss2); + if (err) + return err; + err = FSpMakeFSRef(&fss2, &fsr); + if (err) + return err; + err = (OSErr)FSRefMakePath(&fsr, path, len-1); + if (err) + return err; + /* This part is not 100% safe: we append the filename part, but + ** I'm not sure that we don't run afoul of the various 8bit + ** encodings here. Will have to look this up at some point... + */ + strcat(path, "/"); + tocopy = fss->name[0]; + if ((strlen(path) + tocopy) >= len) + tocopy = len - strlen(path) - 1; + if (tocopy > 0) + strncat(path, fss->name+1, tocopy); + } + else { + if (err) + return err; + err = (OSErr)FSRefMakePath(&fsr, path, len); + if (err) + return err; + } + return 0; } """ From tim_one at users.sourceforge.net Mon Jul 18 01:45:27 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 17 Jul 2005 16:45:27 -0700 Subject: [Python-checkins] python/dist/src/Objects longobject.c, 1.168, 1.169 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20172/Objects Modified Files: longobject.c Log Message: SF bug #1238681: freed pointer is used in longobject.c:long_pow(). In addition, long_pow() skipped a necessary (albeit extremely unlikely to trigger) error check when converting an int modulus to long. Alas, I was unable to write a test case that crashed due to either cause. Bugfix candidate. Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.168 retrieving revision 1.169 diff -u -d -r1.168 -r1.169 --- longobject.c 29 Jun 2005 23:29:55 -0000 1.168 +++ longobject.c 17 Jul 2005 23:45:23 -0000 1.169 @@ -2360,8 +2360,11 @@ c = (PyLongObject *)x; Py_INCREF(x); } - else if (PyInt_Check(x)) + else if (PyInt_Check(x)) { c = (PyLongObject *)PyLong_FromLong(PyInt_AS_LONG(x)); + if (c == NULL) + goto Error; + } else if (x == Py_None) c = NULL; else { @@ -2511,14 +2514,14 @@ } /* fall through */ Done: - Py_XDECREF(a); - Py_XDECREF(b); - Py_XDECREF(c); - Py_XDECREF(temp); if (b->ob_size > FIVEARY_CUTOFF) { for (i = 0; i < 32; ++i) Py_XDECREF(table[i]); } + Py_DECREF(a); + Py_DECREF(b); + Py_XDECREF(c); + Py_XDECREF(temp); return (PyObject *)z; } From tim_one at users.sourceforge.net Mon Jul 18 01:45:27 2005 From: tim_one at users.sourceforge.net (tim_one@users.sourceforge.net) Date: Sun, 17 Jul 2005 16:45:27 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1318,1.1319 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20172/Misc Modified Files: NEWS Log Message: SF bug #1238681: freed pointer is used in longobject.c:long_pow(). In addition, long_pow() skipped a necessary (albeit extremely unlikely to trigger) error check when converting an int modulus to long. Alas, I was unable to write a test case that crashed due to either cause. Bugfix candidate. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1318 retrieving revision 1.1319 diff -u -d -r1.1318 -r1.1319 --- NEWS 17 Jul 2005 20:27:40 -0000 1.1318 +++ NEWS 17 Jul 2005 23:45:21 -0000 1.1319 @@ -12,6 +12,8 @@ Core and builtins ----------------- +- SF bug #1238681: freed pointer is used in longobject.c:long_pow(). + - SF bug #1229429: PyObject_CallMethod failed to decrement some reference counts in some error exit cases. From pje at users.sourceforge.net Mon Jul 18 03:39:48 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 18:39:48 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/tests doctest.py, NONE, 1.1 __init__.py, 1.7, 1.8 test_resources.py, 1.15, 1.16 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6719/setuptools/tests Modified Files: __init__.py test_resources.py Added Files: doctest.py Log Message: Massive API refactoring; see setuptools.txt changelog for details. Also, add ``#egg=project-version`` link support, and docs on how to make your package available for EasyInstall to find. --- NEW FILE: doctest.py --- # Module doctest. # Released to the public domain 16-Jan-2001, by Tim Peters (tim at python.org). # Major enhancements and refactoring by: # Jim Fulton # Edward Loper # Provided as-is; use at your own risk; no warranty; no promises; enjoy! try: basestring except NameError: basestring = str,unicode try: enumerate except NameError: def enumerate(seq): return zip(range(len(seq)),seq) [...2638 lines suppressed...] [0, 1, 2, ..., 999] """, "whitespace normalization": r""" If the whitespace normalization flag is used, then differences in whitespace are ignored. >>> print range(30) #doctest: +NORMALIZE_WHITESPACE [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] """, } def _test(): r = unittest.TextTestRunner() r.run(DocTestSuite()) if __name__ == "__main__": _test() Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/__init__.py,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- __init__.py 6 Jul 2005 01:54:08 -0000 1.7 +++ __init__.py 18 Jul 2005 01:39:45 -0000 1.8 @@ -408,8 +408,15 @@ +def test_api(): + import doctest + return doctest.DocFileSuite( + 'api_tests.txt', optionflags=doctest.ELLIPSIS, package='pkg_resources', + ) + + testClasses = (DependsTests, DistroTests, FeatureTests, TestCommandTests) -testNames = ["setuptools.tests.test_resources"] +testNames = ["setuptools.tests.test_resources", "setuptools.tests.test_api"] def test_suite(): return TestSuite( @@ -442,10 +449,3 @@ - - - - - - - Index: test_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/test_resources.py,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- test_resources.py 17 Jul 2005 19:01:15 -0000 1.15 +++ test_resources.py 18 Jul 2005 01:39:45 -0000 1.16 @@ -54,23 +54,23 @@ [dist.version for dist in ad['FooPkg']], ['1.9','1.4','1.2'] ) - path = [] + ws = WorkingSet([]) + foo12 = Distribution.from_filename("FooPkg-1.2-py2.4.egg") + foo14 = Distribution.from_filename("FooPkg-1.4-py2.4-win32.egg") req, = parse_requirements("FooPkg>=1.3") # Nominal case: no distros on path, should yield all applicable - self.assertEqual(ad.best_match(req,path).version, '1.9') - + self.assertEqual(ad.best_match(req,ws).version, '1.9') # If a matching distro is already installed, should return only that - path.append("FooPkg-1.4-py2.4-win32.egg") - self.assertEqual(ad.best_match(req,path).version, '1.4') + ws.add(foo14); self.assertEqual(ad.best_match(req,ws).version, '1.4') # If the first matching distro is unsuitable, it's a version conflict - path.insert(0,"FooPkg-1.2-py2.4.egg") - self.assertRaises(VersionConflict, ad.best_match, req, path) + ws = WorkingSet([]); ws.add(foo12); ws.add(foo14) + self.assertRaises(VersionConflict, ad.best_match, req, ws) # If more than one match on the path, the first one takes precedence - path.insert(0,"FooPkg-1.4-py2.4-win32.egg") - self.assertEqual(ad.best_match(req,path).version, '1.4') + ws = WorkingSet([]); ws.add(foo14); ws.add(foo12); ws.add(foo14); + self.assertEqual(ad.best_match(req,ws).version, '1.4') def checkFooPkg(self,d): self.assertEqual(d.project_name, "FooPkg") @@ -86,8 +86,6 @@ project_name="FooPkg",version="1.3-1",py_version="2.4",platform="win32" ) self.checkFooPkg(d) - self.failUnless(d.installed_on(["/some/path"])) - self.failIf(d.installed_on([])) d = Distribution("/some/path") self.assertEqual(d.py_version, sys.version[:3]) @@ -121,15 +119,17 @@ self.checkDepends(self.distDepends(v), v) + + def testResolve(self): - ad = AvailableDistributions([]) + ad = AvailableDistributions([]); ws = WorkingSet([]) # Resolving no requirements -> nothing to install - self.assertEqual( list(ad.resolve([],[])), [] ) + self.assertEqual( list(ws.resolve([],ad)), [] ) # Request something not in the collection -> DistributionNotFound self.assertRaises( - DistributionNotFound, ad.resolve, parse_requirements("Foo"), [] + DistributionNotFound, ws.resolve, parse_requirements("Foo"), ad ) Foo = Distribution.from_filename( @@ -138,28 +138,28 @@ ) ad.add(Foo) - # Request thing(s) that are available -> list to install + # Request thing(s) that are available -> list to activate self.assertEqual( - list(ad.resolve(parse_requirements("Foo"),[])), [Foo] + list(ws.resolve(parse_requirements("Foo"), ad)), [Foo] ) - # Request an option that causes an unresolved dependency for "Baz" + # Request an extra that causes an unresolved dependency for "Baz" self.assertRaises( - DistributionNotFound, ad.resolve,parse_requirements("Foo[bar]"),[] + DistributionNotFound, ws.resolve,parse_requirements("Foo[bar]"), ad ) Baz = Distribution.from_filename( "/foo_dir/Baz-2.1.egg", metadata=Metadata(('depends.txt', "Foo")) ) ad.add(Baz) - # Install list now includes resolved dependency + # Activation list now includes resolved dependency self.assertEqual( - list(ad.resolve(parse_requirements("Foo[bar]"),[])), [Foo,Baz] + list(ws.resolve(parse_requirements("Foo[bar]"), ad)), [Foo,Baz] ) # Requests for conflicting versions produce VersionConflict self.assertRaises( VersionConflict, - ad.resolve, parse_requirements("Foo==1.2\nFoo!=1.2"), [] + ws.resolve, parse_requirements("Foo==1.2\nFoo!=1.2"), ad ) def testDistroDependsOptions(self): @@ -208,7 +208,7 @@ def testBasics(self): r = Requirement.parse("Twisted>=1.2") self.assertEqual(str(r),"Twisted>=1.2") - self.assertEqual(repr(r),"Requirement('Twisted', [('>=', '1.2')], ())") + self.assertEqual(repr(r),"Requirement.parse('Twisted>=1.2')") self.assertEqual(r, Requirement("Twisted", [('>=','1.2')])) self.assertEqual(r, Requirement("twisTed", [('>=','1.2')])) self.assertNotEqual(r, Requirement("Twisted", [('>=','2.0')])) @@ -285,13 +285,6 @@ - - - - - - - class ParseTests(TestCase): def testEmptyParse(self): From pje at users.sourceforge.net Mon Jul 18 03:39:47 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 18:39:47 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools package_index.py, 1.13, 1.14 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6719/setuptools Modified Files: package_index.py Log Message: Massive API refactoring; see setuptools.txt changelog for details. Also, add ``#egg=project-version`` link support, and docs on how to make your package available for EasyInstall to find. Index: package_index.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/package_index.py,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- package_index.py 17 Jul 2005 19:54:38 -0000 1.13 +++ package_index.py 18 Jul 2005 01:39:45 -0000 1.14 @@ -5,7 +5,8 @@ from distutils import log from distutils.errors import DistutilsError -HREF = re.compile(r"""href\s*=\s*['"]?([^'"> ]+)""", re.I) +EGG_FRAGMENT = re.compile('^egg=(\\w+(-\\w+)?)$') +HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I) URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):',re.I).match EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz".split() @@ -38,28 +39,34 @@ - def distros_for_url(url, metadata=None): """Yield egg or source distribution objects that might be found at a URL""" - path = urlparse.urlparse(url)[2] + scheme, server, path, parameters, query, fragment = urlparse.urlparse(url) base = urllib2.unquote(path.split('/')[-1]) - return distros_for_filename(url, base, metadata) + dists = distros_for_location(url, base, metadata) + if fragment and not dists: + match = EGG_FRAGMENT.match(fragment) + if match: + return interpret_distro_name( + url, match.group(1), metadata, precedence = CHECKOUT_DIST + ) + return dists -def distros_for_filename(url_or_path, basename, metadata=None): +def distros_for_location(location, basename, metadata=None): """Yield egg or source distribution objects based on basename""" if basename.endswith('.egg.zip'): basename = basename[:-4] # strip the .zip if basename.endswith('.egg'): # only one, unambiguous interpretation - return [Distribution.from_location(url_or_path, basename, metadata)] + return [Distribution.from_location(location, basename, metadata)] if basename.endswith('.exe'): win_base, py_ver = parse_bdist_wininst(basename) if win_base is not None: return interpret_distro_name( - url_or_path, win_base, metadata, py_ver, BINARY_DIST, "win32" + location, win_base, metadata, py_ver, BINARY_DIST, "win32" ) # Try source distro extensions (.zip, .tgz, etc.) @@ -67,22 +74,28 @@ for ext in EXTENSIONS: if basename.endswith(ext): basename = basename[:-len(ext)] - return interpret_distro_name(url_or_path, basename, metadata) + return interpret_distro_name(location, basename, metadata) return [] # no extension matched +def distros_for_filename(filename, metadata=None): + """Yield possible egg or source distribution objects based on a filename""" + return distros_for_location( + normalize_path(filename), os.path.basename(filename), metadata + ) - - - - - -def interpret_distro_name(url_or_path, basename, metadata, - py_version=None, distro_type=SOURCE_DIST, platform=None +def interpret_distro_name(location, basename, metadata, + py_version=None, precedence=SOURCE_DIST, platform=None ): + """Generate alternative interpretations of a source distro name + + Note: if `location` is a filesystem filename, you should call + ``pkg_resources.normalize_path()`` on it before passing it to this + routine! + """ # Generate alternative interpretations of a source distro name # Because some packages are ambiguous as to name/versions split @@ -99,8 +112,8 @@ parts = basename.split('-') for p in range(1,len(parts)+1): yield Distribution( - url_or_path, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), - py_version=py_version, distro_type = distro_type, + location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), + py_version=py_version, precedence = precedence, platform = platform ) @@ -108,19 +121,6 @@ - - - - - - - - - - - - - class PackageIndex(AvailableDistributions): """A distribution index that scans web pages for download URLs""" @@ -142,11 +142,7 @@ if not URL_SCHEME(url): # process filenames or directories if os.path.isfile(url): - dists = list( - distros_for_filename( - os.path.realpath(url), os.path.basename(url) - ) - ) + dists = list(distros_for_filename(url)) elif os.path.isdir(url): url = os.path.realpath(url) for item in os.listdir(url): @@ -160,8 +156,6 @@ if dists: self.debug("Found link: %s", url) - - if dists or not retrieve or url in self.fetched_urls: for dist in dists: self.add(dist) @@ -203,6 +197,12 @@ + + + + + + def process_index(self,url,page): """Process the contents of a PyPI page""" @@ -344,11 +344,11 @@ if force_scan: self.find_packages(requirement) - dist = self.best_match(requirement, []) # XXX + dist = self.best_match(requirement, WorkingSet([])) # XXX if dist is not None: self.info("Best match: %s", dist) - return self.download(dist.path, tmpdir) + return self.download(dist.location, tmpdir) self.warn( "No local packages or download links found for %s", requirement @@ -475,8 +475,8 @@ file.close() raise DistutilsError("Unexpected HTML page found at "+url) - def _download_svn(self, url, filename): + url = url.split('#',1)[0] # remove any fragment for svn's sake self.info("Doing subversion checkout from %s to %s", url, filename) os.system("svn checkout -q %s %s" % (url, filename)) return filename From pje at users.sourceforge.net Mon Jul 18 03:39:47 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 18:39:47 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command develop.py, 1.4, 1.5 easy_install.py, 1.13, 1.14 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6719/setuptools/command Modified Files: develop.py easy_install.py Log Message: Massive API refactoring; see setuptools.txt changelog for details. Also, add ``#egg=project-version`` link support, and docs on how to make your package available for EasyInstall to find. Index: develop.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/develop.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- develop.py 17 Jul 2005 04:42:41 -0000 1.4 +++ develop.py 18 Jul 2005 01:39:45 -0000 1.5 @@ -1,6 +1,6 @@ from setuptools.command.easy_install import easy_install from distutils.util import convert_path -from pkg_resources import Distribution, PathMetadata +from pkg_resources import Distribution, PathMetadata, normalize_path from distutils import log import sys, os @@ -49,7 +49,7 @@ # Make a distribution for the package's source self.dist = Distribution( - self.egg_path, + normalize_path(self.egg_path), PathMetadata(self.egg_path, os.path.abspath(ei.egg_info)), project_name = ei.egg_name ) Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- easy_install.py 17 Jul 2005 19:54:38 -0000 1.13 +++ easy_install.py 18 Jul 2005 01:39:45 -0000 1.14 @@ -139,7 +139,7 @@ ) # default --record from the install command self.set_undefined_options('install', ('record', 'record')) - normpath = map(normalize,sys.path) + normpath = map(normalize_path, sys.path) self.all_site_dirs = get_site_dirs() if self.site_dirs is not None: site_dirs = [ @@ -148,15 +148,15 @@ for d in site_dirs: if not os.path.isdir(d): log.warn("%s (in --site-dirs) does not exist", d) - elif normalize(d) not in normpath: + elif normalize_path(d) not in normpath: raise DistutilsOptionError( d+" (in --site-dirs) is not on sys.path" ) else: - self.all_site_dirs.append(normalize(d)) + self.all_site_dirs.append(normalize_path(d)) - instdir = self.install_dir or self.all_site_dirs[-1] - if normalize(instdir) in self.all_site_dirs: + instdir = normalize_path(self.install_dir or self.all_site_dirs[-1]) + if instdir in self.all_site_dirs: if self.pth_file is None: self.pth_file = PthDistributions( os.path.join(instdir,'easy-install.pth') @@ -171,12 +171,12 @@ "Can't do single-version installs outside 'site-package' dirs" ) - self.install_dir = normalize(instdir) + self.install_dir = instdir self.index_url = self.index_url or "http://www.python.org/pypi" - self.shadow_path = map(normalize,sys.path) - for path_item in self.install_dir, self.script_dir: - if normalize(path_item) not in self.shadow_path: - self.shadow_path.insert(0, normalize(path_item)) + self.shadow_path = self.all_site_dirs[:] + for path_item in self.install_dir, normalize_path(self.script_dir): + if path_item not in self.shadow_path: + self.shadow_path.insert(0, path_item) if self.package_index is None: self.package_index = self.create_index( self.index_url, search_path = self.shadow_path @@ -354,8 +354,8 @@ if dist in requirement: log.info("Processing dependencies for %s", requirement) try: - self.local_index.resolve( - [requirement], self.shadow_path, self.easy_install + WorkingSet(self.shadow_path).resolve( + [requirement], self.local_index, self.easy_install ) except DistributionNotFound, e: raise DistutilsError( @@ -711,7 +711,7 @@ pkg_resources.require("%(name)s==%(version)s") # this exact version pkg_resources.require("%(name)s>=%(version)s") # this version or higher """ - if self.install_dir not in map(normalize,sys.path): + if self.install_dir not in map(normalize_path,sys.path): msg += """ Note also that the installation directory must be on sys.path at runtime for @@ -782,14 +782,14 @@ return for d in self.pth_file.get(dist.key,()): # drop old entries - if self.multi_version or normalize(d.location) != normalize(dist.location): + if self.multi_version or d.location != dist.location: log.info("Removing %s from easy-install.pth file", d) self.pth_file.remove(d) - if normalize(d.location) in self.shadow_path: + if d.location in self.shadow_path: self.shadow_path.remove(d.location) if not self.multi_version: - if normalize(dist.location) in map(normalize,self.pth_file.paths): + if dist.location in map(normalize_path,self.pth_file.paths): log.info( "%s is already the active version in easy-install.pth", dist @@ -797,8 +797,8 @@ else: log.info("Adding %s to easy-install.pth file", dist) self.pth_file.add(dist) # add new entry - if normalize(dist.location) not in self.shadow_path: - self.shadow_path.append(normalize(dist.location)) + if dist.location not in self.shadow_path: + self.shadow_path.append(dist.location) self.pth_file.save() @@ -894,8 +894,8 @@ 'site-packages')) sitedirs = filter(os.path.isdir, sitedirs) - sitedirs = map(normalize, sitedirs) - return sitedirs or [normalize(get_python_lib())] # ensure at least one + sitedirs = map(normalize_path, sitedirs) + return sitedirs or [normalize_path(get_python_lib())] # ensure at least one @@ -906,7 +906,7 @@ seen = {} for dirname in inputs: - dirname = normalize(dirname) + dirname = normalize_path(dirname) if dirname in seen: continue @@ -933,7 +933,7 @@ # Yield existing non-dupe, non-import directory lines from it for line in lines: if not line.startswith("import"): - line = normalize(line.rstrip()) + line = normalize_path(line.rstrip()) if line not in seen: seen[line] = 1 if not os.path.isdir(line): @@ -1027,7 +1027,6 @@ """A .pth file with Distribution paths in it""" dirty = False - def __init__(self, filename): self.filename = filename; self._load() AvailableDistributions.__init__( @@ -1039,14 +1038,17 @@ if os.path.isfile(self.filename): self.paths = [line.rstrip() for line in open(self.filename,'rt')] while self.paths and not self.paths[-1].strip(): self.paths.pop() - + # delete non-existent paths, in case somebody deleted a package + # manually: + for line in list(yield_lines(self.paths)): + if not os.path.exists(line): + self.paths.remove(line); self.dirty = True + def save(self): """Write changed .pth file back to disk""" if self.dirty: data = '\n'.join(self.paths+['']) - f = open(self.filename,'wt') - f.write(data) - f.close() + f = open(self.filename,'wt'); f.write(data); f.close() self.dirty = False def add(self,dist): @@ -1062,15 +1064,13 @@ AvailableDistributions.remove(self,dist) - - def main(argv, **kw): from setuptools import setup setup(script_args = ['-q','easy_install', '-v']+argv, **kw) -def normalize(path): - return os.path.normcase(os.path.realpath(path)) + + From pje at users.sourceforge.net Mon Jul 18 03:39:47 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 18:39:47 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools api_tests.txt, NONE, 1.1 EasyInstall.txt, 1.43, 1.44 pkg_resources.py, 1.45, 1.46 setuptools.txt, 1.18, 1.19 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6719 Modified Files: EasyInstall.txt pkg_resources.py setuptools.txt Added Files: api_tests.txt Log Message: Massive API refactoring; see setuptools.txt changelog for details. Also, add ``#egg=project-version`` link support, and docs on how to make your package available for EasyInstall to find. --- NEW FILE: api_tests.txt --- Pluggable Distributions of Python Software ========================================== Distributions ------------- A "Distribution" is a collection of files that represent a "Release" of a "Project" as of a particular point in time, denoted by a "Version":: >>> import sys, pkg_resources >>> from pkg_resources import Distribution >>> Distribution(project_name="Foo", version="1.2") Foo 1.2 Distributions have a location, which can be a filename, URL, or really anything else you care to use:: >>> dist = Distribution( ... location="http://example.com/something", ... project_name="Bar", version="0.9" ... ) >>> dist Bar 0.9 (http://example.com/something) Distributions have various introspectable attributes:: >>> dist.location 'http://example.com/something' >>> dist.project_name 'Bar' >>> dist.version '0.9' >>> dist.py_version == sys.version[:3] True >>> print dist.platform None Including various computed attributes:: >>> from pkg_resources import parse_version >>> dist.parsed_version == parse_version(dist.version) True >>> dist.key # case-insensitive form of the project name 'bar' Distributions are compared (and hashed) by version first:: >>> Distribution(version='1.0') == Distribution(version='1.0') True >>> Distribution(version='1.0') == Distribution(version='1.1') False >>> Distribution(version='1.0') < Distribution(version='1.1') True but also by project name (case-insensitive), platform, Python version, location, etc.:: >>> Distribution(project_name="Foo",version="1.0") == \ ... Distribution(project_name="Foo",version="1.0") True >>> Distribution(project_name="Foo",version="1.0") == \ ... Distribution(project_name="foo",version="1.0") True >>> Distribution(project_name="Foo",version="1.0") == \ ... Distribution(project_name="Foo",version="1.1") False >>> Distribution(project_name="Foo",py_version="2.3",version="1.0") == \ ... Distribution(project_name="Foo",py_version="2.4",version="1.0") False >>> Distribution(location="spam",version="1.0") == \ ... Distribution(location="spam",version="1.0") True >>> Distribution(location="spam",version="1.0") == \ ... Distribution(location="baz",version="1.0") False Hash and compare distribution by prio/plat Get version from metadata provider capabilities egg_name() as_requirement() from_location, from_filename (w/path normalization) Releases may have zero or more "Requirements", which indicate what releases of another project the release requires in order to function. A Requirement names the other project, expresses some criteria as to what releases of that project are acceptable, and lists any "Extras" that the requiring release may need from that project. (An Extra is an optional feature of a Release, that can only be used if its additional Requirements are satisfied.) The Working Set --------------- A collection of active distributions is called a Working Set. Note that a Working Set can contain any importable distribution, not just pluggable ones. For example, the Python standard library is an importable distribution that will usually be part of the Working Set, even though it is not pluggable. Similarly, when you are doing development work on a project, the files you are editing are also a Distribution. (And, with a little attention to the directory names used, and including some additional metadata, such a "development distribution" can be made pluggable as well.) >>> from pkg_resources import WorkingSet A working set's entries are the sys.path entries that correspond to the active distributions. By default, the working set's entries are the items on ``sys.path``:: >>> ws = WorkingSet() >>> ws.entries == sys.path True But you can also create an empty working set explicitly, and add distributions to it:: >>> ws = WorkingSet([]) >>> ws.add(dist) >>> ws.entries ['http://example.com/something'] >>> dist in ws True >>> Distribution('foo') in ws False And you can iterate over its distributions:: >>> list(ws) [Bar 0.9 (http://example.com/something)] Adding the same distribution more than once is a no-op:: >>> ws.add(dist) >>> list(ws) [Bar 0.9 (http://example.com/something)] For that matter, adding multiple distributions for the same project also does nothing, because a working set can only hold one active distribution per project -- the first one added to it:: >>> ws.add( ... Distribution( ... 'http://example.com/something', project_name="Bar", ... version="7.2" ... ) ... ) >>> list(ws) [Bar 0.9 (http://example.com/something)] You can append a path entry to a working set using ``add_entry()``:: >>> ws.entries ['http://example.com/something'] >>> ws.add_entry(pkg_resources.__file__) >>> ws.entries ['http://example.com/something', '...pkg_resources.py...'] Multiple additions result in multiple entries, even if the entry is already in the working set (because ``sys.path`` can contain the same entry more than once):: >>> ws.add_entry(pkg_resources.__file__) >>> ws.entries ['...example.com...', '...pkg_resources...', '...pkg_resources...'] And you can specify the path entry a distribution was found under, using the optional second parameter to ``add()`` >>> ws.add(dist,"foo") >>> ws.add(dist,"bar") >>> ws.entries ['http://example.com/something', ..., 'foo', 'bar'] But even if a distribution is found under multiple path entries, it still only shows up once when iterating the working set: >>> list(ws) [Bar 0.9 (http://example.com/something)] You can ask a WorkingSet to ``find()`` a distribution matching a requirement:: >>> from pkg_resources import Requirement >>> print ws.find(Requirement.parse("Foo==1.0")) # no match, return None None >>> ws.find(Requirement.parse("Bar==0.9")) # match, return distribution Bar 0.9 (http://example.com/something) Note that asking for a conflicting version of a distribution already in a working set triggers a ``pkg_resources.VersionConflict`` error: >>> ws.find(Requirement.parse("Bar==1.0")) # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... VersionConflict: (Bar 0.9 (http://example.com/something), Requirement.parse('Bar==1.0')) You can subscribe a callback function to receive notifications whenever a new distribution is added to a working set. The callback is immediately invoked once for each existing distribution in the working set, and then is called again for new distributions added thereafter:: >>> def added(dist): print "Added", dist >>> ws.subscribe(added) Added Bar 0.9 >>> foo12 = Distribution(project_name="Foo", version="1.2") >>> ws.add(foo12) Added Foo 1.2 Note, however, that only the first distribution added for a given project name will trigger a callback, even during the initial ``subscribe()`` callback:: >>> foo14 = Distribution(project_name="Foo", version="1.4") >>> ws.add(foo14) # no callback, because Foo 1.2 is already active >>> ws = WorkingSet([]) >>> ws.add(foo12) >>> ws.add(foo14) >>> ws.subscribe(added) Added Foo 1.2 And adding a callback more than once has no effect, either:: >>> ws.subscribe(added) # no callbacks # and no double-callbacks on subsequent additions, either >>> ws.add(Distribution(project_name="JustATest", version="0.99")) Added JustATest 0.99 Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.43 retrieving revision 1.44 diff -u -d -r1.43 -r1.44 --- EasyInstall.txt 16 Jul 2005 21:57:50 -0000 1.43 +++ EasyInstall.txt 18 Jul 2005 01:39:45 -0000 1.44 @@ -623,6 +623,22 @@ Made ``easy-install.pth`` work in platform-specific alternate site directories (e.g. ``~/Library/Python/2.x/site-packages``). + * If you manually delete the current version of a package, the next run of + EasyInstall against the target directory will now remove the stray entry + from the ``easy-install.pth``file. + + * EasyInstall now recognizes URLs with a ``#egg=project_name`` fragment ID + as pointing to the named project's source checkout. Such URLs have a lower + match precedence than any other kind of distribution, so they'll only be + used if they have a higher version number than any other available + distribution. (Future versions may allow you to specify that you want to + use source checkouts instead of other kinds of distributions.) The ``#egg`` + fragment can contain a version if it's formatted as ``#egg=proj-ver``, + where ``proj`` is the project name, and ``ver`` is the version number. You + *must* use the format for these values that the ``bdist_egg`` command uses; + i.e., all non-alphanumeric runs must be condensed to single underscore + characters. + 0.5a12 * Fix ``python -m easy_install`` not working due to setuptools being installed as a zipfile. Update safety scanner to check for modules that might be used Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.45 retrieving revision 1.46 diff -u -d -r1.45 -r1.46 --- pkg_resources.py 17 Jul 2005 19:54:37 -0000 1.45 +++ pkg_resources.py 18 Jul 2005 01:39:45 -0000 1.46 @@ -23,7 +23,8 @@ 'get_importer', 'find_distributions', 'find_on_path', 'register_finder', 'split_sections', 'declare_namespace', 'register_namespace_handler', 'safe_name', 'safe_version', 'run_main', 'BINARY_DIST', 'run_script', - 'get_default_cache', 'EmptyProvider', 'empty_provider', + 'get_default_cache', 'EmptyProvider', 'empty_provider', 'normalize_path', + 'WorkingSet', 'working_set', 'add_activation_listener', 'CHECKOUT_DIST', ] import sys, os, zipimport, time, re, imp @@ -38,7 +39,6 @@ - class ResolutionError(Exception): """Abstract base for dependency resolution errors""" @@ -57,6 +57,7 @@ EGG_DIST = 3 BINARY_DIST = 2 SOURCE_DIST = 1 +CHECKOUT_DIST = 0 def register_loader_type(loader_type, provider_factory): """Register `provider_factory` to make providers for `loader_type` @@ -79,7 +80,6 @@ - def get_platform(): """Return this platform's string for platform-specific distributions @@ -203,6 +203,211 @@ +class WorkingSet(object): + """A collection of active distributions on sys.path (or a similar list)""" + + def __init__(self, entries=None): + """Create working set from list of path entries (default=sys.path)""" + self.entries = [] + self.entry_keys = {} + self.by_key = {} + self.callbacks = [] + + if entries is None: + entries = sys.path + + for entry in entries: + self.add_entry(entry) + + + def add_entry(self, entry): + """Add a path item to ``.entries``, finding any distributions on it + + ``find_distributions(entry,False)`` is used to find distributions + corresponding to the path entry, and they are added. `entry` is + always appended to ``.entries``, even if it is already present. + (This is because ``sys.path`` can contain the same value more than + once, and the ``.entries`` of the ``sys.path`` WorkingSet should always + equal ``sys.path``.) + """ + self.entry_keys.setdefault(entry, []) + self.entries.append(entry) + for dist in find_distributions(entry, False): + self.add(dist, entry) + + + def __contains__(self,dist): + """True if `dist` is the active distribution for its project""" + return self.by_key.get(dist.key) == dist + + + + + + def __iter__(self): + """Yield distributions for non-duplicate projects in the working set + + The yield order is the order in which the items' path entries were + added to the working set. + """ + for item in self.entries: + for key in self.entry_keys[item]: + yield self.by_key[key] + + + def find(self, req): + """Find a distribution matching requirement `req` + + If there is an active distribution for the requested project, this + returns it as long as it meets the version requirement specified by + `req`. But, if there is an active distribution for the project and it + does *not* meet the `req` requirement, ``VersionConflict`` is raised. + If there is no active distribution for the requested project, ``None`` + is returned. + """ + dist = self.by_key.get(req.key) + if dist is not None and dist not in req: + raise VersionConflict(dist,req) # XXX add more info + else: + return dist + + + + + + + + + + + + + + + + def add(self, dist, entry=None): + """Add `dist` to working set, associated with `entry` + + If `entry` is unspecified, it defaults to the ``.location`` of `dist`. + On exit from this routine, `entry` is added to the end of the working + set's ``.entries`` (if it wasn't already present). + + `dist` is only added to the working set if it's for a project that + doesn't already have a distribution in the set. If it's added, any + callbacks registered with the ``subscribe()`` method will be called. + """ + if entry is None: + entry = dist.location + + if entry not in self.entry_keys: + self.entries.append(entry) + self.entry_keys[entry] = [] + + if dist.key in self.by_key: + return # ignore hidden distros + + self.by_key[dist.key] = dist + keys = self.entry_keys[entry] + + if dist.key not in keys: + keys.append(dist.key) + + self._added_new(dist) + + + + + + + + + + + + + + def resolve(self, requirements, env=None, installer=None): + """List all distributions needed to (recursively) meet `requirements` + + `requirements` must be a sequence of ``Requirement`` objects. `env`, + if supplied, should be an ``AvailableDistributions`` instance. If + not supplied, it defaults to all distributions available within any + entry or distribution in the working set. `installer`, if supplied, + will be invoked with each requirement that cannot be met by an + already-installed distribution; it should return a ``Distribution`` or + ``None``. + """ + if env is None: + env = AvailableDistributions(self.entries) + + requirements = list(requirements)[::-1] # set up the stack + processed = {} # set of processed requirements + best = {} # key -> dist + to_activate = [] + + while requirements: + req = requirements.pop() + if req in processed: + # Ignore cyclic or redundant dependencies + continue + + dist = best.get(req.key) + if dist is None: + # Find the best distribution and add it to the map + dist = best[req.key] = env.best_match(req, self, installer) + if dist is None: + raise DistributionNotFound(req) # XXX put more info here + to_activate.append(dist) + elif dist not in req: + # Oops, the "best" so far conflicts with a dependency + raise VersionConflict(dist,req) # XXX put more info here + + requirements.extend(dist.depends(req.extras)[::-1]) + processed[req] = True + + return to_activate # return list of distros to activate + + def require(self, *requirements): + """Ensure that distributions matching `requirements` are activated + + `requirements` must be a string or a (possibly-nested) sequence + thereof, specifying the distributions and versions required. The + return value is a sequence of the distributions that needed to be + activated to fulfill the requirements; all relevant distributions are + included, even if they were already activated in this working set. + """ + + needed = self.resolve(parse_requirements(requirements)) + + for dist in needed: + self.add(dist) + + return needed + + + def subscribe(self, callback): + """Invoke `callback` for all distributions (including existing ones)""" + if callback in self.callbacks: + return + self.callbacks.append(callback) + for dist in self: + callback(dist) + + + def _added_new(self, dist): + for callback in self.callbacks: + callback(dist) + + + + + + + + + + + class AvailableDistributions(object): """Searchable snapshot of distributions on a search path""" @@ -296,69 +501,27 @@ """Remove `dist` from the distribution map""" self._distmap[dist.key].remove(dist) - def best_match(self, requirement, path=None, installer=None): - """Find distribution best matching `requirement` and usable on `path` + def best_match(self, req, working_set, installer=None): + """Find distribution best matching `req` and usable on `working_set` - If a distribution that's already installed on `path` is unsuitable, + If a distribution that's already active in `working_set` is unsuitable, a VersionConflict is raised. If one or more suitable distributions are - already installed, the leftmost distribution (i.e., the one first in + already active, the leftmost distribution (i.e., the one first in the search path) is returned. Otherwise, the available distribution - with the highest version number is returned, or a deferred distribution - object is returned if a suitable ``obtain()`` method exists. If there - is no way to meet the requirement, None is returned. + with the highest version number is returned. If nothing is available, + returns ``obtain(req,installer)`` or ``None`` if no distribution can + be obtained. """ - if path is None: - path = sys.path - - distros = self.get(requirement.key, ()) - find = dict([(dist.location,dist) for dist in distros]).get - - for item in path: - dist = find(item) - if dist is not None: - if dist in requirement: - return dist - else: - raise VersionConflict(dist,requirement) # XXX add more info + dist = working_set.find(req) + if dist is not None: + return dist - for dist in distros: - if dist in requirement: + for dist in self.get(req.key, ()): + if dist in req: return dist - return self.obtain(requirement, installer) # try and download/install - def resolve(self, requirements, path=None, installer=None): - """List all distributions needed to (recursively) meet requirements""" - - if path is None: - path = sys.path - - requirements = list(requirements)[::-1] # set up the stack - processed = {} # set of processed requirements - best = {} # key -> dist - to_install = [] - - while requirements: - req = requirements.pop() - if req in processed: - # Ignore cyclic or redundant dependencies - continue - - dist = best.get(req.key) - if dist is None: - # Find the best distribution and add it to the map - dist = best[req.key] = self.best_match(req, path, installer) - if dist is None: - raise DistributionNotFound(req) # XXX put more info here - to_install.append(dist) - - elif dist not in req: - # Oops, the "best" so far conflicts with a dependency - raise VersionConflict(dist,req) # XXX put more info here - - requirements.extend(dist.depends(req.extras)[::-1]) - processed[req] = True + return self.obtain(req, installer) # try and download/install - return to_install # return list of distros to install def obtain(self, requirement, installer=None): """Obtain a distro that matches requirement (e.g. via download)""" @@ -367,6 +530,7 @@ def __len__(self): return len(self._distmap) + class ResourceManager: """Manage resource extraction and packages""" @@ -531,23 +695,6 @@ "Please set the PYTHON_EGG_CACHE enviroment variable" ) -def require(*requirements): - """Ensure that distributions matching `requirements` are on ``sys.path`` - - `requirements` must be a string or a (possibly-nested) sequence - thereof, specifying the distributions and versions required. - - XXX This doesn't support arbitrary PEP 302 sys.path items yet, because - ``find_distributions()`` is hardcoded at the moment. - """ - - requirements = parse_requirements(requirements) - to_install = AvailableDistributions().resolve(requirements) - for dist in to_install: - dist.install_on(sys.path) - return to_install - - def safe_name(name): """Convert an arbitrary string to a standard distribution name @@ -572,6 +719,23 @@ + + + + + + + + + + + + + + + + + class NullProvider: """Try to implement resources and metadata for arbitrary PEP 302 loaders""" @@ -1035,24 +1199,25 @@ _distribution_finders[importer_type] = distribution_finder -def find_distributions(path_item): +def find_distributions(path_item, only=False): """Yield distributions accessible via `path_item`""" importer = get_importer(path_item) finder = _find_adapter(_distribution_finders, importer) - return finder(importer,path_item) + return finder(importer, path_item, only) -def find_in_zip(importer,path_item): +def find_in_zip(importer, path_item, only=False): metadata = EggMetadata(importer) if metadata.has_metadata('PKG-INFO'): yield Distribution.from_filename(path_item, metadata=metadata) + if only: + return # don't yield nested distros for subitem in metadata.resource_listdir('/'): if subitem.endswith('.egg'): subpath = os.path.join(path_item, subitem) for dist in find_in_zip(zipimport.zipimporter(subpath), subpath): yield dist -register_finder(zipimport.zipimporter,find_in_zip) - +register_finder(zipimport.zipimporter, find_in_zip) def StringIO(*args, **kw): """Thunk to load the real StringIO on demand""" @@ -1063,22 +1228,21 @@ from StringIO import StringIO return StringIO(*args,**kw) - -def find_nothing(importer,path_item): +def find_nothing(importer, path_item, only=False): return () - register_finder(object,find_nothing) -def find_on_path(importer,path_item): +def find_on_path(importer, path_item, only=False): """Yield distributions accessible on a sys.path directory""" if not os.path.exists(path_item): return - elif os.path.isdir(path_item): + path_item = normalize_path(path_item) + if os.path.isdir(path_item): if path_item.lower().endswith('.egg'): # unpacked egg yield Distribution.from_filename( path_item, metadata=PathMetadata( - path_item,os.path.join(path_item,'EGG-INFO') + path_item, os.path.join(path_item,'EGG-INFO') ) ) else: @@ -1086,16 +1250,18 @@ for entry in os.listdir(path_item): fullpath = os.path.join(path_item, entry) lower = entry.lower() - if lower.endswith('.egg'): - for dist in find_distributions(fullpath): - yield dist - elif lower.endswith('.egg-info'): + if lower.endswith('.egg-info'): if os.path.isdir(fullpath): # development egg metadata = PathMetadata(path_item, fullpath) dist_name = os.path.splitext(entry)[0] - yield Distribution(path_item,metadata,project_name=dist_name) - elif lower.endswith('.egg-link'): + yield Distribution( + path_item, metadata, project_name=dist_name + ) + elif not only and lower.endswith('.egg'): + for dist in find_distributions(fullpath): + yield dist + elif not only and lower.endswith('.egg-link'): for line in file(fullpath): if not line.strip(): continue for item in find_distributions(line.rstrip()): @@ -1103,8 +1269,6 @@ register_finder(ImpWrapper,find_on_path) - - _namespace_handlers = {} _namespace_packages = {} @@ -1209,9 +1373,9 @@ register_namespace_handler(object,null_ns_handler) - - - +def normalize_path(filename): + """Normalize a file/dir name for comparison purposes""" + return os.path.normcase(os.path.realpath(filename)) @@ -1312,10 +1476,9 @@ class Distribution(object): """Wrap an actual or potential sys.path entry w/metadata""" - def __init__(self, - location, metadata=None, project_name=None, version=None, - py_version=PY_MAJOR, platform=None, distro_type = EGG_DIST + location=None, metadata=None, project_name=None, version=None, + py_version=PY_MAJOR, platform=None, precedence = EGG_DIST ): self.project_name = safe_name(project_name or 'Unknown') if version is not None: @@ -1323,15 +1486,9 @@ self.py_version = py_version self.platform = platform self.location = location - self.distro_type = distro_type + self.precedence = precedence self._provider = metadata or empty_provider - def installed_on(self,path=None): - """Is this distro installed on `path`? (defaults to ``sys.path``)""" - if path is None: - path = sys.path - return self.location in path - #@classmethod def from_location(cls,location,basename,metadata=None): project_name, version, py_version, platform = [None]*4 @@ -1348,7 +1505,14 @@ ) from_location = classmethod(from_location) - + hashcmp = property( + lambda self: ( + getattr(self,'parsed_version',()), self.precedence, self.key, + self.location, self.py_version, self.platform + ) + ) + def __cmp__(self, other): return cmp(self.hashcmp, other) + def __hash__(self): return hash(self.hashcmp) # These properties have to be lazy so that we don't have to load any @@ -1389,7 +1553,7 @@ ) version = property(version) - + #@property @@ -1424,7 +1588,7 @@ for line in self.get_metadata_lines(name): yield line - def install_on(self,path=None): + def activate(self,path=None): """Ensure distribution is importable on `path` (default=sys.path)""" if path is None: path = sys.path if self.location not in path: @@ -1446,7 +1610,10 @@ return filename def __repr__(self): - return "%s (%s)" % (self,self.location) + if self.location: + return "%s (%s)" % (self,self.location) + else: + return str(self) def __str__(self): version = getattr(self,'version',None) or "[unknown version]" @@ -1460,19 +1627,13 @@ #@classmethod def from_filename(cls,filename,metadata=None): - return cls.from_location(filename, os.path.basename(filename), metadata) + return cls.from_location( + normalize_path(filename), os.path.basename(filename), metadata + ) from_filename = classmethod(from_filename) def as_requirement(self): - return Requirement.parse('%s==%s' % (dist.project_name, dist.version)) - - - - - - - - + return Requirement.parse('%s==%s' % (self.project_name, self.version)) @@ -1538,9 +1699,9 @@ def _sort_dists(dists): - tmp = [(dist.parsed_version,dist.distro_type,dist) for dist in dists] + tmp = [(dist.hashcmp,dist) for dist in dists] tmp.sort() - dists[::-1] = [d for v,t,d in tmp] + dists[::-1] = [d for hc,d in tmp] @@ -1560,7 +1721,6 @@ class Requirement: - def __init__(self, project_name, specs=(), extras=()): self.project_name = project_name self.key = project_name.lower() @@ -1575,11 +1735,12 @@ self.__hash = hash(self.hashCmp) def __str__(self): - return self.project_name + ','.join([''.join(s) for s in self.specs]) + specs = ','.join([''.join(s) for s in self.specs]) + extras = ','.join(self.extras) + if extras: extras = '[%s]' % extras + return '%s%s%s' % (self.project_name, extras, specs) - def __repr__(self): - return "Requirement(%r, %r, %r)" % \ - (self.project_name,self.specs,self.extras) + def __repr__(self): return "Requirement.parse(%r)" % str(self) def __eq__(self,other): return isinstance(other,Requirement) and self.hashCmp==other.hashCmp @@ -1693,17 +1854,17 @@ _initialize(globals()) +# Prepare the master working set and make the ``require()`` API available +working_set = WorkingSet() +require = working_set.require +add_activation_listener = working_set.subscribe - - - - - - - - - +# Activate all distributions already on sys.path, and ensure that +# all distributions added to the working set in the future (e.g. by +# calling ``require()``) will get activated as well. +# +add_activation_listener(lambda dist: dist.activate()) Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- setuptools.txt 17 Jul 2005 19:54:38 -0000 1.18 +++ setuptools.txt 18 Jul 2005 01:39:45 -0000 1.19 @@ -732,6 +732,58 @@ so we can include support for it, too.) +Making your package available for EasyInstall +--------------------------------------------- + +If you use the ``register`` command (``setup.py register``) to register your +package with PyPI, that's most of the battle right there. (See the +`docs for the register command`_ for more details.) + +.. _docs for the register command: http://docs.python.org/dist/package-index.html + +If you also use the `upload`_ command to upload actual distributions of your +package, that's even better, because EasyInstall will be able to find and +download them directly from your project's PyPI page. + +However, there may be reasons why you don't want to upload distributions to +PyPI, and just want your existing distributions (or perhaps a Subversion +checkout) to be used instead. + +So here's what you need to do before running the ``register`` command. There +are three ``setup()`` arguments that affect EasyInstall: + +``url`` and ``download_url`` + These become links on your project's PyPI page. EasyInstall will examine + them to see if they link to a package ("primary links"), or whether they are + HTML pages. If they're HTML pages, EasyInstall scans all HREF's on the + page for primary links + +``long_description`` + EasyInstall will check any URLs contained in this argument to see if they + are primary links. + +A URL is considered a "primary link" if it is a link to a .tar.gz, .tgz, .zip, +.egg, .egg.zip, .tar.bz2, or .exe file, or if it has an ``#egg=project`` or +``#egg=project-version`` fragment identifier attached to it. EasyInstall +attempts to determine a project name and optional version number from the text +of a primary link *without* downloading it. When it has found all the primary +links, EasyInstall will select the best match based on requested version, +platform compatibility, and other criteria. + +So, if your ``url`` or ``download_url`` point either directly to a downloadable +source distribution, or to HTML page(s) that have direct links to such, then +EasyInstall will be able to locate downloads automatically. If you want to +make Subversion checkouts available, then you should create links with either +``#egg=project`` or ``#egg=project-version`` added to the URL (replacing +``project`` and ``version`` with appropriate values). + +Note that Subversion checkout links are of lower precedence than other kinds +of distributions, so EasyInstall will not select a Subversion checkout for +downloading unless it has a version included in the ``#egg=`` suffix, and +it's a higher version than EasyInstall has seen in any other links for your +project. + + Distributing Extensions compiled with Pyrex ------------------------------------------- @@ -1342,7 +1394,7 @@ * Fixed ``pkg_resources.resource_exists()`` not working correctly. - * Many ``pkg_resources`` API changes: + * Many ``pkg_resources`` API changes and enhancements: * ``Distribution`` objects now implement the ``IResourceProvider`` and ``IMetadataProvider`` interfaces, so you don't need to reference the (no @@ -1354,11 +1406,35 @@ * The ``path`` attribute of ``Distribution`` objects is now ``location``, because it isn't necessarily a filesystem path (and hasn't been for some - time now). + time now). The ``location`` of ``Distribution`` objects in the filesystem + should always be normalized using ``pkg_resources.normalize_path()``; all + of the setuptools and EasyInstall code that generates distributions from + the filesystem (including ``Distribution.from_filename()``) ensure this + invariant, but if you use a more generic API like ``Distribution()`` or + ``Distribution.from_location()`` you should take care that you don't + create a distribution with an un-normalized filesystem path. * ``Distribution`` objects now have an ``as_requirement()`` method that returns a ``Requirement`` for the distribution's project name and version. + * Distribution objects no longer have an ``installed_on()`` method, and the + ``install_on()`` method is now ``activate()`` (but may go away altogether + soon). + + * ``find_distributions()`` now takes an additional argument called ``only``, + that tells it to only yield distributions whose location is the passed-in + path. (It defaults to False, so that the default behavior is unchanged.) + + * The ``resolve()`` method of ``AvailableDistributions`` is now a method of + ``WorkingSet`` instead, and the ``best_match()`` method now uses a working + set instead of a path list as its second argument. + + * There is a new ``pkg_resources.add_activation_listener()`` API that lets + you register a callback for notifications about distributions added to + ``sys.path`` (including the distributions already on it). This is + basically a hook for extensible applications and frameworks to be able to + search for plugin metadata in distributions added at runtime. + 0.5a13 * Fixed a bug in resource extraction from nested packages in a zipped egg. From pje at users.sourceforge.net Mon Jul 18 04:06:33 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 19:06:33 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools __init__.py, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10165/setuptools Modified Files: __init__.py Log Message: Massive API refactoring; see setuptools.txt changelog for details. Also, add ``#egg=project-version`` link support, and docs on how to make your package available for EasyInstall to find. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/__init__.py,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- __init__.py 16 Jul 2005 16:17:29 -0000 1.20 +++ __init__.py 18 Jul 2005 02:06:15 -0000 1.21 @@ -7,7 +7,7 @@ from distutils.util import convert_path import os.path -__version__ = '0.5a13' +__version__ = '0.6a0' __all__ = [ 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', 'find_packages' From pje at users.sourceforge.net Mon Jul 18 04:06:35 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 19:06:35 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.14, 1.15 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10165/setuptools/command Modified Files: easy_install.py Log Message: Massive API refactoring; see setuptools.txt changelog for details. Also, add ``#egg=project-version`` link support, and docs on how to make your package available for EasyInstall to find. Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- easy_install.py 18 Jul 2005 01:39:45 -0000 1.14 +++ easy_install.py 18 Jul 2005 02:06:30 -0000 1.15 @@ -419,7 +419,7 @@ options = match.group(1) or '' if options: options = ' '+options - spec = dist.as_requirement() + spec = str(dist.as_requirement()) executable = os.path.normpath(sys.executable) if dev_path: @@ -789,7 +789,7 @@ self.shadow_path.remove(d.location) if not self.multi_version: - if dist.location in map(normalize_path,self.pth_file.paths): + if dist.location in self.pth_file.paths: log.info( "%s is already the active version in easy-install.pth", dist @@ -802,10 +802,10 @@ self.pth_file.save() - if dist.project_name=='setuptools': + if dist.key=='setuptools': # Ensure that setuptools itself never becomes unavailable! # XXX should this check for latest version? - f = open(os.path.join(self.install_dir,'setuptools.pth'), 'w') + f = open(os.path.join(self.install_dir,'setuptools.pth'), 'wt') f.write(dist.location+'\n') f.close() @@ -1027,6 +1027,7 @@ """A .pth file with Distribution paths in it""" dirty = False + def __init__(self, filename): self.filename = filename; self._load() AvailableDistributions.__init__( @@ -1035,22 +1036,34 @@ def _load(self): self.paths = [] + seen = {} if os.path.isfile(self.filename): - self.paths = [line.rstrip() for line in open(self.filename,'rt')] - while self.paths and not self.paths[-1].strip(): self.paths.pop() - # delete non-existent paths, in case somebody deleted a package - # manually: - for line in list(yield_lines(self.paths)): - if not os.path.exists(line): - self.paths.remove(line); self.dirty = True - + for line in open(self.filename,'rt'): + path = line.rstrip() + self.paths.append(path) + if not path.strip() or path.strip().startswith('#'): + continue + # skip non-existent paths, in case somebody deleted a package + # manually, and duplicate paths as well + path = self.paths[-1] = normalize_path(path) + if not os.path.exists(path) or path in seen: + self.paths.pop() # skip it + self.dirty = True # we cleaned up, so we're dirty now :) + continue + seen[path] = 1 + + while self.paths and not self.paths[-1].strip(): self.paths.pop() + def save(self): """Write changed .pth file back to disk""" if self.dirty: + log.debug("Saving %s", self.filename) data = '\n'.join(self.paths+['']) f = open(self.filename,'wt'); f.write(data); f.close() self.dirty = False + + def add(self,dist): """Add `dist` to the distribution map""" if dist.location not in self.paths: @@ -1092,16 +1105,3 @@ - - - - - - - - - - - - - From pje at users.sourceforge.net Mon Jul 18 04:06:48 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 19:06:48 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.44, 1.45 ez_setup.py, 1.20, 1.21 pkg_resources.py, 1.46, 1.47 setup.cfg, 1.1, 1.2 setup.py, 1.31, 1.32 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10165 Modified Files: EasyInstall.txt ez_setup.py pkg_resources.py setup.cfg setup.py Log Message: Massive API refactoring; see setuptools.txt changelog for details. Also, add ``#egg=project-version`` link support, and docs on how to make your package available for EasyInstall to find. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.44 retrieving revision 1.45 diff -u -d -r1.44 -r1.45 --- EasyInstall.txt 18 Jul 2005 01:39:45 -0000 1.44 +++ EasyInstall.txt 18 Jul 2005 02:06:15 -0000 1.45 @@ -67,7 +67,7 @@ **Example 2**. Install or upgrade a package by name and version by finding links on a given "download page":: - easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.5a13" + easy_install -f http://peak.telecommunity.com/dist "setuptools>=0.6a0" **Example 3**. Download a source distribution from a specified URL, automatically building and installing it:: Index: ez_setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/ez_setup.py,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- ez_setup.py 16 Jul 2005 16:17:29 -0000 1.20 +++ ez_setup.py 18 Jul 2005 02:06:15 -0000 1.21 @@ -14,7 +14,7 @@ This file can also be run as a script to install or upgrade setuptools. """ -DEFAULT_VERSION = "0.5a13" +DEFAULT_VERSION = "0.6a0" DEFAULT_URL = "http://www.python.org/packages/source/s/setuptools/" import sys, os Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.46 retrieving revision 1.47 diff -u -d -r1.46 -r1.47 --- pkg_resources.py 18 Jul 2005 01:39:45 -0000 1.46 +++ pkg_resources.py 18 Jul 2005 02:06:15 -0000 1.47 @@ -232,7 +232,7 @@ """ self.entry_keys.setdefault(entry, []) self.entries.append(entry) - for dist in find_distributions(entry, False): + for dist in find_distributions(entry, True): self.add(dist, entry) Index: setup.cfg =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.cfg,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- setup.cfg 8 Jul 2005 15:52:05 -0000 1.1 +++ setup.cfg 18 Jul 2005 02:06:15 -0000 1.2 @@ -1,4 +1,5 @@ [aliases] -source = register sdist binary binary = bdist_egg upload --show-response +develop = develop +source = register sdist binary Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.31 retrieving revision 1.32 diff -u -d -r1.31 -r1.32 --- setup.py 16 Jul 2005 16:17:29 -0000 1.31 +++ setup.py 18 Jul 2005 02:06:15 -0000 1.32 @@ -15,7 +15,7 @@ f.close() return ''.join(lines) -VERSION = "0.5a13" +VERSION = "0.6a0" from setuptools import setup, find_packages From pje at users.sourceforge.net Mon Jul 18 04:28:16 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 19:28:16 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.47, 1.48 setuptools.txt, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13936 Modified Files: pkg_resources.py setuptools.txt Log Message: Catch a few missed terminology changes. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.47 retrieving revision 1.48 diff -u -d -r1.47 -r1.48 --- pkg_resources.py 18 Jul 2005 02:06:15 -0000 1.47 +++ pkg_resources.py 18 Jul 2005 02:28:14 -0000 1.48 @@ -362,7 +362,7 @@ # Oops, the "best" so far conflicts with a dependency raise VersionConflict(dist,req) # XXX put more info here - requirements.extend(dist.depends(req.extras)[::-1]) + requirements.extend(dist.requires(req.extras)[::-1]) processed[req] = True return to_activate # return list of distros to activate @@ -1569,8 +1569,8 @@ _dep_map = property(_dep_map) - def depends(self,extras=()): - """List of Requirements needed for this distro if `options` are used""" + def requires(self,extras=()): + """List of Requirements needed for this distro if `extras` are used""" dm = self._dep_map deps = [] deps.extend(dm.get(None,())) @@ -1686,16 +1686,18 @@ raise ValueError("Missing distribution spec", line) project_name = match.group(1) p = match.end() - options = [] + extras = [] match = OBRACKET(line,p) if match: p = match.end() - line, p, options = scan_list(DISTRO,CBRACKET,line,p,(1,),"option") + line, p, extras = scan_list( + DISTRO, CBRACKET, line, p, (1,), "'extra' name" + ) line, p, specs = scan_list(VERSION,LINE_END,line,p,(1,2),"version spec") specs = [(op,val.replace('_','-')) for op,val in specs] - yield Requirement(project_name.replace('_','-'), specs, options) + yield Requirement(project_name.replace('_','-'), specs, extras) def _sort_dists(dists): @@ -1718,8 +1720,6 @@ - - class Requirement: def __init__(self, project_name, specs=(), extras=()): self.project_name = project_name Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- setuptools.txt 18 Jul 2005 01:39:45 -0000 1.19 +++ setuptools.txt 18 Jul 2005 02:28:14 -0000 1.20 @@ -1419,7 +1419,7 @@ * Distribution objects no longer have an ``installed_on()`` method, and the ``install_on()`` method is now ``activate()`` (but may go away altogether - soon). + soon). The ``depends()`` method has also been renamed to ``requires()``. * ``find_distributions()`` now takes an additional argument called ``only``, that tells it to only yield distributions whose location is the passed-in From pje at users.sourceforge.net Mon Jul 18 04:28:16 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 17 Jul 2005 19:28:16 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/tests test_resources.py, 1.16, 1.17 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13936/setuptools/tests Modified Files: test_resources.py Log Message: Catch a few missed terminology changes. Index: test_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/test_resources.py,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- test_resources.py 18 Jul 2005 01:39:45 -0000 1.16 +++ test_resources.py 18 Jul 2005 02:28:14 -0000 1.17 @@ -105,18 +105,18 @@ self.checkFooPkg(d) - def distDepends(self, txt): + def distRequires(self, txt): return Distribution("/foo", metadata=Metadata(('depends.txt', txt))) - def checkDepends(self, dist, txt, opts=()): + def checkRequires(self, dist, txt, extras=()): self.assertEqual( - list(dist.depends(opts)), + list(dist.requires(extras)), list(parse_requirements(txt)) ) def testDistroDependsSimple(self): for v in "Twisted>=1.5", "Twisted>=1.5\nZConfig>=2.0": - self.checkDepends(self.distDepends(v), v) + self.checkRequires(self.distRequires(v), v) @@ -163,29 +163,29 @@ ) def testDistroDependsOptions(self): - d = self.distDepends(""" + d = self.distRequires(""" Twisted>=1.5 [docgen] ZConfig>=2.0 docutils>=0.3 [fastcgi] fcgiapp>=0.1""") - self.checkDepends(d,"Twisted>=1.5") - self.checkDepends( + self.checkRequires(d,"Twisted>=1.5") + self.checkRequires( d,"Twisted>=1.5 ZConfig>=2.0 docutils>=0.3".split(), ["docgen"] ) - self.checkDepends( + self.checkRequires( d,"Twisted>=1.5 fcgiapp>=0.1".split(), ["fastcgi"] ) - self.checkDepends( + self.checkRequires( d,"Twisted>=1.5 ZConfig>=2.0 docutils>=0.3 fcgiapp>=0.1".split(), ["docgen","fastcgi"] ) - self.checkDepends( + self.checkRequires( d,"Twisted>=1.5 fcgiapp>=0.1 ZConfig>=2.0 docutils>=0.3".split(), ["fastcgi", "docgen"] ) - self.assertRaises(InvalidOption, d.depends, ["foo"]) + self.assertRaises(InvalidOption, d.requires, ["foo"]) From birkenfeld at users.sourceforge.net Mon Jul 18 09:24:39 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 00:24:39 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS, 1.1193.2.62, 1.1193.2.63 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28967/Misc Modified Files: Tag: release24-maint NEWS Log Message: backporting fix by tim_one: """ SF bug #1238681: freed pointer is used in longobject.c:long_pow(). In addition, long_pow() skipped a necessary (albeit extremely unlikely to trigger) error check when converting an int modulus to long. Alas, I was unable to write a test case that crashed due to either cause. """ Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.62 retrieving revision 1.1193.2.63 diff -u -d -r1.1193.2.62 -r1.1193.2.63 --- NEWS 17 Jul 2005 20:26:33 -0000 1.1193.2.62 +++ NEWS 18 Jul 2005 07:24:35 -0000 1.1193.2.63 @@ -12,6 +12,8 @@ Core and builtins ----------------- +- SF bug #1238681: freed pointer is used in longobject.c:long_pow(). + - SF bug #1185883: Python's small-object memory allocator took over a block managed by the platform C library whenever a realloc specified a small new size. However, there's no portable way to know then how From birkenfeld at users.sourceforge.net Mon Jul 18 09:24:39 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 00:24:39 -0700 Subject: [Python-checkins] python/dist/src/Objects longobject.c, 1.165.2.1, 1.165.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28967/Objects Modified Files: Tag: release24-maint longobject.c Log Message: backporting fix by tim_one: """ SF bug #1238681: freed pointer is used in longobject.c:long_pow(). In addition, long_pow() skipped a necessary (albeit extremely unlikely to trigger) error check when converting an int modulus to long. Alas, I was unable to write a test case that crashed due to either cause. """ Index: longobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v retrieving revision 1.165.2.1 retrieving revision 1.165.2.2 diff -u -d -r1.165.2.1 -r1.165.2.2 --- longobject.c 3 Mar 2005 12:26:05 -0000 1.165.2.1 +++ longobject.c 18 Jul 2005 07:24:37 -0000 1.165.2.2 @@ -2360,8 +2360,11 @@ c = (PyLongObject *)x; Py_INCREF(x); } - else if (PyInt_Check(x)) + else if (PyInt_Check(x)) { c = (PyLongObject *)PyLong_FromLong(PyInt_AS_LONG(x)); + if (c == NULL) + goto Error; + } else if (x == Py_None) c = NULL; else { @@ -2511,14 +2514,14 @@ } /* fall through */ Done: - Py_XDECREF(a); - Py_XDECREF(b); - Py_XDECREF(c); - Py_XDECREF(temp); if (b->ob_size > FIVEARY_CUTOFF) { for (i = 0; i < 32; ++i) Py_XDECREF(table[i]); } + Py_DECREF(a); + Py_DECREF(b); + Py_XDECREF(c); + Py_XDECREF(temp); return (PyObject *)z; } From birkenfeld at users.sourceforge.net Mon Jul 18 09:38:46 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 00:38:46 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libsocksvr.tex, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31427/Doc/lib Modified Files: libsocksvr.tex Log Message: bug [ 957505 ] SocketServer module documentation misleading Index: libsocksvr.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libsocksvr.tex,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- libsocksvr.tex 12 May 2005 13:42:42 -0000 1.19 +++ libsocksvr.tex 18 Jul 2005 07:38:44 -0000 1.20 @@ -95,8 +95,7 @@ can then run various versions of the service by combining one of the server classes with your request handler class. The request handler class must be different for datagram or stream services. This can be hidden by using the -mix-in request handler classes \class{StreamRequestHandler} or -\class{DatagramRequestHandler}. +handler subclasses \class{StreamRequestHandler} or \class{DatagramRequestHandler}. Of course, you still have to use your head! For instance, it makes no sense to use a forking server if the service contains state in memory that can be @@ -279,11 +278,10 @@ The type of \member{self.request} is different for datagram or stream services. For stream services, \member{self.request} is a socket object; for datagram services, \member{self.request} is a string. -However, this can be hidden by using the mix-in request handler -classes +However, this can be hidden by using the request handler subclasses \class{StreamRequestHandler} or \class{DatagramRequestHandler}, which override the \method{setup()} and \method{finish()} methods, and -provides \member{self.rfile} and \member{self.wfile} attributes. +provide \member{self.rfile} and \member{self.wfile} attributes. \member{self.rfile} and \member{self.wfile} can be read or written, respectively, to get the request data or return data to the client. \end{funcdesc} From birkenfeld at users.sourceforge.net Mon Jul 18 09:38:47 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 00:38:47 -0700 Subject: [Python-checkins] python/dist/src/Lib SocketServer.py,1.39,1.40 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31427/Lib Modified Files: SocketServer.py Log Message: bug [ 957505 ] SocketServer module documentation misleading Index: SocketServer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/SocketServer.py,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- SocketServer.py 30 Apr 2005 00:20:35 -0000 1.39 +++ SocketServer.py 18 Jul 2005 07:38:44 -0000 1.40 @@ -65,8 +65,8 @@ with your request handler class. The request handler class must be different for datagram or stream -services. This can be hidden by using the mix-in request handler -classes StreamRequestHandler or DatagramRequestHandler. +services. This can be hidden by using the request handler +subclasses StreamRequestHandler or DatagramRequestHandler. Of course, you still have to use your head! From birkenfeld at users.sourceforge.net Mon Jul 18 09:38:51 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 00:38:51 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libsocksvr.tex, 1.18.4.1, 1.18.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31445/Doc/lib Modified Files: Tag: release24-maint libsocksvr.tex Log Message: backport bug [ 957505 ] SocketServer module documentation misleading Index: libsocksvr.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libsocksvr.tex,v retrieving revision 1.18.4.1 retrieving revision 1.18.4.2 diff -u -d -r1.18.4.1 -r1.18.4.2 --- libsocksvr.tex 12 May 2005 13:43:40 -0000 1.18.4.1 +++ libsocksvr.tex 18 Jul 2005 07:38:49 -0000 1.18.4.2 @@ -95,8 +95,7 @@ can then run various versions of the service by combining one of the server classes with your request handler class. The request handler class must be different for datagram or stream services. This can be hidden by using the -mix-in request handler classes \class{StreamRequestHandler} or -\class{DatagramRequestHandler}. +handler subclasses \class{StreamRequestHandler} or \class{DatagramRequestHandler}. Of course, you still have to use your head! For instance, it makes no sense to use a forking server if the service contains state in memory that can be @@ -279,11 +278,10 @@ The type of \member{self.request} is different for datagram or stream services. For stream services, \member{self.request} is a socket object; for datagram services, \member{self.request} is a string. -However, this can be hidden by using the mix-in request handler -classes +However, this can be hidden by using the request handler subclasses \class{StreamRequestHandler} or \class{DatagramRequestHandler}, which override the \method{setup()} and \method{finish()} methods, and -provides \member{self.rfile} and \member{self.wfile} attributes. +provide \member{self.rfile} and \member{self.wfile} attributes. \member{self.rfile} and \member{self.wfile} can be read or written, respectively, to get the request data or return data to the client. \end{funcdesc} From birkenfeld at users.sourceforge.net Mon Jul 18 09:38:51 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 00:38:51 -0700 Subject: [Python-checkins] python/dist/src/Lib SocketServer.py, 1.37, 1.37.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31445/Lib Modified Files: Tag: release24-maint SocketServer.py Log Message: backport bug [ 957505 ] SocketServer module documentation misleading Index: SocketServer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/SocketServer.py,v retrieving revision 1.37 retrieving revision 1.37.4.1 diff -u -d -r1.37 -r1.37.4.1 --- SocketServer.py 9 Oct 2003 23:48:52 -0000 1.37 +++ SocketServer.py 18 Jul 2005 07:38:49 -0000 1.37.4.1 @@ -65,8 +65,8 @@ with your request handler class. The request handler class must be different for datagram or stream -services. This can be hidden by using the mix-in request handler -classes StreamRequestHandler or DatagramRequestHandler. +services. This can be hidden by using the request handler +subclasses StreamRequestHandler or DatagramRequestHandler. Of course, you still have to use your head! From birkenfeld at users.sourceforge.net Mon Jul 18 10:04:20 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 01:04:20 -0700 Subject: [Python-checkins] python/dist/src/Doc/doc doc.tex,1.93,1.94 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/doc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3133/Doc/doc Modified Files: doc.tex Log Message: bug [ 850238 ] unclear documentation/missing command? Index: doc.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/doc/doc.tex,v retrieving revision 1.93 retrieving revision 1.94 diff -u -d -r1.93 -r1.94 --- doc.tex 18 Jun 2005 17:54:13 -0000 1.93 +++ doc.tex 18 Jul 2005 08:04:17 -0000 1.94 @@ -1134,9 +1134,9 @@ \subsection{Module-specific Markup \label{module-markup}} The markup described in this section is used to provide information - about a module being documented. A typical use of this markup - appears at the top of the section used to document a module. A - typical example might look like this: + about a module being documented. Each module should be documented + in its own \macro{section}. A typical use of this markup + appears at the top of that section and might look like this: \begin{verbatim} \section{\module{spam} --- From birkenfeld at users.sourceforge.net Mon Jul 18 10:04:24 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 01:04:24 -0700 Subject: [Python-checkins] python/dist/src/Doc/doc doc.tex, 1.90.2.2, 1.90.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/doc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3166/Doc/doc Modified Files: Tag: release24-maint doc.tex Log Message: backport bug [ 850238 ] unclear documentation/missing command? Index: doc.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/doc/doc.tex,v retrieving revision 1.90.2.2 retrieving revision 1.90.2.3 diff -u -d -r1.90.2.2 -r1.90.2.3 --- doc.tex 3 Mar 2005 23:07:47 -0000 1.90.2.2 +++ doc.tex 18 Jul 2005 08:04:22 -0000 1.90.2.3 @@ -1134,9 +1134,9 @@ \subsection{Module-specific Markup \label{module-markup}} The markup described in this section is used to provide information - about a module being documented. A typical use of this markup - appears at the top of the section used to document a module. A - typical example might look like this: + about a module being documented. Each module should be documented + in its own \macro{section}. A typical use of this markup + appears at the top of that section and might look like this: \begin{verbatim} \section{\module{spam} --- From birkenfeld at users.sourceforge.net Mon Jul 18 10:16:36 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 01:16:36 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libos.tex,1.163,1.164 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5427/Doc/lib Modified Files: libos.tex Log Message: [ 755617 ] os module: Need a better description of "mode" Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.163 retrieving revision 1.164 diff -u -d -r1.163 -r1.164 --- libos.tex 17 Jul 2005 21:10:11 -0000 1.163 +++ libos.tex 18 Jul 2005 08:16:33 -0000 1.164 @@ -764,6 +764,11 @@ \item \code{S_IXOTH} \end{itemize} Availability: Macintosh, \UNIX, Windows. + +\note{Although Windows supports \function{chmod()}, you can only +set the file's read-only flag with it (via the \code{S_IWRITE} +and \code{S_IREAD} constants or a corresponding integer value). +All other bits are ignored.} \end{funcdesc} \begin{funcdesc}{chown}{path, uid, gid} From birkenfeld at users.sourceforge.net Mon Jul 18 10:17:11 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 01:17:11 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libos.tex, 1.146.2.9, 1.146.2.10 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5439/Doc/lib Modified Files: Tag: release24-maint libos.tex Log Message: backport bug [ 755617 ] os module: Need a better description of "mode" Index: libos.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libos.tex,v retrieving revision 1.146.2.9 retrieving revision 1.146.2.10 diff -u -d -r1.146.2.9 -r1.146.2.10 --- libos.tex 17 Jul 2005 21:10:07 -0000 1.146.2.9 +++ libos.tex 18 Jul 2005 08:17:08 -0000 1.146.2.10 @@ -751,6 +751,11 @@ \item \code{S_IXOTH} \end{itemize} Availability: Macintosh, \UNIX, Windows. + +\note{Although Windows supports \function{chmod()}, you can only +set the file's read-only flag with it (via the \code{S_IWRITE} +and \code{S_IREAD} constants or a corresponding integer value). +All other bits are ignored.} \end{funcdesc} \begin{funcdesc}{chown}{path, uid, gid} From birkenfeld at users.sourceforge.net Mon Jul 18 10:53:21 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 01:53:21 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1319,1.1320 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12122/Misc Modified Files: NEWS Log Message: added news entry for previous checkin Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1319 retrieving revision 1.1320 diff -u -d -r1.1319 -r1.1320 --- NEWS 17 Jul 2005 23:45:21 -0000 1.1319 +++ NEWS 18 Jul 2005 08:53:17 -0000 1.1320 @@ -418,6 +418,8 @@ Documentation ------------- +- Bug #755617: Document the effects of os.chown() on Windows. + - Patch #1180012: The documentation for modulefinder is now in the library reference. - Patch #1213031: Document that os.chown() accepts argument values of -1. From birkenfeld at users.sourceforge.net Mon Jul 18 10:53:43 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 01:53:43 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS, 1.1193.2.63, 1.1193.2.64 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12130/Misc Modified Files: Tag: release24-maint NEWS Log Message: added news entry for previous checkin Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.63 retrieving revision 1.1193.2.64 diff -u -d -r1.1193.2.63 -r1.1193.2.64 --- NEWS 18 Jul 2005 07:24:35 -0000 1.1193.2.63 +++ NEWS 18 Jul 2005 08:53:40 -0000 1.1193.2.64 @@ -86,6 +86,8 @@ Documentation ------------- +- Bug #755617: Document the effects of os.chown() on Windows. + - Patch #1180012: The documentation for modulefinder is now in the library reference. - Patch #1213031: Document that os.chown() accepts argument values of -1. From birkenfeld at users.sourceforge.net Mon Jul 18 12:33:09 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 03:33:09 -0700 Subject: [Python-checkins] python/nondist/sandbox/path - New directory Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31161/path Log Message: Directory /cvsroot/python/python/nondist/sandbox/path added to the repository From birkenfeld at users.sourceforge.net Mon Jul 18 14:09:28 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 18 Jul 2005 05:09:28 -0700 Subject: [Python-checkins] python/nondist/sandbox/path path.py, NONE, 1.1 test_path.py, NONE, 1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17007 Added Files: path.py test_path.py Log Message: Adding first revision of revised Path module for the hopefully upcoming PEP. --- NEW FILE: path.py --- """ path.py - An object representing a path to a file or directory. Example: from os.path import Path d = Path('/home/guido/bin') for f in d.files('*.py'): f.chmod(0755) Author: Jason Orendorff (and others) Date: 7 Mar 2004 Adapted for stdlib by: Reinhold Birkenfeld, July 2005 """ # TODO # - Bug in write_text(). It doesn't support Universal newline mode. # - Better error message in listdir() when self isn't a # directory. (On Windows, the error message really sucks.) # - Add methods for regex find and replace. # - guess_content_type() method? # TODO (standard module) # - add more standard header? # - shutil functions should accept a Path as "dst" # - Make sure everything has a good docstring. import sys, os, fnmatch, glob, shutil, codecs __version__ = "$Id: path.py,v 1.1 2005/07/18 12:09:26 birkenfeld Exp $" __all__ = ['Path'] # Universal newline support _textmode = 'r' if hasattr(file, 'newlines'): _textmode = 'U' # helper function: if given string/unicode, return it # if given path, return path string def _strpath(thing): if isinstance(thing, Path): return thing._p return thing class Path(object): """ Represents a filesystem path. Path is an immutable object. For documentation on individual methods, consult their counterparts in os.path. """ # --- Special Python methods. def __init__(self, path=os.curdir): """ Initialize a Path instance. The path argument can be either a string or an existing Path object. """ if isinstance(path, Path): self._p = path._p else: self._p = path def __repr__(self): return 'Path(%s)' % repr(self._p) def __str__(self): return str(self._p) # Adding path and string yields a path def __add__(self, other): if isinstance(other, (str, unicode)): return Path(self._p + other) elif isinstance(other, Path): return Path(self._p + other._p) return NotImplemented def __radd__(self, other): if isinstance(other, (str, unicode)): return Path(other + self._p) elif isinstance(other, Path): return Path(other._p + self._p) return NotImplemented # The / joins paths def __div__(self, other): return self.joinwith(other) __truediv__ = __div__ # Rich comparison def __eq__(self, other): return isinstance(other, Path) and (self._p == other._p) def __ne__(self, other): return (not isinstance(other, Path)) or (self._p != other._p) def __lt__(self, other): if isinstance(other, Path): return self._p < other._p return NotImplemented def __le__(self, other): if isinstance(other, Path): return self._p <= other._p return NotImplemented def __gt__(self, other): if isinstance(other, Path): return self._p > other._p return NotImplemented def __ge__(self, other): if isinstance(other, Path): return self._p >= other._p return NotImplemented # Hash like strings def __hash__(self): return hash(self._p) + 1 # Alternative constructor. @staticmethod def cwd(): """ Return the current working directory as a path object. """ if os.path.supports_unicode_filenames: return Path(os.getcwdu()) else: return Path(os.getcwd()) # --- Operations which yield strings def _get_basename(self): return os.path.basename(self._p) def _get_namebase(self): base, ext = os.path.splitext(self.basename) return base def _get_ext(self): f, ext = os.path.splitext(self._p) return ext def _get_drive(self): drive, r = os.path.splitdrive(self._p) return drive basename = property( _get_basename, None, None, """ The name of this file or directory without the full path. For example, path('/usr/local/lib/libpython.so').basename == 'libpython.so' """) namebase = property( _get_namebase, None, None, """ The same as Path.basename, but with one file extension stripped off. For example, path('/home/guido/python.tar.gz').basename == 'python.tar.gz', but path('/home/guido/python.tar.gz').namebase == 'python.tar' """) ext = property( _get_ext, None, None, """ The file extension, for example '.py'. """) drive = property( _get_drive, None, None, """ The drive specifier, for example 'C:'. This is always empty on systems that don't use drive specifiers. """) # --- Operations which yield Path objects def abspath(self): return Path(os.path.abspath(self._p)) def normcase(self): return Path(os.path.normcase(self._p)) def normpath(self): return Path(os.path.normpath(self._p)) def realpath(self): return Path(os.path.realpath(self._p)) def expanduser(self): return Path(os.path.expanduser(self._p)) def expandvars(self): return Path(os.path.expandvars(self._p)) def expand(self): """ Clean up a filename by calling expandvars(), expanduser(), and normpath() on it. This is commonly everything needed to clean up a filename read from a configuration file, for example. """ return self.expandvars().expanduser().normpath() def _get_directory(self): return Path(os.path.dirname(self._p)) directory = property( _get_directory, None, None, """ This path's parent directory, as a new path object. For example, Path('/usr/local/lib/libpython.so').directory == Path('/usr/local/lib') """) def stripext(self): """ p.stripext() -> Remove one file extension from the path. For example, path('/home/guido/python.tar.gz').stripext() returns path('/home/guido/python.tar'). """ return self.splitext()[0] # --- Operations which yield Paths and strings def splitpath(self): """ p.splitpath() -> Return (p.directory, p.basename). """ parent, child = os.path.split(self._p) return Path(parent), child def splitdrive(self): """ p.splitdrive() -> Return (Path(p.drive), ). Split the drive specifier from this path. If there is no drive specifier, p.drive is empty, so the return value is simply (Path(''), p). This is always the case on Unix. """ drive, rel = os.path.splitdrive(self._p) return Path(drive), rel def splitext(self): """ p.splitext() -> Return (p.stripext(), p.ext). Split the filename extension from this path and return the two parts. Either part may be empty. The extension is everything from '.' to the end of the last path segment. """ filename, ext = os.path.splitext(self._p) return Path(filename), ext if hasattr(os.path, 'splitunc'): def splitunc(self): unc, rest = os.path.splitunc(self._p) return Path(unc), rest def _get_uncshare(self): unc, r = os.path.splitunc(self._p) return Path(unc) uncshare = property( _get_uncshare, None, None, """ The UNC mount point for this path. This is empty for paths on local drives. """) @staticmethod def join(*args): if args: return Path(args[0]).joinwith(args[1:]) return Path('') def joinwith(self, *args): """ Join two or more path components, adding a separator character (os.sep) if needed. Returns a new path object. """ return Path(os.path.join(self._p, *map(str, args))) def parts(self): """ Return a list of the path components in this path. The first item in the list will be a path. Its value will be either os.curdir, os.pardir, empty, or the root directory of this path (for example, '/' or 'C:\\'). The other items in the list will be strings. Path.join(*result) will yield the original path. """ parts = [] loc = self while loc != os.curdir and loc != os.pardir: prev = loc loc, child = prev.splitpath() if loc == prev: break parts.append(child) parts.append(loc) parts.reverse() return parts def relpath(self): """ Return this path as a relative path, based from the current working directory. """ return Path.cwd().relpathto(self) def relpathto(self, dest): """ Return a relative path from self to dest. If there is no relative path from self to dest, for example if they reside on different drives in Windows, then this returns dest.abspath(). """ origin = self.abspath() dest = Path(dest).abspath() orig_list = origin.normcase().parts() # Don't normcase dest! We want to preserve the case. dest_list = dest.parts() if orig_list[0] != os.path.normcase(dest_list[0]): # Can't get here from there. return dest # Find the location where the two paths start to differ. i = 0 for start_seg, dest_seg in zip(orig_list, dest_list): if start_seg != os.path.normcase(dest_seg): break i += 1 # Now i is the point where the two paths diverge. # Need a certain number of "os.pardir"s to work up # from the origin to the point of divergence. segments = [os.pardir] * (len(orig_list) - i) # Need to add the diverging part of dest_list. segments += dest_list[i:] if len(segments) == 0: # If they happen to be identical, use os.curdir. return Path(os.curdir) else: return Path(os.path.join(*segments)) # --- Listing, searching, walking, and matching def listdir(self): return [Path(p) for p in os.listdir(self._p)] def children(self, pattern=None): """ D.children() -> List of items in this directory, with this path prepended to them. Use D.files() or D.subdirs() instead if you want a listing of just files or just subdirectories. The elements of the list are path objects. With the optional 'pattern' argument, this only lists items whose names match the given pattern. """ names = os.listdir(self._p) if pattern is not None: names = fnmatch.filter(names, pattern) return [self / child for child in names] def subdirs(self, pattern=None): """ D.subdirs() -> List of this directory's subdirectories. The elements of the list are path objects. This does not walk recursively into subdirectories (but see path.walkdirs). With the optional 'pattern' argument, this only lists directories whose names match the given pattern. For example, d.subdirs('build-*'). """ return [p for p in self.children(pattern) if p.isdir()] def files(self, pattern=None): """ D.files() -> List of the files in this directory. The elements of the list are path objects. This does not walk into subdirectories (see path.walkfiles). With the optional 'pattern' argument, this only lists files whose names match the given pattern. For example, d.files('*.pyc'). """ return [p for p in self.children(pattern) if p.isfile()] def walk(self, pattern=None): """ D.walk() -> iterator over files and subdirs, recursively. The iterator yields path objects naming each child item of this directory and its descendants, including the starting path. This requires that D.isdir(). This performs a depth-first traversal of the directory tree. Each directory is returned just before all its children. """ for child in self.children(): if pattern is None or child.fnmatch(pattern): yield child if child.isdir(): for item in child.walk(pattern): yield item def walkdirs(self, pattern=None): """ D.walkdirs() -> iterator over subdirs, recursively. With the optional 'pattern' argument, this yields only directories whose names match the given pattern. For example, mydir.walkdirs('*test') yields only directories with names ending in 'test'. """ for child in self.subdirs(): if pattern is None or child.fnmatch(pattern): yield child for subsubdir in child.walkdirs(pattern): yield subsubdir def walkfiles(self, pattern=None): """ D.walkfiles() -> iterator over files in D, recursively. The optional argument, pattern, limits the results to files with names that match the pattern. For example, mydir.walkfiles('*.tmp') yields only files with the .tmp extension. """ for child in self.children(): if child.isfile(): if pattern is None or child.fnmatch(pattern): yield child elif child.isdir(): for f in child.walkfiles(pattern): yield f def fnmatch(self, pattern): """ Return True if self.name matches the given pattern. pattern - A filename pattern with wildcards, for example '*.py'. """ return fnmatch.fnmatch(self.basename, pattern) def glob(self, pattern): """ Return a list of path objects that match the pattern. pattern - a path relative to this directory, with wildcards. For example, path('/users').glob('*/bin/*') returns a list of all the files users have in their bin directories. """ return map(Path, glob.glob((self / pattern)._p)) # --- Reading or writing an entire file at once. def open(self, mode='r'): """ Open this file. Return a file object. """ return file(self._p, mode) def get_file_bytes(self): """ Open this file, read all bytes, return them as a string. """ f = self.open('rb') try: return f.read() finally: f.close() def write_file_bytes(self, bytes, append=False): """ Open this file and write the given bytes to it. Default behavior is to overwrite any existing file. Call this with write_bytes(bytes, append=True) to append instead. """ if append: mode = 'ab' else: mode = 'wb' f = self.open(mode) try: f.write(bytes) finally: f.close() def get_file_text(self, encoding=None, errors='strict'): """ Open this file, read it in, return the content as a string. This uses 'U' mode in Python 2.3 and later, so '\r\n' and '\r' are automatically translated to '\n'. Optional arguments: encoding - The Unicode encoding (or character set) of the file. If present, the content of the file is decoded and returned as a unicode object; otherwise it is returned as an 8-bit str. errors - How to handle Unicode errors; see help(str.decode) for the options. Default is 'strict'. """ if encoding is None: # 8-bit f = self.open(_textmode) try: return f.read() finally: f.close() else: # Unicode f = codecs.open(self._p, 'r', encoding, errors) # (Note - Can't use 'U' mode here, since codecs.open # doesn't support 'U' mode, even in Python 2.3.) try: t = f.read() finally: f.close() return (t.replace(u'\r\n', u'\n') .replace(u'\r\x85', u'\n') .replace(u'\r', u'\n') .replace(u'\x85', u'\n') .replace(u'\u2028', u'\n')) def write_file_text(self, text, encoding=None, errors='strict', linesep=os.linesep, append=False): """ Write the given text to this file. The default behavior is to overwrite any existing file; to append instead, use the 'append=True' keyword argument. There are two differences between path.write_file_text() and path.write_file_bytes(): newline handling and Unicode handling. See below. Parameters: - text - str/unicode - The text to be written. - encoding - str - The Unicode encoding that will be used. This is ignored if 'text' isn't a Unicode string. - errors - str - How to handle Unicode encoding errors. Default is 'strict'. See help(unicode.encode) for the options. This is ignored if 'text' isn't a Unicode string. - linesep - keyword argument - str/unicode - The sequence of characters to be used to mark end-of-line. The default is os.linesep. You can also specify None; this means to leave all newlines as they are in 'text'. - append - keyword argument - bool - Specifies what to do if the file already exists (True: append to the end of it; False: overwrite it.) The default is False. --- Newline handling. write_text() converts all standard end-of-line sequences ('\n', '\r', and '\r\n') to your platform's default end-of-line sequence (see os.linesep; on Windows, for example, the end-of-line marker is '\r\n'). If you don't like your platform's default, you can override it using the 'linesep=' keyword argument. If you specifically want write_text() to preserve the newlines as-is, use 'linesep=None'. This applies to Unicode text the same as to 8-bit text, except there are three additional standard Unicode end-of-line sequences: u'\x85', u'\r\x85', and u'\u2028'. (This is slightly different from when you open a file for writing with fopen(filename, "w") in C or file(filename, 'w') in Python.) --- Unicode If 'text' isn't Unicode, then apart from newline handling, the bytes are written verbatim to the file. The 'encoding' and 'errors' arguments are not used and must be omitted. If 'text' is Unicode, it is first converted to bytes using the specified 'encoding' (or the default encoding if 'encoding' isn't specified). The 'errors' argument applies only to this conversion. """ if isinstance(text, unicode): if linesep is not None: # Convert all standard end-of-line sequences to # ordinary newline characters. text = (text.replace(u'\r\n', u'\n') .replace(u'\r\x85', u'\n') .replace(u'\r', u'\n') .replace(u'\x85', u'\n') .replace(u'\u2028', u'\n')) text = text.replace(u'\n', linesep) if encoding is None: encoding = sys.getdefaultencoding() bytes = text.encode(encoding, errors) else: # It is an error to specify an encoding if 'text' is # an 8-bit string. assert encoding is None if linesep is not None: text = (text.replace('\r\n', '\n') .replace('\r', '\n')) bytes = text.replace('\n', linesep) self.write_file_bytes(bytes, append) def get_file_lines(self, encoding=None, errors='strict', retain=True): """ Open this file, read all lines, return them in a list. Optional arguments: encoding - The Unicode encoding (or character set) of the file. The default is None, meaning the content of the file is read as 8-bit characters and returned as a list of (non-Unicode) str objects. errors - How to handle Unicode errors; see help(str.decode) for the options. Default is 'strict' retain - If true, retain newline characters; but all newline character combinations ('\r', '\n', '\r\n') are translated to '\n'. If false, newline characters are stripped off. Default is True. This uses 'U' mode in Python 2.3 and later. """ if encoding is None and retain: f = self.open(_textmode) try: return f.readlines() finally: f.close() else: return self.get_file_text(encoding, errors).splitlines(retain) def write_file_lines(self, lines, encoding=None, errors='strict', linesep=os.linesep, append=False): """ Write the given lines of text to this file. By default this overwrites any existing file at this path. This puts a platform-specific newline sequence on every line. See 'linesep' below. lines - A list of strings. encoding - A Unicode encoding to use. This applies only if 'lines' contains any Unicode strings. errors - How to handle errors in Unicode encoding. This also applies only to Unicode strings. linesep - The desired line-ending. This line-ending is applied to every line. If a line already has any standard line ending ('\r', '\n', '\r\n', u'\x85', u'\r\x85', u'\u2028'), that will be stripped off and this will be used instead. The default is os.linesep, which is platform-dependent ('\r\n' on Windows, '\n' on Unix, etc.) Specify None to write the lines as-is, like file.writelines(). Use the keyword argument append=True to append lines to the file. The default is to overwrite the file. Warning: When you use this with Unicode data, if the encoding of the existing data in the file is different from the encoding you specify with the encoding= parameter, the result is mixed-encoding data, which can really confuse someone trying to read the file later. """ if append: mode = 'ab' else: mode = 'wb' f = self.open(mode) try: for line in lines: isUnicode = isinstance(line, unicode) if linesep is not None: # Strip off any existing line-end and add the # specified linesep string. if isUnicode: if line[-2:] in (u'\r\n', u'\x0d\x85'): line = line[:-2] elif line[-1:] in (u'\r', u'\n', u'\x85', u'\u2028'): line = line[:-1] else: if line[-2:] == '\r\n': line = line[:-2] elif line[-1:] in ('\r', '\n'): line = line[:-1] line += linesep if isUnicode: if encoding is None: encoding = sys.getdefaultencoding() line = line.encode(encoding, errors) f.write(line) finally: f.close() # --- Methods for querying the filesystem. def exists(self): return os.path.exists(self._p) def isabs(self): return os.path.isabs(self._p) def isdir(self): return os.path.isdir(self._p) def isfile(self): return os.path.isfile(self._p) def islink(self): return os.path.islink(self._p) def ismount(self): return os.path.ismount(self._p) if hasattr(os.path, 'samefile'): def samefile(self): return os.path.samefile(self._p) def atime(self): return os.path.getatime(self._p) def mtime(self): return os.path.getmtime(self._p) if hasattr(os.path, 'getctime'): def ctime(self): return os.path.getctime(self._p) def getsize(self): return os.path.getsize(self._p) if hasattr(os, 'access'): def access(self, mode): """ Return true if current user has access to this path. mode - One of the constants os.F_OK, os.R_OK, os.W_OK, os.X_OK """ return os.access(self._p, mode) def stat(self): """ Perform a stat() system call on this path. """ return os.stat(self._p) def lstat(self): """ Like path.stat(), but do not follow symbolic links. """ return os.lstat(self._p) if hasattr(os, 'statvfs'): def statvfs(self): """ Perform a statvfs() system call on this path. """ return os.statvfs(self._p) if hasattr(os, 'pathconf'): def pathconf(self, name): return os.pathconf(self._p, name) # --- Modifying operations on files and directories def utime(self, times): """ Set the access and modified times of this file. """ os.utime(self._p, times) def chmod(self, mode): os.chmod(self._p, mode) if hasattr(os, 'chown'): def chown(self, uid, gid): os.chown(self._p, uid, gid) def rename(self, new): os.rename(self._p, _strpath(new)) def renames(self, new): os.renames(self._p, _strpath(new)) # --- Create/delete operations on directories def mkdir(self, mode=0777): os.mkdir(self._p, mode) def makedirs(self, mode=0777): os.makedirs(self._p, mode) def rmdir(self): os.rmdir(self._p) def removedirs(self): os.removedirs(self._p) # --- Modifying operations on files def touch(self, mode=None): """ Set the access/modified times of this file to the current time. Create the file if it does not exist. The file mode is only set if the file must be created. The mode argument can be None, in which case the current umask is used. """ if mode is None: mode = os.umask(0) os.umask(mode) mode = mode ^ 0777 fd = os.open(self._p, os.O_WRONLY | os.O_CREAT, mode) os.close(fd) self.utime(None) def remove(self): os.remove(self._p) def unlink(self): os.unlink(self._p) # --- Links if hasattr(os, 'link'): def link(self, newpath): """ Create a hard link at 'newpath', pointing to this file. """ os.link(self._p, _strpath(newpath)) if hasattr(os, 'symlink'): def symlink(self, newlink): """ Create a symbolic link at 'newlink', pointing here. """ os.symlink(self._p, _strpath(newlink)) if hasattr(os, 'readlink'): def readlink(self): """ Return the path to which this symbolic link points. The result may be an absolute or a relative path. """ return Path(os.readlink(self._p)) def readlinkabs(self): """ Return the path to which this symbolic link points. The result is always an absolute path. """ p = self.readlink() if p.isabs(): return p else: return (self.directory / p).abspath() # --- High-level shutils functions def copyfile(self, dst): return shutil.copyfile(self._p, _strpath(dst)) def copymode(self, dst): return shutil.copymode(self._p, _strpath(dst)) def copystat(self, dst): return shutil.copystat(self._p, _strpath(dst)) def copy(self, dst): return shutil.copy(self._p, _strpath(dst)) def copy2(self, dst): return shutil.copy2(self._p, _strpath(dst)) def copytree(self, dst, symlinks=False): return shutil.copytree(self._p, _strpath(dst), symlinks) def rmtree(self, ignore_errors=False, onerror=None): return shutil.rmtree(self._p, ignore_errors, onerror) def move(self, dst): return shutil.move(self._p, _strpath(dst)) # --- Special stuff from os if hasattr(os, 'chroot'): def chroot(self): os.chroot(self._p) if hasattr(os, 'startfile'): def startfile(self): os.startfile(self._p) --- NEW FILE: test_path.py --- """ test_path.py - Test the path module. This only runs on Posix and NT right now. I would like to have more tests. You can help! Just add appropriate pathnames for your platform (os.name) in each place where the p() function is called. Then send me the result. If you can't get the test to run at all on your platform, there's probably a bug in path.py -- please let me know! TempDirTestCase.testTouch() takes a while to run. It sleeps a few seconds to allow some time to pass between calls to check the modify time on files. URL: http://www.jorendorff.com/articles/python/path Author: Jason Orendorff Date: 7 Mar 2004 """ import unittest import codecs, os, random, shutil, tempfile, time from path import Path def p(**choices): """ Choose a value from several possible values, based on os.name """ return Path(choices[os.name]) class BasicTestCase(unittest.TestCase): def testRelpath(self): root = p(nt='C:\\', posix='/') foo = root / 'foo' quux = foo / 'quux' bar = foo / 'bar' boz = bar / 'Baz' / 'Boz' up = Path(os.pardir) # basics self.assertEqual(root.relpathto(boz), Path('foo')/'bar'/'Baz'/'Boz') self.assertEqual(bar.relpathto(boz), Path('Baz')/'Boz') self.assertEqual(quux.relpathto(boz), up/'bar'/'Baz'/'Boz') self.assertEqual(boz.relpathto(quux), up/up/up/'quux') self.assertEqual(boz.relpathto(bar), up/up) # x.relpathto(x) == curdir self.assertEqual(root.relpathto(root), Path()) self.assertEqual(boz.relpathto(boz), Path()) # Make sure case is properly noted (or ignored) self.assertEqual(boz.relpathto(boz.normcase()), Path()) # relpath() cwd = Path.cwd() self.assertEqual(boz.relpath(), cwd.relpathto(boz)) if os.name == 'nt': # Check relpath across drives. d = Path('D:\\') self.assertEqual(d.relpathto(boz), boz) def testProperties(self): # Create sample Path object. f = p(nt='C:\\Program Files\\Python\\Lib\\xyzzy.py', posix='/usr/local/python/lib/xyzzy.py') # .directory self.assertEqual(f.directory, p(nt='C:\\Program Files\\Python\\Lib', posix='/usr/local/python/lib')) # .basename self.assertEqual(f.basename, 'xyzzy.py') self.assertEqual(f.directory.basename, str(p(nt='Lib', posix='lib'))) # .ext self.assertEqual(f.ext, '.py') self.assertEqual(f.directory.ext, '') # .drive self.assertEqual(f.drive, str(p(nt='C:', posix=''))) def testMethods(self): # .abspath() self.assertEqual(Path().abspath(), Path.cwd()) # .getcwd() cwd = Path.cwd() self.assert_(isinstance(cwd, Path)) self.assertEqual(cwd, Path.cwd()) def testUNC(self): if hasattr(os.path, 'splitunc'): p = Path(r'\\python1\share1\dir1\file1.txt') self.assert_(p.uncshare == r'\\python1\share1') self.assert_(p.splitunc() == os.path.splitunc(str(p))) class TempDirTestCase(unittest.TestCase): def setUp(self): # Create a temporary directory. f = tempfile.mktemp() system_tmp_dir = os.path.dirname(f) my_dir = 'testpath_tempdir_' + str(random.random())[2:] self.tempdir = os.path.join(system_tmp_dir, my_dir) os.mkdir(self.tempdir) def tearDown(self): shutil.rmtree(self.tempdir) def testTouch(self): # NOTE: This test takes a long time to run (~10 seconds). # It sleeps several seconds because on Windows, the resolution # of a file's mtime and ctime is about 2 seconds. # # atime isn't tested because on Windows the resolution of atime # is something like 24 hours. d = Path(self.tempdir) f = d / 'test.txt' t0 = time.time() - 3 f.touch() t1 = time.time() + 3 try: self.assert_(f.exists()) self.assert_(f.isfile()) self.assertEqual(f.getsize(), 0) self.assert_(t0 <= f.mtime() <= t1) if hasattr(os.path, 'getctime'): ct = f.ctime() self.assert_(t0 <= ct <= t1) time.sleep(4) fobj = f.open('ab') fobj.write('some bytes') fobj.close() time.sleep(4) t2 = time.time() - 3 f.touch() t3 = time.time() + 3 assert t0 <= t1 < t2 <= t3 # sanity check self.assert_(f.exists()) self.assert_(f.isfile()) self.assertEqual(f.getsize(), 10) self.assert_(t2 <= f.mtime() <= t3) if hasattr(os.path, 'getctime'): ct2 = f.ctime() if os.name == 'nt': # On Windows, "ctime" is CREATION time self.assertEqual(ct, ct2) self.assert_(ct2 < t2) else: # On other systems, it might be the CHANGE time # (especially on Unix, time of inode changes) self.failUnless(ct == ct2 or ct2 == f.mtime()) finally: f.remove() def testListing(self): d = Path(self.tempdir) self.assertEqual(d.listdir(), []) f = 'testfile.txt' af = d / f self.assertEqual(str(af), os.path.join(str(d), f)) af.touch() try: self.assert_(af.exists()) self.assertEqual(d.listdir(), [Path(f)]) # .glob() self.assertEqual(d.glob('testfile.txt'), [af]) self.assertEqual(d.glob('test*.txt'), [af]) self.assertEqual(d.glob('*.txt'), [af]) self.assertEqual(d.glob('*txt'), [af]) self.assertEqual(d.glob('*'), [af]) self.assertEqual(d.glob('*.html'), []) self.assertEqual(d.glob('testfile'), []) finally: af.remove() # Try a test with 20 files files = [d / ('%d.txt' % i) for i in range(20)] for f in files: fobj = f.open('w') fobj.write('some text\n') fobj.close() try: files2 = d.children() files.sort() files2.sort() self.assertEqual(files, files2) finally: for f in files: try: f.remove() except: pass def testMakeDirs(self): d = Path(self.tempdir) # Placeholder file so that when removedirs() is called, # it doesn't remove the temporary directory itself. tempf = d / 'temp.txt' tempf.touch() try: foo = d / 'foo' boz = foo / 'bar' / 'baz' / 'boz' boz.makedirs() try: self.assert_(boz.isdir()) finally: boz.removedirs() self.failIf(foo.exists()) self.assert_(d.exists()) foo.mkdir(0750) boz.makedirs(0700) try: self.assert_(boz.isdir()) finally: boz.removedirs() self.failIf(foo.exists()) self.assert_(d.exists()) finally: os.remove(str(tempf)) def assertSetsEqual(self, a, b): ad = {} for i in a: ad[i] = None bd = {} for i in b: bd[i] = None self.assertEqual(ad, bd) def testShutil(self): # Note: This only tests the methods exist and do roughly what # they should, neglecting the details as they are shutil's # responsibility. d = Path(self.tempdir) testDir = d / 'testdir' testFile = testDir / 'testfile.txt' testA = testDir / 'A' testCopy = testA / 'testcopy.txt' testLink = testA / 'testlink.txt' testB = testDir / 'B' testC = testB / 'C' testCopyOfLink = testC / testA.relpathto(testLink) # Create test dirs and a file testDir.mkdir() testA.mkdir() testB.mkdir() f = testFile.open('w') f.write('x' * 10000) f.close() # Test simple file copying. testFile.copyfile(testCopy) self.assert_(testCopy.isfile()) self.assert_(testFile.get_file_bytes() == testCopy.get_file_bytes()) # Test copying into a directory. testCopy2 = testA / testFile.basename testFile.copy(testA) self.assert_(testCopy2.isfile()) self.assert_(testFile.get_file_bytes() == testCopy2.get_file_bytes()) # Make a link for the next test to use. if hasattr(os, 'symlink'): testFile.symlink(testLink) else: testFile.copy(testLink) # fallback # Test copying directory tree. testA.copytree(testC) self.assert_(testC.isdir()) self.assertSetsEqual( testC.children(), [testC / testCopy.basename, testC / testFile.basename, testCopyOfLink]) self.assert_(not testCopyOfLink.islink()) # Clean up for another try. testC.rmtree() self.assert_(not testC.exists()) # Copy again, preserving symlinks. testA.copytree(testC, True) self.assert_(testC.isdir()) self.assertSetsEqual( testC.children(), [testC / testCopy.basename, testC / testFile.basename, testCopyOfLink]) if hasattr(os, 'symlink'): self.assert_(testCopyOfLink.islink()) self.assert_(testCopyOfLink.readlink() == testFile) # Clean up. testDir.rmtree() self.assert_(not testDir.exists()) self.assertList(d.children(), []) def assertList(self, listing, expected): listing = list(listing) listing.sort() expected = list(expected) expected.sort() self.assertEqual(listing, expected) def testPatterns(self): d = Path(self.tempdir) names = [ 'x.tmp', 'x.xtmp', 'x2g', 'x22', 'x.txt' ] dirs = [d, d/'xdir', d/'xdir.tmp', d/'xdir.tmp'/'xsubdir'] for e in dirs: if not e.isdir(): e.makedirs() for name in names: (e/name).touch() self.assertList(d.children('*.tmp'), [d/'x.tmp', d/'xdir.tmp']) self.assertList(d.files('*.tmp'), [d/'x.tmp']) self.assertList(d.subdirs('*.tmp'), [d/'xdir.tmp']) self.assertList(d.walk(), [e for e in dirs if e != d] + [e/n for e in dirs for n in names]) self.assertList(d.walk('*.tmp'), [e/'x.tmp' for e in dirs] + [d/'xdir.tmp']) self.assertList(d.walkfiles('*.tmp'), [e/'x.tmp' for e in dirs]) self.assertList(d.walkdirs('*.tmp'), [d/'xdir.tmp']) def testUnicode(self): d = Path(self.tempdir) p = d/'unicode.txt' def test(enc): """ Test that Path works with the specified encoding, which must be capable of representing the entire range of Unicode codepoints. """ given = (u'Hello world\n' u'\u0d0a\u0a0d\u0d15\u0a15\r\n' u'\u0d0a\u0a0d\u0d15\u0a15\x85' u'\u0d0a\u0a0d\u0d15\u0a15\u2028' u'\r' u'hanging') clean = (u'Hello world\n' u'\u0d0a\u0a0d\u0d15\u0a15\n' u'\u0d0a\u0a0d\u0d15\u0a15\n' u'\u0d0a\u0a0d\u0d15\u0a15\n' u'\n' u'hanging') givenLines = [ u'Hello world\n', u'\u0d0a\u0a0d\u0d15\u0a15\r\n', u'\u0d0a\u0a0d\u0d15\u0a15\x85', u'\u0d0a\u0a0d\u0d15\u0a15\u2028', u'\r', u'hanging'] expectedLines = [ u'Hello world\n', u'\u0d0a\u0a0d\u0d15\u0a15\n', u'\u0d0a\u0a0d\u0d15\u0a15\n', u'\u0d0a\u0a0d\u0d15\u0a15\n', u'\n', u'hanging'] expectedLines2 = [ u'Hello world', u'\u0d0a\u0a0d\u0d15\u0a15', u'\u0d0a\u0a0d\u0d15\u0a15', u'\u0d0a\u0a0d\u0d15\u0a15', u'', u'hanging'] # write bytes manually to file f = codecs.open(str(p), 'w', enc) f.write(given) f.close() # test all 3 path read-fully functions, including # Path.lines() in unicode mode. self.assertEqual(p.get_file_bytes(), given.encode(enc)) self.assertEqual(p.get_file_text(enc), clean) self.assertEqual(p.get_file_lines(enc), expectedLines) self.assertEqual(p.get_file_lines(enc, retain=False), expectedLines2) # If this is UTF-16, that's enough. # The rest of these will unfortunately fail because append=True mode # causes an extra BOM to be written in the middle of the file. # UTF-16 is the only encoding that has this problem. if enc == 'UTF-16': return # Write Unicode to file using Path.write_text(). cleanNoHanging = clean + u'\n' # This test doesn't work with a hanging line. p.write_file_text(cleanNoHanging, enc) p.write_file_text(cleanNoHanging, enc, append=True) # Check the result. expectedBytes = 2 * cleanNoHanging.replace('\n', os.linesep).encode(enc) expectedLinesNoHanging = expectedLines[:] expectedLinesNoHanging[-1] += '\n' self.assertEqual(p.get_file_bytes(), expectedBytes) self.assertEqual(p.get_file_text(enc), 2 * cleanNoHanging) self.assertEqual(p.get_file_lines(enc), 2 * expectedLinesNoHanging) self.assertEqual(p.get_file_lines(enc, retain=False), 2 * expectedLines2) # Write Unicode to file using Path.write_file_lines(). # The output in the file should be exactly the same as last time. p.write_file_lines(expectedLines, enc) p.write_file_lines(expectedLines2, enc, append=True) # Check the result. self.assertEqual(p.get_file_bytes(), expectedBytes) # Now: same test, but using various newline sequences. # If linesep is being properly applied, these will be converted # to the platform standard newline sequence. p.write_file_lines(givenLines, enc) p.write_file_lines(givenLines, enc, append=True) # Check the result. self.assertEqual(p.get_file_bytes(), expectedBytes) # Same test, using newline sequences that are different # from the platform default. def testLinesep(eol): p.write_file_lines(givenLines, enc, linesep=eol) p.write_file_lines(givenLines, enc, linesep=eol, append=True) expected = 2 * cleanNoHanging.replace(u'\n', eol).encode(enc) self.assertEqual(p.get_file_bytes(), expected) testLinesep(u'\n') testLinesep(u'\r') testLinesep(u'\r\n') testLinesep(u'\x0d\x85') # Again, but with linesep=None. p.write_file_lines(givenLines, enc, linesep=None) p.write_file_lines(givenLines, enc, linesep=None, append=True) # Check the result. expectedBytes = 2 * given.encode(enc) self.assertEqual(p.get_file_bytes(), expectedBytes) self.assertEqual(p.get_file_text(enc), 2 * clean) expectedResultLines = expectedLines[:] expectedResultLines[-1] += expectedLines[0] expectedResultLines += expectedLines[1:] self.assertEqual(p.get_file_lines(enc), expectedResultLines) test('UTF-8') test('UTF-16BE') test('UTF-16LE') test('UTF-16') if __name__ == '__main__': unittest.main() From birkenfeld at users.sourceforge.net Wed Jul 20 00:20:24 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Tue, 19 Jul 2005 15:20:24 -0700 Subject: [Python-checkins] python/dist/src/Python bltinmodule.c, 2.321, 2.322 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6123/Python Modified Files: bltinmodule.c Log Message: Fix cleanup DECREF logic in builtin_filter function. Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.321 retrieving revision 2.322 diff -u -d -r2.321 -r2.322 --- bltinmodule.c 11 Mar 2005 06:49:40 -0000 2.321 +++ bltinmodule.c 19 Jul 2005 22:20:20 -0000 2.322 @@ -210,10 +210,15 @@ if (PyTuple_Check(seq)) return filtertuple(func, seq); + /* Pre-allocate argument list tuple. */ + arg = PyTuple_New(1); + if (arg == NULL) + return NULL; + /* Get iterator. */ it = PyObject_GetIter(seq); if (it == NULL) - return NULL; + goto Fail_arg; /* Guess a result list size. */ len = PyObject_Size(seq); @@ -222,11 +227,6 @@ len = 8; /* arbitrary */ } - /* Pre-allocate argument list tuple. */ - arg = PyTuple_New(1); - if (arg == NULL) - goto Fail_arg; - /* Get a result list. */ if (PyList_Check(seq) && seq->ob_refcnt == 1) { /* Eww - can modify the list in-place. */ From birkenfeld at users.sourceforge.net Wed Jul 20 00:20:54 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Tue, 19 Jul 2005 15:20:54 -0700 Subject: [Python-checkins] python/dist/src/Python bltinmodule.c, 2.318, 2.318.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6347/Python Modified Files: Tag: release24-maint bltinmodule.c Log Message: Backport: fix cleanup DECREF logic in builtin_filter function. Index: bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.318 retrieving revision 2.318.2.1 diff -u -d -r2.318 -r2.318.2.1 --- bltinmodule.c 25 Aug 2004 10:42:41 -0000 2.318 +++ bltinmodule.c 19 Jul 2005 22:20:44 -0000 2.318.2.1 @@ -147,10 +147,15 @@ if (PyTuple_Check(seq)) return filtertuple(func, seq); + /* Pre-allocate argument list tuple. */ + arg = PyTuple_New(1); + if (arg == NULL) + return NULL; + /* Get iterator. */ it = PyObject_GetIter(seq); if (it == NULL) - return NULL; + goto Fail_arg; /* Guess a result list size. */ len = PyObject_Size(seq); @@ -159,11 +164,6 @@ len = 8; /* arbitrary */ } - /* Pre-allocate argument list tuple. */ - arg = PyTuple_New(1); - if (arg == NULL) - goto Fail_arg; - /* Get a result list. */ if (PyList_Check(seq) && seq->ob_refcnt == 1) { /* Eww - can modify the list in-place. */ From fdrake at users.sourceforge.net Wed Jul 20 05:49:45 2005 From: fdrake at users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 19 Jul 2005 20:49:45 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib librandom.tex,1.38,1.39 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9070/lib Modified Files: librandom.tex Log Message: fix markup nits Index: librandom.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/librandom.tex,v retrieving revision 1.38 retrieving revision 1.39 diff -u -d -r1.38 -r1.39 --- librandom.tex 28 Sep 2004 03:04:23 -0000 1.38 +++ librandom.tex 20 Jul 2005 03:49:42 -0000 1.39 @@ -159,8 +159,8 @@ population contains repeats, then each occurrence is a possible selection in the sample. - To choose a sample from a range of integers, use \function{xrange} - as an argument. This is especially fast and space efficient for + To choose a sample from a range of integers, use an \function{xrange()} + object as an argument. This is especially fast and space efficient for sampling from a large population: \code{sample(xrange(10000000), 60)}. \end{funcdesc} @@ -236,7 +236,7 @@ \begin{classdesc}{WichmannHill}{\optional{seed}} Class that implements the Wichmann-Hill algorithm as the core generator. -Has all of the same methods as \class{Random} plus the \method{whseed} +Has all of the same methods as \class{Random} plus the \method{whseed()} method described below. Because this class is implemented in pure Python, it is not threadsafe and may require locks between calls. The period of the generator is 6,953,607,871,644 which is small enough to @@ -246,7 +246,7 @@ \begin{funcdesc}{whseed}{\optional{x}} This is obsolete, supplied for bit-level compatibility with versions of Python prior to 2.1. - See \function{seed} for details. \function{whseed} does not guarantee + See \function{seed()} for details. \function{whseed()} does not guarantee that distinct integer arguments yield distinct internal states, and can yield no more than about 2**24 distinct internal states in all. \end{funcdesc} From fdrake at users.sourceforge.net Wed Jul 20 06:33:04 2005 From: fdrake at users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 19 Jul 2005 21:33:04 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref1.tex,1.15,1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16401/ref Modified Files: ref1.tex Log Message: add information about alternate implementations, noting that documentation for the implementation should be consulted (thanks to Evelyn Mitchell for suggesting this) Index: ref1.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref1.tex,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- ref1.tex 2 Jun 2005 13:50:19 -0000 1.15 +++ ref1.tex 20 Jul 2005 04:33:01 -0000 1.16 @@ -21,7 +21,7 @@ reference document --- the implementation may change, and other implementations of the same language may work differently. On the other hand, there is currently only one Python implementation in -widespread use (although a second one now exists!), and +widespread use (although alternate implementations exist), and its particular quirks are sometimes worth being mentioned, especially where the implementation imposes additional limitations. Therefore, you'll find short ``implementation notes'' sprinkled throughout the @@ -34,6 +34,56 @@ with the language definition. +\section{Alternate Implementations\label{implementations}} + +Though there is one Python implementation which is by far the most +popular, there are some alternate implementations which are of +particular interest to different audiences. + +Known implementations include: + +\begin{itemize} +\item[CPython] +This is the original and most-maintained implementation of Python, +written in C. New language features generally appear here first. + +\item[Jython] +Python implemented in Java. This implementation can be used as a +scripting language for Java applications, or can be used to create +applications using the Java class libraries. It is also often used to +create tests for Java libraries. More information can be found at +\ulink{the Jython website}{http://www.jython.org/}. + +\item[Python for .NET] +This implementation actually uses the CPython implementation, but is a +managed .NET application and makes .NET libraries available. This was +created by Brian Lloyd. For more information, see the \ulink{Python +for .NET home page}{http://www.zope.org/Members/Brian/PythonNet}. + +\item[IronPython] +An alternate Python for\ .NET. Unlike Python.NET, this is a complete +Python implementation that generates IL, and compiles Python code +directly to\ .NET assemblies. It was created by Jim Hugunin, the +original creator of Jython. For more information, see \ulink{the +IronPython website}{http://workspaces.gotdotnet.com/ironpython}. + +\item[PyPy] +An implementation of Python written in Python; even the bytecode +interpreter is written in Python. This is executed using CPython as +the underlying interpreter. One of the goals of the project is to +encourage experimentation with the language itself by making it easier +to modify the interpreter (since it is written in Python). Additional +information is available on \ulink{the PyPy project's home +page}{http://codespeak.net/pypy/}. +\end{itemize} + +Each of these implementations varies in some way from the language as +documented in this manual, or introduces specific information beyond +what's covered in the standard Python documentation. Please refer to +the implementation-specific documentation to determine what else you +need to know about the specific implementation you're using. + + \section{Notation\label{notation}} The descriptions of lexical analysis and syntax use a modified BNF From fdrake at users.sourceforge.net Wed Jul 20 06:33:51 2005 From: fdrake at users.sourceforge.net (fdrake@users.sourceforge.net) Date: Tue, 19 Jul 2005 21:33:51 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref1.tex, 1.14.28.1, 1.14.28.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16547/ref Modified Files: Tag: release24-maint ref1.tex Log Message: add information about alternate implementations, noting that documentation for the implementation should be consulted (thanks to Evelyn Mitchell for suggesting this; backported from trunk rev 1.16) Index: ref1.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref1.tex,v retrieving revision 1.14.28.1 retrieving revision 1.14.28.2 diff -u -d -r1.14.28.1 -r1.14.28.2 --- ref1.tex 2 Jun 2005 13:52:07 -0000 1.14.28.1 +++ ref1.tex 20 Jul 2005 04:33:49 -0000 1.14.28.2 @@ -21,7 +21,7 @@ reference document --- the implementation may change, and other implementations of the same language may work differently. On the other hand, there is currently only one Python implementation in -widespread use (although a second one now exists!), and +widespread use (although alternate implementations exist), and its particular quirks are sometimes worth being mentioned, especially where the implementation imposes additional limitations. Therefore, you'll find short ``implementation notes'' sprinkled throughout the @@ -34,6 +34,56 @@ with the language definition. +\section{Alternate Implementations\label{implementations}} + +Though there is one Python implementation which is by far the most +popular, there are some alternate implementations which are of +particular interest to different audiences. + +Known implementations include: + +\begin{itemize} +\item[CPython] +This is the original and most-maintained implementation of Python, +written in C. New language features generally appear here first. + +\item[Jython] +Python implemented in Java. This implementation can be used as a +scripting language for Java applications, or can be used to create +applications using the Java class libraries. It is also often used to +create tests for Java libraries. More information can be found at +\ulink{the Jython website}{http://www.jython.org/}. + +\item[Python for .NET] +This implementation actually uses the CPython implementation, but is a +managed .NET application and makes .NET libraries available. This was +created by Brian Lloyd. For more information, see the \ulink{Python +for .NET home page}{http://www.zope.org/Members/Brian/PythonNet}. + +\item[IronPython] +An alternate Python for\ .NET. Unlike Python.NET, this is a complete +Python implementation that generates IL, and compiles Python code +directly to\ .NET assemblies. It was created by Jim Hugunin, the +original creator of Jython. For more information, see \ulink{the +IronPython website}{http://workspaces.gotdotnet.com/ironpython}. + +\item[PyPy] +An implementation of Python written in Python; even the bytecode +interpreter is written in Python. This is executed using CPython as +the underlying interpreter. One of the goals of the project is to +encourage experimentation with the language itself by making it easier +to modify the interpreter (since it is written in Python). Additional +information is available on \ulink{the PyPy project's home +page}{http://codespeak.net/pypy/}. +\end{itemize} + +Each of these implementations varies in some way from the language as +documented in this manual, or introduces specific information beyond +what's covered in the standard Python documentation. Please refer to +the implementation-specific documentation to determine what else you +need to know about the specific implementation you're using. + + \section{Notation\label{notation}} The descriptions of lexical analysis and syntax use a modified BNF From creditcard at paypal.com Wed Jul 20 20:59:23 2005 From: creditcard at paypal.com (PayPal UPDATE) Date: Wed, 20 Jul 2005 20:59:23 +0200 (CEST) Subject: [Python-checkins] Update Credit/Debit CARD Message-ID: <20050720185923.B5E1C672C@wmphpp09.st2.lyceu.net> An HTML attachment was scrubbed... URL: http://mail.python.org/pipermail/python-checkins/attachments/20050720/6fb5dfbe/attachment.htm From doerwalter at users.sourceforge.net Thu Jul 21 00:15:42 2005 From: doerwalter at users.sourceforge.net (doerwalter@users.sourceforge.net) Date: Wed, 20 Jul 2005 15:15:42 -0700 Subject: [Python-checkins] python/dist/src/Lib codecs.py,1.45,1.46 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28950/Lib Modified Files: codecs.py Log Message: Make attributes and local variables in the StreamReader str objects instead of unicode objects, so that codecs that do a str->str decoding won't promote the result to unicode. This fixes SF bug #1241507. Index: codecs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/codecs.py,v retrieving revision 1.45 retrieving revision 1.46 diff -u -d -r1.45 -r1.46 --- codecs.py 21 Apr 2005 21:42:35 -0000 1.45 +++ codecs.py 20 Jul 2005 22:15:39 -0000 1.46 @@ -229,7 +229,9 @@ self.stream = stream self.errors = errors self.bytebuffer = "" - self.charbuffer = u"" + # For str->str decoding this will stay a str + # For str->unicode decoding the first read will promote it to unicode + self.charbuffer = "" def decode(self, input, errors='strict'): raise NotImplementedError @@ -284,7 +286,7 @@ if chars < 0: # Return everything we've got result = self.charbuffer - self.charbuffer = u"" + self.charbuffer = "" else: # Return the first chars characters result = self.charbuffer[:chars] @@ -301,7 +303,7 @@ """ readsize = size or 72 - line = u"" + line = "" # If size is given, we call read() only once while True: data = self.read(readsize) @@ -309,7 +311,7 @@ # If we're at a "\r" read one extra character (which might # be a "\n") to get a proper line ending. If the stream is # temporarily exhausted we return the wrong line ending. - if data.endswith(u"\r"): + if data.endswith("\r"): data += self.read(size=1, chars=1) line += data @@ -319,7 +321,7 @@ line0withoutend = lines[0].splitlines(False)[0] if line0withend != line0withoutend: # We really have a line end # Put the rest back together and keep it until the next call - self.charbuffer = u"".join(lines[1:]) + self.charbuffer + self.charbuffer = "".join(lines[1:]) + self.charbuffer if keepends: line = line0withend else: From doerwalter at users.sourceforge.net Thu Jul 21 00:15:42 2005 From: doerwalter at users.sourceforge.net (doerwalter@users.sourceforge.net) Date: Wed, 20 Jul 2005 15:15:42 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_codecs.py, 1.23, 1.24 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28950/Lib/test Modified Files: test_codecs.py Log Message: Make attributes and local variables in the StreamReader str objects instead of unicode objects, so that codecs that do a str->str decoding won't promote the result to unicode. This fixes SF bug #1241507. Index: test_codecs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_codecs.py,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- test_codecs.py 21 Apr 2005 21:45:36 -0000 1.23 +++ test_codecs.py 20 Jul 2005 22:15:39 -0000 1.24 @@ -663,6 +663,22 @@ f = self.reader(self.stream) self.assertEquals(f.readlines(), [u'\ud55c\n', u'\uae00']) +class Str2StrTest(unittest.TestCase): + + def test_read(self): + sin = "\x80".encode("base64_codec") + reader = codecs.getreader("base64_codec")(StringIO.StringIO(sin)) + sout = reader.read() + self.assertEqual(sout, "\x80") + self.assert_(isinstance(sout, str)) + + def test_readline(self): + sin = "\x80".encode("base64_codec") + reader = codecs.getreader("base64_codec")(StringIO.StringIO(sin)) + sout = reader.readline() + self.assertEqual(sout, "\x80") + self.assert_(isinstance(sout, str)) + all_unicode_encodings = [ "ascii", "base64_codec", @@ -867,6 +883,7 @@ CodecTest, CodecsModuleTest, StreamReaderTest, + Str2StrTest, BasicUnicodeTest, BasicStrTest ) From doerwalter at users.sourceforge.net Thu Jul 21 00:52:11 2005 From: doerwalter at users.sourceforge.net (doerwalter@users.sourceforge.net) Date: Wed, 20 Jul 2005 15:52:11 -0700 Subject: [Python-checkins] python/dist/src/Lib codecs.py,1.35.2.7,1.35.2.8 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6952/Lib Modified Files: Tag: release24-maint codecs.py Log Message: Backport checkin: Make attributes and local variables in the StreamReader str objects instead of unicode objects, so that codecs that do a str->str decoding won't promote the result to unicode. This fixes SF bug #1241507. Index: codecs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/codecs.py,v retrieving revision 1.35.2.7 retrieving revision 1.35.2.8 diff -u -d -r1.35.2.7 -r1.35.2.8 --- codecs.py 21 Apr 2005 21:53:43 -0000 1.35.2.7 +++ codecs.py 20 Jul 2005 22:52:08 -0000 1.35.2.8 @@ -229,7 +229,9 @@ self.stream = stream self.errors = errors self.bytebuffer = "" - self.charbuffer = u"" + # For str->str decoding this will stay a str + # For str->unicode decoding the first read will promote it to unicode + self.charbuffer = "" def decode(self, input, errors='strict'): raise NotImplementedError @@ -284,7 +286,7 @@ if chars < 0: # Return everything we've got result = self.charbuffer - self.charbuffer = u"" + self.charbuffer = "" else: # Return the first chars characters result = self.charbuffer[:chars] @@ -301,7 +303,7 @@ """ readsize = size or 72 - line = u"" + line = "" # If size is given, we call read() only once while True: data = self.read(readsize) @@ -309,7 +311,7 @@ # If we're at a "\r" read one extra character (which might # be a "\n") to get a proper line ending. If the stream is # temporarily exhausted we return the wrong line ending. - if data.endswith(u"\r"): + if data.endswith("\r"): data += self.read(size=1, chars=1) line += data @@ -319,7 +321,7 @@ line0withoutend = lines[0].splitlines(False)[0] if line0withend != line0withoutend: # We really have a line end # Put the rest back together and keep it until the next call - self.charbuffer = u"".join(lines[1:]) + self.charbuffer + self.charbuffer = "".join(lines[1:]) + self.charbuffer if keepends: line = line0withend else: From doerwalter at users.sourceforge.net Thu Jul 21 00:52:11 2005 From: doerwalter at users.sourceforge.net (doerwalter@users.sourceforge.net) Date: Wed, 20 Jul 2005 15:52:11 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_codecs.py, 1.15.2.5, 1.15.2.6 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6952/Lib/test Modified Files: Tag: release24-maint test_codecs.py Log Message: Backport checkin: Make attributes and local variables in the StreamReader str objects instead of unicode objects, so that codecs that do a str->str decoding won't promote the result to unicode. This fixes SF bug #1241507. Index: test_codecs.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_codecs.py,v retrieving revision 1.15.2.5 retrieving revision 1.15.2.6 diff -u -d -r1.15.2.5 -r1.15.2.6 --- test_codecs.py 21 Apr 2005 21:53:43 -0000 1.15.2.5 +++ test_codecs.py 20 Jul 2005 22:52:09 -0000 1.15.2.6 @@ -665,6 +665,22 @@ f = self.reader(self.stream) self.assertEquals(f.readlines(), [u'\ud55c\n', u'\uae00']) +class Str2StrTest(unittest.TestCase): + + def test_read(self): + sin = "\x80".encode("base64_codec") + reader = codecs.getreader("base64_codec")(StringIO.StringIO(sin)) + sout = reader.read() + self.assertEqual(sout, "\x80") + self.assert_(isinstance(sout, str)) + + def test_readline(self): + sin = "\x80".encode("base64_codec") + reader = codecs.getreader("base64_codec")(StringIO.StringIO(sin)) + sout = reader.readline() + self.assertEqual(sout, "\x80") + self.assert_(isinstance(sout, str)) + def test_main(): test_support.run_unittest( UTF16Test, @@ -677,7 +693,8 @@ NameprepTest, CodecTest, CodecsModuleTest, - StreamReaderTest + StreamReaderTest, + Str2StrTest ) From pje at users.sourceforge.net Thu Jul 21 02:49:48 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 20 Jul 2005 17:49:48 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.15, 1.16 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30770/setuptools/command Modified Files: easy_install.py Log Message: Fixed installing extra ``.pyc`` or ``.pyo`` files for scripts with ``.py`` extensions. Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- easy_install.py 18 Jul 2005 02:06:30 -0000 1.15 +++ easy_install.py 21 Jul 2005 00:49:45 -0000 1.16 @@ -822,7 +822,7 @@ to_compile = [] def pf(src,dst): - if dst.endswith('.py'): + if dst.endswith('.py') and not src.startswith('EGG-INFO/'): to_compile.append(dst) self.unpack_progress(src,dst) return not self.dry_run and dst or None From pje at users.sourceforge.net Thu Jul 21 02:51:09 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 20 Jul 2005 17:51:09 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command test.py, 1.3, 1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31008/setuptools/command Modified Files: test.py Log Message: Make 'test' command work correctly with the 0.6 WorkingSet class. Index: test.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/test.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- test.py 6 Jul 2005 03:46:16 -0000 1.3 +++ test.py 21 Jul 2005 00:51:07 -0000 1.4 @@ -1,6 +1,7 @@ from setuptools import Command from distutils.errors import DistutilsOptionError import sys +from pkg_resources import * class test(Command): @@ -38,7 +39,6 @@ if self.verbose: self.test_args.insert(0,'--verbose') - def run(self): # Ensure metadata is up-to-date self.run_command('egg_info') @@ -56,19 +56,19 @@ self.run_tests() def run_tests(self): - import unittest, pkg_resources + import unittest old_path = sys.path[:] ei_cmd = self.get_finalized_command("egg_info") - try: - # put the egg on sys.path, and require() it - sys.path.insert(0, ei_cmd.egg_base) - pkg_resources.require( - "%s==%s" % (ei_cmd.egg_name, ei_cmd.egg_version) - ) - unittest.main(None, None, [unittest.__file__]+self.test_args) - finally: - sys.path[:] = old_path - # XXX later this might need to save/restore the WorkingSet + path_item = normalize_path(ei_cmd.egg_base) + metadata = PathMetadata( + path_item, normalize_path(ei_cmd.egg_info) + ) + dist = Distribution(path_item, metadata, project_name=ei_cmd.egg_name) + working_set.add(dist) + require(str(dist.as_requirement())) + unittest.main(None, None, [unittest.__file__]+self.test_args) + + From pje at users.sourceforge.net Thu Jul 21 03:11:34 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 20 Jul 2005 18:11:34 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.45, 1.46 api_tests.txt, 1.1, 1.2 pkg_resources.py, 1.48, 1.49 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2980 Modified Files: EasyInstall.txt api_tests.txt pkg_resources.py Log Message: Added support for handling MacOS platform information in ``.egg`` filenames, based on a contribution by Kevin Dangoor. (NOTE: this may make eggs compiled for OS X with older versions of setuptools unusable! If you have eggs whose file/directory names end with ``-darwin-*.egg``, you will probably need to rename them to ``-macosx-*.egg``, substituting your current Mac OS version for the darwin kernel version in the version number. Or, you can just delete and reinstall the problematic eggs.) Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.45 retrieving revision 1.46 diff -u -d -r1.45 -r1.46 --- EasyInstall.txt 18 Jul 2005 02:06:15 -0000 1.45 +++ EasyInstall.txt 21 Jul 2005 01:11:31 -0000 1.46 @@ -619,6 +619,17 @@ rate don't expect it to work with all packages. 0.6a1 + * Added support for handling MacOS platform information in ``.egg`` filenames, + based on a contribution by Kevin Dangoor. (NOTE: this may make eggs + compiled for OS X with older versions of setuptools unusable! If you have + eggs whose file/directory names end with ``-darwin-*.egg``, you will + probably need to rename them to ``-macosx-*.egg``, substituting your current + Mac OS version for the darwin kernel version in the version number. Or, you + can just delete and reinstall the problematic eggs.) + + * Fixed installing extra ``.pyc`` or ``.pyo`` files for scripts with ``.py`` + extensions. + * Added ``--site-dirs`` option to allow adding custom "site" directories. Made ``easy-install.pth`` work in platform-specific alternate site directories (e.g. ``~/Library/Python/2.x/site-packages``). Index: api_tests.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/api_tests.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- api_tests.txt 18 Jul 2005 01:39:45 -0000 1.1 +++ api_tests.txt 21 Jul 2005 01:11:31 -0000 1.2 @@ -245,3 +245,38 @@ >>> ws.add(Distribution(project_name="JustATest", version="0.99")) Added JustATest 0.99 + +Platform Compatibility Rules +---------------------------- + +On the Mac, there are potential compatibility issues for modules compiled +on newer versions of Mac OS X than what the user is running. Additionally, +Mac OS X will soon have two platforms to contend with: Intel and PowerPC. + +Basic equality works as on other platforms:: + + >>> from pkg_resources import compatible_platforms as cp + >>> reqd = 'macosx-10.4.2-Power_Macintosh' + >>> cp(reqd, reqd) + True + >>> cp("win32", reqd) + False + +Distributions made on other machine types are not compatible:: + + >>> cp("macosx-10.4.2-Intel", reqd) + False + +Distributions made on earlier versions of the OS are compatible, as +long as they are from the same top-level version. The patchlevel version +number does not matter:: + + >>> cp("macosx-10.4.5-Power_Macintosh", reqd) + True + >>> cp("macosx-10.3.5-Power_Macintosh", reqd) + True + >>> cp("macosx-10.5.5-Power_Macintosh", reqd) + False + >>> cp("macosx-9.5.5-Power_Macintosh", reqd) + False + Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.48 retrieving revision 1.49 diff -u -d -r1.48 -r1.49 --- pkg_resources.py 18 Jul 2005 02:28:14 -0000 1.48 +++ pkg_resources.py 21 Jul 2005 01:11:31 -0000 1.49 @@ -80,15 +80,47 @@ +def _macosx_vers(_cache=[]): + if not _cache: + info = os.popen('/usr/bin/sw_vers').read().splitlines() + for line in info: + key, value = line.split(None, 1) + if key == 'ProductVersion:': + _cache.append(value.strip().split(".")) + break + else: + raise ValueError, "What?!" + return _cache[0] + + def get_platform(): """Return this platform's string for platform-specific distributions XXX Currently this is the same as ``distutils.util.get_platform()``, but it needs some hacks for Linux and Mac OS X. """ + if sys.platform == "darwin": + try: + version = _macosx_vers() + machine = os.uname()[4].replace(" ", "_") + return "macosx-%d.%d.%d-%s" % (int(version[0]), int(version[1]), + int(version[2]), machine) + except ValueError: + # if someone is running a non-Mac darwin system, this will fall + # through to the default implementation + pass + from distutils.util import get_platform return get_platform() +macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)\.(\d+)-(.*)") +# XXX darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") + + + + + + def compatible_platforms(provided,required): """Can code for the `provided` platform run on the `required` platform? @@ -99,9 +131,37 @@ if provided is None or required is None or provided==required: return True # easy case - # XXX all the tricky cases go here + # Mac OS X special cases + reqMac = macosVersionString.match(required) + if reqMac: + provMac = macosVersionString.match(provided) + + # is this a Mac package? + if not provMac: + # XXX backward compatibility should go here! + return False + + # are they the same major version and machine type? + if provMac.group(1) != reqMac.group(1) or \ + provMac.group(4) != reqMac.group(4): + return False + + # is the required OS major update >= the provided one? + if int(provMac.group(2)) > int(reqMac.group(2)): + return False + + return True + + # XXX Linux and other platforms' special cases should go here return False + + + + + + + def run_script(dist_spec, script_name): """Locate distribution `dist_spec` and run its `script_name` script""" ns = sys._getframe(1).f_globals @@ -113,14 +173,6 @@ run_main = run_script # backward compatibility - - - - - - - - class IMetadataProvider: def has_metadata(name): @@ -151,17 +203,6 @@ - - - - - - - - - - - class IResourceProvider(IMetadataProvider): """An object that provides access to package resources""" From pje at users.sourceforge.net Thu Jul 21 06:51:07 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Wed, 20 Jul 2005 21:51:07 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools api_tests.txt, 1.2, 1.3 pkg_resources.py, 1.49, 1.50 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9649 Modified Files: api_tests.txt pkg_resources.py Log Message: Tweak Mac OS platform string based on Mac SIG feedback: remove "micro" version number, and map "PowerPC" and "Power_Macintosh" to "ppc". Index: api_tests.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/api_tests.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- api_tests.txt 21 Jul 2005 01:11:31 -0000 1.2 +++ api_tests.txt 21 Jul 2005 04:50:50 -0000 1.3 @@ -256,7 +256,7 @@ Basic equality works as on other platforms:: >>> from pkg_resources import compatible_platforms as cp - >>> reqd = 'macosx-10.4.2-Power_Macintosh' + >>> reqd = 'macosx-10.4-ppc' >>> cp(reqd, reqd) True >>> cp("win32", reqd) @@ -264,19 +264,19 @@ Distributions made on other machine types are not compatible:: - >>> cp("macosx-10.4.2-Intel", reqd) + >>> cp("macosx-10.4-i386", reqd) False Distributions made on earlier versions of the OS are compatible, as long as they are from the same top-level version. The patchlevel version number does not matter:: - >>> cp("macosx-10.4.5-Power_Macintosh", reqd) + >>> cp("macosx-10.4-ppc", reqd) True - >>> cp("macosx-10.3.5-Power_Macintosh", reqd) + >>> cp("macosx-10.3-ppc", reqd) True - >>> cp("macosx-10.5.5-Power_Macintosh", reqd) + >>> cp("macosx-10.5-ppc", reqd) False - >>> cp("macosx-9.5.5-Power_Macintosh", reqd) + >>> cp("macosx-9.5-ppc", reqd) False Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.49 retrieving revision 1.50 diff -u -d -r1.49 -r1.50 --- pkg_resources.py 21 Jul 2005 01:11:31 -0000 1.49 +++ pkg_resources.py 21 Jul 2005 04:50:50 -0000 1.50 @@ -103,8 +103,11 @@ try: version = _macosx_vers() machine = os.uname()[4].replace(" ", "_") - return "macosx-%d.%d.%d-%s" % (int(version[0]), int(version[1]), - int(version[2]), machine) + machine = { + 'PowerPC':'ppc', 'Power_Macintosh':'ppc' + }.get(machine,machine) + return "macosx-%d.%d-%s" % (int(version[0]), int(version[1]), + machine) except ValueError: # if someone is running a non-Mac darwin system, this will fall # through to the default implementation @@ -113,14 +116,11 @@ from distutils.util import get_platform return get_platform() -macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)\.(\d+)-(.*)") +macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") # XXX darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") - - - def compatible_platforms(provided,required): """Can code for the `provided` platform run on the `required` platform? @@ -143,7 +143,7 @@ # are they the same major version and machine type? if provMac.group(1) != reqMac.group(1) or \ - provMac.group(4) != reqMac.group(4): + provMac.group(3) != reqMac.group(3): return False # is the required OS major update >= the provided one? From pje at users.sourceforge.net Thu Jul 21 18:11:36 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Thu, 21 Jul 2005 09:11:36 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.46, 1.47 api_tests.txt, 1.3, 1.4 pkg_resources.py, 1.50, 1.51 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23992 Modified Files: EasyInstall.txt api_tests.txt pkg_resources.py Log Message: Improved backward compatibility of Mac OS platform string changes, thanks to more help from Kevin Dangoor. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.46 retrieving revision 1.47 diff -u -d -r1.46 -r1.47 --- EasyInstall.txt 21 Jul 2005 01:11:31 -0000 1.46 +++ EasyInstall.txt 21 Jul 2005 16:11:33 -0000 1.47 @@ -620,12 +620,11 @@ 0.6a1 * Added support for handling MacOS platform information in ``.egg`` filenames, - based on a contribution by Kevin Dangoor. (NOTE: this may make eggs - compiled for OS X with older versions of setuptools unusable! If you have - eggs whose file/directory names end with ``-darwin-*.egg``, you will - probably need to rename them to ``-macosx-*.egg``, substituting your current - Mac OS version for the darwin kernel version in the version number. Or, you - can just delete and reinstall the problematic eggs.) + based on a contribution by Kevin Dangoor. You may wish to delete and + reinstall any eggs whose filename includes "darwin" and "Power_Macintosh", + because the format for this platform information has changed so that minor + OS X upgrades (such as 10.4.1 to 10.4.2) do not cause eggs built with a + previous OS version to become obsolete. * Fixed installing extra ``.pyc`` or ``.pyo`` files for scripts with ``.py`` extensions. Index: api_tests.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/api_tests.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- api_tests.txt 21 Jul 2005 04:50:50 -0000 1.3 +++ api_tests.txt 21 Jul 2005 16:11:34 -0000 1.4 @@ -280,3 +280,13 @@ >>> cp("macosx-9.5-ppc", reqd) False +Backwards compatibility for packages made via earlier versions of +setuptools is provided as well:: + + >>> cp("darwin-8.2.0-Power_Macintosh", reqd) + True + >>> cp("darwin-7.2.0-Power_Macintosh", reqd) + True + >>> cp("darwin-8.2.0-Power_Macintosh", "macosx-10.3-ppc") + False + Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.50 retrieving revision 1.51 diff -u -d -r1.50 -r1.51 --- pkg_resources.py 21 Jul 2005 04:50:50 -0000 1.50 +++ pkg_resources.py 21 Jul 2005 16:11:34 -0000 1.51 @@ -92,6 +92,8 @@ raise ValueError, "What?!" return _cache[0] +def _macosx_arch(machine): + return {'PowerPC':'ppc', 'Power_Macintosh':'ppc'}.get(machine,machine) def get_platform(): """Return this platform's string for platform-specific distributions @@ -103,21 +105,19 @@ try: version = _macosx_vers() machine = os.uname()[4].replace(" ", "_") - machine = { - 'PowerPC':'ppc', 'Power_Macintosh':'ppc' - }.get(machine,machine) return "macosx-%d.%d-%s" % (int(version[0]), int(version[1]), - machine) + _macosx_arch(machine)) except ValueError: # if someone is running a non-Mac darwin system, this will fall # through to the default implementation pass - + from distutils.util import get_platform return get_platform() macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") -# XXX darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") +darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") + @@ -135,33 +135,44 @@ reqMac = macosVersionString.match(required) if reqMac: provMac = macosVersionString.match(provided) - + # is this a Mac package? if not provMac: - # XXX backward compatibility should go here! - return False - + # this is backwards compatibility for packages built before + # setuptools 0.6. All packages built after this point will + # use the new macosx designation. + provDarwin = darwinVersionString.match(provided) + if provDarwin: + dversion = int(provDarwin.group(1)) + macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) + if dversion == 7 and macosversion >= "10.3" or \ + dversion == 8 and macosversion >= "10.4": + + #import warnings + #warnings.warn("Mac eggs should be rebuilt to " + # "use the macosx designation instead of darwin.", + # category=DeprecationWarning) + return True + + return False # egg isn't macosx or legacy darwin + # are they the same major version and machine type? if provMac.group(1) != reqMac.group(1) or \ provMac.group(3) != reqMac.group(3): return False - + + # is the required OS major update >= the provided one? if int(provMac.group(2)) > int(reqMac.group(2)): return False - + return True - # XXX Linux and other platforms' special cases should go here + # XXX Linux and other platforms' special cases should go here return False - - - - - def run_script(dist_spec, script_name): """Locate distribution `dist_spec` and run its `script_name` script""" ns = sys._getframe(1).f_globals @@ -173,6 +184,25 @@ run_main = run_script # backward compatibility + + + + + + + + + + + + + + + + + + + class IMetadataProvider: def has_metadata(name): @@ -203,6 +233,17 @@ + + + + + + + + + + + class IResourceProvider(IMetadataProvider): """An object that provides access to package resources""" From gward at users.sourceforge.net Fri Jul 22 03:54:57 2005 From: gward at users.sourceforge.net (gward@users.sourceforge.net) Date: Thu, 21 Jul 2005 18:54:57 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib liboptparse.tex, 1.18.2.5, 1.18.2.6 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11295 Modified Files: Tag: release24-maint liboptparse.tex Log Message: SF #1204347: typo fix. Index: liboptparse.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/liboptparse.tex,v retrieving revision 1.18.2.5 retrieving revision 1.18.2.6 diff -u -d -r1.18.2.5 -r1.18.2.6 --- liboptparse.tex 19 Mar 2005 17:15:03 -0000 1.18.2.5 +++ liboptparse.tex 22 Jul 2005 01:54:54 -0000 1.18.2.6 @@ -584,7 +584,7 @@ There are two broad classes of errors that \module{optparse} has to worry about: programmer errors and user errors. Programmer errors are usually -erroneous calls to \code{parse.add{\_}option()}, e.g. invalid option strings, +erroneous calls to \code{parser.add{\_}option()}, e.g. invalid option strings, unknown option attributes, missing option attributes, etc. These are dealt with in the usual way: raise an exception (either \code{optparse.OptionError} or \code{TypeError}) and let the program crash. @@ -1347,7 +1347,7 @@ To avoid this confusion, use \method{set{\_}defaults()}: \begin{verbatim} -parse.set_defaults(mode="advanced") +parser.set_defaults(mode="advanced") parser.add_option("--advanced", action="store_const", dest="mode", const="advanced") parser.add_option("--novice", action="store_const", From rhettinger at users.sourceforge.net Fri Jul 22 17:29:53 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 22 Jul 2005 08:29:53 -0700 Subject: [Python-checkins] python/nondist/sandbox/set - New directory Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26744/set Log Message: Directory /cvsroot/python/python/nondist/sandbox/set added to the repository From rhettinger at users.sourceforge.net Fri Jul 22 17:32:34 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 22 Jul 2005 08:32:34 -0700 Subject: [Python-checkins] python/nondist/sandbox/set setobject.c, NONE, 1.1 setobject.h, NONE, 1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26902/set Added Files: setobject.c setobject.h Log Message: First pass at a set implementation with its own dict-like data structure. Consumes 1/3 less memory and runs a bit faster. Passes all tests. --- NEW FILE: setobject.c --- /* Set object implementation using a hash table Functions adapted from dictobject.c */ #include "Python.h" typedef PySetEntry setentry; typedef PySetObject setobject; /* This must be >= 1. */ #define PERTURB_SHIFT 5 /* Object used as dummy key to fill deleted entries */ static PyObject *dummy; /* Initialized by first call to newsetobject() */ /* forward declarations */ static setentry * set_lookkey_string(setobject *mp, PyObject *key, long hash); [...1822 lines suppressed...] frozenset_doc, /* tp_doc */ (traverseproc)set_traverse, /* tp_traverse */ 0, /* tp_clear */ (richcmpfunc)set_richcompare, /* tp_richcompare */ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ (getiterfunc)set_iter, /* tp_iter */ 0, /* tp_iternext */ frozenset_methods, /* tp_methods */ 0, /* tp_members */ 0, /* 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 */ frozenset_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; --- NEW FILE: setobject.h --- /* Set object interface */ #ifndef Py_SETOBJECT_H #define Py_SETOBJECT_H #ifdef __cplusplus extern "C" { #endif /* There are three kinds of slots in the table: 1. Unused: me_key == NULL 2. Active: me_key != NULL and me_key != dummy 3. Dummy: me_key == dummy */ #define PySet_MINSIZE 8 typedef struct { long me_hash; /* cached hash code of me_key */ PyObject *me_key; } PySetEntry; /* This data structure is shared by set and frozenset objects. */ typedef struct _setobject PySetObject; struct _setobject { PyObject_HEAD int ma_fill; /* # Active + # Dummy */ int ma_used; /* # Active */ /* The table contains ma_mask + 1 slots, and that's a power of 2. * We store the mask instead of the size because the mask is more * frequently needed. */ int ma_mask; /* ma_table points to ma_smalltable for small tables, else to * additional malloc'ed memory. ma_table is never NULL! This rule * saves repeated runtime null-tests in the workhorse getitem and * setitem calls. */ PySetEntry *ma_table; PySetEntry *(*ma_lookup)(PySetObject *mp, PyObject *key, long hash); PySetEntry ma_smalltable[PySet_MINSIZE]; long hash; /* only used by frozenset objects */ PyObject *weakreflist; /* List of weak references */ }; PyAPI_DATA(PyTypeObject) PySet_Type; PyAPI_DATA(PyTypeObject) PyFrozenSet_Type; /* Invariants for frozensets only: * data is immutable. * hash is the hash of the frozenset or -1 if not computed yet. */ #define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type) #define PyAnySet_Check(ob) \ ((ob)->ob_type == &PySet_Type || (ob)->ob_type == &PyFrozenSet_Type || \ PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \ PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type)) #ifdef __cplusplus } #endif #endif /* !Py_SETOBJECT_H */ From birkenfeld at users.sourceforge.net Fri Jul 22 20:39:19 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:39:19 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1320,1.1321 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5474/Misc Modified Files: NEWS Log Message: [ 1243081 ] repair typos Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1320 retrieving revision 1.1321 diff -u -d -r1.1320 -r1.1321 --- NEWS 18 Jul 2005 08:53:17 -0000 1.1320 +++ NEWS 22 Jul 2005 18:39:16 -0000 1.1321 @@ -906,7 +906,7 @@ - The decimal package's Context.copy() method now returns deep copies. - Deprecated sys.exitfunc in favor of the atexit module. The sys.exitfunc - attribute will be kept around for backwards compatability and atexit + attribute will be kept around for backwards compatibility and atexit will just become the one preferred way to do it. - patch #675551: Add get_history_item and replace_history_item functions From birkenfeld at users.sourceforge.net Fri Jul 22 20:39:20 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:39:20 -0700 Subject: [Python-checkins] python/dist/src/Lib/plat-mac macostools.py, 1.4, 1.5 aetypes.py, 1.7, 1.8 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/plat-mac In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5474/Lib/plat-mac Modified Files: macostools.py aetypes.py Log Message: [ 1243081 ] repair typos Index: macostools.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/plat-mac/macostools.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- macostools.py 18 Jul 2004 06:14:45 -0000 1.4 +++ macostools.py 22 Jul 2005 18:39:17 -0000 1.5 @@ -13,7 +13,7 @@ try: openrf = MacOS.openrf except AttributeError: - # Backward compatability + # Backward compatibility openrf = open Error = 'macostools.Error' Index: aetypes.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/plat-mac/aetypes.py,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- aetypes.py 18 Jul 2004 06:14:45 -0000 1.7 +++ aetypes.py 22 Jul 2005 18:39:17 -0000 1.8 @@ -430,7 +430,7 @@ return isinstance(x, ObjectSpecifier) -# Backwards compatability, sigh... +# Backwards compatibility, sigh... class Property(ObjectSpecifier): def __init__(self, which, fr = None, want='prop'): From birkenfeld at users.sourceforge.net Fri Jul 22 20:39:20 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:39:20 -0700 Subject: [Python-checkins] python/dist/src/Include objimpl.h,2.60,2.61 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5474/Include Modified Files: objimpl.h Log Message: [ 1243081 ] repair typos Index: objimpl.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/objimpl.h,v retrieving revision 2.60 retrieving revision 2.61 diff -u -d -r2.60 -r2.61 --- objimpl.h 15 Jul 2004 04:05:59 -0000 2.60 +++ objimpl.h 22 Jul 2005 18:39:18 -0000 2.61 @@ -124,7 +124,7 @@ #else /* ! WITH_PYMALLOC */ #define PyObject_MALLOC PyMem_MALLOC #define PyObject_REALLOC PyMem_REALLOC -/* This is an odd one! For backward compatability with old extensions, the +/* This is an odd one! For backward compatibility with old extensions, the PyMem "release memory" functions have to invoke the object allocator's free() function. When pymalloc isn't enabled, that leaves us using the platform free(). */ From birkenfeld at users.sourceforge.net Fri Jul 22 20:39:20 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:39:20 -0700 Subject: [Python-checkins] python/dist/src/Lib/idlelib ChangeLog,1.5,1.6 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/idlelib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5474/Lib/idlelib Modified Files: ChangeLog Log Message: [ 1243081 ] repair typos Index: ChangeLog =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/ChangeLog,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- ChangeLog 12 Jun 2003 03:57:23 -0000 1.5 +++ ChangeLog 22 Jul 2005 18:39:17 -0000 1.6 @@ -378,7 +378,7 @@ 2001-07-12 16:54 elguavas - * ReplaceDialog.py: py-cvs merge, python 1.5.2 compatability + * ReplaceDialog.py: py-cvs merge, python 1.5.2 compatibility 2001-07-12 16:46 elguavas From birkenfeld at users.sourceforge.net Fri Jul 22 20:39:21 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:39:21 -0700 Subject: [Python-checkins] python/dist/src/Doc/whatsnew whatsnew25.tex, 1.13, 1.14 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/whatsnew In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5474/Doc/whatsnew Modified Files: whatsnew25.tex Log Message: [ 1243081 ] repair typos Index: whatsnew25.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/whatsnew/whatsnew25.tex,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- whatsnew25.tex 9 Apr 2005 23:59:41 -0000 1.13 +++ whatsnew25.tex 22 Jul 2005 18:39:19 -0000 1.14 @@ -216,7 +216,7 @@ \function{os.lseek()} function. \item The \class{TarFile} class in the \module{tarfile} module now has -a \method{extractall()} method that extracts all members from the +an \method{extractall()} method that extracts all members from the archive into the current working directory. It's also possible to set a different directory as the extraction target, and to unpack only a subset of the archive's members. (Contributed by Lars Gust\"abel.) From birkenfeld at users.sourceforge.net Fri Jul 22 20:39:21 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:39:21 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libsets.tex, 1.18, 1.19 libfuncs.tex, 1.184, 1.185 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5474/Doc/lib Modified Files: libsets.tex libfuncs.tex Log Message: [ 1243081 ] repair typos Index: libsets.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libsets.tex,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- libsets.tex 1 Jul 2005 23:00:13 -0000 1.18 +++ libsets.tex 22 Jul 2005 18:39:18 -0000 1.19 @@ -169,8 +169,8 @@ Also note, the module also includes a \method{union_update()} method which is an alias for \method{update()}. The method is included for -backwards compatability. Programmers should prefer the -\method{update()} method because it the one supported by the builtin +backwards compatibility. Programmers should prefer the +\method{update()} method because it is the one supported by the builtin \class{set()} and \class{frozenset()} types. \subsection{Example \label{set-example}} @@ -254,7 +254,7 @@ \item The built-in versions have more space efficient pickles. \item The built-in versions do not have a \method{union_update()} method. Instead, use the \method{update()} method which is equivalent. -\item The built-in versions do not have a \method{_repr(sort=True)} method. +\item The built-in versions do not have a \method{_repr(sorted=True)} method. Instead, use the built-in \function{repr()} and \function{sorted()} functions: \code{repr(sorted(s))}. \item The built-in version does not have a protocol for automatic conversion Index: libfuncs.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfuncs.tex,v retrieving revision 1.184 retrieving revision 1.185 diff -u -d -r1.184 -r1.185 --- libfuncs.tex 25 Jun 2005 20:07:36 -0000 1.184 +++ libfuncs.tex 22 Jul 2005 18:39:19 -0000 1.185 @@ -1173,7 +1173,7 @@ There are several built-in functions that are no longer essential to learn, know or use in modern Python programming. They have been kept here to -maintain backwards compatability with programs written for older versions +maintain backwards compatibility with programs written for older versions of Python. Python programmers, trainers, students and bookwriters should feel free to From birkenfeld at users.sourceforge.net Fri Jul 22 20:39:48 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:39:48 -0700 Subject: [Python-checkins] python/dist/src/Modules/cjkcodecs _codecs_jp.c, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/dist/src/Modules/cjkcodecs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5474/Modules/cjkcodecs Modified Files: _codecs_jp.c Log Message: [ 1243081 ] repair typos Index: _codecs_jp.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/cjkcodecs/_codecs_jp.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- _codecs_jp.c 18 Jul 2004 03:06:27 -0000 1.1 +++ _codecs_jp.c 22 Jul 2005 18:39:15 -0000 1.2 @@ -36,7 +36,7 @@ continue; } else if (c >= 0xf8f0 && c <= 0xf8f3) { - /* Windows compatability */ + /* Windows compatibility */ REQUIRE_OUTBUF(1) if (c == 0xf8f0) OUT1(0xa0) From birkenfeld at users.sourceforge.net Fri Jul 22 20:40:03 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:40:03 -0700 Subject: [Python-checkins] python/dist/src/Modules/cjkcodecs _codecs_jp.c, 1.1, 1.1.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Modules/cjkcodecs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5608/Modules/cjkcodecs Modified Files: Tag: release24-maint _codecs_jp.c Log Message: [ 1243081 ] repair typos Index: _codecs_jp.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/cjkcodecs/_codecs_jp.c,v retrieving revision 1.1 retrieving revision 1.1.4.1 diff -u -d -r1.1 -r1.1.4.1 --- _codecs_jp.c 18 Jul 2004 03:06:27 -0000 1.1 +++ _codecs_jp.c 22 Jul 2005 18:40:00 -0000 1.1.4.1 @@ -36,7 +36,7 @@ continue; } else if (c >= 0xf8f0 && c <= 0xf8f3) { - /* Windows compatability */ + /* Windows compatibility */ REQUIRE_OUTBUF(1) if (c == 0xf8f0) OUT1(0xa0) From birkenfeld at users.sourceforge.net Fri Jul 22 20:40:05 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:40:05 -0700 Subject: [Python-checkins] python/dist/src/Lib/idlelib ChangeLog, 1.5, 1.5.12.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/idlelib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5608/Lib/idlelib Modified Files: Tag: release24-maint ChangeLog Log Message: [ 1243081 ] repair typos Index: ChangeLog =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/ChangeLog,v retrieving revision 1.5 retrieving revision 1.5.12.1 diff -u -d -r1.5 -r1.5.12.1 --- ChangeLog 12 Jun 2003 03:57:23 -0000 1.5 +++ ChangeLog 22 Jul 2005 18:40:02 -0000 1.5.12.1 @@ -378,7 +378,7 @@ 2001-07-12 16:54 elguavas - * ReplaceDialog.py: py-cvs merge, python 1.5.2 compatability + * ReplaceDialog.py: py-cvs merge, python 1.5.2 compatibility 2001-07-12 16:46 elguavas From birkenfeld at users.sourceforge.net Fri Jul 22 20:40:05 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:40:05 -0700 Subject: [Python-checkins] python/dist/src/Lib/plat-mac macostools.py, 1.4, 1.4.4.1 aetypes.py, 1.7, 1.7.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/plat-mac In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5608/Lib/plat-mac Modified Files: Tag: release24-maint macostools.py aetypes.py Log Message: [ 1243081 ] repair typos Index: macostools.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/plat-mac/macostools.py,v retrieving revision 1.4 retrieving revision 1.4.4.1 diff -u -d -r1.4 -r1.4.4.1 --- macostools.py 18 Jul 2004 06:14:45 -0000 1.4 +++ macostools.py 22 Jul 2005 18:40:02 -0000 1.4.4.1 @@ -13,7 +13,7 @@ try: openrf = MacOS.openrf except AttributeError: - # Backward compatability + # Backward compatibility openrf = open Error = 'macostools.Error' Index: aetypes.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/plat-mac/aetypes.py,v retrieving revision 1.7 retrieving revision 1.7.4.1 diff -u -d -r1.7 -r1.7.4.1 --- aetypes.py 18 Jul 2004 06:14:45 -0000 1.7 +++ aetypes.py 22 Jul 2005 18:40:02 -0000 1.7.4.1 @@ -430,7 +430,7 @@ return isinstance(x, ObjectSpecifier) -# Backwards compatability, sigh... +# Backwards compatibility, sigh... class Property(ObjectSpecifier): def __init__(self, which, fr = None, want='prop'): From birkenfeld at users.sourceforge.net Fri Jul 22 20:40:05 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:40:05 -0700 Subject: [Python-checkins] python/dist/src/Include objimpl.h,2.60,2.60.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5608/Include Modified Files: Tag: release24-maint objimpl.h Log Message: [ 1243081 ] repair typos Index: objimpl.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/objimpl.h,v retrieving revision 2.60 retrieving revision 2.60.4.1 diff -u -d -r2.60 -r2.60.4.1 --- objimpl.h 15 Jul 2004 04:05:59 -0000 2.60 +++ objimpl.h 22 Jul 2005 18:40:02 -0000 2.60.4.1 @@ -124,7 +124,7 @@ #else /* ! WITH_PYMALLOC */ #define PyObject_MALLOC PyMem_MALLOC #define PyObject_REALLOC PyMem_REALLOC -/* This is an odd one! For backward compatability with old extensions, the +/* This is an odd one! For backward compatibility with old extensions, the PyMem "release memory" functions have to invoke the object allocator's free() function. When pymalloc isn't enabled, that leaves us using the platform free(). */ From birkenfeld at users.sourceforge.net Fri Jul 22 20:40:06 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:40:06 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib libsets.tex, 1.15.4.3, 1.15.4.4 libfuncs.tex, 1.175.2.4, 1.175.2.5 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5608/Doc/lib Modified Files: Tag: release24-maint libsets.tex libfuncs.tex Log Message: [ 1243081 ] repair typos Index: libsets.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libsets.tex,v retrieving revision 1.15.4.3 retrieving revision 1.15.4.4 diff -u -d -r1.15.4.3 -r1.15.4.4 --- libsets.tex 1 Jul 2005 23:01:46 -0000 1.15.4.3 +++ libsets.tex 22 Jul 2005 18:40:02 -0000 1.15.4.4 @@ -169,7 +169,7 @@ Also note, the module also includes a \method{union_update()} method which is an alias for \method{update()}. The method is included for -backwards compatability. Programmers should prefer the +backwards compatibility. Programmers should prefer the \method{update()} method because it the one supported by the builtin \class{set()} and \class{frozenset()} types. Index: libfuncs.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfuncs.tex,v retrieving revision 1.175.2.4 retrieving revision 1.175.2.5 diff -u -d -r1.175.2.4 -r1.175.2.5 --- libfuncs.tex 25 Jun 2005 20:07:39 -0000 1.175.2.4 +++ libfuncs.tex 22 Jul 2005 18:40:02 -0000 1.175.2.5 @@ -1135,7 +1135,7 @@ There are several built-in functions that are no longer essential to learn, know or use in modern Python programming. They have been kept here to -maintain backwards compatability with programs written for older versions +maintain backwards compatibility with programs written for older versions of Python. Python programmers, trainers, students and bookwriters should feel free to From birkenfeld at users.sourceforge.net Fri Jul 22 20:40:05 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 11:40:05 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS, 1.1193.2.64, 1.1193.2.65 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5608/Misc Modified Files: Tag: release24-maint NEWS Log Message: [ 1243081 ] repair typos Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.64 retrieving revision 1.1193.2.65 diff -u -d -r1.1193.2.64 -r1.1193.2.65 --- NEWS 18 Jul 2005 08:53:40 -0000 1.1193.2.64 +++ NEWS 22 Jul 2005 18:40:01 -0000 1.1193.2.65 @@ -759,7 +759,7 @@ - The decimal package's Context.copy() method now returns deep copies. - Deprecated sys.exitfunc in favor of the atexit module. The sys.exitfunc - attribute will be kept around for backwards compatability and atexit + attribute will be kept around for backwards compatibility and atexit will just become the one preferred way to do it. - patch #675551: Add get_history_item and replace_history_item functions From birkenfeld at users.sourceforge.net Fri Jul 22 21:48:05 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 12:48:05 -0700 Subject: [Python-checkins] python/dist/src/Doc/ref ref2.tex, 1.56.2.1, 1.56.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/ref In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24031/Doc/ref Modified Files: Tag: release24-maint ref2.tex Log Message: [ 1243288 ] Misuse of "it's" Index: ref2.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref2.tex,v retrieving revision 1.56.2.1 retrieving revision 1.56.2.2 diff -u -d -r1.56.2.1 -r1.56.2.2 --- ref2.tex 25 May 2005 05:30:36 -0000 1.56.2.1 +++ ref2.tex 22 Jul 2005 19:48:03 -0000 1.56.2.2 @@ -349,7 +349,7 @@ \item[\code{__*__}] System-defined names. These names are defined by the interpreter - and it's implementation (including the standard library); + and its implementation (including the standard library); applications should not expect to define additional names using this convention. The set of names of this class defined by Python may be extended in future versions. From birkenfeld at users.sourceforge.net Fri Jul 22 23:48:53 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:48:53 -0700 Subject: [Python-checkins] python/dist/src/Lib SimpleXMLRPCServer.py, 1.9.2.1, 1.9.2.2 tarfile.py, 1.21.2.1, 1.21.2.2 ConfigParser.py, 1.68, 1.68.2.1 difflib.py, 1.28, 1.28.2.1 pydoc.py, 1.100.2.2, 1.100.2.3 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/Lib Modified Files: Tag: release24-maint SimpleXMLRPCServer.py tarfile.py ConfigParser.py difflib.py pydoc.py Log Message: Fix all wrong instances of "it's". Index: SimpleXMLRPCServer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/SimpleXMLRPCServer.py,v retrieving revision 1.9.2.1 retrieving revision 1.9.2.2 diff -u -d -r1.9.2.1 -r1.9.2.2 --- SimpleXMLRPCServer.py 3 Feb 2005 15:00:18 -0000 1.9.2.1 +++ SimpleXMLRPCServer.py 22 Jul 2005 21:48:49 -0000 1.9.2.2 @@ -170,7 +170,7 @@ If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and - it's parameters as a tuple + its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method @@ -371,7 +371,7 @@ If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and - it's parameters as a tuple + its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method Index: tarfile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tarfile.py,v retrieving revision 1.21.2.1 retrieving revision 1.21.2.2 diff -u -d -r1.21.2.1 -r1.21.2.2 --- tarfile.py 3 Mar 2005 23:15:03 -0000 1.21.2.1 +++ tarfile.py 22 Jul 2005 21:48:50 -0000 1.21.2.2 @@ -1374,7 +1374,7 @@ # stream of tar blocks. raise StreamError, "cannot extract (sym)link as file object" else: - # A (sym)link's file object is it's target's file object. + # A (sym)link's file object is its target's file object. return self.extractfile(self._getmember(tarinfo.linkname, tarinfo)) else: Index: ConfigParser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ConfigParser.py,v retrieving revision 1.68 retrieving revision 1.68.2.1 diff -u -d -r1.68 -r1.68.2.1 --- ConfigParser.py 3 Oct 2004 15:55:09 -0000 1.68 +++ ConfigParser.py 22 Jul 2005 21:48:50 -0000 1.68.2.1 @@ -28,7 +28,7 @@ create the parser and specify a dictionary of intrinsic defaults. The keys must be strings, the values must be appropriate for %()s string interpolation. Note that `__name__' is always an intrinsic default; - it's value is the section's name. + its value is the section's name. sections() return all the configuration section names, sans DEFAULT Index: difflib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/difflib.py,v retrieving revision 1.28 retrieving revision 1.28.2.1 diff -u -d -r1.28 -r1.28.2.1 --- difflib.py 12 Nov 2004 16:12:15 -0000 1.28 +++ difflib.py 22 Jul 2005 21:48:50 -0000 1.28.2.1 @@ -1371,7 +1371,7 @@ text = ' ' # insert marks that won't be noticed by an xml/html escaper. text = '\0' + format_key + text + '\1' - # Return line of text, first allow user's line formatter to do it's + # Return line of text, first allow user's line formatter to do its # thing (such as adding the line number) then replace the special # marks with what the user's change markup. return (num_lines[side],text) @@ -1472,7 +1472,7 @@ """Yields from/to lines of text with a change indication. This function is an iterator. It itself pulls lines from the line - iterator. It's difference from that iterator is that this function + iterator. Its difference from that iterator is that this function always yields a pair of from/to text lines (with the change indication). If necessary it will collect single from/to lines until it has a matching pair from/to pair to yield. Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.100.2.2 retrieving revision 1.100.2.3 diff -u -d -r1.100.2.2 -r1.100.2.3 --- pydoc.py 19 Feb 2005 22:57:37 -0000 1.100.2.2 +++ pydoc.py 22 Jul 2005 21:48:50 -0000 1.100.2.3 @@ -92,7 +92,7 @@ return name def isdata(object): - """Check if an object is of a type that probably means it's data.""" + """Check if an object is of a type that probably means its data.""" return not (inspect.ismodule(object) or inspect.isclass(object) or inspect.isroutine(object) or inspect.isframe(object) or inspect.istraceback(object) or inspect.iscode(object)) From birkenfeld at users.sourceforge.net Fri Jul 22 23:48:53 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:48:53 -0700 Subject: [Python-checkins] python/dist/src/Mac/Tools/IDE Wbase.py, 1.15, 1.15.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Tools/IDE In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/Mac/Tools/IDE Modified Files: Tag: release24-maint Wbase.py Log Message: Fix all wrong instances of "it's". Index: Wbase.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Tools/IDE/Wbase.py,v retrieving revision 1.15 retrieving revision 1.15.4.1 diff -u -d -r1.15 -r1.15.4.1 --- Wbase.py 18 Jul 2004 05:58:14 -0000 1.15 +++ Wbase.py 22 Jul 2005 21:48:51 -0000 1.15.4.1 @@ -128,28 +128,28 @@ # depending on the values of l(eft), t(op), r(right) and b(ottom), # they mean different things: if l < -1: - # l is less than -1, this mean it measures from the *right* of it's parent + # l is less than -1, this mean it measures from the *right* of its parent l = pr + l else: - # l is -1 or greater, this mean it measures from the *left* of it's parent + # l is -1 or greater, this mean it measures from the *left* of its parent l = pl + l if t < -1: - # t is less than -1, this mean it measures from the *bottom* of it's parent + # t is less than -1, this mean it measures from the *bottom* of its parent t = pb + t else: - # t is -1 or greater, this mean it measures from the *top* of it's parent + # t is -1 or greater, this mean it measures from the *top* of its parent t = pt + t if r > 1: # r is greater than 1, this means r is the *width* of the widget r = l + r else: - # r is less than 1, this means it measures from the *right* of it's parent + # r is less than 1, this means it measures from the *right* of its parent r = pr + r if b > 1: # b is greater than 1, this means b is the *height* of the widget b = t + b else: - # b is less than 1, this means it measures from the *bottom* of it's parent + # b is less than 1, this means it measures from the *bottom* of its parent b = pb + b self._bounds = (l, t, r, b) if oldbounds and oldbounds <> self._bounds: From birkenfeld at users.sourceforge.net Fri Jul 22 23:48:53 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:48:53 -0700 Subject: [Python-checkins] python/dist/src/Lib/idlelib configDialog.py, 1.60, 1.60.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/idlelib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/Lib/idlelib Modified Files: Tag: release24-maint configDialog.py Log Message: Fix all wrong instances of "it's". Index: configDialog.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/configDialog.py,v retrieving revision 1.60 retrieving revision 1.60.2.1 diff -u -d -r1.60 -r1.60.2.1 --- configDialog.py 16 Nov 2004 21:28:36 -0000 1.60 +++ configDialog.py 22 Jul 2005 21:48:50 -0000 1.60.2.1 @@ -29,7 +29,7 @@ self.configure(borderwidth=5) self.geometry("+%d+%d" % (parent.winfo_rootx()+20, parent.winfo_rooty()+30)) - #Theme Elements. Each theme element key is it's display name. + #Theme Elements. Each theme element key is its display name. #The first value of the tuple is the sample area tag name. #The second value is the display name list sort index. self.themeElements={'Normal Text':('normal','00'), From birkenfeld at users.sourceforge.net Fri Jul 22 23:48:53 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:48:53 -0700 Subject: [Python-checkins] python/dist/src/PC w9xpopen.c, 1.5, 1.5.18.1 getpathp.c, 1.33, 1.33.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/PC In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/PC Modified Files: Tag: release24-maint w9xpopen.c getpathp.c Log Message: Fix all wrong instances of "it's". Index: w9xpopen.c =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/w9xpopen.c,v retrieving revision 1.5 retrieving revision 1.5.18.1 diff -u -d -r1.5 -r1.5.18.1 --- w9xpopen.c 14 Jul 2002 22:14:19 -0000 1.5 +++ w9xpopen.c 22 Jul 2005 21:48:51 -0000 1.5.18.1 @@ -9,7 +9,7 @@ * This program is to be launched with redirected standard * handles. It will launch the command line specified 16-bit * console based application in the same console, forwarding - * it's own redirected standard handles to the 16-bit child. + * its own redirected standard handles to the 16-bit child. * AKA solution to the problem described in KB: Q150956. */ Index: getpathp.c =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/getpathp.c,v retrieving revision 1.33 retrieving revision 1.33.2.1 diff -u -d -r1.33 -r1.33.2.1 --- getpathp.c 7 Aug 2004 19:12:27 -0000 1.33 +++ getpathp.c 22 Jul 2005 21:48:51 -0000 1.33.2.1 @@ -11,7 +11,7 @@ * Python always adds an empty entry at the start, which corresponds to the current directory. - * If the PYTHONPATH env. var. exists, it's entries are added next. + * If the PYTHONPATH env. var. exists, its entries are added next. * We look in the registry for "application paths" - that is, sub-keys under the main PythonPath registry key. These are added next (the From birkenfeld at users.sourceforge.net Fri Jul 22 23:48:54 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:48:54 -0700 Subject: [Python-checkins] python/dist/src/PC/os2emx getpathp.c, 1.3.14.1, 1.3.14.2 Message-ID: Update of /cvsroot/python/python/dist/src/PC/os2emx In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/PC/os2emx Modified Files: Tag: release24-maint getpathp.c Log Message: Fix all wrong instances of "it's". Index: getpathp.c =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/os2emx/getpathp.c,v retrieving revision 1.3.14.1 retrieving revision 1.3.14.2 diff -u -d -r1.3.14.1 -r1.3.14.2 --- getpathp.c 12 Dec 2004 08:32:15 -0000 1.3.14.1 +++ getpathp.c 22 Jul 2005 21:48:51 -0000 1.3.14.2 @@ -11,7 +11,7 @@ * Python always adds an empty entry at the start, which corresponds to the current directory. - * If the PYTHONPATH env. var. exists, it's entries are added next. + * If the PYTHONPATH env. var. exists, its entries are added next. * We attempt to locate the "Python Home" - if the PYTHONHOME env var is set, we believe it. Otherwise, we use the path of our host .EXE's From birkenfeld at users.sourceforge.net Fri Jul 22 23:48:54 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:48:54 -0700 Subject: [Python-checkins] python/dist/src/Tools/pynche README, 2.16, 2.16.34.1 StripViewer.py, 2.17, 2.17.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/pynche In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/Tools/pynche Modified Files: Tag: release24-maint README StripViewer.py Log Message: Fix all wrong instances of "it's". Index: README =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/pynche/README,v retrieving revision 2.16 retrieving revision 2.16.34.1 diff -u -d -r2.16 -r2.16.34.1 --- README 23 Aug 2001 16:15:21 -0000 2.16 +++ README 22 Jul 2005 21:48:51 -0000 2.16.34.1 @@ -107,7 +107,7 @@ master[*] the master window to use as the parent of the modal dialog. Without this argument, pyColorChooser will create - it's own Tkinter.Tk instance as the master. This may not + its own Tkinter.Tk instance as the master. This may not be what you want. databasefile Index: StripViewer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/pynche/StripViewer.py,v retrieving revision 2.17 retrieving revision 2.17.4.1 diff -u -d -r2.17 -r2.17.4.1 --- StripViewer.py 18 Jul 2004 06:02:04 -0000 2.17 +++ StripViewer.py 22 Jul 2005 21:48:52 -0000 2.17.4.1 @@ -268,7 +268,7 @@ else: # decimal text = repr(coloraxis) - # move the arrow, and set it's text + # move the arrow, and set its text if coloraxis <= 128: # use the left arrow self.__leftarrow.set_text(text) From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:21 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:21 -0700 Subject: [Python-checkins] python/dist/src/Doc/dist dist.tex, 1.86.2.5, 1.86.2.6 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/dist In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/Doc/dist Modified Files: Tag: release24-maint dist.tex Log Message: Fix all wrong instances of "it's". Index: dist.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/dist/dist.tex,v retrieving revision 1.86.2.5 retrieving revision 1.86.2.6 diff -u -d -r1.86.2.5 -r1.86.2.6 --- dist.tex 18 Jun 2005 20:11:26 -0000 1.86.2.5 +++ dist.tex 22 Jul 2005 21:48:48 -0000 1.86.2.6 @@ -2174,7 +2174,7 @@ \begin{classdesc*}{Extension} The Extension class describes a single C or \Cpp extension module in a -setup script. It accepts the following keyword arguments in it's +setup script. It accepts the following keyword arguments in its constructor \begin{tableiii}{c|l|l}{argument name}{argument name}{value}{type} @@ -2234,7 +2234,7 @@ \end{classdesc*} \begin{classdesc*}{Command} -A \class{Command} class (or rather, an instance of one of it's subclasses) +A \class{Command} class (or rather, an instance of one of its subclasses) implement a single distutils command. \end{classdesc*} @@ -2323,7 +2323,7 @@ (don't actually execute the steps) and \var{force} (rebuild everything, regardless of dependencies). All of these flags default to \code{0} (off). Note that you probably don't want to instantiate -\class{CCompiler} or one of it's subclasses directly - use the +\class{CCompiler} or one of its subclasses directly - use the \function{distutils.CCompiler.new_compiler()} factory function instead. @@ -3203,7 +3203,7 @@ The option_table is a list of 3-tuples: \samp{(long_option, short_option, help_string)} -If an option takes an argument, it's \var{long_option} should have \code{'='} +If an option takes an argument, its \var{long_option} should have \code{'='} appended; \var{short_option} should just be a single character, no \code{':'} in any case. \var{short_option} should be \code{None} if a \var{long_option} doesn't have a corresponding \var{short_option}. All option tuples must have From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:21 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:21 -0700 Subject: [Python-checkins] python/dist/src/Doc/perl l2hinit.perl, 1.87, 1.87.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/perl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/Doc/perl Modified Files: Tag: release24-maint l2hinit.perl Log Message: Fix all wrong instances of "it's". Index: l2hinit.perl =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/perl/l2hinit.perl,v retrieving revision 1.87 retrieving revision 1.87.2.1 diff -u -d -r1.87 -r1.87.2.1 --- l2hinit.perl 10 Nov 2004 07:48:17 -0000 1.87 +++ l2hinit.perl 22 Jul 2005 21:48:49 -0000 1.87.2.1 @@ -98,7 +98,7 @@ $dir =~ s/$dd$//; $TEXINPUTS = "$dir$envkey$mytexinputs"; # Push everything into $TEXINPUTS since LaTeX2HTML doesn't pick - # this up on it's own; we clear $ENV{'TEXINPUTS'} so the value set + # this up on its own; we clear $ENV{'TEXINPUTS'} so the value set # for this by the main LaTeX2HTML script doesn't contain duplicate # directories. if ($ENV{'TEXINPUTS'}) { From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:21 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:21 -0700 Subject: [Python-checkins] python/dist/src/Doc Makefile,1.279,1.279.2.1 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/Doc Modified Files: Tag: release24-maint Makefile Log Message: Fix all wrong instances of "it's". Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile,v retrieving revision 1.279 retrieving revision 1.279.2.1 diff -u -d -r1.279 -r1.279.2.1 --- Makefile 5 Nov 2004 04:51:05 -0000 1.279 +++ Makefile 22 Jul 2005 21:48:48 -0000 1.279.2.1 @@ -87,7 +87,7 @@ # (e.g. OpenBSD needs package gmake installed; use gmake instead of make) PWD=$(shell pwd) -# (The trailing colon in the value is needed; TeX places it's default +# (The trailing colon in the value is needed; TeX places its default # set of paths at the location of the empty string in the path list.) TEXINPUTS=$(PWD)/commontex: From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:22 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:22 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_cd.py, 1.6, 1.6.20.1 test_al.py, 1.7, 1.7.20.1 test_cl.py, 1.6, 1.6.20.1 test_unicodedata.py, 1.11, 1.11.2.1 test_minidom.py, 1.39, 1.39.4.1 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21442/Lib/test Modified Files: Tag: release24-maint test_cd.py test_al.py test_cl.py test_unicodedata.py test_minidom.py Log Message: Fix all wrong instances of "it's". Index: test_cd.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_cd.py,v retrieving revision 1.6 retrieving revision 1.6.20.1 diff -u -d -r1.6 -r1.6.20.1 --- test_cd.py 30 Jul 2002 23:26:01 -0000 1.6 +++ test_cd.py 22 Jul 2005 21:48:49 -0000 1.6.20.1 @@ -10,7 +10,7 @@ 'ident', 'index', 'msftoframe', 'open', 'pnum', 'ptime'] -# This is a very inobtrusive test for the existence of the cd module and all it's +# This is a very inobtrusive test for the existence of the cd module and all its # attributes. More comprehensive examples can be found in Demo/cd and # require that you have a CD and a CD ROM drive Index: test_al.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_al.py,v retrieving revision 1.7 retrieving revision 1.7.20.1 diff -u -d -r1.7 -r1.7.20.1 --- test_al.py 30 Jul 2002 23:26:00 -0000 1.7 +++ test_al.py 22 Jul 2005 21:48:49 -0000 1.7.20.1 @@ -8,7 +8,7 @@ alattrs = ['__doc__', '__name__', 'getdefault', 'getminmax', 'getname', 'getparams', 'newconfig', 'openport', 'queryparams', 'setparams'] -# This is a very unobtrusive test for the existence of the al module and all it's +# This is a very unobtrusive test for the existence of the al module and all its # attributes. More comprehensive examples can be found in Demo/al def main(): Index: test_cl.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_cl.py,v retrieving revision 1.6 retrieving revision 1.6.20.1 diff -u -d -r1.6 -r1.6.20.1 --- test_cl.py 30 Jul 2002 23:26:01 -0000 1.6 +++ test_cl.py 22 Jul 2005 21:48:49 -0000 1.6.20.1 @@ -64,7 +64,7 @@ # This is a very inobtrusive test for the existence of the cl -# module and all it's attributes. +# module and all its attributes. def main(): # touch all the attributes of al without doing anything Index: test_unicodedata.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_unicodedata.py,v retrieving revision 1.11 retrieving revision 1.11.2.1 diff -u -d -r1.11 -r1.11.2.1 --- test_unicodedata.py 4 Aug 2004 07:38:33 -0000 1.11 +++ test_unicodedata.py 22 Jul 2005 21:48:49 -0000 1.11.2.1 @@ -191,7 +191,7 @@ def test_decimal_numeric_consistent(self): # Test that decimal and numeric are consistent, # i.e. if a character has a decimal value, - # it's numeric value should be the same. + # its numeric value should be the same. count = 0 for i in xrange(0x10000): c = unichr(i) @@ -204,7 +204,7 @@ def test_digit_numeric_consistent(self): # Test that digit and numeric are consistent, # i.e. if a character has a digit value, - # it's numeric value should be the same. + # its numeric value should be the same. count = 0 for i in xrange(0x10000): c = unichr(i) Index: test_minidom.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_minidom.py,v retrieving revision 1.39 retrieving revision 1.39.4.1 diff -u -d -r1.39 -r1.39.4.1 --- test_minidom.py 12 Feb 2004 17:35:11 -0000 1.39 +++ test_minidom.py 22 Jul 2005 21:48:49 -0000 1.39.4.1 @@ -1199,7 +1199,7 @@ and not a1.isId and a2.isId and not a3.isId) - # renaming an attribute should not affect it's ID-ness: + # renaming an attribute should not affect its ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) @@ -1235,7 +1235,7 @@ confirm(a2.isId) confirm(not a3.isId) confirm(doc.getElementById("v") is None) - # renaming an attribute should not affect it's ID-ness: + # renaming an attribute should not affect its ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) @@ -1271,7 +1271,7 @@ confirm(a2.isId) confirm(not a3.isId) confirm(doc.getElementById("v") is None) - # renaming an attribute should not affect it's ID-ness: + # renaming an attribute should not affect its ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:34 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:34 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1321,1.1322 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Misc Modified Files: NEWS Log Message: Fix all wrong instances of "it's". Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1321 retrieving revision 1.1322 diff -u -d -r1.1321 -r1.1322 --- NEWS 22 Jul 2005 18:39:16 -0000 1.1321 +++ NEWS 22 Jul 2005 21:49:30 -0000 1.1322 @@ -275,7 +275,7 @@ - Enhancements to the csv module: + Dialects are now validated by the underlying C code, better - reflecting it's capabilities, and improving it's compliance with + reflecting its capabilities, and improving its compliance with PEP 305. + Dialect parameter parsing has been re-implemented to improve error reporting. From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:35 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:35 -0700 Subject: [Python-checkins] python/dist/src/PC w9xpopen.c, 1.5, 1.6 getpathp.c, 1.33, 1.34 Message-ID: Update of /cvsroot/python/python/dist/src/PC In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/PC Modified Files: w9xpopen.c getpathp.c Log Message: Fix all wrong instances of "it's". Index: w9xpopen.c =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/w9xpopen.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- w9xpopen.c 14 Jul 2002 22:14:19 -0000 1.5 +++ w9xpopen.c 22 Jul 2005 21:49:32 -0000 1.6 @@ -9,7 +9,7 @@ * This program is to be launched with redirected standard * handles. It will launch the command line specified 16-bit * console based application in the same console, forwarding - * it's own redirected standard handles to the 16-bit child. + * its own redirected standard handles to the 16-bit child. * AKA solution to the problem described in KB: Q150956. */ Index: getpathp.c =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/getpathp.c,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- getpathp.c 7 Aug 2004 19:12:27 -0000 1.33 +++ getpathp.c 22 Jul 2005 21:49:32 -0000 1.34 @@ -11,7 +11,7 @@ * Python always adds an empty entry at the start, which corresponds to the current directory. - * If the PYTHONPATH env. var. exists, it's entries are added next. + * If the PYTHONPATH env. var. exists, its entries are added next. * We look in the registry for "application paths" - that is, sub-keys under the main PythonPath registry key. These are added next (the From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:35 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:35 -0700 Subject: [Python-checkins] python/dist/src/Tools/pynche README, 2.16, 2.17 StripViewer.py, 2.17, 2.18 Message-ID: Update of /cvsroot/python/python/dist/src/Tools/pynche In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Tools/pynche Modified Files: README StripViewer.py Log Message: Fix all wrong instances of "it's". Index: README =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/pynche/README,v retrieving revision 2.16 retrieving revision 2.17 diff -u -d -r2.16 -r2.17 --- README 23 Aug 2001 16:15:21 -0000 2.16 +++ README 22 Jul 2005 21:49:32 -0000 2.17 @@ -107,7 +107,7 @@ master[*] the master window to use as the parent of the modal dialog. Without this argument, pyColorChooser will create - it's own Tkinter.Tk instance as the master. This may not + its own Tkinter.Tk instance as the master. This may not be what you want. databasefile Index: StripViewer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Tools/pynche/StripViewer.py,v retrieving revision 2.17 retrieving revision 2.18 diff -u -d -r2.17 -r2.18 --- StripViewer.py 18 Jul 2004 06:02:04 -0000 2.17 +++ StripViewer.py 22 Jul 2005 21:49:32 -0000 2.18 @@ -268,7 +268,7 @@ else: # decimal text = repr(coloraxis) - # move the arrow, and set it's text + # move the arrow, and set its text if coloraxis <= 128: # use the left arrow self.__leftarrow.set_text(text) From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:35 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:35 -0700 Subject: [Python-checkins] python/dist/src/PC/os2emx getpathp.c,1.4,1.5 Message-ID: Update of /cvsroot/python/python/dist/src/PC/os2emx In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/PC/os2emx Modified Files: getpathp.c Log Message: Fix all wrong instances of "it's". Index: getpathp.c =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/os2emx/getpathp.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- getpathp.c 12 Dec 2004 08:27:31 -0000 1.4 +++ getpathp.c 22 Jul 2005 21:49:32 -0000 1.5 @@ -11,7 +11,7 @@ * Python always adds an empty entry at the start, which corresponds to the current directory. - * If the PYTHONPATH env. var. exists, it's entries are added next. + * If the PYTHONPATH env. var. exists, its entries are added next. * We attempt to locate the "Python Home" - if the PYTHONHOME env var is set, we believe it. Otherwise, we use the path of our host .EXE's From birkenfeld at users.sourceforge.net Fri Jul 22 23:49:58 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:49:58 -0700 Subject: [Python-checkins] python/dist/src/Doc/dist dist.tex,1.95,1.96 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/dist In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Doc/dist Modified Files: dist.tex Log Message: Fix all wrong instances of "it's". Index: dist.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/dist/dist.tex,v retrieving revision 1.95 retrieving revision 1.96 diff -u -d -r1.95 -r1.96 --- dist.tex 18 Jun 2005 20:11:40 -0000 1.95 +++ dist.tex 22 Jul 2005 21:49:26 -0000 1.96 @@ -2294,7 +2294,7 @@ \begin{classdesc*}{Extension} The Extension class describes a single C or \Cpp extension module in a -setup script. It accepts the following keyword arguments in it's +setup script. It accepts the following keyword arguments in its constructor \begin{tableiii}{c|l|l}{argument name}{argument name}{value}{type} @@ -2354,7 +2354,7 @@ \end{classdesc*} \begin{classdesc*}{Command} -A \class{Command} class (or rather, an instance of one of it's subclasses) +A \class{Command} class (or rather, an instance of one of its subclasses) implement a single distutils command. \end{classdesc*} @@ -2443,7 +2443,7 @@ (don't actually execute the steps) and \var{force} (rebuild everything, regardless of dependencies). All of these flags default to \code{0} (off). Note that you probably don't want to instantiate -\class{CCompiler} or one of it's subclasses directly - use the +\class{CCompiler} or one of its subclasses directly - use the \function{distutils.CCompiler.new_compiler()} factory function instead. @@ -3323,7 +3323,7 @@ The option_table is a list of 3-tuples: \samp{(long_option, short_option, help_string)} -If an option takes an argument, it's \var{long_option} should have \code{'='} +If an option takes an argument, its \var{long_option} should have \code{'='} appended; \var{short_option} should just be a single character, no \code{':'} in any case. \var{short_option} should be \code{None} if a \var{long_option} doesn't have a corresponding \var{short_option}. All option tuples must have From birkenfeld at users.sourceforge.net Fri Jul 22 23:50:01 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:50:01 -0700 Subject: [Python-checkins] python/dist/src/Doc Makefile,1.280,1.281 Message-ID: Update of /cvsroot/python/python/dist/src/Doc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Doc Modified Files: Makefile Log Message: Fix all wrong instances of "it's". Index: Makefile =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/Makefile,v retrieving revision 1.280 retrieving revision 1.281 diff -u -d -r1.280 -r1.281 --- Makefile 1 Dec 2004 05:55:47 -0000 1.280 +++ Makefile 22 Jul 2005 21:49:26 -0000 1.281 @@ -87,7 +87,7 @@ # (e.g. OpenBSD needs package gmake installed; use gmake instead of make) PWD=$(shell pwd) -# (The trailing colon in the value is needed; TeX places it's default +# (The trailing colon in the value is needed; TeX places its default # set of paths at the location of the empty string in the path list.) TEXINPUTS=$(PWD)/commontex: From birkenfeld at users.sourceforge.net Fri Jul 22 23:50:01 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:50:01 -0700 Subject: [Python-checkins] python/dist/src/Doc/perl l2hinit.perl,1.87,1.88 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/perl In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Doc/perl Modified Files: l2hinit.perl Log Message: Fix all wrong instances of "it's". Index: l2hinit.perl =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/perl/l2hinit.perl,v retrieving revision 1.87 retrieving revision 1.88 diff -u -d -r1.87 -r1.88 --- l2hinit.perl 10 Nov 2004 07:48:17 -0000 1.87 +++ l2hinit.perl 22 Jul 2005 21:49:29 -0000 1.88 @@ -98,7 +98,7 @@ $dir =~ s/$dd$//; $TEXINPUTS = "$dir$envkey$mytexinputs"; # Push everything into $TEXINPUTS since LaTeX2HTML doesn't pick - # this up on it's own; we clear $ENV{'TEXINPUTS'} so the value set + # this up on its own; we clear $ENV{'TEXINPUTS'} so the value set # for this by the main LaTeX2HTML script doesn't contain duplicate # directories. if ($ENV{'TEXINPUTS'}) { From birkenfeld at users.sourceforge.net Fri Jul 22 23:50:02 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:50:02 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_cd.py, 1.6, 1.7 test_al.py, 1.7, 1.8 test_cl.py, 1.6, 1.7 test_unicodedata.py, 1.11, 1.12 test_minidom.py, 1.39, 1.40 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Lib/test Modified Files: test_cd.py test_al.py test_cl.py test_unicodedata.py test_minidom.py Log Message: Fix all wrong instances of "it's". Index: test_cd.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_cd.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- test_cd.py 30 Jul 2002 23:26:01 -0000 1.6 +++ test_cd.py 22 Jul 2005 21:49:29 -0000 1.7 @@ -10,7 +10,7 @@ 'ident', 'index', 'msftoframe', 'open', 'pnum', 'ptime'] -# This is a very inobtrusive test for the existence of the cd module and all it's +# This is a very inobtrusive test for the existence of the cd module and all its # attributes. More comprehensive examples can be found in Demo/cd and # require that you have a CD and a CD ROM drive Index: test_al.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_al.py,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- test_al.py 30 Jul 2002 23:26:00 -0000 1.7 +++ test_al.py 22 Jul 2005 21:49:29 -0000 1.8 @@ -8,7 +8,7 @@ alattrs = ['__doc__', '__name__', 'getdefault', 'getminmax', 'getname', 'getparams', 'newconfig', 'openport', 'queryparams', 'setparams'] -# This is a very unobtrusive test for the existence of the al module and all it's +# This is a very unobtrusive test for the existence of the al module and all its # attributes. More comprehensive examples can be found in Demo/al def main(): Index: test_cl.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_cl.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- test_cl.py 30 Jul 2002 23:26:01 -0000 1.6 +++ test_cl.py 22 Jul 2005 21:49:29 -0000 1.7 @@ -64,7 +64,7 @@ # This is a very inobtrusive test for the existence of the cl -# module and all it's attributes. +# module and all its attributes. def main(): # touch all the attributes of al without doing anything Index: test_unicodedata.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_unicodedata.py,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- test_unicodedata.py 4 Aug 2004 07:38:33 -0000 1.11 +++ test_unicodedata.py 22 Jul 2005 21:49:29 -0000 1.12 @@ -191,7 +191,7 @@ def test_decimal_numeric_consistent(self): # Test that decimal and numeric are consistent, # i.e. if a character has a decimal value, - # it's numeric value should be the same. + # its numeric value should be the same. count = 0 for i in xrange(0x10000): c = unichr(i) @@ -204,7 +204,7 @@ def test_digit_numeric_consistent(self): # Test that digit and numeric are consistent, # i.e. if a character has a digit value, - # it's numeric value should be the same. + # its numeric value should be the same. count = 0 for i in xrange(0x10000): c = unichr(i) Index: test_minidom.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_minidom.py,v retrieving revision 1.39 retrieving revision 1.40 diff -u -d -r1.39 -r1.40 --- test_minidom.py 12 Feb 2004 17:35:11 -0000 1.39 +++ test_minidom.py 22 Jul 2005 21:49:29 -0000 1.40 @@ -1199,7 +1199,7 @@ and not a1.isId and a2.isId and not a3.isId) - # renaming an attribute should not affect it's ID-ness: + # renaming an attribute should not affect its ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) @@ -1235,7 +1235,7 @@ confirm(a2.isId) confirm(not a3.isId) confirm(doc.getElementById("v") is None) - # renaming an attribute should not affect it's ID-ness: + # renaming an attribute should not affect its ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) @@ -1271,7 +1271,7 @@ confirm(a2.isId) confirm(not a3.isId) confirm(doc.getElementById("v") is None) - # renaming an attribute should not affect it's ID-ness: + # renaming an attribute should not affect its ID-ness: doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") confirm(e.isSameNode(doc.getElementById("w")) and a2.isId) From birkenfeld at users.sourceforge.net Fri Jul 22 23:50:02 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:50:02 -0700 Subject: [Python-checkins] python/dist/src/Lib/idlelib configDialog.py, 1.61, 1.62 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/idlelib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Lib/idlelib Modified Files: configDialog.py Log Message: Fix all wrong instances of "it's". Index: configDialog.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/idlelib/configDialog.py,v retrieving revision 1.61 retrieving revision 1.62 diff -u -d -r1.61 -r1.62 --- configDialog.py 31 Jan 2005 03:34:26 -0000 1.61 +++ configDialog.py 22 Jul 2005 21:49:29 -0000 1.62 @@ -27,7 +27,7 @@ self.configure(borderwidth=5) self.geometry("+%d+%d" % (parent.winfo_rootx()+20, parent.winfo_rooty()+30)) - #Theme Elements. Each theme element key is it's display name. + #Theme Elements. Each theme element key is its display name. #The first value of the tuple is the sample area tag name. #The second value is the display name list sort index. self.themeElements={'Normal Text':('normal','00'), From birkenfeld at users.sourceforge.net Fri Jul 22 23:50:02 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:50:02 -0700 Subject: [Python-checkins] python/dist/src/Mac/Tools/IDE Wbase.py, 1.15, 1.16 Message-ID: Update of /cvsroot/python/python/dist/src/Mac/Tools/IDE In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Mac/Tools/IDE Modified Files: Wbase.py Log Message: Fix all wrong instances of "it's". Index: Wbase.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Mac/Tools/IDE/Wbase.py,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- Wbase.py 18 Jul 2004 05:58:14 -0000 1.15 +++ Wbase.py 22 Jul 2005 21:49:30 -0000 1.16 @@ -128,28 +128,28 @@ # depending on the values of l(eft), t(op), r(right) and b(ottom), # they mean different things: if l < -1: - # l is less than -1, this mean it measures from the *right* of it's parent + # l is less than -1, this mean it measures from the *right* of its parent l = pr + l else: - # l is -1 or greater, this mean it measures from the *left* of it's parent + # l is -1 or greater, this mean it measures from the *left* of its parent l = pl + l if t < -1: - # t is less than -1, this mean it measures from the *bottom* of it's parent + # t is less than -1, this mean it measures from the *bottom* of its parent t = pb + t else: - # t is -1 or greater, this mean it measures from the *top* of it's parent + # t is -1 or greater, this mean it measures from the *top* of its parent t = pt + t if r > 1: # r is greater than 1, this means r is the *width* of the widget r = l + r else: - # r is less than 1, this means it measures from the *right* of it's parent + # r is less than 1, this means it measures from the *right* of its parent r = pr + r if b > 1: # b is greater than 1, this means b is the *height* of the widget b = t + b else: - # b is less than 1, this means it measures from the *bottom* of it's parent + # b is less than 1, this means it measures from the *bottom* of its parent b = pb + b self._bounds = (l, t, r, b) if oldbounds and oldbounds <> self._bounds: From birkenfeld at users.sourceforge.net Fri Jul 22 23:50:02 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:50:02 -0700 Subject: [Python-checkins] python/dist/src/Lib SimpleXMLRPCServer.py, 1.10, 1.11 tarfile.py, 1.28, 1.29 ConfigParser.py, 1.68, 1.69 difflib.py, 1.28, 1.29 pydoc.py, 1.104, 1.105 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21637/Lib Modified Files: SimpleXMLRPCServer.py tarfile.py ConfigParser.py difflib.py pydoc.py Log Message: Fix all wrong instances of "it's". Index: SimpleXMLRPCServer.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/SimpleXMLRPCServer.py,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- SimpleXMLRPCServer.py 3 Feb 2005 15:01:24 -0000 1.10 +++ SimpleXMLRPCServer.py 22 Jul 2005 21:49:29 -0000 1.11 @@ -170,7 +170,7 @@ If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and - it's parameters as a tuple + its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method @@ -371,7 +371,7 @@ If the registered instance has a _dispatch method then that method will be called with the name of the XML-RPC method and - it's parameters as a tuple + its parameters as a tuple e.g. instance._dispatch('add',(2,3)) If the registered instance does not have a _dispatch method Index: tarfile.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/tarfile.py,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- tarfile.py 28 Mar 2005 01:08:02 -0000 1.28 +++ tarfile.py 22 Jul 2005 21:49:29 -0000 1.29 @@ -1462,7 +1462,7 @@ # stream of tar blocks. raise StreamError, "cannot extract (sym)link as file object" else: - # A (sym)link's file object is it's target's file object. + # A (sym)link's file object is its target's file object. return self.extractfile(self._getmember(tarinfo.linkname, tarinfo)) else: Index: ConfigParser.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/ConfigParser.py,v retrieving revision 1.68 retrieving revision 1.69 diff -u -d -r1.68 -r1.69 --- ConfigParser.py 3 Oct 2004 15:55:09 -0000 1.68 +++ ConfigParser.py 22 Jul 2005 21:49:29 -0000 1.69 @@ -28,7 +28,7 @@ create the parser and specify a dictionary of intrinsic defaults. The keys must be strings, the values must be appropriate for %()s string interpolation. Note that `__name__' is always an intrinsic default; - it's value is the section's name. + its value is the section's name. sections() return all the configuration section names, sans DEFAULT Index: difflib.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/difflib.py,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- difflib.py 12 Nov 2004 16:12:15 -0000 1.28 +++ difflib.py 22 Jul 2005 21:49:29 -0000 1.29 @@ -1371,7 +1371,7 @@ text = ' ' # insert marks that won't be noticed by an xml/html escaper. text = '\0' + format_key + text + '\1' - # Return line of text, first allow user's line formatter to do it's + # Return line of text, first allow user's line formatter to do its # thing (such as adding the line number) then replace the special # marks with what the user's change markup. return (num_lines[side],text) @@ -1472,7 +1472,7 @@ """Yields from/to lines of text with a change indication. This function is an iterator. It itself pulls lines from the line - iterator. It's difference from that iterator is that this function + iterator. Its difference from that iterator is that this function always yields a pair of from/to text lines (with the change indication). If necessary it will collect single from/to lines until it has a matching pair from/to pair to yield. Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.104 retrieving revision 1.105 diff -u -d -r1.104 -r1.105 --- pydoc.py 19 Feb 2005 22:58:26 -0000 1.104 +++ pydoc.py 22 Jul 2005 21:49:29 -0000 1.105 @@ -92,7 +92,7 @@ return name def isdata(object): - """Check if an object is of a type that probably means it's data.""" + """Check if an object is of a type that probably means its data.""" return not (inspect.ismodule(object) or inspect.isclass(object) or inspect.isroutine(object) or inspect.isframe(object) or inspect.istraceback(object) or inspect.iscode(object)) From birkenfeld at users.sourceforge.net Fri Jul 22 23:52:27 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:52:27 -0700 Subject: [Python-checkins] python/dist/src/Lib pydoc.py,1.105,1.106 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23002/Lib Modified Files: pydoc.py Log Message: That was one too much. Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.105 retrieving revision 1.106 diff -u -d -r1.105 -r1.106 --- pydoc.py 22 Jul 2005 21:49:29 -0000 1.105 +++ pydoc.py 22 Jul 2005 21:52:25 -0000 1.106 @@ -92,7 +92,7 @@ return name def isdata(object): - """Check if an object is of a type that probably means its data.""" + """Check if an object is of a type that probably means it's data.""" return not (inspect.ismodule(object) or inspect.isclass(object) or inspect.isroutine(object) or inspect.isframe(object) or inspect.istraceback(object) or inspect.iscode(object)) From birkenfeld at users.sourceforge.net Fri Jul 22 23:52:35 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Fri, 22 Jul 2005 14:52:35 -0700 Subject: [Python-checkins] python/dist/src/Lib pydoc.py, 1.100.2.3, 1.100.2.4 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23010/Lib Modified Files: Tag: release24-maint pydoc.py Log Message: That was one too much. Index: pydoc.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/pydoc.py,v retrieving revision 1.100.2.3 retrieving revision 1.100.2.4 diff -u -d -r1.100.2.3 -r1.100.2.4 --- pydoc.py 22 Jul 2005 21:48:50 -0000 1.100.2.3 +++ pydoc.py 22 Jul 2005 21:52:33 -0000 1.100.2.4 @@ -92,7 +92,7 @@ return name def isdata(object): - """Check if an object is of a type that probably means its data.""" + """Check if an object is of a type that probably means it's data.""" return not (inspect.ismodule(object) or inspect.isclass(object) or inspect.isroutine(object) or inspect.isframe(object) or inspect.istraceback(object) or inspect.iscode(object)) From birkenfeld at users.sourceforge.net Sat Jul 23 11:27:42 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 23 Jul 2005 02:27:42 -0700 Subject: [Python-checkins] python/nondist/sandbox/path path.py, 1.1, 1.2 test_path.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18577 Modified Files: path.py test_path.py Log Message: Path inherits from str or unicode again. Index: path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/path.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- path.py 18 Jul 2005 12:09:26 -0000 1.1 +++ path.py 23 Jul 2005 09:27:40 -0000 1.2 @@ -38,14 +38,12 @@ if hasattr(file, 'newlines'): _textmode = 'U' -# helper function: if given string/unicode, return it -# if given path, return path string -def _strpath(thing): - if isinstance(thing, Path): - return thing._p - return thing +if os.path.supports_unicode_filenames: + _base = unicode +else: + _base = str -class Path(object): +class Path(_base): """ Represents a filesystem path. Path is an immutable object. @@ -56,35 +54,40 @@ # --- Special Python methods. - def __init__(self, path=os.curdir): + def __new__(typ, *args): """ Initialize a Path instance. - The path argument can be either a string or an existing Path object. + The argument can be either a string or an existing Path object. """ - if isinstance(path, Path): - self._p = path._p - else: - self._p = path + if not args: + return Path(os.curdir) + return _base.__new__(typ, *args) def __repr__(self): - return 'Path(%s)' % repr(self._p) + return 'Path(%s)' % repr(_base(self)) def __str__(self): - return str(self._p) + if _base is unicode: + return str(self[:]) + else: + return self[:] + + def __unicode__(self): + if _base is unicode: + return self[:] + else: + return unicode(self[:]) # Adding path and string yields a path + # Caution: this is not a join! def __add__(self, other): - if isinstance(other, (str, unicode)): - return Path(self._p + other) - elif isinstance(other, Path): - return Path(self._p + other._p) + if isinstance(other, basestring): + return Path(_base(self) + other) return NotImplemented def __radd__(self, other): - if isinstance(other, (str, unicode)): - return Path(other + self._p) - elif isinstance(other, Path): - return Path(other._p + self._p) + if isinstance(other, basestring): + return Path(other + _base(self)) return NotImplemented # The / joins paths @@ -95,32 +98,28 @@ # Rich comparison def __eq__(self, other): - return isinstance(other, Path) and (self._p == other._p) + return isinstance(other, Path) and _base.__eq__(self, other) def __ne__(self, other): - return (not isinstance(other, Path)) or (self._p != other._p) + return (not isinstance(other, Path)) or _base.__ne__(self, other) def __lt__(self, other): if isinstance(other, Path): - return self._p < other._p + return _base.__lt__(self, other) return NotImplemented def __le__(self, other): if isinstance(other, Path): - return self._p <= other._p + return _base.__le__(self, other) return NotImplemented def __gt__(self, other): if isinstance(other, Path): - return self._p > other._p + return _base.__gt__(self, other) return NotImplemented def __ge__(self, other): if isinstance(other, Path): - return self._p >= other._p + return _base.__ge__(self, other) return NotImplemented - # Hash like strings - def __hash__(self): - return hash(self._p) + 1 - # Alternative constructor. @staticmethod @@ -132,30 +131,27 @@ return Path(os.getcwd()) - # --- Operations which yield strings + # --- Operations which return strings + + basename = property( + os.path.basename, None, None, + """ The name of this file or directory without the full path. + + For example, path('/usr/local/lib/libpython.so').basename == 'libpython.so' + """) - def _get_basename(self): - return os.path.basename(self._p) - def _get_namebase(self): base, ext = os.path.splitext(self.basename) return base def _get_ext(self): - f, ext = os.path.splitext(self._p) + f, ext = os.path.splitext(self) return ext def _get_drive(self): - drive, r = os.path.splitdrive(self._p) + drive, r = os.path.splitdrive(self) return drive - basename = property( - _get_basename, None, None, - """ The name of this file or directory without the full path. - - For example, path('/usr/local/lib/libpython.so').basename == 'libpython.so' - """) - namebase = property( _get_namebase, None, None, """ The same as Path.basename, but with one file extension stripped off. @@ -174,25 +170,25 @@ This is always empty on systems that don't use drive specifiers. """) - # --- Operations which yield Path objects + # --- Operations which return Path objects def abspath(self): - return Path(os.path.abspath(self._p)) + return Path(os.path.abspath(self)) def normcase(self): - return Path(os.path.normcase(self._p)) + return Path(os.path.normcase(self)) def normpath(self): - return Path(os.path.normpath(self._p)) + return Path(os.path.normpath(self)) def realpath(self): - return Path(os.path.realpath(self._p)) + return Path(os.path.realpath(self)) def expanduser(self): - return Path(os.path.expanduser(self._p)) + return Path(os.path.expanduser(self)) def expandvars(self): - return Path(os.path.expandvars(self._p)) + return Path(os.path.expandvars(self)) def expand(self): """ Clean up a filename by calling expandvars(), @@ -204,7 +200,7 @@ return self.expandvars().expanduser().normpath() def _get_directory(self): - return Path(os.path.dirname(self._p)) + return Path(os.path.dirname(self)) directory = property( _get_directory, None, None, @@ -221,11 +217,11 @@ """ return self.splitext()[0] - # --- Operations which yield Paths and strings + # --- Operations which return Paths and strings def splitpath(self): """ p.splitpath() -> Return (p.directory, p.basename). """ - parent, child = os.path.split(self._p) + parent, child = os.path.split(self) return Path(parent), child def splitdrive(self): @@ -235,7 +231,7 @@ no drive specifier, p.drive is empty, so the return value is simply (Path(''), p). This is always the case on Unix. """ - drive, rel = os.path.splitdrive(self._p) + drive, rel = os.path.splitdrive(self) return Path(drive), rel def splitext(self): @@ -247,16 +243,16 @@ The extension is everything from '.' to the end of the last path segment. """ - filename, ext = os.path.splitext(self._p) + filename, ext = os.path.splitext(self) return Path(filename), ext if hasattr(os.path, 'splitunc'): def splitunc(self): - unc, rest = os.path.splitunc(self._p) + unc, rest = os.path.splitunc(self) return Path(unc), rest def _get_uncshare(self): - unc, r = os.path.splitunc(self._p) + unc, r = os.path.splitunc(self) return Path(unc) uncshare = property( @@ -275,7 +271,9 @@ character (os.sep) if needed. Returns a new path object. """ - return Path(os.path.join(self._p, *map(str, args))) + return Path(os.path.join(self, *map(_base, args))) + + joinpath = joinwith def parts(self): """ Return a list of the path components in this path. @@ -346,7 +344,7 @@ # --- Listing, searching, walking, and matching def listdir(self): - return [Path(p) for p in os.listdir(self._p)] + return [Path(p) for p in os.listdir(self)] def children(self, pattern=None): """ D.children() -> List of items in this directory, @@ -360,7 +358,7 @@ With the optional 'pattern' argument, this only lists items whose names match the given pattern. """ - names = os.listdir(self._p) + names = os.listdir(self) if pattern is not None: names = fnmatch.filter(names, pattern) return [self / child for child in names] @@ -454,16 +452,16 @@ For example, path('/users').glob('*/bin/*') returns a list of all the files users have in their bin directories. """ - return map(Path, glob.glob((self / pattern)._p)) + return map(Path, glob.glob(self / pattern)) # --- Reading or writing an entire file at once. def open(self, mode='r'): """ Open this file. Return a file object. """ - return file(self._p, mode) + return file(self, mode) - def get_file_bytes(self): + def read_file_bytes(self): """ Open this file, read all bytes, return them as a string. """ f = self.open('rb') try: @@ -487,7 +485,7 @@ finally: f.close() - def get_file_text(self, encoding=None, errors='strict'): + def read_file_text(self, encoding=None, errors='strict'): """ Open this file, read it in, return the content as a string. This uses 'U' mode in Python 2.3 and later, so '\r\n' and '\r' @@ -511,7 +509,7 @@ f.close() else: # Unicode - f = codecs.open(self._p, 'r', encoding, errors) + f = codecs.open(self, 'r', encoding, errors) # (Note - Can't use 'U' mode here, since codecs.open # doesn't support 'U' mode, even in Python 2.3.) try: @@ -613,7 +611,7 @@ self.write_file_bytes(bytes, append) - def get_file_lines(self, encoding=None, errors='strict', retain=True): + def read_file_lines(self, encoding=None, errors='strict', retain=True): """ Open this file, read all lines, return them in a list. Optional arguments: @@ -637,7 +635,7 @@ finally: f.close() else: - return self.get_file_text(encoding, errors).splitlines(retain) + return self.read_file_text(encoding, errors).splitlines(retain) def write_file_lines(self, lines, encoding=None, errors='strict', linesep=os.linesep, append=False): @@ -707,40 +705,27 @@ # --- Methods for querying the filesystem. - def exists(self): - return os.path.exists(self._p) - - def isabs(self): - return os.path.isabs(self._p) + exists = os.path.exists + isabs = os.path.isabs + isdir = os.path.isdir + isfile = os.path.isfile + islink = os.path.islink + ismount = os.path.ismount - def isdir(self): - return os.path.isdir(self._p) - - def isfile(self): - return os.path.isfile(self._p) - - def islink(self): - return os.path.islink(self._p) - - def ismount(self): - return os.path.ismount(self._p) - if hasattr(os.path, 'samefile'): - def samefile(self): - return os.path.samefile(self._p) + samefile = os.path.samefile def atime(self): - return os.path.getatime(self._p) + return os.path.getatime(self) def mtime(self): - return os.path.getmtime(self._p) + return os.path.getmtime(self) if hasattr(os.path, 'getctime'): def ctime(self): - return os.path.getctime(self._p) + return os.path.getctime(self) - def getsize(self): - return os.path.getsize(self._p) + getsize = os.path.getsize if hasattr(os, 'access'): def access(self, mode): @@ -748,59 +733,58 @@ mode - One of the constants os.F_OK, os.R_OK, os.W_OK, os.X_OK """ - return os.access(self._p, mode) + return os.access(self, mode) def stat(self): """ Perform a stat() system call on this path. """ - return os.stat(self._p) + return os.stat(self) def lstat(self): """ Like path.stat(), but do not follow symbolic links. """ - return os.lstat(self._p) + return os.lstat(self) if hasattr(os, 'statvfs'): def statvfs(self): """ Perform a statvfs() system call on this path. """ - return os.statvfs(self._p) + return os.statvfs(self) if hasattr(os, 'pathconf'): def pathconf(self, name): - return os.pathconf(self._p, name) - + return os.pathconf(self, name) # --- Modifying operations on files and directories def utime(self, times): """ Set the access and modified times of this file. """ - os.utime(self._p, times) + os.utime(self, times) def chmod(self, mode): - os.chmod(self._p, mode) + os.chmod(self, mode) if hasattr(os, 'chown'): def chown(self, uid, gid): - os.chown(self._p, uid, gid) + os.chown(self, uid, gid) def rename(self, new): - os.rename(self._p, _strpath(new)) + os.rename(self, new) def renames(self, new): - os.renames(self._p, _strpath(new)) + os.renames(self, new) # --- Create/delete operations on directories def mkdir(self, mode=0777): - os.mkdir(self._p, mode) + os.mkdir(self, mode) def makedirs(self, mode=0777): - os.makedirs(self._p, mode) + os.makedirs(self, mode) def rmdir(self): - os.rmdir(self._p) + os.rmdir(self) def removedirs(self): - os.removedirs(self._p) + os.removedirs(self) # --- Modifying operations on files @@ -816,15 +800,15 @@ mode = os.umask(0) os.umask(mode) mode = mode ^ 0777 - fd = os.open(self._p, os.O_WRONLY | os.O_CREAT, mode) + fd = os.open(self, os.O_WRONLY | os.O_CREAT, mode) os.close(fd) self.utime(None) - + def remove(self): - os.remove(self._p) + os.remove(self) def unlink(self): - os.unlink(self._p) + os.unlink(self) # --- Links @@ -832,12 +816,12 @@ if hasattr(os, 'link'): def link(self, newpath): """ Create a hard link at 'newpath', pointing to this file. """ - os.link(self._p, _strpath(newpath)) + os.link(self, newpath) if hasattr(os, 'symlink'): def symlink(self, newlink): """ Create a symbolic link at 'newlink', pointing here. """ - os.symlink(self._p, _strpath(newlink)) + os.symlink(self, newlink) if hasattr(os, 'readlink'): def readlink(self): @@ -845,7 +829,7 @@ The result may be an absolute or a relative path. """ - return Path(os.readlink(self._p)) + return Path(os.readlink(self)) def readlinkabs(self): """ Return the path to which this symbolic link points. @@ -858,39 +842,25 @@ else: return (self.directory / p).abspath() - # --- High-level shutils functions - - def copyfile(self, dst): - return shutil.copyfile(self._p, _strpath(dst)) - - def copymode(self, dst): - return shutil.copymode(self._p, _strpath(dst)) - - def copystat(self, dst): - return shutil.copystat(self._p, _strpath(dst)) - - def copy(self, dst): - return shutil.copy(self._p, _strpath(dst)) - - def copy2(self, dst): - return shutil.copy2(self._p, _strpath(dst)) - - def copytree(self, dst, symlinks=False): - return shutil.copytree(self._p, _strpath(dst), symlinks) - - def rmtree(self, ignore_errors=False, onerror=None): - return shutil.rmtree(self._p, ignore_errors, onerror) + # --- High-level functions from shutil - def move(self, dst): - return shutil.move(self._p, _strpath(dst)) + copyfile = shutil.copyfile + copymode = shutil.copymode + copystat = shutil.copystat + copy = shutil.copy + copy2 = shutil.copy2 + copytree = shutil.copytree + if hasattr(shutil, 'move'): + move = shutil.move + rmtree = shutil.rmtree # --- Special stuff from os if hasattr(os, 'chroot'): def chroot(self): - os.chroot(self._p) + os.chroot(self) if hasattr(os, 'startfile'): def startfile(self): - os.startfile(self._p) + os.startfile(self) Index: test_path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/test_path.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- test_path.py 18 Jul 2005 12:09:26 -0000 1.1 +++ test_path.py 23 Jul 2005 09:27:40 -0000 1.2 @@ -21,14 +21,15 @@ import codecs, os, random, shutil, tempfile, time from path import Path + def p(**choices): """ Choose a value from several possible values, based on os.name """ - return Path(choices[os.name]) + return choices[os.name] class BasicTestCase(unittest.TestCase): def testRelpath(self): - root = p(nt='C:\\', posix='/') - + root = Path(p(nt='C:\\', + posix='/')) foo = root / 'foo' quux = foo / 'quux' bar = foo / 'bar' @@ -57,34 +58,59 @@ d = Path('D:\\') self.assertEqual(d.relpathto(boz), boz) + ## this isn't going to work cause Paths won't compare + ## with ordinary strings + ''' + def testStringCompatibility(self): + """ Test compatibility with ordinary strings. """ + #x = Path('xyzzy') + #self.assertEqual(x, 'xyzzy') + #self.assertEqual(x, u'xyzzy') + + # sorting + items = [Path('fhj'), + Path('fgh'), + 'E', + Path('d'), + 'A', + Path('B'), + 'c'] + items.sort() + self.assert_(items == ['A', 'B', 'E', 'c', 'd', 'fgh', 'fhj']) + ''' + def testProperties(self): # Create sample Path object. f = p(nt='C:\\Program Files\\Python\\Lib\\xyzzy.py', posix='/usr/local/python/lib/xyzzy.py') + f = Path(f) # .directory - self.assertEqual(f.directory, p(nt='C:\\Program Files\\Python\\Lib', - posix='/usr/local/python/lib')) + self.assertEqual(f.directory, Path(p(nt='C:\\Program Files\\Python\\Lib', + posix='/usr/local/python/lib'))) # .basename self.assertEqual(f.basename, 'xyzzy.py') - self.assertEqual(f.directory.basename, str(p(nt='Lib', posix='lib'))) + self.assertEqual(f.directory.basename, p(nt='Lib', posix='lib')) # .ext self.assertEqual(f.ext, '.py') self.assertEqual(f.directory.ext, '') # .drive - self.assertEqual(f.drive, str(p(nt='C:', posix=''))) + self.assertEqual(f.drive, p(nt='C:', posix='')) def testMethods(self): # .abspath() self.assertEqual(Path().abspath(), Path.cwd()) - # .getcwd() + # .cwd() cwd = Path.cwd() self.assert_(isinstance(cwd, Path)) - self.assertEqual(cwd, Path.cwd()) + if os.path.supports_unicode_filenames: + self.assertEqual(unicode(cwd), os.getcwdu()) + else: + self.assertEqual(str(cwd), os.getcwd()) def testUNC(self): if hasattr(os.path, 'splitunc'): @@ -126,12 +152,12 @@ ct = f.ctime() self.assert_(t0 <= ct <= t1) - time.sleep(4) - fobj = f.open('ab') + time.sleep(5) + fobj = file(f, 'ab') fobj.write('some bytes') fobj.close() - time.sleep(4) + time.sleep(5) t2 = time.time() - 3 f.touch() t3 = time.time() + 3 @@ -161,12 +187,12 @@ f = 'testfile.txt' af = d / f - self.assertEqual(str(af), os.path.join(str(d), f)) + self.assertEqual(af, os.path.join(d, f)) af.touch() try: self.assert_(af.exists()) - self.assertEqual(d.listdir(), [Path(f)]) + self.assertEqual(d.children(), [af]) # .glob() self.assertEqual(d.glob('testfile.txt'), [af]) @@ -182,7 +208,7 @@ # Try a test with 20 files files = [d / ('%d.txt' % i) for i in range(20)] for f in files: - fobj = f.open('w') + fobj = file(f, 'w') fobj.write('some text\n') fobj.close() try: @@ -224,7 +250,7 @@ self.failIf(foo.exists()) self.assert_(d.exists()) finally: - os.remove(str(tempf)) + os.remove(tempf) def assertSetsEqual(self, a, b): ad = {} @@ -253,20 +279,20 @@ testA.mkdir() testB.mkdir() - f = testFile.open('w') + f = open(testFile, 'w') f.write('x' * 10000) f.close() # Test simple file copying. testFile.copyfile(testCopy) self.assert_(testCopy.isfile()) - self.assert_(testFile.get_file_bytes() == testCopy.get_file_bytes()) + self.assert_(testFile.read_file_bytes() == testCopy.read_file_bytes()) # Test copying into a directory. testCopy2 = testA / testFile.basename testFile.copy(testA) self.assert_(testCopy2.isfile()) - self.assert_(testFile.get_file_bytes() == testCopy2.get_file_bytes()) + self.assert_(testFile.read_file_bytes() == testCopy2.read_file_bytes()) # Make a link for the next test to use. if hasattr(os, 'symlink'): @@ -375,16 +401,16 @@ u'hanging'] # write bytes manually to file - f = codecs.open(str(p), 'w', enc) + f = codecs.open(p, 'w', enc) f.write(given) f.close() - # test all 3 path read-fully functions, including - # Path.lines() in unicode mode. - self.assertEqual(p.get_file_bytes(), given.encode(enc)) - self.assertEqual(p.get_file_text(enc), clean) - self.assertEqual(p.get_file_lines(enc), expectedLines) - self.assertEqual(p.get_file_lines(enc, retain=False), expectedLines2) + # test all 3 Path read-fully functions, including + # Path.read_file_lines() in unicode mode. + self.assertEqual(p.read_file_bytes(), given.encode(enc)) + self.assertEqual(p.read_file_text(enc), clean) + self.assertEqual(p.read_file_lines(enc), expectedLines) + self.assertEqual(p.read_file_lines(enc, retain=False), expectedLines2) # If this is UTF-16, that's enough. # The rest of these will unfortunately fail because append=True mode @@ -393,7 +419,7 @@ if enc == 'UTF-16': return - # Write Unicode to file using Path.write_text(). + # Write Unicode to file using Path.write_file_text(). cleanNoHanging = clean + u'\n' # This test doesn't work with a hanging line. p.write_file_text(cleanNoHanging, enc) p.write_file_text(cleanNoHanging, enc, append=True) @@ -401,17 +427,17 @@ expectedBytes = 2 * cleanNoHanging.replace('\n', os.linesep).encode(enc) expectedLinesNoHanging = expectedLines[:] expectedLinesNoHanging[-1] += '\n' - self.assertEqual(p.get_file_bytes(), expectedBytes) - self.assertEqual(p.get_file_text(enc), 2 * cleanNoHanging) - self.assertEqual(p.get_file_lines(enc), 2 * expectedLinesNoHanging) - self.assertEqual(p.get_file_lines(enc, retain=False), 2 * expectedLines2) + self.assertEqual(p.read_file_bytes(), expectedBytes) + self.assertEqual(p.read_file_text(enc), 2 * cleanNoHanging) + self.assertEqual(p.read_file_lines(enc), 2 * expectedLinesNoHanging) + self.assertEqual(p.read_file_lines(enc, retain=False), 2 * expectedLines2) # Write Unicode to file using Path.write_file_lines(). # The output in the file should be exactly the same as last time. p.write_file_lines(expectedLines, enc) p.write_file_lines(expectedLines2, enc, append=True) # Check the result. - self.assertEqual(p.get_file_bytes(), expectedBytes) + self.assertEqual(p.read_file_bytes(), expectedBytes) # Now: same test, but using various newline sequences. # If linesep is being properly applied, these will be converted @@ -419,7 +445,7 @@ p.write_file_lines(givenLines, enc) p.write_file_lines(givenLines, enc, append=True) # Check the result. - self.assertEqual(p.get_file_bytes(), expectedBytes) + self.assertEqual(p.read_file_bytes(), expectedBytes) # Same test, using newline sequences that are different # from the platform default. @@ -427,7 +453,7 @@ p.write_file_lines(givenLines, enc, linesep=eol) p.write_file_lines(givenLines, enc, linesep=eol, append=True) expected = 2 * cleanNoHanging.replace(u'\n', eol).encode(enc) - self.assertEqual(p.get_file_bytes(), expected) + self.assertEqual(p.read_file_bytes(), expected) testLinesep(u'\n') testLinesep(u'\r') @@ -440,12 +466,12 @@ p.write_file_lines(givenLines, enc, linesep=None, append=True) # Check the result. expectedBytes = 2 * given.encode(enc) - self.assertEqual(p.get_file_bytes(), expectedBytes) - self.assertEqual(p.get_file_text(enc), 2 * clean) + self.assertEqual(p.read_file_bytes(), expectedBytes) + self.assertEqual(p.read_file_text(enc), 2 * clean) expectedResultLines = expectedLines[:] expectedResultLines[-1] += expectedLines[0] expectedResultLines += expectedLines[1:] - self.assertEqual(p.get_file_lines(enc), expectedResultLines) + self.assertEqual(p.read_file_lines(enc), expectedResultLines) test('UTF-8') test('UTF-16BE') From python at dynkin.com Sat Jul 23 14:40:51 2005 From: python at dynkin.com (George Yoshida) Date: Sat, 23 Jul 2005 21:40:51 +0900 Subject: [Python-checkins] python/nondist/sandbox/path path.py, 1.1, 1.2 test_path.py, 1.1, 1.2 In-Reply-To: References: Message-ID: <42E23AD3.6090403@dynkin.com> birkenfeld at users.sourceforge.net wrote: > Update of /cvsroot/python/python/nondist/sandbox/path > In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18577 > > Modified Files: > path.py test_path.py > Log Message: > Path inherits from str or unicode again. > > if os.path.supports_unicode_filenames: > _base = unicode > else: > _base = str str and unicode are not interchangeable. >>> set(vars(str)) - set(vars(unicode)) set(['__ne__', '__le__', '__gt__', '__lt__', '__eq__', '__ge__']) For example, if _base is unicode, _base.__eq__(self, other) raises AttributeError. -- george From pje at users.sourceforge.net Sun Jul 24 04:38:22 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 23 Jul 2005 19:38:22 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools sandbox.py, 1.4, 1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7019/setuptools Modified Files: sandbox.py Log Message: Fixed the setup script sandbox facility not recognizing certain paths as valid on case-insensitive platforms. Index: sandbox.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/sandbox.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- sandbox.py 10 Jul 2005 04:49:31 -0000 1.4 +++ sandbox.py 24 Jul 2005 02:38:20 -0000 1.5 @@ -150,7 +150,7 @@ ]) def __init__(self,sandbox): - self._sandbox = os.path.realpath(sandbox) + self._sandbox = os.path.normcase(os.path.realpath(sandbox)) self._prefix = os.path.join(self._sandbox,'') AbstractSandbox.__init__(self) @@ -169,7 +169,7 @@ active = self._active try: self._active = False - realpath = os.path.realpath(path) + realpath = os.path.normcase(os.path.realpath(path)) if realpath==self._sandbox or realpath.startswith(self._prefix): return True finally: From pje at users.sourceforge.net Sun Jul 24 04:41:46 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 23 Jul 2005 19:41:46 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.47, 1.48 setuptools.txt, 1.20, 1.21 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7421 Modified Files: EasyInstall.txt setuptools.txt Log Message: Implement --editable option, which allows you to just download and extract (or check out from Subversion) one or more source distributions, without actually building or installing them (or their dependencies). Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.47 retrieving revision 1.48 diff -u -d -r1.47 -r1.48 --- EasyInstall.txt 21 Jul 2005 16:11:33 -0000 1.47 +++ EasyInstall.txt 24 Jul 2005 02:41:43 -0000 1.48 @@ -88,6 +88,17 @@ easy_install . +**Example 7**. (New in 0.6a1) Find a source distribution or Subversion +checkout URL for a package, and extract it or check it out to +``~/projects/sqlobject`` (the name will always be in all-lowercase), where it +can be examined or edited. (The package will not be installed, but it can +easily be installed with ``easy_install ~/projects/sqlobject``. See `Editing +and Viewing Source Packages`_ below for more info.):: + + easy_install --editable --build-directory ~/projects SQLObject + +Note: + Easy Install accepts URLs, filenames, PyPI package names (i.e., ``distutils`` "distribution" names), and package+version specifiers. In each case, it will attempt to locate the latest available version that meets your criteria. @@ -270,6 +281,44 @@ more documentation on using distutils configuration files. +Editing and Viewing Source Packages +----------------------------------- + +Sometimes a package's source distribution contains additional documentation, +examples, configuration files, etc., that are not part of its actual code. If +you want to be able to examine these files, you can use the ``--editable`` +option to EasyInstall, and EasyInstall will look for a source distribution +or Subversion URL for the package, then download and extract it or check it out +as a subdirectory of the ``--build-directory`` you specify. If you then wish +to install the package after editing or configuring it, you can do so by +rerunning EasyInstall with that directory as the target. + +Note that using ``--editable`` stops EasyInstall from actually building or +installing the package; it just finds, obtains, and possibly unpacks it for +you. This allows you to make changes to the package if necessary, and to +either install it in development mode using ``setup.py develop`` (if the +package uses setuptools, that is), or by running ``easy_install projectdir`` +(where ``projectdir`` is the subdirectory EasyInstall created for the +downloaded package. + +In order to use ``--editable`` (``-e`` for short), you *must* also supply a +``--build-directory`` (``-b`` for short). The project will be placed in a +subdirectory of the build directory. The subdirectory will have the same +name as the project itself, but in all-lowercase. If a file or directory of +that name already exists, EasyInstall will print an error message and exit. + +Also, when using ``--editable``, you cannot use URLs or filenames as arguments. +You *must* specify project names (and optional version requirements) so that +EasyInstall knows what directory name(s) to create. If you need to force +EasyInstall to use a particular URL or filename, you should specify it as a +``--find-links`` item (``-f`` for short), and then also specify +the project name, e.g.:: + + easy_install -eb ~/projects \ + -fhttp://prdownloads.sourceforge.net/ctypes/ctypes-0.9.6.tar.gz?download \ + ctypes==0.9.6 + + Dealing with Installation Conflicts ----------------------------------- @@ -530,16 +579,26 @@ package, and those download pages will be searched for links to download an egg or source distribution. -``--build-directory=DIR, -b DIR`` (New in 0.3a3) - Set the directory used to download, extract, and install the package. The - directory is not cleared before or after installation, so the downloaded - packages and extracted contents will remain there afterwards, allowing you - to read any documentation, examples, scripts, etc. that may have been - included with the source distribution (if any). +``--editable, -e`` (New in 0.6a1) + Only find and download source distributions for the specified projects, + unpacking them to subdirectories of the specified ``--build-directory``. + EasyInstall will not actually build or install the requested projects or + their dependencies; it will just find and extract them for you. See + `Editing and Viewing Source Packages`_ above for more details. + +``--build-directory=DIR, -b DIR`` (UPDATED in 0.6a1) + Set the directory used to build source packages. If a package is built + from a source distribution or checkout, it will be extracted to a + subdirectory of the specified directory. The subdirectory will have the + same name as the extracted distribution's project, but in all-lowercase. + If a file or directory of that name already exists in the given directory, + a warning will be printed to the console, and the build will take place in + a temporary directory instead. - This option can only be used when you are specifying a single installation - URL or filename, so that the installer will not be confused by the presence - of multiple ``setup.py`` files in the build directory. + This option is most useful in combination with the ``--editable`` option, + which forces EasyInstall to *only* find and extract (but not build and + install) source distributions. See `Editing and Viewing Source Packages`_, + above, for more information. ``--verbose, -v, --quiet, -q`` (New in 0.4a4) Control the level of detail of EasyInstall's progress messages. The @@ -649,6 +708,13 @@ i.e., all non-alphanumeric runs must be condensed to single underscore characters. + * Added the ``--editable`` option; see `Editing and Viewing Source Packages`_ + above for more info. Also, slightly changed the behavior of the + ``--build-directory`` option. + + * Fixed the setup script sandbox facility not recognizing certain paths as + valid on case-insensitive platforms. + 0.5a12 * Fix ``python -m easy_install`` not working due to setuptools being installed as a zipfile. Update safety scanner to check for modules that might be used @@ -689,7 +755,7 @@ * Added the ``--always-unzip/-Z`` option, to force unzipping of packages that would ordinarily be considered safe to unzip, and changed the meaning of ``--zip-ok/-z`` to "always leave everything zipped". - + 0.5a8 * There is now a separate documentation page for `setuptools`_; revision history that's not specific to EasyInstall has been moved to that page. Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- setuptools.txt 18 Jul 2005 02:28:14 -0000 1.20 +++ setuptools.txt 24 Jul 2005 02:41:43 -0000 1.21 @@ -783,6 +783,14 @@ it's a higher version than EasyInstall has seen in any other links for your project. +As a result, it's a common practice to use mark checkout URLs with a version of +"dev" (i.e., ``#egg=projectname-dev``), so that users can do something like +this:: + + easy_install --editable projectname==dev + +in order to check out the in-development version of ``projectname``. + Distributing Extensions compiled with Pyrex ------------------------------------------- From pje at users.sourceforge.net Sun Jul 24 04:41:46 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 23 Jul 2005 19:41:46 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools package_index.py, 1.14, 1.15 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7421/setuptools Modified Files: package_index.py Log Message: Implement --editable option, which allows you to just download and extract (or check out from Subversion) one or more source distributions, without actually building or installing them (or their dependencies). Index: package_index.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/package_index.py,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- package_index.py 18 Jul 2005 01:39:45 -0000 1.14 +++ package_index.py 24 Jul 2005 02:41:43 -0000 1.15 @@ -318,7 +318,7 @@ (spec,) ) - return self.fetch(spec, tmpdir, force_scan) + return self.fetch(spec, tmpdir) @@ -326,7 +326,7 @@ - def fetch(self, requirement, tmpdir, force_scan=False): + def fetch(self, requirement, tmpdir, force_scan=False, source=False): """Obtain a file suitable for fulfilling `requirement` `requirement` must be a ``pkg_resources.Requirement`` instance. @@ -336,35 +336,35 @@ the return value is the same as if you had called the ``download()`` method with the matching distribution's URL. If no matching distribution is found, returns ``None``. - """ + If the `source` flag is set, only source distributions and source + checkout links will be considered. + """ # process a Requirement self.info("Searching for %s", requirement) + def find(req): + for dist in self.get(req.key, ()): + if dist in req and (dist.precedence<=SOURCE_DIST or not source): + self.info("Best match: %s", dist) + return self.download(dist.location, tmpdir) + if force_scan: self.find_packages(requirement) + dist = find(requirement) + else: + dist = find(requirement) + if dist is None: + self.find_packages(requirement) + dist = find(requirement) - dist = self.best_match(requirement, WorkingSet([])) # XXX - - if dist is not None: - self.info("Best match: %s", dist) - return self.download(dist.location, tmpdir) - - self.warn( - "No local packages or download links found for %s", requirement - ) - return None - - - - - - - - - - - + if dist is None: + self.warn( + "No local packages or download links found for %s%s", + (source and "a source distribution of " or ""), + requirement, + ) + return dist dl_blocksize = 8192 From pje at users.sourceforge.net Sun Jul 24 04:41:46 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 23 Jul 2005 19:41:46 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.16, 1.17 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7421/setuptools/command Modified Files: easy_install.py Log Message: Implement --editable option, which allows you to just download and extract (or check out from Subversion) one or more source distributions, without actually building or installing them (or their dependencies). Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- easy_install.py 21 Jul 2005 00:49:45 -0000 1.16 +++ easy_install.py 24 Jul 2005 02:41:44 -0000 1.17 @@ -69,17 +69,17 @@ "filename in which to record list of installed files"), ('always-unzip', 'Z', "don't install as a zipfile, no matter what"), ('site-dirs=','S',"list of directories where .pth files work"), + ('editable', 'e', "Install specified packages in editable form"), ] boolean_options = [ 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy', - 'delete-conflicting', 'ignore-conflicts-at-my-risk', + 'delete-conflicting', 'ignore-conflicts-at-my-risk', 'editable', ] negative_opt = {'always-unzip': 'zip-ok'} create_index = PackageIndex - def initialize_options(self): self.zip_ok = None self.install_dir = self.script_dir = self.exclude_scripts = None @@ -89,6 +89,8 @@ self.args = None self.optimize = self.record = None self.upgrade = self.always_copy = self.multi_version = None + self.editable = None + # Options not specifiable via command line self.package_index = None self.pth_file = None @@ -119,8 +121,6 @@ - - def finalize_options(self): # If a non-default installation directory was specified, default the # script directory to match it. @@ -203,27 +203,18 @@ "--ignore-conflicts-at-my-risk at the same time" ) - if not self.args: + if self.editable and not self.build_directory: raise DistutilsArgError( - "No urls, filenames, or requirements specified (see --help)") + "Must specify a build directory (-b) when using --editable" + ) - elif len(self.args)>1 and self.build_directory is not None: + if not self.args: raise DistutilsArgError( - "Build directory can only be set when using one URL" - ) + "No urls, filenames, or requirements specified (see --help)") self.outputs = [] - def alloc_tmp(self): - if self.build_directory is None: - return tempfile.mkdtemp(prefix="easy_install-") - tmpdir = os.path.realpath(self.build_directory) - if not os.path.isdir(tmpdir): - os.makedirs(tmpdir) - return tmpdir - - def run(self): if self.verbose<>self.distribution.verbose: log.set_verbosity(self.verbose) @@ -244,21 +235,6 @@ - def add_output(self, path): - if os.path.isdir(path): - for base, dirs, files in os.walk(path): - for filename in files: - self.outputs.append(os.path.join(base,filename)) - else: - self.outputs.append(path) - - - - - - - - @@ -268,9 +244,32 @@ + def add_output(self, path): + if os.path.isdir(path): + for base, dirs, files in os.walk(path): + for filename in files: + self.outputs.append(os.path.join(base,filename)) + else: + self.outputs.append(path) + def not_editable(self, spec): + if self.editable: + raise DistutilsArgError( + "Invalid argument %r: you can't use filenames or URLs " + "with --editable (except via the --find-links option)." + % (spec,) + ) + def check_editable(self,spec): + if not self.editable: + return + if os.path.exists(os.path.join(self.build_directory, spec.key)): + raise DistutilsArgError( + "%r already exists in %s; can't do a checkout there" % + (spec.key, self.build_directory) + ) + @@ -282,36 +281,33 @@ + def easy_install(self, spec): - tmpdir = self.alloc_tmp() + tmpdir = tempfile.mkdtemp(prefix="easy_install-") download = None try: if not isinstance(spec,Requirement): if URL_SCHEME(spec): # It's a url, download it to tmpdir and process + self.not_editable(spec) download = self.package_index.download(spec, tmpdir) return self.install_item(None, download, tmpdir, True) elif os.path.exists(spec): # Existing file or directory, just process it directly + self.not_editable(spec) return self.install_item(None, spec, tmpdir, True) else: - try: - spec = Requirement.parse(spec) - except ValueError: - raise DistutilsError( - "Not a URL, existing file, or requirement spec: %r" - % (spec,) - ) + spec = parse_requirement_arg(spec) - if isinstance(spec, Requirement): - download = self.package_index.fetch(spec, tmpdir, self.upgrade) - else: - spec = None + self.check_editable(spec) + download = self.package_index.fetch( + spec, tmpdir, self.upgrade, self.editable + ) if download is None: raise DistutilsError( @@ -321,18 +317,22 @@ return self.install_item(spec, download, tmpdir) finally: - if self.build_directory is None: + if os.path.exists(tmpdir): shutil.rmtree(tmpdir) + + + + def install_item(self, spec, download, tmpdir, install_needed=False): # Installation is also needed if file in tmpdir or is not an egg install_needed = install_needed or os.path.dirname(download) == tmpdir install_needed = install_needed or not download.endswith('.egg') log.info("Processing %s", os.path.basename(download)) if install_needed or self.always_copy: - dists = self.install_eggs(download, tmpdir) + dists = self.install_eggs(spec, download, tmpdir) for dist in dists: self.process_distribution(spec, dist) else: @@ -386,28 +386,28 @@ return True return False - - - - - - - - - - - - - - - - - - - - - - + def maybe_move(self, spec, dist_filename, setup_base): + dst = os.path.join(self.build_directory, spec.key) + if os.path.exists(dst): + log.warn( + "%r already exists in %s; build directory %s will not be kept", + spec.key, self.build_directory, setup_base + ) + return setup_base + if os.path.isdir(dist_filename): + setup_base = dist_filename + else: + if os.path.dirname(dist_filename)==setup_base: + os.unlink(dist_filename) # get it out of the tmp dir + contents = os.listdir(setup_base) + if len(contents)==1: + dist_filename = os.path.join(setup_base,contents[0]) + if os.path.isdir(dist_filename): + # if the only thing there is a directory, move it instead + setup_base = dist_filename + ensure_directory(dst); shutil.move(setup_base, dst) + return dst + def install_script(self, dist, script_name, script_text, dev_path=None): log.info("Installing %s script to %s", script_name,self.script_dir) target = os.path.join(self.script_dir, script_name) @@ -449,7 +449,7 @@ pass - def install_eggs(self, dist_filename, tmpdir): + def install_eggs(self, spec, dist_filename, tmpdir): # .egg dirs or files are already built, so just return them if dist_filename.lower().endswith('.egg'): return [self.install_egg(dist_filename, tmpdir)] @@ -461,8 +461,12 @@ if os.path.isfile(dist_filename): unpack_archive(dist_filename, tmpdir, self.unpack_progress) elif os.path.isdir(dist_filename): + # note that setup_base==tmpdir here if this is a svn checkout setup_base = os.path.abspath(dist_filename) + if setup_base==tmpdir and self.build_directory and spec is not None: + setup_base = self.maybe_move(spec, dist_filename, setup_base) + # Find the setup.py file setup_script = os.path.join(setup_base, 'setup.py') @@ -479,15 +483,11 @@ setup_script = setups[0] # Now run it, and return the result - return self.build_and_install(setup_script, setup_base) - - - - - - - - + if self.editable: + log.warn(self.report_editable(spec, setup_script)) + return [] + else: + return self.build_and_install(setup_script, setup_base) def egg_distribution(self, egg_path): @@ -723,24 +723,24 @@ version = dist.version return msg % locals() + def report_editable(self, spec, setup_script): + dirname = os.path.dirname(setup_script) + python = sys.executable + return """\nExtracted editable version of %(spec)s to %(dirname)s +If it uses setuptools in its setup script, you can activate it in +"development" mode by going to that directory and running:: + %(python)s setup.py --develop +See the setuptools documentation for the "develop" command for more info. +""" % locals() - - - - - - - - - - def build_and_install(self, setup_script, setup_base): + def run_setup(self, setup_script, setup_base, args): sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) - sys.modules.setdefault('distutils.command.bdist_egg', egg_info) + sys.modules.setdefault('distutils.command.egg_info', egg_info) - args = ['bdist_egg', '--dist-dir'] + args = list(args) if self.verbose>2: v = 'v' * self.verbose - 1 args.insert(0,'-'+v) @@ -748,31 +748,31 @@ args.insert(0,'-q') if self.dry_run: args.insert(0,'-n') + log.info( + "Running %s %s", setup_script[len(setup_base)+1:], ' '.join(args) + ) + try: + run_setup(setup_script, args) + except SystemExit, v: + raise DistutilsError("Setup script exited with %s" % (v.args[0],)) - dist_dir = tempfile.mkdtemp(prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script)) + def build_and_install(self, setup_script, setup_base): + args = ['bdist_egg', '--dist-dir'] + dist_dir = tempfile.mkdtemp( + prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script) + ) try: args.append(dist_dir) - log.info( - "Running %s %s", setup_script[len(setup_base)+1:], - ' '.join(args) - ) - try: - run_setup(setup_script, args) - except SystemExit, v: - raise DistutilsError( - "Setup script exited with %s" % (v.args[0],) - ) - + self.run_setup(setup_script, setup_base, args) + all_eggs = AvailableDistributions([dist_dir]) eggs = [] - for egg in glob(os.path.join(dist_dir,'*.egg')): - eggs.append(self.install_egg(egg, setup_base)) - + for key in eggs: + for dist in eggs[key]: + eggs.append(self.install_egg(egg, setup_base)) if not eggs and not self.dry_run: log.warn("No eggs found in %s (setup script problem?)", dist_dir) - return eggs - finally: shutil.rmtree(dist_dir) log.set_verbosity(self.verbose) # restore our log verbosity @@ -1010,13 +1010,13 @@ return prefixes - - - - - - - +def parse_requirement_arg(spec): + try: + return Requirement.parse(spec) + except ValueError: + raise DistutilsError( + "Not a URL, existing file, or requirement spec: %r" % (spec,) + ) From pje at users.sourceforge.net Sun Jul 24 07:51:09 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sat, 23 Jul 2005 22:51:09 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command easy_install.py, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2120/setuptools/command Modified Files: easy_install.py Log Message: Fix a regression; this code was changed in order to avoid being fooled by incompatible eggs that might have ended up in the distribution directory, but the "fixed" code was broken. Index: easy_install.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/easy_install.py,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- easy_install.py 24 Jul 2005 02:41:44 -0000 1.17 +++ easy_install.py 24 Jul 2005 05:51:07 -0000 1.18 @@ -766,9 +766,9 @@ self.run_setup(setup_script, setup_base, args) all_eggs = AvailableDistributions([dist_dir]) eggs = [] - for key in eggs: - for dist in eggs[key]: - eggs.append(self.install_egg(egg, setup_base)) + for key in all_eggs: + for dist in all_eggs[key]: + eggs.append(self.install_egg(dist.location, setup_base)) if not eggs and not self.dry_run: log.warn("No eggs found in %s (setup script problem?)", dist_dir) From birkenfeld at users.sourceforge.net Sun Jul 24 14:42:54 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 24 Jul 2005 05:42:54 -0700 Subject: [Python-checkins] python/nondist/sandbox/path test_path.py, 1.2, 1.3 path.py, 1.2, 1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14122 Modified Files: test_path.py path.py Log Message: * subdirs() is now dirs(). * fixed compare behaviour for unicode base (unicode has no rich compare) * __iter__() iterates over the parts(). * the following methods raise NotImplemented: capitalize, expandtabs, join, splitlines, title, zfill Index: test_path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/test_path.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- test_path.py 23 Jul 2005 09:27:40 -0000 1.2 +++ test_path.py 24 Jul 2005 12:42:51 -0000 1.3 @@ -59,7 +59,7 @@ self.assertEqual(d.relpathto(boz), boz) ## this isn't going to work cause Paths won't compare - ## with ordinary strings + ## to ordinary strings ''' def testStringCompatibility(self): """ Test compatibility with ordinary strings. """ @@ -79,6 +79,12 @@ self.assert_(items == ['A', 'B', 'E', 'c', 'd', 'fgh', 'fhj']) ''' + def testUnusableMethods(self): + p = Path() + for method in [p.capitalize, p.expandtabs, p.join, p.splitlines, + p.title, p.zfill]: + self.assertRaises(NotImplementedError, method) + def testProperties(self): # Create sample Path object. f = p(nt='C:\\Program Files\\Python\\Lib\\xyzzy.py', @@ -118,6 +124,16 @@ self.assert_(p.uncshare == r'\\python1\share1') self.assert_(p.splitunc() == os.path.splitunc(str(p))) + def testCompare(self): + p1 = Path('/') + lst = [p1, Path('/usr/'), Path('/usr/share')] + p2 = Path('/') + # a Path is not interned, so these are different objects + assert p1 is not p2 + # but they must compare the same + self.assert_(p1 == p2) + self.assert_(p2 in lst) + class TempDirTestCase(unittest.TestCase): def setUp(self): # Create a temporary directory. @@ -349,7 +365,7 @@ (e/name).touch() self.assertList(d.children('*.tmp'), [d/'x.tmp', d/'xdir.tmp']) self.assertList(d.files('*.tmp'), [d/'x.tmp']) - self.assertList(d.subdirs('*.tmp'), [d/'xdir.tmp']) + self.assertList(d.dirs('*.tmp'), [d/'xdir.tmp']) self.assertList(d.walk(), [e for e in dirs if e != d] + [e/n for e in dirs for n in names]) self.assertList(d.walk('*.tmp'), [e/'x.tmp' for e in dirs] + [d/'xdir.tmp']) Index: path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/path.py,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- path.py 23 Jul 2005 09:27:40 -0000 1.2 +++ path.py 24 Jul 2005 12:42:51 -0000 1.3 @@ -63,6 +63,10 @@ return Path(os.curdir) return _base.__new__(typ, *args) + # Iterating over a string yields its parts + def __iter__(self): + return iter(self.parts()) + def __repr__(self): return 'Path(%s)' % repr(_base(self)) @@ -95,30 +99,37 @@ return self.joinwith(other) __truediv__ = __div__ - - # Rich comparison - def __eq__(self, other): - return isinstance(other, Path) and _base.__eq__(self, other) - - def __ne__(self, other): - return (not isinstance(other, Path)) or _base.__ne__(self, other) - def __lt__(self, other): - if isinstance(other, Path): - return _base.__lt__(self, other) - return NotImplemented - def __le__(self, other): - if isinstance(other, Path): - return _base.__le__(self, other) - return NotImplemented - def __gt__(self, other): - if isinstance(other, Path): - return _base.__gt__(self, other) - return NotImplemented - def __ge__(self, other): - if isinstance(other, Path): - return _base.__ge__(self, other) - return NotImplemented + if _base is str: + # Rich comparison for string + def __eq__(self, other): + return isinstance(other, Path) and _base.__eq__(self, other) + + def __ne__(self, other): + return (not isinstance(other, Path)) or _base.__ne__(self, other) + + def __lt__(self, other): + if isinstance(other, Path): + return _base.__lt__(self, other) + return NotImplemented + def __le__(self, other): + if isinstance(other, Path): + return _base.__le__(self, other) + return NotImplemented + def __gt__(self, other): + if isinstance(other, Path): + return _base.__gt__(self, other) + return NotImplemented + def __ge__(self, other): + if isinstance(other, Path): + return _base.__ge__(self, other) + return NotImplemented + else: + # Unicode has no rich compare methods + def __cmp__(self, other): + if isinstance(other, Path): + return _base.__cmp__(self, other) + return NotImplemented # Alternative constructor. @@ -350,7 +361,7 @@ """ D.children() -> List of items in this directory, with this path prepended to them. - Use D.files() or D.subdirs() instead if you want a listing + Use D.files() or D.dirs() instead if you want a listing of just files or just subdirectories. The elements of the list are path objects. @@ -363,8 +374,8 @@ names = fnmatch.filter(names, pattern) return [self / child for child in names] - def subdirs(self, pattern=None): - """ D.subdirs() -> List of this directory's subdirectories. + def dirs(self, pattern=None): + """ D.dirs() -> List of this directory's subdirectories. The elements of the list are path objects. This does not walk recursively into subdirectories @@ -372,7 +383,7 @@ With the optional 'pattern' argument, this only lists directories whose names match the given pattern. For - example, d.subdirs('build-*'). + example, d.dirs('build-*'). """ return [p for p in self.children(pattern) if p.isdir()] @@ -414,7 +425,7 @@ example, mydir.walkdirs('*test') yields only directories with names ending in 'test'. """ - for child in self.subdirs(): + for child in self.dirs(): if pattern is None or child.fnmatch(pattern): yield child for subsubdir in child.walkdirs(pattern): @@ -864,3 +875,14 @@ def startfile(self): os.startfile(self) + # --- Unusable string methods + + def _not_implemented(self, *args, **kwargs): + raise NotImplementedError("not implemented for Path objects") + + capitalize = _not_implemented + expandtabs = _not_implemented + join = _not_implemented + splitlines = _not_implemented + title = _not_implemented + zfill = _not_implemented From birkenfeld at users.sourceforge.net Sun Jul 24 17:51:10 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sun, 24 Jul 2005 08:51:10 -0700 Subject: [Python-checkins] python/nondist/sandbox/path path.py, 1.3, 1.4 test_path.py, 1.3, 1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15659 Modified Files: path.py test_path.py Log Message: Seems that people want Path.splitlines(). A pity. Index: path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/path.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- path.py 24 Jul 2005 12:42:51 -0000 1.3 +++ path.py 24 Jul 2005 15:51:07 -0000 1.4 @@ -23,7 +23,6 @@ # TODO (standard module) # - add more standard header? -# - shutil functions should accept a Path as "dst" # - Make sure everything has a good docstring. @@ -875,14 +874,3 @@ def startfile(self): os.startfile(self) - # --- Unusable string methods - - def _not_implemented(self, *args, **kwargs): - raise NotImplementedError("not implemented for Path objects") - - capitalize = _not_implemented - expandtabs = _not_implemented - join = _not_implemented - splitlines = _not_implemented - title = _not_implemented - zfill = _not_implemented Index: test_path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/test_path.py,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- test_path.py 24 Jul 2005 12:42:51 -0000 1.3 +++ test_path.py 24 Jul 2005 15:51:07 -0000 1.4 @@ -79,12 +79,6 @@ self.assert_(items == ['A', 'B', 'E', 'c', 'd', 'fgh', 'fhj']) ''' - def testUnusableMethods(self): - p = Path() - for method in [p.capitalize, p.expandtabs, p.join, p.splitlines, - p.title, p.zfill]: - self.assertRaises(NotImplementedError, method) - def testProperties(self): # Create sample Path object. f = p(nt='C:\\Program Files\\Python\\Lib\\xyzzy.py', From pje at users.sourceforge.net Sun Jul 24 19:59:28 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 10:59:28 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.51, 1.52 setuptools.txt, 1.21, 1.22 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8768 Modified Files: pkg_resources.py setuptools.txt Log Message: Fix eager resource extraction. Add eager_resources setup() argument. Add support for obtaining project-level resources by making get_provider() accept Requirement objects. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.51 retrieving revision 1.52 diff -u -d -r1.51 -r1.52 --- pkg_resources.py 21 Jul 2005 16:11:34 -0000 1.51 +++ pkg_resources.py 24 Jul 2005 17:59:26 -0000 1.52 @@ -25,6 +25,7 @@ 'safe_name', 'safe_version', 'run_main', 'BINARY_DIST', 'run_script', 'get_default_cache', 'EmptyProvider', 'empty_provider', 'normalize_path', 'WorkingSet', 'working_set', 'add_activation_listener', 'CHECKOUT_DIST', + 'list_resources', 'resource_exists', 'resource_isdir', ] import sys, os, zipimport, time, re, imp @@ -38,7 +39,6 @@ - class ResolutionError(Exception): """Abstract base for dependency resolution errors""" @@ -68,18 +68,18 @@ """ _provider_factories[loader_type] = provider_factory -def get_provider(moduleName): - """Return an IResourceProvider for the named module""" +def get_provider(moduleOrReq): + """Return an IResourceProvider for the named module or requirement""" + if isinstance(moduleOrReq,Requirement): + return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] try: - module = sys.modules[moduleName] + module = sys.modules[moduleOrReq] except KeyError: - __import__(moduleName) - module = sys.modules[moduleName] + __import__(moduleOrReq) + module = sys.modules[moduleOrReq] loader = getattr(module, '__loader__', None) return _find_adapter(_provider_factories, loader)(module) - - def _macosx_vers(_cache=[]): if not _cache: info = os.popen('/usr/bin/sw_vers').read().splitlines() @@ -627,7 +627,7 @@ def resource_isdir(self, package_name, resource_name): """Does the named resource exist in the named package?""" - return get_provider(package_name).resource_isdir(self, resource_name) + return get_provider(package_name).resource_isdir(resource_name) def resource_filename(self, package_name, resource_name): """Return a true filesystem path for specified resource""" @@ -648,7 +648,7 @@ ) def list_resources(self, package_name, resource_name): - return get_provider(package_name).resource_listdir(self, resource_name) + return get_provider(package_name).resource_listdir(resource_name) @@ -913,8 +913,8 @@ register_loader_type(object, NullProvider) -class DefaultProvider(NullProvider): - """Provides access to package resources in the filesystem""" +class EggProvider(NullProvider): + """Provider based on a virtual filesystem""" def __init__(self,module): NullProvider.__init__(self,module) @@ -925,22 +925,28 @@ # of multiple eggs; that's why we use module_path instead of .archive path = self.module_path old = None - self.prefix = [] while path!=old: if path.lower().endswith('.egg'): self.egg_name = os.path.basename(path) self.egg_info = os.path.join(path, 'EGG-INFO') + self.egg_root = path break old = path path, base = os.path.split(path) - self.prefix.append(base) - self.prefix.reverse() - def _has(self, path): - return os.path.exists(path) + + + + +class DefaultProvider(EggProvider): + """Provides access to package resources in the filesystem""" + + def _has(self, path): + return os.path.exists(path) + def _isdir(self,path): return os.path.isdir(path) @@ -976,67 +982,63 @@ - - - - - - -class ZipProvider(DefaultProvider): +class ZipProvider(EggProvider): """Resource support for zips and eggs""" eagers = None def __init__(self, module): - DefaultProvider.__init__(self,module) + EggProvider.__init__(self,module) self.zipinfo = zipimport._zip_directory_cache[self.loader.archive] self.zip_pre = self.loader.archive+os.sep - def _short_name(self, path): - if path.startswith(self.zip_pre): - return path[len(self.zip_pre):] - return path + def _zipinfo_name(self, fspath): + # Convert a virtual filename (full path to file) into a zipfile subpath + # usable with the zipimport directory cache for our target archive + if fspath.startswith(self.zip_pre): + return fspath[len(self.zip_pre):] + raise AssertionError( + "%s is not a subpath of %s" % (fspath,self.zip_pre) + ) - def get_resource_stream(self, manager, resource_name): - return StringIO(self.get_resource_string(manager, resource_name)) + def _parts(self,zip_path): + # Convert a zipfile subpath into an egg-relative path part list + fspath = self.zip_pre+zip_path # pseudo-fs path + if fspath.startswith(self.egg_root+os.sep): + return fspath[len(self.egg_root)+1:].split(os.sep) + raise AssertionError( + "%s is not a subpath of %s" % (fspath,self.egg_root) + ) - def get_resource_filename(self, manager, resource_name): + def get_resource_filename(self, manager, resource_name): if not self.egg_name: raise NotImplementedError( "resource_filename() only supported for .egg, not .zip" ) - # no need to lock for extraction, since we use temp names + zip_path = self._resource_to_zip(resource_name) eagers = self._get_eager_resources() - if resource_name in eagers: + if '/'.join(self._parts(zip_path)) in eagers: for name in eagers: - self._extract_resource(manager, name) - - return self._extract_resource(manager, resource_name) - - def _extract_directory(self, manager, resource_name): - if resource_name.endswith('/'): - resource_name = resource_name[:-1] - for resource in self.resource_listdir(resource_name): - last = self._extract_resource(manager, resource_name+'/'+resource) - return os.path.dirname(last) # return the directory path - - + self._extract_resource(manager, self._eager_to_zip(name)) + return self._extract_resource(manager, zip_path) - def _extract_resource(self, manager, resource_name): - if self.resource_isdir(resource_name): - return self._extract_directory(manager, resource_name) + def _extract_resource(self, manager, zip_path): + if zip_path in self._index(): + for name in self._index()[zip_path]: + last = self._extract_resource( + manager, os.path.join(zip_path, name) + ) + return os.path.dirname(last) # return the extracted directory name - parts = resource_name.split('/') - zip_path = os.path.join(self.module_path, *parts) - zip_stat = self.zipinfo[os.path.join(*self.prefix+parts)] + zip_stat = self.zipinfo[zip_path] t,d,size = zip_stat[5], zip_stat[6], zip_stat[3] date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F, # ymd (t&0xFFFF)>>11, (t>>5)&0x3F, (t&0x1F) * 2, 0, 0, -1 # hms, etc. ) timestamp = time.mktime(date_time) - real_path = manager.get_cache_path(self.egg_name, self.prefix+parts) + real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path)) if os.path.isfile(real_path): stat = os.stat(real_path) @@ -1060,10 +1062,8 @@ # so we're done return real_path raise - return real_path - def _get_eager_resources(self): if self.eagers is None: eagers = [] @@ -1077,12 +1077,9 @@ try: return self._dirindex except AttributeError: - ind = {}; skip = len(self.prefix) + ind = {} for path in self.zipinfo: parts = path.split(os.sep) - if parts[:skip] != self.prefix: - continue # only include items under our prefix - parts = parts[skip:] # but don't include prefix in paths while parts: parent = '/'.join(parts[:-1]) if parent in ind: @@ -1093,26 +1090,26 @@ self._dirindex = ind return ind - def _has(self, path): - return self._short_name(path) in self.zipinfo or self._isdir(path) + def _has(self, fspath): + zip_path = self._zipinfo_name(fspath) + return zip_path in self.zipinfo or zip_path in self._index() - def _isdir(self,path): - return self._dir_name(path) in self._index() + def _isdir(self,fspath): + return self._zipinfo_name(fspath) in self._index() - def _listdir(self,path): - return list(self._index().get(self._dir_name(path), ())) + def _listdir(self,fspath): + return list(self._index().get(self._zipinfo_name(fspath), ())) - def _dir_name(self,path): - if path.startswith(self.module_path+os.sep): - path = path[len(self.module_path+os.sep):] - path = path.replace(os.sep,'/') - if path.endswith('/'): path = path[:-1] - return path - _get = NullProvider._get + + def _eager_to_zip(self,resource_name): + return self._zipinfo_name(self._fn(self.egg_root,resource_name)) + + def _resource_to_zip(self,resource_name): + return self._zipinfo_name(self._fn(self.module_path,resource_name)) register_loader_type(zipimport.zipimporter, ZipProvider) @@ -1146,6 +1143,9 @@ + + + class PathMetadata(DefaultProvider): """Metadata provider for egg directories Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- setuptools.txt 24 Jul 2005 02:41:43 -0000 1.21 +++ setuptools.txt 24 Jul 2005 17:59:26 -0000 1.22 @@ -180,6 +180,22 @@ does not contain any code. See the section below on `Namespace Packages`_ for more information. +``eager_resources`` + A list of strings naming resources that should be extracted together, if + any of them is needed, or if any C extensions included in the project are + imported. This argument is only useful if the project will be installed as + a zipfile, and there is a need to have all of the listed resources be + extracted to the filesystem *as a unit*. Resources listed here + should be '/'-separated paths, relative to the source root, so to list a + resource ``foo.png`` in package ``bar.baz``, you would include the string + ``bar/baz/foo.png`` in this argument. + + If you only need to obtain resources one at a time, or you don't have any C + extensions that access other files in the project (such as data files or + shared libraries), you probably do NOT need this argument and shouldn't + mess with it. For more details on how this argument works, see the section + below on `Automatic Resource Extraction`_. + Using ``find_packages()`` ------------------------- @@ -414,6 +430,7 @@ __ http://docs.python.org/dist/node11.html + Accessing Data Files at Runtime ------------------------------- @@ -432,6 +449,76 @@ .. _Accessing Package Resources: http://peak.telecommunity.com/DevCenter/PythonEggs#accessing-package-resources +Non-Package Data Files +---------------------- + +The ``distutils`` normally install general "data files" to a platform-specific +location (e.g. ``/usr/share``). This feature intended to be used for things +like documentation, example configuration files, and the like. ``setuptools`` +does not install these data files in a separate location, however. They are +bundled inside the egg file or directory, alongside the Python modules and +packages. The data files can also be accessed using the `Resource Management +API`_, by specifying a ``Requirement`` instead of a package name:: + + from pkg_resources import Requirement, resource_filename + filename = resource_filename(Requirement.parse("MyProject"),"sample.conf") + +The above code will obtain the filename of the "sample.conf" file in the data +root of the "MyProject" distribution. + +Note, by the way, that this encapsulation of data files means that you can't +actually install data files to some arbitrary location on a user's machine; +this is a feature, not a bug. You can always include a script in your +distribution that extracts and copies your the documentation or data files to +a user-specified location, at their discretion. If you put related data files +in a single directory, you can use ``resource_filename()`` with the directory +name to get a filesystem directory that then can be copied with the ``shutil`` +module. (Even if your package is installed as a zipfile, calling +``resource_filename()`` on a directory will return an actual filesystem +directory, whose contents will be that entire subtree of your distribution.) + +(Of course, if you're writing a new package, you can just as easily place your +data files or directories inside one of your packages, rather than using the +distutils' approach. However, if you're updating an existing application, it +may be simpler not to change the way it currently specifies these data files.) + + +Automatic Resource Extraction +----------------------------- + +If you are using tools that expect your resources to be "real" files, or your +project includes non-extension native libraries or other files that your C +extensions expect to be able to access, you may need to list those files in +the ``eager_resources`` argument to ``setup()``, so that the files will be +extracted together, whenever a C extension in the project is imported. This +is especially important if your project includes shared libraries *other* than +distutils-built C extensions. Those shared libraries should be listed as +``eager_resources``, because they need to be present in the filesystem when the +C extensions that link to them are used. + +The ``pkg_resources`` runtime for compressed packages will automatically +extract *all* C extensions and ``eager_resources`` at the same time, whenever +*any* C extension or eager resource is requested via the ``resource_filename()`` +API. (C extensions are imported using ``resource_filename()`` internally.) +This ensures that C extensions will see all of the "real" files that they +expect to see. + +Note also that you can list directory resource names in ``eager_resources`` as +well, in which case the directory's contents (including subdirectories) will be +extracted whenever any C extension or eager resource is requested. + +Please note that if you're not sure whether you need to use this argument, you +don't! It's really intended to support projects with lots of non-Python +dependencies and as a last resort for crufty projects that can't otherwise +handle being compressed. If your package is pure Python, Python plus data +files, or Python plus C, you really don't need this. You've got to be using +either C or an external program that needs "real" files in your project before +there's any possibility of ``eager_resources`` being relevant to your project. + + + + + "Development Mode" ================== @@ -1396,14 +1483,32 @@ * Fixed the ``--tag-svn-revision`` option of ``egg_info`` not finding the latest revision number; it was using the revision number of the directory containing ``setup.py``, not the highest revision number in the project. + + * Added ``eager_resources`` setup argument * Fixed some problems using ``pkg_resources`` w/PEP 302 loaders other than - ``zipimport``. - - * Fixed ``pkg_resources.resource_exists()`` not working correctly. + ``zipimport``, and the previously-broken "eager resource" support. + + * Fixed ``pkg_resources.resource_exists()`` not working correctly, along with + some other resource API bugs. + * Many ``pkg_resources`` API changes and enhancements: + * Resource API functions like ``resource_string()`` that accepted a package + name and resource name, will now also accept a ``Requirement`` object in + place of the package name (to allow access to non-package data files in + an egg). + + * ``get_provider()`` will now accept a ``Requirement`` instance or a module + name. If it is given a ``Requirement``, it will return a corresponding + ``Distribution`` (by calling ``require()`` if a suitable distribution + isn't already in the working set), rather than returning a metadata and + resource provider for a specific module. (The difference is in how + resource paths are interpreted; supplying a module name means resources + path will be module-relative, rather than relative to the distribution's + root.) + * ``Distribution`` objects now implement the ``IResourceProvider`` and ``IMetadataProvider`` interfaces, so you don't need to reference the (no longer available) ``metadata`` attribute to get at these interfaces. From pje at users.sourceforge.net Sun Jul 24 19:59:29 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 10:59:29 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools dist.py, 1.14, 1.15 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8768/setuptools Modified Files: dist.py Log Message: Fix eager resource extraction. Add eager_resources setup() argument. Add support for obtaining project-level resources by making get_provider() accept Requirement objects. Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- dist.py 10 Jul 2005 15:43:08 -0000 1.14 +++ dist.py 24 Jul 2005 17:59:26 -0000 1.15 @@ -92,6 +92,7 @@ self.dist_files = [] self.zip_safe = None self.namespace_packages = None + self.eager_resources = None _Distribution.__init__(self,attrs) if not have_package_data: from setuptools.command.build_py import build_py @@ -120,16 +121,18 @@ - def finalize_options(self): _Distribution.finalize_options(self) + if self.features: self._set_global_opts_from_features() + if self.extra_path: raise DistutilsSetupError( "The 'extra_path' parameter is not needed when using " "setuptools. Please remove it from your setup script." ) + try: list(pkg_resources.parse_requirements(self.install_requires)) except (TypeError,ValueError): @@ -137,6 +140,7 @@ "'install_requires' must be a string or list of strings " "containing valid project/version requirement specifiers" ) + try: for k,v in self.extras_require.items(): list(pkg_resources.parse_requirements(v)) @@ -146,22 +150,27 @@ "strings or lists of strings containing valid project/version " "requirement specifiers." ) - if self.namespace_packages is not None: - try: - assert ''.join(self.namespace_packages)!=self.namespace_packages - except (TypeError,ValueError,AttributeError,AssertionError): - raise DistutilsSetupError( - "'namespace_packages' must be a sequence of strings" - ) - for nsp in self.namespace_packages: - for name in iter_distribution_names(self): - if name.startswith(nsp+'.'): break - else: + + for attr in 'namespace_packages','eager_resources': + value = getattr(self,attr,None) + if value is not None: + try: + assert ''.join(value)!=value + except (TypeError,ValueError,AttributeError,AssertionError): raise DistutilsSetupError( - "Distribution contains no modules or packages for " + - "namespace package %r" % nsp + "%r must be a list of strings (got %r)" % (attr,value) ) + + for nsp in self.namespace_packages or (): + for name in iter_distribution_names(self): + if name.startswith(nsp+'.'): break + else: + raise DistutilsSetupError( + "Distribution contains no modules or packages for " + + "namespace package %r" % nsp + ) + def _set_global_opts_from_features(self): """Add --with-X/--without-X options based on optional features""" @@ -186,6 +195,14 @@ self.global_options = self.feature_options = go + self.global_options self.negative_opt = self.feature_negopt = no + + + + + + + + def _finalize_features(self): """Add/remove features and resolve dependencies between them""" @@ -203,6 +220,30 @@ feature.exclude_from(self) self._set_feature(name,0) + + + + + + + + + + + + + + + + + + + + + + + + def _set_feature(self,name,status): """Set feature's inclusion status""" setattr(self,self._feature_attrname(name),status) From pje at users.sourceforge.net Sun Jul 24 19:59:29 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 10:59:29 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command egg_info.py, 1.7, 1.8 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8768/setuptools/command Modified Files: egg_info.py Log Message: Fix eager resource extraction. Add eager_resources setup() argument. Add support for obtaining project-level resources by making get_provider() accept Requirement objects. Index: egg_info.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/egg_info.py,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- egg_info.py 16 Jul 2005 16:43:02 -0000 1.7 +++ egg_info.py 24 Jul 2005 17:59:27 -0000 1.8 @@ -96,13 +96,13 @@ finally: metadata.name, metadata.version = oldname, oldver - self.write_namespace_packages() self.write_requirements() self.write_toplevel_names() - + self.write_or_delete_dist_arg('namespace_packages') + self.write_or_delete_dist_arg('eager_resources') if os.path.exists(os.path.join(self.egg_info,'depends.txt')): log.warn( - "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" + "WARNING: 'depends.txt' is not used by setuptools 0.6!\n" "Use the install_requires/extras_require setup() args instead." ) @@ -162,18 +162,19 @@ - def write_namespace_packages(self): - nsp = getattr(self.distribution,'namespace_packages',None) - if nsp is None: + def write_or_delete_dist_arg(self, argname, filename=None): + value = getattr(self.distribution, argname, None) + if value is None: return - filename = os.path.join(self.egg_info,"namespace_packages.txt") + filename = filename or argname+'.txt' + filename = os.path.join(self.egg_info,filename) - if nsp: + if value: log.info("writing %s", filename) if not self.dry_run: f = open(filename, 'wt') - f.write('\n'.join(nsp)) + f.write('\n'.join(value)) f.write('\n') f.close() @@ -202,4 +203,3 @@ - From pje at users.sourceforge.net Sun Jul 24 19:59:46 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 10:59:46 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/tests test_resources.py, 1.17, 1.18 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8768/setuptools/tests Modified Files: test_resources.py Log Message: Fix eager resource extraction. Add eager_resources setup() argument. Add support for obtaining project-level resources by making get_provider() accept Requirement objects. Index: test_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/test_resources.py,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- test_resources.py 18 Jul 2005 02:28:14 -0000 1.17 +++ test_resources.py 24 Jul 2005 17:59:27 -0000 1.18 @@ -146,7 +146,7 @@ # Request an extra that causes an unresolved dependency for "Baz" self.assertRaises( DistributionNotFound, ws.resolve,parse_requirements("Foo[bar]"), ad - ) + ) Baz = Distribution.from_filename( "/foo_dir/Baz-2.1.egg", metadata=Metadata(('depends.txt', "Foo")) ) @@ -332,7 +332,7 @@ self.assertEqual(safe_version("2.3.4 20050521"), "2.3.4.20050521") self.assertEqual(safe_version("Money$$$Maker"), "Money-Maker") self.assertEqual(safe_version("peak.web"), "peak.web") - + def testSimpleRequirements(self): self.assertEqual( list(parse_requirements('Twis-Ted>=1.2-1')), From pje at users.sourceforge.net Mon Jul 25 00:09:41 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 15:09:41 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools.egg-info - New directory Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.egg-info In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31268/setuptools.egg-info Log Message: Directory /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.egg-info added to the repository From pje at users.sourceforge.net Mon Jul 25 00:47:08 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 15:47:08 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools dist.py, 1.15, 1.16 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6325/setuptools Modified Files: dist.py Log Message: Implement "entry points" for dynamic discovery of drivers and plugins. Change setuptools to discover setup commands using an entry point group called "distutils.commands". Thanks to Ian Bicking for the suggestion that led to designing this super-cool feature. Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- dist.py 24 Jul 2005 17:59:26 -0000 1.15 +++ dist.py 24 Jul 2005 22:47:05 -0000 1.16 @@ -11,6 +11,32 @@ from distutils.errors import DistutilsSetupError import setuptools, pkg_resources +def get_command_class(self, command): + """Pluggable version of get_command_class()""" + if command in self.cmdclass: + return self.cmdclass[command] + + for dist in pkg_resources.working_set: + if dist.get_entry_info('distutils.commands',command): + cmdclass = dist.load_entry_point('distutils.commands',command) + self.cmdclass[command] = cmdclass + return cmdclass + else: + return _old_get_command_class(self, command) + +def print_commands(self): + for dist in pkg_resources.working_set: + for cmd,ep in dist.get_entry_map('distutils.commands').items(): + if cmd not in self.cmdclass: + cmdclass = ep.load() # don't require extras, we're not running + self.cmdclass[cmd] = cmdclass + return _old_print_commands(self) + +for meth in 'print_commands', 'get_command_class': + if getattr(_Distribution,meth).im_func.func_globals is not globals(): + globals()['_old_'+meth] = getattr(_Distribution,meth) + setattr(_Distribution, meth, globals()[meth]) + sequence = tuple, list class Distribution(_Distribution): @@ -80,6 +106,21 @@ distribution for the included and excluded features. """ + + + + + + + + + + + + + + + def __init__ (self, attrs=None): have_package_data = hasattr(self, "package_data") if not have_package_data: @@ -93,15 +134,9 @@ self.zip_safe = None self.namespace_packages = None self.eager_resources = None + self.entry_points = None _Distribution.__init__(self,attrs) - if not have_package_data: - from setuptools.command.build_py import build_py - self.cmdclass.setdefault('build_py',build_py) - self.cmdclass.setdefault('build_ext',build_ext) - self.cmdclass.setdefault('install',install) - self.cmdclass.setdefault('install_lib',install_lib) - self.cmdclass.setdefault('sdist',sdist) def parse_command_line(self): """Process features after parsing command line options""" @@ -121,6 +156,12 @@ + + + + + + def finalize_options(self): _Distribution.finalize_options(self) @@ -171,6 +212,12 @@ "namespace package %r" % nsp ) + if self.entry_points is not None: + try: + pkg_resources.EntryPoint.parse_map(self.entry_points) + except ValueError, e: + raise DistutilsSetupError(e) + def _set_global_opts_from_features(self): """Add --with-X/--without-X options based on optional features""" @@ -197,12 +244,6 @@ - - - - - - def _finalize_features(self): """Add/remove features and resolve dependencies between them""" @@ -420,7 +461,7 @@ src,alias = aliases[command] del aliases[command] # ensure each alias can expand only once! import shlex - args[:1] = shlex.split(alias,True) + args[:1] = shlex.split(alias,True) command = args[0] nargs = _Distribution._parse_command_opts(self, parser, args) From pje at users.sourceforge.net Mon Jul 25 00:47:08 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 15:47:08 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/tests test_resources.py, 1.18, 1.19 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6325/setuptools/tests Modified Files: test_resources.py Log Message: Implement "entry points" for dynamic discovery of drivers and plugins. Change setuptools to discover setup commands using an entry point group called "distutils.commands". Thanks to Ian Bicking for the suggestion that led to designing this super-cool feature. Index: test_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/test_resources.py,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- test_resources.py 24 Jul 2005 17:59:27 -0000 1.18 +++ test_resources.py 24 Jul 2005 22:47:06 -0000 1.19 @@ -185,7 +185,16 @@ d,"Twisted>=1.5 fcgiapp>=0.1 ZConfig>=2.0 docutils>=0.3".split(), ["fastcgi", "docgen"] ) - self.assertRaises(InvalidOption, d.requires, ["foo"]) + self.assertRaises(UnknownExtra, d.requires, ["foo"]) + + + + + + + + + @@ -194,13 +203,86 @@ +class EntryPointTests(TestCase): + + def assertfields(self, ep): + self.assertEqual(ep.name,"foo") + self.assertEqual(ep.module_name,"setuptools.tests.test_resources") + self.assertEqual(ep.attrs, ("EntryPointTests",)) + self.assertEqual(ep.extras, ("x",)) + self.failUnless(ep.load() is EntryPointTests) + self.assertEqual( + str(ep), + "foo = setuptools.tests.test_resources:EntryPointTests [x]" + ) + + def testBasics(self): + ep = EntryPoint( + "foo", "setuptools.tests.test_resources", ["EntryPointTests"], + ["x"] + ) + self.assertfields(ep) + + def testParse(self): + s = "foo = setuptools.tests.test_resources:EntryPointTests [x]" + ep = EntryPoint.parse(s) + self.assertfields(ep) + + ep = EntryPoint.parse("bar baz= spammity[PING]") + self.assertEqual(ep.name,"bar baz") + self.assertEqual(ep.module_name,"spammity") + self.assertEqual(ep.attrs, ()) + self.assertEqual(ep.extras, ("ping",)) + + ep = EntryPoint.parse(" fizzly = wocka:foo") + self.assertEqual(ep.name,"fizzly") + self.assertEqual(ep.module_name,"wocka") + self.assertEqual(ep.attrs, ("foo",)) + self.assertEqual(ep.extras, ()) + + + def testRejects(self): + for ep in [ + "foo", "x=1=2", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2", + ]: + try: EntryPoint.parse(ep) + except ValueError: pass + else: raise AssertionError("Should've been bad", ep) + def checkSubMap(self, m): + self.assertEqual(str(m), + "{" + "'feature2': EntryPoint.parse(" + "'feature2 = another.module:SomeClass [extra1,extra2]'), " + "'feature1': EntryPoint.parse(" + "'feature1 = somemodule:somefunction')" + "}" + ) + submap_str = """ + # define features for blah blah + feature1 = somemodule:somefunction + feature2 = another.module:SomeClass [extra1,extra2] + """ + def testParseList(self): + self.checkSubMap(EntryPoint.parse_list("xyz", self.submap_str)) + self.assertRaises(ValueError, EntryPoint.parse_list, "x a", "foo=bar") + self.assertRaises(ValueError, EntryPoint.parse_list, "x", + ["foo=baz", "foo=bar"]) + def testParseMap(self): + m = EntryPoint.parse_map({'xyz':self.submap_str}) + self.checkSubMap(m['xyz']) + self.assertEqual(m.keys(),['xyz']) + m = EntryPoint.parse_map("[xyz]\n"+self.submap_str) + self.checkSubMap(m['xyz']) + self.assertEqual(m.keys(),['xyz']) + self.assertRaises(ValueError, EntryPoint.parse_map, ["[xyz]", "[xyz]"]) + self.assertRaises(ValueError, EntryPoint.parse_map, self.submap_str) class RequirementsTests(TestCase): From pje at users.sourceforge.net Mon Jul 25 00:47:09 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 15:47:09 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools.egg-info entry_points.txt, NONE, 1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.egg-info In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6325/setuptools.egg-info Added Files: entry_points.txt Log Message: Implement "entry points" for dynamic discovery of drivers and plugins. Change setuptools to discover setup commands using an entry point group called "distutils.commands". Thanks to Ian Bicking for the suggestion that led to designing this super-cool feature. --- NEW FILE: entry_points.txt --- [distutils.commands] rotate = setuptools.command.rotate:rotate develop = setuptools.command.develop:develop setopt = setuptools.command.setopt:setopt saveopts = setuptools.command.saveopts:saveopts egg_info = setuptools.command.egg_info:egg_info depends = setuptools.command.depends:depends upload = setuptools.command.upload:upload alias = setuptools.command.alias:alias easy_install = setuptools.command.easy_install:easy_install bdist_egg = setuptools.command.bdist_egg:bdist_egg install = setuptools.command.install:install test = setuptools.command.test:test install_lib = setuptools.command.install_lib:install_lib build_ext = setuptools.command.build_ext:build_ext sdist = setuptools.command.sdist:sdist From pje at users.sourceforge.net Mon Jul 25 00:47:08 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 15:47:08 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/command __init__.py, 1.6, 1.7 egg_info.py, 1.8, 1.9 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6325/setuptools/command Modified Files: __init__.py egg_info.py Log Message: Implement "entry points" for dynamic discovery of drivers and plugins. Change setuptools to discover setup commands using an entry point group called "distutils.commands". Thanks to Ian Bicking for the suggestion that led to designing this super-cool feature. Index: __init__.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/__init__.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- __init__.py 8 Jul 2005 05:09:23 -0000 1.6 +++ __init__.py 24 Jul 2005 22:47:06 -0000 1.7 @@ -1,17 +1,10 @@ -import distutils.command - __all__ = [ - 'test', 'develop', 'bdist_egg', 'saveopts', 'setopt', 'rotate', 'alias' + 'alias', 'bdist_egg', 'build_ext', 'build_py', 'depends', 'develop', + 'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts', + 'sdist', 'setopt', 'test', 'upload', ] -# Make our commands available as though they were part of the distutils - -distutils.command.__path__.extend(__path__) -distutils.command.__all__.extend( - [cmd for cmd in __all__ if cmd not in distutils.command.__all__] - ) - from distutils.command.bdist import bdist if 'egg' not in bdist.format_commands: Index: egg_info.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/command/egg_info.py,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- egg_info.py 24 Jul 2005 17:59:27 -0000 1.8 +++ egg_info.py 24 Jul 2005 22:47:06 -0000 1.9 @@ -8,7 +8,7 @@ from distutils.errors import * from distutils import log from pkg_resources import parse_requirements, safe_name, \ - safe_version, yield_lines + safe_version, yield_lines, EntryPoint from setuptools.dist import iter_distribution_names class egg_info(Command): @@ -95,7 +95,7 @@ metadata.write_pkg_info(self.egg_info) finally: metadata.name, metadata.version = oldname, oldver - + self.write_entry_points() self.write_requirements() self.write_toplevel_names() self.write_or_delete_dist_arg('namespace_packages') @@ -183,23 +183,23 @@ if not self.dry_run: os.unlink(filename) + def write_entry_points(self): + ep = getattr(self.distribution,'entry_points',None) + if ep is None: + return + epname = os.path.join(self.egg_info,"entry_points.txt") + log.info("writing %s", epname) - - - - - - - - - - - - - - - - - + if not self.dry_run: + f = open(epname, 'wt') + if isinstance(ep,basestring): + f.write(ep) + else: + for section, contents in ep.items(): + if not isinstance(contents,basestring): + contents = EntryPoint.parse_list(section, contents) + contents = '\n'.join(map(str,contents.values())) + f.write('[%s]\n%s\n\n' % (section,contents)) + f.close() From pje at users.sourceforge.net Mon Jul 25 00:47:08 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 15:47:08 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.52, 1.53 setup.py, 1.32, 1.33 setuptools.txt, 1.22, 1.23 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6325 Modified Files: pkg_resources.py setup.py setuptools.txt Log Message: Implement "entry points" for dynamic discovery of drivers and plugins. Change setuptools to discover setup commands using an entry point group called "distutils.commands". Thanks to Ian Bicking for the suggestion that led to designing this super-cool feature. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.52 retrieving revision 1.53 diff -u -d -r1.52 -r1.53 --- pkg_resources.py 24 Jul 2005 17:59:26 -0000 1.52 +++ pkg_resources.py 24 Jul 2005 22:47:05 -0000 1.53 @@ -12,21 +12,6 @@ .zip files and with custom PEP 302 loaders that support the ``get_data()`` method. """ -__all__ = [ - 'register_loader_type', 'get_provider', 'IResourceProvider','PathMetadata', - 'ResourceManager', 'AvailableDistributions', 'require', 'resource_string', - 'resource_stream', 'resource_filename', 'set_extraction_path', 'EGG_DIST', - 'cleanup_resources', 'parse_requirements', 'ensure_directory','SOURCE_DIST', - 'compatible_platforms', 'get_platform', 'IMetadataProvider','parse_version', - 'ResolutionError', 'VersionConflict', 'DistributionNotFound','EggMetadata', - 'InvalidOption', 'Distribution', 'Requirement', 'yield_lines', - 'get_importer', 'find_distributions', 'find_on_path', 'register_finder', - 'split_sections', 'declare_namespace', 'register_namespace_handler', - 'safe_name', 'safe_version', 'run_main', 'BINARY_DIST', 'run_script', - 'get_default_cache', 'EmptyProvider', 'empty_provider', 'normalize_path', - 'WorkingSet', 'working_set', 'add_activation_listener', 'CHECKOUT_DIST', - 'list_resources', 'resource_exists', 'resource_isdir', -] import sys, os, zipimport, time, re, imp from sets import ImmutableSet @@ -39,6 +24,62 @@ + + + + + + + + + + + + + + + +__all__ = [ + # Basic resource access and distribution/entry point discovery + 'require', 'run_script', 'get_provider', 'get_distribution', + 'load_entry_point', 'get_entry_map', 'get_entry_info', + 'resource_string', 'resource_stream', 'resource_filename', + 'resource_listdir', 'resource_exists', 'resource_isdir', + + # Environmental control + 'declare_namespace', 'working_set', 'add_activation_listener', + 'find_distributions', 'set_extraction_path', 'cleanup_resources', + 'get_default_cache', + + # Primary implementation classes + 'AvailableDistributions', 'WorkingSet', 'ResourceManager', + 'Distribution', 'Requirement', 'EntryPoint', + + # Exceptions + 'ResolutionError','VersionConflict','DistributionNotFound','UnknownExtra', + + # Parsing functions and string utilities + 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', + 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', + + # filesystem utilities + 'ensure_directory', 'normalize_path', + + # Distribution "precedence" constants + 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', + + # "Provider" interfaces, implementations, and registration/lookup APIs + 'IMetadataProvider', 'IResourceProvider', + 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', + 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', + 'register_finder', 'register_namespace_handler', 'register_loader_type', + 'fixup_namespace_packages', 'get_importer', + + # Deprecated/backward compatibility only + 'run_main', +] + + class ResolutionError(Exception): """Abstract base for dependency resolution errors""" @@ -48,8 +89,8 @@ class DistributionNotFound(ResolutionError): """A requested distribution was not found""" -class InvalidOption(ResolutionError): - """Invalid or unrecognized option name for a distribution""" +class UnknownExtra(ResolutionError): + """Distribution doesn't have an "extra feature" of the given name""" _provider_factories = {} PY_MAJOR = sys.version[:3] @@ -172,7 +213,6 @@ return False - def run_script(dist_spec, script_name): """Locate distribution `dist_spec` and run its `script_name` script""" ns = sys._getframe(1).f_globals @@ -183,24 +223,25 @@ run_main = run_script # backward compatibility +def get_distribution(dist): + """Return a current distribution object for a Requirement or string""" + if isinstance(dist,basestring): dist = Requirement.parse(dist) + if isinstance(dist,Requirement): dist = get_provider(dist) + if not isintance(dist,Distribution): + raise TypeError("Expected string, Requirement, or Distribution", dist) + return dist +def load_entry_point(dist, kind, name): + """Return the `name` entry point of `kind` for dist or raise ImportError""" + return get_distribution(dist).load_entry_point(dist, kind, name) + +def get_entry_map(dist, kind=None): + """Return the entry point map for `kind`, or the full entry map""" + return get_distribution(dist).get_entry_map(dist, kind) - - - - - - - - - - - - - - - - +def get_entry_info(dist, kind, name): + """Return the EntryPoint object for `kind`+`name`, or ``None``""" + return get_distribution(dist).get_entry_info(dist, kind, name) class IMetadataProvider: @@ -647,7 +688,7 @@ self, resource_name ) - def list_resources(self, package_name, resource_name): + def resource_listdir(self, package_name, resource_name): return get_provider(package_name).resource_listdir(resource_name) @@ -1008,9 +1049,9 @@ return fspath[len(self.egg_root)+1:].split(os.sep) raise AssertionError( "%s is not a subpath of %s" % (fspath,self.egg_root) - ) + ) - def get_resource_filename(self, manager, resource_name): + def get_resource_filename(self, manager, resource_name): if not self.egg_name: raise NotImplementedError( "resource_filename() only supported for .egg, not .zip" @@ -1493,7 +1534,7 @@ COMMA = re.compile(r"\s*,").match # comma between items OBRACKET = re.compile(r"\s*\[").match CBRACKET = re.compile(r"\s*\]").match - +MODULE = re.compile(r"\w+(\.\w+)*$").match EGG_NAME = re.compile( r"(?P[^-]+)" r"( -(?P[^-]+) (-py(?P[^-]+) (-(?P.+))? )? )?", @@ -1556,6 +1597,131 @@ +class EntryPoint(object): + """Object representing an importable location""" + + def __init__(self, name, module_name, attrs=(), extras=()): + if not MODULE(module_name): + raise ValueError("Invalid module name", module_name) + self.name = name + self.module_name = module_name + self.attrs = tuple(attrs) + self.extras = Requirement.parse( + ("x[%s]" % ','.join(extras)).lower() + ).extras + + def __str__(self): + s = "%s = %s" % (self.name, self.module_name) + if self.attrs: + s += ':' + '.'.join(self.attrs) + if self.extras: + s += ' [%s]' % ','.join(self.extras) + return s + + def __repr__(self): + return "EntryPoint.parse(%r)" % str(self) + + def load(self): + entry = __import__(self.module_name, globals(),globals(), ['__name__']) + for attr in self.attrs: + try: + entry = getattr(entry,attr) + except AttributeError: + raise ImportError("%r has no %r attribute" % (entry,attr)) + return entry + + + + + + + + + + #@classmethod + def parse(cls, src): + """Parse a single entry point from string `src` + + Entry point syntax follows the form:: + + name = some.module:some.attr [extra1,extra2] + + The entry name and module name are required, but the ``:attrs`` and + ``[extras]`` parts are optional + """ + try: + attrs = extras = () + name,value = src.split('=',1) + if '[' in value: + value,extras = value.split('[',1) + req = Requirement.parse("x["+extras) + if req.specs: raise ValueError + extras = req.extras + if ':' in value: + value,attrs = value.split(':',1) + if not MODULE(attrs.rstrip()): + raise ValueError + attrs = attrs.rstrip().split('.') + except ValueError: + raise ValueError( + "EntryPoint must be in 'name=module:attrs [extras]' format", + src + ) + else: + return cls(name.strip(), value.lstrip(), attrs, extras) + + parse = classmethod(parse) + + + + + + + + + #@classmethod + def parse_list(cls, section, contents): + if not MODULE(section): + raise ValueError("Invalid section name", section) + this = {} + for ep in map(cls.parse, yield_lines(contents)): + if ep.name in this: + raise ValueError("Duplicate entry point",section,ep.name) + this[ep.name]=ep + return this + + parse_list = classmethod(parse_list) + + #@classmethod + def parse_map(cls, data): + if isinstance(data,dict): + data = data.items() + else: + data = split_sections(data) + maps = {} + for section, contents in data: + if section is None: + if not contents: + continue + raise ValueError("Entry points must be listed in sections") + section = section.strip() + if section in maps: + raise ValueError("Duplicate section name", section) + maps[section] = cls.parse_list(section, contents) + return maps + + parse_map = classmethod(parse_map) + + + + + + + + + + + class Distribution(object): """Wrap an actual or potential sys.path entry w/metadata""" def __init__(self, @@ -1660,7 +1826,7 @@ try: deps.extend(dm[ext.lower()]) except KeyError: - raise InvalidOption( + raise UnknownExtra( "%s has no such extra feature %r" % (self, ext) ) return deps @@ -1720,6 +1886,47 @@ + def load_entry_point(self, kind, name): + """Return the `name` entry point of `kind` or raise ImportError""" + ep = self.get_entry_info(kind,name) + if ep is None: + raise ImportError("Entry point %r not found" % ((kind,name),)) + if ep.extras: + # Ensure any needed extras get added to the working set + map(working_set.add, working_set.resolve(self.requires(ep.extras))) + return ep.load() + + def get_entry_map(self,kind=None): + """Return the entry point map for `kind`, or the full entry map""" + try: + ep_map = self._ep_map + except AttributeError: + ep_map = self._ep_map = EntryPoint.parse_map( + self._get_metadata('entry_points.txt') + ) + if kind is not None: + return ep_map.get(kind,{}) + return ep_map + + def get_entry_info(self, kind, name): + """Return the EntryPoint object for `kind`+`name`, or ``None``""" + return self.get_entry_map(kind).get(name) + + + + + + + + + + + + + + + + def parse_requirements(strs): """Yield ``Requirement`` objects for each specification in `strs` @@ -1885,6 +2092,7 @@ def ensure_directory(path): + """Ensure that the parent directory of `path` exists""" dirname = os.path.dirname(path) if not os.path.isdir(dirname): os.makedirs(dirname) @@ -1924,7 +2132,6 @@ - # Set up global resource manager _manager = ResourceManager() Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.32 retrieving revision 1.33 diff -u -d -r1.32 -r1.33 --- setup.py 18 Jul 2005 02:06:15 -0000 1.32 +++ setup.py 24 Jul 2005 22:47:05 -0000 1.33 @@ -18,6 +18,9 @@ VERSION = "0.6a0" from setuptools import setup, find_packages +import sys + +from setuptools.command import __all__ as SETUP_COMMANDS setup( name="setuptools", @@ -35,9 +38,15 @@ packages = find_packages(), py_modules = ['pkg_resources', 'easy_install'], scripts = ['easy_install.py'], + zip_safe = False, # We want 'python -m easy_install' to work :( - + entry_points = { + "distutils.commands" : [ + "%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals() + for cmd in SETUP_COMMANDS if cmd!="build_py" or sys.version>="2.4" + ], + }, classifiers = [f.strip() for f in """ Development Status :: 3 - Alpha @@ -71,12 +80,3 @@ - - - - - - - - - Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- setuptools.txt 24 Jul 2005 17:59:26 -0000 1.22 +++ setuptools.txt 24 Jul 2005 22:47:05 -0000 1.23 @@ -153,21 +153,20 @@ A string or list of strings specifying what other distributions need to be installed when this one is. See the section below on `Declaring Dependencies`_ for details and examples of the format of this argument. - + +``entry_points`` + A dictionary mapping entry point group names to strings or lists of strings + defining the entry points. Entry points are used to support dynamic + discovery of services or plugins provided by a project. See `Dynamic + Discovery of Services and Plugins`_ for details and examples of the format + of this argument. + ``extras_require`` A dictionary mapping names of "extras" (optional features of your project) to strings or lists of strings specifying what other distributions must be installed to support those features. See the section below on `Declaring Dependencies`_ for details and examples of the format of this argument. -``test_suite`` - A string naming a ``unittest.TestCase`` subclass (or a module containing - one or more of them, or a method of such a subclass), or naming a function - that can be called with no arguments and returns a ``unittest.TestSuite``. - Specifying this argument enables use of the `test`_ command to run the - specified test suite, e.g. via ``setup.py test``. See the section on the - `test`_ command below for more details. - ``namespace_packages`` A list of strings naming the project's "namespace packages". A namespace package is a package that may be split across multiple project @@ -180,6 +179,14 @@ does not contain any code. See the section below on `Namespace Packages`_ for more information. +``test_suite`` + A string naming a ``unittest.TestCase`` subclass (or a module containing + one or more of them, or a method of such a subclass), or naming a function + that can be called with no arguments and returns a ``unittest.TestSuite``. + Specifying this argument enables use of the `test`_ command to run the + specified test suite, e.g. via ``setup.py test``. See the section on the + `test`_ command below for more details. + ``eager_resources`` A list of strings naming resources that should be extracted together, if any of them is needed, or if any C extensions included in the project are @@ -516,7 +523,72 @@ there's any possibility of ``eager_resources`` being relevant to your project. +Extensible Applications and Frameworks +====================================== + +Dynamic Discovery of Services and Plugins +----------------------------------------- + +``setuptools`` supports creating libraries that "plug in" to extensible +applications and frameworks, by letting you register "entry points" in your +project that can be imported by the application or framework. + +For example, suppose that a blogging tool wants to support plugins +that provide translation for various file types to the blog's output format. +The framework might define an "entry point group" called ``blogtool.parsers``, +and then allow plugins to register entry points for the file extensions they +support. + +This would allow people to create distributions that contain one or more +parsers for different file types, and then the blogging tool would be able to +find the parsers at runtime by looking up an entry point for the file +extension (or mime type, or however it wants to). + +Note that if the blogging tool includes parsers for certain file formats, it +can register these as entry points in its own setup script, which means it +doesn't have to special-case its built-in formats. They can just be treated +the same as any other plugin's entry points would be. + +If you're creating a project that plugs in to an existing application or +framework, you'll need to know what entry points or entry point groups are +defined by that application or framework. Then, you can register entry points +in your setup script. Here are a few examples of ways you might register an +``.rst`` file parser entry point in the ``blogtool.parsers`` entry point group, +for our hypothetical blogging tool:: + + setup( + # ... + entry_points = {'blogtool.parsers': '.rst = some_module:SomeClass'} + ) + + setup( + # ... + entry_points = {'blogtool.parsers': ['.rst = some_module:a_func']} + ) + + setup( + # ... + entry_points = """ + [blogtool.parsers] + .rst = some.nested.module:SomeClass.some_classmethod [reST] + """, + extras_require = dict(reST = "Docutils>=0.3.5") + ) + +The ``entry_points`` argument to ``setup()`` accepts either a string with +``.ini``-style sections, or a dictionary mapping entry point group names to +either strings or lists of strings containing entry point specifiers. An +entry point specifier consists of a name and value, separated by an ``=`` +sign. The value consists of a dotted module name, optionally followed by a +``:`` and a dotted identifier naming an object within the module. It can +also include a bracketed list of "extras" that are required for the entry +point to be used. When the invoking application or framework requests loading +of an entry point, any requirements implied by the associated extras will be +passed to ``pkg_resources.require()``, so that an appropriate error message +can be displayed if the needed package(s) are missing. (Of course, the +invoking app or framework can ignore such errors if it wants to make an entry +point optional if a requirement isn't installed.) "Development Mode" @@ -1072,12 +1144,13 @@ command to ensure any C extensions in the project have been built and are up-to-date, and the ``egg_info`` command to ensure the project's metadata is updated (so that the runtime and wrappers know what the project's dependencies -are). If you make changes to the project's metadata or C extensions, you -should rerun the ``develop`` command (or ``egg_info``, or ``build_ext -i``) in -order to keep the project up-to-date. If you add or rename any of the -project's scripts, you should re-run ``develop`` against all relevant staging -areas to update the wrapper scripts. Most other kinds of changes to your -project should not require any build operations or rerunning ``develop``. +are). If you make any changes to the project's setup script or C extensions, +you should rerun the ``develop`` command against all relevant staging areas to +keep the project's scripts, metadata and extensions up-to-date. Most other +kinds of changes to your project should not require any build operations or +rerunning ``develop``, but keep in mind that even minor changes to the setup +script (e.g. changing an entry point definition) require you to re-run the +``develop`` or ``test`` commands to keep the distribution updated. Here are the options that the ``develop`` command accepts. Note that they affect the project's dependencies as well as the project itself, so if you have @@ -1442,8 +1515,39 @@ added or updated. +Adding Commands +=============== + +You can create add-on packages that extend setuptools with additional commands +by defining entry points in the ``distutils.commands`` group. For example, if +you wanted to add a ``foo`` command, you might add something like this to your +setup script:: + + setup( + # ... + entry_points = { + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + }, + ) + +Assuming, of course, that the ``foo`` class in ``mypackage.some_module`` is +a ``setuptools.Command`` subclass. + +Once a project containing such entry points has been activated on ``sys.path``, +(e.g. by running "install" or "develop" with a site-packages installation +directory) the command(s) will be available to any ``setuptools``-based setup +scripts. It is not necessary to use the ``--command-packages`` option or +to monkeypatch the ``distutils.command`` package to install your commands; +``setuptools`` automatically adds a wrapper to the distutils to search for +entry points in the active distributions on ``sys.path``. In fact, this is +how setuptools' own commands are installed: the setuptools setup script defines +entry points for them. + + Subclassing ``Command`` -======================= +----------------------- XXX @@ -1492,9 +1596,15 @@ * Fixed ``pkg_resources.resource_exists()`` not working correctly, along with some other resource API bugs. + * Added ``entry_points`` argument to ``setup()`` * Many ``pkg_resources`` API changes and enhancements: + * Added ``EntryPoint``, ``get_entry_map``, ``load_entry_point``, and + ``get_entry_info`` APIs for dynamic plugin discovery. + + * ``list_resources`` is now ``resource_listdir`` (and it actually works) + * Resource API functions like ``resource_string()`` that accepted a package name and resource name, will now also accept a ``Requirement`` object in place of the package name (to allow access to non-package data files in @@ -1532,7 +1642,8 @@ * Distribution objects no longer have an ``installed_on()`` method, and the ``install_on()`` method is now ``activate()`` (but may go away altogether - soon). The ``depends()`` method has also been renamed to ``requires()``. + soon). The ``depends()`` method has also been renamed to ``requires()``, + and ``InvalidOption`` is now ``UnknownExtra``. * ``find_distributions()`` now takes an additional argument called ``only``, that tells it to only yield distributions whose location is the passed-in From pje at users.sourceforge.net Mon Jul 25 05:12:53 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 20:12:53 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools dist.py, 1.16, 1.17 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv750/setuptools Modified Files: dist.py Log Message: Misc. bug fixes and doc additions. Add 'iter_entry_points()' API. Index: dist.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/dist.py,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- dist.py 24 Jul 2005 22:47:05 -0000 1.16 +++ dist.py 25 Jul 2005 03:12:51 -0000 1.17 @@ -16,20 +16,17 @@ if command in self.cmdclass: return self.cmdclass[command] - for dist in pkg_resources.working_set: - if dist.get_entry_info('distutils.commands',command): - cmdclass = dist.load_entry_point('distutils.commands',command) - self.cmdclass[command] = cmdclass - return cmdclass + for ep in pkg_resources.iter_entry_points('distutils.commands',command): + self.cmdclass[command] = cmdclass = ep.load() + return cmdclass else: return _old_get_command_class(self, command) def print_commands(self): - for dist in pkg_resources.working_set: - for cmd,ep in dist.get_entry_map('distutils.commands').items(): - if cmd not in self.cmdclass: - cmdclass = ep.load() # don't require extras, we're not running - self.cmdclass[cmd] = cmdclass + for ep in pkg_resources.iter_entry_points('distutils.commands'): + if ep.name not in self.cmdclass: + cmdclass = ep.load(False) # don't require extras, we're not running + self.cmdclass[ep.name] = cmdclass return _old_print_commands(self) for meth in 'print_commands', 'get_command_class': @@ -39,6 +36,9 @@ sequence = tuple, list + + + class Distribution(_Distribution): """Distribution with support for features, tests, and package data From pje at users.sourceforge.net Mon Jul 25 05:12:54 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 20:12:54 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools/setuptools/tests test_resources.py, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv750/setuptools/tests Modified Files: test_resources.py Log Message: Misc. bug fixes and doc additions. Add 'iter_entry_points()' API. Index: test_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools/tests/test_resources.py,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- test_resources.py 24 Jul 2005 22:47:06 -0000 1.19 +++ test_resources.py 25 Jul 2005 03:12:51 -0000 1.20 @@ -216,16 +216,20 @@ "foo = setuptools.tests.test_resources:EntryPointTests [x]" ) + def setUp(self): + self.dist = Distribution.from_filename( + "FooPkg-1.2-py2.4.egg", metadata=Metadata(('requires.txt','[x]'))) + def testBasics(self): ep = EntryPoint( "foo", "setuptools.tests.test_resources", ["EntryPointTests"], - ["x"] + ["x"], self.dist ) self.assertfields(ep) def testParse(self): s = "foo = setuptools.tests.test_resources:EntryPointTests [x]" - ep = EntryPoint.parse(s) + ep = EntryPoint.parse(s, self.dist) self.assertfields(ep) ep = EntryPoint.parse("bar baz= spammity[PING]") @@ -240,10 +244,6 @@ self.assertEqual(ep.attrs, ("foo",)) self.assertEqual(ep.extras, ()) - - - - def testRejects(self): for ep in [ "foo", "x=1=2", "x=a:b:c", "q=x/na", "fez=pish:tush-z", "x=f[a]>2", From pje at users.sourceforge.net Mon Jul 25 05:12:54 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 24 Jul 2005 20:12:54 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools EasyInstall.txt, 1.48, 1.49 pkg_resources.py, 1.53, 1.54 setuptools.txt, 1.23, 1.24 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv750 Modified Files: EasyInstall.txt pkg_resources.py setuptools.txt Log Message: Misc. bug fixes and doc additions. Add 'iter_entry_points()' API. Index: EasyInstall.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/EasyInstall.txt,v retrieving revision 1.48 retrieving revision 1.49 diff -u -d -r1.48 -r1.49 --- EasyInstall.txt 24 Jul 2005 02:41:43 -0000 1.48 +++ EasyInstall.txt 25 Jul 2005 03:12:50 -0000 1.49 @@ -647,7 +647,7 @@ "site" directory, he or she should create an ``altinstall.pth`` file in the normal site-packages directory, containing this:: - import os; addsitedir(os.path.expanduser('~/lib/python2.3')) + import os, site; site.addsitedir(os.path.expanduser('~/lib/python2.3')) and a ``distutils.cfg`` file inside the ``distutils`` package directory, containing this:: Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.53 retrieving revision 1.54 diff -u -d -r1.53 -r1.54 --- pkg_resources.py 24 Jul 2005 22:47:05 -0000 1.53 +++ pkg_resources.py 25 Jul 2005 03:12:50 -0000 1.54 @@ -42,7 +42,7 @@ __all__ = [ # Basic resource access and distribution/entry point discovery 'require', 'run_script', 'get_provider', 'get_distribution', - 'load_entry_point', 'get_entry_map', 'get_entry_info', + 'load_entry_point', 'get_entry_map', 'get_entry_info', 'iter_entry_points', 'resource_string', 'resource_stream', 'resource_filename', 'resource_listdir', 'resource_exists', 'resource_isdir', @@ -231,17 +231,17 @@ raise TypeError("Expected string, Requirement, or Distribution", dist) return dist -def load_entry_point(dist, kind, name): - """Return the `name` entry point of `kind` for dist or raise ImportError""" - return get_distribution(dist).load_entry_point(dist, kind, name) +def load_entry_point(dist, group, name): + """Return `name` entry point of `group` for `dist` or raise ImportError""" + return get_distribution(dist).load_entry_point(group, name) -def get_entry_map(dist, kind=None): - """Return the entry point map for `kind`, or the full entry map""" - return get_distribution(dist).get_entry_map(dist, kind) +def get_entry_map(dist, group=None): + """Return the entry point map for `group`, or the full entry map""" + return get_distribution(dist).get_entry_map(group) -def get_entry_info(dist, kind, name): - """Return the EntryPoint object for `kind`+`name`, or ``None``""" - return get_distribution(dist).get_entry_info(dist, kind, name) +def get_entry_info(dist, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return get_distribution(dist).get_entry_info(group, name) class IMetadataProvider: @@ -377,7 +377,6 @@ for key in self.entry_keys[item]: yield self.by_key[key] - def find(self, req): """Find a distribution matching requirement `req` @@ -394,19 +393,20 @@ else: return dist + def iter_entry_points(self, group, name=None): + """Yield entry point objects from `group` matching `name` - - - - - - - - - - - - + If `name` is None, yields all entry points in `group` from all + distributions in the working set, otherwise only ones matching + both `group` and `name` are yielded (in distribution order). + """ + for dist in self: + entries = dist.get_entry_map(group) + if name is None: + for ep in entries.values(): + yield ep + elif name in entries: + yield entries[name] def add(self, dist, entry=None): """Add `dist` to working set, associated with `entry` @@ -1600,7 +1600,7 @@ class EntryPoint(object): """Object representing an importable location""" - def __init__(self, name, module_name, attrs=(), extras=()): + def __init__(self, name, module_name, attrs=(), extras=(), dist=None): if not MODULE(module_name): raise ValueError("Invalid module name", module_name) self.name = name @@ -1609,6 +1609,7 @@ self.extras = Requirement.parse( ("x[%s]" % ','.join(extras)).lower() ).extras + self.dist = dist def __str__(self): s = "%s = %s" % (self.name, self.module_name) @@ -1621,7 +1622,8 @@ def __repr__(self): return "EntryPoint.parse(%r)" % str(self) - def load(self): + def load(self, require=True): + if require: self.require() entry = __import__(self.module_name, globals(),globals(), ['__name__']) for attr in self.attrs: try: @@ -1630,16 +1632,14 @@ raise ImportError("%r has no %r attribute" % (entry,attr)) return entry - - - - - - - - + def require(self): + if self.extras and not self.dist: + raise UnknownExtra("Can't require() without a distribution", self) + map(working_set.add, + working_set.resolve(self.dist.requires(self.extras))) + #@classmethod - def parse(cls, src): + def parse(cls, src, dist=None): """Parse a single entry point from string `src` Entry point syntax follows the form:: @@ -1668,7 +1668,7 @@ src ) else: - return cls(name.strip(), value.lstrip(), attrs, extras) + return cls(name.strip(), value.lstrip(), attrs, extras, dist) parse = classmethod(parse) @@ -1680,11 +1680,12 @@ #@classmethod - def parse_list(cls, section, contents): + def parse_list(cls, section, contents, dist=None): if not MODULE(section): raise ValueError("Invalid section name", section) this = {} - for ep in map(cls.parse, yield_lines(contents)): + for line in yield_lines(contents): + ep = cls.parse(line, dist) if ep.name in this: raise ValueError("Duplicate entry point",section,ep.name) this[ep.name]=ep @@ -1693,7 +1694,7 @@ parse_list = classmethod(parse_list) #@classmethod - def parse_map(cls, data): + def parse_map(cls, data, dist=None): if isinstance(data,dict): data = data.items() else: @@ -1707,7 +1708,7 @@ section = section.strip() if section in maps: raise ValueError("Duplicate section name", section) - maps[section] = cls.parse_list(section, contents) + maps[section] = cls.parse_list(section, contents, dist) return maps parse_map = classmethod(parse_map) @@ -1719,9 +1720,6 @@ - - - class Distribution(object): """Wrap an actual or potential sys.path entry w/metadata""" def __init__(self, @@ -1886,31 +1884,31 @@ - def load_entry_point(self, kind, name): - """Return the `name` entry point of `kind` or raise ImportError""" - ep = self.get_entry_info(kind,name) + def load_entry_point(self, group, name): + """Return the `name` entry point of `group` or raise ImportError""" + ep = self.get_entry_info(group,name) if ep is None: - raise ImportError("Entry point %r not found" % ((kind,name),)) - if ep.extras: - # Ensure any needed extras get added to the working set - map(working_set.add, working_set.resolve(self.requires(ep.extras))) + raise ImportError("Entry point %r not found" % ((group,name),)) return ep.load() - def get_entry_map(self,kind=None): - """Return the entry point map for `kind`, or the full entry map""" + def get_entry_map(self, group=None): + """Return the entry point map for `group`, or the full entry map""" try: ep_map = self._ep_map except AttributeError: ep_map = self._ep_map = EntryPoint.parse_map( - self._get_metadata('entry_points.txt') + self._get_metadata('entry_points.txt'), self ) - if kind is not None: - return ep_map.get(kind,{}) + if group is not None: + return ep_map.get(group,{}) return ep_map - def get_entry_info(self, kind, name): - """Return the EntryPoint object for `kind`+`name`, or ``None``""" - return self.get_entry_map(kind).get(name) + def get_entry_info(self, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return self.get_entry_map(group).get(name) + + + @@ -2147,6 +2145,7 @@ working_set = WorkingSet() require = working_set.require +iter_entry_points = working_set.iter_entry_points add_activation_listener = working_set.subscribe # Activate all distributions already on sys.path, and ensure that @@ -2172,4 +2171,3 @@ - Index: setuptools.txt =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setuptools.txt,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- setuptools.txt 24 Jul 2005 22:47:05 -0000 1.23 +++ setuptools.txt 25 Jul 2005 03:12:51 -0000 1.24 @@ -72,6 +72,14 @@ setuptools being present; if so, you must be sure to delete it entirely, along with the old ``pkg_resources`` module if it's present on ``sys.path``. +To get the in-development version of setuptools, run:: + + cvs -d:pserver:anonymous at cvs.sourceforge.net:/cvsroot/python login + cvs -z3 -d:pserver:anonymous at cvs.sourceforge.net:/cvsroot/python \ + co -d setuptools python/nondist/sandbox/setuptools + +You can then install it using the usual "setup.py install" incantation. + Basic Use ========= From birkenfeld at users.sourceforge.net Mon Jul 25 09:34:26 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 25 Jul 2005 00:34:26 -0700 Subject: [Python-checkins] python/nondist/sandbox/path path.py, 1.4, 1.5 test_path.py, 1.4, 1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10847 Modified Files: path.py test_path.py Log Message: * Add base() method to convert to str/unicode. * Allow compare against normal strings. Index: path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/path.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- path.py 24 Jul 2005 15:51:07 -0000 1.4 +++ path.py 25 Jul 2005 07:34:21 -0000 1.5 @@ -69,17 +69,8 @@ def __repr__(self): return 'Path(%s)' % repr(_base(self)) - def __str__(self): - if _base is unicode: - return str(self[:]) - else: - return self[:] - - def __unicode__(self): - if _base is unicode: - return self[:] - else: - return unicode(self[:]) + def base(self): + return _base(self) # Adding path and string yields a path # Caution: this is not a join! @@ -99,37 +90,6 @@ __truediv__ = __div__ - if _base is str: - # Rich comparison for string - def __eq__(self, other): - return isinstance(other, Path) and _base.__eq__(self, other) - - def __ne__(self, other): - return (not isinstance(other, Path)) or _base.__ne__(self, other) - - def __lt__(self, other): - if isinstance(other, Path): - return _base.__lt__(self, other) - return NotImplemented - def __le__(self, other): - if isinstance(other, Path): - return _base.__le__(self, other) - return NotImplemented - def __gt__(self, other): - if isinstance(other, Path): - return _base.__gt__(self, other) - return NotImplemented - def __ge__(self, other): - if isinstance(other, Path): - return _base.__ge__(self, other) - return NotImplemented - else: - # Unicode has no rich compare methods - def __cmp__(self, other): - if isinstance(other, Path): - return _base.__cmp__(self, other) - return NotImplemented - # Alternative constructor. @staticmethod Index: test_path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/test_path.py,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- test_path.py 24 Jul 2005 15:51:07 -0000 1.4 +++ test_path.py 25 Jul 2005 07:34:23 -0000 1.5 @@ -58,14 +58,15 @@ d = Path('D:\\') self.assertEqual(d.relpathto(boz), boz) - ## this isn't going to work cause Paths won't compare - ## to ordinary strings - ''' def testStringCompatibility(self): """ Test compatibility with ordinary strings. """ - #x = Path('xyzzy') - #self.assertEqual(x, 'xyzzy') - #self.assertEqual(x, u'xyzzy') + x = Path('xyzzy') + self.assertEqual(x, 'xyzzy') + self.assertEqual(x, u'xyzzy') + + strx = x.base() + self.assertEqual(strx, x) + self.assert_(strx.__class__ in (str, unicode)) # sorting items = [Path('fhj'), @@ -77,7 +78,6 @@ 'c'] items.sort() self.assert_(items == ['A', 'B', 'E', 'c', 'd', 'fgh', 'fhj']) - ''' def testProperties(self): # Create sample Path object. From birkenfeld at users.sourceforge.net Mon Jul 25 18:06:35 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 25 Jul 2005 09:06:35 -0700 Subject: [Python-checkins] python/nondist/sandbox/path path.py, 1.5, 1.6 test_path.py, 1.5, 1.6 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21228 Modified Files: path.py test_path.py Log Message: Don't accept anything except a basestring as constructor argument. Index: path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/path.py,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- path.py 25 Jul 2005 07:34:21 -0000 1.5 +++ path.py 25 Jul 2005 16:06:32 -0000 1.6 @@ -60,6 +60,10 @@ """ if not args: return Path(os.curdir) + if len(args) > 1: + raise TypeError("Path() takes at most 1 argument (%i given)" % len(args)) + if not isinstance(args[0], basestring): + raise ValueError("Path() argument must be str or unicode") return _base.__new__(typ, *args) # Iterating over a string yields its parts Index: test_path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/test_path.py,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- test_path.py 25 Jul 2005 07:34:23 -0000 1.5 +++ test_path.py 25 Jul 2005 16:06:32 -0000 1.6 @@ -27,6 +27,18 @@ return choices[os.name] class BasicTestCase(unittest.TestCase): + def testConstructor(self): + # constructor can only be called with zero or one arguments + p = Path() + self.assert_(p.base() == os.curdir) + + self.assertRaises(TypeError, Path, "a", "b") + self.assertRaises(TypeError, Path, 1, 2) + + # constructor can only be called with basestring as argument + self.assertRaises(ValueError, Path, None) + self.assertRaises(ValueError, Path, 1) + def testRelpath(self): root = Path(p(nt='C:\\', posix='/')) From birkenfeld at users.sourceforge.net Mon Jul 25 18:09:20 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Mon, 25 Jul 2005 09:09:20 -0700 Subject: [Python-checkins] python/nondist/sandbox/path path.py,1.6,1.7 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22176 Modified Files: path.py Log Message: Index: path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/path.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- path.py 25 Jul 2005 16:06:32 -0000 1.6 +++ path.py 25 Jul 2005 16:09:17 -0000 1.7 @@ -63,7 +63,7 @@ if len(args) > 1: raise TypeError("Path() takes at most 1 argument (%i given)" % len(args)) if not isinstance(args[0], basestring): - raise ValueError("Path() argument must be str or unicode") + raise ValueError("Path() argument must be Path, str or unicode") return _base.__new__(typ, *args) # Iterating over a string yields its parts From tmick at users.sourceforge.net Tue Jul 26 04:29:23 2005 From: tmick at users.sourceforge.net (tmick@users.sourceforge.net) Date: Mon, 25 Jul 2005 19:29:23 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1322,1.1323 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3727/dist/src/Misc Modified Files: NEWS Log Message: Upgrade Windows build to zlib 1.2.3 (a security fix) Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1322 retrieving revision 1.1323 diff -u -d -r1.1322 -r1.1323 --- NEWS 22 Jul 2005 21:49:30 -0000 1.1322 +++ NEWS 26 Jul 2005 02:29:20 -0000 1.1323 @@ -374,6 +374,9 @@ Build ----- +- Upgrade Windows build to zlib 1.2.3 which eliminates a potential security + vulnerability in zlib 1.2.1 and 1.2.2. + - EXTRA_CFLAGS has been introduced as an environment variable to hold compiler flags that change binary compatibility. Changes were also made to distutils.sysconfig to also use the environment variable when used during From tmick at users.sourceforge.net Tue Jul 26 04:29:24 2005 From: tmick at users.sourceforge.net (tmick@users.sourceforge.net) Date: Mon, 25 Jul 2005 19:29:24 -0700 Subject: [Python-checkins] python/dist/src/PCbuild readme.txt, 1.59, 1.60 zlib.vcproj, 1.6, 1.7 Message-ID: Update of /cvsroot/python/python/dist/src/PCbuild In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3727/dist/src/PCbuild Modified Files: readme.txt zlib.vcproj Log Message: Upgrade Windows build to zlib 1.2.3 (a security fix) Index: readme.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/readme.txt,v retrieving revision 1.59 retrieving revision 1.60 diff -u -d -r1.59 -r1.60 --- readme.txt 6 Jul 2005 19:34:10 -0000 1.59 +++ readme.txt 26 Jul 2005 02:29:21 -0000 1.60 @@ -126,15 +126,15 @@ zlib Python wrapper for the zlib compression library. Get the source code - for version 1.2.1 from a convenient mirror at: + for version 1.2.3 from a convenient mirror at: http://www.gzip.org/zlib/ - Unpack into dist\zlib-1.2.1. + Unpack into dist\zlib-1.2.3. A custom pre-link step in the zlib project settings should manage to - build zlib-1.2.1\zlib.lib by magic before zlib.pyd (or zlib_d.pyd) is + build zlib-1.2.3\zlib.lib by magic before zlib.pyd (or zlib_d.pyd) is linked in PCbuild\. However, the zlib project is not smart enough to remove anything under - zlib-1.2.1\ when you do a clean, so if you want to rebuild zlib.lib - you need to clean up zlib-1.2.1\ by hand. + zlib-1.2.3\ when you do a clean, so if you want to rebuild zlib.lib + you need to clean up zlib-1.2.3\ by hand. bz2 Python wrapper for the libbz2 compression library. Homepage Index: zlib.vcproj =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/zlib.vcproj,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- zlib.vcproj 20 Jul 2004 14:37:48 -0000 1.6 +++ zlib.vcproj 26 Jul 2005 02:29:21 -0000 1.7 @@ -21,7 +21,7 @@ Update of /cvsroot/python/python/dist/src/PCbuild In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5036/dist/src/PCbuild Modified Files: Tag: release24-maint readme.txt zlib.vcproj Log Message: Upgrade Windows build to zlib 1.2.3 (a security fix) Index: readme.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/readme.txt,v retrieving revision 1.58 retrieving revision 1.58.2.1 diff -u -d -r1.58 -r1.58.2.1 --- readme.txt 31 Aug 2004 16:22:09 -0000 1.58 +++ readme.txt 26 Jul 2005 02:35:39 -0000 1.58.2.1 @@ -126,15 +126,15 @@ zlib Python wrapper for the zlib compression library. Get the source code - for version 1.2.1 from a convenient mirror at: + for version 1.2.3 from a convenient mirror at: http://www.gzip.org/zlib/ - Unpack into dist\zlib-1.2.1. + Unpack into dist\zlib-1.2.3. A custom pre-link step in the zlib project settings should manage to - build zlib-1.2.1\zlib.lib by magic before zlib.pyd (or zlib_d.pyd) is + build zlib-1.2.3\zlib.lib by magic before zlib.pyd (or zlib_d.pyd) is linked in PCbuild\. However, the zlib project is not smart enough to remove anything under - zlib-1.2.1\ when you do a clean, so if you want to rebuild zlib.lib - you need to clean up zlib-1.2.1\ by hand. + zlib-1.2.3\ when you do a clean, so if you want to rebuild zlib.lib + you need to clean up zlib-1.2.3\ by hand. bz2 Python wrapper for the libbz2 compression library. Homepage Index: zlib.vcproj =================================================================== RCS file: /cvsroot/python/python/dist/src/PCbuild/zlib.vcproj,v retrieving revision 1.6 retrieving revision 1.6.4.1 diff -u -d -r1.6 -r1.6.4.1 --- zlib.vcproj 20 Jul 2004 14:37:48 -0000 1.6 +++ zlib.vcproj 26 Jul 2005 02:35:39 -0000 1.6.4.1 @@ -21,7 +21,7 @@ Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5036/dist/src/Misc Modified Files: Tag: release24-maint NEWS Log Message: Upgrade Windows build to zlib 1.2.3 (a security fix) Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.65 retrieving revision 1.1193.2.66 diff -u -d -r1.1193.2.65 -r1.1193.2.66 --- NEWS 22 Jul 2005 18:40:01 -0000 1.1193.2.65 +++ NEWS 26 Jul 2005 02:35:38 -0000 1.1193.2.66 @@ -83,6 +83,14 @@ line ending. Remove the special handling of a "\r\n" that has been split between two lines. + +Build +----- + +- Upgrade Windows build to zlib 1.2.3 which eliminates a potential security + vulnerability in zlib 1.2.1 and 1.2.2. + + Documentation ------------- From gregorykjohnson at users.sourceforge.net Tue Jul 26 22:47:51 2005 From: gregorykjohnson at users.sourceforge.net (gregorykjohnson@users.sourceforge.net) Date: Tue, 26 Jul 2005 13:47:51 -0700 Subject: [Python-checkins] python/nondist/sandbox/mailbox mailbox.py, NONE, 1.1 test_mailbox.py, NONE, 1.1 docs.tex, NONE, 1.1 libmailbox.tex, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/mailbox In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3755 Modified Files: libmailbox.tex Added Files: mailbox.py test_mailbox.py docs.tex Log Message: Maildir, with tests. --- NEW FILE: mailbox.py --- #! /usr/bin/env python """Read/write support for Maildir, mbox, MH, Babyl, and MMDF mailboxes.""" import os import time import socket import errno import stat import copy import email import email.Message import email.Generator import rfc822 __all__ = [ 'open', 'Mailbox', 'Maildir', 'mbox', 'MH', 'Babyl', 'MMDF', 'Message', 'MaildirMessage', 'mboxMessage', 'MHMessage', 'BabylMessage', 'MMDFMessage' ] def open(path, format=None, factory=None): """Open a mailbox at the given path and return a Mailbox instance.""" class Mailbox: """A group of messages in a particular place.""" def __init__(self, path, factory=None): """Initialize a Mailbox instance.""" self._path = os.path.abspath(path) self._factory = factory def add(self, message): """Add message and return assigned key.""" raise NotImplementedError, "Method must be implemented by subclass" def remove(self, key): """Remove the keyed message; raise KeyError if it doesn't exist.""" raise NotImplementedError, "Method must be implemented by subclass" def __delitem__(self, key): self.remove(key) def discard(self, key): """If the keyed message exists, remove it.""" try: self.remove(key) except KeyError: pass def __setitem__(self, key, message): """Replace the keyed message; raise KeyError if it doesn't exist.""" raise NotImplementedError, "Method must be implemented by subclass" def get(self, key, default=None): """Return the keyed message, or default if it doesn't exist.""" try: return self.__getitem__(key) except KeyError: return default def __getitem__(self, key): """Return the keyed message; raise KeyError if it doesn't exist.""" if self._factory is None: return self.get_message(key) else: return self._factory(self.get_file(key)) def get_message(self, key): """Return a Message representation or raise a KeyError.""" raise NotImplementedError, "Method must be implemented by subclass" def get_string(self, key): """Return a string representation or raise a KeyError.""" raise NotImplementedError, "Method must be implemented by subclass" def get_file(self, key): """Return a file-like representation or raise a KeyError.""" raise NotImplementedError, "Method must be implemented by subclass" def iterkeys(self): """Return an iterator over keys.""" raise NotImplementedError, "Method must be implemented by subclass" def keys(self): """Return a list of keys.""" return list(self.iterkeys()) def itervalues(self): """Return an iterator over all messages.""" for key in self.iterkeys(): try: value = self[key] except KeyError: continue yield value def __iter__(self): return self.itervalues() def values(self): """Return a list of messages. Memory intensive.""" return list(self.itervalues()) def iteritems(self): """Return an iterator over (key, message) tuples.""" for key in self.iterkeys(): try: value = self[key] except KeyError: continue yield (key, value) def items(self): """Return a list of (key, message) tuples. Memory intensive.""" return list(self.iteritems()) def has_key(self, key): """Return True if the keyed message exists, False otherwise.""" raise NotImplementedError, "Method must be implemented by subclass" def __contains__(self, key): return self.has_key(key) def __len__(self): """Return a count of messages in the mailbox.""" raise NotImplementedError, "Method must be implemented by subclass" def clear(self): """Delete all messages.""" for key in self.iterkeys(): self.discard(key) def pop(self, key, default=None): """Delete the keyed message and return it, or default.""" try: result = self[key] except KeyError: return default self.discard(key) return result def popitem(self): """Delete an arbitrary (key, message) pair and return it.""" for key in self.iterkeys(): return (key, self.pop(key)) # This is only run once. else: raise KeyError, "No messages in mailbox" def update(self, arg=None): """Change the messages that correspond to certain keys.""" if hasattr(arg, 'items'): source = arg.items() else: source = arg bad_key = False for key, message in source: try: self[key] = message except KeyError: bad_key = True if bad_key: raise KeyError, "No message with key(s)" def flush(self): """Write any pending changes to disk.""" raise NotImplementedError, "Method must be implemented by subclass" def _dump_message(self, message, target): """Dump message contents to target file.""" if isinstance(message, email.Message.Message): generator = email.Generator.Generator(target, False, 0) generator.flatten(message) elif isinstance(message, str): target.write(message) elif hasattr(message, 'read'): while True: buffer = message.read(4096) # Buffer size is arbitrary. if buffer == "": break target.write(buffer) else: raise TypeError, "Invalid message type" class Maildir(Mailbox): """A qmail-style Maildir mailbox.""" def __init__(self, dirname, factory=rfc822.Message): """Initialize a Maildir instance.""" Mailbox.__init__(self, dirname, factory) if not os.path.exists(self._path): os.mkdir(self._path, 0700) os.mkdir(os.path.join(self._path, "tmp"), 0700) os.mkdir(os.path.join(self._path, "new"), 0700) os.mkdir(os.path.join(self._path, "cur"), 0700) self._toc = {} def add(self, message): """Add message and return assigned key.""" tmp_file = self._create_tmp() try: self._dump_message(message, tmp_file) finally: tmp_file.close() if isinstance(message, MaildirMessage): subdir = message.get_subdir() suffix = ':' + message.get_info() if suffix == ':': suffix = '' else: subdir = 'new' suffix = '' uniq = os.path.basename(tmp_file.name).split(':')[0] dest = os.path.join(self._path, subdir, uniq + suffix) os.rename(tmp_file.name, dest) return uniq def remove(self, key): """Remove the keyed message; raise KeyError if it doesn't exist.""" os.remove(os.path.join(self._path, self._lookup(key))) def discard(self, key): """If the keyed message exists, remove it.""" # This overrides an inapplicable implementation in the superclass. try: self.remove(key) except KeyError: pass except OSError, e: if errno == errno.ENOENT: pass else: raise def __setitem__(self, key, message): """Replace the keyed message; raise KeyError if it doesn't exist.""" old_subpath = self._lookup(key) temp_key = self.add(message) temp_subpath = self._lookup(temp_key) if isinstance(message, MaildirMessage): # temp's subdir and suffix were specified by message. dominant_subpath = temp_subpath else: # temp's subdir and suffix were defaults from add(). dominant_subpath = old_subpath subdir = os.path.split(dominant_subpath)[0] if dominant_subpath.find(':') != -1: suffix = ':' + dominant_subpath.split(':')[-1] else: suffix = '' self.discard(key) os.rename(os.path.join(self._path, temp_subpath), os.path.join(self._path, subdir, key + suffix)) def get_message(self, key): """Return a Message representation or raise a KeyError.""" subpath = self._lookup(key) f = file(os.path.join(self._path, subpath), 'r') try: msg = MaildirMessage(f) finally: f.close() subdir, name = os.path.split(subpath) if subdir == 'cur': msg.set_subdir('cur') if name.find(':') != -1: msg.set_info(name.split(':')[-1]) return msg def get_string(self, key): """Return a string representation or raise a KeyError.""" f = file(os.path.join(self._path, self._lookup(key)), 'r') try: return f.read() finally: f.close() def get_file(self, key): """Return a file-like representation or raise a KeyError.""" f = file(os.path.join(self._path, self._lookup(key)), 'r') return _ProxyFile(f) def iterkeys(self): """Return an iterator over keys.""" self._refresh() for key in self._toc: try: self._lookup(key) except KeyError: continue yield key def has_key(self, key): """Return True if the keyed message exists, False otherwise.""" self._refresh() return key in self._toc def __len__(self): """Return a count of messages in the mailbox.""" self._refresh() return len(self._toc) def flush(self): """Write any pending changes to disk.""" return # Maildir changes are always written immediately. def list_folders(self): """Return a list of folder names.""" result = [] for entry in os.listdir(self._path): if len(entry) > 1 and entry[0] == '.' and \ os.path.isdir(os.path.join(self._path, entry)): result.append(entry[1:]) return result def open_folder(self, name): """Return a Maildir for the named folder, creating it if necessary.""" path = os.path.join(self._path, '.' + name) maildirfolder_path = os.path.join(path, 'maildirfolder') result = Maildir(path) if not os.path.exists(maildirfolder_path): os.mknod(maildirfolder_path, 0600 | stat.S_IFREG) return result def remove_folder(self, name): """Delete the named folder, which must be empty.""" path = os.path.join(self._path, '.' + name) for entry in os.listdir(os.path.join(path, 'new')) + \ os.listdir(os.path.join(path, 'cur')): if len(entry) < 1 or entry[0] != '.': raise IOError, "Folder '%s' contains message" % name for entry in os.listdir(path): if entry != 'new' and entry != 'cur' and entry != 'tmp' and \ os.path.isdir(os.path.join(path, entry)): raise IOError, "Folder '%s' contains subdirectory '%s'" % \ (name, entry) for root, dirs, files in os.walk(path, topdown=False): for entry in files: os.remove(os.path.join(root, entry)) for entry in dirs: os.rmdir(os.path.join(root, entry)) os.rmdir(path) def clean(self): """Delete old files in "tmp".""" now = time.time() for entry in os.listdir(os.path.join(self._path, 'tmp')): path = os.path.join(self._path, 'tmp', entry) if now - os.stat(path).st_atime > 129600: # 60 * 60 * 36 os.remove(path) _count = 1 # This is used to generate unique file names. def _create_tmp(self): """Create a file in the tmp subdirectory and open and return it.""" now = time.time() hostname = socket.gethostname() if '/' in hostname: hostname = hostname.replace('/', r'\057') if ':' in hostname: hostname = hostname.replace(':', r'\072') uniq = "%s.M%sP%sQ%s.%s" % (int(now), int(now % 1 * 1e6), os.getpid(), self._count, hostname) path = os.path.join(self._path, 'tmp', uniq) try: os.stat(path) except OSError, e: if e.errno == errno.ENOENT: self._count += 1 return file(path, 'w+') else: raise else: raise Error, "Name clash prevented file creation: '%s'" % path def _refresh(self): """Update table of contents mapping.""" self._toc = {} for subdir in ('new', 'cur'): for entry in os.listdir(os.path.join(self._path, subdir)): uniq = entry.split(':')[0] self._toc[uniq] = os.path.join(subdir, entry) def _lookup(self, key): """Use TOC to return subpath for given key, or raise a KeyError.""" try: if os.path.exists(os.path.join(self._path, self._toc[key])): return self._toc[key] except KeyError: pass self._refresh() try: return self._toc[key] except KeyError: raise KeyError, "No message with key '%s'" % key class Message(email.Message.Message): """Message with mailbox-format-specific properties.""" def __init__(self, message=None): """Initialize a Message instance.""" if isinstance(message, email.Message.Message): self._become_message(copy.deepcopy(message)) elif isinstance(message, str): self._become_message(email.message_from_string(message)) elif hasattr(message, "read"): self._become_message(email.message_from_file(message)) elif message is None: email.Message.Message.__init__(self) else: raise TypeError, "Invalid message type" def _become_message(self, message): """Assume the non-format-specific state of message.""" for name in ('_headers', '_unixfrom', '_payload', '_charset', 'preamble', 'epilogue', 'defects', '_default_type'): self.__dict__[name] = message.__dict__[name] def _explain_to(self, message): """Copy format-specific state to message insofar as possible.""" if isinstance(message, Message): return # There's nothing format-specific to explain. else: raise TypeError, "Cannot convert to specified type" class MaildirMessage(Message): """Message with Maildir-specific properties.""" def __init__(self, message=None): """Initialize a MaildirMessage instance.""" Message.__init__(self, message) self._subdir = 'new' self._info = '' if isinstance(message, Message): message._explain_to(self) def get_subdir(self): """Return 'new' or 'cur'.""" return self._subdir def set_subdir(self, subdir): """Set subdir to 'new' or 'cur'.""" if subdir == 'new' or subdir == 'cur': self._subdir = subdir else: raise ValueError, "subdir must be 'new' or 'cur'" def get_flags(self): """Return as a string the flags that are set.""" if len(self._info) > 2 and self._info[:2] == '2,': return self._info[2:] else: return "" def set_flags(self, flags): """Set the given flags and unset all others.""" if self.get_subdir() == 'new': self.set_subdir('cur') self._info = '2,' + ''.join(sorted(flags)) def add_flags(self, flags): """Set the given flags without changing others.""" self.set_flags(''.join(set(self.get_flags()) | set(flags))) def remove_flags(self, flags): """Unset the given string flags (if set) without changing other.""" if self.get_flags() != "": self.set_flags(''.join(set(self.get_flags()) - set(flags))) def get_info(self): """Get the message's "info" as a string.""" return self._info def set_info(self, info): """Set the message's "info" string.""" if self.get_subdir() == 'new': self.set_subdir('cur') if isinstance(info, str): self._info = info else: raise TypeError, "info must be a string" def _explain_to(self, message): """Copy Maildir-specific state to message insofar as possible.""" if isinstance(message, Message): return # XXX convert to other formats as needed else: raise TypeError, "Cannot convert to specified type" class _ProxyFile: """A read-only wrapper of a file.""" def __init__(self, f, pos=None): """Initialize a _ProxyFile.""" self._file = f if pos is None: self._pos = f.tell() else: self._pos = pos def read(self, size=None): """Read bytes.""" return self._read(size, self._file.read) def readline(self, size=None): """Read a line.""" return self._read(size, self._file.readline) def readlines(self, sizehint=None): """Read multiple lines.""" result = [] for line in self: result.append(line) if sizehint is not None: sizehint -= len(line) if sizehint <= 0: break return result def __iter__(self): """Iterate over lines.""" return iter(self.readline, "") def tell(self): """Return the position.""" return self._pos def seek(self, offset, whence=0): """Change position.""" if whence == 1: self._file.seek(self._pos) self._file.seek(offset, whence) self._pos = self._file.tell() def close(self): """Close the file.""" del self._file def _read(self, size, read_method): """Read size bytes using read_method.""" if size is None: size = -1 self._file.seek(self._pos) result = read_method(size) self._pos = self._file.tell() return result class _PartialFile(_ProxyFile): """A read-only wrapper of part of a file.""" def __init__(self, f, start=None, stop=None): """Initialize a _PartialFile.""" _ProxyFile.__init__(self, f, start) self._start = start self._stop = stop def tell(self): """Return the position with respect to start.""" return _ProxyFile.tell(self) - self._start def seek(self, offset, whence=0): """Change position, possibly with respect to start or stop.""" if whence == 0: self._pos = self._start whence = 1 elif whence == 2: self._pos = self._stop whence = 1 _ProxyFile.seek(self, offset, whence) def _read(self, size, read_method): """Read size bytes using read_method, honoring start and stop.""" remaining = self._stop - self._pos if remaining <= 0: return '' if size is None or size < 0 or size > remaining: size = remaining return _ProxyFile._read(self, size, read_method) class Error(Exception): """Raised for module-specific errors.""" --- NEW FILE: test_mailbox.py --- import os import time import stat import socket import email import email.Message import rfc822 import re import StringIO from test import test_support import unittest import mailbox class TestBase(unittest.TestCase): def _check_sample(self, msg): # Inspect a mailbox.Message representation of the sample message self.assert_(isinstance(msg, email.Message.Message)) [...985 lines suppressed...] "From":""""Gregory K. Johnson" """, "To":"gkj at gregorykjohnson.com", "Subject":"Sample message", "Mime-Version":"1.0", "Content-Type":"""multipart/mixed; boundary="NMuMz9nt05w80d4+\"""", "Content-Disposition":"inline", "User-Agent": "Mutt/1.5.9i" } _sample_payloads = ("This is a sample message.\n\n-- \nGregory K. Johnson\n", "H4sICM2D1UIAA3RleHQAC8nILFYAokSFktSKEoW0zJxUPa7wzJIMhZLyfIWczLzUYj0uAHTs\n3FYlAAAA\n") def test_main(): test_support.run_unittest(TestMaildir, TestMessage, TestMaildirMessage, TestMessageConversion, TestProxyFile, TestPartialFile) if __name__ == '__main__': test_main() --- NEW FILE: docs.tex --- % Compile using mkhowto, e.g.: % ../../../dist/src/Doc/tools/mkhowto --html docs.tex \documentclass{manual} \title{\module{mailbox} Module Documentation} \begin{document} \maketitle \tableofcontents \input{libmailbox} \end{document} Index: libmailbox.tex =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/libmailbox.tex,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- libmailbox.tex 9 Jul 2005 20:15:25 -0000 1.1 +++ libmailbox.tex 26 Jul 2005 20:47:48 -0000 1.2 @@ -41,48 +41,53 @@ \subsection{\class{Mailbox} objects} \label{mailbox-objects} +\begin{classdesc*}{Mailbox} +Represents a mailbox, which may be inspected and modified. +\end{classdesc*} + The \class{Mailbox} interface is dictionary-like, with small keys corresponding to messages. Keys are issued by the \class{Mailbox} instance with which they will be used and are only meaningful to that \class{Mailbox} -instance. (\strong{Implementation note:} \class{mbox}, \class{MH}, -\class{Babyl}, and \class{MMDF} instances use integers as keys, and -\class{Maildir} instances uses short strings.) A key continues to identify a -message even if the corresponding message is modified by replacing it with -another message. Because keys are issued by a \class{Mailbox} instance rather +instance. A key continues to identify a message even if the corresponding +message is modified, such as by replacing it with another message. Messages may +be added to a \class{Mailbox} instance using the set-like method +\method{add()}. Because keys are issued by a \class{Mailbox} instance rather than being chosen, the conventional method for adding an item to a mapping -(assigning a value to a new key) cannot be used. Instead, messages may be -added to a \class{Mailbox} instance using the set-like method \method{add()}. -For uniformity, \method{remove()} and \method{discard()} are also available. +(assigning a value to a new key) cannot be used. (\strong{Implementation note:} +\class{mbox}, \class{MH}, \class{Babyl}, and \class{MMDF} instances use +integers as keys, and \class{Maildir} instances use short strings.) -\class{Mailbox} semantics differ from dictionary semantics in important ways. -Each time a message is requested, a new message representation (typically a -\class{Message} instance) is generated based upon the current state of the -underlying message. Similarly, when a message representation is assigned into -a \class{Mailbox} instance's mapping, the message representation's contents -are copied into the mailbox. In neither case is a reference to the message -representation kept by the \class{Mailbox} instance. +\class{Mailbox} interface semantics differ from dictionary semantics in some +ways. Each time a message is requested, a new message representation (typically +a \class{Message} instance) is generated based upon the current state of the +underlying message. The \class{Mailbox} instance does not reuse this +representation or keep a reference to it. Similarly, when a message +representation is assigned into a \class{Mailbox} instance's mapping, the +message representation's contents are copied into the mailbox. In neither case +is a reference to the message representation kept by the \class{Mailbox} +instance. -Also unlike dictionaries, the default \class{Mailbox} iterator iterates over -message representations, not keys. Moreover, modification of a mailbox during -iteration is safe and well-defined. Messages added to the mailbox after an -iterator is created will not be seen by the iterator, and messages removed -from the mailbox before the iterator yields them will be silently skipped. All -three kinds of iterator---key, value, and item---have this behavior. +The default \class{Mailbox} iterator iterates over message representations, not +keys as dictionaries do. Moreover, modification of a mailbox during iteration +is safe and well-defined. Messages added to the mailbox after an iterator is +created will not be seen by the iterator. Messages removed from the mailbox +before the iterator yields them will be silently skipped, though using a key +from an iterator may result in a \exception{KeyError} exception if the +corresponding message is subsequently removed. -\class{Mailbox} itself is not intended to be instantiated. Rather, it is -intended to define an interface and to be inherited from by format-specific -subclasses. You may directly instantiate a subclass, or alternatively you may -use the module-level \function{open()} function to instantiate the appropriate -subclass. +\class{Mailbox} itself is intended to define an interface and to be inherited +from by format-specific subclasses but is not intended to be instantiated. +Instead, you may directly instantiate a subclass or use the module-level +\function{open()} function to do so. -\begin{funcdesc}{open}{path\optional{, format, factory}} +\begin{funcdesc}{open}{path\optional{, format\optional{, factory}}} Instantiate and return an instance of the appropriate \class{Mailbox} subclass for the mailbox at \var{path}. The mailbox is created if it does not already exist. If \var{format} is specified, it should be one of "Maildir", "mbox", "MH", "Babyl", or "MMDF" (case insensitive). If \var{format} is not specified, then -the format of the mailbox will be automatically detected. Automatic detection +the format of the mailbox is automatically detected. Automatic detection involves inspecting the mailbox at \var{path} if such a mailbox exists or if no such mailbox exists inspecting \var{path} itself and assuming Maildir format if \var{path} ends with the system's path separator (e.g., "/" or @@ -93,7 +98,7 @@ representation. If \var{factory} is not specified, \class{Message} instances are used to represent messages. -For historic reasons, some subclasses of \class{Mailbox} take instantiation +For historical reasons, some subclasses of \class{Mailbox} take instantiation arguments with different purposes, names, or default values. The \function{open()} function is intended to present a convenient, uniform interface for \class{Mailbox} instantiation while maintaining backward @@ -110,126 +115,101 @@ \class{email.Message.Message} instance, a string, or a file-like object. If \var{message} is an instance of the appropriate format-specific \class{Message} subclass (e.g., if it's an \class{mboxMessage} instance and -this is an \class{mbox} instance), its format-specific information will be -used. Otherwise, reasonable defaults for format-specific information will be -used. +this is an \class{mbox} instance), its format-specific information is used. +Otherwise, reasonable defaults for format-specific information are used. \end{methoddesc} \begin{methoddesc}[Mailbox]{remove}{key} -Delete the message corresponding to \var{key} from the mailbox. Raise a -\exception{KeyError} exception if no such message exists. +\methodline{__delitem__}{key} +\methodline{discard}{key} +Delete the message corresponding to \var{key} from the mailbox. -The behavior of \method{discard()} may be preferred to that of -\method{remove()} if the underlying mailbox format supports concurrent -modification by other processes, as is the case for Maildir. +If no such message exists, a \exception{KeyError} exception is raised if the +method was called as \method{remove()} or \method{__delitem__()} and no +exception is raised if the method was called as \method{discard()}. The +behavior of \method{discard()} may be preferred if the underlying mailbox +format supports concurrent modification by other processes. \end{methoddesc} -\begin{methoddesc}[Mailbox]{discard}{key} -Delete the message corresponding to \var{key} from the mailbox, or do nothing -if no such message exists. -\end{methoddesc} +\begin{methoddesc}[Mailbox]{__setitem__}{key, message} +Replace the message corresponding to \var{key} with the message represented by +\var{message}. Raise a \exception{KeyError} exception if no message already +corresponds to \var{key}. -\begin{methoddesc}[Mailbox]{iterkeys}{} -Return an iterator over all keys. +As with \method{add()}, parameter \var{message} may be a \class{Message} +instance, an \class{email.Message.Message} instance, a string, or a file-like +object. If \var{message} is an instance of the appropriate format-specific +\class{Message} subclass (e.g., if it's an \class{mboxMessage} instance and +this is an \class{mbox} instance), its format-specific information is used. +Otherwise, the format-specific information of the message that currently +corresponds to \var{key} is left unchanged. \end{methoddesc} -\begin{methoddesc}[Mailbox]{keys}{} -Return a list of all keys. +\begin{methoddesc}[Mailbox]{iterkeys}{} +\methodline{keys}{} +Return an iterator over all keys if called as \method{iterkeys()} or return a +list of keys if called as \method{keys()}. \end{methoddesc} \begin{methoddesc}[Mailbox]{itervalues}{} -Return an iterator over representations of all messages. The messages are -represented as \class{Message} instances unless a custom message factory was -specified when the \class{Mailbox} instance was initialized. -\end{methoddesc} - -\begin{methoddesc}[Mailbox]{values}{} -Return a list of representations of all messages. The messages are represented -as \class{Message} instances unless a custom message factory was specified -when the \class{Mailbox} instance was initialized. \warning{This may require a -large amount of memory.} +\methodline{__iter__}{} +\methodline{values}{} +Return an iterator over representations of all messages if called as +\method{itervalues()} or \method{__iter__()} or return a list of such +representations if called as \method{values()}. The messages are represented as +\class{Message} instances unless a custom message factory was specified when +the \class{Mailbox} instance was initialized. \note{The behavior of +\method{__iter__()} is unlike that of dictionaries, which iterate over keys.} \end{methoddesc} \begin{methoddesc}[Mailbox]{iteritems}{} +\methodline{items}{} Return an iterator over (\var{key}, \var{message}) pairs, where \var{key} is a -key and \var{message} is a message representation. The messages are -represented as \class{Message} instances unless a custom message factory was -specified when the \class{Mailbox} instance was initialized. -\end{methoddesc} - -\begin{methoddesc}[Mailbox]{items}{} -Return a list of (\var{key}, \var{message}) pairs, where \var{key} is a key -and \var{message} is a message representation. The messages are represented as -\class{Message} instances unless a custom message factory was specified when -the \class{Mailbox} instance was initialized. \warning{This may require a -large amount of memory.} +key and \var{message} is a message representation, if called as +\method{iteritems()} or return a list of such pairs if called as +\method{items()}. The messages are represented as \class{Message} instances +unless a custom message factory was specified when the \class{Mailbox} instance +was initialized. \end{methoddesc} \begin{methoddesc}[Mailbox]{get}{key\optional{, default=None}} -Return a representation of the message corresponding to \var{key}, or -\var{default} if no such message exists. The message is represented as a -\class{Message} instance unless a custom message factory was specified when -the \class{Mailbox} instance was initialized. +\methodline{__getitem__}{key} +Return a representation of the message corresponding to \var{key}. If no such +message exists, \var{default} is returned if the method was called as +\method{get()} and a \exception{KeyError} exception is raised if the method was +called as \method{__getitem__()}. The message is represented as a +\class{Message} instance unless a custom message factory was specified when the +\class{Mailbox} instance was initialized. \end{methoddesc} -\begin{methoddesc}[Mailbox]{get_message}{key\optional{, default=None}} +\begin{methoddesc}[Mailbox]{get_message}{key} Return a \class{Message} representation of the message corresponding to -\var{key}, or \var{default} if no such message exists. +\var{key}, or raise a \exception{KeyError} exception if no such message +exists. \end{methoddesc} -\begin{methoddesc}[Mailbox]{get_string}{key\optional{, default=None}} +\begin{methoddesc}[Mailbox]{get_string}{key} Return a string representation of the message corresponding to \var{key}, or -\var{default} if no such message exists. +raise a \exception{KeyError} exception if no such message exists. \end{methoddesc} -\begin{methoddesc}[Mailbox]{get_file}{key\optional{, default=None}} +\begin{methoddesc}[Mailbox]{get_file}{key} Return a file-like representation of the message corresponding to \var{key}, -or \var{default} if no such message exists. +or raise a \exception{KeyError} exception if no such message exists. This file +should be closed once it is no longer needed. \note{Unlike other representations of messages, file-like representations are not independent of the \class{Mailbox} instance that created them or of the -underlying mailbox. If the mailbox is modified, the file-like representation -may become unusable. More specific documentation is provided by each -subclass.} +underlying mailbox, although their exact behavior is mailbox-format dependent. +More specific documentation is provided by each subclass.} \end{methoddesc} \begin{methoddesc}[Mailbox]{has_key}{key} +\methodline{__contains__}{} Return \code{True} if \var{key} corresponds to a message, \code{False} otherwise. \end{methoddesc} -\begin{methoddesc}[Mailbox]{__iter__}{} -Synonymous with \method{itervalues()}. \note{This is unlike the default -iteration behavior of dictionaries.} -\end{methoddesc} - -\begin{methoddesc}[Mailbox]{__getitem__}{key} -Like \method{get()}, except raises a \exception{KeyError} exception if the -message corresponding to \var{key} does not exist. -\end{methoddesc} - -\begin{methoddesc}[Mailbox]{__setitem__}{key, message} -Replace the message corresponding to \var{key} with the message represented by -\var{message}. Raise a \exception{KeyError} exception if no message already -corresponds to the given key. - -As with \method{add()}, parameter \var{message} may be a \class{Message} -instance, an \class{email.Message.Message} instance, a string, or a file-like -object. If \var{message} is an instance of the appropriate format-specific -\class{Message} subclass (e.g., if it's an \class{mboxMessage} instance and -this is an \class{mbox} instance), its format-specific information will be -used. Otherwise, reasonable defaults for format-specific information will be -used. -\end{methoddesc} - -\begin{methoddesc}[Mailbox]{__delitem__}{key} -Synonymous with \method{remove()}. -\end{methoddesc} - -\begin{methoddesc}[Mailbox]{__contains__}{key} -Synonymous with \method{has_key()}. -\end{methoddesc} - \begin{methoddesc}[Mailbox]{__len__}{} Return a count of messages in the mailbox. \end{methoddesc} @@ -240,34 +220,125 @@ \begin{methoddesc}[Mailbox]{pop}{key\optional{, default}} Return a representation of the message corresponding to \var{key} and delete -the message. If no such message exists, return \var{default} if it was -supplied or if \var{default} was not supplied raise a \exception{KeyError} -exception. The message is represented as a \class{Message} instance unless a -custom message factory was specified when the \class{Mailbox} instance was -initialized. +the message. If no such message exists, return \var{default} if it was supplied +or else raise a \exception{KeyError} exception. The message is represented as a +\class{Message} instance unless a custom message factory was specified when the +\class{Mailbox} instance was initialized. \end{methoddesc} \begin{methoddesc}[Mailbox]{popitem}{} Return an arbitrary (\var{key}, \var{message}) pair, where \var{key} is a key and \var{message} is a message representation, and delete the corresponding -message from the mailbox. If the mailbox is empty, raise a -\exception{KeyError} exception. The message is represented as a -\class{Message} instance unless a custom message factory was specified when -the \class{Mailbox} instance was initialized. +message. If the mailbox is empty, raise a \exception{KeyError} exception. The +message is represented as a \class{Message} instance unless a custom message +factory was specified when the \class{Mailbox} instance was initialized. \end{methoddesc} \begin{methoddesc}[Mailbox]{update}{arg} -If \var{arg} is a mailbox-like \var{key}-to-\var{message} mapping or an -iterable of (\var{key}, \var{message}) pairs, update the mailbox so that, for +Parameter \var{arg} should be a \var{key}-to-\var{message} mapping or an +iterable of (\var{key}, \var{message}) pairs. Updates the mailbox so that, for each given \var{key} and \var{message}, the message corresponding to \var{key} -is set to \var{message} as if by using \method{__setitem__()}. \note{Keyword -arguments are not supported, unlike with dictionaries.} +is set to \var{message} as if by using \method{__setitem__()}. Each \var{key} +must already correspond to a message in the mailbox or a \exception{KeyError} +exception will be raised. \note{Unlike with dictionaries, keyword arguments +are not supported.} +\end{methoddesc} + +\begin{methoddesc}[Mailbox]{flush}{} +Write any pending changes to the filesystem. For some \class{Mailbox} +subclasses, this is done automatically and calling \method{flush()} has no +effect. More specific documentation is provided by each subclass. \end{methoddesc} \subsubsection{\class{Maildir}} \label{mailbox-maildir} +\begin{classdesc}{Maildir}{dirname\optional{, factory}} +A subclass of \class{Mailbox} for mailboxes in Maildir format. Parameter +\var{dirname} is the path to the mailbox. Parameter \var{factory} has the same +meaning as with the module-level \method{open()} function. For historical +reasons, \var{factory} defaults to \class{rfc822.Message}. +\end{classdesc} + +Maildir is a directory-based mailbox format invented for the qmail MTA and now +widely supported by other programs. Messages in a Maildir mailbox are stored +in separate files within a shared directory structure. This structure allows +Maildir mailboxes to be accessed and modified by multiple unrelated programs +without data corruption, so file locking is unnecessary. + +Folders, as introduced by the Courier MTA, are supported. Each folder is +itself a Maildir mailbox and is represented as a \class{Maildir} instance. Any +subdirectory of the main Maildir directory is considered a folder if +\character{.} is the first character in its name. Folder names are represented +without the leading dot. For example, "Sent.2005.07" would be the name of a +folder implemented with a directory called ".Sent.2005.07" on the filesystem. + +\class{Maildir} instances have all of the methods of \class{Mailbox} in +addition to the following: + +\begin{methoddesc}[Maildir]{list_folders}{} +Return a list of the names of all folders. If there are no folders, the empty +list is returned. +\end{methoddesc} + +\begin{methoddesc}[Maildir]{open_folder}{name} +Return a \class{Maildir} instance representing the folder whose name is +\var{name}. The folder will be created if it does not exist. +\end{methoddesc} + +\begin{methoddesc}[Maildir]{remove_folder}{name} +Delete the folder whose name is \var{name}. If the folder contains any +messages, an \exception{IOError} exception will be raised and the folder will +not be deleted. +\end{methoddesc} + +\begin{methoddesc}[Maildir]{clean}{} +Delete temporary files from the mailbox that have not been accessed in the +last 36 hours. The Maildir specification says that mail-reading programs +should do this occassionally. +\end{methoddesc} + +\warning{Three \class{Maildir} methods---\method{add()}, +\method{__setitem__()}, and \method{update()}---generate unique file names +based upon the current process ID. When using multiple threads, undetected +clashes may occur and cause corruption of the mailbox unless threads are +coordinated to avoid using these methods to manipulate the same mailbox +simultaneously.} + +Some \class{Mailbox} methods implemented by \class{Maildir} deserve special +remarks: + +\begin{methoddesc}[Maildir]{add}{message} +\methodline[Maildir]{__setitem__}{key, message} +\methodline[Maildir]{update}{arg} +\warning{These methods generate unique file names based upon the current +process ID. When using multiple threads, undetected name clashes may occur and +cause corruption of the mailbox unless threads are coordinated to avoid using +these methods to manipulate the same mailbox simultaneously.} +\end{methoddesc} + +\begin{methoddesc}[Maildir]{flush}{} +All changes to Maildir mailboxes are immediately applied. This method does +nothing. +\end{methoddesc} + +\begin{methoddesc}[Maildir]{get_file}{key} +Depending upon the host platform, it may not be possible to use a +\class{Maildir} instance to modify or remove the underlying message while the +returned file remains open. +\end{methoddesc} + +\begin{seealso} + \seelink{http://www.qmail.org/man/man5/maildir.html}{maildir man page from + qmail}{The original specification of the format.} + \seelink{http://cr.yp.to/proto/maildir.html}{Using maildir format}{Notes + on Maildir by it's inventor. Includes an updated name-creation scheme and + details on "info" semantics.} + \seelink{http://www.courier-mta.org/?maildir.html}{maildir man page from + Courier}{Another specification of the format. Describes a common extension + for supporting folders.} +\end{seealso} \subsubsection{\class{mbox}} \label{mailbox-mbox} @@ -288,10 +359,132 @@ \subsection{\class{Message} objects} \label{mailbox-message-objects} +The \class{Message} class is an extension of a class of the same name from the +\module{email.Message} module. In addition, subclasses of \class{Message} +support mailbox-format-specific state and behavior. + +\begin{classdesc}{Message}{\optional{message}} +Represents a message with mailbox-format-specific properties. + +If \var{message} is omitted, the new instance is created in a default, empty +state. If \var{message} is an \class{email.Message.Message} instance, its +contents are copied, converting any format-specific information insofar as +possible if \var{message} is a \class{Message} instance. If \var{message} is a +string or a file, it should contain an \rfc{2822}-compliant message, which is +read and parsed. +\end{classdesc} + +The format-specific state and behaviors offered by subclasses vary, but in +general it is only the properties that are not specific to a particular +mailbox that are supported (although presumably the properties are specific to +a particular mailbox format). For example, file offsets for single-file mailbox +formats and file names for directory-based mailbox formats are not retained, +but state such as whether a message has been read or marked as important by the +user is. + +In some situations, the time and memory overhead involved in generating +\class{Message} representations might not not justified. For such situations, +\class{Mailbox} instances also offer string and file-like representations, and +a custom message factory may be specified when a \class{Mailbox} instance is +initialized. There is no requirement to use the \class{Message} class to +represent messages from a mailbox. + +All of the \class{email.Message.Message} class's methods and members are +supported by \class{Message}, and subclasses of \class{Message} provide many +additional format-specific methods. Some functionality supported by all +\class{Message} subclasses is accessible via the following methods: + +XXX \subsubsection{\class{MaildirMessage}} \label{mailbox-maildirmessage} +\begin{classdesc}{MaildirMessage}{\optional{message}} +Represents a message with Maildir-specific behaviors. Parameter \var{message} +has the same meaning as with the \class{Message} constructor. +\end{classdesc} + +Maildir messages are stored in individual files, in either the \file{new} or +the \file{cur} subdirectory of the Maildir. Typically, messages are delivered +to the \file{new} subdirectory and then moved to the \file{cur} subdirectory +as soon as the user's mail reading application detects them. Each message in +\file{cur} has an "info" section added to its file name to store information +about its state. The "info" section may take one of two forms: it may contain +a standardized list of flags or it may contain so-called experimental +information. + +Standard flags for Maildir messages are as follows: + +\begin{tableiii}{l|l|l}{textrm}{Flag}{Meaning}{Explanation} +\lineiii{D}{Draft}{Under composition} +\lineiii{F}{Flagged}{Marked by the user as important} +\lineiii{P}{Passed}{Forwarded, resent, or bounced by the user} +\lineiii{R}{Replied}{Responded to} +\lineiii{S}{Seen}{Read by the user} +\lineiii{T}{Trashed}{Marked for subsequent deletion} +\end{tableiii} + +\class{MaildirMessage} instances offer the following methods: + +\begin{methoddesc}[MaildirMessage]{get_subdir}{} +Return either "new" (if the message should be stored in the \file{new} +subdirectory) or "cur" (if the message should be stored in the \file{cur} +subdirectory). \note{A Maildir message typically moves from \file{new} to +\file{cur} when an MUA first detects it, but most MUAs refer to a message as +new if it is unseen, i.e., if \code{"S" in get_flags()} is \code{False}.} +\end{methoddesc} + +\begin{methoddesc}[MaildirMessage]{set_subdir}{subdir} +Set the subdirectory the message should be stored in. Parameter \var{subdir} +must be either "new" or "cur". +\end{methoddesc} + +\begin{methoddesc}[MaildirMessage]{get_flags}{} +Return a string specifying the flags that are currently set. If the message +complies with the standard Maildir format, the result is the concatenation in +alphabetical order of zero or one occurrence of each of \character{D}, +\character{F}, \character{P}, \character{R}, \character{S}, and \character{T}. +The empty string is returned if no flags are set, if the message is new, or if +"info" contains experimental semantics. +\end{methoddesc} + +\begin{methoddesc}[MaildirMessage]{set_flags}{flags} +Set the flags specified by \var{flags} and unset all others. Parameter +\var{flags} should be the concatenation in any order of zero or more +occurrences of each of \character{D}, \character{F}, \character{P}, +\character{R}, \character{S}, and \character{T}. If the message is new, it +is made non-new. The current "info" is overwritten whether or not it contains +experimental information instead of flags. +\end{methoddesc} + +\begin{methoddesc}[MaildirMessage]{add_flags}{flags} +Set the flags specified by \var{flags} (if they are not set), and don't change +other flags. Parameter \var{flags} should be the concatenation in any order of +zero or more occurrences of each of \character{D}, \character{F}, +\character{P}, \character{R}, \character{S}, and \character{T}. If the message +is new, it is made non-new. If "info" contains experimental information rather +than flags, the "info" will be overwritten. +\end{methoddesc} + +\begin{methoddesc}[MaildirMessage]{remove_flags}{flags} +Unset the flags specified by \var{flags} (if they are set), and don't change +other flags. Parameter \var{flags} should be the concatenation in any order of +zero or more occurrences of each of \character{D}, \character{F}, +\character{P}, \character{R}, \character{S}, and \character{T}. If the message +is new, it remains so. If "info" contains experimental information rather than +flags, the current "info" is not modified. +\end{methoddesc} + +\begin{methoddesc}[MaildirMessage]{get_info}{} +Return a string containing the "info" for a message. This is useful for +accessing and modifying "info" that is experimental (i.e., not a list of +flags). +\end{methoddesc} + +\begin{methoddesc}[MaildirMessage]{set_info}{info} +Set "info" to \var{info}, which should be a string. If the message is new, it +is made non-new. +\end{methoddesc} \subsubsection{\class{mboxMessage}} \label{mailbox-mboxmessage} From gvanrossum at users.sourceforge.net Wed Jul 27 01:57:30 2005 From: gvanrossum at users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Tue, 26 Jul 2005 16:57:30 -0700 Subject: [Python-checkins] python/dist/src/Lib/lib-tk Tkinter.py, 1.182, 1.183 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/lib-tk In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17940 Modified Files: Tkinter.py Log Message: Fix a problem in Tkinter introduced by SF patch #869468 (checked in as 1.179): delete bogus __hasattr__ and __delattr__ methods on class Tk that were breaking Tkdnd. Index: Tkinter.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/lib-tk/Tkinter.py,v retrieving revision 1.182 retrieving revision 1.183 diff -u -d -r1.182 -r1.183 --- Tkinter.py 1 Mar 2005 08:09:27 -0000 1.182 +++ Tkinter.py 26 Jul 2005 23:57:27 -0000 1.183 @@ -1652,12 +1652,6 @@ def __getattr__(self, attr): "Delegate attribute access to the interpreter object" return getattr(self.tk, attr) - def __hasattr__(self, attr): - "Delegate attribute access to the interpreter object" - return hasattr(self.tk, attr) - def __delattr__(self, attr): - "Delegate attribute access to the interpreter object" - return delattr(self.tk, attr) # Ideally, the classes Pack, Place and Grid disappear, the # pack/place/grid methods are defined on the Widget class, and From gvanrossum at users.sourceforge.net Wed Jul 27 01:57:48 2005 From: gvanrossum at users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Tue, 26 Jul 2005 16:57:48 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1323,1.1324 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18021 Modified Files: NEWS Log Message: Fix a problem in Tkinter introduced by SF patch #869468 (checked in as 1.179): delete bogus __hasattr__ and __delattr__ methods on class Tk that were breaking Tkdnd. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1323 retrieving revision 1.1324 diff -u -d -r1.1323 -r1.1324 --- NEWS 26 Jul 2005 02:29:20 -0000 1.1323 +++ NEWS 26 Jul 2005 23:57:46 -0000 1.1324 @@ -12,6 +12,10 @@ Core and builtins ----------------- +- Fix a problem in Tkinter introduced by SF patch #869468: delete bogus + __hasattr__ and __delattr__ methods on class Tk that were breaking + Tkdnd. + - SF bug #1238681: freed pointer is used in longobject.c:long_pow(). - SF bug #1229429: PyObject_CallMethod failed to decrement some From gvanrossum at users.sourceforge.net Wed Jul 27 01:59:40 2005 From: gvanrossum at users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Tue, 26 Jul 2005 16:59:40 -0700 Subject: [Python-checkins] python/dist/src/Lib/lib-tk Tkinter.py, 1.181.2.1, 1.181.2.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/lib-tk In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18345 Modified Files: Tag: release24-maint Tkinter.py Log Message: (Backport) Fix a problem in Tkinter introduced by SF patch #869468 (checked in as 1.179): delete bogus __hasattr__ and __delattr__ methods on class Tk that were breaking Tkdnd. Index: Tkinter.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/lib-tk/Tkinter.py,v retrieving revision 1.181.2.1 retrieving revision 1.181.2.2 diff -u -d -r1.181.2.1 -r1.181.2.2 --- Tkinter.py 1 Mar 2005 08:10:49 -0000 1.181.2.1 +++ Tkinter.py 26 Jul 2005 23:59:38 -0000 1.181.2.2 @@ -1652,12 +1652,6 @@ def __getattr__(self, attr): "Delegate attribute access to the interpreter object" return getattr(self.tk, attr) - def __hasattr__(self, attr): - "Delegate attribute access to the interpreter object" - return hasattr(self.tk, attr) - def __delattr__(self, attr): - "Delegate attribute access to the interpreter object" - return delattr(self.tk, attr) # Ideally, the classes Pack, Place and Grid disappear, the # pack/place/grid methods are defined on the Widget class, and From gvanrossum at users.sourceforge.net Wed Jul 27 02:00:01 2005 From: gvanrossum at users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Tue, 26 Jul 2005 17:00:01 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS, 1.1193.2.66, 1.1193.2.67 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18428 Modified Files: Tag: release24-maint NEWS Log Message: (Backport) Fix a problem in Tkinter introduced by SF patch #869468 (checked in as 1.179): delete bogus __hasattr__ and __delattr__ methods on class Tk that were breaking Tkdnd. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1193.2.66 retrieving revision 1.1193.2.67 diff -u -d -r1.1193.2.66 -r1.1193.2.67 --- NEWS 26 Jul 2005 02:35:38 -0000 1.1193.2.66 +++ NEWS 26 Jul 2005 23:59:58 -0000 1.1193.2.67 @@ -53,6 +53,10 @@ Library ------- +- Fix a problem in Tkinter introduced by SF patch #869468: delete bogus + __hasattr__ and __delattr__ methods on class Tk that were breaking + Tkdnd. + - Bug #1015140: disambiguated the term "article id" in nntplib docs and docstrings to either "article number" or "message id". From gvanrossum at users.sourceforge.net Wed Jul 27 02:00:52 2005 From: gvanrossum at users.sourceforge.net (gvanrossum@users.sourceforge.net) Date: Tue, 26 Jul 2005 17:00:52 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1324,1.1325 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18697 Modified Files: NEWS Log Message: Ouch, move that comment to the right place. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1324 retrieving revision 1.1325 diff -u -d -r1.1324 -r1.1325 --- NEWS 26 Jul 2005 23:57:46 -0000 1.1324 +++ NEWS 27 Jul 2005 00:00:44 -0000 1.1325 @@ -12,10 +12,6 @@ Core and builtins ----------------- -- Fix a problem in Tkinter introduced by SF patch #869468: delete bogus - __hasattr__ and __delattr__ methods on class Tk that were breaking - Tkdnd. - - SF bug #1238681: freed pointer is used in longobject.c:long_pow(). - SF bug #1229429: PyObject_CallMethod failed to decrement some @@ -174,6 +170,10 @@ Library ------- +- Fix a problem in Tkinter introduced by SF patch #869468: delete bogus + __hasattr__ and __delattr__ methods on class Tk that were breaking + Tkdnd. + - Bug #1015140: disambiguated the term "article id" in nntplib docs and docstrings to either "article number" or "message id". From rhettinger at users.sourceforge.net Wed Jul 27 19:59:06 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Wed, 27 Jul 2005 10:59:06 -0700 Subject: [Python-checkins] python/dist/src/Misc developers.txt,1.16,1.17 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22821 Modified Files: developers.txt Log Message: Update permissions for Johannes Gijsbers. Index: developers.txt =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/developers.txt,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- developers.txt 14 Jul 2005 17:34:00 -0000 1.16 +++ developers.txt 27 Jul 2005 17:59:03 -0000 1.17 @@ -50,6 +50,8 @@ Permissions Dropped on Request ------------------------------ +- Johannes Gijsbers sent a drop request. 27 July 2005 RDH + - Flovis Bruynooghe sent a drop request. 14 July 2005 RDH - Paul Prescod sent a drop request. 30 Apr 2005 RDH From mwh at users.sourceforge.net Wed Jul 27 22:24:42 2005 From: mwh at users.sourceforge.net (mwh@users.sourceforge.net) Date: Wed, 27 Jul 2005 13:24:42 -0700 Subject: [Python-checkins] python/dist/src/Modules fcntlmodule.c,2.43,2.44 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29673/Modules Modified Files: fcntlmodule.c Log Message: This is barry-scott's patch: [ 1231069 ] ioctl has problem with -ive request codes by using the 'I' not the 'i' format code to PyArg_ParseTuple(). Backport candidate? Maybe... Index: fcntlmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/fcntlmodule.c,v retrieving revision 2.43 retrieving revision 2.44 diff -u -d -r2.43 -r2.44 --- fcntlmodule.c 30 Nov 2004 14:31:54 -0000 2.43 +++ fcntlmodule.c 27 Jul 2005 20:24:30 -0000 2.44 @@ -102,7 +102,7 @@ int mutate_arg = 1; char buf[1024]; - if (PyArg_ParseTuple(args, "O&iw#|i:ioctl", + if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl", conv_descriptor, &fd, &code, &str, &len, &mutate_arg)) { char *arg; @@ -151,7 +151,7 @@ } PyErr_Clear(); - if (PyArg_ParseTuple(args, "O&is#:ioctl", + if (PyArg_ParseTuple(args, "O&Is#:ioctl", conv_descriptor, &fd, &code, &str, &len)) { if (len > sizeof buf) { PyErr_SetString(PyExc_ValueError, @@ -172,7 +172,7 @@ PyErr_Clear(); arg = 0; if (!PyArg_ParseTuple(args, - "O&i|i;ioctl requires a file or file descriptor," + "O&I|i;ioctl requires a file or file descriptor," " an integer and optionally a integer or buffer argument", conv_descriptor, &fd, &code, &arg)) { return NULL; From mwh at users.sourceforge.net Wed Jul 27 22:24:44 2005 From: mwh at users.sourceforge.net (mwh@users.sourceforge.net) Date: Wed, 27 Jul 2005 13:24:44 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1325,1.1326 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv29673/Misc Modified Files: NEWS Log Message: This is barry-scott's patch: [ 1231069 ] ioctl has problem with -ive request codes by using the 'I' not the 'i' format code to PyArg_ParseTuple(). Backport candidate? Maybe... Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1325 retrieving revision 1.1326 diff -u -d -r1.1325 -r1.1326 --- NEWS 27 Jul 2005 00:00:44 -0000 1.1325 +++ NEWS 27 Jul 2005 20:24:40 -0000 1.1326 @@ -117,6 +117,10 @@ Extension Modules ----------------- +- Patch #1231069: The fcntl.ioctl function now uses the 'I' code for + the request code argument, which results in more C-like behaviour + for large or negative values. + - Bug #1234979: For the argument of thread.Lock.acquire, the Windows implemented treated all integer values except 1 as false. From rhettinger at users.sourceforge.net Thu Jul 28 01:38:43 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Wed, 27 Jul 2005 16:38:43 -0700 Subject: [Python-checkins] python/nondist/sandbox/set setobject.c,1.1,1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12069 Modified Files: setobject.c Log Message: Restore original intersection_update logic. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- setobject.c 22 Jul 2005 15:32:29 -0000 1.1 +++ setobject.c 27 Jul 2005 23:38:40 -0000 1.2 @@ -1009,41 +1009,53 @@ \n\ (i.e. all elements that are in both sets.)"); + +static void +set_swap_bodys(PySetObject *a, PySetObject *b) +{ + int t; + PySetEntry *u; + PySetEntry *(*f)(PySetObject *mp, PyObject *key, long hash); + PySetEntry tab[PySet_MINSIZE]; + long h; + + t = a->ma_fill; a->ma_fill = b->ma_fill; b->ma_fill = t; + t = a->ma_used; a->ma_used = b->ma_used; b->ma_used = t; + t = a->ma_mask; a->ma_mask = b->ma_mask; b->ma_mask = t; + + u = a->ma_table; + if (a->ma_table == a->ma_smalltable) + u = b->ma_smalltable; + a->ma_table = b->ma_table; + if (b->ma_table == b->ma_smalltable) + a->ma_table = a->ma_smalltable; + b->ma_table = u; + + f = a->ma_lookup; a->ma_lookup = b->ma_lookup; b->ma_lookup = f; + + if (a->ma_table == a->ma_smalltable || b->ma_table == b->ma_smalltable) { + memcpy(tab, a->ma_smalltable, sizeof(tab)); + memcpy(a->ma_smalltable, b->ma_smalltable, sizeof(tab)); + memcpy(b->ma_smalltable, tab, sizeof(tab)); + } + + h = a->hash; a->hash = b->hash; b->hash = h; +} + static PyObject *set_clear(PySetObject *so); /// XXX remove forward declaration static int set_tp_clear(PySetObject *so); /// XXX remove forward declaration static PyObject * set_intersection_update(PySetObject *so, PyObject *other) { -/* // Hmm, this made the timings slower - PyObject *tmp, *key; - int pos = 0; + PyObject *tmp; tmp = set_intersection(so, other); if (tmp == NULL) return NULL; - - while (set_next_internal(so, &pos, &key)) { - if (!set_contains_internal((PySetObject *)tmp, key)) { - if (set_remove_internal(so, key) == -1) { - Py_DECREF(tmp); - return NULL; - } - } - } + set_swap_bodys(so, (PySetObject *)tmp); Py_DECREF(tmp); Py_RETURN_NONE; -*/ - - PyObject *tmp, *rv; - - tmp = set_intersection(so, other); - if (tmp == NULL) - return NULL; - set_tp_clear(so); - rv = set_update(so, tmp); - Py_DECREF(tmp); - return rv; } PyDoc_STRVAR(intersection_update_doc, From bcannon at users.sourceforge.net Thu Jul 28 07:50:04 2005 From: bcannon at users.sourceforge.net (bcannon@users.sourceforge.net) Date: Wed, 27 Jul 2005 22:50:04 -0700 Subject: [Python-checkins] python/dist/src/Python newcompile.c, 1.1.2.109, 1.1.2.110 Message-ID: Update of /cvsroot/python/python/dist/src/Python In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31317/Python Modified Files: Tag: ast-branch newcompile.c Log Message: Fix the creation of lnotab to emit ``\x00x01`` for the first line of code (such as def statements). Causes test_dis:test_dis to pass. Partially fixes bug #1246473. Index: newcompile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/newcompile.c,v retrieving revision 1.1.2.109 retrieving revision 1.1.2.110 diff -u -d -r1.1.2.109 -r1.1.2.110 --- newcompile.c 11 Jul 2005 03:43:56 -0000 1.1.2.109 +++ newcompile.c 28 Jul 2005 05:50:01 -0000 1.1.2.110 @@ -3339,17 +3339,22 @@ a->a_lnotab_off += ncodes * 2; } - if (d_bytecode) { - len = PyString_GET_SIZE(a->a_lnotab); - if (a->a_lnotab_off + 2 >= len) { - if (_PyString_Resize(&a->a_lnotab, len * 2) < 0) - return 0; - } - lnotab = PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; - a->a_lnotab_off += 2; + len = PyString_GET_SIZE(a->a_lnotab); + if (a->a_lnotab_off + 2 >= len) { + if (_PyString_Resize(&a->a_lnotab, len * 2) < 0) + return 0; + } + lnotab = PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; + + a->a_lnotab_off += 2; + if (d_bytecode) { *lnotab++ = d_bytecode; *lnotab++ = d_lineno; } + else { /* First line of a block; def stmt, etc. */ + *lnotab++ = 0; + *lnotab++ = 1; + } a->a_lineno = i->i_lineno; a->a_lineno_off = a->a_offset; return 1; From perky at users.sourceforge.net Thu Jul 28 07:57:22 2005 From: perky at users.sourceforge.net (perky@users.sourceforge.net) Date: Wed, 27 Jul 2005 22:57:22 -0700 Subject: [Python-checkins] python/dist/src/Modules fcntlmodule.c,2.44,2.45 Message-ID: Update of /cvsroot/python/python/dist/src/Modules In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32262/Modules Modified Files: fcntlmodule.c Log Message: Fix a typo. (found by Jong-uk Kim) Index: fcntlmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/fcntlmodule.c,v retrieving revision 2.44 retrieving revision 2.45 diff -u -d -r2.44 -r2.45 --- fcntlmodule.c 27 Jul 2005 20:24:30 -0000 2.44 +++ fcntlmodule.c 28 Jul 2005 05:57:19 -0000 2.45 @@ -173,7 +173,7 @@ arg = 0; if (!PyArg_ParseTuple(args, "O&I|i;ioctl requires a file or file descriptor," - " an integer and optionally a integer or buffer argument", + " an integer and optionally an integer or buffer argument", conv_descriptor, &fd, &code, &arg)) { return NULL; } From doerwalter at users.sourceforge.net Thu Jul 28 18:49:19 2005 From: doerwalter at users.sourceforge.net (doerwalter@users.sourceforge.net) Date: Thu, 28 Jul 2005 09:49:19 -0700 Subject: [Python-checkins] python/dist/src/Lib/test string_tests.py, 1.44, 1.45 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7035/Lib/test Modified Files: string_tests.py Log Message: Disable encoding/decoding test, if unicode is disabled. Index: string_tests.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/string_tests.py,v retrieving revision 1.44 retrieving revision 1.45 diff -u -d -r1.44 -r1.45 --- string_tests.py 20 Feb 2005 09:54:53 -0000 1.44 +++ string_tests.py 28 Jul 2005 16:49:15 -0000 1.45 @@ -737,26 +737,27 @@ # Additional tests that only work with # 8bit compatible object, i.e. str and UserString - def test_encoding_decoding(self): - codecs = [('rot13', 'uryyb jbeyq'), - ('base64', 'aGVsbG8gd29ybGQ=\n'), - ('hex', '68656c6c6f20776f726c64'), - ('uu', 'begin 666 \n+:&5L;&\\@=V]R;&0 \n \nend\n')] - for encoding, data in codecs: - self.checkequal(data, 'hello world', 'encode', encoding) - self.checkequal('hello world', data, 'decode', encoding) - # zlib is optional, so we make the test optional too... - try: - import zlib - except ImportError: - pass - else: - data = 'x\x9c\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\x01\x00\x1a\x0b\x04]' - self.checkequal(data, 'hello world', 'encode', 'zlib') - self.checkequal('hello world', data, 'decode', 'zlib') + if test_support.have_unicode: + def test_encoding_decoding(self): + codecs = [('rot13', 'uryyb jbeyq'), + ('base64', 'aGVsbG8gd29ybGQ=\n'), + ('hex', '68656c6c6f20776f726c64'), + ('uu', 'begin 666 \n+:&5L;&\\@=V]R;&0 \n \nend\n')] + for encoding, data in codecs: + self.checkequal(data, 'hello world', 'encode', encoding) + self.checkequal('hello world', data, 'decode', encoding) + # zlib is optional, so we make the test optional too... + try: + import zlib + except ImportError: + pass + else: + data = 'x\x9c\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\x01\x00\x1a\x0b\x04]' + self.checkequal(data, 'hello world', 'encode', 'zlib') + self.checkequal('hello world', data, 'decode', 'zlib') - self.checkraises(TypeError, 'xyz', 'decode', 42) - self.checkraises(TypeError, 'xyz', 'encode', 42) + self.checkraises(TypeError, 'xyz', 'decode', 42) + self.checkraises(TypeError, 'xyz', 'encode', 42) class MixinStrUnicodeTest: From vsajip at users.sourceforge.net Fri Jul 29 13:52:25 2005 From: vsajip at users.sourceforge.net (vsajip@users.sourceforge.net) Date: Fri, 29 Jul 2005 04:52:25 -0700 Subject: [Python-checkins] python/dist/src/Doc/lib liblogging.tex, 1.37, 1.38 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11567 Modified Files: liblogging.tex Log Message: Documentation added about changes in 2.4 to basicConfig(), including documentation of the keyword arguments. A version change note was also added to the basic example. Index: liblogging.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/liblogging.tex,v retrieving revision 1.37 retrieving revision 1.38 diff -u -d -r1.37 -r1.38 --- liblogging.tex 5 Jun 2005 20:39:36 -0000 1.37 +++ liblogging.tex 29 Jul 2005 11:52:19 -0000 1.38 @@ -258,13 +258,32 @@ it as a \class{LogRecord} instance at the receiving end. \end{funcdesc} -\begin{funcdesc}{basicConfig}{} +\begin{funcdesc}{basicConfig}{\optional{**kwargs}} Does basic configuration for the logging system by creating a \class{StreamHandler} with a default \class{Formatter} and adding it to the root logger. The functions \function{debug()}, \function{info()}, \function{warning()}, \function{error()} and \function{critical()} will call \function{basicConfig()} automatically if no handlers are defined for the root logger. + +\versionchanged[Formerly, \function{basicConfig} did not take any keyword +arguments]{2.4} + +The following keyword arguments are supported. + +\begin{tableii}{l|l}{code}{Format}{Description} +\lineii{filename}{Specifies that a FileHandler be created, using the +specified filename, rather than a StreamHandler.} +\lineii{filemode}{Specifies the mode to open the file, if filename is +specified (if filemode is unspecified, it defaults to 'a').} +\lineii{format}{Use the specified format string for the handler.} +\lineii{datefmt}{Use the specified date/time format.} +\lineii{level}{Set the root logger level to the specified level.} +\lineii{stream}{Use the specified stream to initialize the StreamHandler. +Note that this argument is incompatible with 'filename' - if both +are present, 'stream' is ignored.} +\end{tableii} + \end{funcdesc} \begin{funcdesc}{shutdown}{} @@ -415,6 +434,9 @@ \subsection{Basic example \label{minimal-example}} +\versionchanged[formerly \function{basicConfig} did not take any keyword +arguments]{2.4} + The \module{logging} package provides a lot of flexibility, and its configuration can appear daunting. This section demonstrates that simple use of the logging package is possible. From fdrake at users.sourceforge.net Fri Jul 29 17:56:34 2005 From: fdrake at users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 29 Jul 2005 08:56:34 -0700 Subject: [Python-checkins] python/dist/src/Lib urlparse.py,1.47,1.48 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26623/Lib Modified Files: urlparse.py Log Message: add support for svn: and svn+ssh: URL schemes to urlparse Index: urlparse.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/urlparse.py,v retrieving revision 1.47 retrieving revision 1.48 diff -u -d -r1.47 -r1.48 --- urlparse.py 9 Jan 2005 15:29:10 -0000 1.47 +++ urlparse.py 29 Jul 2005 15:56:32 -0000 1.48 @@ -13,7 +13,8 @@ 'prospero', 'rtsp', 'rtspu', ''] uses_netloc = ['ftp', 'http', 'gopher', 'nntp', 'telnet', 'imap', 'wais', 'file', 'mms', 'https', 'shttp', - 'snews', 'prospero', 'rtsp', 'rtspu', 'rsync', ''] + 'snews', 'prospero', 'rtsp', 'rtspu', 'rsync', '', + 'svn', 'svn+ssh'] non_hierarchical = ['gopher', 'hdl', 'mailto', 'news', 'telnet', 'wais', 'imap', 'snews', 'sip'] uses_params = ['ftp', 'hdl', 'prospero', 'http', 'imap', From fdrake at users.sourceforge.net Fri Jul 29 17:56:34 2005 From: fdrake at users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 29 Jul 2005 08:56:34 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_urlparse.py, 1.14, 1.15 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26623/Lib/test Modified Files: test_urlparse.py Log Message: add support for svn: and svn+ssh: URL schemes to urlparse Index: test_urlparse.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_urlparse.py,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- test_urlparse.py 9 Jan 2005 15:29:10 -0000 1.14 +++ test_urlparse.py 29 Jul 2005 15:56:32 -0000 1.15 @@ -35,6 +35,11 @@ '', '', ''), ('mms', 'wms.sys.hinet.net', '/cts/Drama/09006251100.asf', '', '')), + ('svn+ssh://svn.zope.org/repos/main/ZConfig/trunk/', + ('svn+ssh', 'svn.zope.org', '/repos/main/ZConfig/trunk/', + '', '', ''), + ('svn+ssh', 'svn.zope.org', '/repos/main/ZConfig/trunk/', + '', '')) ] for url, parsed, split in testcases: self.checkRoundtrips(url, parsed, split) From fdrake at users.sourceforge.net Fri Jul 29 17:58:02 2005 From: fdrake at users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 29 Jul 2005 08:58:02 -0700 Subject: [Python-checkins] python/dist/src/Lib/test test_urlparse.py, 1.13.4.1, 1.13.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib/test In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26913/Lib/test Modified Files: Tag: release24-maint test_urlparse.py Log Message: add support for svn: and svn+ssh: URL schemes to urlparse (backported from trunk urlparse.py 1.48, test_urlparse.py 1.15) Index: test_urlparse.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_urlparse.py,v retrieving revision 1.13.4.1 retrieving revision 1.13.4.2 diff -u -d -r1.13.4.1 -r1.13.4.2 --- test_urlparse.py 9 Jan 2005 15:32:37 -0000 1.13.4.1 +++ test_urlparse.py 29 Jul 2005 15:57:59 -0000 1.13.4.2 @@ -35,6 +35,11 @@ '', '', ''), ('mms', 'wms.sys.hinet.net', '/cts/Drama/09006251100.asf', '', '')), + ('svn+ssh://svn.zope.org/repos/main/ZConfig/trunk/', + ('svn+ssh', 'svn.zope.org', '/repos/main/ZConfig/trunk/', + '', '', ''), + ('svn+ssh', 'svn.zope.org', '/repos/main/ZConfig/trunk/', + '', '')) ] for url, parsed, split in testcases: self.checkRoundtrips(url, parsed, split) From fdrake at users.sourceforge.net Fri Jul 29 17:58:02 2005 From: fdrake at users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 29 Jul 2005 08:58:02 -0700 Subject: [Python-checkins] python/dist/src/Lib urlparse.py, 1.45.4.1, 1.45.4.2 Message-ID: Update of /cvsroot/python/python/dist/src/Lib In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26913/Lib Modified Files: Tag: release24-maint urlparse.py Log Message: add support for svn: and svn+ssh: URL schemes to urlparse (backported from trunk urlparse.py 1.48, test_urlparse.py 1.15) Index: urlparse.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/urlparse.py,v retrieving revision 1.45.4.1 retrieving revision 1.45.4.2 diff -u -d -r1.45.4.1 -r1.45.4.2 --- urlparse.py 9 Jan 2005 15:32:37 -0000 1.45.4.1 +++ urlparse.py 29 Jul 2005 15:57:53 -0000 1.45.4.2 @@ -13,7 +13,8 @@ 'prospero', 'rtsp', 'rtspu', ''] uses_netloc = ['ftp', 'http', 'gopher', 'nntp', 'telnet', 'imap', 'wais', 'file', 'mms', 'https', 'shttp', - 'snews', 'prospero', 'rtsp', 'rtspu', 'rsync', ''] + 'snews', 'prospero', 'rtsp', 'rtspu', 'rsync', '', + 'svn', 'svn+ssh'] non_hierarchical = ['gopher', 'hdl', 'mailto', 'news', 'telnet', 'wais', 'imap', 'snews', 'sip'] uses_params = ['ftp', 'hdl', 'prospero', 'http', 'imap', From fdrake at users.sourceforge.net Fri Jul 29 19:17:22 2005 From: fdrake at users.sourceforge.net (fdrake@users.sourceforge.net) Date: Fri, 29 Jul 2005 10:17:22 -0700 Subject: [Python-checkins] python/dist/src/Doc/texinputs howto.cls, 1.15, 1.16 manual.cls, 1.19, 1.20 Message-ID: Update of /cvsroot/python/python/dist/src/Doc/texinputs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12501/texinputs Modified Files: howto.cls manual.cls Log Message: use a test for PDF support that is more portable across teTeX major versions (closes SF bug #1238210) Index: howto.cls =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/texinputs/howto.cls,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- howto.cls 31 Mar 2004 08:08:34 -0000 1.15 +++ howto.cls 29 Jul 2005 17:17:19 -0000 1.16 @@ -50,7 +50,8 @@ % \renewcommand{\maketitle}{ \py at doHorizontalRule - \@ifundefined{pdfinfo}{}{{ + \ifpdf + \begingroup % This \def is required to deal with multi-line authors; it % changes \\ to ', ' (comma-space), making it pass muster for % generating document info in the PDF file. @@ -59,7 +60,8 @@ /Author (\@author) /Title (\@title) } - }} + \endgroup + \fi \begin{flushright} {\rm\Huge\py at HeaderFamily \@title} \par {\em\large\py at HeaderFamily \py at release\releaseinfo} \par Index: manual.cls =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/texinputs/manual.cls,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- manual.cls 31 Mar 2004 08:08:34 -0000 1.19 +++ manual.cls 29 Jul 2005 17:17:19 -0000 1.20 @@ -64,7 +64,8 @@ \let\footnotesize\small \let\footnoterule\relax \py at doHorizontalRule% - \@ifundefined{pdfinfo}{}{{ + \ifpdf + \begingroup % This \def is required to deal with multi-line authors; it % changes \\ to ', ' (comma-space), making it pass muster for % generating document info in the PDF file. @@ -73,7 +74,8 @@ /Author (\@author) /Title (\@title) } - }} + \endgroup + \fi \begin{flushright}% {\rm\Huge\py at HeaderFamily \@title \par}% {\em\LARGE\py at HeaderFamily \py at release\releaseinfo \par} From rhettinger at users.sourceforge.net Fri Jul 29 21:03:11 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 29 Jul 2005 12:03:11 -0700 Subject: [Python-checkins] python/nondist/sandbox/set setobject.c,1.2,1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4100 Modified Files: setobject.c Log Message: * Implement an internal discard function so that client functions don't have to check for and clear KeyErrors. * Simplify code where a contains check is followed by a remove operation. Can be reduced from two lookups to just one. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- setobject.c 27 Jul 2005 23:38:40 -0000 1.2 +++ setobject.c 29 Jul 2005 19:03:00 -0000 1.3 @@ -362,8 +362,14 @@ return set_table_resize(mp, mp->ma_used*(mp->ma_used>50000 ? 2 : 4)); } -int -set_remove_internal(PySetObject *mp, PyObject *key) +/* Discard unconditionally removes an entry. + Returns 1 if not found + Returns 0 if found and removed + Returns -1 on hash error +*/ + +static int +set_discard_internal(PySetObject *mp, PyObject *key) { register long hash; register setentry *ep; @@ -378,8 +384,7 @@ } ep = (mp->ma_lookup)(mp, key, hash); if (ep->me_key == NULL || ep->me_key == dummy) { // XXX ? can this be simplified - PyErr_SetObject(PyExc_KeyError, key); - return -1; + return 1; } old_key = ep->me_key; Py_INCREF(dummy); @@ -389,6 +394,18 @@ return 0; } +static int +set_remove_internal(PySetObject *mp, PyObject *key) +{ + int rv = set_discard_internal(mp, key); + + if (rv == 1) { + PyErr_SetObject(PyExc_KeyError, key); + return -1; + } + return rv; +} + static void set_clear_internal(PySetObject *mp) { @@ -1098,14 +1115,10 @@ return NULL; while ((item = PyIter_Next(it)) != NULL) { - if (set_remove_internal(so, item) == -1) { - if (PyErr_ExceptionMatches(PyExc_KeyError)) - PyErr_Clear(); - else { - Py_DECREF(it); - Py_DECREF(item); - return NULL; - } + if (set_discard_internal(so, item) == -1) { + Py_DECREF(it); + Py_DECREF(item); + return NULL; } Py_DECREF(item); } @@ -1200,11 +1213,12 @@ if (PyDict_Check(other)) { PyObject *value; + int rv; while (PyDict_Next(other, &pos, &key, &value)) { - if (set_contains_internal(so, key)) { - if (set_remove_internal(so, key) == -1) - return NULL; - } else { + rv = set_discard_internal(so, key); + if (rv == -1) + return NULL; + if (rv == 1) { if (set_add_internal(so, key) == -1) return NULL; } @@ -1222,12 +1236,12 @@ } while (set_next_internal(otherset, &pos, &key)) { - if (set_contains_internal(so, key)) { - if (set_remove_internal(so, key) == -1) { - Py_XDECREF(otherset); - return NULL; - } - } else { + int rv = set_discard_internal(so, key); + if (rv == -1) { + Py_XDECREF(otherset); + return NULL; + } + if (rv == 1) { if (set_add_internal(so, key) == -1) { Py_XDECREF(otherset); return NULL; @@ -1555,11 +1569,8 @@ return result; } - if (set_remove_internal(so, item) == -1) { - if (!PyErr_ExceptionMatches(PyExc_KeyError)) - return NULL; - PyErr_Clear(); - } + if (set_discard_internal(so, item) == -1) + return NULL; Py_RETURN_NONE; } From rhettinger at users.sourceforge.net Fri Jul 29 21:59:30 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Fri, 29 Jul 2005 12:59:30 -0700 Subject: [Python-checkins] python/nondist/sandbox/set settimings.py, NONE, 1.1 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16836 Added Files: settimings.py Log Message: Sandbox a benchmarking tool. Compares relative performance of dicts vs sets. Compares set() vs sets.Set(). Compares operations with various input types (sets, dicts, lists, uniqlists). Also useful for comparing the Py2.4 version to the Py2.5 version. --- NEW FILE: settimings.py --- # timings of the new sets module from timeit import Timer setup = """ from random import randrange, seed from sets import Set, ImmutableSet seed(845957276943582345234523452734241L) n = 1000 a = [randrange(n) for i in xrange(n)] b = [randrange(n) for i in xrange(n)] seta = set(a) Seta = Set(a) setb = set(b) dicta = dict.fromkeys(a, True) dictb = dict.fromkeys(b, True) NONE = None TRUE = True listseta = list(seta) listsetb = list(setb) dac = dicta.__contains__ dah = dicta.has_key sac = seta.__contains__ sadd = seta.add setc = set(seta) for _ in setc: pass seta.discard(None) setb.discard(None) """ """ If you don't already have a set, then passing the list form is always better or as good a making a temp set If you do have a set or dict, then passing it is better or as good (w/in 20)% as a listset() The w/20 is because looping over sets is slower than looping over a list. Need more study on difference (first result) and sym_diff_up (second result) -------------- set(a).binop(b) vs set(a).binop(set(b)) when =, it means internally b is first converted to a set if not already when <, it means the binop uses an algo that doesn't make a set first: diff, diff_up, inter, inter_up, union, union_up set(a).binop(listsetb) vs set(a).binop(setb) when >>, it means that the list had to be coerced to a set first diff, sym_diff_up when >, it means that faster merge was used instead of iter union, union_up, when < 1/6, just means looping over dicts is slower than lists which is ok inter, inter_up, diff_up or something else sym_diff has ?flawed strategy of makingset and passing to sym_up B:makeset, A:sparseloop A:contains A-m:adds m:deletes vs. B:makeset, A:sparseloop A:contains A-m:adds B:sparseloop B:contains B-m:adds delete B """ # set_diff use of iterable vs set stmts = [ 'list(seta)', 'list(dicta)', 'dicta.keys()', 'list(listseta)', 'list(setb)', 'setc.__contains__(None); list(setc)', 'setc.discard(None); list(setc)', 'frozenset(setb)', 'frozenset(listsetb)', "'< means binop bypassed forcing to set'", "seta.difference(b)", "seta.difference(set(b))", "Seta.difference(b)", "seta.union(b)", "seta.union(set(b))", "Seta.union(b)", "seta.intersection(b)", "seta.intersection(set(b))", "Seta.intersection(b)", "seta.symmetric_difference(b)", "seta.symmetric_difference(set(b))", "Seta.symmetric_difference(b)", "seta.difference_update(b)", "seta.difference_update(set(b))", "Seta.difference_update(b)", "seta.update(b)", "seta.update(set(b))", "Seta.update(b)", "seta.intersection_update(b)", "seta.intersection_update(set(b))", "Seta.intersection_update(b)", "seta.symmetric_difference_update(b)", "seta.symmetric_difference_update(set(b))", "Seta.symmetric_difference_update(b)", "'>> due to set coercion; > merge faster than iter; < 1/6 dict looping is slow'", "seta.difference(listsetb)", "seta.difference(setb)", "seta.difference(dictb)", "seta.union(listsetb)", "seta.union(setb)", "seta.union(dictb)", "seta.intersection(listsetb)", "seta.intersection(setb)", "seta.intersection(dictb)", "seta.symmetric_difference(listsetb)", "seta.symmetric_difference(setb)", "seta.symmetric_difference(dictb)", "seta.difference_update(listsetb)", "seta.difference_update(setb)", "seta.difference_update(dictb)", "seta.update(listsetb)", "seta.update(setb)", "seta.update(dictb)", "seta.intersection_update(listsetb)", "seta.intersection_update(setb)", "seta.intersection_update(dictb)", "seta.symmetric_difference_update(listsetb)", "seta.symmetric_difference_update(setb)", "seta.symmetric_difference_update(dictb)", "for i in xrange(500): seta.add(i)", "for i in xrange(500): Seta.add(i)", "for i in xrange(500): dicta[i] = NONE", "for i in xrange(500): sadd(i)", "set(b)", "Set(b)", "dict.fromkeys(b, TRUE)", "set(listsetb)", "set(setb)", "set(dictb)", "for i in xrange(200): i in seta", "for i in xrange(200): i in Seta", "for i in xrange(200): i in dicta", "for i in xrange(200): dah(i)", "for i in xrange(200): dac(i)", "for i in xrange(200): sac(i)", "for i in xrange(200): seta.discard(i)", "for i in xrange(20): Seta.discard(i)", "for i in xrange(200): dicta.pop(i, NONE)", # Repeat first five to check validity of timings 'list(seta)', 'list(dicta)', 'dicta.keys()', 'list(listseta)', 'list(setb)', # Uniquification, 'list(set(a))', 'dict.fromkeys(a).keys()', 'list(dict.fromkeys(a))', 'list(set(b))', 'dict.fromkeys(b).keys()', 'list(dict.fromkeys(b))', ] from time import time import gc start = time() for stmt in stmts: gc.collect() print "%f\t%s" % (min(Timer(stmt, setup).repeat(9, 3500)), stmt) end = time() print end-start, "! total elapsed" From birkenfeld at users.sourceforge.net Sat Jul 30 14:14:17 2005 From: birkenfeld at users.sourceforge.net (birkenfeld@users.sourceforge.net) Date: Sat, 30 Jul 2005 05:14:17 -0700 Subject: [Python-checkins] python/nondist/sandbox/path path.py, 1.7, 1.8 test_path.py, 1.6, 1.7 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/path In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13772 Modified Files: path.py test_path.py Log Message: Allow constructor to take more args. Path("a", "b") => "a/b". Index: path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/path.py,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- path.py 25 Jul 2005 16:09:17 -0000 1.7 +++ path.py 30 Jul 2005 12:14:14 -0000 1.8 @@ -60,11 +60,13 @@ """ if not args: return Path(os.curdir) - if len(args) > 1: - raise TypeError("Path() takes at most 1 argument (%i given)" % len(args)) - if not isinstance(args[0], basestring): - raise ValueError("Path() argument must be Path, str or unicode") - return _base.__new__(typ, *args) + for arg in args: + if not isinstance(arg, basestring): + raise ValueError("Path() arguments must be Path, str or unicode") + if len(args) == 1: + return _base.__new__(typ, *args) + else: + return Path(os.path.join(*args)) # Iterating over a string yields its parts def __iter__(self): @@ -234,18 +236,12 @@ """ The UNC mount point for this path. This is empty for paths on local drives. """) - @staticmethod - def join(*args): - if args: - return Path(args[0]).joinwith(args[1:]) - return Path('') - def joinwith(self, *args): """ Join two or more path components, adding a separator character (os.sep) if needed. Returns a new path object. """ - return Path(os.path.join(self, *map(_base, args))) + return Path(os.path.join(self, *args)) joinpath = joinwith @@ -257,7 +253,7 @@ this path (for example, '/' or 'C:\\'). The other items in the list will be strings. - Path.join(*result) will yield the original path. + Path(*result) will yield the original path. """ parts = [] loc = self Index: test_path.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/path/test_path.py,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- test_path.py 25 Jul 2005 16:06:32 -0000 1.6 +++ test_path.py 30 Jul 2005 12:14:14 -0000 1.7 @@ -28,17 +28,19 @@ class BasicTestCase(unittest.TestCase): def testConstructor(self): - # constructor can only be called with zero or one arguments + # constructor can be called with zero arguments, which is os.curdir p = Path() - self.assert_(p.base() == os.curdir) + self.assertEquals(p.base(), os.curdir) - self.assertRaises(TypeError, Path, "a", "b") - self.assertRaises(TypeError, Path, 1, 2) - - # constructor can only be called with basestring as argument + # constructor can only be called with basestring(s) as argument self.assertRaises(ValueError, Path, None) self.assertRaises(ValueError, Path, 1) + # calling with more than one argument joins them + p1 = Path("a").joinwith("b") + p2 = Path("a", "b") + self.assertEquals(p1, p2) + def testRelpath(self): root = Path(p(nt='C:\\', posix='/')) From rhettinger at users.sourceforge.net Sat Jul 30 16:22:12 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 07:22:12 -0700 Subject: [Python-checkins] python/nondist/sandbox/set setobject.c,1.3,1.4 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3511 Modified Files: setobject.c Log Message: Simplify code for symmetric_differences. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- setobject.c 29 Jul 2005 19:03:00 -0000 1.3 +++ setobject.c 30 Jul 2005 14:22:10 -0000 1.4 @@ -1258,46 +1258,17 @@ static PyObject * set_symmetric_difference(PySetObject *so, PyObject *other) { - PyObject *rv, *key; - PySetObject *result, *otherset; - int pos = 0; - - if (!PyAnySet_Check(other)) { - otherset = (PySetObject *)make_new_set(so->ob_type, other); - if (otherset == NULL) - return NULL; - rv = set_symmetric_difference_update(otherset, (PyObject *)so); - if (rv == NULL) - return NULL; - Py_DECREF(rv); - return (PyObject *)otherset; - } + PyObject *rv; + PySetObject *otherset; - result = (PySetObject *)make_new_set(so->ob_type, NULL); - if (result == NULL) + otherset = (PySetObject *)make_new_set(so->ob_type, other); + if (otherset == NULL) return NULL; - - otherset = (PySetObject *)other; - while (set_next_internal(otherset, &pos, &key)) { - if (!set_contains_internal(so, key)) { - if (set_add_internal(result, key) == -1) { - Py_DECREF(result); - return NULL; - } - } - } - - pos = 0; - while (set_next_internal(so, &pos, &key)) { - if (!set_contains_internal(otherset, key)) { - if (set_add_internal(result, key) == -1) { - Py_DECREF(result); - return NULL; - } - } - } - - return (PyObject *)result; + rv = set_symmetric_difference_update(otherset, (PyObject *)so); + if (rv == NULL) + return NULL; + Py_DECREF(rv); + return (PyObject *)otherset; } PyDoc_STRVAR(symmetric_difference_doc, From rhettinger at users.sourceforge.net Sat Jul 30 17:02:24 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 08:02:24 -0700 Subject: [Python-checkins] python/nondist/sandbox/set setobject.c,1.4,1.5 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11269 Modified Files: setobject.c Log Message: Fix spelling. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- setobject.c 30 Jul 2005 14:22:10 -0000 1.4 +++ setobject.c 30 Jul 2005 15:02:21 -0000 1.5 @@ -383,7 +383,7 @@ return -1; } ep = (mp->ma_lookup)(mp, key, hash); - if (ep->me_key == NULL || ep->me_key == dummy) { // XXX ? can this be simplified + if (ep->me_key == NULL || ep->me_key == dummy) { return 1; } old_key = ep->me_key; @@ -1028,7 +1028,7 @@ static void -set_swap_bodys(PySetObject *a, PySetObject *b) +set_swap_bodies(PySetObject *a, PySetObject *b) { int t; PySetEntry *u; @@ -1070,7 +1070,7 @@ tmp = set_intersection(so, other); if (tmp == NULL) return NULL; - set_swap_bodys(so, (PySetObject *)tmp); + set_swap_bodies(so, (PySetObject *)tmp); Py_DECREF(tmp); Py_RETURN_NONE; } From rhettinger at users.sourceforge.net Sat Jul 30 18:21:20 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 09:21:20 -0700 Subject: [Python-checkins] python/nondist/sandbox/set setobject.c,1.5,1.6 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25306 Modified Files: setobject.c Log Message: * Restore logic for temporary frozensets in __contains__ , discard, and remove. * Eliminate set_keys_internal in favor of PySequence_List. * Add self-documenting macro for discard's return values. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- setobject.c 30 Jul 2005 15:02:21 -0000 1.5 +++ setobject.c 30 Jul 2005 16:21:17 -0000 1.6 @@ -362,11 +362,8 @@ return set_table_resize(mp, mp->ma_used*(mp->ma_used>50000 ? 2 : 4)); } -/* Discard unconditionally removes an entry. - Returns 1 if not found - Returns 0 if found and removed - Returns -1 on hash error -*/ +#define DISCARD_FOUND 0 +#define DISCARD_NOTFOUND 1 static int set_discard_internal(PySetObject *mp, PyObject *key) @@ -383,15 +380,14 @@ return -1; } ep = (mp->ma_lookup)(mp, key, hash); - if (ep->me_key == NULL || ep->me_key == dummy) { - return 1; - } + if (ep->me_key == NULL || ep->me_key == dummy) + return DISCARD_NOTFOUND; old_key = ep->me_key; Py_INCREF(dummy); ep->me_key = dummy; mp->ma_used--; Py_DECREF(old_key); - return 0; + return DISCARD_FOUND; } static int @@ -496,7 +492,7 @@ return 0; ep = mp->ma_table; mask = mp->ma_mask; - while (i <= mask && (ep[i].me_key == NULL || ep[i].me_key == dummy)) // XXX ? can this be simplified + while (i <= mask && (ep[i].me_key == NULL || ep[i].me_key == dummy)) i++; *ppos = i+1; if (i > mask) @@ -541,40 +537,6 @@ return 0; } -static PyObject * -set_keys_internal(register PySetObject *mp) -{ - register PyObject *v; - register int i, j; - setentry *ep; - int mask, n; - - again: - n = mp->ma_used; - v = PyList_New(n); - if (v == NULL) - return NULL; - if (n != mp->ma_used) { - /* Durnit. The allocations caused the set to resize. - * Just start over, this shouldn't normally happen. - */ - Py_DECREF(v); - goto again; - } - ep = mp->ma_table; - mask = mp->ma_mask; - for (i = 0, j = 0; i <= mask; i++) { - if (ep[i].me_key != NULL && ep[i].me_key != dummy) { // XXX can this be simplified - PyObject *key = ep[i].me_key; - Py_INCREF(key); - PyList_SET_ITEM(v, j, key); - j++; - } - } - assert(j == n); - return v; -} - static PyTypeObject PysetiterKey_Type; /* Forward */ static PyObject *set_iter(setobject *); @@ -868,6 +830,38 @@ return ((PySetObject *)so)->ma_used; } +static void +set_swap_bodies(PySetObject *a, PySetObject *b) +{ + int t; + PySetEntry *u; + PySetEntry *(*f)(PySetObject *mp, PyObject *key, long hash); + PySetEntry tab[PySet_MINSIZE]; + long h; + + t = a->ma_fill; a->ma_fill = b->ma_fill; b->ma_fill = t; + t = a->ma_used; a->ma_used = b->ma_used; b->ma_used = t; + t = a->ma_mask; a->ma_mask = b->ma_mask; b->ma_mask = t; + + u = a->ma_table; + if (a->ma_table == a->ma_smalltable) + u = b->ma_smalltable; + a->ma_table = b->ma_table; + if (b->ma_table == b->ma_smalltable) + a->ma_table = a->ma_smalltable; + b->ma_table = u; + + f = a->ma_lookup; a->ma_lookup = b->ma_lookup; b->ma_lookup = f; + + if (a->ma_table == a->ma_smalltable || b->ma_table == b->ma_smalltable) { + memcpy(tab, a->ma_smalltable, sizeof(tab)); + memcpy(a->ma_smalltable, b->ma_smalltable, sizeof(tab)); + memcpy(b->ma_smalltable, tab, sizeof(tab)); + } + + h = a->hash; a->hash = b->hash; b->hash = h; +} + static int set_contains(PySetObject *so, PyObject *key) { @@ -877,10 +871,12 @@ result = set_contains_internal(so, key); if (result == -1 && PyAnySet_Check(key)) { PyErr_Clear(); - tmp = make_new_set(&PyFrozenSet_Type, key); + tmp = make_new_set(&PyFrozenSet_Type, NULL); if (tmp == NULL) return -1; + set_swap_bodies((PySetObject *)tmp, (PySetObject *)key); result = set_contains_internal(so, tmp); + set_swap_bodies((PySetObject *)tmp, (PySetObject *)key); Py_DECREF(tmp); } return result; @@ -1026,42 +1022,6 @@ \n\ (i.e. all elements that are in both sets.)"); - -static void -set_swap_bodies(PySetObject *a, PySetObject *b) -{ - int t; - PySetEntry *u; - PySetEntry *(*f)(PySetObject *mp, PyObject *key, long hash); - PySetEntry tab[PySet_MINSIZE]; - long h; - - t = a->ma_fill; a->ma_fill = b->ma_fill; b->ma_fill = t; - t = a->ma_used; a->ma_used = b->ma_used; b->ma_used = t; - t = a->ma_mask; a->ma_mask = b->ma_mask; b->ma_mask = t; - - u = a->ma_table; - if (a->ma_table == a->ma_smalltable) - u = b->ma_smalltable; - a->ma_table = b->ma_table; - if (b->ma_table == b->ma_smalltable) - a->ma_table = a->ma_smalltable; - b->ma_table = u; - - f = a->ma_lookup; a->ma_lookup = b->ma_lookup; b->ma_lookup = f; - - if (a->ma_table == a->ma_smalltable || b->ma_table == b->ma_smalltable) { - memcpy(tab, a->ma_smalltable, sizeof(tab)); - memcpy(a->ma_smalltable, b->ma_smalltable, sizeof(tab)); - memcpy(b->ma_smalltable, tab, sizeof(tab)); - } - - h = a->hash; a->hash = b->hash; b->hash = h; -} - -static PyObject *set_clear(PySetObject *so); /// XXX remove forward declaration -static int set_tp_clear(PySetObject *so); /// XXX remove forward declaration - static PyObject * set_intersection_update(PySetObject *so, PyObject *other) { @@ -1218,7 +1178,7 @@ rv = set_discard_internal(so, key); if (rv == -1) return NULL; - if (rv == 1) { + if (rv == DISCARD_NOTFOUND) { if (set_add_internal(so, key) == -1) return NULL; } @@ -1241,7 +1201,7 @@ Py_XDECREF(otherset); return NULL; } - if (rv == 1) { + if (rv == DISCARD_NOTFOUND) { if (set_add_internal(so, key) == -1) { Py_XDECREF(otherset); return NULL; @@ -1438,7 +1398,7 @@ { PyObject *keys, *result, *listrepr; - keys = set_keys_internal(so); + keys = PySequence_List((PyObject *)so); if (keys == NULL) return NULL; listrepr = PyObject_Repr(keys); @@ -1508,10 +1468,12 @@ PyObject *tmp, *result; if (PyType_IsSubtype(item->ob_type, &PySet_Type)) { - tmp = make_new_set(&PyFrozenSet_Type, item); + tmp = make_new_set(&PyFrozenSet_Type, NULL); if (tmp == NULL) return NULL; + set_swap_bodies((PySetObject *)item, (PySetObject *)tmp); result = set_remove(so, tmp); + set_swap_bodies((PySetObject *)item, (PySetObject *)tmp); Py_DECREF(tmp); return result; } @@ -1532,10 +1494,12 @@ PyObject *tmp, *result; if (PyType_IsSubtype(item->ob_type, &PySet_Type)) { - tmp = make_new_set(&PyFrozenSet_Type, item); + tmp = make_new_set(&PyFrozenSet_Type, NULL); if (tmp == NULL) return NULL; + set_swap_bodies((PySetObject *)item, (PySetObject *)tmp); result = set_discard(so, tmp); + set_swap_bodies((PySetObject *)item, (PySetObject *)tmp); Py_DECREF(tmp); return result; } @@ -1575,7 +1539,7 @@ { PyObject *keys=NULL, *args=NULL, *result=NULL, *dict=NULL; - keys = set_keys_internal(so); + keys = PySequence_List((PyObject *)so); if (keys == NULL) goto done; args = PyTuple_Pack(1, keys); From rhettinger at users.sourceforge.net Sat Jul 30 23:07:31 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 14:07:31 -0700 Subject: [Python-checkins] python/nondist/sandbox/set setobject.c, 1.6, 1.7 setobject.h, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12279 Modified Files: setobject.c setobject.h Log Message: Improve variable names and other minor clean-up. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- setobject.c 30 Jul 2005 16:21:17 -0000 1.6 +++ setobject.c 30 Jul 2005 21:07:28 -0000 1.7 @@ -16,13 +16,13 @@ /* forward declarations */ static setentry * -set_lookkey_string(setobject *mp, PyObject *key, long hash); +set_lookkey_string(setobject *so, PyObject *key, long hash); -#define EMPTY_TO_MINSIZE(mp) do { \ - memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \ - (mp)->ma_used = (mp)->ma_fill = 0; \ - (mp)->ma_table = (mp)->ma_smalltable; \ - (mp)->ma_mask = PySet_MINSIZE - 1; \ +#define EMPTY_TO_MINSIZE(so) do { \ + memset((so)->smalltable, 0, sizeof((so)->smalltable)); \ + (so)->used = (so)->fill = 0; \ + (so)->table = (so)->smalltable; \ + (so)->mask = PySet_MINSIZE - 1; \ } while(0) @@ -38,18 +38,18 @@ All arithmetic on hash should ignore overflow. This function must never return NULL; failures are indicated by returning -a setentry* for which the me_value field is NULL. Exceptions are never +a setentry* for which the value field is NULL. Exceptions are never reported by this function, and outstanding exceptions are maintained. */ static setentry * -set_lookkey(setobject *mp, PyObject *key, register long hash) +set_lookkey(setobject *so, PyObject *key, register long hash) { register int i; register unsigned int perturb; register setentry *freeslot; - register unsigned int mask = mp->ma_mask; - setentry *ep0 = mp->ma_table; + register unsigned int mask = so->mask; + setentry *ep0 = so->table; register setentry *ep; register int restore_error; register int checked_error; @@ -59,25 +59,25 @@ i = hash & mask; ep = &ep0[i]; - if (ep->me_key == NULL || ep->me_key == key) + if (ep->key == NULL || ep->key == key) return ep; restore_error = checked_error = 0; - if (ep->me_key == dummy) + if (ep->key == dummy) freeslot = ep; else { - if (ep->me_hash == hash) { + if (ep->hash == hash) { /* error can't have been checked yet */ checked_error = 1; if (PyErr_Occurred()) { restore_error = 1; PyErr_Fetch(&err_type, &err_value, &err_tb); } - startkey = ep->me_key; + startkey = ep->key; cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); if (cmp < 0) PyErr_Clear(); - if (ep0 == mp->ma_table && ep->me_key == startkey) { + if (ep0 == so->table && ep->key == startkey) { if (cmp > 0) goto Done; } @@ -87,26 +87,26 @@ * XXX A clever adversary could prevent this * XXX from terminating. */ - ep = set_lookkey(mp, key, hash); + ep = set_lookkey(so, key, hash); goto Done; } } freeslot = NULL; } - /* In the loop, me_key == dummy is by far (factor of 100s) the + /* In the loop, key == dummy is by far (factor of 100s) the least likely outcome, so test for that last. */ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { i = (i << 2) + i + perturb + 1; ep = &ep0[i & mask]; - if (ep->me_key == NULL) { + if (ep->key == NULL) { if (freeslot != NULL) ep = freeslot; break; } - if (ep->me_key == key) + if (ep->key == key) break; - if (ep->me_hash == hash && ep->me_key != dummy) { + if (ep->hash == hash && ep->key != dummy) { if (!checked_error) { checked_error = 1; if (PyErr_Occurred()) { @@ -115,11 +115,11 @@ &err_tb); } } - startkey = ep->me_key; + startkey = ep->key; cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); if (cmp < 0) PyErr_Clear(); - if (ep0 == mp->ma_table && ep->me_key == startkey) { + if (ep0 == so->table && ep->key == startkey) { if (cmp > 0) break; } @@ -129,11 +129,11 @@ * XXX A clever adversary could prevent this * XXX from terminating. */ - ep = set_lookkey(mp, key, hash); + ep = set_lookkey(so, key, hash); break; } } - else if (ep->me_key == dummy && freeslot == NULL) + else if (ep->key == dummy && freeslot == NULL) freeslot = ep; } @@ -154,13 +154,13 @@ * expensive, and sets with pure-string keys may be very common. */ static setentry * -set_lookkey_string(setobject *mp, PyObject *key, register long hash) +set_lookkey_string(setobject *so, PyObject *key, register long hash) { register int i; register unsigned int perturb; register setentry *freeslot; - register unsigned int mask = mp->ma_mask; - setentry *ep0 = mp->ma_table; + register unsigned int mask = so->mask; + setentry *ep0 = so->table; register setentry *ep; /* Make sure this function doesn't have to handle non-string keys, @@ -168,36 +168,34 @@ strings is to override __eq__, and for speed we don't cater to that here. */ if (!PyString_CheckExact(key)) { - mp->ma_lookup = set_lookkey; - return set_lookkey(mp, key, hash); + so->lookup = set_lookkey; + return set_lookkey(so, key, hash); } i = hash & mask; ep = &ep0[i]; - if (ep->me_key == NULL || ep->me_key == key) + if (ep->key == NULL || ep->key == key) return ep; - if (ep->me_key == dummy) + if (ep->key == dummy) freeslot = ep; else { - if (ep->me_hash == hash - && _PyString_Eq(ep->me_key, key)) { + if (ep->hash == hash && _PyString_Eq(ep->key, key)) return ep; - } freeslot = NULL; } - /* In the loop, me_key == dummy is by far (factor of 100s) the + /* In the loop, key == dummy is by far (factor of 100s) the least likely outcome, so test for that last. */ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { i = (i << 2) + i + perturb + 1; ep = &ep0[i & mask]; - if (ep->me_key == NULL) + if (ep->key == NULL) return freeslot == NULL ? ep : freeslot; - if (ep->me_key == key - || (ep->me_hash == hash - && ep->me_key != dummy - && _PyString_Eq(ep->me_key, key))) + if (ep->key == key + || (ep->hash == hash + && ep->key != dummy + && _PyString_Eq(ep->key, key))) return ep; - if (ep->me_key == dummy && freeslot == NULL) + if (ep->key == dummy && freeslot == NULL) freeslot = ep; } } @@ -208,31 +206,27 @@ Eats a reference to key. */ static void -set_insert_key(register setobject *mp, PyObject *key, long hash) +set_insert_key(register setobject *so, PyObject *key, long hash) { register setentry *ep; typedef PySetEntry *(*lookupfunc)(PySetObject *, PyObject *, long); - assert(mp->ma_lookup != NULL); + assert(so->lookup != NULL); - ep = mp->ma_lookup(mp, key, hash); - if (ep->me_key == NULL) { + ep = so->lookup(so, key, hash); + if (ep->key == NULL) { /* UNUSED */ - mp->ma_fill++; - ep->me_key = key; - ep->me_hash = hash; - mp->ma_used++; - } - - else if (ep->me_key == dummy) { + so->fill++; + ep->key = key; + ep->hash = hash; + so->used++; + } else if (ep->key == dummy) { /* DUMMY */ Py_DECREF(dummy); - ep->me_key = key; - ep->me_hash = hash; - mp->ma_used++; - } - - else { + ep->key = key; + ep->hash = hash; + so->used++; + } else { /* ACTIVE */ Py_DECREF(key); } @@ -244,7 +238,7 @@ actually be smaller than the old one. */ static int -set_table_resize(setobject *mp, int minused) +set_table_resize(setobject *so, int minused) { int newsize; setentry *oldtable, *newtable, *ep; @@ -265,15 +259,15 @@ } /* Get space for a new table. */ - oldtable = mp->ma_table; + oldtable = so->table; assert(oldtable != NULL); - is_oldtable_malloced = oldtable != mp->ma_smalltable; + is_oldtable_malloced = oldtable != so->smalltable; if (newsize == PySet_MINSIZE) { /* A large table is shrinking, or we can't get any smaller. */ - newtable = mp->ma_smalltable; + newtable = so->smalltable; if (newtable == oldtable) { - if (mp->ma_fill == mp->ma_used) { + if (so->fill == so->used) { /* No dummies, so no point doing anything. */ return 0; } @@ -283,7 +277,7 @@ as set_lookkey needs at least one virgin slot to terminate failing searches. If fill < size, it's merely desirable, as dummies slow searches. */ - assert(mp->ma_fill > mp->ma_used); + assert(so->fill > so->used); memcpy(small_copy, oldtable, sizeof(small_copy)); oldtable = small_copy; } @@ -298,33 +292,28 @@ /* Make the set empty, using the new table. */ assert(newtable != oldtable); - mp->ma_table = newtable; - mp->ma_mask = newsize - 1; + so->table = newtable; + so->mask = newsize - 1; memset(newtable, 0, sizeof(setentry) * newsize); - mp->ma_used = 0; - i = mp->ma_fill; - mp->ma_fill = 0; + so->used = 0; + i = so->fill; + so->fill = 0; /* Copy the data over; this is refcount-neutral for active entries; dummy entries aren't copied over, of course */ for (ep = oldtable; i > 0; ep++) { - - if (ep->me_key == NULL) { + if (ep->key == NULL) { // UNUSED ; - } - - else if (ep->me_key == dummy) { + } else if (ep->key == dummy) { // DUMMY --i; - assert(ep->me_key == dummy); - Py_DECREF(ep->me_key); - } - - else { + assert(ep->key == dummy); + Py_DECREF(ep->key); + } else { // ACTIVE --i; - set_insert_key(mp, ep->me_key, ep->me_hash); + set_insert_key(so, ep->key, ep->hash); } } @@ -338,7 +327,7 @@ /* CAUTION: set_add_internal() must guarantee that it won't resize the table */ static int -set_add_internal(register PySetObject *mp, PyObject *key) +set_add_internal(register PySetObject *so, PyObject *key) { register long hash; register int n_used; @@ -347,63 +336,50 @@ hash = ((PyStringObject *)key)->ob_shash; if (hash == -1) hash = PyObject_Hash(key); - } - else { + } else { hash = PyObject_Hash(key); if (hash == -1) return -1; } - assert(mp->ma_fill <= mp->ma_mask); /* at least one empty slot */ - n_used = mp->ma_used; + assert(so->fill <= so->mask); /* at least one empty slot */ + n_used = so->used; Py_INCREF(key); - set_insert_key(mp, key, hash); - if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2)) + set_insert_key(so, key, hash); + if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2)) return 0; - return set_table_resize(mp, mp->ma_used*(mp->ma_used>50000 ? 2 : 4)); + return set_table_resize(so, so->used*(so->used>50000 ? 2 : 4)); } #define DISCARD_FOUND 0 #define DISCARD_NOTFOUND 1 static int -set_discard_internal(PySetObject *mp, PyObject *key) +set_discard_internal(PySetObject *so, PyObject *key) { register long hash; register setentry *ep; PyObject *old_key; - assert (PyAnySet_Check(mp)); + assert (PyAnySet_Check(so)); if (!PyString_CheckExact(key) || (hash = ((PyStringObject *) key)->ob_shash) == -1) { hash = PyObject_Hash(key); if (hash == -1) return -1; } - ep = (mp->ma_lookup)(mp, key, hash); - if (ep->me_key == NULL || ep->me_key == dummy) + ep = (so->lookup)(so, key, hash); + if (ep->key == NULL || ep->key == dummy) return DISCARD_NOTFOUND; - old_key = ep->me_key; + old_key = ep->key; Py_INCREF(dummy); - ep->me_key = dummy; - mp->ma_used--; + ep->key = dummy; + so->used--; Py_DECREF(old_key); return DISCARD_FOUND; } -static int -set_remove_internal(PySetObject *mp, PyObject *key) -{ - int rv = set_discard_internal(mp, key); - - if (rv == 1) { - PyErr_SetObject(PyExc_KeyError, key); - return -1; - } - return rv; -} - static void -set_clear_internal(PySetObject *mp) +set_clear_internal(PySetObject *so) { setentry *ep, *table; int table_is_malloced; @@ -413,15 +389,15 @@ int i, n; #endif - assert (PyAnySet_Check(mp)); + assert (PyAnySet_Check(so)); #ifdef Py_DEBUG - n = mp->ma_mask + 1; + n = so->mask + 1; i = 0; #endif - table = mp->ma_table; + table = so->table; assert(table != NULL); - table_is_malloced = table != mp->ma_smalltable; + table_is_malloced = table != so->smalltable; /* This is delicate. During the process of clearing the set, * decrefs can cause the set to mutate. To avoid fatal confusion @@ -429,9 +405,9 @@ * clearing the slots, and never refer to anything via mp->ref while * clearing. */ - fill = mp->ma_fill; + fill = so->fill; if (table_is_malloced) - EMPTY_TO_MINSIZE(mp); + EMPTY_TO_MINSIZE(so); else if (fill > 0) { /* It's a small table with something that needs to be cleared. @@ -440,7 +416,7 @@ */ memcpy(small_copy, table, sizeof(small_copy)); table = small_copy; - EMPTY_TO_MINSIZE(mp); + EMPTY_TO_MINSIZE(so); } /* else it's a small table that's already empty */ @@ -453,13 +429,13 @@ assert(i < n); ++i; #endif - if (ep->me_key) { + if (ep->key) { --fill; - Py_DECREF(ep->me_key); + Py_DECREF(ep->key); } #ifdef Py_DEBUG else - assert(ep->me_key == NULL || ep->me_key == dummy); + assert(ep->key == NULL || ep->key == dummy); #endif } @@ -481,67 +457,64 @@ * mutates the table. */ static int -set_next_internal(PySetObject *mp, int *ppos, PyObject **pkey) +set_next_internal(PySetObject *so, int *ppos, PyObject **pkey) { register int i, mask; register setentry *ep; - assert (PyAnySet_Check(mp)); + assert (PyAnySet_Check(so)); i = *ppos; if (i < 0) return 0; - ep = mp->ma_table; - mask = mp->ma_mask; - while (i <= mask && (ep[i].me_key == NULL || ep[i].me_key == dummy)) + ep = so->table; + mask = so->mask; + while (i <= mask && (ep[i].key == NULL || ep[i].key == dummy)) i++; *ppos = i+1; if (i > mask) return 0; if (pkey) - *pkey = ep[i].me_key; + *pkey = ep[i].key; return 1; } /* Methods */ static int -set_merge_internal(PySetObject *mp, PyObject *b) +set_merge_internal(PySetObject *so, PyObject *b) { register PySetObject *other; register int i; setentry *entry; - assert (PyAnySet_Check(mp)); + assert (PyAnySet_Check(so)); assert (PyAnySet_Check(b)); other = (setobject*)b; - if (other == mp || other->ma_used == 0) + if (other == so || other->used == 0) /* a.update(a) or a.update({}); nothing to do */ return 0; /* Do one big resize at the start, rather than * incrementally resizing as we insert new items. Expect * that there will be no (or few) overlapping keys. */ - if ((mp->ma_fill + other->ma_used)*3 >= (mp->ma_mask+1)*2) { - if (set_table_resize(mp, (mp->ma_used + other->ma_used)*2) != 0) + if ((so->fill + other->used)*3 >= (so->mask+1)*2) { + if (set_table_resize(so, (so->used + other->used)*2) != 0) return -1; } - for (i = 0; i <= other->ma_mask; i++) { - entry = &other->ma_table[i]; - if (entry->me_key != NULL && - entry->me_key != dummy) { - Py_INCREF(entry->me_key); - set_insert_key(mp, entry->me_key, entry->me_hash); + for (i = 0; i <= other->mask; i++) { + entry = &other->table[i]; + if (entry->key != NULL && + entry->key != dummy) { + Py_INCREF(entry->key); + set_insert_key(so, entry->key, entry->hash); } } return 0; } -static PyTypeObject PysetiterKey_Type; /* Forward */ -static PyObject *set_iter(setobject *); - static int -set_contains_internal(PySetObject *mp, PyObject *key) +set_contains_internal(PySetObject *so, PyObject *key) { long hash; @@ -551,51 +524,49 @@ if (hash == -1) return -1; } - key = (mp->ma_lookup)(mp, key, hash)->me_key; + key = (so->lookup)(so, key, hash)->key; return key != NULL && key != dummy; } +static PyTypeObject PySetIter_Type; /* Forward */ +static PyObject *set_iter(setobject *); /* Set iterator types */ typedef struct { PyObject_HEAD - setobject *di_set; /* Set to NULL when iterator is exhausted */ - int di_used; - int di_pos; - PyObject* di_result; /* reusable result tuple for iteritems */ + setobject *si_set; /* Set to NULL when iterator is exhausted */ + int si_used; + int si_pos; long len; } setiterobject; static PyObject * set_iter(setobject *so) { - setiterobject *di; - di = PyObject_New(setiterobject, &PysetiterKey_Type); - if (di == NULL) + setiterobject *si = PyObject_New(setiterobject, &PySetIter_Type); + if (si == NULL) return NULL; Py_INCREF(so); - di->di_set = so; - di->di_used = so->ma_used; - di->di_pos = 0; - di->len = so->ma_used; - di->di_result = NULL; - return (PyObject *)di; + si->si_set = so; + si->si_used = so->used; + si->si_pos = 0; + si->len = so->used; + return (PyObject *)si; } static void -setiter_dealloc(setiterobject *di) +setiter_dealloc(setiterobject *si) { - Py_XDECREF(di->di_set); - Py_XDECREF(di->di_result); - PyObject_Del(di); + Py_XDECREF(si->si_set); + PyObject_Del(si); } static int -setiter_len(setiterobject *di) +setiter_len(setiterobject *si) { - if (di->di_set != NULL && di->di_used == di->di_set->ma_used) - return di->len; + if (si->si_set != NULL && si->si_used == si->si_set->used) + return si->len; return 0; } @@ -604,49 +575,49 @@ 0, /* sq_concat */ }; -static PyObject *setiter_iternextkey(setiterobject *di) +static PyObject *setiter_iternextkey(setiterobject *si) { PyObject *key; register int i, mask; register setentry *ep; - setobject *d = di->di_set; + setobject *d = si->si_set; if (d == NULL) return NULL; assert (PyAnySet_Check(d)); - if (di->di_used != d->ma_used) { + if (si->si_used != d->used) { PyErr_SetString(PyExc_RuntimeError, "Set changed size during iteration"); - di->di_used = -1; /* Make this state sticky */ + si->si_used = -1; /* Make this state sticky */ return NULL; } - i = di->di_pos; + i = si->si_pos; if (i < 0) goto fail; - ep = d->ma_table; - mask = d->ma_mask; - while (i <= mask && (ep[i].me_key == NULL || ep[i].me_key == dummy)) + ep = d->table; + mask = d->mask; + while (i <= mask && (ep[i].key == NULL || ep[i].key == dummy)) i++; - di->di_pos = i+1; + si->si_pos = i+1; if (i > mask) goto fail; - di->len--; - key = ep[i].me_key; + si->len--; + key = ep[i].key; Py_INCREF(key); return key; fail: Py_DECREF(d); - di->di_set = NULL; + si->si_set = NULL; return NULL; } -PyTypeObject PysetiterKey_Type = { +PyTypeObject PySetIter_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ - "Set-keyiterator", /* tp_name */ + "Set-keyiterator", /* tp_name */ sizeof(setiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -748,8 +719,7 @@ return NULL; EMPTY_TO_MINSIZE(so); - so->ma_lookup = set_lookkey_string; - //_PyObject_GC_TRACK(so); + so->lookup = set_lookkey_string; so->hash = -1; so->weakreflist = NULL; @@ -762,7 +732,6 @@ Py_DECREF(tmp); } - assert (so->hash == -1); return (PyObject *)so; } @@ -790,21 +759,21 @@ set_dealloc(PySetObject *so) { register setentry *ep; - int fill = so->ma_fill; + int fill = so->fill; PyObject_GC_UnTrack(so); Py_TRASHCAN_SAFE_BEGIN(so) if (so->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) so); - for (ep = so->ma_table; fill > 0; ep++) { - if (ep->me_key) { + for (ep = so->table; fill > 0; ep++) { + if (ep->key) { --fill; - Py_DECREF(ep->me_key); + Py_DECREF(ep->key); } } - if (so->ma_table != so->ma_smalltable) - PyMem_DEL(so->ma_table); + if (so->table != so->smalltable) + PyMem_DEL(so->table); so->ob_type->tp_free(so); Py_TRASHCAN_SAFE_END(so) @@ -813,21 +782,18 @@ static int set_traverse(PySetObject *so, visitproc visit, void *arg) { - int i = 0, err; + int i = 0; PyObject *pk; - while (set_next_internal(so, &i, &pk)) { - err = visit(pk, arg); - if (err) - return err; - } + while (set_next_internal(so, &i, &pk)) + Py_VISIT(pk); return 0; } static int set_len(PyObject *so) { - return ((PySetObject *)so)->ma_used; + return ((PySetObject *)so)->used; } static void @@ -835,28 +801,28 @@ { int t; PySetEntry *u; - PySetEntry *(*f)(PySetObject *mp, PyObject *key, long hash); + PySetEntry *(*f)(PySetObject *so, PyObject *key, long hash); PySetEntry tab[PySet_MINSIZE]; long h; - t = a->ma_fill; a->ma_fill = b->ma_fill; b->ma_fill = t; - t = a->ma_used; a->ma_used = b->ma_used; b->ma_used = t; - t = a->ma_mask; a->ma_mask = b->ma_mask; b->ma_mask = t; + t = a->fill; a->fill = b->fill; b->fill = t; + t = a->used; a->used = b->used; b->used = t; + t = a->mask; a->mask = b->mask; b->mask = t; - u = a->ma_table; - if (a->ma_table == a->ma_smalltable) - u = b->ma_smalltable; - a->ma_table = b->ma_table; - if (b->ma_table == b->ma_smalltable) - a->ma_table = a->ma_smalltable; - b->ma_table = u; + u = a->table; + if (a->table == a->smalltable) + u = b->smalltable; + a->table = b->table; + if (b->table == b->smalltable) + a->table = a->smalltable; + b->table = u; - f = a->ma_lookup; a->ma_lookup = b->ma_lookup; b->ma_lookup = f; + f = a->lookup; a->lookup = b->lookup; b->lookup = f; - if (a->ma_table == a->ma_smalltable || b->ma_table == b->ma_smalltable) { - memcpy(tab, a->ma_smalltable, sizeof(tab)); - memcpy(a->ma_smalltable, b->ma_smalltable, sizeof(tab)); - memcpy(b->ma_smalltable, tab, sizeof(tab)); + if (a->table == a->smalltable || b->table == b->smalltable) { + memcpy(tab, a->smalltable, sizeof(tab)); + memcpy(a->smalltable, b->smalltable, sizeof(tab)); + memcpy(b->smalltable, tab, sizeof(tab)); } h = a->hash; a->hash = b->hash; b->hash = h; @@ -1466,6 +1432,7 @@ set_remove(PySetObject *so, PyObject *item) { PyObject *tmp, *result; + int rv; if (PyType_IsSubtype(item->ob_type, &PySet_Type)) { tmp = make_new_set(&PyFrozenSet_Type, NULL); @@ -1478,8 +1445,13 @@ return result; } - if (set_remove_internal(so, item) == -1) + rv = set_discard_internal(so, item); + if (rv == -1) + return NULL; + else if (rv == DISCARD_NOTFOUND) { + PyErr_SetObject(PyExc_KeyError, item); return NULL; + } Py_RETURN_NONE; } @@ -1519,14 +1491,21 @@ { PyObject *key; int pos = 0; + int rv; if (!set_next_internal(so, &pos, &key)) { PyErr_SetString(PyExc_KeyError, "pop from an empty set"); return NULL; } Py_INCREF(key); - if (set_remove_internal(so, key) == -1) { + + rv = set_discard_internal(so, key); + if (rv == -1) { + Py_DECREF(key); + return NULL; + } else if (rv == DISCARD_NOTFOUND) { Py_DECREF(key); + PyErr_SetObject(PyExc_KeyError, key); return NULL; } return key; Index: setobject.h =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- setobject.h 22 Jul 2005 15:32:30 -0000 1.1 +++ setobject.h 30 Jul 2005 21:07:28 -0000 1.2 @@ -10,16 +10,16 @@ /* There are three kinds of slots in the table: -1. Unused: me_key == NULL -2. Active: me_key != NULL and me_key != dummy -3. Dummy: me_key == dummy +1. Unused: key == NULL +2. Active: key != NULL and key != dummy +3. Dummy: key == dummy */ #define PySet_MINSIZE 8 typedef struct { - long me_hash; /* cached hash code of me_key */ - PyObject *me_key; + long hash; /* cached hash code for the entry key */ + PyObject *key; } PySetEntry; @@ -31,23 +31,23 @@ struct _setobject { PyObject_HEAD - int ma_fill; /* # Active + # Dummy */ - int ma_used; /* # Active */ + int fill; /* # Active + # Dummy */ + int used; /* # Active */ - /* The table contains ma_mask + 1 slots, and that's a power of 2. + /* The table contains mask + 1 slots, and that's a power of 2. * We store the mask instead of the size because the mask is more * frequently needed. */ - int ma_mask; + int mask; - /* ma_table points to ma_smalltable for small tables, else to - * additional malloc'ed memory. ma_table is never NULL! This rule + /* table points to smalltable for small tables, else to + * additional malloc'ed memory. table is never NULL! This rule * saves repeated runtime null-tests in the workhorse getitem and * setitem calls. */ - PySetEntry *ma_table; - PySetEntry *(*ma_lookup)(PySetObject *mp, PyObject *key, long hash); - PySetEntry ma_smalltable[PySet_MINSIZE]; + PySetEntry *table; + PySetEntry *(*lookup)(PySetObject *so, PyObject *key, long hash); + PySetEntry smalltable[PySet_MINSIZE]; long hash; /* only used by frozenset objects */ PyObject *weakreflist; /* List of weak references */ From rhettinger at users.sourceforge.net Sun Jul 31 00:21:12 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 15:21:12 -0700 Subject: [Python-checkins] python/nondist/sandbox/set setobject.c, 1.7, 1.8 setobject.h, 1.2, 1.3 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/set In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26909 Modified Files: setobject.c setobject.h Log Message: More cleanups. * Remove unnecessary typedefs and forward declarations. * Make the empty frozenset a singleton * Eliminate C++ style comments Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- setobject.c 30 Jul 2005 21:07:28 -0000 1.7 +++ setobject.c 30 Jul 2005 22:21:09 -0000 1.8 @@ -5,18 +5,11 @@ #include "Python.h" -typedef PySetEntry setentry; -typedef PySetObject setobject; - /* This must be >= 1. */ #define PERTURB_SHIFT 5 /* Object used as dummy key to fill deleted entries */ -static PyObject *dummy; /* Initialized by first call to newsetobject() */ - -/* forward declarations */ -static setentry * -set_lookkey_string(setobject *so, PyObject *key, long hash); +static PyObject *dummy; /* Initialized by first call to make_new_set() */ #define EMPTY_TO_MINSIZE(so) do { \ memset((so)->smalltable, 0, sizeof((so)->smalltable)); \ @@ -43,7 +36,7 @@ */ static setentry * -set_lookkey(setobject *so, PyObject *key, register long hash) +set_lookkey(PySetObject *so, PyObject *key, register long hash) { register int i; register unsigned int perturb; @@ -83,9 +76,7 @@ } else { /* The compare did major nasty stuff to the - * xx: start over. - * XXX A clever adversary could prevent this - * XXX from terminating. + * set: start over. */ ep = set_lookkey(so, key, hash); goto Done; @@ -125,9 +116,7 @@ } else { /* The compare did major nasty stuff to the - * xx: start over. - * XXX A clever adversary could prevent this - * XXX from terminating. + * set: start over. */ ep = set_lookkey(so, key, hash); break; @@ -154,7 +143,7 @@ * expensive, and sets with pure-string keys may be very common. */ static setentry * -set_lookkey_string(setobject *so, PyObject *key, register long hash) +set_lookkey_string(PySetObject *so, PyObject *key, register long hash) { register int i; register unsigned int perturb; @@ -206,10 +195,10 @@ Eats a reference to key. */ static void -set_insert_key(register setobject *so, PyObject *key, long hash) +set_insert_key(register PySetObject *so, PyObject *key, long hash) { register setentry *ep; - typedef PySetEntry *(*lookupfunc)(PySetObject *, PyObject *, long); + typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long); assert(so->lookup != NULL); @@ -222,10 +211,10 @@ so->used++; } else if (ep->key == dummy) { /* DUMMY */ - Py_DECREF(dummy); ep->key = key; ep->hash = hash; so->used++; + Py_DECREF(dummy); } else { /* ACTIVE */ Py_DECREF(key); @@ -238,7 +227,7 @@ actually be smaller than the old one. */ static int -set_table_resize(setobject *so, int minused) +set_table_resize(PySetObject *so, int minused) { int newsize; setentry *oldtable, *newtable, *ep; @@ -303,15 +292,15 @@ dummy entries aren't copied over, of course */ for (ep = oldtable; i > 0; ep++) { if (ep->key == NULL) { - // UNUSED + /* UNUSED */ ; } else if (ep->key == dummy) { - // DUMMY + /* DUMMY */ --i; assert(ep->key == dummy); Py_DECREF(ep->key); } else { - // ACTIVE + /* ACTIVE */ --i; set_insert_key(so, ep->key, ep->hash); } @@ -350,8 +339,8 @@ return set_table_resize(so, so->used*(so->used>50000 ? 2 : 4)); } -#define DISCARD_FOUND 0 -#define DISCARD_NOTFOUND 1 +#define DISCARD_NOTFOUND 0 +#define DISCARD_FOUND 1 static int set_discard_internal(PySetObject *so, PyObject *key) @@ -490,7 +479,7 @@ assert (PyAnySet_Check(so)); assert (PyAnySet_Check(b)); - other = (setobject*)b; + other = (PySetObject*)b; if (other == so || other->used == 0) /* a.update(a) or a.update({}); nothing to do */ return 0; @@ -529,20 +518,19 @@ } static PyTypeObject PySetIter_Type; /* Forward */ -static PyObject *set_iter(setobject *); /* Set iterator types */ typedef struct { PyObject_HEAD - setobject *si_set; /* Set to NULL when iterator is exhausted */ + PySetObject *si_set; /* Set to NULL when iterator is exhausted */ int si_used; int si_pos; long len; } setiterobject; static PyObject * -set_iter(setobject *so) +set_iter(PySetObject *so) { setiterobject *si = PyObject_New(setiterobject, &PySetIter_Type); if (si == NULL) @@ -580,7 +568,7 @@ PyObject *key; register int i, mask; register setentry *ep; - setobject *d = si->si_set; + PySetObject *d = si->si_set; if (d == NULL) return NULL; @@ -646,7 +634,7 @@ (iternextfunc)setiter_iternextkey, /* tp_iternext */ }; -/***** Derived functions (table accesses only done thru above primitives *****/ +/***** Derived functions (table accesses only done with above primitives *****/ #include "structmember.h" @@ -739,10 +727,19 @@ frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *iterable = NULL; + static PyObject *emptyfrozenset = NULL; if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) return NULL; - if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) { + if (iterable == NULL) { + if (type == &PyFrozenSet_Type) { + if (emptyfrozenset == NULL) + emptyfrozenset = make_new_set(type, NULL); + else + Py_INCREF(emptyfrozenset); + return emptyfrozenset; + } + } else if (PyFrozenSet_CheckExact(iterable)) { Py_INCREF(iterable); return iterable; } @@ -800,9 +797,9 @@ set_swap_bodies(PySetObject *a, PySetObject *b) { int t; - PySetEntry *u; - PySetEntry *(*f)(PySetObject *so, PyObject *key, long hash); - PySetEntry tab[PySet_MINSIZE]; + setentry *u; + setentry *(*f)(PySetObject *so, PyObject *key, long hash); + setentry tab[PySet_MINSIZE]; long h; t = a->fill; a->fill = b->fill; b->fill = t; Index: setobject.h =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- setobject.h 30 Jul 2005 21:07:28 -0000 1.2 +++ setobject.h 30 Jul 2005 22:21:10 -0000 1.3 @@ -20,7 +20,7 @@ typedef struct { long hash; /* cached hash code for the entry key */ PyObject *key; -} PySetEntry; +} setentry; /* @@ -45,9 +45,9 @@ * saves repeated runtime null-tests in the workhorse getitem and * setitem calls. */ - PySetEntry *table; - PySetEntry *(*lookup)(PySetObject *so, PyObject *key, long hash); - PySetEntry smalltable[PySet_MINSIZE]; + setentry *table; + setentry *(*lookup)(PySetObject *so, PyObject *key, long hash); + setentry smalltable[PySet_MINSIZE]; long hash; /* only used by frozenset objects */ PyObject *weakreflist; /* List of weak references */ From gregorykjohnson at users.sourceforge.net Sun Jul 31 00:49:27 2005 From: gregorykjohnson at users.sourceforge.net (gregorykjohnson@users.sourceforge.net) Date: Sat, 30 Jul 2005 15:49:27 -0700 Subject: [Python-checkins] python/nondist/sandbox/mailbox mailbox.py, 1.1, 1.2 libmailbox.tex, 1.2, 1.3 test_mailbox.py, 1.1, 1.2 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/mailbox In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31617 Modified Files: mailbox.py libmailbox.tex test_mailbox.py Log Message: * Implement all Message subclasses, including conversion. * Fix handling of new-ness by Maildir: let subdir and info vary orthogonally (so flags can be added to messages in "new"). The spec doesn't disallow this, and some implementations do so. * Miscellaneous documentation and code enhancements. Index: mailbox.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/mailbox.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- mailbox.py 26 Jul 2005 20:47:46 -0000 1.1 +++ mailbox.py 30 Jul 2005 22:49:08 -0000 1.2 @@ -191,9 +191,9 @@ Mailbox.__init__(self, dirname, factory) if not os.path.exists(self._path): os.mkdir(self._path, 0700) - os.mkdir(os.path.join(self._path, "tmp"), 0700) - os.mkdir(os.path.join(self._path, "new"), 0700) - os.mkdir(os.path.join(self._path, "cur"), 0700) + os.mkdir(os.path.join(self._path, 'tmp'), 0700) + os.mkdir(os.path.join(self._path, 'new'), 0700) + os.mkdir(os.path.join(self._path, 'cur'), 0700) self._toc = {} def add(self, message): @@ -252,6 +252,7 @@ self.discard(key) os.rename(os.path.join(self._path, temp_subpath), os.path.join(self._path, subdir, key + suffix)) + # XXX: the mtime should be reset to keep delivery date def get_message(self, key): """Return a Message representation or raise a KeyError.""" @@ -262,10 +263,9 @@ finally: f.close() subdir, name = os.path.split(subpath) - if subdir == 'cur': - msg.set_subdir('cur') - if name.find(':') != -1: - msg.set_info(name.split(':')[-1]) + msg.set_subdir(subdir) + if name.find(':') != -1: + msg.set_info(name.split(':')[-1]) return msg def get_string(self, key): @@ -403,6 +403,8 @@ """Initialize a Message instance.""" if isinstance(message, email.Message.Message): self._become_message(copy.deepcopy(message)) + if isinstance(message, Message): + message._explain_to(self) elif isinstance(message, str): self._become_message(email.message_from_string(message)) elif hasattr(message, "read"): @@ -431,11 +433,9 @@ def __init__(self, message=None): """Initialize a MaildirMessage instance.""" - Message.__init__(self, message) self._subdir = 'new' self._info = '' - if isinstance(message, Message): - message._explain_to(self) + Message.__init__(self, message) def get_subdir(self): """Return 'new' or 'cur'.""" @@ -453,21 +453,19 @@ if len(self._info) > 2 and self._info[:2] == '2,': return self._info[2:] else: - return "" + return '' def set_flags(self, flags): """Set the given flags and unset all others.""" - if self.get_subdir() == 'new': - self.set_subdir('cur') self._info = '2,' + ''.join(sorted(flags)) def add_flags(self, flags): - """Set the given flags without changing others.""" + """Set the given flags without changing others.""" self.set_flags(''.join(set(self.get_flags()) | set(flags))) def remove_flags(self, flags): - """Unset the given string flags (if set) without changing other.""" - if self.get_flags() != "": + """Unset the given string flags (if set) without changing others.""" + if self.get_flags() != '': self.set_flags(''.join(set(self.get_flags()) - set(flags))) def get_info(self): @@ -476,8 +474,6 @@ def set_info(self, info): """Set the message's "info" string.""" - if self.get_subdir() == 'new': - self.set_subdir('cur') if isinstance(info, str): self._info = info else: @@ -485,13 +481,307 @@ def _explain_to(self, message): """Copy Maildir-specific state to message insofar as possible.""" - if isinstance(message, Message): - return - # XXX convert to other formats as needed + if isinstance(message, MaildirMessage): + message.set_flags(self.get_flags()) + message.set_subdir(self.get_subdir()) + elif isinstance(message, _mboxMMDFMessage): + flags = set(self.get_flags()) + if 'S' in flags: + message.add_flags('R') + if self.get_subdir() == 'cur': + message.add_flags('O') + if 'T' in flags: + message.add_flags('D') + if 'F' in flags: + message.add_flags('F') + if 'R' in flags: + message.add_flags('A') + elif isinstance(message, MHMessage): + flags = set(self.get_flags()) + if 'S' not in flags: + message.join_sequence('unseen') + if 'R' in flags: + message.join_sequence('replied') + if 'F' in flags: + message.join_sequence('flagged') + elif isinstance(message, BabylMessage): + flags = set(self.get_flags()) + if 'S' not in flags: + message.add_label('unseen') + if 'T' in flags: + message.add_label('deleted') + if 'R' in flags: + message.add_label('answered') + if 'P' in flags: + message.add_label('forwarded') + elif isinstance(message, Message): + pass + else: + raise TypeError, "Cannot convert to specified type" + + +class _mboxMMDFMessage(Message): + """Message with mbox- or MMDF-specific properties.""" + + def __init__(self, message=None): + """Initialize an mboxMMDFMessage instance.""" + self.set_from('MAILER-DAEMON', True) + if isinstance(message, email.Message.Message): + unixfrom = message.get_unixfrom() + if unixfrom is not None and unixfrom[:5] == 'From ': + self.set_from(unixfrom[5:]) + elif 'Return-Path' in message: + # XXX: generate "From " line from Return-Path: and Received: + pass + Message.__init__(self, message) + + def get_from(self): + """Return contents of "From " line.""" + return self._from + + def set_from(self, from_, time_=None): + """Set "From " line, formatting and appending time_ if specified.""" + if time_ is not None: + if time_ is True: + time_ = time.gmtime() + from_ += time.strftime(" %a %b %d %H:%M:%S %Y", time_) + self._from = from_ + + def get_flags(self): + """Return as a string the flags that are set.""" + return self.get('Status', '') + self.get('X-Status', '') + + def set_flags(self, flags): + """Set the given flags and unset all others.""" + flags = set(flags) + status_flags, xstatus_flags = '', '' + for flag in ('R', 'O'): + if flag in flags: + status_flags += flag + flags.remove(flag) + for flag in ('D', 'F', 'A'): + if flag in flags: + xstatus_flags += flag + flags.remove(flag) + xstatus_flags += ''.join(sorted(flags)) + try: + self.replace_header('Status', status_flags) + except KeyError: + self.add_header('Status', status_flags) + try: + self.replace_header('X-Status', xstatus_flags) + except KeyError: + self.add_header('X-Status', xstatus_flags) + + def add_flags(self, flags): + """Set the given flags without changing others.""" + self.set_flags(''.join(set(self.get_flags()) | set(flags))) + + def remove_flags(self, flags): + """Unset the given string flags (if set) without changing others.""" + if 'Status' in self or 'X-Status' in self: + self.set_flags(''.join(set(self.get_flags()) - set(flags))) + + def _explain_to(self, message): + """Copy mbox- or MMDF-specific state to message insofar as possible.""" + if isinstance(message, MaildirMessage): + flags = set(self.get_flags()) + if 'O' in flags: + message.set_subdir('cur') + if 'F' in flags: + message.add_flags('F') + if 'A' in flags: + message.add_flags('R') + if 'R' in flags: + message.add_flags('S') + if 'D' in flags: + message.add_flags('T') + elif isinstance(message, _mboxMMDFMessage): + message.set_flags(self.get_flags()) + message.set_from(self.get_from()) + elif isinstance(message, MHMessage): + flags = set(self.get_flags()) + if 'R' not in flags: + message.join_sequence('unseen') + if 'A' in flags: + message.join_sequence('replied') + if 'F' in flags: + message.join_sequence('flagged') + elif isinstance(message, BabylMessage): + flags = set(self.get_flags()) + if 'R' not in flags: + message.add_label('unseen') + if 'D' in flags: + message.add_label('deleted') + if 'A' in flags: + message.add_label('answered') + elif isinstance(message, Message): + pass + else: + raise TypeError, "Cannot convert to specified type" + + +class mboxMessage(_mboxMMDFMessage): + """Message with mbox-specific properties.""" + + +class MHMessage(Message): + """Message with MH-specific properties.""" + + def __init__(self, message=None): + """Initialize an MHMessage instance.""" + self._sequences = [] + Message.__init__(self, message) + + def list_sequences(self): + """Return a list of sequences that include the message.""" + return self._sequences[:] + + def join_sequence(self, sequence): + """Add sequence to list of sequences including the message.""" + if isinstance(sequence, str): + if not sequence in self._sequences: + self._sequences.append(sequence) + else: + raise TypeError, "sequence must be a string" + + def leave_sequence(self, sequence): + """Remove sequence from the list of sequences including the message.""" + try: + self._sequences.remove(sequence) + except ValueError: + pass + + def _explain_to(self, message): + """Copy MH-specific state to message insofar as possible.""" + if isinstance(message, MaildirMessage): + sequences = set(self.list_sequences()) + if 'unseen' in sequences: + message.set_subdir('cur') + else: + message.set_subdir('cur') + message.add_flags('S') + if 'flagged' in sequences: + message.add_flags('F') + if 'replied' in sequences: + message.add_flags('R') + elif isinstance(message, _mboxMMDFMessage): + sequences = set(self.list_sequences()) + if 'unseen' not in sequences: + message.add_flags('RO') + else: + message.add_flags('O') + if 'flagged' in sequences: + message.add_flags('F') + if 'replied' in sequences: + message.add_flags('A') + elif isinstance(message, MHMessage): + for sequence in self.list_sequences(): + message.join_sequence(sequence) + elif isinstance(message, BabylMessage): + sequences = set(self.list_sequences()) + if 'unseen' in sequences: + message.add_label('unseen') + if 'replied' in sequences: + message.add_label('answered') + elif isinstance(message, Message): + pass + else: + raise TypeError, "Cannot convert to specified type" + + +class BabylMessage(Message): + """Message with Babyl-specific properties.""" + + def __init__(self, message=None): + """Initialize an BabylMessage instance.""" + self._labels = [] + self._visible = Message() + Message.__init__(self, message) + + def list_labels(self): + """Return a list of labels on the message.""" + return self._labels[:] + + def add_label(self, label): + """Add label to list of labels on the message.""" + if isinstance(label, str): + if label not in self._labels: + self._labels.append(label) + else: + raise TypeError, "label must be a string" + + def remove_label(self, label): + """Remove label from the list of labels on the message.""" + try: + self._labels.remove(label) + except ValueError: + pass + + def get_visible(self): + """Return a Message representation of visible headers.""" + return Message(self._visible) + + def set_visible(self, visible): + """Set the Message representation of visible headers.""" + self._visible = Message(visible) + + def update_visible(self): + """Update and/or sensibly generate a set of visible headers.""" + for header in self._visible.keys(): + if header in self: + self._visible.replace_header(header, self[header]) + else: + del self._visible[header] + for header in ('Date', 'From', 'Reply-To', 'To', 'CC', 'Subject'): + if header in self and header not in self._visible: + self._visible[header] = self[header] + + def _explain_to(self, message): + """Copy Babyl-specific state to message insofar as possible.""" + if isinstance(message, MaildirMessage): + labels = set(self.list_labels()) + if 'unseen' in labels: + message.set_subdir('cur') + else: + message.set_subdir('cur') + message.add_flags('S') + if 'forwarded' in labels or 'resent' in labels: + message.add_flags('P') + if 'answered' in labels: + message.add_flags('R') + if 'deleted' in labels: + message.add_flags('T') + elif isinstance(message, _mboxMMDFMessage): + labels = set(self.list_labels()) + if 'unseen' not in labels: + message.add_flags('RO') + else: + message.add_flags('O') + if 'deleted' in labels: + message.add_flags('D') + if 'answered' in labels: + message.add_flags('A') + elif isinstance(message, MHMessage): + labels = set(self.list_labels()) + if 'unseen' in labels: + message.join_sequence('unseen') + if 'answered' in labels: + message.join_sequence('replied') + elif isinstance(message, BabylMessage): + message.set_visible(self.get_visible()) + for label in self.list_labels(): + message.add_label(label) + elif isinstance(message, Message): + pass else: raise TypeError, "Cannot convert to specified type" +class MMDFMessage(_mboxMMDFMessage): + """Message with MMDF-specific properties.""" + + class _ProxyFile: """A read-only wrapper of a file.""" Index: libmailbox.tex =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/libmailbox.tex,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- libmailbox.tex 26 Jul 2005 20:47:48 -0000 1.2 +++ libmailbox.tex 30 Jul 2005 22:49:08 -0000 1.3 @@ -29,7 +29,6 @@ in a mailbox, the modified message representation must be explicitly assigned back into the \class{Mailbox} instance's mapping. - \begin{seealso} \seemodule{email}{Represent and manipulate messages.} \seemodule{poplib}{Access mail via POP3.} @@ -37,12 +36,11 @@ \seemodule{smtplib}{Transfer mail via SMTP.} \end{seealso} - \subsection{\class{Mailbox} objects} \label{mailbox-objects} \begin{classdesc*}{Mailbox} -Represents a mailbox, which may be inspected and modified. +A mailbox, which may be inspected and modified. \end{classdesc*} The \class{Mailbox} interface is dictionary-like, with small keys @@ -107,7 +105,7 @@ \class{Mailbox} instances have the following methods: -\begin{methoddesc}[Mailbox]{add}{message} +\begin{methoddesc}{add}{message} Add \var{message} to the mailbox and return the key that has been assigned to it. @@ -119,7 +117,7 @@ Otherwise, reasonable defaults for format-specific information are used. \end{methoddesc} -\begin{methoddesc}[Mailbox]{remove}{key} +\begin{methoddesc}{remove}{key} \methodline{__delitem__}{key} \methodline{discard}{key} Delete the message corresponding to \var{key} from the mailbox. @@ -131,7 +129,7 @@ format supports concurrent modification by other processes. \end{methoddesc} -\begin{methoddesc}[Mailbox]{__setitem__}{key, message} +\begin{methoddesc}{__setitem__}{key, message} Replace the message corresponding to \var{key} with the message represented by \var{message}. Raise a \exception{KeyError} exception if no message already corresponds to \var{key}. @@ -145,13 +143,13 @@ corresponds to \var{key} is left unchanged. \end{methoddesc} -\begin{methoddesc}[Mailbox]{iterkeys}{} +\begin{methoddesc}{iterkeys}{} \methodline{keys}{} Return an iterator over all keys if called as \method{iterkeys()} or return a list of keys if called as \method{keys()}. \end{methoddesc} -\begin{methoddesc}[Mailbox]{itervalues}{} +\begin{methoddesc}{itervalues}{} \methodline{__iter__}{} \methodline{values}{} Return an iterator over representations of all messages if called as @@ -162,7 +160,7 @@ \method{__iter__()} is unlike that of dictionaries, which iterate over keys.} \end{methoddesc} -\begin{methoddesc}[Mailbox]{iteritems}{} +\begin{methoddesc}{iteritems}{} \methodline{items}{} Return an iterator over (\var{key}, \var{message}) pairs, where \var{key} is a key and \var{message} is a message representation, if called as @@ -172,7 +170,7 @@ was initialized. \end{methoddesc} -\begin{methoddesc}[Mailbox]{get}{key\optional{, default=None}} +\begin{methoddesc}{get}{key\optional{, default=None}} \methodline{__getitem__}{key} Return a representation of the message corresponding to \var{key}. If no such message exists, \var{default} is returned if the method was called as @@ -182,18 +180,18 @@ \class{Mailbox} instance was initialized. \end{methoddesc} -\begin{methoddesc}[Mailbox]{get_message}{key} +\begin{methoddesc}{get_message}{key} Return a \class{Message} representation of the message corresponding to \var{key}, or raise a \exception{KeyError} exception if no such message exists. \end{methoddesc} -\begin{methoddesc}[Mailbox]{get_string}{key} +\begin{methoddesc}{get_string}{key} Return a string representation of the message corresponding to \var{key}, or raise a \exception{KeyError} exception if no such message exists. \end{methoddesc} -\begin{methoddesc}[Mailbox]{get_file}{key} +\begin{methoddesc}{get_file}{key} Return a file-like representation of the message corresponding to \var{key}, or raise a \exception{KeyError} exception if no such message exists. This file should be closed once it is no longer needed. @@ -204,21 +202,21 @@ More specific documentation is provided by each subclass.} \end{methoddesc} -\begin{methoddesc}[Mailbox]{has_key}{key} +\begin{methoddesc}{has_key}{key} \methodline{__contains__}{} Return \code{True} if \var{key} corresponds to a message, \code{False} otherwise. \end{methoddesc} -\begin{methoddesc}[Mailbox]{__len__}{} +\begin{methoddesc}{__len__}{} Return a count of messages in the mailbox. \end{methoddesc} -\begin{methoddesc}[Mailbox]{clear}{} +\begin{methoddesc}{clear}{} Delete all messages from the mailbox. \end{methoddesc} -\begin{methoddesc}[Mailbox]{pop}{key\optional{, default}} +\begin{methoddesc}{pop}{key\optional{, default}} Return a representation of the message corresponding to \var{key} and delete the message. If no such message exists, return \var{default} if it was supplied or else raise a \exception{KeyError} exception. The message is represented as a @@ -226,7 +224,7 @@ \class{Mailbox} instance was initialized. \end{methoddesc} -\begin{methoddesc}[Mailbox]{popitem}{} +\begin{methoddesc}{popitem}{} Return an arbitrary (\var{key}, \var{message}) pair, where \var{key} is a key and \var{message} is a message representation, and delete the corresponding message. If the mailbox is empty, raise a \exception{KeyError} exception. The @@ -234,7 +232,7 @@ factory was specified when the \class{Mailbox} instance was initialized. \end{methoddesc} -\begin{methoddesc}[Mailbox]{update}{arg} +\begin{methoddesc}{update}{arg} Parameter \var{arg} should be a \var{key}-to-\var{message} mapping or an iterable of (\var{key}, \var{message}) pairs. Updates the mailbox so that, for each given \var{key} and \var{message}, the message corresponding to \var{key} @@ -244,7 +242,7 @@ are not supported.} \end{methoddesc} -\begin{methoddesc}[Mailbox]{flush}{} +\begin{methoddesc}{flush}{} Write any pending changes to the filesystem. For some \class{Mailbox} subclasses, this is done automatically and calling \method{flush()} has no effect. More specific documentation is provided by each subclass. @@ -277,23 +275,23 @@ \class{Maildir} instances have all of the methods of \class{Mailbox} in addition to the following: -\begin{methoddesc}[Maildir]{list_folders}{} +\begin{methoddesc}{list_folders}{} Return a list of the names of all folders. If there are no folders, the empty list is returned. \end{methoddesc} -\begin{methoddesc}[Maildir]{open_folder}{name} +\begin{methoddesc}{open_folder}{name} Return a \class{Maildir} instance representing the folder whose name is \var{name}. The folder will be created if it does not exist. \end{methoddesc} -\begin{methoddesc}[Maildir]{remove_folder}{name} +\begin{methoddesc}{remove_folder}{name} Delete the folder whose name is \var{name}. If the folder contains any messages, an \exception{IOError} exception will be raised and the folder will not be deleted. \end{methoddesc} -\begin{methoddesc}[Maildir]{clean}{} +\begin{methoddesc}{clean}{} Delete temporary files from the mailbox that have not been accessed in the last 36 hours. The Maildir specification says that mail-reading programs should do this occassionally. @@ -307,9 +305,9 @@ simultaneously.} Some \class{Mailbox} methods implemented by \class{Maildir} deserve special -remarks: +remarks: -\begin{methoddesc}[Maildir]{add}{message} +\begin{methoddesc}{add}{message} \methodline[Maildir]{__setitem__}{key, message} \methodline[Maildir]{update}{arg} \warning{These methods generate unique file names based upon the current @@ -318,12 +316,12 @@ these methods to manipulate the same mailbox simultaneously.} \end{methoddesc} -\begin{methoddesc}[Maildir]{flush}{} +\begin{methoddesc}{flush}{} All changes to Maildir mailboxes are immediately applied. This method does nothing. \end{methoddesc} -\begin{methoddesc}[Maildir]{get_file}{key} +\begin{methoddesc}{get_file}{key} Depending upon the host platform, it may not be possible to use a \class{Maildir} instance to modify or remove the underlying message while the returned file remains open. @@ -343,18 +341,205 @@ \subsubsection{\class{mbox}} \label{mailbox-mbox} +\begin{classdesc}{mbox}{path\optional{, factory}} +A subclass of \class{Mailbox} for mailboxes in mbox format. Parameters +\var{path} and \var{factory} has the same meaning as with the module-level +\method{open()} function. +\end{classdesc} + +The mbox format is the classic format for storing mail on \UNIX{} systems. All +messages in an mbox mailbox are stored in a single file with the beginning of +each message indicated by a line whose first five characters are "From~". +Several variations of the mbox format exist to address perceived shortcomings. +In the interest of compatibility, \class{mbox} implements the original format, +which is sometimes referred to as \dfn{mboxo}. This means that the +\mailheader{Content-Length} header, if present, is ignored and that any +occurrences of "From~" at the beginning of a line in a message body are +transformed to ">From~" when storing the message although occurences of +">From~" are not transformed to "From~" when reading the message. + +Some \class{Mailbox} methods implemented by \class{mbox} deserve special +remarks: + +\begin{methoddesc}{get_file}{key} +XXX +\end{methoddesc} + +\begin{seealso} + \seelink{http://www.qmail.org/man/man5/mbox.html}{mbox man page from + qmail}{A specification of the format and its variations.} + \seelink{http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html} + {Configuring Netscape Mail on \UNIX{}: Why The Content-Length Format is + Bad}{An argument for using the original mbox format rather than a + variation.} + \seelink{http://homepages.tesco.net./\tilde{}J.deBoynePollard/FGA/mail-mbox-formats.html} + {"mbox" is a family of several mutually incompatible mailbox formats}{A + history of mbox variations.} +\end{seealso} \subsubsection{\class{MH}} \label{mailbox-mh} +\begin{classdesc}{MH}{path\optional{, factory}} +A subclass of \class{Mailbox} for mailboxes in MH format. Parameters \var{path} +and \var{factory} has the same meaning as with the module-level \method{open()} +function. +\end{classdesc} + +MH is a directory-based mailbox format invented for the MH Message Handling +System, a mail reading application. Each message in an MH mailbox resides in +its own file. An MH mailbox may contain other MH mailboxes (called +\dfn{folders}) in addition to messages. Folders may be nested indefinitely. + +MH mailboxes support \dfn{sequences}, which are named lists used to logically +group messages without moving them to sub-folders. Some mail reading programs +(although not the standard \program{mh} and \program{nmh} implementations) use +sequences to the same end as flags are used in other formats: unread messages +are added to the "unseen" sequence, replied-to messages are added to the +"replied" sequence, and important messages are added upon request to the +"flagged" sequence. + +\class{MH} instances have all of the methods of \class{Mailbox} in addition to +the following: + +\begin{methoddesc}{list_folders}{} +Return a list of the names of all folders. If there are no folders, the empty +list is returned. +\end{methoddesc} + +\begin{methoddesc}{open_folder}{name} +Return an \class{MH} instance representing the folder whose name is \var{name}. +The folder will be created if it does not exist. +\end{methoddesc} + +\begin{methoddesc}{remove_folder}{name} +Delete the folder whose name is \var{name}. If the folder contains any +messages, an \exception{IOError} exception will be raised and the folder will +not be deleted. +\end{methoddesc} + +\begin{methoddesc}{list_sequences}{} +Return a list of the names of sequences defined in the mailbox. If there are no +sequences, the empty list is returned. +\end{methoddesc} + +\begin{methoddesc}{get_sequence}{name} +Return a list of keys in sequence \var{name}. +\end{methoddesc} + +\begin{methoddesc}{set_sequence}{name, value} +Set to \var{value} the list of keys in sequence \var{name}. The sequence will +be created if it does not exist. If \var{value} is the empty list, sequence +\var{name} will be removed. +\end{methoddesc} + +\begin{methoddesc}{pack}{} +Renames messages in the mailbox as necessary to eliminate gaps in numbering. +Already-issued keys are invalidated by this operation. +\end{methoddesc} + +Some \class{Mailbox} methods implemented by \class{MH} deserve special remarks: + +\begin{methoddesc}{remove}{key} +\methodline{__delitem__}{key} +\methodline{discard}{key} +These methods immediately delete the message. The \program{mh} convention of +marking a message for deletion by prepending a comma to its name is not used. +\end{methoddesc} + +\begin{methoddesc}{get_file}{key} +XXX +\end{methoddesc} + +\begin{methoddesc}{flush}{} +All changes to MH mailboxes are immediately applied. This method does nothing. +\end{methoddesc} + +\begin{classdesc}{MH}{path\optional{, factory}} +A subclass of \class{Mailbox} for mailboxes in MH format. Parameters \var{path} +and \var{factory} has the same meaning as with the module-level \method{open()} +function. +\end{classdesc} + +\class{MH} instances have all of the methods of \class{Mailbox} in addition to +the following: + +Some \class{Mailbox} methods implemented by \class{MH} deserve special remarks: + +\begin{methoddesc}{get_file}{key} +XXX +\end{methoddesc} + +\begin{seealso} +\seelink{http://www.nongnu.org/nmh/}{nmh - Message Handling System}{Home page +of \program{nmh}, a modern version of the original \program{mh}.} +\seelink{http://www.ics.uci.edu/\tilde{}mh/book/}{MH \& nmh: Email for Users \& +Programmers}{An open-source book on \program{mh} and \program{nmh}, with some +information on the mailbox format.} +\end{seealso} \subsubsection{\class{Babyl}} \label{mailbox-babyl} +\begin{classdesc}{Babyl}{path\optional{, factory}} +A subclass of \class{Mailbox} for mailboxes in Babyl format. Parameters +\var{path} and \var{factory} has the same meaning as with the module-level +\method{open()} function. +\end{classdesc} + +Babyl is a single-file mailbox format invented for use with the Rmail mail +reading application that ships with Emacs. A Babyl mailbox begins with a +so-called options section that indicates the format of the mailbox. Messages +follow the options section, with the beginning and end of each message +indicated by control characters. Each message in a Babyl mailbox has an +accompanying list of \dfn{labels}, or short strings that record extra +information about the message. + +Some \class{Mailbox} methods implemented by \class{Babyl} deserve special +remarks: + +\begin{methoddesc}{get_file}{key} +XXX +\end{methoddesc} + +\begin{seealso} +\seelink{http://quimby.gnus.org/notes/BABYL}{Format of Version 5 Babyl Files}{A +specification of the Babyl format.} +\seelink{http://www.gnu.org/software/emacs/manual/html_node/Rmail.html}{Reading +Mail with Rmail}{The Rmail manual, with some information on Babyl semantics.} +\end{seealso} \subsubsection{\class{MMDF}} \label{mailbox-mmdf} +\begin{classdesc}{MMDF}{path\optional{, factory}} +A subclass of \class{Mailbox} for mailboxes in MMDF format. Parameters +\var{path} and \var{factory} has the same meaning as with the module-level +\method{open()} function. +\end{classdesc} + +MMDF is a single-file mailbox format invented for the Multichannel Memorandum +Distribution Facility, a mail transfer agent. Each message is in the same form +as an mbox message but is bracketed before and after by lines containing four +Control-A characters. As with the mbox format, the beginning of each message +indicated by a line whose first five characters are "From~", but because of the +additional message separators it is unnecessary to transform "From~" to +">From~" when storing messages. + +Some \class{Mailbox} methods implemented by \class{MMDF} deserve special +remarks: + +\begin{methoddesc}{get_file}{key} +XXX +\end{methoddesc} + +\begin{seealso} +\seelink{http://www.tin.org/bin/man.cgi?section=5\&topic=mmdf}{mmdf man page +from tin}{A specification of MMDF format from the documentation of tin, a +newsreader.} +\seelink{http://en.wikipedia.org/wiki/MMDF}{MMDF}{A Wikipedia article +describing the Multichannel Memorandum Distribution Facility.} +\end{seealso} \subsection{\class{Message} objects} \label{mailbox-message-objects} @@ -364,7 +549,7 @@ support mailbox-format-specific state and behavior. \begin{classdesc}{Message}{\optional{message}} -Represents a message with mailbox-format-specific properties. +A message with mailbox-format-specific properties. If \var{message} is omitted, the new instance is created in a default, empty state. If \var{message} is an \class{email.Message.Message} instance, its @@ -400,19 +585,22 @@ \label{mailbox-maildirmessage} \begin{classdesc}{MaildirMessage}{\optional{message}} -Represents a message with Maildir-specific behaviors. Parameter \var{message} +A message with Maildir-specific behaviors. Parameter \var{message} has the same meaning as with the \class{Message} constructor. \end{classdesc} Maildir messages are stored in individual files, in either the \file{new} or -the \file{cur} subdirectory of the Maildir. Typically, messages are delivered -to the \file{new} subdirectory and then moved to the \file{cur} subdirectory -as soon as the user's mail reading application detects them. Each message in -\file{cur} has an "info" section added to its file name to store information -about its state. The "info" section may take one of two forms: it may contain -a standardized list of flags or it may contain so-called experimental -information. +the \file{cur} subdirectory of the Maildir. Messages are delivered to the +\file{new} subdirectory. Typically, a mail reading application moves messages +to the \file{cur} subdirectory after the user opens and closes the mailbox, +thereby recording that the messages are old whether or not they've actually +been read. +Each message in \file{cur} has an "info" section added to its file name to +store information about its state. (Some mail readers may also add an "info" +section to messages in \file{new}.) The "info" section may take one of two +forms: it may contain "2," followed by a list of standardized flags (e.g., +"2,FR") or it may contain "1," followed by so-called experimental information. Standard flags for Maildir messages are as follows: \begin{tableiii}{l|l|l}{textrm}{Flag}{Meaning}{Explanation} @@ -426,81 +614,507 @@ \class{MaildirMessage} instances offer the following methods: -\begin{methoddesc}[MaildirMessage]{get_subdir}{} +\begin{methoddesc}{get_subdir}{} Return either "new" (if the message should be stored in the \file{new} subdirectory) or "cur" (if the message should be stored in the \file{cur} -subdirectory). \note{A Maildir message typically moves from \file{new} to -\file{cur} when an MUA first detects it, but most MUAs refer to a message as -new if it is unseen, i.e., if \code{"S" in get_flags()} is \code{False}.} +subdirectory). \note{A message is typically moved from \file{new} to \file{cur} +after its mailbox has been accessed, whether or not the message is has been +read. A message has been read if \code{"S" not in get_flags()}.} \end{methoddesc} -\begin{methoddesc}[MaildirMessage]{set_subdir}{subdir} +\begin{methoddesc}{set_subdir}{subdir} Set the subdirectory the message should be stored in. Parameter \var{subdir} must be either "new" or "cur". \end{methoddesc} -\begin{methoddesc}[MaildirMessage]{get_flags}{} +\begin{methoddesc}{get_flags}{} Return a string specifying the flags that are currently set. If the message complies with the standard Maildir format, the result is the concatenation in alphabetical order of zero or one occurrence of each of \character{D}, \character{F}, \character{P}, \character{R}, \character{S}, and \character{T}. -The empty string is returned if no flags are set, if the message is new, or if -"info" contains experimental semantics. +The empty string is returned if no flags are set or if "info" contains +experimental semantics. \end{methoddesc} -\begin{methoddesc}[MaildirMessage]{set_flags}{flags} +\begin{methoddesc}{set_flags}{flags} Set the flags specified by \var{flags} and unset all others. Parameter \var{flags} should be the concatenation in any order of zero or more occurrences of each of \character{D}, \character{F}, \character{P}, -\character{R}, \character{S}, and \character{T}. If the message is new, it -is made non-new. The current "info" is overwritten whether or not it contains -experimental information instead of flags. +\character{R}, \character{S}, and \character{T}. The current "info" is +overwritten whether or not it contains experimental information instead of +flags. \end{methoddesc} -\begin{methoddesc}[MaildirMessage]{add_flags}{flags} +\begin{methoddesc}{add_flags}{flags} Set the flags specified by \var{flags} (if they are not set), and don't change other flags. Parameter \var{flags} should be the concatenation in any order of zero or more occurrences of each of \character{D}, \character{F}, -\character{P}, \character{R}, \character{S}, and \character{T}. If the message -is new, it is made non-new. If "info" contains experimental information rather -than flags, the "info" will be overwritten. +\character{P}, \character{R}, \character{S}, and \character{T}. The current +"info" is overwritten whether or not it contains experimental information +instead of flags. \end{methoddesc} -\begin{methoddesc}[MaildirMessage]{remove_flags}{flags} +\begin{methoddesc}{remove_flags}{flags} Unset the flags specified by \var{flags} (if they are set), and don't change other flags. Parameter \var{flags} should be the concatenation in any order of zero or more occurrences of each of \character{D}, \character{F}, -\character{P}, \character{R}, \character{S}, and \character{T}. If the message -is new, it remains so. If "info" contains experimental information rather than -flags, the current "info" is not modified. +\character{P}, \character{R}, \character{S}, and \character{T}. If "info" +contains experimental information rather than flags, the current "info" is not +modified. \end{methoddesc} -\begin{methoddesc}[MaildirMessage]{get_info}{} +\begin{methoddesc}{get_info}{} Return a string containing the "info" for a message. This is useful for accessing and modifying "info" that is experimental (i.e., not a list of flags). \end{methoddesc} -\begin{methoddesc}[MaildirMessage]{set_info}{info} -Set "info" to \var{info}, which should be a string. If the message is new, it -is made non-new. +\begin{methoddesc}{set_info}{info} +Set "info" to \var{info}, which should be a string. \end{methoddesc} +When a \class{MaildirMessage} instance is created based upon an +\class{mboxMessage} or \class{MMDFMessage} instance, the \mailheader{Status} +and \mailheader{X-Status} headers are omitted and the following conversions +take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{mboxMessage} or \class{MMDFMessage} state} +\lineii{"cur" subdirectory}{O flag} +\lineii{F flag}{F flag} +\lineii{R flag}{A flag} +\lineii{S flag}{R flag} +\lineii{T flag}{D flag} +\end{tableii} + +When a \class{MaildirMessage} instance is created based upon an +\class{MHMessage} instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MHMessage} state} +\lineii{"cur" subdirectory}{"unseen" sequence} +\lineii{"cur" subdirectory and S flag}{no "unseen" sequence} +\lineii{F flag}{"flagged" sequence} +\lineii{R flag}{"replied" sequence} +\end{tableii} + +When a \class{MaildirMessage} instance is created based upon a +\class{BabylMessage} instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{BabylMessage} state} +\lineii{"cur" subdirectory}{"unseen" label} +\lineii{"cur" subdirectory and S flag}{no "unseen" label} +\lineii{P flag}{"forwarded" or "resent" label} +\lineii{R flag}{"answered" label} +\lineii{T flag}{"deleted" label} +\end{tableii} + \subsubsection{\class{mboxMessage}} \label{mailbox-mboxmessage} +\begin{classdesc}{mboxMessage}{\optional{message}} +A message with mbox-specific behaviors. Parameter \var{message} has the same +meaning as with the \class{Message} constructor. +\end{classdesc} + +Messages in an mbox mailbox are stored together in a single file. The sender's +envelope address and the time of delivery are typically stored in a line +beginning with "From~" that is used to indicate the start of a message, though +there is considerable variation in the exact format of this data among mbox +implementations. Flags that indicate the state of the message, such as whether +it has been read or marked as important, are typically stored in +\mailheader{Status} and \mailheader{X-Status} headers. + +Conventional flags for mbox messages are as follows: + +\begin{tableiii}{l|l|l}{textrm}{Flag}{Meaning}{Explanation} +\lineiii{R}{Read}{Read by the user} +\lineiii{O}{Old}{Previously detected by mail reader} +\lineiii{D}{Deleted}{Marked for subsequent deletion} +\lineiii{F}{Flagged}{Marked by the user as important} +\lineiii{A}{Answered}{Responded to} +\end{tableiii} + +The "R" and "O" flags are stored in the \mailheader{Status} header, and the +"D", "F", and "A" flags are stored in the \mailheader{X-Status} header. The +flags and headers typically appear in the order mentioned. + +\class{mboxMessage} instances offer the following methods: + +\begin{methoddesc}{get_from}{} +Return a string representing the "From~" line that marks the start of the +message in an mbox mailbox. The leading "From~" and the trailing newline are +excluded. +\end{methoddesc} + +\begin{methoddesc}{set_from}{from_\optional{, time_=None}} +Set the "From~" line to \var{from_}, which should be specified without a +leading "From~" or trailing newline. If \var{time_} is specified, it should be +a \class{struct_time} or a tuple suitable for passing to +\method{time.strftime()}; if \var{time_} is \code{True}, the result of +\method{time.gmtime()} is used. +\end{methoddesc} + +\begin{methoddesc}{get_flags}{} +Return a string specifying the flags that are currently set. If the message +complies with the conventional format, the result is the concatenation in the +following order of zero or one occurrence of each of \character{R}, +\character{O}, \character{D}, \character{F}, and \character{A}. +\end{methoddesc} + +\begin{methoddesc}{set_flags}{flags} +Set the flags specified by \var{flags} and unset all others. Parameter +\var{flags} should be the concatenation in any order of zero or more +occurrences of each of \character{R}, \character{O}, \character{D}, +\character{F}, and \character{A}. +\end{methoddesc} + +\begin{methoddesc}{add_flags}{flags} +Set the flags specified by \var{flags} (if they are not set), and don't change +other flags. Parameter \var{flags} should be the concatenation in any order of +zero or more occurrences of each of \character{R}, \character{O}, +\character{D}, \character{F}, and \character{A}. +\end{methoddesc} + +\begin{methoddesc}{remove_flags}{flags} +Unset the flags specified by \var{flags} (if they are set), and don't change +other flags. Parameter \var{flags} should be the concatenation in any order of +zero or more occurrences of each of \character{R}, \character{O}, +\character{D}, \character{F}, and \character{A}. +\end{methoddesc} + +When an \class{mboxMessage} instance is created based upon a +\class{MaildirMessage} instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MaildirMessage} state} +\lineii{R flag}{S flag} +\lineii{O flag}{"cur" subdirectory} +\lineii{D flag}{T flag} +\lineii{F flag}{F flag} +\lineii{A flag}{R flag} +\end{tableii} + +When an \class{mboxMessage} instance is created based upon an \class{MHMessage} +instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MHMessage} state} +\lineii{R flag and O flag}{no "unseen" sequence} +\lineii{O flag}{"unseen" sequence} +\lineii{F flag}{"flagged" sequence} +\lineii{A flag}{"replied" sequence} +\end{tableii} + +When an \class{mboxMessage} instance is created based upon a +\class{BabylMessage} instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{BabylMessage} state} +\lineii{R flag and O flag}{no "unseen" label} +\lineii{O flag}{"unseen" label} +\lineii{D flag}{"deleted" label} +\lineii{A flag}{"answered" label} +\end{tableii} + +When a \class{Message} instance is created based upon an \class{MMDFMessage} +instance, the "From~" line is copied and all flags directly correspond: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MMDFMessage} state} +\lineii{R flag}{R flag} +\lineii{O flag}{O flag} +\lineii{D flag}{D flag} +\lineii{F flag}{F flag} +\lineii{A flag}{A flag} +\end{tableii} \subsubsection{\class{MHMessage}} \label{mailbox-mhmessage} +\begin{classdesc}{MHMessage}{\optional{message}} +A message with MH-specific behaviors. Parameter \var{message} has the same +meaning as with the \class{Message} constructor. +\end{classdesc} + +MH messages do not support marks or flags in the traditional sense, but they do +support sequences, which are logical groupings of arbitrary messages. Because +sequences are often used to indicate the state of a messsage, they are +maintained by the \class{MHMessage} class even though they are not, strictly +speaking, a property of the message itself. + +Some mail user agents make use of sequences to record message state as follows: + +\begin{tableii}{l|l}{textrm}{Sequence}{Explanation} +\lineii{unseen}{Previously detected by mail reader but not read} +\lineii{replied}{Responded to} +\lineii{flagged}{Marked by the user as important} +\end{tableii} + +\class{MHMessage} instances offer the following methods: + +\begin{methoddesc}{list_sequences}{} +Return a list of the names of sequences that include the message. +\end{methoddesc} + +\begin{methoddesc}{join_sequence}{sequence} +Add \var{sequence} to the list of sequences that include the message. +\end{methoddesc} + +\begin{methoddesc}{leave_sequence}{sequence} +Remove \var{sequence} from the list of sequences that include the message. +\end{methoddesc} + +When an \class{MHMessage} instance is created based upon a +\class{MaildirMessage} instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MaildirMessage} state} +\lineii{"unseen" sequence}{no S flag} +\lineii{"replied" sequence}{R flag} +\lineii{"flagged" sequence}{F flag} +\end{tableii} + +When an \class{MHMessage} instance is created based upon an \class{mboxMessage} +or \class{MMDFMessage} instance, the \mailheader{Status} and +\mailheader{X-Status} headers are omitted and the following conversions take +place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{mboxMessage} or \class{MMDFMessage} state} +\lineii{"unseen" sequence}{no R flag} +\lineii{"replied" sequence}{A flag} +\lineii{"flagged" sequence}{F flag} +\end{tableii} + +When an \class{MHMessage} instance is created based upon a \class{BabylMessage} +instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{BabylMessage} state} +\lineii{"unseen" sequence}{"unseen" label} +\lineii{"replied" sequence}{"answered" label} +\end{tableii} \subsubsection{\class{BabylMessage}} \label{mailbox-babylmessage} +\begin{classdesc}{BabylMessage}{\optional{message}} +A message with Babyl-specific behaviors. Parameter \var{message} has the same +meaning as with the \class{Message} constructor. +\end{classdesc} + +Information about Babyl messages is recorded using \dfn{labels}, or short +strings which are stored in an MH mailbox just before each message. Some +labels are assigned special meaning and are called \dfn{attributes}. Other +labels are user-defined. The attributes are as follows: + +\begin{tableii}{l|l}{textrm}{Label}{Explanation} +\lineii{unseen}{Previously detected by mail reader but not read} +\lineii{deleted}{Marked for subsequent deletion} +\lineii{filed}{Copied to another file or mailbox} +\lineii{answered}{Responded to} +\lineii{forwarded}{Forwarded by the the user} +\lineii{edited}{Message content modified by the user} +\lineii{resent}{Resent by the user} +\end{tableii} + +Each message in a Babyl mailbox has two sets of headers, original headers and +visible headers. Visible headers are typically a subset of the original +headers reformatted to be more attractive. By default, \program{rmail} displays +only visible headers. \class{BabylMessage} uses the original headers because +they are more complete, though the visible headers may be accessed explicitly +if desired. + +\class{BabylMessage} instances offer the following methods: + +\begin{methoddesc}{list_labels}{} +Return a list of labels on the message. +\end{methoddesc} + +\begin{methoddesc}{add_label}{label} +Add \var{label} to the list of labels on the message. +\end{methoddesc} + +\begin{methoddesc}{remove_label}{label} +Remove \var{label} from the list of labels on the message. +\end{methoddesc} + +\begin{methoddesc}{get_visible}{} +Return an \class{Message} instance whose headers are the message's visible +headers and whose body is empty. +\end{methoddesc} + +\begin{methoddesc}{set_visible}{visible} +Set the message's visible headers to be the same as the headers in +\var{message}. Parameter \var{visible} should be a \class{Message} instance, an +\class{email.Message.Message} instance, a string, or a file-like object. +\end{methoddesc} + +\begin{methoddesc}{update_visible}{} +When a \class{BabylMessage} instance's original headers are modified, the +visible headers are not automatically modified to correspond. This method +updates the visible headers as follows: each visible header with a +corresponding original header is set to the value of the original header, each +visible header without a corresponding original header is removed, and any of +\mailheader{Date}, \mailheader{From}, \mailheader{Reply-To}, \mailheader{To}, +\mailheader{CC}, and \mailheader{Subject} that are present in the original +headers but not the visible headers are added to the visible headers. +\end{methoddesc} + +When a \class{BabylMessage} instance is created based upon a +\class{MaildirMessage} instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MaildirMessage} state} +\lineii{"unseen" label}{no S flag} +\lineii{"deleted" label}{T flag} +\lineii{"answered" label}{R flag} +\lineii{"forwarded" label}{P flag} +\end{tableii} + +When a \class{BabylMessage} instance is created based upon an +\class{mboxMessage} or \class{MMDFMessage} instance, the \mailheader{Status} +and \mailheader{X-Status} headers are omitted and the following conversions +take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{mboxMessage} or \class{MMDFMessage} state} +\lineii{"unseen" label}{no R flag} +\lineii{"deleted" label}{D flag} +\lineii{"answered" label}{A flag} +\end{tableii} + +When a \class{BabylMessage} instance is created based upon an \class{MHMessage} +instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MHMessage} state} +\lineii{"unseen" label}{"unseen" sequence} +\lineii{"answered" label}{"replied" sequence} +\end{tableii} \subsubsection{\class{MMDFMessage}} \label{mailbox-mmdfmessage} +\begin{classdesc}{MMDFMessage}{\optional{message}} +A message with MMDF-specific behaviors. Parameter \var{message} has the same +meaning as with the \class{Message} constructor. +\end{classdesc} + +As with message in an mbox mailbox, MMDF messages are stored with the sender's +address and the delivery date in an initial line beginning with "From ". +Likewise, flags that indicate the state of the message are typically stored in +\mailheader{Status} and \mailheader{X-Status} headers. + +Conventional flags for MMDF messages are identical to those of mbox message and +are as follows: + +\begin{tableiii}{l|l|l}{textrm}{Flag}{Meaning}{Explanation} +\lineiii{R}{Read}{Read by the user} +\lineiii{O}{Old}{Previously detected by mail reader} +\lineiii{D}{Deleted}{Marked for subsequent deletion} +\lineiii{F}{Flagged}{Marked by the user as important} +\lineiii{A}{Answered}{Responded to} +\end{tableiii} + +The "R" and "O" flags are stored in the \mailheader{Status} header, and the +"D", "F", and "A" flags are stored in the \mailheader{X-Status} header. The +flags and headers typically appear in the order mentioned. + +\class{MMDFMessage} instances offer the following methods, which are identical +to those offered by \class{mboxMessage}: + +\begin{methoddesc}{get_from}{} +Return a string representing the "From~" line that marks the start of the +message in an mbox mailbox. The leading "From~" and the trailing newline are +excluded. +\end{methoddesc} + +\begin{methoddesc}{set_from}{from_\optional{, time_=None}} +Set the "From~" line to \var{from_}, which should be specified without a +leading "From~" or trailing newline. If \var{time_} is specified, it should be +a \class{struct_time} or a tuple suitable for passing to +\method{time.strftime()}; if \var{time_} is \code{True}, the result of +\method{time.gmtime()} is used. +\end{methoddesc} + +\begin{methoddesc}{get_flags}{} +Return a string specifying the flags that are currently set. If the message +complies with the conventional format, the result is the concatenation in the +following order of zero or one occurrence of each of \character{R}, +\character{O}, \character{D}, \character{F}, and \character{A}. +\end{methoddesc} + +\begin{methoddesc}{set_flags}{flags} +Set the flags specified by \var{flags} and unset all others. Parameter +\var{flags} should be the concatenation in any order of zero or more +occurrences of each of \character{R}, \character{O}, \character{D}, +\character{F}, and \character{A}. +\end{methoddesc} + +\begin{methoddesc}{add_flags}{flags} +Set the flags specified by \var{flags} (if they are not set), and don't change +other flags. Parameter \var{flags} should be the concatenation in any order of +zero or more occurrences of each of \character{R}, \character{O}, +\character{D}, \character{F}, and \character{A}. +\end{methoddesc} + +\begin{methoddesc}{remove_flags}{flags} +Unset the flags specified by \var{flags} (if they are set), and don't change +other flags. Parameter \var{flags} should be the concatenation in any order of +zero or more occurrences of each of \character{R}, \character{O}, +\character{D}, \character{F}, and \character{A}. +\end{methoddesc} + +When an \class{MMDFMessage} instance is created based upon a +\class{MaildirMessage} instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MaildirMessage} state} +\lineii{R flag}{S flag} +\lineii{O flag}{"cur" subdirectory} +\lineii{D flag}{T flag} +\lineii{F flag}{F flag} +\lineii{A flag}{R flag} +\end{tableii} + +When an \class{MMDFMessage} instance is created based upon an \class{MHMessage} +instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{MHMessage} state} +\lineii{R flag and O flag}{no "unseen" sequence} +\lineii{O flag}{"unseen" sequence} +\lineii{F flag}{"flagged" sequence} +\lineii{A flag}{"replied" sequence} +\end{tableii} + +When an \class{MMDFMessage} instance is created based upon a +\class{BabylMessage} instance, the following conversions take place: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{BabylMessage} state} +\lineii{R flag and O flag}{no "unseen" label} +\lineii{O flag}{"unseen" label} +\lineii{D flag}{"deleted" label} +\lineii{A flag}{"answered" label} +\end{tableii} + +When an \class{MMDFMessage} instance is created based upon an +\class{mboxMessage} instance, the "From~" line is copied and all flags directly +correspond: + +\begin{tableii}{l|l}{textrm} + {Resulting state}{\class{mboxMessage} state} +\lineii{R flag}{R flag} +\lineii{O flag}{O flag} +\lineii{D flag}{D flag} +\lineii{F flag}{F flag} +\lineii{A flag}{A flag} +\end{tableii} + \subsection{Deprecated classes} \label{mailbox-deprecated-classes} Index: test_mailbox.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/test_mailbox.py,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- test_mailbox.py 26 Jul 2005 20:47:48 -0000 1.1 +++ test_mailbox.py 30 Jul 2005 22:49:08 -0000 1.2 @@ -451,7 +451,7 @@ msg0.set_flags('TP') key = box.add(msg0) msg_returned = box.get_message(key) - self.assert_(msg_returned.get_subdir() == 'cur') + self.assert_(msg_returned.get_subdir() == 'new') self.assert_(msg_returned.get_flags() == 'PT') msg1 = mailbox.MaildirMessage(template % 1) box[key] = msg1 @@ -464,7 +464,7 @@ box[key] = msg2 box[key] = template % 3 msg_returned = box.get_message(key) - self.assert_(msg_returned.get_subdir() == 'cur') + self.assert_(msg_returned.get_subdir() == 'new') self.assert_(msg_returned.get_flags() == 'S') self.assert_(msg_returned.get_payload() == '3') @@ -696,7 +696,9 @@ # Copy self's format-specific data to other message formats. # This test is superficial; better ones are in TestMessageConversion. msg = self._factory() - for class_ in (mailbox.Message, mailbox.MaildirMessage): + for class_ in (mailbox.Message, mailbox.MaildirMessage, + mailbox.mboxMessage, mailbox.MHMessage, + mailbox.BabylMessage, mailbox.MMDFMessage): other_msg = class_() msg._explain_to(other_msg) other_msg = email.Message.Message() @@ -735,7 +737,7 @@ self.assert_(msg.get_flags() == '') self.assert_(msg.get_subdir() == 'new') msg.set_flags('F') - self.assert_(msg.get_subdir() == 'cur') + self.assert_(msg.get_subdir() == 'new') self.assert_(msg.get_flags() == 'F') msg.set_flags('SDTP') self.assert_(msg.get_flags() == 'DPST') @@ -743,7 +745,7 @@ self.assert_(msg.get_flags() == 'DFPST') msg.remove_flags('TDRP') self.assert_(msg.get_flags() == 'FS') - self.assert_(msg.get_subdir() == 'cur') + self.assert_(msg.get_subdir() == 'new') self._check_sample(msg) def test_info(self): @@ -774,8 +776,377 @@ self._check_sample(msg) +class _TestMboxMMDFMessage(TestMessage): + + _factory = mailbox._mboxMMDFMessage + + def _post_initialize_hook(self, msg): + self._check_from(msg) + + def test_initialize_with_unixfrom(self): + # Initialize with a message that already has a _unixfrom attribute + msg = mailbox.Message(_sample_message) + msg.set_unixfrom('From foo at bar blah') + msg = mailbox.mboxMessage(msg) + self.assert_(msg.get_from() == 'foo at bar blah', msg.get_from()) + + def test_from(self): + # Get and set "From " line + msg = mailbox.mboxMessage(_sample_message) + self._check_from(msg) + msg.set_from('foo bar') + self.assert_(msg.get_from() == 'foo bar') + msg.set_from('foo at bar', True) + self._check_from(msg, 'foo at bar') + msg.set_from('blah at temp', time.localtime()) + self._check_from(msg, 'blah at temp') + + def test_flags(self): + # Use get_flags(), set_flags(), add_flags(), remove_flags() + msg = mailbox.mboxMessage(_sample_message) + self.assert_(msg.get_flags() == '') + msg.set_flags('F') + self.assert_(msg.get_flags() == 'F') + msg.set_flags('XODR') + self.assert_(msg.get_flags() == 'RODX') + msg.add_flags('FA') + self.assert_(msg.get_flags() == 'RODFAX') + msg.remove_flags('FDXA') + self.assert_(msg.get_flags() == 'RO') + self._check_sample(msg) + + def _check_from(self, msg, sender=None): + # Check contents of "From " line + if sender is None: + sender = "MAILER-DAEMON" + self.assert_(re.match(sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:" + r"\d{2} \d{4}", msg.get_from()) is not None) + + +class TestMboxMessage(_TestMboxMMDFMessage): + + _factory = mailbox.mboxMessage + + +class TestMHMessage(TestMessage): + + _factory = mailbox.MHMessage + + def _post_initialize_hook(self, msg): + self.assert_(msg._sequences == []) + + def test_sequences(self): + # List, join, and leave sequences + msg = mailbox.MHMessage(_sample_message) + self.assert_(msg.list_sequences() == []) + msg.join_sequence('unseen') + self.assert_(msg.list_sequences() == ['unseen']) + msg.join_sequence('flagged') + self.assert_(msg.list_sequences() == ['unseen', 'flagged']) + msg.join_sequence('flagged') + self.assert_(msg.list_sequences() == ['unseen', 'flagged']) + msg.leave_sequence('unseen') + self.assert_(msg.list_sequences() == ['flagged']) + msg.join_sequence('foobar') + self.assert_(msg.list_sequences() == ['flagged', 'foobar']) + msg.leave_sequence('replied') + self.assert_(msg.list_sequences() == ['flagged', 'foobar']) + + +class TestBabylMessage(TestMessage): + + _factory = mailbox.BabylMessage + + def _post_initialize_hook(self, msg): + self.assert_(msg._labels == []) + + def test_labels(self): + # List, add, and remove labels + msg = mailbox.BabylMessage(_sample_message) + self.assert_(msg.list_labels() == []) + msg.add_label('filed') + self.assert_(msg.list_labels() == ['filed']) + msg.add_label('resent') + self.assert_(msg.list_labels() == ['filed', 'resent']) + msg.add_label('resent') + self.assert_(msg.list_labels() == ['filed', 'resent']) + msg.remove_label('filed') + self.assert_(msg.list_labels() == ['resent']) + msg.add_label('foobar') + self.assert_(msg.list_labels() == ['resent', 'foobar']) + msg.remove_label('unseen') + self.assert_(msg.list_labels() == ['resent', 'foobar']) + + def test_visible(self): + # Get, set, and update visible headers + msg = mailbox.BabylMessage(_sample_message) + visible = msg.get_visible() + self.assert_(visible.keys() == []) + self.assert_(visible.get_payload() is None) + visible['User-Agent'] = 'FooBar 1.0' + visible['X-Whatever'] = 'Blah' + self.assert_(msg.get_visible().keys() == []) + msg.set_visible(visible) + visible = msg.get_visible() + self.assert_(visible.keys() == ['User-Agent', 'X-Whatever']) + self.assert_(visible['User-Agent'] == 'FooBar 1.0') + self.assert_(visible['X-Whatever'] == 'Blah') + self.assert_(visible.get_payload() is None) + msg.update_visible() + self.assert_(visible.keys() == ['User-Agent', 'X-Whatever']) + self.assert_(visible.get_payload() is None) + visible = msg.get_visible() + self.assert_(visible.keys() == ['User-Agent', 'Date', 'From', 'To', + 'Subject']) + for header in ('User-Agent', 'Date', 'From', 'To', 'Subject'): + self.assert_(visible[header] == msg[header]) + + +class TestMMDFMessage(_TestMboxMMDFMessage): + + _factory = mailbox.MMDFMessage + + class TestMessageConversion(TestBase): - pass + + def test_plain_to_x(self): + # Convert Message to all formats + for class_ in (mailbox.Message, mailbox.MaildirMessage, + mailbox.mboxMessage, mailbox.MHMessage, + mailbox.BabylMessage, mailbox.MMDFMessage): + msg_plain = mailbox.Message(_sample_message) + msg = class_(msg_plain) + self._check_sample(msg) + + def test_x_to_plain(self): + # Convert all formats to Message + for class_ in (mailbox.Message, mailbox.MaildirMessage, + mailbox.mboxMessage, mailbox.MHMessage, + mailbox.BabylMessage, mailbox.MMDFMessage): + msg = class_(_sample_message) + msg_plain = mailbox.Message(msg) + self._check_sample(msg_plain) + + def test_x_to_invalid(self): + # Convert all formats to an invalid format + for class_ in (mailbox.Message, mailbox.MaildirMessage, + mailbox.mboxMessage, mailbox.MHMessage, + mailbox.BabylMessage, mailbox.MMDFMessage): + self.assertRaises(TypeError, lambda: class_(False)) + + def test_maildir_to_maildir(self): + # Convert MaildirMessage to MaildirMessage + msg_maildir = mailbox.MaildirMessage(_sample_message) + msg_maildir.set_flags('DFPRST') + msg_maildir.set_subdir('cur') + msg = mailbox.MaildirMessage(msg_maildir) + self._check_sample(msg) + self.assert_(msg.get_flags() == 'DFPRST') + self.assert_(msg.get_subdir() == 'cur') + + def test_maildir_to_mboxmmdf(self): + # Convert MaildirMessage to mboxmessage and MMDFMessage + pairs = (('D', ''), ('F', 'F'), ('P', ''), ('R', 'A'), ('S', 'R'), + ('T', 'D'), ('DFPRST', 'RDFA')) + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + msg_maildir = mailbox.MaildirMessage(_sample_message) + for setting, result in pairs: + msg_maildir.set_flags(setting) + self.assert_(class_(msg_maildir).get_flags() == result) + msg_maildir.set_subdir('cur') + self.assert_(class_(msg_maildir).get_flags() == 'RODFA') + + def test_maildir_to_mh(self): + # Convert MaildirMessage to MHMessage + msg_maildir = mailbox.MaildirMessage(_sample_message) + pairs = (('D', ['unseen']), ('F', ['unseen', 'flagged']), + ('P', ['unseen']), ('R', ['unseen', 'replied']), ('S', []), + ('T', ['unseen']), ('DFPRST', ['replied', 'flagged'])) + for setting, result in pairs: + msg_maildir.set_flags(setting) + self.assert_(mailbox.MHMessage(msg_maildir).list_sequences() == \ + result) + + def test_maildir_to_babyl(self): + # Convert MaildirMessage to Babyl + msg_maildir = mailbox.MaildirMessage(_sample_message) + pairs = (('D', ['unseen']), ('F', ['unseen']), + ('P', ['unseen', 'forwarded']), ('R', ['unseen', 'answered']), + ('S', []), ('T', ['unseen', 'deleted']), + ('DFPRST', ['deleted', 'answered', 'forwarded'])) + for setting, result in pairs: + msg_maildir.set_flags(setting) + self.assert_(mailbox.BabylMessage(msg_maildir).list_labels() == \ + result) + + def test_mboxmmdf_to_maildir(self): + # Convert mboxMessage and MMDFMessage to MaildirMessage + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + msg_mboxMMDF = class_(_sample_message) + pairs = (('R', 'S'), ('O', ''), ('D', 'T'), ('F', 'F'), ('A', 'R'), + ('RODFA', 'FRST')) + for setting, result in pairs: + msg_mboxMMDF.set_flags(setting) + self.assert_(mailbox.MaildirMessage(msg_mboxMMDF).get_flags() \ + == result) + msg_mboxMMDF.set_flags('O') + self.assert_(mailbox.MaildirMessage(msg_mboxMMDF).get_subdir() == \ + 'cur') + + def test_mboxmmdf_to_mboxmmdf(self): + # Convert mboxMessage and MMDFMessage to mboxMessage and MMDFMessage + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + msg_mboxMMDF = class_(_sample_message) + msg_mboxMMDF.set_flags('RODFA') + msg_mboxMMDF.set_from('foo at bar') + for class2_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + msg2 = class2_(msg_mboxMMDF) + self.assert_(msg2.get_flags() == 'RODFA') + self.assert_(msg2.get_from() == 'foo at bar') + + def test_mboxmmdf_to_mh(self): + # Convert mboxMessage and MMDFMessage to MHMessage + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + msg_mboxMMDF = class_(_sample_message) + pairs = (('R', []), ('O', ['unseen']), ('D', ['unseen']), + ('F', ['unseen', 'flagged']), + ('A', ['unseen', 'replied']), + ('RODFA', ['replied', 'flagged'])) + for setting, result in pairs: + msg_mboxMMDF.set_flags(setting) + self.assert_(mailbox.MHMessage(msg_mboxMMDF).list_sequences() \ + == result) + + def test_mboxmmdf_to_babyl(self): + # Convert mboxMessage and MMDFMessage to BabylMessage + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + msg = class_(_sample_message) + pairs = (('R', []), ('O', ['unseen']), + ('D', ['unseen', 'deleted']), ('F', ['unseen']), + ('A', ['unseen', 'answered']), + ('RODFA', ['deleted', 'answered'])) + for setting, result in pairs: + msg.set_flags(setting) + self.assert_(mailbox.BabylMessage(msg).list_labels() == result) + + def test_mh_to_maildir(self): + # Convert MHMessage to MaildirMessage + pairs = (('unseen', ''), ('replied', 'RS'), ('flagged', 'FS')) + for setting, result in pairs: + msg = mailbox.MHMessage(_sample_message) + msg.join_sequence(setting) + self.assert_(mailbox.MaildirMessage(msg).get_flags() == result) + self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur') + msg = mailbox.MHMessage(_sample_message) + msg.join_sequence('unseen') + msg.join_sequence('replied') + msg.join_sequence('flagged') + self.assert_(mailbox.MaildirMessage(msg).get_flags() == 'FR') + self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur') + + def test_mh_to_mboxmmdf(self): + # Convert MHMessage to mboxMessage and MMDFMessage + pairs = (('unseen', 'O'), ('replied', 'ROA'), ('flagged', 'ROF')) + for setting, result in pairs: + msg = mailbox.MHMessage(_sample_message) + msg.join_sequence(setting) + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + self.assert_(class_(msg).get_flags() == result) + msg = mailbox.MHMessage(_sample_message) + msg.join_sequence('unseen') + msg.join_sequence('replied') + msg.join_sequence('flagged') + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + self.assert_(class_(msg).get_flags() == 'OFA') + + def test_mh_to_mh(self): + # Convert MHMessage to MHMessage + msg = mailbox.MHMessage(_sample_message) + msg.join_sequence('unseen') + msg.join_sequence('replied') + msg.join_sequence('flagged') + self.assert_(mailbox.MHMessage(msg).list_sequences() == \ + ['unseen', 'replied', 'flagged']) + + def test_mh_to_babyl(self): + # Convert MHMessage to BabylMessage + pairs = (('unseen', ['unseen']), ('replied', ['answered']), + ('flagged', [])) + for setting, result in pairs: + msg = mailbox.MHMessage(_sample_message) + msg.join_sequence(setting) + self.assert_(mailbox.BabylMessage(msg).list_labels() == result) + msg = mailbox.MHMessage(_sample_message) + msg.join_sequence('unseen') + msg.join_sequence('replied') + msg.join_sequence('flagged') + self.assert_(mailbox.BabylMessage(msg).list_labels() == \ + ['unseen', 'answered']) + + def test_babyl_to_maildir(self): + # Convert BabylMessage to MaildirMessage + pairs = (('unseen', ''), ('deleted', 'ST'), ('filed', 'S'), + ('answered', 'RS'), ('forwarded', 'PS'), ('edited', 'S'), + ('resent', 'PS')) + for setting, result in pairs: + msg = mailbox.BabylMessage(_sample_message) + msg.add_label(setting) + self.assert_(mailbox.MaildirMessage(msg).get_flags() == result) + self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur') + msg = mailbox.BabylMessage(_sample_message) + for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded', + 'edited', 'resent'): + msg.add_label(label) + self.assert_(mailbox.MaildirMessage(msg).get_flags() == 'PRT') + self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur') + + def test_babyl_to_mboxmmdf(self): + # Convert BabylMessage to mboxMessage and MMDFMessage + pairs = (('unseen', 'O'), ('deleted', 'ROD'), ('filed', 'RO'), + ('answered', 'ROA'), ('forwarded', 'RO'), ('edited', 'RO'), + ('resent', 'RO')) + for setting, result in pairs: + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + msg = mailbox.BabylMessage(_sample_message) + msg.add_label(setting) + self.assert_(class_(msg).get_flags() == result) + msg = mailbox.BabylMessage(_sample_message) + for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded', + 'edited', 'resent'): + msg.add_label(label) + for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage): + self.assert_(class_(msg).get_flags() == 'ODA') + + def test_babyl_to_mh(self): + # Convert BabylMessage to MHMessage + pairs = (('unseen', ['unseen']), ('deleted', []), ('filed', []), + ('answered', ['replied']), ('forwarded', []), ('edited', []), + ('resent', [])) + for setting, result in pairs: + msg = mailbox.BabylMessage(_sample_message) + msg.add_label(setting) + self.assert_(mailbox.MHMessage(msg).list_sequences() == result) + msg = mailbox.BabylMessage(_sample_message) + for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded', + 'edited', 'resent'): + msg.add_label(label) + self.assert_(mailbox.MHMessage(msg).list_sequences() == \ + ['unseen', 'replied']) + + def test_babyl_to_babyl(self): + # Convert BabylMessage to BabylMessage + msg = mailbox.BabylMessage(_sample_message) + msg.update_visible() + for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded', + 'edited', 'resent'): + msg.add_label(label) + msg2 = mailbox.BabylMessage(msg) + self.assert_(msg2.list_labels() == ['unseen', 'deleted', 'filed', + 'answered', 'forwarded', 'edited', + 'resent']) + self.assert_(msg.get_visible().keys() == msg2.get_visible().keys()) + for key in msg.get_visible().keys(): + self.assert_(msg.get_visible()[key] == msg2.get_visible()[key]) class TestProxyFileBase(TestBase): @@ -1016,8 +1387,9 @@ def test_main(): test_support.run_unittest(TestMaildir, TestMessage, TestMaildirMessage, - TestMessageConversion, TestProxyFile, - TestPartialFile) + TestMboxMessage, TestMHMessage, TestBabylMessage, + TestMMDFMessage, TestMessageConversion, + TestProxyFile, TestPartialFile) if __name__ == '__main__': From rhettinger at users.sourceforge.net Sun Jul 31 03:16:38 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 18:16:38 -0700 Subject: [Python-checkins] python/dist/src/Objects setobject.c,1.32,1.33 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27783/Objects Modified Files: setobject.c Log Message: Revised the set() and frozenset() implementaion to use its own internal data structure instead of using dictionaries. Reduces memory consumption by 1/3 and provides modest speed-ups for most set operations. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v retrieving revision 1.32 retrieving revision 1.33 diff -u -d -r1.32 -r1.33 --- setobject.c 18 Jun 2005 21:00:25 -0000 1.32 +++ setobject.c 31 Jul 2005 01:16:36 -0000 1.33 @@ -1,4 +1,641 @@ + +/* Set object implementation using a hash table + Functions adapted from dictobject.c +*/ + #include "Python.h" + +/* This must be >= 1. */ +#define PERTURB_SHIFT 5 + +/* Object used as dummy key to fill deleted entries */ [...1390 lines suppressed...] + Py_TPFLAGS_BASETYPE, /* tp_flags */ set_doc, /* tp_doc */ (traverseproc)set_traverse, /* tp_traverse */ (inquiry)set_tp_clear, /* tp_clear */ (richcmpfunc)set_richcompare, /* tp_richcompare */ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)set_iter, /* tp_iter */ + (getiterfunc)set_iter, /* tp_iter */ 0, /* tp_iternext */ set_methods, /* tp_methods */ 0, /* tp_members */ @@ -1120,7 +1772,7 @@ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES | - Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ + Py_TPFLAGS_BASETYPE, /* tp_flags */ frozenset_doc, /* tp_doc */ (traverseproc)set_traverse, /* tp_traverse */ 0, /* tp_clear */ From rhettinger at users.sourceforge.net Sun Jul 31 03:16:38 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 18:16:38 -0700 Subject: [Python-checkins] python/dist/src/Misc NEWS,1.1326,1.1327 Message-ID: Update of /cvsroot/python/python/dist/src/Misc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27783/Misc Modified Files: NEWS Log Message: Revised the set() and frozenset() implementaion to use its own internal data structure instead of using dictionaries. Reduces memory consumption by 1/3 and provides modest speed-ups for most set operations. Index: NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.1326 retrieving revision 1.1327 diff -u -d -r1.1326 -r1.1327 --- NEWS 27 Jul 2005 20:24:40 -0000 1.1326 +++ NEWS 31 Jul 2005 01:16:35 -0000 1.1327 @@ -12,6 +12,10 @@ Core and builtins ----------------- +- The implementation of set() and frozenset() was revised to use its + own internal data structure. Memory consumption is reduced by 1/3 + and there are modest speed-ups as well. The API is unchanged. + - SF bug #1238681: freed pointer is used in longobject.c:long_pow(). - SF bug #1229429: PyObject_CallMethod failed to decrement some From rhettinger at users.sourceforge.net Sun Jul 31 03:16:39 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 18:16:39 -0700 Subject: [Python-checkins] python/dist/src/Include setobject.h,2.5,2.6 Message-ID: Update of /cvsroot/python/python/dist/src/Include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27783/Include Modified Files: setobject.h Log Message: Revised the set() and frozenset() implementaion to use its own internal data structure instead of using dictionaries. Reduces memory consumption by 1/3 and provides modest speed-ups for most set operations. Index: setobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/setobject.h,v retrieving revision 2.5 retrieving revision 2.6 diff -u -d -r2.5 -r2.6 --- setobject.h 28 Oct 2004 16:31:59 -0000 2.5 +++ setobject.h 31 Jul 2005 01:16:36 -0000 2.6 @@ -1,4 +1,3 @@ - /* Set object interface */ #ifndef Py_SETOBJECT_H @@ -7,28 +6,61 @@ extern "C" { #endif + /* -This data structure is shared by set and frozenset objects. +There are three kinds of slots in the table: + +1. Unused: key == NULL +2. Active: key != NULL and key != dummy +3. Dummy: key == dummy */ +#define PySet_MINSIZE 8 + typedef struct { + long hash; /* cached hash code for the entry key */ + PyObject *key; +} setentry; + + +/* +This data structure is shared by set and frozenset objects. +*/ + +typedef struct _setobject PySetObject; +struct _setobject { PyObject_HEAD - PyObject *data; - long hash; /* only used by frozenset objects */ - PyObject *weakreflist; /* List of weak references */ - /* Invariants: - * data is a dictionary whose values are all True. - * data points to the same dict for the whole life of the set. - * For frozensets only: - * data is immutable. - * hash is the hash of the frozenset or -1 if not computed yet. + int fill; /* # Active + # Dummy */ + int used; /* # Active */ + + /* The table contains mask + 1 slots, and that's a power of 2. + * We store the mask instead of the size because the mask is more + * frequently needed. */ -} PySetObject; + int mask; + + /* table points to smalltable for small tables, else to + * additional malloc'ed memory. table is never NULL! This rule + * saves repeated runtime null-tests in the workhorse getitem and + * setitem calls. + */ + setentry *table; + setentry *(*lookup)(PySetObject *so, PyObject *key, long hash); + setentry smalltable[PySet_MINSIZE]; + + long hash; /* only used by frozenset objects */ + PyObject *weakreflist; /* List of weak references */ +}; PyAPI_DATA(PyTypeObject) PySet_Type; PyAPI_DATA(PyTypeObject) PyFrozenSet_Type; +/* Invariants for frozensets only: + * data is immutable. + * hash is the hash of the frozenset or -1 if not computed yet. + */ + #define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type) #define PyAnySet_Check(ob) \ ((ob)->ob_type == &PySet_Type || (ob)->ob_type == &PyFrozenSet_Type || \ From rhettinger at users.sourceforge.net Sun Jul 31 03:33:12 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sat, 30 Jul 2005 18:33:12 -0700 Subject: [Python-checkins] python/dist/src/Objects setobject.c,1.33,1.34 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31785 Modified Files: setobject.c Log Message: Comment on the set_swap_bodies() helper function. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- setobject.c 31 Jul 2005 01:16:36 -0000 1.33 +++ setobject.c 31 Jul 2005 01:33:10 -0000 1.34 @@ -793,6 +793,19 @@ return ((PySetObject *)so)->used; } +/* set_swap_bodies() switches the contents of any two sets by moving their + internal data pointers and, if needed, copying the internal smalltables. + Semantically equivalent to: + + t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t + + The function always succeeds and it leaves both objects in a stable state. + Useful for creating temporary frozensets from sets for membership testing + in __contains__(), discard(), and remove(). Also useful for operations + that update in-place (by allowing an intermediate result to be swapped + into one of original the inputs). +*/ + static void set_swap_bodies(PySetObject *a, PySetObject *b) { From rhettinger at users.sourceforge.net Sun Jul 31 15:09:30 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sun, 31 Jul 2005 06:09:30 -0700 Subject: [Python-checkins] python/dist/src/Objects setobject.c,1.34,1.35 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32542 Modified Files: setobject.c Log Message: Fix frozenset() ref count and a comment typo. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- setobject.c 31 Jul 2005 01:33:10 -0000 1.34 +++ setobject.c 31 Jul 2005 13:09:28 -0000 1.35 @@ -735,8 +735,7 @@ if (type == &PyFrozenSet_Type) { if (emptyfrozenset == NULL) emptyfrozenset = make_new_set(type, NULL); - else - Py_INCREF(emptyfrozenset); + Py_INCREF(emptyfrozenset); return emptyfrozenset; } } else if (PyFrozenSet_CheckExact(iterable)) { @@ -803,7 +802,7 @@ Useful for creating temporary frozensets from sets for membership testing in __contains__(), discard(), and remove(). Also useful for operations that update in-place (by allowing an intermediate result to be swapped - into one of original the inputs). + into one of the original inputs). */ static void From rhettinger at users.sourceforge.net Sun Jul 31 17:36:09 2005 From: rhettinger at users.sourceforge.net (rhettinger@users.sourceforge.net) Date: Sun, 31 Jul 2005 08:36:09 -0700 Subject: [Python-checkins] python/dist/src/Objects setobject.c,1.35,1.36 Message-ID: Update of /cvsroot/python/python/dist/src/Objects In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27102 Modified Files: setobject.c Log Message: Improve variable names. Index: setobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v retrieving revision 1.35 retrieving revision 1.36 diff -u -d -r1.35 -r1.36 --- setobject.c 31 Jul 2005 13:09:28 -0000 1.35 +++ setobject.c 31 Jul 2005 15:36:06 -0000 1.36 @@ -42,8 +42,8 @@ register unsigned int perturb; register setentry *freeslot; register unsigned int mask = so->mask; - setentry *ep0 = so->table; - register setentry *ep; + setentry *entry0 = so->table; + register setentry *entry; register int restore_error; register int checked_error; register int cmp; @@ -51,26 +51,26 @@ PyObject *startkey; i = hash & mask; - ep = &ep0[i]; - if (ep->key == NULL || ep->key == key) - return ep; + entry = &entry0[i]; + if (entry->key == NULL || entry->key == key) + return entry; restore_error = checked_error = 0; - if (ep->key == dummy) - freeslot = ep; + if (entry->key == dummy) + freeslot = entry; else { - if (ep->hash == hash) { + if (entry->hash == hash) { /* error can't have been checked yet */ checked_error = 1; if (PyErr_Occurred()) { restore_error = 1; PyErr_Fetch(&err_type, &err_value, &err_tb); } - startkey = ep->key; + startkey = entry->key; cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); if (cmp < 0) PyErr_Clear(); - if (ep0 == so->table && ep->key == startkey) { + if (entry0 == so->table && entry->key == startkey) { if (cmp > 0) goto Done; } @@ -78,7 +78,7 @@ /* The compare did major nasty stuff to the * set: start over. */ - ep = set_lookkey(so, key, hash); + entry = set_lookkey(so, key, hash); goto Done; } } @@ -89,15 +89,15 @@ least likely outcome, so test for that last. */ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { i = (i << 2) + i + perturb + 1; - ep = &ep0[i & mask]; - if (ep->key == NULL) { + entry = &entry0[i & mask]; + if (entry->key == NULL) { if (freeslot != NULL) - ep = freeslot; + entry = freeslot; break; } - if (ep->key == key) + if (entry->key == key) break; - if (ep->hash == hash && ep->key != dummy) { + if (entry->hash == hash && entry->key != dummy) { if (!checked_error) { checked_error = 1; if (PyErr_Occurred()) { @@ -106,11 +106,11 @@ &err_tb); } } - startkey = ep->key; + startkey = entry->key; cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); if (cmp < 0) PyErr_Clear(); - if (ep0 == so->table && ep->key == startkey) { + if (entry0 == so->table && entry->key == startkey) { if (cmp > 0) break; } @@ -118,18 +118,18 @@ /* The compare did major nasty stuff to the * set: start over. */ - ep = set_lookkey(so, key, hash); + entry = set_lookkey(so, key, hash); break; } } - else if (ep->key == dummy && freeslot == NULL) - freeslot = ep; + else if (entry->key == dummy && freeslot == NULL) + freeslot = entry; } Done: if (restore_error) PyErr_Restore(err_type, err_value, err_tb); - return ep; + return entry; } /* @@ -149,8 +149,8 @@ register unsigned int perturb; register setentry *freeslot; register unsigned int mask = so->mask; - setentry *ep0 = so->table; - register setentry *ep; + setentry *entry0 = so->table; + register setentry *entry; /* Make sure this function doesn't have to handle non-string keys, including subclasses of str; e.g., one reason to subclass @@ -161,14 +161,14 @@ return set_lookkey(so, key, hash); } i = hash & mask; - ep = &ep0[i]; - if (ep->key == NULL || ep->key == key) - return ep; - if (ep->key == dummy) - freeslot = ep; + entry = &entry0[i]; + if (entry->key == NULL || entry->key == key) + return entry; + if (entry->key == dummy) + freeslot = entry; else { - if (ep->hash == hash && _PyString_Eq(ep->key, key)) - return ep; + if (entry->hash == hash && _PyString_Eq(entry->key, key)) + return entry; freeslot = NULL; } @@ -176,43 +176,43 @@ least likely outcome, so test for that last. */ for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { i = (i << 2) + i + perturb + 1; - ep = &ep0[i & mask]; - if (ep->key == NULL) - return freeslot == NULL ? ep : freeslot; - if (ep->key == key - || (ep->hash == hash - && ep->key != dummy - && _PyString_Eq(ep->key, key))) - return ep; - if (ep->key == dummy && freeslot == NULL) - freeslot = ep; + entry = &entry0[i & mask]; + if (entry->key == NULL) + return freeslot == NULL ? entry : freeslot; + if (entry->key == key + || (entry->hash == hash + && entry->key != dummy + && _PyString_Eq(entry->key, key))) + return entry; + if (entry->key == dummy && freeslot == NULL) + freeslot = entry; } } /* -Internal routine to insert a new item into the table. +Internal routine to insert a new key into the table. Used both by the internal resize routine and by the public insert routine. Eats a reference to key. */ static void set_insert_key(register PySetObject *so, PyObject *key, long hash) { - register setentry *ep; + register setentry *entry; typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long); assert(so->lookup != NULL); - ep = so->lookup(so, key, hash); - if (ep->key == NULL) { + entry = so->lookup(so, key, hash); + if (entry->key == NULL) { /* UNUSED */ so->fill++; - ep->key = key; - ep->hash = hash; + entry->key = key; + entry->hash = hash; so->used++; - } else if (ep->key == dummy) { + } else if (entry->key == dummy) { /* DUMMY */ - ep->key = key; - ep->hash = hash; + entry->key = key; + entry->hash = hash; so->used++; Py_DECREF(dummy); } else { @@ -223,14 +223,14 @@ /* Restructure the table by allocating a new table and reinserting all -items again. When entries have been deleted, the new table may +keys again. When entries have been deleted, the new table may actually be smaller than the old one. */ static int set_table_resize(PySetObject *so, int minused) { int newsize; - setentry *oldtable, *newtable, *ep; + setentry *oldtable, *newtable, *entry; int i; int is_oldtable_malloced; setentry small_copy[PySet_MINSIZE]; @@ -290,19 +290,19 @@ /* Copy the data over; this is refcount-neutral for active entries; dummy entries aren't copied over, of course */ - for (ep = oldtable; i > 0; ep++) { - if (ep->key == NULL) { + for (entry = oldtable; i > 0; entry++) { + if (entry->key == NULL) { /* UNUSED */ ; - } else if (ep->key == dummy) { + } else if (entry->key == dummy) { /* DUMMY */ --i; - assert(ep->key == dummy); - Py_DECREF(ep->key); + assert(entry->key == dummy); + Py_DECREF(entry->key); } else { /* ACTIVE */ --i; - set_insert_key(so, ep->key, ep->hash); + set_insert_key(so, entry->key, entry->hash); } } @@ -346,7 +346,7 @@ set_discard_internal(PySetObject *so, PyObject *key) { register long hash; - register setentry *ep; + register setentry *entry; PyObject *old_key; assert (PyAnySet_Check(so)); @@ -356,12 +356,12 @@ if (hash == -1) return -1; } - ep = (so->lookup)(so, key, hash); - if (ep->key == NULL || ep->key == dummy) + entry = (so->lookup)(so, key, hash); + if (entry->key == NULL || entry->key == dummy) return DISCARD_NOTFOUND; - old_key = ep->key; + old_key = entry->key; Py_INCREF(dummy); - ep->key = dummy; + entry->key = dummy; so->used--; Py_DECREF(old_key); return DISCARD_FOUND; @@ -370,7 +370,7 @@ static void set_clear_internal(PySetObject *so) { - setentry *ep, *table; + setentry *entry, *table; int table_is_malloced; int fill; setentry small_copy[PySet_MINSIZE]; @@ -413,18 +413,18 @@ * assert that the refcount on table is 1 now, i.e. that this function * has unique access to it, so decref side-effects can't alter it. */ - for (ep = table; fill > 0; ++ep) { + for (entry = table; fill > 0; ++entry) { #ifdef Py_DEBUG assert(i < n); ++i; #endif - if (ep->key) { + if (entry->key) { --fill; - Py_DECREF(ep->key); + Py_DECREF(entry->key); } #ifdef Py_DEBUG else - assert(ep->key == NULL || ep->key == dummy); + assert(entry->key == NULL || entry->key == dummy); #endif } @@ -446,45 +446,45 @@ * mutates the table. */ static int -set_next_internal(PySetObject *so, int *ppos, PyObject **pkey) +set_next_internal(PySetObject *so, int *pos, PyObject **key) { register int i, mask; - register setentry *ep; + register setentry *entry; assert (PyAnySet_Check(so)); - i = *ppos; + i = *pos; if (i < 0) return 0; - ep = so->table; + entry = so->table; mask = so->mask; - while (i <= mask && (ep[i].key == NULL || ep[i].key == dummy)) + while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) i++; - *ppos = i+1; + *pos = i+1; if (i > mask) return 0; - if (pkey) - *pkey = ep[i].key; + if (key) + *key = entry[i].key; return 1; } /* Methods */ static int -set_merge_internal(PySetObject *so, PyObject *b) +set_merge_internal(PySetObject *so, PyObject *otherset) { register PySetObject *other; register int i; setentry *entry; assert (PyAnySet_Check(so)); - assert (PyAnySet_Check(b)); + assert (PyAnySet_Check(otherset)); - other = (PySetObject*)b; + other = (PySetObject*)otherset; if (other == so || other->used == 0) /* a.update(a) or a.update({}); nothing to do */ return 0; /* Do one big resize at the start, rather than - * incrementally resizing as we insert new items. Expect + * incrementally resizing as we insert new keys. Expect * that there will be no (or few) overlapping keys. */ if ((so->fill + other->used)*3 >= (so->mask+1)*2) { @@ -563,18 +563,18 @@ 0, /* sq_concat */ }; -static PyObject *setiter_iternextkey(setiterobject *si) +static PyObject *setiter_iternext(setiterobject *si) { PyObject *key; register int i, mask; - register setentry *ep; - PySetObject *d = si->si_set; + register setentry *entry; + PySetObject *so = si->si_set; - if (d == NULL) + if (so == NULL) return NULL; - assert (PyAnySet_Check(d)); + assert (PyAnySet_Check(so)); - if (si->si_used != d->used) { + if (si->si_used != so->used) { PyErr_SetString(PyExc_RuntimeError, "Set changed size during iteration"); si->si_used = -1; /* Make this state sticky */ @@ -584,20 +584,20 @@ i = si->si_pos; if (i < 0) goto fail; - ep = d->table; - mask = d->mask; - while (i <= mask && (ep[i].key == NULL || ep[i].key == dummy)) + entry = so->table; + mask = so->mask; + while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) i++; si->si_pos = i+1; if (i > mask) goto fail; si->len--; - key = ep[i].key; + key = entry[i].key; Py_INCREF(key); return key; fail: - Py_DECREF(d); + Py_DECREF(so); si->si_set = NULL; return NULL; } @@ -605,7 +605,7 @@ PyTypeObject PySetIter_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ - "Set-keyiterator", /* tp_name */ + "setiterator", /* tp_name */ sizeof(setiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ @@ -631,7 +631,7 @@ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)setiter_iternextkey, /* tp_iternext */ + (iternextfunc)setiter_iternext, /* tp_iternext */ }; /***** Derived functions (table accesses only done with above primitives *****/ @@ -650,7 +650,7 @@ static PyObject * set_update(PySetObject *so, PyObject *other) { - PyObject *item, *it; + PyObject *key, *it; if (PyAnySet_Check(other)) { if (set_merge_internal(so, other) == -1) @@ -659,10 +659,10 @@ } if (PyDict_Check(other)) { - PyObject *value, *item; + PyObject *key, *value; int pos = 0; - while (PyDict_Next(other, &pos, &item, &value)) { - if (set_add_internal(so, item) == -1) + while (PyDict_Next(other, &pos, &key, &value)) { + if (set_add_internal(so, key) == -1) return NULL; } Py_RETURN_NONE; @@ -672,13 +672,13 @@ if (it == NULL) return NULL; - while ((item = PyIter_Next(it)) != NULL) { - if (set_add_internal(so, item) == -1) { + while ((key = PyIter_Next(it)) != NULL) { + if (set_add_internal(so, key) == -1) { Py_DECREF(it); - Py_DECREF(item); + Py_DECREF(key); return NULL; } - Py_DECREF(item); + Py_DECREF(key); } Py_DECREF(it); if (PyErr_Occurred()) @@ -754,7 +754,7 @@ static void set_dealloc(PySetObject *so) { - register setentry *ep; + register setentry *entry; int fill = so->fill; PyObject_GC_UnTrack(so); @@ -762,10 +762,10 @@ if (so->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) so); - for (ep = so->table; fill > 0; ep++) { - if (ep->key) { + for (entry = so->table; fill > 0; entry++) { + if (entry->key) { --fill; - Py_DECREF(ep->key); + Py_DECREF(entry->key); } } if (so->table != so->smalltable) @@ -778,11 +778,11 @@ static int set_traverse(PySetObject *so, visitproc visit, void *arg) { - int i = 0; - PyObject *pk; + int pos = 0; + PyObject *key; - while (set_next_internal(so, &i, &pk)) - Py_VISIT(pk); + while (set_next_internal(so, &pos, &key)) + Py_VISIT(key); return 0; } @@ -834,25 +834,25 @@ memcpy(b->smalltable, tab, sizeof(tab)); } - h = a->hash; a->hash = b->hash; b->hash = h; + h = a->hash; a->hash = b->hash; b->hash = h; } static int set_contains(PySetObject *so, PyObject *key) { - PyObject *tmp; + PyObject *tmpkey; int result; result = set_contains_internal(so, key); if (result == -1 && PyAnySet_Check(key)) { PyErr_Clear(); - tmp = make_new_set(&PyFrozenSet_Type, NULL); - if (tmp == NULL) + tmpkey = make_new_set(&PyFrozenSet_Type, NULL); + if (tmpkey == NULL) return -1; - set_swap_bodies((PySetObject *)tmp, (PySetObject *)key); - result = set_contains_internal(so, tmp); - set_swap_bodies((PySetObject *)tmp, (PySetObject *)key); - Py_DECREF(tmp); + set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); + result = set_contains_internal(so, tmpkey); + set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key); + Py_DECREF(tmpkey); } return result; } @@ -942,7 +942,7 @@ set_intersection(PySetObject *so, PyObject *other) { PySetObject *result; - PyObject *item, *it, *tmp; + PyObject *key, *it, *tmp; result = (PySetObject *)make_new_set(so->ob_type, NULL); if (result == NULL) @@ -956,9 +956,9 @@ if (PyAnySet_Check(other)) { int pos = 0; - while (set_next_internal((PySetObject *)other, &pos, &item)) { - if (set_contains_internal(so, item)) { - if (set_add_internal(result, item) == -1) { + while (set_next_internal((PySetObject *)other, &pos, &key)) { + if (set_contains_internal(so, key)) { + if (set_add_internal(result, key) == -1) { Py_DECREF(result); return NULL; } @@ -973,16 +973,16 @@ return NULL; } - while ((item = PyIter_Next(it)) != NULL) { - if (set_contains_internal(so, item)) { - if (set_add_internal(result, item) == -1) { + while ((key = PyIter_Next(it)) != NULL) { + if (set_contains_internal(so, key)) { + if (set_add_internal(result, key) == -1) { Py_DECREF(it); Py_DECREF(result); - Py_DECREF(item); + Py_DECREF(key); return NULL; } } - Py_DECREF(item); + Py_DECREF(key); } Py_DECREF(it); if (PyErr_Occurred()) { @@ -1043,19 +1043,19 @@ static PyObject * set_difference_update(PySetObject *so, PyObject *other) { - PyObject *item, *it; + PyObject *key, *it; it = PyObject_GetIter(other); if (it == NULL) return NULL; - while ((item = PyIter_Next(it)) != NULL) { - if (set_discard_internal(so, item) == -1) { + while ((key = PyIter_Next(it)) != NULL) { + if (set_discard_internal(so, key) == -1) { Py_DECREF(it); - Py_DECREF(item); + Py_DECREF(key); return NULL; } - Py_DECREF(item); + Py_DECREF(key); } Py_DECREF(it); if (PyErr_Occurred()) @@ -1425,9 +1425,9 @@ } static PyObject * -set_add(PySetObject *so, PyObject *item) +set_add(PySetObject *so, PyObject *key) { - if (set_add_internal(so, item) == -1) + if (set_add_internal(so, key) == -1) return NULL; Py_RETURN_NONE; } @@ -1438,27 +1438,27 @@ This has no effect if the element is already present."); static PyObject * -set_remove(PySetObject *so, PyObject *item) +set_remove(PySetObject *so, PyObject *key) { - PyObject *tmp, *result; + PyObject *tmpkey, *result; int rv; - if (PyType_IsSubtype(item->ob_type, &PySet_Type)) { - tmp = make_new_set(&PyFrozenSet_Type, NULL); - if (tmp == NULL) + if (PyType_IsSubtype(key->ob_type, &PySet_Type)) { + tmpkey = make_new_set(&PyFrozenSet_Type, NULL); + if (tmpkey == NULL) return NULL; - set_swap_bodies((PySetObject *)item, (PySetObject *)tmp); - result = set_remove(so, tmp); - set_swap_bodies((PySetObject *)item, (PySetObject *)tmp); - Py_DECREF(tmp); + set_swap_bodies((PySetObject *)key, (PySetObject *)tmpkey); + result = set_remove(so, tmpkey); + set_swap_bodies((PySetObject *)key, (PySetObject *)tmpkey); + Py_DECREF(tmpkey); return result; } - rv = set_discard_internal(so, item); + rv = set_discard_internal(so, key); if (rv == -1) return NULL; else if (rv == DISCARD_NOTFOUND) { - PyErr_SetObject(PyExc_KeyError, item); + PyErr_SetObject(PyExc_KeyError, key); return NULL; } Py_RETURN_NONE; @@ -1470,22 +1470,22 @@ If the element is not a member, raise a KeyError."); static PyObject * -set_discard(PySetObject *so, PyObject *item) +set_discard(PySetObject *so, PyObject *key) { - PyObject *tmp, *result; + PyObject *tmpkey, *result; - if (PyType_IsSubtype(item->ob_type, &PySet_Type)) { - tmp = make_new_set(&PyFrozenSet_Type, NULL); - if (tmp == NULL) + if (PyType_IsSubtype(key->ob_type, &PySet_Type)) { + tmpkey = make_new_set(&PyFrozenSet_Type, NULL); + if (tmpkey == NULL) return NULL; - set_swap_bodies((PySetObject *)item, (PySetObject *)tmp); - result = set_discard(so, tmp); - set_swap_bodies((PySetObject *)item, (PySetObject *)tmp); - Py_DECREF(tmp); + set_swap_bodies((PySetObject *)key, (PySetObject *)tmpkey); + result = set_discard(so, tmpkey); + set_swap_bodies((PySetObject *)key, (PySetObject *)tmpkey); + Py_DECREF(tmpkey); return result; } - if (set_discard_internal(so, item) == -1) + if (set_discard_internal(so, key) == -1) return NULL; Py_RETURN_NONE; } From pje at users.sourceforge.net Sun Jul 31 18:31:21 2005 From: pje at users.sourceforge.net (pje@users.sourceforge.net) Date: Sun, 31 Jul 2005 09:31:21 -0700 Subject: [Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.54, 1.55 setup.py, 1.33, 1.34 Message-ID: Update of /cvsroot/python/python/nondist/sandbox/setuptools In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5869 Modified Files: pkg_resources.py setup.py Log Message: Misc. bugs reported by Ian Bicking and Ashley Walsh. Index: pkg_resources.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v retrieving revision 1.54 retrieving revision 1.55 diff -u -d -r1.54 -r1.55 --- pkg_resources.py 25 Jul 2005 03:12:50 -0000 1.54 +++ pkg_resources.py 31 Jul 2005 16:31:17 -0000 1.55 @@ -227,7 +227,7 @@ """Return a current distribution object for a Requirement or string""" if isinstance(dist,basestring): dist = Requirement.parse(dist) if isinstance(dist,Requirement): dist = get_provider(dist) - if not isintance(dist,Distribution): + if not isinstance(dist,Distribution): raise TypeError("Expected string, Requirement, or Distribution", dist) return dist @@ -1443,7 +1443,7 @@ path, parent = sys.path, None if '.' in packageName: - parent = '.'.join(package.split('.')[:-1]) + parent = '.'.join(packageName.split('.')[:-1]) declare_namespace(parent) __import__(parent) try: Index: setup.py =================================================================== RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- setup.py 24 Jul 2005 22:47:05 -0000 1.33 +++ setup.py 31 Jul 2005 16:31:18 -0000 1.34 @@ -44,7 +44,7 @@ entry_points = { "distutils.commands" : [ "%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals() - for cmd in SETUP_COMMANDS if cmd!="build_py" or sys.version>="2.4" + for cmd in SETUP_COMMANDS if cmd!="build_py" or sys.version<"2.4" ], },