mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Remove regsub, reconvert, regex, regex_syntax and everything under lib-old.
This commit is contained in:
		
							parent
							
								
									efbeaef1c1
								
							
						
					
					
						commit
						10be10cbe7
					
				
					 69 changed files with 73 additions and 7120 deletions
				
			
		|  | @ -6,7 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import string | import string | ||||||
| import regex | import re | ||||||
| import getopt | import getopt | ||||||
| import time | import time | ||||||
| 
 | 
 | ||||||
|  | @ -35,9 +35,9 @@ def main(): | ||||||
|     for rev in allrevs: |     for rev in allrevs: | ||||||
|         formatrev(rev, prefix) |         formatrev(rev, prefix) | ||||||
| 
 | 
 | ||||||
| parsedateprog = regex.compile( | parsedateprog = re.compile( | ||||||
|     '^date: \([0-9]+\)/\([0-9]+\)/\([0-9]+\) ' + |     '^date: ([0-9]+)/([0-9]+)/([0-9]+) ' + | ||||||
|     '\([0-9]+\):\([0-9]+\):\([0-9]+\);  author: \([^ ;]+\)') |     '([0-9]+):([0-9]+):([0-9]+);  author: ([^ ;]+)') | ||||||
| 
 | 
 | ||||||
| authormap = { | authormap = { | ||||||
|     'guido': 'Guido van Rossum  <guido@cnri.reston.va.us>', |     'guido': 'Guido van Rossum  <guido@cnri.reston.va.us>', | ||||||
|  | @ -70,7 +70,7 @@ def formatrev(rev, prefix): | ||||||
|         print |         print | ||||||
|         print |         print | ||||||
| 
 | 
 | ||||||
| startprog = regex.compile("^Working file: \(.*\)$") | startprog = re.compile("^Working file: (.*)$") | ||||||
| 
 | 
 | ||||||
| def getnextfile(f): | def getnextfile(f): | ||||||
|     while 1: |     while 1: | ||||||
|  |  | ||||||
|  | @ -6,12 +6,12 @@ | ||||||
| # Python script for bumping up an RCS major revision number. | # Python script for bumping up an RCS major revision number. | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import rcslib | import rcslib | ||||||
| import string | import string | ||||||
| 
 | 
 | ||||||
| WITHLOCK = 1 | WITHLOCK = 1 | ||||||
| majorrev_re = regex.compile('^[0-9]+') | majorrev_re = re.compile('^[0-9]+') | ||||||
| 
 | 
 | ||||||
| dir = rcslib.RCS() | dir = rcslib.RCS() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
| 
 | 
 | ||||||
| import fnmatch | import fnmatch | ||||||
| import os | import os | ||||||
| import regsub | import re | ||||||
| import string | import string | ||||||
| import tempfile | import tempfile | ||||||
| 
 | 
 | ||||||
|  | @ -150,7 +150,7 @@ def checkin(self, name_rev, message=None, otherflags=""): | ||||||
|             cmd = 'ci %s%s -t%s %s %s' % \ |             cmd = 'ci %s%s -t%s %s %s' % \ | ||||||
|                   (lockflag, rev, f.name, otherflags, name) |                   (lockflag, rev, f.name, otherflags, name) | ||||||
|         else: |         else: | ||||||
|             message = regsub.gsub('\([\\"$`]\)', '\\\\\\1', message) |             message = re.sub(r'([\"$`])', r'\\\1', message) | ||||||
|             cmd = 'ci %s%s -m"%s" %s %s' % \ |             cmd = 'ci %s%s -m"%s" %s %s' % \ | ||||||
|                   (lockflag, rev, message, otherflags, name) |                   (lockflag, rev, message, otherflags, name) | ||||||
|         return self._system(cmd) |         return self._system(cmd) | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ | ||||||
| # into a program for a different change to Python programs... | # into a program for a different change to Python programs... | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import os | import os | ||||||
| from stat import * | from stat import * | ||||||
| import string | import string | ||||||
|  | @ -53,7 +53,7 @@ def main(): | ||||||
|             if fix(arg): bad = 1 |             if fix(arg): bad = 1 | ||||||
|     sys.exit(bad) |     sys.exit(bad) | ||||||
| 
 | 
 | ||||||
| ispythonprog = regex.compile('^[a-zA-Z0-9_]+\.py$') | ispythonprog = re.compile('^[a-zA-Z0-9_]+\.py$') | ||||||
| def ispython(name): | def ispython(name): | ||||||
|     return ispythonprog.match(name) >= 0 |     return ispythonprog.match(name) >= 0 | ||||||
| 
 | 
 | ||||||
|  | @ -104,7 +104,7 @@ def fix(filename): | ||||||
|         if lineno == 1 and g is None and line[:2] == '#!': |         if lineno == 1 and g is None and line[:2] == '#!': | ||||||
|             # Check for non-Python scripts |             # Check for non-Python scripts | ||||||
|             words = string.split(line[2:]) |             words = string.split(line[2:]) | ||||||
|             if words and regex.search('[pP]ython', words[0]) < 0: |             if words and re.search('[pP]ython', words[0]) < 0: | ||||||
|                 msg = filename + ': ' + words[0] |                 msg = filename + ': ' + words[0] | ||||||
|                 msg = msg + ' script; not fixed\n' |                 msg = msg + ' script; not fixed\n' | ||||||
|                 err(msg) |                 err(msg) | ||||||
|  |  | ||||||
|  | @ -13,12 +13,12 @@ | ||||||
| 
 | 
 | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import string | import string | ||||||
| import getopt | import getopt | ||||||
| 
 | 
 | ||||||
| pat = '^\([a-zA-Z0-9 :]*\)!\(.*\)!\(.*\)!\([<>].*\)!\([0-9]+\)!\([0-9]+\)$' | pat = '^([a-zA-Z0-9 :]*)!(.*)!(.*)!([<>].*)!([0-9]+)!([0-9]+)$' | ||||||
| prog = regex.compile(pat) | prog = re.compile(pat) | ||||||
| 
 | 
 | ||||||
| def main(): | def main(): | ||||||
|     maxitems = 25 |     maxitems = 25 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
| import os | import os | ||||||
| import stat | import stat | ||||||
| import getopt | import getopt | ||||||
| import regex | import re | ||||||
| 
 | 
 | ||||||
| def main(): | def main(): | ||||||
|     dofile = mmdf |     dofile = mmdf | ||||||
|  | @ -45,7 +45,7 @@ def main(): | ||||||
|     if sts: |     if sts: | ||||||
|         sys.exit(sts) |         sys.exit(sts) | ||||||
| 
 | 
 | ||||||
| numeric = regex.compile('[1-9][0-9]*') | numeric = re.compile('[1-9][0-9]*') | ||||||
| 
 | 
 | ||||||
| def mh(dir): | def mh(dir): | ||||||
|     sts = 0 |     sts = 0 | ||||||
|  |  | ||||||
|  | @ -8,10 +8,10 @@ | ||||||
| 
 | 
 | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| 
 | 
 | ||||||
| pat = '^\([^: \t\n]+\):\([1-9][0-9]*\):' | pat = '^([^: \t\n]+):([1-9][0-9]*):' | ||||||
| prog = regex.compile(pat) | prog = re.compile(pat) | ||||||
| 
 | 
 | ||||||
| class FileObj: | class FileObj: | ||||||
|     def __init__(self, filename): |     def __init__(self, filename): | ||||||
|  |  | ||||||
|  | @ -13,7 +13,6 @@ | ||||||
| import sys | import sys | ||||||
| import time | import time | ||||||
| import struct | import struct | ||||||
| import regsub |  | ||||||
| from socket import * | from socket import * | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| # Widget to display a man page | # Widget to display a man page | ||||||
| 
 | 
 | ||||||
| import regex | import re | ||||||
| from Tkinter import * | from Tkinter import * | ||||||
| from Tkinter import _tkinter | from Tkinter import _tkinter | ||||||
| from ScrolledText import ScrolledText | from ScrolledText import ScrolledText | ||||||
|  | @ -11,10 +11,10 @@ | ||||||
| 
 | 
 | ||||||
| # XXX Recognizing footers is system dependent | # XXX Recognizing footers is system dependent | ||||||
| # (This one works for IRIX 5.2 and Solaris 2.2) | # (This one works for IRIX 5.2 and Solaris 2.2) | ||||||
| footerprog = regex.compile( | footerprog = re.compile( | ||||||
|         '^     Page [1-9][0-9]*[ \t]+\|^.*Last change:.*[1-9][0-9]*\n') |         '^     Page [1-9][0-9]*[ \t]+\|^.*Last change:.*[1-9][0-9]*\n') | ||||||
| emptyprog = regex.compile('^[ \t]*\n') | emptyprog = re.compile('^[ \t]*\n') | ||||||
| ulprog = regex.compile('^[ \t]*[Xv!_][Xv!_ \t]*\n') | ulprog = re.compile('^[ \t]*[Xv!_][Xv!_ \t]*\n') | ||||||
| 
 | 
 | ||||||
| # Basic Man Page class -- does not disable editing | # Basic Man Page class -- does not disable editing | ||||||
| class EditableManPage(ScrolledText): | class EditableManPage(ScrolledText): | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import getopt | import getopt | ||||||
| import string | import string | ||||||
| import mhlib | import mhlib | ||||||
|  | @ -157,7 +157,7 @@ def scan_unpost(e): | ||||||
|     scanmenu.unpost() |     scanmenu.unpost() | ||||||
|     scanmenu.invoke('active') |     scanmenu.invoke('active') | ||||||
| 
 | 
 | ||||||
| scanparser = regex.compile('^ *\([0-9]+\)') | scanparser = re.compile('^ *([0-9]+)') | ||||||
| 
 | 
 | ||||||
| def open_folder(e=None): | def open_folder(e=None): | ||||||
|     global folder, mhf |     global folder, mhf | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ | ||||||
| import sys | import sys | ||||||
| import os | import os | ||||||
| import string | import string | ||||||
| import regex | import re | ||||||
| from Tkinter import * | from Tkinter import * | ||||||
| from ManPage import ManPage | from ManPage import ManPage | ||||||
| 
 | 
 | ||||||
|  | @ -208,15 +208,15 @@ def search_string(self, search): | ||||||
|             print 'Empty search string' |             print 'Empty search string' | ||||||
|             return |             return | ||||||
|         if not self.casevar.get(): |         if not self.casevar.get(): | ||||||
|             map = regex.casefold |             map = re.IGNORECASE | ||||||
|         else: |         else: | ||||||
|             map = None |             map = None | ||||||
|         try: |         try: | ||||||
|             if map: |             if map: | ||||||
|                 prog = regex.compile(search, map) |                 prog = re.compile(search, map) | ||||||
|             else: |             else: | ||||||
|                 prog = regex.compile(search) |                 prog = re.compile(search) | ||||||
|         except regex.error, msg: |         except re.error, msg: | ||||||
|             self.frame.bell() |             self.frame.bell() | ||||||
|             print 'Regex error:', msg |             print 'Regex error:', msg | ||||||
|             return |             return | ||||||
|  |  | ||||||
|  | @ -33,11 +33,8 @@ This document is available from | ||||||
| 
 | 
 | ||||||
| The \module{re} module was added in Python 1.5, and provides | The \module{re} module was added in Python 1.5, and provides | ||||||
| Perl-style regular expression patterns.  Earlier versions of Python | Perl-style regular expression patterns.  Earlier versions of Python | ||||||
| came with the \module{regex} module, which provides Emacs-style | came with the \module{regex} module, which provided Emacs-style | ||||||
| patterns.  Emacs-style patterns are slightly less readable and | patterns.  \module{regex} module was removed in Python 2.5. | ||||||
| don't provide as many features, so there's not much reason to use |  | ||||||
| the \module{regex} module when writing new code, though you might |  | ||||||
| encounter old code that uses it. |  | ||||||
| 
 | 
 | ||||||
| Regular expressions (or REs) are essentially a tiny, highly | Regular expressions (or REs) are essentially a tiny, highly | ||||||
| specialized programming language embedded inside Python and made | specialized programming language embedded inside Python and made | ||||||
|  | @ -1458,7 +1455,7 @@ Jeffrey Friedl's \citetitle{Mastering Regular Expressions}, published | ||||||
| by O'Reilly.  Unfortunately, it exclusively concentrates on Perl and | by O'Reilly.  Unfortunately, it exclusively concentrates on Perl and | ||||||
| Java's flavours of regular expressions, and doesn't contain any Python | Java's flavours of regular expressions, and doesn't contain any Python | ||||||
| material at all, so it won't be useful as a reference for programming | material at all, so it won't be useful as a reference for programming | ||||||
| in Python.  (The first edition covered Python's now-obsolete | in Python.  (The first edition covered Python's now-removed | ||||||
| \module{regex} module, which won't help you much.)  Consider checking | \module{regex} module, which won't help you much.)  Consider checking | ||||||
| it out from your library. | it out from your library. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -87,7 +87,6 @@ and how to embed it in other applications. | ||||||
| \input{libstrings}              % String Services | \input{libstrings}              % String Services | ||||||
| \input{libstring} | \input{libstring} | ||||||
| \input{libre} | \input{libre} | ||||||
| \input{libreconvert} |  | ||||||
| \input{libstruct}   % XXX also/better in File Formats? | \input{libstruct}   % XXX also/better in File Formats? | ||||||
| \input{libdifflib} | \input{libdifflib} | ||||||
| \input{libstringio} | \input{libstringio} | ||||||
|  | @ -454,8 +453,6 @@ and how to embed it in other applications. | ||||||
| %\input{libcmpcache} | %\input{libcmpcache} | ||||||
| %\input{libcmp} | %\input{libcmp} | ||||||
| %\input{libni} | %\input{libni} | ||||||
| %\input{libregex} |  | ||||||
| %\input{libregsub} |  | ||||||
| 
 | 
 | ||||||
| \chapter{Reporting Bugs} | \chapter{Reporting Bugs} | ||||||
| \input{reportingbugs} | \input{reportingbugs} | ||||||
|  |  | ||||||
|  | @ -566,9 +566,6 @@ ignored. | ||||||
| >>> re.split('\W+', 'Words, words, words.', 1) | >>> re.split('\W+', 'Words, words, words.', 1) | ||||||
| ['Words', 'words, words.'] | ['Words', 'words, words.'] | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
| 
 |  | ||||||
|   This function combines and extends the functionality of |  | ||||||
|   the old \function{regsub.split()} and \function{regsub.splitx()}. |  | ||||||
| \end{funcdesc} | \end{funcdesc} | ||||||
| 
 | 
 | ||||||
| \begin{funcdesc}{findall}{pattern, string\optional{, flags}} | \begin{funcdesc}{findall}{pattern, string\optional{, flags}} | ||||||
|  | @ -943,7 +940,7 @@ the message \code{maximum recursion limit} exceeded. For example, | ||||||
| >>> re.match('Begin (\w| )*? end', s).end() | >>> re.match('Begin (\w| )*? end', s).end() | ||||||
| Traceback (most recent call last): | Traceback (most recent call last): | ||||||
|   File "<stdin>", line 1, in ? |   File "<stdin>", line 1, in ? | ||||||
|   File "/usr/local/lib/python2.3/sre.py", line 132, in match |   File "/usr/local/lib/python2.5/re.py", line 132, in match | ||||||
|     return _compile(pattern, flags).match(string) |     return _compile(pattern, flags).match(string) | ||||||
| RuntimeError: maximum recursion limit exceeded | RuntimeError: maximum recursion limit exceeded | ||||||
| \end{verbatim} | \end{verbatim} | ||||||
|  |  | ||||||
|  | @ -1,80 +0,0 @@ | ||||||
| \section{\module{reconvert} --- |  | ||||||
|          Convert regular expressions from regex to re form} |  | ||||||
| \declaremodule{standard}{reconvert} |  | ||||||
| \moduleauthor{Andrew M. Kuchling}{amk@amk.ca} |  | ||||||
| \sectionauthor{Skip Montanaro}{skip@pobox.com} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| \modulesynopsis{Convert regex-, emacs- or sed-style regular expressions |  | ||||||
| to re-style syntax.} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| This module provides a facility to convert regular expressions from the |  | ||||||
| syntax used by the deprecated \module{regex} module to those used by the |  | ||||||
| newer \module{re} module.  Because of similarity between the regular |  | ||||||
| expression syntax of \code{sed(1)} and \code{emacs(1)} and the |  | ||||||
| \module{regex} module, it is also helpful to convert patterns written for |  | ||||||
| those tools to \module{re} patterns. |  | ||||||
| 
 |  | ||||||
| When used as a script, a Python string literal (or any other expression |  | ||||||
| evaluating to a string) is read from stdin, and the translated expression is |  | ||||||
| written to stdout as a string literal.  Unless stdout is a tty, no trailing |  | ||||||
| newline is written to stdout.  This is done so that it can be used with |  | ||||||
| Emacs \code{C-U M-|} (shell-command-on-region) which filters the region |  | ||||||
| through the shell command. |  | ||||||
| 
 |  | ||||||
| \begin{seealso} |  | ||||||
|   \seetitle{Mastering Regular Expressions}{Book on regular expressions |  | ||||||
|             by Jeffrey Friedl, published by O'Reilly.  The second  |  | ||||||
|             edition of the book no longer covers Python at all,  |  | ||||||
|             but the first edition covered writing good regular expression |  | ||||||
|             patterns in great detail.} |  | ||||||
| \end{seealso} |  | ||||||
| 
 |  | ||||||
| \subsection{Module Contents} |  | ||||||
| \nodename{Contents of Module reconvert} |  | ||||||
| 
 |  | ||||||
| The module defines two functions and a handful of constants. |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{convert}{pattern\optional{, syntax=None}} |  | ||||||
|  Convert a \var{pattern} representing a \module{regex}-stype regular |  | ||||||
|  expression into a \module{re}-style regular expression.  The optional |  | ||||||
|  \var{syntax} parameter is a bitwise-or'd set of flags that control what |  | ||||||
|  constructs are converted.  See below for a description of the various |  | ||||||
|  constants. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{quote}{s\optional{, quote=None}} |  | ||||||
|  Convert a string object to a quoted string literal. |  | ||||||
| 
 |  | ||||||
|  This is similar to \function{repr} but will return a "raw" string (r'...' |  | ||||||
|  or r"...") when the string contains backslashes, instead of doubling all |  | ||||||
|  backslashes.  The resulting string does not always evaluate to the same |  | ||||||
|  string as the original; however it will do just the right thing when passed |  | ||||||
|  into re.compile(). |  | ||||||
| 
 |  | ||||||
|  The optional second argument forces the string quote; it must be a single |  | ||||||
|  character which is a valid Python string quote.  Note that prior to Python |  | ||||||
|  2.5 this would not accept triple-quoted string delimiters. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{RE_NO_BK_PARENS} |  | ||||||
|  Suppress paren conversion.  This should be omitted when converting |  | ||||||
|  \code{sed}-style or \code{emacs}-style regular expressions. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{RE_NO_BK_VBAR} |  | ||||||
|  Suppress vertical bar conversion.  This should be omitted when converting |  | ||||||
|  \code{sed}-style or \code{emacs}-style regular expressions. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{RE_BK_PLUS_QM} |  | ||||||
|  Enable conversion of \code{+} and \code{?} characters.  This should be |  | ||||||
|  added to the \var{syntax} arg of \function{convert} when converting |  | ||||||
|  \code{sed}-style regular expressions and omitted when converting |  | ||||||
|  \code{emacs}-style regular expressions. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{RE_NEWLINE_OR} |  | ||||||
|  When set, newline characters are replaced by \code{|}. |  | ||||||
| \end{datadesc} |  | ||||||
|  | @ -1,370 +0,0 @@ | ||||||
| \section{\module{regex} --- |  | ||||||
|          Regular expression operations} |  | ||||||
| \declaremodule{builtin}{regex} |  | ||||||
| 
 |  | ||||||
| \modulesynopsis{Regular expression search and match operations. |  | ||||||
|                 \strong{Obsolete!}} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| This module provides regular expression matching operations similar to |  | ||||||
| those found in Emacs. |  | ||||||
| 
 |  | ||||||
| \strong{Obsolescence note:} |  | ||||||
| This module is obsolete as of Python version 1.5; it is still being |  | ||||||
| maintained because much existing code still uses it.  All new code in |  | ||||||
| need of regular expressions should use the new |  | ||||||
| \code{re}\refstmodindex{re} module, which supports the more powerful |  | ||||||
| and regular Perl-style regular expressions.  Existing code should be |  | ||||||
| converted.  The standard library module |  | ||||||
| \code{reconvert}\refstmodindex{reconvert} helps in converting |  | ||||||
| \code{regex} style regular expressions to \code{re}\refstmodindex{re} |  | ||||||
| style regular expressions.  (For more conversion help, see Andrew |  | ||||||
| Kuchling's\index{Kuchling, Andrew} ``\module{regex-to-re} HOWTO'' at |  | ||||||
| \url{http://www.python.org/doc/howto/regex-to-re/}.) |  | ||||||
| 
 |  | ||||||
| By default the patterns are Emacs-style regular expressions |  | ||||||
| (with one exception).  There is |  | ||||||
| a way to change the syntax to match that of several well-known |  | ||||||
| \UNIX{} utilities.  The exception is that Emacs' \samp{\e s} |  | ||||||
| pattern is not supported, since the original implementation references |  | ||||||
| the Emacs syntax tables. |  | ||||||
| 
 |  | ||||||
| This module is 8-bit clean: both patterns and strings may contain null |  | ||||||
| bytes and characters whose high bit is set. |  | ||||||
| 
 |  | ||||||
| \strong{Please note:} There is a little-known fact about Python string |  | ||||||
| literals which means that you don't usually have to worry about |  | ||||||
| doubling backslashes, even though they are used to escape special |  | ||||||
| characters in string literals as well as in regular expressions.  This |  | ||||||
| is because Python doesn't remove backslashes from string literals if |  | ||||||
| they are followed by an unrecognized escape character. |  | ||||||
| \emph{However}, if you want to include a literal \dfn{backslash} in a |  | ||||||
| regular expression represented as a string literal, you have to |  | ||||||
| \emph{quadruple} it or enclose it in a singleton character class. |  | ||||||
| E.g.\  to extract \LaTeX\ \samp{\e section\{\textrm{\ldots}\}} headers |  | ||||||
| from a document, you can use this pattern: |  | ||||||
| \code{'[\e ]section\{\e (.*\e )\}'}.  \emph{Another exception:} |  | ||||||
| the escape sequence \samp{\e b} is significant in string literals |  | ||||||
| (where it means the ASCII bell character) as well as in Emacs regular |  | ||||||
| expressions (where it stands for a word boundary), so in order to |  | ||||||
| search for a word boundary, you should use the pattern \code{'\e \e b'}. |  | ||||||
| Similarly, a backslash followed by a digit 0-7 should be doubled to |  | ||||||
| avoid interpretation as an octal escape. |  | ||||||
| 
 |  | ||||||
| \subsection{Regular Expressions} |  | ||||||
| 
 |  | ||||||
| A regular expression (or RE) specifies a set of strings that matches |  | ||||||
| it; the functions in this module let you check if a particular string |  | ||||||
| matches a given regular expression (or if a given regular expression |  | ||||||
| matches a particular string, which comes down to the same thing). |  | ||||||
| 
 |  | ||||||
| Regular expressions can be concatenated to form new regular |  | ||||||
| expressions; if \emph{A} and \emph{B} are both regular expressions, |  | ||||||
| then \emph{AB} is also an regular expression.  If a string \emph{p} |  | ||||||
| matches A and another string \emph{q} matches B, the string \emph{pq} |  | ||||||
| will match AB.  Thus, complex expressions can easily be constructed |  | ||||||
| from simpler ones like the primitives described here.  For details of |  | ||||||
| the theory and implementation of regular expressions, consult almost |  | ||||||
| any textbook about compiler construction. |  | ||||||
| 
 |  | ||||||
| % XXX The reference could be made more specific, say to  |  | ||||||
| % "Compilers: Principles, Techniques and Tools", by Alfred V. Aho,  |  | ||||||
| % Ravi Sethi, and Jeffrey D. Ullman, or some FA text.    |  | ||||||
| 
 |  | ||||||
| A brief explanation of the format of regular expressions follows. |  | ||||||
| 
 |  | ||||||
| Regular expressions can contain both special and ordinary characters. |  | ||||||
| Ordinary characters, like '\code{A}', '\code{a}', or '\code{0}', are |  | ||||||
| the simplest regular expressions; they simply match themselves.  You |  | ||||||
| can concatenate ordinary characters, so '\code{last}' matches the |  | ||||||
| characters 'last'.  (In the rest of this section, we'll write RE's in |  | ||||||
| \code{this special font}, usually without quotes, and strings to be |  | ||||||
| matched 'in single quotes'.) |  | ||||||
| 
 |  | ||||||
| Special characters either stand for classes of ordinary characters, or |  | ||||||
| affect how the regular expressions around them are interpreted. |  | ||||||
| 
 |  | ||||||
| The special characters are: |  | ||||||
| \begin{itemize} |  | ||||||
| \item[\code{.}] (Dot.)  Matches any character except a newline. |  | ||||||
| \item[\code{\^}] (Caret.)  Matches the start of the string. |  | ||||||
| \item[\code{\$}] Matches the end of the string.   |  | ||||||
| \code{foo} matches both 'foo' and 'foobar', while the regular |  | ||||||
| expression '\code{foo\$}' matches only 'foo'. |  | ||||||
| \item[\code{*}] Causes the resulting RE to |  | ||||||
| match 0 or more repetitions of the preceding RE.  \code{ab*} will |  | ||||||
| match 'a', 'ab', or 'a' followed by any number of 'b's. |  | ||||||
| \item[\code{+}] Causes the |  | ||||||
| resulting RE to match 1 or more repetitions of the preceding RE. |  | ||||||
| \code{ab+} will match 'a' followed by any non-zero number of 'b's; it |  | ||||||
| will not match just 'a'. |  | ||||||
| \item[\code{?}] Causes the resulting RE to |  | ||||||
| match 0 or 1 repetitions of the preceding RE.  \code{ab?} will |  | ||||||
| match either 'a' or 'ab'. |  | ||||||
| 
 |  | ||||||
| \item[\code{\e}] Either escapes special characters (permitting you to match |  | ||||||
| characters like '*?+\&\$'), or signals a special sequence; special |  | ||||||
| sequences are discussed below.  Remember that Python also uses the |  | ||||||
| backslash as an escape sequence in string literals; if the escape |  | ||||||
| sequence isn't recognized by Python's parser, the backslash and |  | ||||||
| subsequent character are included in the resulting string.  However, |  | ||||||
| if Python would recognize the resulting sequence, the backslash should |  | ||||||
| be repeated twice.   |  | ||||||
| 
 |  | ||||||
| \item[\code{[]}] Used to indicate a set of characters.  Characters can |  | ||||||
| be listed individually, or a range is indicated by giving two |  | ||||||
| characters and separating them by a '-'.  Special characters are |  | ||||||
| not active inside sets.  For example, \code{[akm\$]} |  | ||||||
| will match any of the characters 'a', 'k', 'm', or '\$'; \code{[a-z]} will |  | ||||||
| match any lowercase letter.   |  | ||||||
| 
 |  | ||||||
| If you want to include a \code{]} inside a |  | ||||||
| set, it must be the first character of the set; to include a \code{-}, |  | ||||||
| place it as the first or last character.  |  | ||||||
| 
 |  | ||||||
| Characters \emph{not} within a range can be matched by including a |  | ||||||
| \code{\^} as the first character of the set; \code{\^} elsewhere will |  | ||||||
| simply match the '\code{\^}' character.   |  | ||||||
| \end{itemize} |  | ||||||
| 
 |  | ||||||
| The special sequences consist of '\code{\e}' and a character |  | ||||||
| from the list below.  If the ordinary character is not on the list, |  | ||||||
| then the resulting RE will match the second character.  For example, |  | ||||||
| \code{\e\$} matches the character '\$'.  Ones where the backslash |  | ||||||
| should be doubled in string literals are indicated. |  | ||||||
| 
 |  | ||||||
| \begin{itemize} |  | ||||||
| \item[\code{\e|}]\code{A\e|B}, where A and B can be arbitrary REs, |  | ||||||
| creates a regular expression that will match either A or B.  This can |  | ||||||
| be used inside groups (see below) as well. |  | ||||||
| % |  | ||||||
| \item[\code{\e( \e)}] Indicates the start and end of a group; the |  | ||||||
| contents of a group can be matched later in the string with the |  | ||||||
| \code{\e [1-9]} special sequence, described next. |  | ||||||
| \end{itemize} |  | ||||||
| 
 |  | ||||||
| \begin{fulllineitems} |  | ||||||
| \item[\code{\e \e 1, ... \e \e 7, \e 8, \e 9}] |  | ||||||
| Matches the contents of the group of the same |  | ||||||
| number.  For example, \code{\e (.+\e ) \e \e 1} matches 'the the' or |  | ||||||
| '55 55', but not 'the end' (note the space after the group).  This |  | ||||||
| special sequence can only be used to match one of the first 9 groups; |  | ||||||
| groups with higher numbers can be matched using the \code{\e v} |  | ||||||
| sequence.  (\code{\e 8} and \code{\e 9} don't need a double backslash |  | ||||||
| because they are not octal digits.) |  | ||||||
| \end{fulllineitems} |  | ||||||
| 
 |  | ||||||
| \begin{itemize} |  | ||||||
| \item[\code{\e \e b}] Matches the empty string, but only at the |  | ||||||
| beginning or end of a word.  A word is defined as a sequence of |  | ||||||
| alphanumeric characters, so the end of a word is indicated by |  | ||||||
| whitespace or a non-alphanumeric character. |  | ||||||
| % |  | ||||||
| \item[\code{\e B}] Matches the empty string, but when it is \emph{not} at the |  | ||||||
| beginning or end of a word. |  | ||||||
| % |  | ||||||
| \item[\code{\e v}] Must be followed by a two digit decimal number, and |  | ||||||
| matches the contents of the group of the same number.  The group |  | ||||||
| number must be between 1 and 99, inclusive. |  | ||||||
| % |  | ||||||
| \item[\code{\e w}]Matches any alphanumeric character; this is |  | ||||||
| equivalent to the set \code{[a-zA-Z0-9]}. |  | ||||||
| % |  | ||||||
| \item[\code{\e W}] Matches any non-alphanumeric character; this is |  | ||||||
| equivalent to the set \code{[\^a-zA-Z0-9]}. |  | ||||||
| \item[\code{\e <}] Matches the empty string, but only at the beginning of a |  | ||||||
| word.  A word is defined as a sequence of alphanumeric characters, so |  | ||||||
| the end of a word is indicated by whitespace or a non-alphanumeric  |  | ||||||
| character. |  | ||||||
| \item[\code{\e >}] Matches the empty string, but only at the end of a |  | ||||||
| word. |  | ||||||
| 
 |  | ||||||
| \item[\code{\e \e \e \e}] Matches a literal backslash. |  | ||||||
| 
 |  | ||||||
| % In Emacs, the following two are start of buffer/end of buffer.  In |  | ||||||
| % Python they seem to be synonyms for ^$. |  | ||||||
| \item[\code{\e `}] Like \code{\^}, this only matches at the start of the |  | ||||||
| string. |  | ||||||
| \item[\code{\e \e '}] Like \code{\$}, this only matches at the end of |  | ||||||
| the string. |  | ||||||
| % end of buffer |  | ||||||
| \end{itemize} |  | ||||||
| 
 |  | ||||||
| \subsection{Module Contents} |  | ||||||
| \nodename{Contents of Module regex} |  | ||||||
| 
 |  | ||||||
| The module defines these functions, and an exception: |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{match}{pattern, string} |  | ||||||
|   Return how many characters at the beginning of \var{string} match |  | ||||||
|   the regular expression \var{pattern}.  Return \code{-1} if the |  | ||||||
|   string does not match the pattern (this is different from a |  | ||||||
|   zero-length match!). |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{search}{pattern, string} |  | ||||||
|   Return the first position in \var{string} that matches the regular |  | ||||||
|   expression \var{pattern}.  Return \code{-1} if no position in the string |  | ||||||
|   matches the pattern (this is different from a zero-length match |  | ||||||
|   anywhere!). |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{compile}{pattern\optional{, translate}} |  | ||||||
|   Compile a regular expression pattern into a regular expression |  | ||||||
|   object, which can be used for matching using its \code{match()} and |  | ||||||
|   \code{search()} methods, described below.  The optional argument |  | ||||||
|   \var{translate}, if present, must be a 256-character string |  | ||||||
|   indicating how characters (both of the pattern and of the strings to |  | ||||||
|   be matched) are translated before comparing them; the \var{i}-th |  | ||||||
|   element of the string gives the translation for the character with |  | ||||||
|   \ASCII{} code \var{i}.  This can be used to implement |  | ||||||
|   case-insensitive matching; see the \code{casefold} data item below. |  | ||||||
| 
 |  | ||||||
|   The sequence |  | ||||||
| 
 |  | ||||||
| \begin{verbatim} |  | ||||||
| prog = regex.compile(pat) |  | ||||||
| result = prog.match(str) |  | ||||||
| \end{verbatim} |  | ||||||
| % |  | ||||||
| is equivalent to |  | ||||||
| 
 |  | ||||||
| \begin{verbatim} |  | ||||||
| result = regex.match(pat, str) |  | ||||||
| \end{verbatim} |  | ||||||
| 
 |  | ||||||
| but the version using \code{compile()} is more efficient when multiple |  | ||||||
| regular expressions are used concurrently in a single program.  (The |  | ||||||
| compiled version of the last pattern passed to \code{regex.match()} or |  | ||||||
| \code{regex.search()} is cached, so programs that use only a single |  | ||||||
| regular expression at a time needn't worry about compiling regular |  | ||||||
| expressions.) |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{set_syntax}{flags} |  | ||||||
|   Set the syntax to be used by future calls to \code{compile()}, |  | ||||||
|   \code{match()} and \code{search()}.  (Already compiled expression |  | ||||||
|   objects are not affected.)  The argument is an integer which is the |  | ||||||
|   OR of several flag bits.  The return value is the previous value of |  | ||||||
|   the syntax flags.  Names for the flags are defined in the standard |  | ||||||
|   module \code{regex_syntax}\refstmodindex{regex_syntax}; read the |  | ||||||
|   file \file{regex_syntax.py} for more information. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{get_syntax}{} |  | ||||||
|   Returns the current value of the syntax flags as an integer. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{symcomp}{pattern\optional{, translate}} |  | ||||||
| This is like \code{compile()}, but supports symbolic group names: if a |  | ||||||
| parenthesis-enclosed group begins with a group name in angular |  | ||||||
| brackets, e.g. \code{'\e(<id>[a-z][a-z0-9]*\e)'}, the group can |  | ||||||
| be referenced by its name in arguments to the \code{group()} method of |  | ||||||
| the resulting compiled regular expression object, like this: |  | ||||||
| \code{p.group('id')}.  Group names may contain alphanumeric characters |  | ||||||
| and \code{'_'} only. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{excdesc}{error} |  | ||||||
|   Exception raised when a string passed to one of the functions here |  | ||||||
|   is not a valid regular expression (e.g., unmatched parentheses) or |  | ||||||
|   when some other error occurs during compilation or matching.  (It is |  | ||||||
|   never an error if a string contains no match for a pattern.) |  | ||||||
| \end{excdesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{casefold} |  | ||||||
| A string suitable to pass as the \var{translate} argument to |  | ||||||
| \code{compile()} to map all upper case characters to their lowercase |  | ||||||
| equivalents. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \noindent |  | ||||||
| Compiled regular expression objects support these methods: |  | ||||||
| 
 |  | ||||||
| \setindexsubitem{(regex method)} |  | ||||||
| \begin{funcdesc}{match}{string\optional{, pos}} |  | ||||||
|   Return how many characters at the beginning of \var{string} match |  | ||||||
|   the compiled regular expression.  Return \code{-1} if the string |  | ||||||
|   does not match the pattern (this is different from a zero-length |  | ||||||
|   match!). |  | ||||||
|    |  | ||||||
|   The optional second parameter, \var{pos}, gives an index in the string |  | ||||||
|   where the search is to start; it defaults to \code{0}.  This is not |  | ||||||
|   completely equivalent to slicing the string; the \code{'\^'} pattern |  | ||||||
|   character matches at the real beginning of the string and at positions |  | ||||||
|   just after a newline, not necessarily at the index where the search |  | ||||||
|   is to start. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{search}{string\optional{, pos}} |  | ||||||
|   Return the first position in \var{string} that matches the regular |  | ||||||
|   expression \code{pattern}.  Return \code{-1} if no position in the |  | ||||||
|   string matches the pattern (this is different from a zero-length |  | ||||||
|   match anywhere!). |  | ||||||
|    |  | ||||||
|   The optional second parameter has the same meaning as for the |  | ||||||
|   \code{match()} method. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{group}{index, index, ...} |  | ||||||
| This method is only valid when the last call to the \code{match()} |  | ||||||
| or \code{search()} method found a match.  It returns one or more |  | ||||||
| groups of the match.  If there is a single \var{index} argument, |  | ||||||
| the result is a single string; if there are multiple arguments, the |  | ||||||
| result is a tuple with one item per argument.  If the \var{index} is |  | ||||||
| zero, the corresponding return value is the entire matching string; if |  | ||||||
| it is in the inclusive range [1..99], it is the string matching the |  | ||||||
| corresponding parenthesized group (using the default syntax, |  | ||||||
| groups are parenthesized using \code{{\e}(} and \code{{\e})}).  If no |  | ||||||
| such group exists, the corresponding result is \code{None}. |  | ||||||
| 
 |  | ||||||
| If the regular expression was compiled by \code{symcomp()} instead of |  | ||||||
| \code{compile()}, the \var{index} arguments may also be strings |  | ||||||
| identifying groups by their group name. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \noindent |  | ||||||
| Compiled regular expressions support these data attributes: |  | ||||||
| 
 |  | ||||||
| \setindexsubitem{(regex attribute)} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{regs} |  | ||||||
| When the last call to the \code{match()} or \code{search()} method found a |  | ||||||
| match, this is a tuple of pairs of indexes corresponding to the |  | ||||||
| beginning and end of all parenthesized groups in the pattern.  Indices |  | ||||||
| are relative to the string argument passed to \code{match()} or |  | ||||||
| \code{search()}.  The 0-th tuple gives the beginning and end or the |  | ||||||
| whole pattern.  When the last match or search failed, this is |  | ||||||
| \code{None}. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{last} |  | ||||||
| When the last call to the \code{match()} or \code{search()} method found a |  | ||||||
| match, this is the string argument passed to that method.  When the |  | ||||||
| last match or search failed, this is \code{None}. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{translate} |  | ||||||
| This is the value of the \var{translate} argument to |  | ||||||
| \code{regex.compile()} that created this regular expression object.  If |  | ||||||
| the \var{translate} argument was omitted in the \code{regex.compile()} |  | ||||||
| call, this is \code{None}. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{givenpat} |  | ||||||
| The regular expression pattern as passed to \code{compile()} or |  | ||||||
| \code{symcomp()}. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{realpat} |  | ||||||
| The regular expression after stripping the group names for regular |  | ||||||
| expressions compiled with \code{symcomp()}.  Same as \code{givenpat} |  | ||||||
| otherwise. |  | ||||||
| \end{datadesc} |  | ||||||
| 
 |  | ||||||
| \begin{datadesc}{groupindex} |  | ||||||
| A dictionary giving the mapping from symbolic group names to numerical |  | ||||||
| group indexes for regular expressions compiled with \code{symcomp()}. |  | ||||||
| \code{None} otherwise. |  | ||||||
| \end{datadesc} |  | ||||||
|  | @ -1,74 +0,0 @@ | ||||||
| \section{\module{regsub} --- |  | ||||||
|          String operations using regular expressions} |  | ||||||
| 
 |  | ||||||
| \declaremodule{standard}{regsub} |  | ||||||
| \modulesynopsis{Substitution and splitting operations that use |  | ||||||
|                 regular expressions.  \strong{Obsolete!}} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| This module defines a number of functions useful for working with |  | ||||||
| regular expressions (see built-in module \refmodule{regex}). |  | ||||||
| 
 |  | ||||||
| Warning: these functions are not thread-safe. |  | ||||||
| 
 |  | ||||||
| \strong{Obsolescence note:} |  | ||||||
| This module is obsolete as of Python version 1.5; it is still being |  | ||||||
| maintained because much existing code still uses it.  All new code in |  | ||||||
| need of regular expressions should use the new \refmodule{re} module, which |  | ||||||
| supports the more powerful and regular Perl-style regular expressions. |  | ||||||
| Existing code should be converted.  The standard library module |  | ||||||
| \module{reconvert} helps in converting \refmodule{regex} style regular |  | ||||||
| expressions to \refmodule{re} style regular expressions.  (For more |  | ||||||
| conversion help, see Andrew Kuchling's\index{Kuchling, Andrew} |  | ||||||
| ``regex-to-re HOWTO'' at |  | ||||||
| \url{http://www.python.org/doc/howto/regex-to-re/}.) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{sub}{pat, repl, str} |  | ||||||
| Replace the first occurrence of pattern \var{pat} in string |  | ||||||
| \var{str} by replacement \var{repl}.  If the pattern isn't found, |  | ||||||
| the string is returned unchanged.  The pattern may be a string or an |  | ||||||
| already compiled pattern.  The replacement may contain references |  | ||||||
| \samp{\e \var{digit}} to subpatterns and escaped backslashes. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{gsub}{pat, repl, str} |  | ||||||
| Replace all (non-overlapping) occurrences of pattern \var{pat} in |  | ||||||
| string \var{str} by replacement \var{repl}.  The same rules as for |  | ||||||
| \code{sub()} apply.  Empty matches for the pattern are replaced only |  | ||||||
| when not adjacent to a previous match, so e.g. |  | ||||||
| \code{gsub('', '-', 'abc')} returns \code{'-a-b-c-'}. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{split}{str, pat\optional{, maxsplit}} |  | ||||||
| Split the string \var{str} in fields separated by delimiters matching |  | ||||||
| the pattern \var{pat}, and return a list containing the fields.  Only |  | ||||||
| non-empty matches for the pattern are considered, so e.g. |  | ||||||
| \code{split('a:b', ':*')} returns \code{['a', 'b']} and |  | ||||||
| \code{split('abc', '')} returns \code{['abc']}.  The \var{maxsplit} |  | ||||||
| defaults to 0. If it is nonzero, only \var{maxsplit} number of splits |  | ||||||
| occur, and the remainder of the string is returned as the final |  | ||||||
| element of the list. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{splitx}{str, pat\optional{, maxsplit}} |  | ||||||
| Split the string \var{str} in fields separated by delimiters matching |  | ||||||
| the pattern \var{pat}, and return a list containing the fields as well |  | ||||||
| as the separators.  For example, \code{splitx('a:::b', ':*')} returns |  | ||||||
| \code{['a', ':::', 'b']}.  Otherwise, this function behaves the same |  | ||||||
| as \code{split}. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{capwords}{s\optional{, pat}} |  | ||||||
| Capitalize words separated by optional pattern \var{pat}.  The default |  | ||||||
| pattern uses any characters except letters, digits and underscores as |  | ||||||
| word delimiters.  Capitalization is done by changing the first |  | ||||||
| character of each word to upper case. |  | ||||||
| \end{funcdesc} |  | ||||||
| 
 |  | ||||||
| \begin{funcdesc}{clear_cache}{} |  | ||||||
| The regsub module maintains a cache of compiled regular expressions, |  | ||||||
| keyed on the regular expression string and the syntax of the regex |  | ||||||
| module at the time the expression was compiled.  This function clears |  | ||||||
| that cache. |  | ||||||
| \end{funcdesc} |  | ||||||
|  | @ -137,18 +137,6 @@ now just as good). | ||||||
| \item[\module{rand}] | \item[\module{rand}] | ||||||
| --- Old interface to the random number generator. | --- Old interface to the random number generator. | ||||||
| 
 | 
 | ||||||
| \item[\module{regex}] |  | ||||||
| --- Emacs-style regular expression support; may still be used in some |  | ||||||
| old code (extension module).  Refer to the |  | ||||||
| \citetitle[http://www.python.org/doc/1.6/lib/module-regex.html]{Python |  | ||||||
| 1.6 Documentation} for documentation. |  | ||||||
| 
 |  | ||||||
| \item[\module{regsub}] |  | ||||||
| --- Regular expression based string replacement utilities, for use |  | ||||||
| with \module{regex} (extension module).  Refer to the |  | ||||||
| \citetitle[http://www.python.org/doc/1.6/lib/module-regsub.html]{Python |  | ||||||
| 1.6 Documentation} for documentation. |  | ||||||
| 
 |  | ||||||
| \item[\module{statcache}] | \item[\module{statcache}] | ||||||
| --- Caches the results of os.stat().  Using the cache can be fragile | --- Caches the results of os.stat().  Using the cache can be fragile | ||||||
| and error-prone, just use \code{os.stat()} directly. | and error-prone, just use \code{os.stat()} directly. | ||||||
|  |  | ||||||
|  | @ -1,343 +0,0 @@ | ||||||
| # Text formatting abstractions |  | ||||||
| # Note -- this module is obsolete, it's too slow anyway |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Oft-used type object |  | ||||||
| Int = type(0) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Represent a paragraph.  This is a list of words with associated |  | ||||||
| # font and size information, plus indents and justification for the |  | ||||||
| # entire paragraph. |  | ||||||
| # Once the words have been added to a paragraph, it can be laid out |  | ||||||
| # for different line widths.  Once laid out, it can be rendered at |  | ||||||
| # different screen locations.  Once rendered, it can be queried |  | ||||||
| # for mouse hits, and parts of the text can be highlighted |  | ||||||
| class Para: |  | ||||||
|     # |  | ||||||
|     def __init__(self): |  | ||||||
|         self.words = [] # The words |  | ||||||
|         self.just = 'l' # Justification: 'l', 'r', 'lr' or 'c' |  | ||||||
|         self.indent_left = self.indent_right = self.indent_hang = 0 |  | ||||||
|         # Final lay-out parameters, may change |  | ||||||
|         self.left = self.top = self.right = self.bottom = \ |  | ||||||
|                 self.width = self.height = self.lines = None |  | ||||||
|     # |  | ||||||
|     # Add a word, computing size information for it. |  | ||||||
|     # Words may also be added manually by appending to self.words |  | ||||||
|     # Each word should be a 7-tuple: |  | ||||||
|     # (font, text, width, space, stretch, ascent, descent) |  | ||||||
|     def addword(self, d, font, text, space, stretch): |  | ||||||
|         if font is not None: |  | ||||||
|             d.setfont(font) |  | ||||||
|         width = d.textwidth(text) |  | ||||||
|         ascent = d.baseline() |  | ||||||
|         descent = d.lineheight() - ascent |  | ||||||
|         spw = d.textwidth(' ') |  | ||||||
|         space = space * spw |  | ||||||
|         stretch = stretch * spw |  | ||||||
|         tuple = (font, text, width, space, stretch, ascent, descent) |  | ||||||
|         self.words.append(tuple) |  | ||||||
|     # |  | ||||||
|     # Hooks to begin and end anchors -- insert numbers in the word list! |  | ||||||
|     def bgn_anchor(self, id): |  | ||||||
|         self.words.append(id) |  | ||||||
|     # |  | ||||||
|     def end_anchor(self, id): |  | ||||||
|         self.words.append(0) |  | ||||||
|     # |  | ||||||
|     # Return the total length (width) of the text added so far, in pixels |  | ||||||
|     def getlength(self): |  | ||||||
|         total = 0 |  | ||||||
|         for word in self.words: |  | ||||||
|             if type(word) is not Int: |  | ||||||
|                 total = total + word[2] + word[3] |  | ||||||
|         return total |  | ||||||
|     # |  | ||||||
|     # Tab to a given position (relative to the current left indent): |  | ||||||
|     # remove all stretch, add fixed space up to the new indent. |  | ||||||
|     # If the current position is already at the tab stop, |  | ||||||
|     # don't add any new space (but still remove the stretch) |  | ||||||
|     def tabto(self, tab): |  | ||||||
|         total = 0 |  | ||||||
|         as, de = 1, 0 |  | ||||||
|         for i in range(len(self.words)): |  | ||||||
|             word = self.words[i] |  | ||||||
|             if type(word) is Int: continue |  | ||||||
|             (fo, te, wi, sp, st, as, de) = word |  | ||||||
|             self.words[i] = (fo, te, wi, sp, 0, as, de) |  | ||||||
|             total = total + wi + sp |  | ||||||
|         if total < tab: |  | ||||||
|             self.words.append((None, '', 0, tab-total, 0, as, de)) |  | ||||||
|     # |  | ||||||
|     # Make a hanging tag: tab to hang, increment indent_left by hang, |  | ||||||
|     # and reset indent_hang to -hang |  | ||||||
|     def makehangingtag(self, hang): |  | ||||||
|         self.tabto(hang) |  | ||||||
|         self.indent_left = self.indent_left + hang |  | ||||||
|         self.indent_hang = -hang |  | ||||||
|     # |  | ||||||
|     # Decide where the line breaks will be given some screen width |  | ||||||
|     def layout(self, linewidth): |  | ||||||
|         self.width = linewidth |  | ||||||
|         height = 0 |  | ||||||
|         self.lines = lines = [] |  | ||||||
|         avail1 = self.width - self.indent_left - self.indent_right |  | ||||||
|         avail = avail1 - self.indent_hang |  | ||||||
|         words = self.words |  | ||||||
|         i = 0 |  | ||||||
|         n = len(words) |  | ||||||
|         lastfont = None |  | ||||||
|         while i < n: |  | ||||||
|             firstfont = lastfont |  | ||||||
|             charcount = 0 |  | ||||||
|             width = 0 |  | ||||||
|             stretch = 0 |  | ||||||
|             ascent = 0 |  | ||||||
|             descent = 0 |  | ||||||
|             lsp = 0 |  | ||||||
|             j = i |  | ||||||
|             while i < n: |  | ||||||
|                 word = words[i] |  | ||||||
|                 if type(word) is Int: |  | ||||||
|                     if word > 0 and width >= avail: |  | ||||||
|                         break |  | ||||||
|                     i = i+1 |  | ||||||
|                     continue |  | ||||||
|                 fo, te, wi, sp, st, as, de = word |  | ||||||
|                 if width + wi > avail and width > 0 and wi > 0: |  | ||||||
|                     break |  | ||||||
|                 if fo is not None: |  | ||||||
|                     lastfont = fo |  | ||||||
|                     if width == 0: |  | ||||||
|                         firstfont = fo |  | ||||||
|                 charcount = charcount + len(te) + (sp > 0) |  | ||||||
|                 width = width + wi + sp |  | ||||||
|                 lsp = sp |  | ||||||
|                 stretch = stretch + st |  | ||||||
|                 lst = st |  | ||||||
|                 ascent = max(ascent, as) |  | ||||||
|                 descent = max(descent, de) |  | ||||||
|                 i = i+1 |  | ||||||
|             while i > j and type(words[i-1]) is Int and \ |  | ||||||
|                     words[i-1] > 0: i = i-1 |  | ||||||
|             width = width - lsp |  | ||||||
|             if i < n: |  | ||||||
|                 stretch = stretch - lst |  | ||||||
|             else: |  | ||||||
|                 stretch = 0 |  | ||||||
|             tuple = i-j, firstfont, charcount, width, stretch, \ |  | ||||||
|                     ascent, descent |  | ||||||
|             lines.append(tuple) |  | ||||||
|             height = height + ascent + descent |  | ||||||
|             avail = avail1 |  | ||||||
|         self.height = height |  | ||||||
|     # |  | ||||||
|     # Call a function for all words in a line |  | ||||||
|     def visit(self, wordfunc, anchorfunc): |  | ||||||
|         avail1 = self.width - self.indent_left - self.indent_right |  | ||||||
|         avail = avail1 - self.indent_hang |  | ||||||
|         v = self.top |  | ||||||
|         i = 0 |  | ||||||
|         for tuple in self.lines: |  | ||||||
|             wordcount, firstfont, charcount, width, stretch, \ |  | ||||||
|                     ascent, descent = tuple |  | ||||||
|             h = self.left + self.indent_left |  | ||||||
|             if i == 0: h = h + self.indent_hang |  | ||||||
|             extra = 0 |  | ||||||
|             if self.just == 'r': h = h + avail - width |  | ||||||
|             elif self.just == 'c': h = h + (avail - width) / 2 |  | ||||||
|             elif self.just == 'lr' and stretch > 0: |  | ||||||
|                 extra = avail - width |  | ||||||
|             v2 = v + ascent + descent |  | ||||||
|             for j in range(i, i+wordcount): |  | ||||||
|                 word = self.words[j] |  | ||||||
|                 if type(word) is Int: |  | ||||||
|                     ok = anchorfunc(self, tuple, word, \ |  | ||||||
|                                     h, v) |  | ||||||
|                     if ok is not None: return ok |  | ||||||
|                     continue |  | ||||||
|                 fo, te, wi, sp, st, as, de = word |  | ||||||
|                 if extra > 0 and stretch > 0: |  | ||||||
|                     ex = extra * st / stretch |  | ||||||
|                     extra = extra - ex |  | ||||||
|                     stretch = stretch - st |  | ||||||
|                 else: |  | ||||||
|                     ex = 0 |  | ||||||
|                 h2 = h + wi + sp + ex |  | ||||||
|                 ok = wordfunc(self, tuple, word, h, v, \ |  | ||||||
|                         h2, v2, (j==i), (j==i+wordcount-1)) |  | ||||||
|                 if ok is not None: return ok |  | ||||||
|                 h = h2 |  | ||||||
|             v = v2 |  | ||||||
|             i = i + wordcount |  | ||||||
|             avail = avail1 |  | ||||||
|     # |  | ||||||
|     # Render a paragraph in "drawing object" d, using the rectangle |  | ||||||
|     # given by (left, top, right) with an unspecified bottom. |  | ||||||
|     # Return the computed bottom of the text. |  | ||||||
|     def render(self, d, left, top, right): |  | ||||||
|         if self.width != right-left: |  | ||||||
|             self.layout(right-left) |  | ||||||
|         self.left = left |  | ||||||
|         self.top = top |  | ||||||
|         self.right = right |  | ||||||
|         self.bottom = self.top + self.height |  | ||||||
|         self.anchorid = 0 |  | ||||||
|         try: |  | ||||||
|             self.d = d |  | ||||||
|             self.visit(self.__class__._renderword, \ |  | ||||||
|                        self.__class__._renderanchor) |  | ||||||
|         finally: |  | ||||||
|             self.d = None |  | ||||||
|         return self.bottom |  | ||||||
|     # |  | ||||||
|     def _renderword(self, tuple, word, h, v, h2, v2, isfirst, islast): |  | ||||||
|         if word[0] is not None: self.d.setfont(word[0]) |  | ||||||
|         baseline = v + tuple[5] |  | ||||||
|         self.d.text((h, baseline - word[5]), word[1]) |  | ||||||
|         if self.anchorid > 0: |  | ||||||
|             self.d.line((h, baseline+2), (h2, baseline+2)) |  | ||||||
|     # |  | ||||||
|     def _renderanchor(self, tuple, word, h, v): |  | ||||||
|         self.anchorid = word |  | ||||||
|     # |  | ||||||
|     # Return which anchor(s) was hit by the mouse |  | ||||||
|     def hitcheck(self, mouseh, mousev): |  | ||||||
|         self.mouseh = mouseh |  | ||||||
|         self.mousev = mousev |  | ||||||
|         self.anchorid = 0 |  | ||||||
|         self.hits = [] |  | ||||||
|         self.visit(self.__class__._hitcheckword, \ |  | ||||||
|                    self.__class__._hitcheckanchor) |  | ||||||
|         return self.hits |  | ||||||
|     # |  | ||||||
|     def _hitcheckword(self, tuple, word, h, v, h2, v2, isfirst, islast): |  | ||||||
|         if self.anchorid > 0 and h <= self.mouseh <= h2 and \ |  | ||||||
|                 v <= self.mousev <= v2: |  | ||||||
|             self.hits.append(self.anchorid) |  | ||||||
|     # |  | ||||||
|     def _hitcheckanchor(self, tuple, word, h, v): |  | ||||||
|         self.anchorid = word |  | ||||||
|     # |  | ||||||
|     # Return whether the given anchor id is present |  | ||||||
|     def hasanchor(self, id): |  | ||||||
|         return id in self.words or -id in self.words |  | ||||||
|     # |  | ||||||
|     # Extract the raw text from the word list, substituting one space |  | ||||||
|     # for non-empty inter-word space, and terminating with '\n' |  | ||||||
|     def extract(self): |  | ||||||
|         text = '' |  | ||||||
|         for w in self.words: |  | ||||||
|             if type(w) is not Int: |  | ||||||
|                 word = w[1] |  | ||||||
|                 if w[3]: word = word + ' ' |  | ||||||
|                 text = text + word |  | ||||||
|         return text + '\n' |  | ||||||
|     # |  | ||||||
|     # Return which character position was hit by the mouse, as |  | ||||||
|     # an offset in the entire text as returned by extract(). |  | ||||||
|     # Return None if the mouse was not in this paragraph |  | ||||||
|     def whereis(self, d, mouseh, mousev): |  | ||||||
|         if mousev < self.top or mousev > self.bottom: |  | ||||||
|             return None |  | ||||||
|         self.mouseh = mouseh |  | ||||||
|         self.mousev = mousev |  | ||||||
|         self.lastfont = None |  | ||||||
|         self.charcount = 0 |  | ||||||
|         try: |  | ||||||
|             self.d = d |  | ||||||
|             return self.visit(self.__class__._whereisword, \ |  | ||||||
|                               self.__class__._whereisanchor) |  | ||||||
|         finally: |  | ||||||
|             self.d = None |  | ||||||
|     # |  | ||||||
|     def _whereisword(self, tuple, word, h1, v1, h2, v2, isfirst, islast): |  | ||||||
|         fo, te, wi, sp, st, as, de = word |  | ||||||
|         if fo is not None: self.lastfont = fo |  | ||||||
|         h = h1 |  | ||||||
|         if isfirst: h1 = 0 |  | ||||||
|         if islast: h2 = 999999 |  | ||||||
|         if not (v1 <= self.mousev <= v2 and h1 <= self.mouseh <= h2): |  | ||||||
|             self.charcount = self.charcount + len(te) + (sp > 0) |  | ||||||
|             return |  | ||||||
|         if self.lastfont is not None: |  | ||||||
|             self.d.setfont(self.lastfont) |  | ||||||
|         cc = 0 |  | ||||||
|         for c in te: |  | ||||||
|             cw = self.d.textwidth(c) |  | ||||||
|             if self.mouseh <= h + cw/2: |  | ||||||
|                 return self.charcount + cc |  | ||||||
|             cc = cc+1 |  | ||||||
|             h = h+cw |  | ||||||
|         self.charcount = self.charcount + cc |  | ||||||
|         if self.mouseh <= (h+h2) / 2: |  | ||||||
|             return self.charcount |  | ||||||
|         else: |  | ||||||
|             return self.charcount + 1 |  | ||||||
|     # |  | ||||||
|     def _whereisanchor(self, tuple, word, h, v): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     # Return screen position corresponding to position in paragraph. |  | ||||||
|     # Return tuple (h, vtop, vbaseline, vbottom). |  | ||||||
|     # This is more or less the inverse of whereis() |  | ||||||
|     def screenpos(self, d, pos): |  | ||||||
|         if pos < 0: |  | ||||||
|             ascent, descent = self.lines[0][5:7] |  | ||||||
|             return self.left, self.top, self.top + ascent, \ |  | ||||||
|                     self.top + ascent + descent |  | ||||||
|         self.pos = pos |  | ||||||
|         self.lastfont = None |  | ||||||
|         try: |  | ||||||
|             self.d = d |  | ||||||
|             ok = self.visit(self.__class__._screenposword, \ |  | ||||||
|                             self.__class__._screenposanchor) |  | ||||||
|         finally: |  | ||||||
|             self.d = None |  | ||||||
|         if ok is None: |  | ||||||
|             ascent, descent = self.lines[-1][5:7] |  | ||||||
|             ok = self.right, self.bottom - ascent - descent, \ |  | ||||||
|                     self.bottom - descent, self.bottom |  | ||||||
|         return ok |  | ||||||
|     # |  | ||||||
|     def _screenposword(self, tuple, word, h1, v1, h2, v2, isfirst, islast): |  | ||||||
|         fo, te, wi, sp, st, as, de = word |  | ||||||
|         if fo is not None: self.lastfont = fo |  | ||||||
|         cc = len(te) + (sp > 0) |  | ||||||
|         if self.pos > cc: |  | ||||||
|             self.pos = self.pos - cc |  | ||||||
|             return |  | ||||||
|         if self.pos < cc: |  | ||||||
|             self.d.setfont(self.lastfont) |  | ||||||
|             h = h1 + self.d.textwidth(te[:self.pos]) |  | ||||||
|         else: |  | ||||||
|             h = h2 |  | ||||||
|         ascent, descent = tuple[5:7] |  | ||||||
|         return h, v1, v1+ascent, v2 |  | ||||||
|     # |  | ||||||
|     def _screenposanchor(self, tuple, word, h, v): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     # Invert the stretch of text between pos1 and pos2. |  | ||||||
|     # If pos1 is None, the beginning is implied; |  | ||||||
|     # if pos2 is None, the end is implied. |  | ||||||
|     # Undoes its own effect when called again with the same arguments |  | ||||||
|     def invert(self, d, pos1, pos2): |  | ||||||
|         if pos1 is None: |  | ||||||
|             pos1 = self.left, self.top, self.top, self.top |  | ||||||
|         else: |  | ||||||
|             pos1 = self.screenpos(d, pos1) |  | ||||||
|         if pos2 is None: |  | ||||||
|             pos2 = self.right, self.bottom,self.bottom,self.bottom |  | ||||||
|         else: |  | ||||||
|             pos2 = self.screenpos(d, pos2) |  | ||||||
|         h1, top1, baseline1, bottom1 = pos1 |  | ||||||
|         h2, top2, baseline2, bottom2 = pos2 |  | ||||||
|         if bottom1 <= top2: |  | ||||||
|             d.invert((h1, top1), (self.right, bottom1)) |  | ||||||
|             h1 = self.left |  | ||||||
|             if bottom1 < top2: |  | ||||||
|                 d.invert((h1, bottom1), (self.right, top2)) |  | ||||||
|             top1, bottom1 = top2, bottom2 |  | ||||||
|         d.invert((h1, top1), (h2, bottom2)) |  | ||||||
|  | @ -1,67 +0,0 @@ | ||||||
| # This module provides standard support for "packages". |  | ||||||
| # |  | ||||||
| # The idea is that large groups of related modules can be placed in |  | ||||||
| # their own subdirectory, which can be added to the Python search path |  | ||||||
| # in a relatively easy way. |  | ||||||
| # |  | ||||||
| # The current version takes a package name and searches the Python |  | ||||||
| # search path for a directory by that name, and if found adds it to |  | ||||||
| # the module search path (sys.path).  It maintains a list of packages |  | ||||||
| # that have already been added so adding the same package many times |  | ||||||
| # is OK. |  | ||||||
| # |  | ||||||
| # It is intended to be used in a fairly stylized manner: each module |  | ||||||
| # that wants to use a particular package, say 'Foo', is supposed to |  | ||||||
| # contain the following code: |  | ||||||
| # |  | ||||||
| #   from addpack import addpack |  | ||||||
| #   addpack('Foo') |  | ||||||
| #   <import modules from package Foo> |  | ||||||
| # |  | ||||||
| # Additional arguments, when present, provide additional places where |  | ||||||
| # to look for the package before trying sys.path (these may be either |  | ||||||
| # strings or lists/tuples of strings).  Also, if the package name is a |  | ||||||
| # full pathname, first the last component is tried in the usual way, |  | ||||||
| # then the full pathname is tried last.  If the package name is a |  | ||||||
| # *relative* pathname (UNIX: contains a slash but doesn't start with |  | ||||||
| # one), then nothing special is done.  The packages "/foo/bar/bletch" |  | ||||||
| # and "bletch" are considered the same, but unrelated to "bar/bletch". |  | ||||||
| # |  | ||||||
| # If the algorithm finds more than one suitable subdirectory, all are |  | ||||||
| # added to the search path -- this makes it possible to override part |  | ||||||
| # of a package.  The same path will not be added more than once. |  | ||||||
| # |  | ||||||
| # If no directory is found, ImportError is raised. |  | ||||||
| 
 |  | ||||||
| _packs = {}                             # {pack: [pathname, ...], ...} |  | ||||||
| 
 |  | ||||||
| def addpack(pack, *locations): |  | ||||||
|     import os |  | ||||||
|     if os.path.isabs(pack): |  | ||||||
|         base = os.path.basename(pack) |  | ||||||
|     else: |  | ||||||
|         base = pack |  | ||||||
|     if _packs.has_key(base): |  | ||||||
|         return |  | ||||||
|     import sys |  | ||||||
|     path = [] |  | ||||||
|     for loc in _flatten(locations) + sys.path: |  | ||||||
|         fn = os.path.join(loc, base) |  | ||||||
|         if fn not in path and os.path.isdir(fn): |  | ||||||
|             path.append(fn) |  | ||||||
|     if pack != base and pack not in path and os.path.isdir(pack): |  | ||||||
|         path.append(pack) |  | ||||||
|     if not path: raise ImportError, 'package ' + pack + ' not found' |  | ||||||
|     _packs[base] = path |  | ||||||
|     for fn in path: |  | ||||||
|         if fn not in sys.path: |  | ||||||
|             sys.path.append(fn) |  | ||||||
| 
 |  | ||||||
| def _flatten(locations): |  | ||||||
|     locs = [] |  | ||||||
|     for loc in locations: |  | ||||||
|         if type(loc) == type(''): |  | ||||||
|             locs.append(loc) |  | ||||||
|         else: |  | ||||||
|             locs = locs + _flatten(loc) |  | ||||||
|     return locs |  | ||||||
|  | @ -1,63 +0,0 @@ | ||||||
| """Efficiently compare files, boolean outcome only (equal / not equal). |  | ||||||
| 
 |  | ||||||
| Tricks (used in this order): |  | ||||||
|     - Files with identical type, size & mtime are assumed to be clones |  | ||||||
|     - Files with different type or size cannot be identical |  | ||||||
|     - We keep a cache of outcomes of earlier comparisons |  | ||||||
|     - We don't fork a process to run 'cmp' but read the files ourselves |  | ||||||
| """ |  | ||||||
| 
 |  | ||||||
| import os |  | ||||||
| 
 |  | ||||||
| cache = {} |  | ||||||
| 
 |  | ||||||
| def cmp(f1, f2, shallow=1): |  | ||||||
|     """Compare two files, use the cache if possible. |  | ||||||
|     Return 1 for identical files, 0 for different. |  | ||||||
|     Raise exceptions if either file could not be statted, read, etc.""" |  | ||||||
|     s1, s2 = sig(os.stat(f1)), sig(os.stat(f2)) |  | ||||||
|     if s1[0] != 8 or s2[0] != 8: |  | ||||||
|         # Either is a not a plain file -- always report as different |  | ||||||
|         return 0 |  | ||||||
|     if shallow and s1 == s2: |  | ||||||
|         # type, size & mtime match -- report same |  | ||||||
|         return 1 |  | ||||||
|     if s1[:2] != s2[:2]: # Types or sizes differ, don't bother |  | ||||||
|         # types or sizes differ -- report different |  | ||||||
|         return 0 |  | ||||||
|     # same type and size -- look in the cache |  | ||||||
|     key = (f1, f2) |  | ||||||
|     try: |  | ||||||
|         cs1, cs2, outcome = cache[key] |  | ||||||
|         # cache hit |  | ||||||
|         if s1 == cs1 and s2 == cs2: |  | ||||||
|             # cached signatures match |  | ||||||
|             return outcome |  | ||||||
|         # stale cached signature(s) |  | ||||||
|     except KeyError: |  | ||||||
|         # cache miss |  | ||||||
|         pass |  | ||||||
|     # really compare |  | ||||||
|     outcome = do_cmp(f1, f2) |  | ||||||
|     cache[key] = s1, s2, outcome |  | ||||||
|     return outcome |  | ||||||
| 
 |  | ||||||
| def sig(st): |  | ||||||
|     """Return signature (i.e., type, size, mtime) from raw stat data |  | ||||||
|     0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid |  | ||||||
|     6-9: st_size, st_atime, st_mtime, st_ctime""" |  | ||||||
|     type = st[0] / 4096 |  | ||||||
|     size = st[6] |  | ||||||
|     mtime = st[8] |  | ||||||
|     return type, size, mtime |  | ||||||
| 
 |  | ||||||
| def do_cmp(f1, f2): |  | ||||||
|     """Compare two files, really.""" |  | ||||||
|     bufsize = 8*1024 # Could be tuned |  | ||||||
|     fp1 = open(f1, 'rb') |  | ||||||
|     fp2 = open(f2, 'rb') |  | ||||||
|     while 1: |  | ||||||
|         b1 = fp1.read(bufsize) |  | ||||||
|         b2 = fp2.read(bufsize) |  | ||||||
|         if b1 != b2: return 0 |  | ||||||
|         if not b1: return 1 |  | ||||||
|  | @ -1,64 +0,0 @@ | ||||||
| """Efficiently compare files, boolean outcome only (equal / not equal). |  | ||||||
| 
 |  | ||||||
| Tricks (used in this order): |  | ||||||
|     - Use the statcache module to avoid statting files more than once |  | ||||||
|     - Files with identical type, size & mtime are assumed to be clones |  | ||||||
|     - Files with different type or size cannot be identical |  | ||||||
|     - We keep a cache of outcomes of earlier comparisons |  | ||||||
|     - We don't fork a process to run 'cmp' but read the files ourselves |  | ||||||
| """ |  | ||||||
| 
 |  | ||||||
| import os |  | ||||||
| from stat import * |  | ||||||
| import statcache |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # The cache. |  | ||||||
| # |  | ||||||
| cache = {} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def cmp(f1, f2, shallow=1): |  | ||||||
|     """Compare two files, use the cache if possible. |  | ||||||
|     May raise os.error if a stat or open of either fails. |  | ||||||
|     Return 1 for identical files, 0 for different. |  | ||||||
|     Raise exceptions if either file could not be statted, read, etc.""" |  | ||||||
|     s1, s2 = sig(statcache.stat(f1)), sig(statcache.stat(f2)) |  | ||||||
|     if not S_ISREG(s1[0]) or not S_ISREG(s2[0]): |  | ||||||
|         # Either is a not a plain file -- always report as different |  | ||||||
|         return 0 |  | ||||||
|     if shallow and s1 == s2: |  | ||||||
|         # type, size & mtime match -- report same |  | ||||||
|         return 1 |  | ||||||
|     if s1[:2] != s2[:2]: # Types or sizes differ, don't bother |  | ||||||
|         # types or sizes differ -- report different |  | ||||||
|         return 0 |  | ||||||
|     # same type and size -- look in the cache |  | ||||||
|     key = f1 + ' ' + f2 |  | ||||||
|     if cache.has_key(key): |  | ||||||
|         cs1, cs2, outcome = cache[key] |  | ||||||
|         # cache hit |  | ||||||
|         if s1 == cs1 and s2 == cs2: |  | ||||||
|             # cached signatures match |  | ||||||
|             return outcome |  | ||||||
|         # stale cached signature(s) |  | ||||||
|     # really compare |  | ||||||
|     outcome = do_cmp(f1, f2) |  | ||||||
|     cache[key] = s1, s2, outcome |  | ||||||
|     return outcome |  | ||||||
| 
 |  | ||||||
| def sig(st): |  | ||||||
|     """Return signature (i.e., type, size, mtime) from raw stat data.""" |  | ||||||
|     return S_IFMT(st[ST_MODE]), st[ST_SIZE], st[ST_MTIME] |  | ||||||
| 
 |  | ||||||
| def do_cmp(f1, f2): |  | ||||||
|     """Compare two files, really.""" |  | ||||||
|     #print '    cmp', f1, f2 # XXX remove when debugged |  | ||||||
|     bufsize = 8*1024 # Could be tuned |  | ||||||
|     fp1 = open(f1, 'rb') |  | ||||||
|     fp2 = open(f2, 'rb') |  | ||||||
|     while 1: |  | ||||||
|         b1 = fp1.read(bufsize) |  | ||||||
|         b2 = fp2.read(bufsize) |  | ||||||
|         if b1 != b2: return 0 |  | ||||||
|         if not b1: return 1 |  | ||||||
|  | @ -1,81 +0,0 @@ | ||||||
| # A subroutine for extracting a function name from a code object |  | ||||||
| # (with cache) |  | ||||||
| 
 |  | ||||||
| import sys |  | ||||||
| from stat import * |  | ||||||
| import string |  | ||||||
| import os |  | ||||||
| import linecache |  | ||||||
| 
 |  | ||||||
| # XXX The functions getcodename() and getfuncname() are now obsolete |  | ||||||
| # XXX as code and function objects now have a name attribute -- |  | ||||||
| # XXX co.co_name and f.func_name. |  | ||||||
| # XXX getlineno() is now also obsolete because of the new attribute |  | ||||||
| # XXX of code objects, co.co_firstlineno. |  | ||||||
| 
 |  | ||||||
| # Extract the function or class name from a code object. |  | ||||||
| # This is a bit of a hack, since a code object doesn't contain |  | ||||||
| # the name directly.  So what do we do: |  | ||||||
| # - get the filename (which *is* in the code object) |  | ||||||
| # - look in the code string to find the first SET_LINENO instruction |  | ||||||
| #   (this must be the first instruction) |  | ||||||
| # - get the line from the file |  | ||||||
| # - if the line starts with 'class' or 'def' (after possible whitespace), |  | ||||||
| #   extract the following identifier |  | ||||||
| # |  | ||||||
| # This breaks apart when the function was read from <stdin> |  | ||||||
| # or constructed by exec(), when the file is not accessible, |  | ||||||
| # and also when the file has been modified or when a line is |  | ||||||
| # continued with a backslash before the function or class name. |  | ||||||
| # |  | ||||||
| # Because this is a pretty expensive hack, a cache is kept. |  | ||||||
| 
 |  | ||||||
| SET_LINENO = 127 # The opcode (see "opcode.h" in the Python source) |  | ||||||
| identchars = string.ascii_letters + string.digits + '_' # Identifier characters |  | ||||||
| 
 |  | ||||||
| _namecache = {} # The cache |  | ||||||
| 
 |  | ||||||
| def getcodename(co): |  | ||||||
|     try: |  | ||||||
|         return co.co_name |  | ||||||
|     except AttributeError: |  | ||||||
|         pass |  | ||||||
|     key = `co` # arbitrary but uniquely identifying string |  | ||||||
|     if _namecache.has_key(key): return _namecache[key] |  | ||||||
|     filename = co.co_filename |  | ||||||
|     code = co.co_code |  | ||||||
|     name = '' |  | ||||||
|     if ord(code[0]) == SET_LINENO: |  | ||||||
|         lineno = ord(code[1]) | ord(code[2]) << 8 |  | ||||||
|         line = linecache.getline(filename, lineno) |  | ||||||
|         words = line.split() |  | ||||||
|         if len(words) >= 2 and words[0] in ('def', 'class'): |  | ||||||
|             name = words[1] |  | ||||||
|             for i in range(len(name)): |  | ||||||
|                 if name[i] not in identchars: |  | ||||||
|                     name = name[:i] |  | ||||||
|                     break |  | ||||||
|     _namecache[key] = name |  | ||||||
|     return name |  | ||||||
| 
 |  | ||||||
| # Use the above routine to find a function's name. |  | ||||||
| 
 |  | ||||||
| def getfuncname(func): |  | ||||||
|     try: |  | ||||||
|         return func.func_name |  | ||||||
|     except AttributeError: |  | ||||||
|         pass |  | ||||||
|     return getcodename(func.func_code) |  | ||||||
| 
 |  | ||||||
| # A part of the above code to extract just the line number from a code object. |  | ||||||
| 
 |  | ||||||
| def getlineno(co): |  | ||||||
|     try: |  | ||||||
|         return co.co_firstlineno |  | ||||||
|     except AttributeError: |  | ||||||
|         pass |  | ||||||
|     code = co.co_code |  | ||||||
|     if ord(code[0]) == SET_LINENO: |  | ||||||
|         return ord(code[1]) | ord(code[2]) << 8 |  | ||||||
|     else: |  | ||||||
|         return -1 |  | ||||||
|  | @ -1,202 +0,0 @@ | ||||||
| """A class to build directory diff tools on.""" |  | ||||||
| 
 |  | ||||||
| import os |  | ||||||
| 
 |  | ||||||
| import dircache |  | ||||||
| import cmpcache |  | ||||||
| import statcache |  | ||||||
| from stat import * |  | ||||||
| 
 |  | ||||||
| class dircmp: |  | ||||||
|     """Directory comparison class.""" |  | ||||||
| 
 |  | ||||||
|     def new(self, a, b): |  | ||||||
|         """Initialize.""" |  | ||||||
|         self.a = a |  | ||||||
|         self.b = b |  | ||||||
|         # Properties that caller may change before calling self.run(): |  | ||||||
|         self.hide = [os.curdir, os.pardir] # Names never to be shown |  | ||||||
|         self.ignore = ['RCS', 'tags'] # Names ignored in comparison |  | ||||||
| 
 |  | ||||||
|         return self |  | ||||||
| 
 |  | ||||||
|     def run(self): |  | ||||||
|         """Compare everything except common subdirectories.""" |  | ||||||
|         self.a_list = filter(dircache.listdir(self.a), self.hide) |  | ||||||
|         self.b_list = filter(dircache.listdir(self.b), self.hide) |  | ||||||
|         self.a_list.sort() |  | ||||||
|         self.b_list.sort() |  | ||||||
|         self.phase1() |  | ||||||
|         self.phase2() |  | ||||||
|         self.phase3() |  | ||||||
| 
 |  | ||||||
|     def phase1(self): |  | ||||||
|         """Compute common names.""" |  | ||||||
|         self.a_only = [] |  | ||||||
|         self.common = [] |  | ||||||
|         for x in self.a_list: |  | ||||||
|             if x in self.b_list: |  | ||||||
|                 self.common.append(x) |  | ||||||
|             else: |  | ||||||
|                 self.a_only.append(x) |  | ||||||
| 
 |  | ||||||
|         self.b_only = [] |  | ||||||
|         for x in self.b_list: |  | ||||||
|             if x not in self.common: |  | ||||||
|                 self.b_only.append(x) |  | ||||||
| 
 |  | ||||||
|     def phase2(self): |  | ||||||
|         """Distinguish files, directories, funnies.""" |  | ||||||
|         self.common_dirs = [] |  | ||||||
|         self.common_files = [] |  | ||||||
|         self.common_funny = [] |  | ||||||
| 
 |  | ||||||
|         for x in self.common: |  | ||||||
|             a_path = os.path.join(self.a, x) |  | ||||||
|             b_path = os.path.join(self.b, x) |  | ||||||
| 
 |  | ||||||
|             ok = 1 |  | ||||||
|             try: |  | ||||||
|                 a_stat = statcache.stat(a_path) |  | ||||||
|             except os.error, why: |  | ||||||
|                 # print 'Can\'t stat', a_path, ':', why[1] |  | ||||||
|                 ok = 0 |  | ||||||
|             try: |  | ||||||
|                 b_stat = statcache.stat(b_path) |  | ||||||
|             except os.error, why: |  | ||||||
|                 # print 'Can\'t stat', b_path, ':', why[1] |  | ||||||
|                 ok = 0 |  | ||||||
| 
 |  | ||||||
|             if ok: |  | ||||||
|                 a_type = S_IFMT(a_stat[ST_MODE]) |  | ||||||
|                 b_type = S_IFMT(b_stat[ST_MODE]) |  | ||||||
|                 if a_type != b_type: |  | ||||||
|                     self.common_funny.append(x) |  | ||||||
|                 elif S_ISDIR(a_type): |  | ||||||
|                     self.common_dirs.append(x) |  | ||||||
|                 elif S_ISREG(a_type): |  | ||||||
|                     self.common_files.append(x) |  | ||||||
|                 else: |  | ||||||
|                     self.common_funny.append(x) |  | ||||||
|             else: |  | ||||||
|                 self.common_funny.append(x) |  | ||||||
| 
 |  | ||||||
|     def phase3(self): |  | ||||||
|         """Find out differences between common files.""" |  | ||||||
|         xx = cmpfiles(self.a, self.b, self.common_files) |  | ||||||
|         self.same_files, self.diff_files, self.funny_files = xx |  | ||||||
| 
 |  | ||||||
|     def phase4(self): |  | ||||||
|         """Find out differences between common subdirectories. |  | ||||||
|         A new dircmp object is created for each common subdirectory, |  | ||||||
|         these are stored in a dictionary indexed by filename. |  | ||||||
|         The hide and ignore properties are inherited from the parent.""" |  | ||||||
|         self.subdirs = {} |  | ||||||
|         for x in self.common_dirs: |  | ||||||
|             a_x = os.path.join(self.a, x) |  | ||||||
|             b_x = os.path.join(self.b, x) |  | ||||||
|             self.subdirs[x] = newdd = dircmp().new(a_x, b_x) |  | ||||||
|             newdd.hide = self.hide |  | ||||||
|             newdd.ignore = self.ignore |  | ||||||
|             newdd.run() |  | ||||||
| 
 |  | ||||||
|     def phase4_closure(self): |  | ||||||
|         """Recursively call phase4() on subdirectories.""" |  | ||||||
|         self.phase4() |  | ||||||
|         for x in self.subdirs.keys(): |  | ||||||
|             self.subdirs[x].phase4_closure() |  | ||||||
| 
 |  | ||||||
|     def report(self): |  | ||||||
|         """Print a report on the differences between a and b.""" |  | ||||||
|         # Assume that phases 1 to 3 have been executed |  | ||||||
|         # Output format is purposely lousy |  | ||||||
|         print 'diff', self.a, self.b |  | ||||||
|         if self.a_only: |  | ||||||
|             print 'Only in', self.a, ':', self.a_only |  | ||||||
|         if self.b_only: |  | ||||||
|             print 'Only in', self.b, ':', self.b_only |  | ||||||
|         if self.same_files: |  | ||||||
|             print 'Identical files :', self.same_files |  | ||||||
|         if self.diff_files: |  | ||||||
|             print 'Differing files :', self.diff_files |  | ||||||
|         if self.funny_files: |  | ||||||
|             print 'Trouble with common files :', self.funny_files |  | ||||||
|         if self.common_dirs: |  | ||||||
|             print 'Common subdirectories :', self.common_dirs |  | ||||||
|         if self.common_funny: |  | ||||||
|             print 'Common funny cases :', self.common_funny |  | ||||||
| 
 |  | ||||||
|     def report_closure(self): |  | ||||||
|         """Print reports on self and on subdirs. |  | ||||||
|         If phase 4 hasn't been done, no subdir reports are printed.""" |  | ||||||
|         self.report() |  | ||||||
|         try: |  | ||||||
|             x = self.subdirs |  | ||||||
|         except AttributeError: |  | ||||||
|             return # No subdirectories computed |  | ||||||
|         for x in self.subdirs.keys(): |  | ||||||
|             print |  | ||||||
|             self.subdirs[x].report_closure() |  | ||||||
| 
 |  | ||||||
|     def report_phase4_closure(self): |  | ||||||
|         """Report and do phase 4 recursively.""" |  | ||||||
|         self.report() |  | ||||||
|         self.phase4() |  | ||||||
|         for x in self.subdirs.keys(): |  | ||||||
|             print |  | ||||||
|             self.subdirs[x].report_phase4_closure() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def cmpfiles(a, b, common): |  | ||||||
|     """Compare common files in two directories. |  | ||||||
|     Return: |  | ||||||
|         - files that compare equal |  | ||||||
|         - files that compare different |  | ||||||
|         - funny cases (can't stat etc.)""" |  | ||||||
| 
 |  | ||||||
|     res = ([], [], []) |  | ||||||
|     for x in common: |  | ||||||
|         res[cmp(os.path.join(a, x), os.path.join(b, x))].append(x) |  | ||||||
|     return res |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def cmp(a, b): |  | ||||||
|     """Compare two files. |  | ||||||
|     Return: |  | ||||||
|         0 for equal |  | ||||||
|         1 for different |  | ||||||
|         2 for funny cases (can't stat, etc.)""" |  | ||||||
| 
 |  | ||||||
|     try: |  | ||||||
|         if cmpcache.cmp(a, b): return 0 |  | ||||||
|         return 1 |  | ||||||
|     except os.error: |  | ||||||
|         return 2 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def filter(list, skip): |  | ||||||
|     """Return a copy with items that occur in skip removed.""" |  | ||||||
| 
 |  | ||||||
|     result = [] |  | ||||||
|     for item in list: |  | ||||||
|         if item not in skip: result.append(item) |  | ||||||
|     return result |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def demo(): |  | ||||||
|     """Demonstration and testing.""" |  | ||||||
| 
 |  | ||||||
|     import sys |  | ||||||
|     import getopt |  | ||||||
|     options, args = getopt.getopt(sys.argv[1:], 'r') |  | ||||||
|     if len(args) != 2: |  | ||||||
|         raise getopt.error, 'need exactly two args' |  | ||||||
|     dd = dircmp().new(args[0], args[1]) |  | ||||||
|     dd.run() |  | ||||||
|     if ('-r', '') in options: |  | ||||||
|         dd.report_phase4_closure() |  | ||||||
|     else: |  | ||||||
|         dd.report() |  | ||||||
| 
 |  | ||||||
| if __name__ == "__main__": |  | ||||||
|     demo() |  | ||||||
|  | @ -1,63 +0,0 @@ | ||||||
| # Module 'dump' |  | ||||||
| # |  | ||||||
| # Print python code that reconstructs a variable. |  | ||||||
| # This only works in certain cases. |  | ||||||
| # |  | ||||||
| # It works fine for: |  | ||||||
| # - ints and floats (except NaNs and other weird things) |  | ||||||
| # - strings |  | ||||||
| # - compounds and lists, provided it works for all their elements |  | ||||||
| # - imported modules, provided their name is the module name |  | ||||||
| # |  | ||||||
| # It works for top-level dictionaries but not for dictionaries |  | ||||||
| # contained in other objects (could be made to work with some hassle |  | ||||||
| # though). |  | ||||||
| # |  | ||||||
| # It does not work for functions (all sorts), classes, class objects, |  | ||||||
| # windows, files etc. |  | ||||||
| # |  | ||||||
| # Finally, objects referenced by more than one name or contained in more |  | ||||||
| # than one other object lose their sharing property (this is bad for |  | ||||||
| # strings used as exception identifiers, for instance). |  | ||||||
| 
 |  | ||||||
| # Dump a whole symbol table |  | ||||||
| # |  | ||||||
| def dumpsymtab(dict): |  | ||||||
|     for key in dict.keys(): |  | ||||||
|         dumpvar(key, dict[key]) |  | ||||||
| 
 |  | ||||||
| # Dump a single variable |  | ||||||
| # |  | ||||||
| def dumpvar(name, x): |  | ||||||
|     import sys |  | ||||||
|     t = type(x) |  | ||||||
|     if t == type({}): |  | ||||||
|         print name, '= {}' |  | ||||||
|         for key in x.keys(): |  | ||||||
|             item = x[key] |  | ||||||
|             if not printable(item): |  | ||||||
|                 print '#', |  | ||||||
|             print name, '[', `key`, '] =', `item` |  | ||||||
|     elif t in (type(''), type(0), type(0.0), type([]), type(())): |  | ||||||
|         if not printable(x): |  | ||||||
|             print '#', |  | ||||||
|         print name, '=', `x` |  | ||||||
|     elif t == type(sys): |  | ||||||
|         print 'import', name, '#', x |  | ||||||
|     else: |  | ||||||
|         print '#', name, '=', x |  | ||||||
| 
 |  | ||||||
| # check if a value is printable in a way that can be read back with input() |  | ||||||
| # |  | ||||||
| def printable(x): |  | ||||||
|     t = type(x) |  | ||||||
|     if t in (type(''), type(0), type(0.0)): |  | ||||||
|         return 1 |  | ||||||
|     if t in (type([]), type(())): |  | ||||||
|         for item in x: |  | ||||||
|             if not printable(item): |  | ||||||
|                 return 0 |  | ||||||
|         return 1 |  | ||||||
|     if x == {}: |  | ||||||
|         return 1 |  | ||||||
|     return 0 |  | ||||||
|  | @ -1,26 +0,0 @@ | ||||||
| import fnmatch |  | ||||||
| import os |  | ||||||
| 
 |  | ||||||
| _debug = 0 |  | ||||||
| 
 |  | ||||||
| _prune = ['(*)'] |  | ||||||
| 
 |  | ||||||
| def find(pattern, dir = os.curdir): |  | ||||||
|     list = [] |  | ||||||
|     names = os.listdir(dir) |  | ||||||
|     names.sort() |  | ||||||
|     for name in names: |  | ||||||
|         if name in (os.curdir, os.pardir): |  | ||||||
|             continue |  | ||||||
|         fullname = os.path.join(dir, name) |  | ||||||
|         if fnmatch.fnmatch(name, pattern): |  | ||||||
|             list.append(fullname) |  | ||||||
|         if os.path.isdir(fullname) and not os.path.islink(fullname): |  | ||||||
|             for p in _prune: |  | ||||||
|                 if fnmatch.fnmatch(name, p): |  | ||||||
|                     if _debug: print "skip", `fullname` |  | ||||||
|                     break |  | ||||||
|             else: |  | ||||||
|                 if _debug: print "descend into", `fullname` |  | ||||||
|                 list = list + find(pattern, fullname) |  | ||||||
|     return list |  | ||||||
|  | @ -1,623 +0,0 @@ | ||||||
| # Text formatting abstractions |  | ||||||
| # Note -- this module is obsolete, it's too slow anyway |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| import string |  | ||||||
| import Para |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # A formatter back-end object has one method that is called by the formatter: |  | ||||||
| # addpara(p), where p is a paragraph object.  For example: |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Formatter back-end to do nothing at all with the paragraphs |  | ||||||
| class NullBackEnd: |  | ||||||
|     # |  | ||||||
|     def __init__(self): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     def addpara(self, p): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     def bgn_anchor(self, id): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     def end_anchor(self, id): |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Formatter back-end to collect the paragraphs in a list |  | ||||||
| class SavingBackEnd(NullBackEnd): |  | ||||||
|     # |  | ||||||
|     def __init__(self): |  | ||||||
|         self.paralist = [] |  | ||||||
|     # |  | ||||||
|     def addpara(self, p): |  | ||||||
|         self.paralist.append(p) |  | ||||||
|     # |  | ||||||
|     def hitcheck(self, h, v): |  | ||||||
|         hits = [] |  | ||||||
|         for p in self.paralist: |  | ||||||
|             if p.top <= v <= p.bottom: |  | ||||||
|                 for id in p.hitcheck(h, v): |  | ||||||
|                     if id not in hits: |  | ||||||
|                         hits.append(id) |  | ||||||
|         return hits |  | ||||||
|     # |  | ||||||
|     def extract(self): |  | ||||||
|         text = '' |  | ||||||
|         for p in self.paralist: |  | ||||||
|             text = text + (p.extract()) |  | ||||||
|         return text |  | ||||||
|     # |  | ||||||
|     def extractpart(self, long1, long2): |  | ||||||
|         if long1 > long2: long1, long2 = long2, long1 |  | ||||||
|         para1, pos1 = long1 |  | ||||||
|         para2, pos2 = long2 |  | ||||||
|         text = '' |  | ||||||
|         while para1 < para2: |  | ||||||
|             ptext = self.paralist[para1].extract() |  | ||||||
|             text = text + ptext[pos1:] |  | ||||||
|             pos1 = 0 |  | ||||||
|             para1 = para1 + 1 |  | ||||||
|         ptext = self.paralist[para2].extract() |  | ||||||
|         return text + ptext[pos1:pos2] |  | ||||||
|     # |  | ||||||
|     def whereis(self, d, h, v): |  | ||||||
|         total = 0 |  | ||||||
|         for i in range(len(self.paralist)): |  | ||||||
|             p = self.paralist[i] |  | ||||||
|             result = p.whereis(d, h, v) |  | ||||||
|             if result is not None: |  | ||||||
|                 return i, result |  | ||||||
|         return None |  | ||||||
|     # |  | ||||||
|     def roundtowords(self, long1, long2): |  | ||||||
|         i, offset = long1 |  | ||||||
|         text = self.paralist[i].extract() |  | ||||||
|         while offset > 0 and text[offset-1] != ' ': offset = offset-1 |  | ||||||
|         long1 = i, offset |  | ||||||
|         # |  | ||||||
|         i, offset = long2 |  | ||||||
|         text = self.paralist[i].extract() |  | ||||||
|         n = len(text) |  | ||||||
|         while offset < n-1 and text[offset] != ' ': offset = offset+1 |  | ||||||
|         long2 = i, offset |  | ||||||
|         # |  | ||||||
|         return long1, long2 |  | ||||||
|     # |  | ||||||
|     def roundtoparagraphs(self, long1, long2): |  | ||||||
|         long1 = long1[0], 0 |  | ||||||
|         long2 = long2[0], len(self.paralist[long2[0]].extract()) |  | ||||||
|         return long1, long2 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Formatter back-end to send the text directly to the drawing object |  | ||||||
| class WritingBackEnd(NullBackEnd): |  | ||||||
|     # |  | ||||||
|     def __init__(self, d, width): |  | ||||||
|         self.d = d |  | ||||||
|         self.width = width |  | ||||||
|         self.lineno = 0 |  | ||||||
|     # |  | ||||||
|     def addpara(self, p): |  | ||||||
|         self.lineno = p.render(self.d, 0, self.lineno, self.width) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # A formatter receives a stream of formatting instructions and assembles |  | ||||||
| # these into a stream of paragraphs on to a back-end.  The assembly is |  | ||||||
| # parametrized by a text measurement object, which must match the output |  | ||||||
| # operations of the back-end.  The back-end is responsible for splitting |  | ||||||
| # paragraphs up in lines of a given maximum width.  (This is done because |  | ||||||
| # in a windowing environment, when the window size changes, there is no |  | ||||||
| # need to redo the assembly into paragraphs, but the splitting into lines |  | ||||||
| # must be done taking the new window size into account.) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Formatter base class.  Initialize it with a text measurement object, |  | ||||||
| # which is used for text measurements, and a back-end object, |  | ||||||
| # which receives the completed paragraphs.  The formatting methods are: |  | ||||||
| # setfont(font) |  | ||||||
| # setleftindent(nspaces) |  | ||||||
| # setjust(type) where type is 'l', 'c', 'r', or 'lr' |  | ||||||
| # flush() |  | ||||||
| # vspace(nlines) |  | ||||||
| # needvspace(nlines) |  | ||||||
| # addword(word, nspaces) |  | ||||||
| class BaseFormatter: |  | ||||||
|     # |  | ||||||
|     def __init__(self, d, b): |  | ||||||
|         # Drawing object used for text measurements |  | ||||||
|         self.d = d |  | ||||||
|         # |  | ||||||
|         # BackEnd object receiving completed paragraphs |  | ||||||
|         self.b = b |  | ||||||
|         # |  | ||||||
|         # Parameters of the formatting model |  | ||||||
|         self.leftindent = 0 |  | ||||||
|         self.just = 'l' |  | ||||||
|         self.font = None |  | ||||||
|         self.blanklines = 0 |  | ||||||
|         # |  | ||||||
|         # Parameters derived from the current font |  | ||||||
|         self.space = d.textwidth(' ') |  | ||||||
|         self.line = d.lineheight() |  | ||||||
|         self.ascent = d.baseline() |  | ||||||
|         self.descent = self.line - self.ascent |  | ||||||
|         # |  | ||||||
|         # Parameter derived from the default font |  | ||||||
|         self.n_space = self.space |  | ||||||
|         # |  | ||||||
|         # Current paragraph being built |  | ||||||
|         self.para = None |  | ||||||
|         self.nospace = 1 |  | ||||||
|         # |  | ||||||
|         # Font to set on the next word |  | ||||||
|         self.nextfont = None |  | ||||||
|     # |  | ||||||
|     def newpara(self): |  | ||||||
|         return Para.Para() |  | ||||||
|     # |  | ||||||
|     def setfont(self, font): |  | ||||||
|         if font is None: return |  | ||||||
|         self.font = self.nextfont = font |  | ||||||
|         d = self.d |  | ||||||
|         d.setfont(font) |  | ||||||
|         self.space = d.textwidth(' ') |  | ||||||
|         self.line = d.lineheight() |  | ||||||
|         self.ascent = d.baseline() |  | ||||||
|         self.descent = self.line - self.ascent |  | ||||||
|     # |  | ||||||
|     def setleftindent(self, nspaces): |  | ||||||
|         self.leftindent = int(self.n_space * nspaces) |  | ||||||
|         if self.para: |  | ||||||
|             hang = self.leftindent - self.para.indent_left |  | ||||||
|             if hang > 0 and self.para.getlength() <= hang: |  | ||||||
|                 self.para.makehangingtag(hang) |  | ||||||
|                 self.nospace = 1 |  | ||||||
|             else: |  | ||||||
|                 self.flush() |  | ||||||
|     # |  | ||||||
|     def setrightindent(self, nspaces): |  | ||||||
|         self.rightindent = int(self.n_space * nspaces) |  | ||||||
|         if self.para: |  | ||||||
|             self.para.indent_right = self.rightindent |  | ||||||
|             self.flush() |  | ||||||
|     # |  | ||||||
|     def setjust(self, just): |  | ||||||
|         self.just = just |  | ||||||
|         if self.para: |  | ||||||
|             self.para.just = self.just |  | ||||||
|     # |  | ||||||
|     def flush(self): |  | ||||||
|         if self.para: |  | ||||||
|             self.b.addpara(self.para) |  | ||||||
|             self.para = None |  | ||||||
|             if self.font is not None: |  | ||||||
|                 self.d.setfont(self.font) |  | ||||||
|         self.nospace = 1 |  | ||||||
|     # |  | ||||||
|     def vspace(self, nlines): |  | ||||||
|         self.flush() |  | ||||||
|         if nlines > 0: |  | ||||||
|             self.para = self.newpara() |  | ||||||
|             tuple = None, '', 0, 0, 0, int(nlines*self.line), 0 |  | ||||||
|             self.para.words.append(tuple) |  | ||||||
|             self.flush() |  | ||||||
|             self.blanklines = self.blanklines + nlines |  | ||||||
|     # |  | ||||||
|     def needvspace(self, nlines): |  | ||||||
|         self.flush() # Just to be sure |  | ||||||
|         if nlines > self.blanklines: |  | ||||||
|             self.vspace(nlines - self.blanklines) |  | ||||||
|     # |  | ||||||
|     def addword(self, text, space): |  | ||||||
|         if self.nospace and not text: |  | ||||||
|             return |  | ||||||
|         self.nospace = 0 |  | ||||||
|         self.blanklines = 0 |  | ||||||
|         if not self.para: |  | ||||||
|             self.para = self.newpara() |  | ||||||
|             self.para.indent_left = self.leftindent |  | ||||||
|             self.para.just = self.just |  | ||||||
|             self.nextfont = self.font |  | ||||||
|         space = int(space * self.space) |  | ||||||
|         self.para.words.append((self.nextfont, text, |  | ||||||
|                 self.d.textwidth(text), space, space, |  | ||||||
|                 self.ascent, self.descent)) |  | ||||||
|         self.nextfont = None |  | ||||||
|     # |  | ||||||
|     def bgn_anchor(self, id): |  | ||||||
|         if not self.para: |  | ||||||
|             self.nospace = 0 |  | ||||||
|             self.addword('', 0) |  | ||||||
|         self.para.bgn_anchor(id) |  | ||||||
|     # |  | ||||||
|     def end_anchor(self, id): |  | ||||||
|         if not self.para: |  | ||||||
|             self.nospace = 0 |  | ||||||
|             self.addword('', 0) |  | ||||||
|         self.para.end_anchor(id) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Measuring object for measuring text as viewed on a tty |  | ||||||
| class NullMeasurer: |  | ||||||
|     # |  | ||||||
|     def __init__(self): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     def setfont(self, font): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     def textwidth(self, text): |  | ||||||
|         return len(text) |  | ||||||
|     # |  | ||||||
|     def lineheight(self): |  | ||||||
|         return 1 |  | ||||||
|     # |  | ||||||
|     def baseline(self): |  | ||||||
|         return 0 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Drawing object for writing plain ASCII text to a file |  | ||||||
| class FileWriter: |  | ||||||
|     # |  | ||||||
|     def __init__(self, fp): |  | ||||||
|         self.fp = fp |  | ||||||
|         self.lineno, self.colno = 0, 0 |  | ||||||
|     # |  | ||||||
|     def setfont(self, font): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     def text(self, (h, v), str): |  | ||||||
|         if not str: return |  | ||||||
|         if '\n' in str: |  | ||||||
|             raise ValueError, 'can\'t write \\n' |  | ||||||
|         while self.lineno < v: |  | ||||||
|             self.fp.write('\n') |  | ||||||
|             self.colno, self.lineno = 0, self.lineno + 1 |  | ||||||
|         while self.lineno > v: |  | ||||||
|             # XXX This should never happen... |  | ||||||
|             self.fp.write('\033[A') # ANSI up arrow |  | ||||||
|             self.lineno = self.lineno - 1 |  | ||||||
|         if self.colno < h: |  | ||||||
|             self.fp.write(' ' * (h - self.colno)) |  | ||||||
|         elif self.colno > h: |  | ||||||
|             self.fp.write('\b' * (self.colno - h)) |  | ||||||
|         self.colno = h |  | ||||||
|         self.fp.write(str) |  | ||||||
|         self.colno = h + len(str) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Formatting class to do nothing at all with the data |  | ||||||
| class NullFormatter(BaseFormatter): |  | ||||||
|     # |  | ||||||
|     def __init__(self): |  | ||||||
|         d = NullMeasurer() |  | ||||||
|         b = NullBackEnd() |  | ||||||
|         BaseFormatter.__init__(self, d, b) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Formatting class to write directly to a file |  | ||||||
| class WritingFormatter(BaseFormatter): |  | ||||||
|     # |  | ||||||
|     def __init__(self, fp, width): |  | ||||||
|         dm = NullMeasurer() |  | ||||||
|         dw = FileWriter(fp) |  | ||||||
|         b = WritingBackEnd(dw, width) |  | ||||||
|         BaseFormatter.__init__(self, dm, b) |  | ||||||
|         self.blanklines = 1 |  | ||||||
|     # |  | ||||||
|     # Suppress multiple blank lines |  | ||||||
|     def needvspace(self, nlines): |  | ||||||
|         BaseFormatter.needvspace(self, min(1, nlines)) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # A "FunnyFormatter" writes ASCII text with a twist: *bold words*, |  | ||||||
| # _italic text_ and _underlined words_, and `quoted text'. |  | ||||||
| # It assumes that the fonts are 'r', 'i', 'b', 'u', 'q': (roman, |  | ||||||
| # italic, bold, underline, quote). |  | ||||||
| # Moreover, if the font is in upper case, the text is converted to |  | ||||||
| # UPPER CASE. |  | ||||||
| class FunnyFormatter(WritingFormatter): |  | ||||||
|     # |  | ||||||
|     def flush(self): |  | ||||||
|         if self.para: finalize(self.para) |  | ||||||
|         WritingFormatter.flush(self) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Surrounds *bold words* and _italic text_ in a paragraph with |  | ||||||
| # appropriate markers, fixing the size (assuming these characters' |  | ||||||
| # width is 1). |  | ||||||
| openchar = \ |  | ||||||
|     {'b':'*', 'i':'_', 'u':'_', 'q':'`', 'B':'*', 'I':'_', 'U':'_', 'Q':'`'} |  | ||||||
| closechar = \ |  | ||||||
|     {'b':'*', 'i':'_', 'u':'_', 'q':'\'', 'B':'*', 'I':'_', 'U':'_', 'Q':'\''} |  | ||||||
| def finalize(para): |  | ||||||
|     oldfont = curfont = 'r' |  | ||||||
|     para.words.append(('r', '', 0, 0, 0, 0)) # temporary, deleted at end |  | ||||||
|     for i in range(len(para.words)): |  | ||||||
|         fo, te, wi = para.words[i][:3] |  | ||||||
|         if fo is not None: curfont = fo |  | ||||||
|         if curfont != oldfont: |  | ||||||
|             if closechar.has_key(oldfont): |  | ||||||
|                 c = closechar[oldfont] |  | ||||||
|                 j = i-1 |  | ||||||
|                 while j > 0 and para.words[j][1] == '': j = j-1 |  | ||||||
|                 fo1, te1, wi1 = para.words[j][:3] |  | ||||||
|                 te1 = te1 + c |  | ||||||
|                 wi1 = wi1 + len(c) |  | ||||||
|                 para.words[j] = (fo1, te1, wi1) + \ |  | ||||||
|                         para.words[j][3:] |  | ||||||
|             if openchar.has_key(curfont) and te: |  | ||||||
|                 c = openchar[curfont] |  | ||||||
|                 te = c + te |  | ||||||
|                 wi = len(c) + wi |  | ||||||
|                 para.words[i] = (fo, te, wi) + \ |  | ||||||
|                         para.words[i][3:] |  | ||||||
|             if te: oldfont = curfont |  | ||||||
|             else: oldfont = 'r' |  | ||||||
|         if curfont in string.uppercase: |  | ||||||
|             te = string.upper(te) |  | ||||||
|             para.words[i] = (fo, te, wi) + para.words[i][3:] |  | ||||||
|     del para.words[-1] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Formatter back-end to draw the text in a window. |  | ||||||
| # This has an option to draw while the paragraphs are being added, |  | ||||||
| # to minimize the delay before the user sees anything. |  | ||||||
| # This manages the entire "document" of the window. |  | ||||||
| class StdwinBackEnd(SavingBackEnd): |  | ||||||
|     # |  | ||||||
|     def __init__(self, window, drawnow): |  | ||||||
|         self.window = window |  | ||||||
|         self.drawnow = drawnow |  | ||||||
|         self.width = window.getwinsize()[0] |  | ||||||
|         self.selection = None |  | ||||||
|         self.height = 0 |  | ||||||
|         window.setorigin(0, 0) |  | ||||||
|         window.setdocsize(0, 0) |  | ||||||
|         self.d = window.begindrawing() |  | ||||||
|         SavingBackEnd.__init__(self) |  | ||||||
|     # |  | ||||||
|     def finish(self): |  | ||||||
|         self.d.close() |  | ||||||
|         self.d = None |  | ||||||
|         self.window.setdocsize(0, self.height) |  | ||||||
|     # |  | ||||||
|     def addpara(self, p): |  | ||||||
|         self.paralist.append(p) |  | ||||||
|         if self.drawnow: |  | ||||||
|             self.height = \ |  | ||||||
|                     p.render(self.d, 0, self.height, self.width) |  | ||||||
|         else: |  | ||||||
|             p.layout(self.width) |  | ||||||
|             p.left = 0 |  | ||||||
|             p.top = self.height |  | ||||||
|             p.right = self.width |  | ||||||
|             p.bottom = self.height + p.height |  | ||||||
|             self.height = p.bottom |  | ||||||
|     # |  | ||||||
|     def resize(self): |  | ||||||
|         self.window.change((0, 0), (self.width, self.height)) |  | ||||||
|         self.width = self.window.getwinsize()[0] |  | ||||||
|         self.height = 0 |  | ||||||
|         for p in self.paralist: |  | ||||||
|             p.layout(self.width) |  | ||||||
|             p.left = 0 |  | ||||||
|             p.top = self.height |  | ||||||
|             p.right = self.width |  | ||||||
|             p.bottom = self.height + p.height |  | ||||||
|             self.height = p.bottom |  | ||||||
|         self.window.change((0, 0), (self.width, self.height)) |  | ||||||
|         self.window.setdocsize(0, self.height) |  | ||||||
|     # |  | ||||||
|     def redraw(self, area): |  | ||||||
|         d = self.window.begindrawing() |  | ||||||
|         (left, top), (right, bottom) = area |  | ||||||
|         d.erase(area) |  | ||||||
|         d.cliprect(area) |  | ||||||
|         for p in self.paralist: |  | ||||||
|             if top < p.bottom and p.top < bottom: |  | ||||||
|                 v = p.render(d, p.left, p.top, p.right) |  | ||||||
|         if self.selection: |  | ||||||
|             self.invert(d, self.selection) |  | ||||||
|         d.close() |  | ||||||
|     # |  | ||||||
|     def setselection(self, new): |  | ||||||
|         if new: |  | ||||||
|             long1, long2 = new |  | ||||||
|             pos1 = long1[:3] |  | ||||||
|             pos2 = long2[:3] |  | ||||||
|             new = pos1, pos2 |  | ||||||
|         if new != self.selection: |  | ||||||
|             d = self.window.begindrawing() |  | ||||||
|             if self.selection: |  | ||||||
|                 self.invert(d, self.selection) |  | ||||||
|             if new: |  | ||||||
|                 self.invert(d, new) |  | ||||||
|             d.close() |  | ||||||
|             self.selection = new |  | ||||||
|     # |  | ||||||
|     def getselection(self): |  | ||||||
|         return self.selection |  | ||||||
|     # |  | ||||||
|     def extractselection(self): |  | ||||||
|         if self.selection: |  | ||||||
|             a, b = self.selection |  | ||||||
|             return self.extractpart(a, b) |  | ||||||
|         else: |  | ||||||
|             return None |  | ||||||
|     # |  | ||||||
|     def invert(self, d, region): |  | ||||||
|         long1, long2 = region |  | ||||||
|         if long1 > long2: long1, long2 = long2, long1 |  | ||||||
|         para1, pos1 = long1 |  | ||||||
|         para2, pos2 = long2 |  | ||||||
|         while para1 < para2: |  | ||||||
|             self.paralist[para1].invert(d, pos1, None) |  | ||||||
|             pos1 = None |  | ||||||
|             para1 = para1 + 1 |  | ||||||
|         self.paralist[para2].invert(d, pos1, pos2) |  | ||||||
|     # |  | ||||||
|     def search(self, prog): |  | ||||||
|         import re, string |  | ||||||
|         if type(prog) is type(''): |  | ||||||
|             prog = re.compile(string.lower(prog)) |  | ||||||
|         if self.selection: |  | ||||||
|             iold = self.selection[0][0] |  | ||||||
|         else: |  | ||||||
|             iold = -1 |  | ||||||
|         hit = None |  | ||||||
|         for i in range(len(self.paralist)): |  | ||||||
|             if i == iold or i < iold and hit: |  | ||||||
|                 continue |  | ||||||
|             p = self.paralist[i] |  | ||||||
|             text = string.lower(p.extract()) |  | ||||||
|             match = prog.search(text) |  | ||||||
|             if match: |  | ||||||
|                 a, b = match.group(0) |  | ||||||
|                 long1 = i, a |  | ||||||
|                 long2 = i, b |  | ||||||
|                 hit = long1, long2 |  | ||||||
|                 if i > iold: |  | ||||||
|                     break |  | ||||||
|         if hit: |  | ||||||
|             self.setselection(hit) |  | ||||||
|             i = hit[0][0] |  | ||||||
|             p = self.paralist[i] |  | ||||||
|             self.window.show((p.left, p.top), (p.right, p.bottom)) |  | ||||||
|             return 1 |  | ||||||
|         else: |  | ||||||
|             return 0 |  | ||||||
|     # |  | ||||||
|     def showanchor(self, id): |  | ||||||
|         for i in range(len(self.paralist)): |  | ||||||
|             p = self.paralist[i] |  | ||||||
|             if p.hasanchor(id): |  | ||||||
|                 long1 = i, 0 |  | ||||||
|                 long2 = i, len(p.extract()) |  | ||||||
|                 hit = long1, long2 |  | ||||||
|                 self.setselection(hit) |  | ||||||
|                 self.window.show( |  | ||||||
|                         (p.left, p.top), (p.right, p.bottom)) |  | ||||||
|                 break |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # GL extensions |  | ||||||
| 
 |  | ||||||
| class GLFontCache: |  | ||||||
|     # |  | ||||||
|     def __init__(self): |  | ||||||
|         self.reset() |  | ||||||
|         self.setfont('') |  | ||||||
|     # |  | ||||||
|     def reset(self): |  | ||||||
|         self.fontkey = None |  | ||||||
|         self.fonthandle = None |  | ||||||
|         self.fontinfo = None |  | ||||||
|         self.fontcache = {} |  | ||||||
|     # |  | ||||||
|     def close(self): |  | ||||||
|         self.reset() |  | ||||||
|     # |  | ||||||
|     def setfont(self, fontkey): |  | ||||||
|         if fontkey == '': |  | ||||||
|             fontkey = 'Times-Roman 12' |  | ||||||
|         elif ' ' not in fontkey: |  | ||||||
|             fontkey = fontkey + ' 12' |  | ||||||
|         if fontkey == self.fontkey: |  | ||||||
|             return |  | ||||||
|         if self.fontcache.has_key(fontkey): |  | ||||||
|             handle = self.fontcache[fontkey] |  | ||||||
|         else: |  | ||||||
|             import string |  | ||||||
|             i = string.index(fontkey, ' ') |  | ||||||
|             name, sizestr = fontkey[:i], fontkey[i:] |  | ||||||
|             size = eval(sizestr) |  | ||||||
|             key1 = name + ' 1' |  | ||||||
|             key = name + ' ' + `size` |  | ||||||
|             # NB key may differ from fontkey! |  | ||||||
|             if self.fontcache.has_key(key): |  | ||||||
|                 handle = self.fontcache[key] |  | ||||||
|             else: |  | ||||||
|                 if self.fontcache.has_key(key1): |  | ||||||
|                     handle = self.fontcache[key1] |  | ||||||
|                 else: |  | ||||||
|                     import fm |  | ||||||
|                     handle = fm.findfont(name) |  | ||||||
|                     self.fontcache[key1] = handle |  | ||||||
|                 handle = handle.scalefont(size) |  | ||||||
|                 self.fontcache[fontkey] = \ |  | ||||||
|                         self.fontcache[key] = handle |  | ||||||
|         self.fontkey = fontkey |  | ||||||
|         if self.fonthandle != handle: |  | ||||||
|             self.fonthandle = handle |  | ||||||
|             self.fontinfo = handle.getfontinfo() |  | ||||||
|             handle.setfont() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class GLMeasurer(GLFontCache): |  | ||||||
|     # |  | ||||||
|     def textwidth(self, text): |  | ||||||
|         return self.fonthandle.getstrwidth(text) |  | ||||||
|     # |  | ||||||
|     def baseline(self): |  | ||||||
|         return self.fontinfo[6] - self.fontinfo[3] |  | ||||||
|     # |  | ||||||
|     def lineheight(self): |  | ||||||
|         return self.fontinfo[6] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class GLWriter(GLFontCache): |  | ||||||
|     # |  | ||||||
|     # NOTES: |  | ||||||
|     # (1) Use gl.ortho2 to use X pixel coordinates! |  | ||||||
|     # |  | ||||||
|     def text(self, (h, v), text): |  | ||||||
|         import gl, fm |  | ||||||
|         gl.cmov2i(h, v + self.fontinfo[6] - self.fontinfo[3]) |  | ||||||
|         fm.prstr(text) |  | ||||||
|     # |  | ||||||
|     def setfont(self, fontkey): |  | ||||||
|         oldhandle = self.fonthandle |  | ||||||
|         GLFontCache.setfont(fontkey) |  | ||||||
|         if self.fonthandle != oldhandle: |  | ||||||
|             handle.setfont() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class GLMeasurerWriter(GLMeasurer, GLWriter): |  | ||||||
|     pass |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class GLBackEnd(SavingBackEnd): |  | ||||||
|     # |  | ||||||
|     def __init__(self, wid): |  | ||||||
|         import gl |  | ||||||
|         gl.winset(wid) |  | ||||||
|         self.wid = wid |  | ||||||
|         self.width = gl.getsize()[1] |  | ||||||
|         self.height = 0 |  | ||||||
|         self.d = GLMeasurerWriter() |  | ||||||
|         SavingBackEnd.__init__(self) |  | ||||||
|     # |  | ||||||
|     def finish(self): |  | ||||||
|         pass |  | ||||||
|     # |  | ||||||
|     def addpara(self, p): |  | ||||||
|         self.paralist.append(p) |  | ||||||
|         self.height = p.render(self.d, 0, self.height, self.width) |  | ||||||
|     # |  | ||||||
|     def redraw(self): |  | ||||||
|         import gl |  | ||||||
|         gl.winset(self.wid) |  | ||||||
|         width = gl.getsize()[1] |  | ||||||
|         if width != self.width: |  | ||||||
|             setdocsize = 1 |  | ||||||
|             self.width = width |  | ||||||
|             for p in self.paralist: |  | ||||||
|                 p.top = p.bottom = None |  | ||||||
|         d = self.d |  | ||||||
|         v = 0 |  | ||||||
|         for p in self.paralist: |  | ||||||
|             v = p.render(d, 0, v, width) |  | ||||||
|  | @ -1,79 +0,0 @@ | ||||||
| # 'grep' |  | ||||||
| 
 |  | ||||||
| import regex |  | ||||||
| from regex_syntax import * |  | ||||||
| 
 |  | ||||||
| opt_show_where = 0 |  | ||||||
| opt_show_filename = 0 |  | ||||||
| opt_show_lineno = 1 |  | ||||||
| 
 |  | ||||||
| def grep(pat, *files): |  | ||||||
|     return ggrep(RE_SYNTAX_GREP, pat, files) |  | ||||||
| 
 |  | ||||||
| def egrep(pat, *files): |  | ||||||
|     return ggrep(RE_SYNTAX_EGREP, pat, files) |  | ||||||
| 
 |  | ||||||
| def emgrep(pat, *files): |  | ||||||
|     return ggrep(RE_SYNTAX_EMACS, pat, files) |  | ||||||
| 
 |  | ||||||
| def ggrep(syntax, pat, files): |  | ||||||
|     if len(files) == 1 and type(files[0]) == type([]): |  | ||||||
|         files = files[0] |  | ||||||
|     global opt_show_filename |  | ||||||
|     opt_show_filename = (len(files) != 1) |  | ||||||
|     syntax = regex.set_syntax(syntax) |  | ||||||
|     try: |  | ||||||
|         prog = regex.compile(pat) |  | ||||||
|     finally: |  | ||||||
|         syntax = regex.set_syntax(syntax) |  | ||||||
|     for filename in files: |  | ||||||
|         fp = open(filename, 'r') |  | ||||||
|         lineno = 0 |  | ||||||
|         while 1: |  | ||||||
|             line = fp.readline() |  | ||||||
|             if not line: break |  | ||||||
|             lineno = lineno + 1 |  | ||||||
|             if prog.search(line) >= 0: |  | ||||||
|                 showline(filename, lineno, line, prog) |  | ||||||
|         fp.close() |  | ||||||
| 
 |  | ||||||
| def pgrep(pat, *files): |  | ||||||
|     if len(files) == 1 and type(files[0]) == type([]): |  | ||||||
|         files = files[0] |  | ||||||
|     global opt_show_filename |  | ||||||
|     opt_show_filename = (len(files) != 1) |  | ||||||
|     import re |  | ||||||
|     prog = re.compile(pat) |  | ||||||
|     for filename in files: |  | ||||||
|         fp = open(filename, 'r') |  | ||||||
|         lineno = 0 |  | ||||||
|         while 1: |  | ||||||
|             line = fp.readline() |  | ||||||
|             if not line: break |  | ||||||
|             lineno = lineno + 1 |  | ||||||
|             if prog.search(line): |  | ||||||
|                 showline(filename, lineno, line, prog) |  | ||||||
|         fp.close() |  | ||||||
| 
 |  | ||||||
| def showline(filename, lineno, line, prog): |  | ||||||
|     if line[-1:] == '\n': line = line[:-1] |  | ||||||
|     if opt_show_lineno: |  | ||||||
|         prefix = `lineno`.rjust(3) + ': ' |  | ||||||
|     else: |  | ||||||
|         prefix = '' |  | ||||||
|     if opt_show_filename: |  | ||||||
|         prefix = filename + ': ' + prefix |  | ||||||
|     print prefix + line |  | ||||||
|     if opt_show_where: |  | ||||||
|         start, end = prog.regs()[0] |  | ||||||
|         line = line[:start] |  | ||||||
|         if '\t' not in line: |  | ||||||
|             prefix = ' ' * (len(prefix) + start) |  | ||||||
|         else: |  | ||||||
|             prefix = ' ' * len(prefix) |  | ||||||
|             for c in line: |  | ||||||
|                 if c != '\t': c = ' ' |  | ||||||
|                 prefix = prefix + c |  | ||||||
|         if start == end: prefix = prefix + '\\' |  | ||||||
|         else: prefix = prefix + '^'*(end-start) |  | ||||||
|         print prefix |  | ||||||
|  | @ -1,15 +0,0 @@ | ||||||
| import struct, fcntl |  | ||||||
| 
 |  | ||||||
| def writelock(f): |  | ||||||
|     _lock(f, fcntl.F_WRLCK) |  | ||||||
| 
 |  | ||||||
| def readlock(f): |  | ||||||
|     _lock(f, fcntl.F_RDLCK) |  | ||||||
| 
 |  | ||||||
| def unlock(f): |  | ||||||
|     _lock(f, fcntl.F_UNLCK) |  | ||||||
| 
 |  | ||||||
| def _lock(f, op): |  | ||||||
|     dummy = fcntl.fcntl(f.fileno(), fcntl.F_SETLKW, |  | ||||||
|                         struct.pack('2h8l', op, |  | ||||||
|                                     0, 0, 0, 0, 0, 0, 0, 0, 0)) |  | ||||||
|  | @ -1,73 +0,0 @@ | ||||||
| # New dir() function |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # This should be the new dir(), except that it should still list |  | ||||||
| # the current local name space by default |  | ||||||
| 
 |  | ||||||
| def listattrs(x): |  | ||||||
|     try: |  | ||||||
|         dictkeys = x.__dict__.keys() |  | ||||||
|     except (AttributeError, TypeError): |  | ||||||
|         dictkeys = [] |  | ||||||
|     # |  | ||||||
|     try: |  | ||||||
|         methods = x.__methods__ |  | ||||||
|     except (AttributeError, TypeError): |  | ||||||
|         methods = [] |  | ||||||
|     # |  | ||||||
|     try: |  | ||||||
|         members = x.__members__ |  | ||||||
|     except (AttributeError, TypeError): |  | ||||||
|         members = [] |  | ||||||
|     # |  | ||||||
|     try: |  | ||||||
|         the_class = x.__class__ |  | ||||||
|     except (AttributeError, TypeError): |  | ||||||
|         the_class = None |  | ||||||
|     # |  | ||||||
|     try: |  | ||||||
|         bases = x.__bases__ |  | ||||||
|     except (AttributeError, TypeError): |  | ||||||
|         bases = () |  | ||||||
|     # |  | ||||||
|     total = dictkeys + methods + members |  | ||||||
|     if the_class: |  | ||||||
|         # It's a class instace; add the class's attributes |  | ||||||
|         # that are functions (methods)... |  | ||||||
|         class_attrs = listattrs(the_class) |  | ||||||
|         class_methods = [] |  | ||||||
|         for name in class_attrs: |  | ||||||
|             if is_function(getattr(the_class, name)): |  | ||||||
|                 class_methods.append(name) |  | ||||||
|         total = total + class_methods |  | ||||||
|     elif bases: |  | ||||||
|         # It's a derived class; add the base class attributes |  | ||||||
|         for base in bases: |  | ||||||
|             base_attrs = listattrs(base) |  | ||||||
|             total = total + base_attrs |  | ||||||
|     total.sort() |  | ||||||
|     return total |  | ||||||
|     i = 0 |  | ||||||
|     while i+1 < len(total): |  | ||||||
|         if total[i] == total[i+1]: |  | ||||||
|             del total[i+1] |  | ||||||
|         else: |  | ||||||
|             i = i+1 |  | ||||||
|     return total |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Helper to recognize functions |  | ||||||
| 
 |  | ||||||
| def is_function(x): |  | ||||||
|     return type(x) == type(is_function) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Approximation of builtin dir(); but note that this lists the user's |  | ||||||
| # variables by default, not the current local name space. |  | ||||||
| 
 |  | ||||||
| def dir(x = None): |  | ||||||
|     if x is not None: |  | ||||||
|         return listattrs(x) |  | ||||||
|     else: |  | ||||||
|         import __main__ |  | ||||||
|         return listattrs(__main__) |  | ||||||
|  | @ -1,433 +0,0 @@ | ||||||
| """New import scheme with package support. |  | ||||||
| 
 |  | ||||||
| Quick Reference |  | ||||||
| --------------- |  | ||||||
| 
 |  | ||||||
| - To enable package support, execute "import ni" before importing any |  | ||||||
|   packages.  Importing this module automatically installs the relevant |  | ||||||
|   import hooks. |  | ||||||
| 
 |  | ||||||
| - To create a package named spam containing sub-modules ham, bacon and |  | ||||||
|   eggs, create a directory spam somewhere on Python's module search |  | ||||||
|   path (i.e. spam's parent directory must be one of the directories in |  | ||||||
|   sys.path or $PYTHONPATH); then create files ham.py, bacon.py and |  | ||||||
|   eggs.py inside spam. |  | ||||||
| 
 |  | ||||||
| - To import module ham from package spam and use function hamneggs() |  | ||||||
|   from that module, you can either do |  | ||||||
| 
 |  | ||||||
|     import spam.ham             # *not* "import spam" !!! |  | ||||||
|     spam.ham.hamneggs() |  | ||||||
| 
 |  | ||||||
|   or |  | ||||||
| 
 |  | ||||||
|     from spam import ham |  | ||||||
|     ham.hamneggs() |  | ||||||
| 
 |  | ||||||
|   or |  | ||||||
| 
 |  | ||||||
|     from spam.ham import hamneggs |  | ||||||
|     hamneggs() |  | ||||||
| 
 |  | ||||||
| - Importing just "spam" does not do what you expect: it creates an |  | ||||||
|   empty package named spam if one does not already exist, but it does |  | ||||||
|   not import spam's submodules.  The only submodule that is guaranteed |  | ||||||
|   to be imported is spam.__init__, if it exists.  Note that |  | ||||||
|   spam.__init__ is a submodule of package spam.  It can reference to |  | ||||||
|   spam's namespace via the '__.' prefix, for instance |  | ||||||
| 
 |  | ||||||
|     __.spam_inited = 1          # Set a package-level variable |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Theory of Operation |  | ||||||
| ------------------- |  | ||||||
| 
 |  | ||||||
| A Package is a module that can contain other modules.  Packages can be |  | ||||||
| nested.  Package introduce dotted names for modules, like P.Q.M, which |  | ||||||
| could correspond to a file P/Q/M.py found somewhere on sys.path.  It |  | ||||||
| is possible to import a package itself, though this makes little sense |  | ||||||
| unless the package contains a module called __init__. |  | ||||||
| 
 |  | ||||||
| A package has two variables that control the namespace used for |  | ||||||
| packages and modules, both initialized to sensible defaults the first |  | ||||||
| time the package is referenced. |  | ||||||
| 
 |  | ||||||
| (1) A package's *module search path*, contained in the per-package |  | ||||||
| variable __path__, defines a list of *directories* where submodules or |  | ||||||
| subpackages of the package are searched.  It is initialized to the |  | ||||||
| directory containing the package.  Setting this variable to None makes |  | ||||||
| the module search path default to sys.path (this is not quite the same |  | ||||||
| as setting it to sys.path, since the latter won't track later |  | ||||||
| assignments to sys.path). |  | ||||||
| 
 |  | ||||||
| (2) A package's *import domain*, contained in the per-package variable |  | ||||||
| __domain__, defines a list of *packages* that are searched (using |  | ||||||
| their respective module search paths) to satisfy imports.  It is |  | ||||||
| initialized to the list consisting of the package itself, its parent |  | ||||||
| package, its parent's parent, and so on, ending with the root package |  | ||||||
| (the nameless package containing all top-level packages and modules, |  | ||||||
| whose module search path is None, implying sys.path). |  | ||||||
| 
 |  | ||||||
| The default domain implements a search algorithm called "expanding |  | ||||||
| search".  An alternative search algorithm called "explicit search" |  | ||||||
| fixes the import search path to contain only the root package, |  | ||||||
| requiring the modules in the package to name all imported modules by |  | ||||||
| their full name.  The convention of using '__' to refer to the current |  | ||||||
| package (both as a per-module variable and in module names) can be |  | ||||||
| used by packages using explicit search to refer to modules in the same |  | ||||||
| package; this combination is known as "explicit-relative search". |  | ||||||
| 
 |  | ||||||
| The PackageImporter and PackageLoader classes together implement the |  | ||||||
| following policies: |  | ||||||
| 
 |  | ||||||
| - There is a root package, whose name is ''.  It cannot be imported |  | ||||||
|   directly but may be referenced, e.g. by using '__' from a top-level |  | ||||||
|   module. |  | ||||||
| 
 |  | ||||||
| - In each module or package, the variable '__' contains a reference to |  | ||||||
|   the parent package; in the root package, '__' points to itself. |  | ||||||
| 
 |  | ||||||
| - In the name for imported modules (e.g. M in "import M" or "from M |  | ||||||
|   import ..."), a leading '__' refers to the current package (i.e. |  | ||||||
|   the package containing the current module); leading '__.__' and so |  | ||||||
|   on refer to the current package's parent, and so on.  The use of |  | ||||||
|   '__' elsewhere in the module name is not supported. |  | ||||||
| 
 |  | ||||||
| - Modules are searched using the "expanding search" algorithm by |  | ||||||
|   virtue of the default value for __domain__. |  | ||||||
| 
 |  | ||||||
| - If A.B.C is imported, A is searched using __domain__; then |  | ||||||
|   subpackage B is searched in A using its __path__, and so on. |  | ||||||
| 
 |  | ||||||
| - Built-in modules have priority: even if a file sys.py exists in a |  | ||||||
|   package, "import sys" imports the built-in sys module. |  | ||||||
| 
 |  | ||||||
| - The same holds for frozen modules, for better or for worse. |  | ||||||
| 
 |  | ||||||
| - Submodules and subpackages are not automatically loaded when their |  | ||||||
|   parent packages is loaded. |  | ||||||
| 
 |  | ||||||
| - The construct "from package import *" is illegal.  (It can still be |  | ||||||
|   used to import names from a module.) |  | ||||||
| 
 |  | ||||||
| - When "from package import module1, module2, ..." is used, those |  | ||||||
|     modules are explicitly loaded. |  | ||||||
| 
 |  | ||||||
| - When a package is loaded, if it has a submodule __init__, that |  | ||||||
|   module is loaded.  This is the place where required submodules can |  | ||||||
|   be loaded, the __path__ variable extended, etc.  The __init__ module |  | ||||||
|   is loaded even if the package was loaded only in order to create a |  | ||||||
|   stub for a sub-package: if "import P.Q.R" is the first reference to |  | ||||||
|   P, and P has a submodule __init__, P.__init__ is loaded before P.Q |  | ||||||
|   is even searched. |  | ||||||
| 
 |  | ||||||
| Caveats: |  | ||||||
| 
 |  | ||||||
| - It is possible to import a package that has no __init__ submodule; |  | ||||||
|   this is not particularly useful but there may be useful applications |  | ||||||
|   for it (e.g. to manipulate its search paths from the outside!). |  | ||||||
| 
 |  | ||||||
| - There are no special provisions for os.chdir().  If you plan to use |  | ||||||
|   os.chdir() before you have imported all your modules, it is better |  | ||||||
|   not to have relative pathnames in sys.path.  (This could actually be |  | ||||||
|   fixed by changing the implementation of path_join() in the hook to |  | ||||||
|   absolutize paths.) |  | ||||||
| 
 |  | ||||||
| - Packages and modules are introduced in sys.modules as soon as their |  | ||||||
|   loading is started.  When the loading is terminated by an exception, |  | ||||||
|   the sys.modules entries remain around. |  | ||||||
| 
 |  | ||||||
| - There are no special measures to support mutually recursive modules, |  | ||||||
|   but it will work under the same conditions where it works in the |  | ||||||
|   flat module space system. |  | ||||||
| 
 |  | ||||||
| - Sometimes dummy entries (whose value is None) are entered in |  | ||||||
|   sys.modules, to indicate that a particular module does not exist -- |  | ||||||
|   this is done to speed up the expanding search algorithm when a |  | ||||||
|   module residing at a higher level is repeatedly imported (Python |  | ||||||
|   promises that importing a previously imported module is cheap!) |  | ||||||
| 
 |  | ||||||
| - Although dynamically loaded extensions are allowed inside packages, |  | ||||||
|   the current implementation (hardcoded in the interpreter) of their |  | ||||||
|   initialization may cause problems if an extension invokes the |  | ||||||
|   interpreter during its initialization. |  | ||||||
| 
 |  | ||||||
| - reload() may find another version of the module only if it occurs on |  | ||||||
|   the package search path.  Thus, it keeps the connection to the |  | ||||||
|   package to which the module belongs, but may find a different file. |  | ||||||
| 
 |  | ||||||
| XXX Need to have an explicit name for '', e.g. '__root__'. |  | ||||||
| 
 |  | ||||||
| """ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| import imp |  | ||||||
| import sys |  | ||||||
| import __builtin__ |  | ||||||
| 
 |  | ||||||
| import ihooks |  | ||||||
| from ihooks import ModuleLoader, ModuleImporter |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class PackageLoader(ModuleLoader): |  | ||||||
| 
 |  | ||||||
|     """A subclass of ModuleLoader with package support. |  | ||||||
| 
 |  | ||||||
|     find_module_in_dir() will succeed if there's a subdirectory with |  | ||||||
|     the given name; load_module() will create a stub for a package and |  | ||||||
|     load its __init__ module if it exists. |  | ||||||
| 
 |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     def find_module_in_dir(self, name, dir): |  | ||||||
|         if dir is not None: |  | ||||||
|             dirname = self.hooks.path_join(dir, name) |  | ||||||
|             if self.hooks.path_isdir(dirname): |  | ||||||
|                 return None, dirname, ('', '', 'PACKAGE') |  | ||||||
|         return ModuleLoader.find_module_in_dir(self, name, dir) |  | ||||||
| 
 |  | ||||||
|     def load_module(self, name, stuff): |  | ||||||
|         file, filename, info = stuff |  | ||||||
|         suff, mode, type = info |  | ||||||
|         if type == 'PACKAGE': |  | ||||||
|             return self.load_package(name, stuff) |  | ||||||
|         if sys.modules.has_key(name): |  | ||||||
|             m = sys.modules[name] |  | ||||||
|         else: |  | ||||||
|             sys.modules[name] = m = imp.new_module(name) |  | ||||||
|         self.set_parent(m) |  | ||||||
|         if type == imp.C_EXTENSION and '.' in name: |  | ||||||
|             return self.load_dynamic(name, stuff) |  | ||||||
|         else: |  | ||||||
|             return ModuleLoader.load_module(self, name, stuff) |  | ||||||
| 
 |  | ||||||
|     def load_dynamic(self, name, stuff): |  | ||||||
|         file, filename, (suff, mode, type) = stuff |  | ||||||
|         # Hack around restriction in imp.load_dynamic() |  | ||||||
|         i = name.rfind('.') |  | ||||||
|         tail = name[i+1:] |  | ||||||
|         if sys.modules.has_key(tail): |  | ||||||
|             save = sys.modules[tail] |  | ||||||
|         else: |  | ||||||
|             save = None |  | ||||||
|         sys.modules[tail] = imp.new_module(name) |  | ||||||
|         try: |  | ||||||
|             m = imp.load_dynamic(tail, filename, file) |  | ||||||
|         finally: |  | ||||||
|             if save: |  | ||||||
|                 sys.modules[tail] = save |  | ||||||
|             else: |  | ||||||
|                 del sys.modules[tail] |  | ||||||
|         sys.modules[name] = m |  | ||||||
|         return m |  | ||||||
| 
 |  | ||||||
|     def load_package(self, name, stuff): |  | ||||||
|         file, filename, info = stuff |  | ||||||
|         if sys.modules.has_key(name): |  | ||||||
|             package = sys.modules[name] |  | ||||||
|         else: |  | ||||||
|             sys.modules[name] = package = imp.new_module(name) |  | ||||||
|         package.__path__ = [filename] |  | ||||||
|         self.init_package(package) |  | ||||||
|         return package |  | ||||||
| 
 |  | ||||||
|     def init_package(self, package): |  | ||||||
|         self.set_parent(package) |  | ||||||
|         self.set_domain(package) |  | ||||||
|         self.call_init_module(package) |  | ||||||
| 
 |  | ||||||
|     def set_parent(self, m): |  | ||||||
|         name = m.__name__ |  | ||||||
|         if '.' in name: |  | ||||||
|             name = name[:name.rfind('.')] |  | ||||||
|         else: |  | ||||||
|             name = '' |  | ||||||
|         m.__ = sys.modules[name] |  | ||||||
| 
 |  | ||||||
|     def set_domain(self, package): |  | ||||||
|         name = package.__name__ |  | ||||||
|         package.__domain__ = domain = [name] |  | ||||||
|         while '.' in name: |  | ||||||
|             name = name[:name.rfind('.')] |  | ||||||
|             domain.append(name) |  | ||||||
|         if name: |  | ||||||
|             domain.append('') |  | ||||||
| 
 |  | ||||||
|     def call_init_module(self, package): |  | ||||||
|         stuff = self.find_module('__init__', package.__path__) |  | ||||||
|         if stuff: |  | ||||||
|             m = self.load_module(package.__name__ + '.__init__', stuff) |  | ||||||
|             package.__init__ = m |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class PackageImporter(ModuleImporter): |  | ||||||
| 
 |  | ||||||
|     """Importer that understands packages and '__'.""" |  | ||||||
| 
 |  | ||||||
|     def __init__(self, loader = None, verbose = 0): |  | ||||||
|         ModuleImporter.__init__(self, |  | ||||||
|         loader or PackageLoader(None, verbose), verbose) |  | ||||||
| 
 |  | ||||||
|     def import_module(self, name, globals={}, locals={}, fromlist=[]): |  | ||||||
|         if globals.has_key('__'): |  | ||||||
|             package = globals['__'] |  | ||||||
|         else: |  | ||||||
|             # No calling context, assume in root package |  | ||||||
|             package = sys.modules[''] |  | ||||||
|         if name[:3] in ('__.', '__'): |  | ||||||
|             p = package |  | ||||||
|             name = name[3:] |  | ||||||
|             while name[:3] in ('__.', '__'): |  | ||||||
|                 p = p.__ |  | ||||||
|                 name = name[3:] |  | ||||||
|             if not name: |  | ||||||
|                 return self.finish(package, p, '', fromlist) |  | ||||||
|             if '.' in name: |  | ||||||
|                 i = name.find('.') |  | ||||||
|                 name, tail = name[:i], name[i:] |  | ||||||
|             else: |  | ||||||
|                 tail = '' |  | ||||||
|             mname = p.__name__ and p.__name__+'.'+name or name |  | ||||||
|             m = self.get1(mname) |  | ||||||
|             return self.finish(package, m, tail, fromlist) |  | ||||||
|         if '.' in name: |  | ||||||
|             i = name.find('.') |  | ||||||
|             name, tail = name[:i], name[i:] |  | ||||||
|         else: |  | ||||||
|             tail = '' |  | ||||||
|         for pname in package.__domain__: |  | ||||||
|             mname = pname and pname+'.'+name or name |  | ||||||
|             m = self.get0(mname) |  | ||||||
|             if m: break |  | ||||||
|         else: |  | ||||||
|             raise ImportError, "No such module %s" % name |  | ||||||
|         return self.finish(m, m, tail, fromlist) |  | ||||||
| 
 |  | ||||||
|     def finish(self, module, m, tail, fromlist): |  | ||||||
|         # Got ....A; now get ....A.B.C.D |  | ||||||
|         yname = m.__name__ |  | ||||||
|         if tail and sys.modules.has_key(yname + tail): # Fast path |  | ||||||
|             yname, tail = yname + tail, '' |  | ||||||
|             m = self.get1(yname) |  | ||||||
|         while tail: |  | ||||||
|             i = tail.find('.', 1) |  | ||||||
|             if i > 0: |  | ||||||
|                 head, tail = tail[:i], tail[i:] |  | ||||||
|             else: |  | ||||||
|                 head, tail = tail, '' |  | ||||||
|             yname = yname + head |  | ||||||
|             m = self.get1(yname) |  | ||||||
| 
 |  | ||||||
|         # Got ....A.B.C.D; now finalize things depending on fromlist |  | ||||||
|         if not fromlist: |  | ||||||
|             return module |  | ||||||
|         if '__' in fromlist: |  | ||||||
|             raise ImportError, "Can't import __ from anywhere" |  | ||||||
|         if not hasattr(m, '__path__'): return m |  | ||||||
|         if '*' in fromlist: |  | ||||||
|             raise ImportError, "Can't import * from a package" |  | ||||||
|         for f in fromlist: |  | ||||||
|             if hasattr(m, f): continue |  | ||||||
|             fname = yname + '.' + f |  | ||||||
|             self.get1(fname) |  | ||||||
|         return m |  | ||||||
| 
 |  | ||||||
|     def get1(self, name): |  | ||||||
|         m = self.get(name) |  | ||||||
|         if not m: |  | ||||||
|             raise ImportError, "No module named %s" % name |  | ||||||
|         return m |  | ||||||
| 
 |  | ||||||
|     def get0(self, name): |  | ||||||
|         m = self.get(name) |  | ||||||
|         if not m: |  | ||||||
|             sys.modules[name] = None |  | ||||||
|         return m |  | ||||||
| 
 |  | ||||||
|     def get(self, name): |  | ||||||
|         # Internal routine to get or load a module when its parent exists |  | ||||||
|         if sys.modules.has_key(name): |  | ||||||
|             return sys.modules[name] |  | ||||||
|         if '.' in name: |  | ||||||
|             i = name.rfind('.') |  | ||||||
|             head, tail = name[:i], name[i+1:] |  | ||||||
|         else: |  | ||||||
|             head, tail = '', name |  | ||||||
|         path = sys.modules[head].__path__ |  | ||||||
|         stuff = self.loader.find_module(tail, path) |  | ||||||
|         if not stuff: |  | ||||||
|             return None |  | ||||||
|         sys.modules[name] = m = self.loader.load_module(name, stuff) |  | ||||||
|         if head: |  | ||||||
|             setattr(sys.modules[head], tail, m) |  | ||||||
|         return m |  | ||||||
| 
 |  | ||||||
|     def reload(self, module): |  | ||||||
|         name = module.__name__ |  | ||||||
|         if '.' in name: |  | ||||||
|             i = name.rfind('.') |  | ||||||
|             head, tail = name[:i], name[i+1:] |  | ||||||
|             path = sys.modules[head].__path__ |  | ||||||
|         else: |  | ||||||
|             tail = name |  | ||||||
|             path = sys.modules[''].__path__ |  | ||||||
|         stuff = self.loader.find_module(tail, path) |  | ||||||
|         if not stuff: |  | ||||||
|             raise ImportError, "No module named %s" % name |  | ||||||
|         return self.loader.load_module(name, stuff) |  | ||||||
| 
 |  | ||||||
|     def unload(self, module): |  | ||||||
|         if hasattr(module, '__path__'): |  | ||||||
|             raise ImportError, "don't know how to unload packages yet" |  | ||||||
|         PackageImporter.unload(self, module) |  | ||||||
| 
 |  | ||||||
|     def install(self): |  | ||||||
|         if not sys.modules.has_key(''): |  | ||||||
|             sys.modules[''] = package = imp.new_module('') |  | ||||||
|             package.__path__ = None |  | ||||||
|             self.loader.init_package(package) |  | ||||||
|             for m in sys.modules.values(): |  | ||||||
|                 if not m: continue |  | ||||||
|                 if not hasattr(m, '__'): |  | ||||||
|                     self.loader.set_parent(m) |  | ||||||
|         ModuleImporter.install(self) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def install(v = 0): |  | ||||||
|     ihooks.install(PackageImporter(None, v)) |  | ||||||
| 
 |  | ||||||
| def uninstall(): |  | ||||||
|     ihooks.uninstall() |  | ||||||
| 
 |  | ||||||
| def ni(v = 0): |  | ||||||
|     install(v) |  | ||||||
| 
 |  | ||||||
| def no(): |  | ||||||
|     uninstall() |  | ||||||
| 
 |  | ||||||
| def test(): |  | ||||||
|     import pdb |  | ||||||
|     try: |  | ||||||
|         testproper() |  | ||||||
|     except: |  | ||||||
|         sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info() |  | ||||||
|         print |  | ||||||
|         print sys.last_type, ':', sys.last_value |  | ||||||
|         print |  | ||||||
|         pdb.pm() |  | ||||||
| 
 |  | ||||||
| def testproper(): |  | ||||||
|     install(1) |  | ||||||
|     try: |  | ||||||
|         import mactest |  | ||||||
|         print dir(mactest) |  | ||||||
|         raw_input('OK?') |  | ||||||
|     finally: |  | ||||||
|         uninstall() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| if __name__ == '__main__': |  | ||||||
|     test() |  | ||||||
| else: |  | ||||||
|     install() |  | ||||||
|  | @ -1,111 +0,0 @@ | ||||||
| # Module 'packmail' -- create a self-unpacking shell archive. |  | ||||||
| 
 |  | ||||||
| # This module works on UNIX and on the Mac; the archives can unpack |  | ||||||
| # themselves only on UNIX. |  | ||||||
| 
 |  | ||||||
| import os |  | ||||||
| from stat import ST_MTIME |  | ||||||
| 
 |  | ||||||
| # Print help |  | ||||||
| def help(): |  | ||||||
|     print 'All fns have a file open for writing as first parameter' |  | ||||||
|     print 'pack(f, fullname, name): pack fullname as name' |  | ||||||
|     print 'packsome(f, directory, namelist): selected files from directory' |  | ||||||
|     print 'packall(f, directory): pack all files from directory' |  | ||||||
|     print 'packnotolder(f, directory, name): pack all files from directory' |  | ||||||
|     print '                        that are not older than a file there' |  | ||||||
|     print 'packtree(f, directory): pack entire directory tree' |  | ||||||
| 
 |  | ||||||
| # Pack one file |  | ||||||
| def pack(outfp, file, name): |  | ||||||
|     fp = open(file, 'r') |  | ||||||
|     outfp.write('echo ' + name + '\n') |  | ||||||
|     outfp.write('sed "s/^X//" >"' + name + '" <<"!"\n') |  | ||||||
|     while 1: |  | ||||||
|         line = fp.readline() |  | ||||||
|         if not line: break |  | ||||||
|         if line[-1:] != '\n': |  | ||||||
|             line = line + '\n' |  | ||||||
|         outfp.write('X' + line) |  | ||||||
|     outfp.write('!\n') |  | ||||||
|     fp.close() |  | ||||||
| 
 |  | ||||||
| # Pack some files from a directory |  | ||||||
| def packsome(outfp, dirname, names): |  | ||||||
|     for name in names: |  | ||||||
|         print name |  | ||||||
|         file = os.path.join(dirname, name) |  | ||||||
|         pack(outfp, file, name) |  | ||||||
| 
 |  | ||||||
| # Pack all files from a directory |  | ||||||
| def packall(outfp, dirname): |  | ||||||
|     names = os.listdir(dirname) |  | ||||||
|     try: |  | ||||||
|         names.remove('.') |  | ||||||
|     except: |  | ||||||
|         pass |  | ||||||
|     try: |  | ||||||
|         names.remove('..') |  | ||||||
|     except: |  | ||||||
|         pass |  | ||||||
|     names.sort() |  | ||||||
|     packsome(outfp, dirname, names) |  | ||||||
| 
 |  | ||||||
| # Pack all files from a directory that are not older than a give one |  | ||||||
| def packnotolder(outfp, dirname, oldest): |  | ||||||
|     names = os.listdir(dirname) |  | ||||||
|     try: |  | ||||||
|         names.remove('.') |  | ||||||
|     except: |  | ||||||
|         pass |  | ||||||
|     try: |  | ||||||
|         names.remove('..') |  | ||||||
|     except: |  | ||||||
|         pass |  | ||||||
|     oldest = os.path.join(dirname, oldest) |  | ||||||
|     st = os.stat(oldest) |  | ||||||
|     mtime = st[ST_MTIME] |  | ||||||
|     todo = [] |  | ||||||
|     for name in names: |  | ||||||
|         print name, '...', |  | ||||||
|         st = os.stat(os.path.join(dirname, name)) |  | ||||||
|         if st[ST_MTIME] >= mtime: |  | ||||||
|             print 'Yes.' |  | ||||||
|             todo.append(name) |  | ||||||
|         else: |  | ||||||
|             print 'No.' |  | ||||||
|     todo.sort() |  | ||||||
|     packsome(outfp, dirname, todo) |  | ||||||
| 
 |  | ||||||
| # Pack a whole tree (no exceptions) |  | ||||||
| def packtree(outfp, dirname): |  | ||||||
|     print 'packtree', dirname |  | ||||||
|     outfp.write('mkdir ' + unixfix(dirname) + '\n') |  | ||||||
|     names = os.listdir(dirname) |  | ||||||
|     try: |  | ||||||
|         names.remove('.') |  | ||||||
|     except: |  | ||||||
|         pass |  | ||||||
|     try: |  | ||||||
|         names.remove('..') |  | ||||||
|     except: |  | ||||||
|         pass |  | ||||||
|     subdirs = [] |  | ||||||
|     for name in names: |  | ||||||
|         fullname = os.path.join(dirname, name) |  | ||||||
|         if os.path.isdir(fullname): |  | ||||||
|             subdirs.append(fullname) |  | ||||||
|         else: |  | ||||||
|             print 'pack', fullname |  | ||||||
|             pack(outfp, fullname, unixfix(fullname)) |  | ||||||
|     for subdirname in subdirs: |  | ||||||
|         packtree(outfp, subdirname) |  | ||||||
| 
 |  | ||||||
| def unixfix(name): |  | ||||||
|     comps = name.split(os.sep) |  | ||||||
|     res = '' |  | ||||||
|     for comp in comps: |  | ||||||
|         if comp: |  | ||||||
|             if res: res = res + '/' |  | ||||||
|             res = res + comp |  | ||||||
|     return res |  | ||||||
|  | @ -1,52 +0,0 @@ | ||||||
| # module 'poly' -- Polynomials |  | ||||||
| 
 |  | ||||||
| # A polynomial is represented by a list of coefficients, e.g., |  | ||||||
| # [1, 10, 5] represents 1*x**0 + 10*x**1 + 5*x**2 (or 1 + 10x + 5x**2). |  | ||||||
| # There is no way to suppress internal zeros; trailing zeros are |  | ||||||
| # taken out by normalize(). |  | ||||||
| 
 |  | ||||||
| def normalize(p): # Strip unnecessary zero coefficients |  | ||||||
|     n = len(p) |  | ||||||
|     while n: |  | ||||||
|         if p[n-1]: return p[:n] |  | ||||||
|         n = n-1 |  | ||||||
|     return [] |  | ||||||
| 
 |  | ||||||
| def plus(a, b): |  | ||||||
|     if len(a) < len(b): a, b = b, a # make sure a is the longest |  | ||||||
|     res = a[:] # make a copy |  | ||||||
|     for i in range(len(b)): |  | ||||||
|         res[i] = res[i] + b[i] |  | ||||||
|     return normalize(res) |  | ||||||
| 
 |  | ||||||
| def minus(a, b): |  | ||||||
|     neg_b = map(lambda x: -x, b[:]) |  | ||||||
|     return plus(a, neg_b) |  | ||||||
| 
 |  | ||||||
| def one(power, coeff): # Representation of coeff * x**power |  | ||||||
|     res = [] |  | ||||||
|     for i in range(power): res.append(0) |  | ||||||
|     return res + [coeff] |  | ||||||
| 
 |  | ||||||
| def times(a, b): |  | ||||||
|     res = [] |  | ||||||
|     for i in range(len(a)): |  | ||||||
|         for j in range(len(b)): |  | ||||||
|             res = plus(res, one(i+j, a[i]*b[j])) |  | ||||||
|     return res |  | ||||||
| 
 |  | ||||||
| def power(a, n): # Raise polynomial a to the positive integral power n |  | ||||||
|     if n == 0: return [1] |  | ||||||
|     if n == 1: return a |  | ||||||
|     if n/2*2 == n: |  | ||||||
|         b = power(a, n/2) |  | ||||||
|         return times(b, b) |  | ||||||
|     return times(power(a, n-1), a) |  | ||||||
| 
 |  | ||||||
| def der(a): # First derivative |  | ||||||
|     res = a[1:] |  | ||||||
|     for i in range(len(res)): |  | ||||||
|         res[i] = res[i] * (i+1) |  | ||||||
|     return res |  | ||||||
| 
 |  | ||||||
| # Computing a primitive function would require rational arithmetic... |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| # Module 'rand' |  | ||||||
| # Don't use unless you want compatibility with C's rand()! |  | ||||||
| 
 |  | ||||||
| import whrandom |  | ||||||
| 
 |  | ||||||
| def srand(seed): |  | ||||||
|     whrandom.seed(seed%256, seed/256%256, seed/65536%256) |  | ||||||
| 
 |  | ||||||
| def rand(): |  | ||||||
|     return int(whrandom.random() * 32768.0) % 32768 |  | ||||||
| 
 |  | ||||||
| def choice(seq): |  | ||||||
|     return seq[rand() % len(seq)] |  | ||||||
|  | @ -1,82 +0,0 @@ | ||||||
| """Maintain a cache of stat() information on files. |  | ||||||
| 
 |  | ||||||
| There are functions to reset the cache or to selectively remove items. |  | ||||||
| """ |  | ||||||
| 
 |  | ||||||
| import warnings |  | ||||||
| warnings.warn("The statcache module is obsolete.  Use os.stat() instead.", |  | ||||||
|               DeprecationWarning) |  | ||||||
| del warnings |  | ||||||
| 
 |  | ||||||
| import os as _os |  | ||||||
| from stat import * |  | ||||||
| 
 |  | ||||||
| __all__ = ["stat","reset","forget","forget_prefix","forget_dir", |  | ||||||
|            "forget_except_prefix","isdir"] |  | ||||||
| 
 |  | ||||||
| # The cache.  Keys are pathnames, values are os.stat outcomes. |  | ||||||
| # Remember that multiple threads may be calling this!  So, e.g., that |  | ||||||
| # path in cache returns 1 doesn't mean the cache will still contain |  | ||||||
| # path on the next line.  Code defensively. |  | ||||||
| 
 |  | ||||||
| cache = {} |  | ||||||
| 
 |  | ||||||
| def stat(path): |  | ||||||
|     """Stat a file, possibly out of the cache.""" |  | ||||||
|     ret = cache.get(path, None) |  | ||||||
|     if ret is None: |  | ||||||
|         cache[path] = ret = _os.stat(path) |  | ||||||
|     return ret |  | ||||||
| 
 |  | ||||||
| def reset(): |  | ||||||
|     """Clear the cache.""" |  | ||||||
|     cache.clear() |  | ||||||
| 
 |  | ||||||
| # For thread saftey, always use forget() internally too. |  | ||||||
| def forget(path): |  | ||||||
|     """Remove a given item from the cache, if it exists.""" |  | ||||||
|     try: |  | ||||||
|         del cache[path] |  | ||||||
|     except KeyError: |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
| def forget_prefix(prefix): |  | ||||||
|     """Remove all pathnames with a given prefix.""" |  | ||||||
|     for path in cache.keys(): |  | ||||||
|         if path.startswith(prefix): |  | ||||||
|             forget(path) |  | ||||||
| 
 |  | ||||||
| def forget_dir(prefix): |  | ||||||
|     """Forget a directory and all entries except for entries in subdirs.""" |  | ||||||
| 
 |  | ||||||
|     # Remove trailing separator, if any.  This is tricky to do in a |  | ||||||
|     # x-platform way.  For example, Windows accepts both / and \ as |  | ||||||
|     # separators, and if there's nothing *but* a separator we want to |  | ||||||
|     # preserve that this is the root.  Only os.path has the platform |  | ||||||
|     # knowledge we need. |  | ||||||
|     from os.path import split, join |  | ||||||
|     prefix = split(join(prefix, "xxx"))[0] |  | ||||||
|     forget(prefix) |  | ||||||
|     for path in cache.keys(): |  | ||||||
|         # First check that the path at least starts with the prefix, so |  | ||||||
|         # that when it doesn't we can avoid paying for split(). |  | ||||||
|         if path.startswith(prefix) and split(path)[0] == prefix: |  | ||||||
|             forget(path) |  | ||||||
| 
 |  | ||||||
| def forget_except_prefix(prefix): |  | ||||||
|     """Remove all pathnames except with a given prefix. |  | ||||||
| 
 |  | ||||||
|     Normally used with prefix = '/' after a chdir(). |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     for path in cache.keys(): |  | ||||||
|         if not path.startswith(prefix): |  | ||||||
|             forget(path) |  | ||||||
| 
 |  | ||||||
| def isdir(path): |  | ||||||
|     """Return True if directory, else False.""" |  | ||||||
|     try: |  | ||||||
|         st = stat(path) |  | ||||||
|     except _os.error: |  | ||||||
|         return False |  | ||||||
|     return S_ISDIR(st.st_mode) |  | ||||||
|  | @ -1,177 +0,0 @@ | ||||||
| # Print tracebacks, with a dump of local variables. |  | ||||||
| # Also an interactive stack trace browser. |  | ||||||
| # Note -- this module is obsolete -- use pdb.pm() instead. |  | ||||||
| 
 |  | ||||||
| import sys |  | ||||||
| import os |  | ||||||
| from stat import * |  | ||||||
| import linecache |  | ||||||
| 
 |  | ||||||
| def br(): browser(sys.last_traceback) |  | ||||||
| 
 |  | ||||||
| def tb(): printtb(sys.last_traceback) |  | ||||||
| 
 |  | ||||||
| def browser(tb): |  | ||||||
|     if not tb: |  | ||||||
|         print 'No traceback.' |  | ||||||
|         return |  | ||||||
|     tblist = [] |  | ||||||
|     while tb: |  | ||||||
|         tblist.append(tb) |  | ||||||
|         tb = tb.tb_next |  | ||||||
|     ptr = len(tblist)-1 |  | ||||||
|     tb = tblist[ptr] |  | ||||||
|     while 1: |  | ||||||
|         if tb != tblist[ptr]: |  | ||||||
|             tb = tblist[ptr] |  | ||||||
|             print `ptr` + ':', |  | ||||||
|             printtbheader(tb) |  | ||||||
|         try: |  | ||||||
|             line = raw_input('TB: ') |  | ||||||
|         except KeyboardInterrupt: |  | ||||||
|             print '\n[Interrupted]' |  | ||||||
|             break |  | ||||||
|         except EOFError: |  | ||||||
|             print '\n[EOF]' |  | ||||||
|             break |  | ||||||
|         cmd = line.strip() |  | ||||||
|         if cmd: |  | ||||||
|             if cmd == 'quit': |  | ||||||
|                 break |  | ||||||
|             elif cmd == 'list': |  | ||||||
|                 browserlist(tb) |  | ||||||
|             elif cmd == 'up': |  | ||||||
|                 if ptr-1 >= 0: ptr = ptr-1 |  | ||||||
|                 else: print 'Bottom of stack.' |  | ||||||
|             elif cmd == 'down': |  | ||||||
|                 if ptr+1 < len(tblist): ptr = ptr+1 |  | ||||||
|                 else: print 'Top of stack.' |  | ||||||
|             elif cmd == 'locals': |  | ||||||
|                 printsymbols(tb.tb_frame.f_locals) |  | ||||||
|             elif cmd == 'globals': |  | ||||||
|                 printsymbols(tb.tb_frame.f_globals) |  | ||||||
|             elif cmd in ('?', 'help'): |  | ||||||
|                 browserhelp() |  | ||||||
|             else: |  | ||||||
|                 browserexec(tb, cmd) |  | ||||||
| 
 |  | ||||||
| def browserlist(tb): |  | ||||||
|     filename = tb.tb_frame.f_code.co_filename |  | ||||||
|     lineno = tb.tb_lineno |  | ||||||
|     last = lineno |  | ||||||
|     first = max(1, last-10) |  | ||||||
|     for i in range(first, last+1): |  | ||||||
|         if i == lineno: prefix = '***' + `i`.rjust(4) + ':' |  | ||||||
|         else: prefix = `i`.rjust(7) + ':' |  | ||||||
|         line = linecache.getline(filename, i) |  | ||||||
|         if line[-1:] == '\n': line = line[:-1] |  | ||||||
|         print prefix + line |  | ||||||
| 
 |  | ||||||
| def browserexec(tb, cmd): |  | ||||||
|     locals = tb.tb_frame.f_locals |  | ||||||
|     globals = tb.tb_frame.f_globals |  | ||||||
|     try: |  | ||||||
|         exec cmd+'\n' in globals, locals |  | ||||||
|     except: |  | ||||||
|         t, v = sys.exc_info()[:2] |  | ||||||
|         print '*** Exception:', |  | ||||||
|         if type(t) is type(''): |  | ||||||
|             print t, |  | ||||||
|         else: |  | ||||||
|             print t.__name__, |  | ||||||
|         if v is not None: |  | ||||||
|             print ':', v, |  | ||||||
|         print |  | ||||||
|         print 'Type help to get help.' |  | ||||||
| 
 |  | ||||||
| def browserhelp(): |  | ||||||
|     print |  | ||||||
|     print '    This is the traceback browser.  Commands are:' |  | ||||||
|     print '        up      : move one level up in the call stack' |  | ||||||
|     print '        down    : move one level down in the call stack' |  | ||||||
|     print '        locals  : print all local variables at this level' |  | ||||||
|     print '        globals : print all global variables at this level' |  | ||||||
|     print '        list    : list source code around the failure' |  | ||||||
|     print '        help    : print help (what you are reading now)' |  | ||||||
|     print '        quit    : back to command interpreter' |  | ||||||
|     print '    Typing any other 1-line statement will execute it' |  | ||||||
|     print '    using the current level\'s symbol tables' |  | ||||||
|     print |  | ||||||
| 
 |  | ||||||
| def printtb(tb): |  | ||||||
|     while tb: |  | ||||||
|         print1tb(tb) |  | ||||||
|         tb = tb.tb_next |  | ||||||
| 
 |  | ||||||
| def print1tb(tb): |  | ||||||
|     printtbheader(tb) |  | ||||||
|     if tb.tb_frame.f_locals is not tb.tb_frame.f_globals: |  | ||||||
|         printsymbols(tb.tb_frame.f_locals) |  | ||||||
| 
 |  | ||||||
| def printtbheader(tb): |  | ||||||
|     filename = tb.tb_frame.f_code.co_filename |  | ||||||
|     lineno = tb.tb_lineno |  | ||||||
|     info = '"' + filename + '"(' + `lineno` + ')' |  | ||||||
|     line = linecache.getline(filename, lineno) |  | ||||||
|     if line: |  | ||||||
|         info = info + ': ' + line.strip() |  | ||||||
|     print info |  | ||||||
| 
 |  | ||||||
| def printsymbols(d): |  | ||||||
|     keys = d.keys() |  | ||||||
|     keys.sort() |  | ||||||
|     for name in keys: |  | ||||||
|         print '  ' + name.ljust(12) + ':', |  | ||||||
|         printobject(d[name], 4) |  | ||||||
|         print |  | ||||||
| 
 |  | ||||||
| def printobject(v, maxlevel): |  | ||||||
|     if v is None: |  | ||||||
|         print 'None', |  | ||||||
|     elif type(v) in (type(0), type(0.0)): |  | ||||||
|         print v, |  | ||||||
|     elif type(v) is type(''): |  | ||||||
|         if len(v) > 20: |  | ||||||
|             print `v[:17] + '...'`, |  | ||||||
|         else: |  | ||||||
|             print `v`, |  | ||||||
|     elif type(v) is type(()): |  | ||||||
|         print '(', |  | ||||||
|         printlist(v, maxlevel) |  | ||||||
|         print ')', |  | ||||||
|     elif type(v) is type([]): |  | ||||||
|         print '[', |  | ||||||
|         printlist(v, maxlevel) |  | ||||||
|         print ']', |  | ||||||
|     elif type(v) is type({}): |  | ||||||
|         print '{', |  | ||||||
|         printdict(v, maxlevel) |  | ||||||
|         print '}', |  | ||||||
|     else: |  | ||||||
|         print v, |  | ||||||
| 
 |  | ||||||
| def printlist(v, maxlevel): |  | ||||||
|     n = len(v) |  | ||||||
|     if n == 0: return |  | ||||||
|     if maxlevel <= 0: |  | ||||||
|         print '...', |  | ||||||
|         return |  | ||||||
|     for i in range(min(6, n)): |  | ||||||
|         printobject(v[i], maxlevel-1) |  | ||||||
|         if i+1 < n: print ',', |  | ||||||
|     if n > 6: print '...', |  | ||||||
| 
 |  | ||||||
| def printdict(v, maxlevel): |  | ||||||
|     keys = v.keys() |  | ||||||
|     n = len(keys) |  | ||||||
|     if n == 0: return |  | ||||||
|     if maxlevel <= 0: |  | ||||||
|         print '...', |  | ||||||
|         return |  | ||||||
|     keys.sort() |  | ||||||
|     for i in range(min(6, n)): |  | ||||||
|         key = keys[i] |  | ||||||
|         print `key` + ':', |  | ||||||
|         printobject(v[key], maxlevel-1) |  | ||||||
|         if i+1 < n: print ',', |  | ||||||
|     if n > 6: print '...', |  | ||||||
|  | @ -1,98 +0,0 @@ | ||||||
| """Parse a timezone specification.""" |  | ||||||
| 
 |  | ||||||
| # XXX Unfinished. |  | ||||||
| # XXX Only the typical form "XXXhhYYY;ddd/hh,ddd/hh" is currently supported. |  | ||||||
| 
 |  | ||||||
| import warnings |  | ||||||
| warnings.warn( |  | ||||||
|     "The tzparse module is obsolete and will disappear in the future", |  | ||||||
|     DeprecationWarning) |  | ||||||
| 
 |  | ||||||
| tzpat = ('^([A-Z][A-Z][A-Z])([-+]?[0-9]+)([A-Z][A-Z][A-Z]);' |  | ||||||
|           '([0-9]+)/([0-9]+),([0-9]+)/([0-9]+)$') |  | ||||||
| 
 |  | ||||||
| tzprog = None |  | ||||||
| 
 |  | ||||||
| def tzparse(tzstr): |  | ||||||
|     """Given a timezone spec, return a tuple of information |  | ||||||
|     (tzname, delta, dstname, daystart, hourstart, dayend, hourend), |  | ||||||
|     where 'tzname' is the name of the timezone, 'delta' is the offset |  | ||||||
|     in hours from GMT, 'dstname' is the name of the daylight-saving |  | ||||||
|     timezone, and 'daystart'/'hourstart' and 'dayend'/'hourend' |  | ||||||
|     specify the starting and ending points for daylight saving time.""" |  | ||||||
|     global tzprog |  | ||||||
|     if tzprog is None: |  | ||||||
|         import re |  | ||||||
|         tzprog = re.compile(tzpat) |  | ||||||
|     match = tzprog.match(tzstr) |  | ||||||
|     if not match: |  | ||||||
|         raise ValueError, 'not the TZ syntax I understand' |  | ||||||
|     subs = [] |  | ||||||
|     for i in range(1, 8): |  | ||||||
|         subs.append(match.group(i)) |  | ||||||
|     for i in (1, 3, 4, 5, 6): |  | ||||||
|         subs[i] = eval(subs[i]) |  | ||||||
|     [tzname, delta, dstname, daystart, hourstart, dayend, hourend] = subs |  | ||||||
|     return (tzname, delta, dstname, daystart, hourstart, dayend, hourend) |  | ||||||
| 
 |  | ||||||
| def tzlocaltime(secs, params): |  | ||||||
|     """Given a Unix time in seconds and a tuple of information about |  | ||||||
|     a timezone as returned by tzparse(), return the local time in the |  | ||||||
|     form (year, month, day, hour, min, sec, yday, wday, tzname).""" |  | ||||||
|     import time |  | ||||||
|     (tzname, delta, dstname, daystart, hourstart, dayend, hourend) = params |  | ||||||
|     year, month, days, hours, mins, secs, yday, wday, isdst = \ |  | ||||||
|             time.gmtime(secs - delta*3600) |  | ||||||
|     if (daystart, hourstart) <= (yday+1, hours) < (dayend, hourend): |  | ||||||
|         tzname = dstname |  | ||||||
|         hours = hours + 1 |  | ||||||
|     return year, month, days, hours, mins, secs, yday, wday, tzname |  | ||||||
| 
 |  | ||||||
| def tzset(): |  | ||||||
|     """Determine the current timezone from the "TZ" environment variable.""" |  | ||||||
|     global tzparams, timezone, altzone, daylight, tzname |  | ||||||
|     import os |  | ||||||
|     tzstr = os.environ['TZ'] |  | ||||||
|     tzparams = tzparse(tzstr) |  | ||||||
|     timezone = tzparams[1] * 3600 |  | ||||||
|     altzone = timezone - 3600 |  | ||||||
|     daylight = 1 |  | ||||||
|     tzname = tzparams[0], tzparams[2] |  | ||||||
| 
 |  | ||||||
| def isdst(secs): |  | ||||||
|     """Return true if daylight-saving time is in effect for the given |  | ||||||
|     Unix time in the current timezone.""" |  | ||||||
|     import time |  | ||||||
|     (tzname, delta, dstname, daystart, hourstart, dayend, hourend) = \ |  | ||||||
|             tzparams |  | ||||||
|     year, month, days, hours, mins, secs, yday, wday, isdst = \ |  | ||||||
|             time.gmtime(secs - delta*3600) |  | ||||||
|     return (daystart, hourstart) <= (yday+1, hours) < (dayend, hourend) |  | ||||||
| 
 |  | ||||||
| tzset() |  | ||||||
| 
 |  | ||||||
| def localtime(secs): |  | ||||||
|     """Get the local time in the current timezone.""" |  | ||||||
|     return tzlocaltime(secs, tzparams) |  | ||||||
| 
 |  | ||||||
| def test(): |  | ||||||
|     from time import asctime, gmtime |  | ||||||
|     import time, sys |  | ||||||
|     now = time.time() |  | ||||||
|     x = localtime(now) |  | ||||||
|     tm = x[:-1] + (0,) |  | ||||||
|     print 'now =', now, '=', asctime(tm), x[-1] |  | ||||||
|     now = now - now % (24*3600) |  | ||||||
|     if sys.argv[1:]: now = now + eval(sys.argv[1]) |  | ||||||
|     x = gmtime(now) |  | ||||||
|     tm = x[:-1] + (0,) |  | ||||||
|     print 'gmtime =', now, '=', asctime(tm), 'yday =', x[-2] |  | ||||||
|     jan1 = now - x[-2]*24*3600 |  | ||||||
|     x = localtime(jan1) |  | ||||||
|     tm = x[:-1] + (0,) |  | ||||||
|     print 'jan1 =', jan1, '=', asctime(tm), x[-1] |  | ||||||
|     for d in range(85, 95) + range(265, 275): |  | ||||||
|         t = jan1 + d*24*3600 |  | ||||||
|         x = localtime(t) |  | ||||||
|         tm = x[:-1] + (0,) |  | ||||||
|         print 'd =', d, 't =', t, '=', asctime(tm), x[-1] |  | ||||||
|  | @ -1,25 +0,0 @@ | ||||||
| # Module 'util' -- some useful functions that don't fit elsewhere |  | ||||||
| 
 |  | ||||||
| # NB: These are now built-in functions, but this module is provided |  | ||||||
| # for compatibility.  Don't use in new programs unless you need backward |  | ||||||
| # compatibility (i.e. need to run with old interpreters). |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Remove an item from a list. |  | ||||||
| # No complaints if it isn't in the list at all. |  | ||||||
| # If it occurs more than once, remove the first occurrence. |  | ||||||
| # |  | ||||||
| def remove(item, list): |  | ||||||
|     if item in list: list.remove(item) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Return a string containing a file's contents. |  | ||||||
| # |  | ||||||
| def readfile(fn): |  | ||||||
|     return readopenfile(open(fn, 'r')) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Read an open file until EOF. |  | ||||||
| # |  | ||||||
| def readopenfile(fp): |  | ||||||
|     return fp.read() |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| from sndhdr import * |  | ||||||
|  | @ -1,144 +0,0 @@ | ||||||
| """Wichman-Hill random number generator. |  | ||||||
| 
 |  | ||||||
| Wichmann, B. A. & Hill, I. D. (1982) |  | ||||||
| Algorithm AS 183: |  | ||||||
| An efficient and portable pseudo-random number generator |  | ||||||
| Applied Statistics 31 (1982) 188-190 |  | ||||||
| 
 |  | ||||||
| see also: |  | ||||||
|         Correction to Algorithm AS 183 |  | ||||||
|         Applied Statistics 33 (1984) 123 |  | ||||||
| 
 |  | ||||||
|         McLeod, A. I. (1985) |  | ||||||
|         A remark on Algorithm AS 183 |  | ||||||
|         Applied Statistics 34 (1985),198-200 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| USE: |  | ||||||
| whrandom.random()       yields double precision random numbers |  | ||||||
|                         uniformly distributed between 0 and 1. |  | ||||||
| 
 |  | ||||||
| whrandom.seed(x, y, z)  must be called before whrandom.random() |  | ||||||
|                         to seed the generator |  | ||||||
| 
 |  | ||||||
| There is also an interface to create multiple independent |  | ||||||
| random generators, and to choose from other ranges. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Multi-threading note: the random number generator used here is not |  | ||||||
| thread-safe; it is possible that nearly simultaneous calls in |  | ||||||
| different theads return the same random value.  To avoid this, you |  | ||||||
| have to use a lock around all calls.  (I didn't want to slow this |  | ||||||
| down in the serial case by using a lock here.) |  | ||||||
| """ |  | ||||||
| 
 |  | ||||||
| import warnings |  | ||||||
| warnings.warn("the whrandom module is deprecated; please use the random module", |  | ||||||
|               DeprecationWarning) |  | ||||||
| 
 |  | ||||||
| # Translated by Guido van Rossum from C source provided by |  | ||||||
| # Adrian Baddeley. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class whrandom: |  | ||||||
|     def __init__(self, x = 0, y = 0, z = 0): |  | ||||||
|         """Initialize an instance. |  | ||||||
|         Without arguments, initialize from current time. |  | ||||||
|         With arguments (x, y, z), initialize from them.""" |  | ||||||
|         self.seed(x, y, z) |  | ||||||
| 
 |  | ||||||
|     def seed(self, x = 0, y = 0, z = 0): |  | ||||||
|         """Set the seed from (x, y, z). |  | ||||||
|         These must be integers in the range [0, 256).""" |  | ||||||
|         if not type(x) == type(y) == type(z) == type(0): |  | ||||||
|             raise TypeError, 'seeds must be integers' |  | ||||||
|         if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256): |  | ||||||
|             raise ValueError, 'seeds must be in range(0, 256)' |  | ||||||
|         if 0 == x == y == z: |  | ||||||
|             # Initialize from current time |  | ||||||
|             import time |  | ||||||
|             t = long(time.time() * 256) |  | ||||||
|             t = int((t&0xffffff) ^ (t>>24)) |  | ||||||
|             t, x = divmod(t, 256) |  | ||||||
|             t, y = divmod(t, 256) |  | ||||||
|             t, z = divmod(t, 256) |  | ||||||
|         # Zero is a poor seed, so substitute 1 |  | ||||||
|         self._seed = (x or 1, y or 1, z or 1) |  | ||||||
| 
 |  | ||||||
|     def random(self): |  | ||||||
|         """Get the next random number in the range [0.0, 1.0).""" |  | ||||||
|         # This part is thread-unsafe: |  | ||||||
|         # BEGIN CRITICAL SECTION |  | ||||||
|         x, y, z = self._seed |  | ||||||
|         # |  | ||||||
|         x = (171 * x) % 30269 |  | ||||||
|         y = (172 * y) % 30307 |  | ||||||
|         z = (170 * z) % 30323 |  | ||||||
|         # |  | ||||||
|         self._seed = x, y, z |  | ||||||
|         # END CRITICAL SECTION |  | ||||||
|         # |  | ||||||
|         return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0 |  | ||||||
| 
 |  | ||||||
|     def uniform(self, a, b): |  | ||||||
|         """Get a random number in the range [a, b).""" |  | ||||||
|         return a + (b-a) * self.random() |  | ||||||
| 
 |  | ||||||
|     def randint(self, a, b): |  | ||||||
|         """Get a random integer in the range [a, b] including |  | ||||||
|         both end points. |  | ||||||
| 
 |  | ||||||
|         (Deprecated; use randrange below.)""" |  | ||||||
|         return self.randrange(a, b+1) |  | ||||||
| 
 |  | ||||||
|     def choice(self, seq): |  | ||||||
|         """Choose a random element from a non-empty sequence.""" |  | ||||||
|         return seq[int(self.random() * len(seq))] |  | ||||||
| 
 |  | ||||||
|     def randrange(self, start, stop=None, step=1, int=int, default=None): |  | ||||||
|         """Choose a random item from range(start, stop[, step]). |  | ||||||
| 
 |  | ||||||
|         This fixes the problem with randint() which includes the |  | ||||||
|         endpoint; in Python this is usually not what you want. |  | ||||||
|         Do not supply the 'int' and 'default' arguments.""" |  | ||||||
|         # This code is a bit messy to make it fast for the |  | ||||||
|         # common case while still doing adequate error checking |  | ||||||
|         istart = int(start) |  | ||||||
|         if istart != start: |  | ||||||
|             raise ValueError, "non-integer arg 1 for randrange()" |  | ||||||
|         if stop is default: |  | ||||||
|             if istart > 0: |  | ||||||
|                 return int(self.random() * istart) |  | ||||||
|             raise ValueError, "empty range for randrange()" |  | ||||||
|         istop = int(stop) |  | ||||||
|         if istop != stop: |  | ||||||
|             raise ValueError, "non-integer stop for randrange()" |  | ||||||
|         if step == 1: |  | ||||||
|             if istart < istop: |  | ||||||
|                 return istart + int(self.random() * |  | ||||||
|                                    (istop - istart)) |  | ||||||
|             raise ValueError, "empty range for randrange()" |  | ||||||
|         istep = int(step) |  | ||||||
|         if istep != step: |  | ||||||
|             raise ValueError, "non-integer step for randrange()" |  | ||||||
|         if istep > 0: |  | ||||||
|             n = (istop - istart + istep - 1) / istep |  | ||||||
|         elif istep < 0: |  | ||||||
|             n = (istop - istart + istep + 1) / istep |  | ||||||
|         else: |  | ||||||
|             raise ValueError, "zero step for randrange()" |  | ||||||
| 
 |  | ||||||
|         if n <= 0: |  | ||||||
|             raise ValueError, "empty range for randrange()" |  | ||||||
|         return istart + istep*int(self.random() * n) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Initialize from the current time |  | ||||||
| _inst = whrandom() |  | ||||||
| seed = _inst.seed |  | ||||||
| random = _inst.random |  | ||||||
| uniform = _inst.uniform |  | ||||||
| randint = _inst.randint |  | ||||||
| choice = _inst.choice |  | ||||||
| randrange = _inst.randrange |  | ||||||
|  | @ -1,94 +0,0 @@ | ||||||
| # module 'zmod' |  | ||||||
| 
 |  | ||||||
| # Compute properties of mathematical "fields" formed by taking |  | ||||||
| # Z/n (the whole numbers modulo some whole number n) and an |  | ||||||
| # irreducible polynomial (i.e., a polynomial with only complex zeros), |  | ||||||
| # e.g., Z/5 and X**2 + 2. |  | ||||||
| # |  | ||||||
| # The field is formed by taking all possible linear combinations of |  | ||||||
| # a set of d base vectors (where d is the degree of the polynomial). |  | ||||||
| # |  | ||||||
| # Note that this procedure doesn't yield a field for all combinations |  | ||||||
| # of n and p: it may well be that some numbers have more than one |  | ||||||
| # inverse and others have none.  This is what we check. |  | ||||||
| # |  | ||||||
| # Remember that a field is a ring where each element has an inverse. |  | ||||||
| # A ring has commutative addition and multiplication, a zero and a one: |  | ||||||
| # 0*x = x*0 = 0, 0+x = x+0 = x, 1*x = x*1 = x.  Also, the distributive |  | ||||||
| # property holds: a*(b+c) = a*b + b*c. |  | ||||||
| # (XXX I forget if this is an axiom or follows from the rules.) |  | ||||||
| 
 |  | ||||||
| import poly |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Example N and polynomial |  | ||||||
| 
 |  | ||||||
| N = 5 |  | ||||||
| P = poly.plus(poly.one(0, 2), poly.one(2, 1)) # 2 + x**2 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Return x modulo y.  Returns >= 0 even if x < 0. |  | ||||||
| 
 |  | ||||||
| def mod(x, y): |  | ||||||
|     return divmod(x, y)[1] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Normalize a polynomial modulo n and modulo p. |  | ||||||
| 
 |  | ||||||
| def norm(a, n, p): |  | ||||||
|     a = poly.modulo(a, p) |  | ||||||
|     a = a[:] |  | ||||||
|     for i in range(len(a)): a[i] = mod(a[i], n) |  | ||||||
|     a = poly.normalize(a) |  | ||||||
|     return a |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Make a list of all n^d elements of the proposed field. |  | ||||||
| 
 |  | ||||||
| def make_all(mat): |  | ||||||
|     all = [] |  | ||||||
|     for row in mat: |  | ||||||
|         for a in row: |  | ||||||
|             all.append(a) |  | ||||||
|     return all |  | ||||||
| 
 |  | ||||||
| def make_elements(n, d): |  | ||||||
|     if d == 0: return [poly.one(0, 0)] |  | ||||||
|     sub = make_elements(n, d-1) |  | ||||||
|     all = [] |  | ||||||
|     for a in sub: |  | ||||||
|         for i in range(n): |  | ||||||
|             all.append(poly.plus(a, poly.one(d-1, i))) |  | ||||||
|     return all |  | ||||||
| 
 |  | ||||||
| def make_inv(all, n, p): |  | ||||||
|     x = poly.one(1, 1) |  | ||||||
|     inv = [] |  | ||||||
|     for a in all: |  | ||||||
|         inv.append(norm(poly.times(a, x), n, p)) |  | ||||||
|     return inv |  | ||||||
| 
 |  | ||||||
| def checkfield(n, p): |  | ||||||
|     all = make_elements(n, len(p)-1) |  | ||||||
|     inv = make_inv(all, n, p) |  | ||||||
|     all1 = all[:] |  | ||||||
|     inv1 = inv[:] |  | ||||||
|     all1.sort() |  | ||||||
|     inv1.sort() |  | ||||||
|     if all1 == inv1: print 'BINGO!' |  | ||||||
|     else: |  | ||||||
|         print 'Sorry:', n, p |  | ||||||
|         print all |  | ||||||
|         print inv |  | ||||||
| 
 |  | ||||||
| def rj(s, width): |  | ||||||
|     if type(s) is not type(''): s = `s` |  | ||||||
|     n = len(s) |  | ||||||
|     if n >= width: return s |  | ||||||
|     return ' '*(width - n) + s |  | ||||||
| 
 |  | ||||||
| def lj(s, width): |  | ||||||
|     if type(s) is not type(''): s = `s` |  | ||||||
|     n = len(s) |  | ||||||
|     if n >= width: return s |  | ||||||
|     return s + ' '*(width - n) |  | ||||||
							
								
								
									
										192
									
								
								Lib/reconvert.py
									
										
									
									
									
								
							
							
						
						
									
										192
									
								
								Lib/reconvert.py
									
										
									
									
									
								
							|  | @ -1,192 +0,0 @@ | ||||||
| #! /usr/bin/env python |  | ||||||
| 
 |  | ||||||
| r"""Convert old ("regex") regular expressions to new syntax ("re"). |  | ||||||
| 
 |  | ||||||
| When imported as a module, there are two functions, with their own |  | ||||||
| strings: |  | ||||||
| 
 |  | ||||||
|   convert(s, syntax=None) -- convert a regex regular expression to re syntax |  | ||||||
| 
 |  | ||||||
|   quote(s) -- return a quoted string literal |  | ||||||
| 
 |  | ||||||
| When used as a script, read a Python string literal (or any other |  | ||||||
| expression evaluating to a string) from stdin, and write the |  | ||||||
| translated expression to stdout as a string literal.  Unless stdout is |  | ||||||
| a tty, no trailing \n is written to stdout.  This is done so that it |  | ||||||
| can be used with Emacs C-U M-| (shell-command-on-region with argument |  | ||||||
| which filters the region through the shell command). |  | ||||||
| 
 |  | ||||||
| No attempt has been made at coding for performance. |  | ||||||
| 
 |  | ||||||
| Translation table... |  | ||||||
| 
 |  | ||||||
|     \(    (     (unless RE_NO_BK_PARENS set) |  | ||||||
|     \)    )     (unless RE_NO_BK_PARENS set) |  | ||||||
|     \|    |     (unless RE_NO_BK_VBAR set) |  | ||||||
|     \<    \b    (not quite the same, but alla...) |  | ||||||
|     \>    \b    (not quite the same, but alla...) |  | ||||||
|     \`    \A |  | ||||||
|     \'    \Z |  | ||||||
| 
 |  | ||||||
| Not translated... |  | ||||||
| 
 |  | ||||||
|     . |  | ||||||
|     ^ |  | ||||||
|     $ |  | ||||||
|     * |  | ||||||
|     +           (unless RE_BK_PLUS_QM set, then to \+) |  | ||||||
|     ?           (unless RE_BK_PLUS_QM set, then to \?) |  | ||||||
|     \ |  | ||||||
|     \b |  | ||||||
|     \B |  | ||||||
|     \w |  | ||||||
|     \W |  | ||||||
|     \1 ... \9 |  | ||||||
| 
 |  | ||||||
| Special cases... |  | ||||||
| 
 |  | ||||||
|     Non-printable characters are always replaced by their 3-digit |  | ||||||
|     escape code (except \t, \n, \r, which use mnemonic escapes) |  | ||||||
| 
 |  | ||||||
|     Newline is turned into | when RE_NEWLINE_OR is set |  | ||||||
| 
 |  | ||||||
| XXX To be done... |  | ||||||
| 
 |  | ||||||
|     [...]     (different treatment of backslashed items?) |  | ||||||
|     [^...]    (different treatment of backslashed items?) |  | ||||||
|     ^ $ * + ? (in some error contexts these are probably treated differently) |  | ||||||
|     \vDD  \DD (in the regex docs but only works when RE_ANSI_HEX set) |  | ||||||
| 
 |  | ||||||
| """ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| import warnings |  | ||||||
| warnings.filterwarnings("ignore", ".* regex .*", DeprecationWarning, __name__, |  | ||||||
|                         append=1) |  | ||||||
| 
 |  | ||||||
| import regex |  | ||||||
| from regex_syntax import * # RE_* |  | ||||||
| 
 |  | ||||||
| __all__ = ["convert","quote"] |  | ||||||
| 
 |  | ||||||
| # Default translation table |  | ||||||
| mastertable = { |  | ||||||
|     r'\<': r'\b', |  | ||||||
|     r'\>': r'\b', |  | ||||||
|     r'\`': r'\A', |  | ||||||
|     r'\'': r'\Z', |  | ||||||
|     r'\(': '(', |  | ||||||
|     r'\)': ')', |  | ||||||
|     r'\|': '|', |  | ||||||
|     '(': r'\(', |  | ||||||
|     ')': r'\)', |  | ||||||
|     '|': r'\|', |  | ||||||
|     '\t': r'\t', |  | ||||||
|     '\n': r'\n', |  | ||||||
|     '\r': r'\r', |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def convert(s, syntax=None): |  | ||||||
|     """Convert a regex regular expression to re syntax. |  | ||||||
| 
 |  | ||||||
|     The first argument is the regular expression, as a string object, |  | ||||||
|     just like it would be passed to regex.compile().  (I.e., pass the |  | ||||||
|     actual string object -- string quotes must already have been |  | ||||||
|     removed and the standard escape processing has already been done, |  | ||||||
|     e.g. by eval().) |  | ||||||
| 
 |  | ||||||
|     The optional second argument is the regex syntax variant to be |  | ||||||
|     used.  This is an integer mask as passed to regex.set_syntax(); |  | ||||||
|     the flag bits are defined in regex_syntax.  When not specified, or |  | ||||||
|     when None is given, the current regex syntax mask (as retrieved by |  | ||||||
|     regex.get_syntax()) is used -- which is 0 by default. |  | ||||||
| 
 |  | ||||||
|     The return value is a regular expression, as a string object that |  | ||||||
|     could be passed to re.compile().  (I.e., no string quotes have |  | ||||||
|     been added -- use quote() below, or repr().) |  | ||||||
| 
 |  | ||||||
|     The conversion is not always guaranteed to be correct.  More |  | ||||||
|     syntactical analysis should be performed to detect borderline |  | ||||||
|     cases and decide what to do with them.  For example, 'x*?' is not |  | ||||||
|     translated correctly. |  | ||||||
| 
 |  | ||||||
|     """ |  | ||||||
|     table = mastertable.copy() |  | ||||||
|     if syntax is None: |  | ||||||
|         syntax = regex.get_syntax() |  | ||||||
|     if syntax & RE_NO_BK_PARENS: |  | ||||||
|         del table[r'\('], table[r'\)'] |  | ||||||
|         del table['('], table[')'] |  | ||||||
|     if syntax & RE_NO_BK_VBAR: |  | ||||||
|         del table[r'\|'] |  | ||||||
|         del table['|'] |  | ||||||
|     if syntax & RE_BK_PLUS_QM: |  | ||||||
|         table['+'] = r'\+' |  | ||||||
|         table['?'] = r'\?' |  | ||||||
|         table[r'\+'] = '+' |  | ||||||
|         table[r'\?'] = '?' |  | ||||||
|     if syntax & RE_NEWLINE_OR: |  | ||||||
|         table['\n'] = '|' |  | ||||||
|     res = "" |  | ||||||
| 
 |  | ||||||
|     i = 0 |  | ||||||
|     end = len(s) |  | ||||||
|     while i < end: |  | ||||||
|         c = s[i] |  | ||||||
|         i = i+1 |  | ||||||
|         if c == '\\': |  | ||||||
|             c = s[i] |  | ||||||
|             i = i+1 |  | ||||||
|             key = '\\' + c |  | ||||||
|             key = table.get(key, key) |  | ||||||
|             res = res + key |  | ||||||
|         else: |  | ||||||
|             c = table.get(c, c) |  | ||||||
|             res = res + c |  | ||||||
|     return res |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def quote(s, quote=None): |  | ||||||
|     """Convert a string object to a quoted string literal. |  | ||||||
| 
 |  | ||||||
|     This is similar to repr() but will return a "raw" string (r'...' |  | ||||||
|     or r"...") when the string contains backslashes, instead of |  | ||||||
|     doubling all backslashes.  The resulting string does *not* always |  | ||||||
|     evaluate to the same string as the original; however it will do |  | ||||||
|     just the right thing when passed into re.compile(). |  | ||||||
| 
 |  | ||||||
|     The optional second argument forces the string quote; it must be |  | ||||||
|     a single character which is a valid Python string quote. |  | ||||||
| 
 |  | ||||||
|     """ |  | ||||||
|     if quote is None: |  | ||||||
|         q = "'" |  | ||||||
|         altq = "'" |  | ||||||
|         if q in s and altq not in s: |  | ||||||
|             q = altq |  | ||||||
|     else: |  | ||||||
|         assert quote in ('"', "'", '"""', "'''") |  | ||||||
|         q = quote |  | ||||||
|     res = q |  | ||||||
|     for c in s: |  | ||||||
|         if c == q: c = '\\' + c |  | ||||||
|         elif c < ' ' or c > '~': c = "\\%03o" % ord(c) |  | ||||||
|         res = res + c |  | ||||||
|     res = res + q |  | ||||||
|     if '\\' in res: |  | ||||||
|         res = 'r' + res |  | ||||||
|     return res |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def main(): |  | ||||||
|     """Main program -- called when run as a script.""" |  | ||||||
|     import sys |  | ||||||
|     s = eval(sys.stdin.read()) |  | ||||||
|     sys.stdout.write(quote(convert(s))) |  | ||||||
|     if sys.stdout.isatty(): |  | ||||||
|         sys.stdout.write("\n") |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| if __name__ == '__main__': |  | ||||||
|     main() |  | ||||||
|  | @ -1,53 +0,0 @@ | ||||||
| """Constants for selecting regexp syntaxes for the obsolete regex module. |  | ||||||
| 
 |  | ||||||
| This module is only for backward compatibility.  "regex" has now |  | ||||||
| been replaced by the new regular expression module, "re". |  | ||||||
| 
 |  | ||||||
| These bits are passed to regex.set_syntax() to choose among |  | ||||||
| alternative regexp syntaxes. |  | ||||||
| """ |  | ||||||
| 
 |  | ||||||
| # 1 means plain parentheses serve as grouping, and backslash |  | ||||||
| #   parentheses are needed for literal searching. |  | ||||||
| # 0 means backslash-parentheses are grouping, and plain parentheses |  | ||||||
| #   are for literal searching. |  | ||||||
| RE_NO_BK_PARENS = 1 |  | ||||||
| 
 |  | ||||||
| # 1 means plain | serves as the "or"-operator, and \| is a literal. |  | ||||||
| # 0 means \| serves as the "or"-operator, and | is a literal. |  | ||||||
| RE_NO_BK_VBAR = 2 |  | ||||||
| 
 |  | ||||||
| # 0 means plain + or ? serves as an operator, and \+, \? are literals. |  | ||||||
| # 1 means \+, \? are operators and plain +, ? are literals. |  | ||||||
| RE_BK_PLUS_QM = 4 |  | ||||||
| 
 |  | ||||||
| # 1 means | binds tighter than ^ or $. |  | ||||||
| # 0 means the contrary. |  | ||||||
| RE_TIGHT_VBAR = 8 |  | ||||||
| 
 |  | ||||||
| # 1 means treat \n as an _OR operator |  | ||||||
| # 0 means treat it as a normal character |  | ||||||
| RE_NEWLINE_OR = 16 |  | ||||||
| 
 |  | ||||||
| # 0 means that a special characters (such as *, ^, and $) always have |  | ||||||
| #   their special meaning regardless of the surrounding context. |  | ||||||
| # 1 means that special characters may act as normal characters in some |  | ||||||
| #   contexts.  Specifically, this applies to: |  | ||||||
| #       ^ - only special at the beginning, or after ( or | |  | ||||||
| #       $ - only special at the end, or before ) or | |  | ||||||
| #       *, +, ? - only special when not after the beginning, (, or | |  | ||||||
| RE_CONTEXT_INDEP_OPS = 32 |  | ||||||
| 
 |  | ||||||
| # ANSI sequences (\n etc) and \xhh |  | ||||||
| RE_ANSI_HEX = 64 |  | ||||||
| 
 |  | ||||||
| # No GNU extensions |  | ||||||
| RE_NO_GNU_EXTENSIONS = 128 |  | ||||||
| 
 |  | ||||||
| # Now define combinations of bits for the standard possibilities. |  | ||||||
| RE_SYNTAX_AWK = (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS) |  | ||||||
| RE_SYNTAX_EGREP = (RE_SYNTAX_AWK | RE_NEWLINE_OR) |  | ||||||
| RE_SYNTAX_GREP = (RE_BK_PLUS_QM | RE_NEWLINE_OR) |  | ||||||
| RE_SYNTAX_EMACS = 0 |  | ||||||
| 
 |  | ||||||
| # (Python's obsolete "regexp" module used a syntax similar to awk.) |  | ||||||
							
								
								
									
										198
									
								
								Lib/regsub.py
									
										
									
									
									
								
							
							
						
						
									
										198
									
								
								Lib/regsub.py
									
										
									
									
									
								
							|  | @ -1,198 +0,0 @@ | ||||||
| """Regexp-based split and replace using the obsolete regex module. |  | ||||||
| 
 |  | ||||||
| This module is only for backward compatibility.  These operations |  | ||||||
| are now provided by the new regular expression module, "re". |  | ||||||
| 
 |  | ||||||
| sub(pat, repl, str):        replace first occurrence of pattern in string |  | ||||||
| gsub(pat, repl, str):       replace all occurrences of pattern in string |  | ||||||
| split(str, pat, maxsplit):  split string using pattern as delimiter |  | ||||||
| splitx(str, pat, maxsplit): split string using pattern as delimiter plus |  | ||||||
|                             return delimiters |  | ||||||
| """ |  | ||||||
| 
 |  | ||||||
| import warnings |  | ||||||
| warnings.warn("the regsub module is deprecated; please use re.sub()", |  | ||||||
|               DeprecationWarning) |  | ||||||
| 
 |  | ||||||
| # Ignore further deprecation warnings about this module |  | ||||||
| warnings.filterwarnings("ignore", "", DeprecationWarning, __name__) |  | ||||||
| 
 |  | ||||||
| import regex |  | ||||||
| 
 |  | ||||||
| __all__ = ["sub","gsub","split","splitx","capwords"] |  | ||||||
| 
 |  | ||||||
| # Replace first occurrence of pattern pat in string str by replacement |  | ||||||
| # repl.  If the pattern isn't found, the string is returned unchanged. |  | ||||||
| # The replacement may contain references \digit to subpatterns and |  | ||||||
| # escaped backslashes.  The pattern may be a string or an already |  | ||||||
| # compiled pattern. |  | ||||||
| 
 |  | ||||||
| def sub(pat, repl, str): |  | ||||||
|     prog = compile(pat) |  | ||||||
|     if prog.search(str) >= 0: |  | ||||||
|         regs = prog.regs |  | ||||||
|         a, b = regs[0] |  | ||||||
|         str = str[:a] + expand(repl, regs, str) + str[b:] |  | ||||||
|     return str |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Replace all (non-overlapping) occurrences of pattern pat in string |  | ||||||
| # str by replacement repl.  The same rules as for sub() apply. |  | ||||||
| # Empty matches for the pattern are replaced only when not adjacent to |  | ||||||
| # a previous match, so e.g. gsub('', '-', 'abc') returns '-a-b-c-'. |  | ||||||
| 
 |  | ||||||
| def gsub(pat, repl, str): |  | ||||||
|     prog = compile(pat) |  | ||||||
|     new = '' |  | ||||||
|     start = 0 |  | ||||||
|     first = 1 |  | ||||||
|     while prog.search(str, start) >= 0: |  | ||||||
|         regs = prog.regs |  | ||||||
|         a, b = regs[0] |  | ||||||
|         if a == b == start and not first: |  | ||||||
|             if start >= len(str) or prog.search(str, start+1) < 0: |  | ||||||
|                 break |  | ||||||
|             regs = prog.regs |  | ||||||
|             a, b = regs[0] |  | ||||||
|         new = new + str[start:a] + expand(repl, regs, str) |  | ||||||
|         start = b |  | ||||||
|         first = 0 |  | ||||||
|     new = new + str[start:] |  | ||||||
|     return new |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Split string str in fields separated by delimiters matching pattern |  | ||||||
| # pat.  Only non-empty matches for the pattern are considered, so e.g. |  | ||||||
| # split('abc', '') returns ['abc']. |  | ||||||
| # The optional 3rd argument sets the number of splits that are performed. |  | ||||||
| 
 |  | ||||||
| def split(str, pat, maxsplit = 0): |  | ||||||
|     return intsplit(str, pat, maxsplit, 0) |  | ||||||
| 
 |  | ||||||
| # Split string str in fields separated by delimiters matching pattern |  | ||||||
| # pat.  Only non-empty matches for the pattern are considered, so e.g. |  | ||||||
| # split('abc', '') returns ['abc']. The delimiters are also included |  | ||||||
| # in the list. |  | ||||||
| # The optional 3rd argument sets the number of splits that are performed. |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def splitx(str, pat, maxsplit = 0): |  | ||||||
|     return intsplit(str, pat, maxsplit, 1) |  | ||||||
| 
 |  | ||||||
| # Internal function used to implement split() and splitx(). |  | ||||||
| 
 |  | ||||||
| def intsplit(str, pat, maxsplit, retain): |  | ||||||
|     prog = compile(pat) |  | ||||||
|     res = [] |  | ||||||
|     start = next = 0 |  | ||||||
|     splitcount = 0 |  | ||||||
|     while prog.search(str, next) >= 0: |  | ||||||
|         regs = prog.regs |  | ||||||
|         a, b = regs[0] |  | ||||||
|         if a == b: |  | ||||||
|             next = next + 1 |  | ||||||
|             if next >= len(str): |  | ||||||
|                 break |  | ||||||
|         else: |  | ||||||
|             res.append(str[start:a]) |  | ||||||
|             if retain: |  | ||||||
|                 res.append(str[a:b]) |  | ||||||
|             start = next = b |  | ||||||
|             splitcount = splitcount + 1 |  | ||||||
|             if (maxsplit and (splitcount >= maxsplit)): |  | ||||||
|                 break |  | ||||||
|     res.append(str[start:]) |  | ||||||
|     return res |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Capitalize words split using a pattern |  | ||||||
| 
 |  | ||||||
| def capwords(str, pat='[^a-zA-Z0-9_]+'): |  | ||||||
|     words = splitx(str, pat) |  | ||||||
|     for i in range(0, len(words), 2): |  | ||||||
|         words[i] = words[i].capitalize() |  | ||||||
|     return "".join(words) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Internal subroutines: |  | ||||||
| # compile(pat): compile a pattern, caching already compiled patterns |  | ||||||
| # expand(repl, regs, str): expand \digit escapes in replacement string |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Manage a cache of compiled regular expressions. |  | ||||||
| # |  | ||||||
| # If the pattern is a string a compiled version of it is returned.  If |  | ||||||
| # the pattern has been used before we return an already compiled |  | ||||||
| # version from the cache; otherwise we compile it now and save the |  | ||||||
| # compiled version in the cache, along with the syntax it was compiled |  | ||||||
| # with.  Instead of a string, a compiled regular expression can also |  | ||||||
| # be passed. |  | ||||||
| 
 |  | ||||||
| cache = {} |  | ||||||
| 
 |  | ||||||
| def compile(pat): |  | ||||||
|     if type(pat) != type(''): |  | ||||||
|         return pat              # Assume it is a compiled regex |  | ||||||
|     key = (pat, regex.get_syntax()) |  | ||||||
|     if key in cache: |  | ||||||
|         prog = cache[key]       # Get it from the cache |  | ||||||
|     else: |  | ||||||
|         prog = cache[key] = regex.compile(pat) |  | ||||||
|     return prog |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def clear_cache(): |  | ||||||
|     global cache |  | ||||||
|     cache = {} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Expand \digit in the replacement. |  | ||||||
| # Each occurrence of \digit is replaced by the substring of str |  | ||||||
| # indicated by regs[digit].  To include a literal \ in the |  | ||||||
| # replacement, double it; other \ escapes are left unchanged (i.e. |  | ||||||
| # the \ and the following character are both copied). |  | ||||||
| 
 |  | ||||||
| def expand(repl, regs, str): |  | ||||||
|     if '\\' not in repl: |  | ||||||
|         return repl |  | ||||||
|     new = '' |  | ||||||
|     i = 0 |  | ||||||
|     ord0 = ord('0') |  | ||||||
|     while i < len(repl): |  | ||||||
|         c = repl[i]; i = i+1 |  | ||||||
|         if c != '\\' or i >= len(repl): |  | ||||||
|             new = new + c |  | ||||||
|         else: |  | ||||||
|             c = repl[i]; i = i+1 |  | ||||||
|             if '0' <= c <= '9': |  | ||||||
|                 a, b = regs[ord(c)-ord0] |  | ||||||
|                 new = new + str[a:b] |  | ||||||
|             elif c == '\\': |  | ||||||
|                 new = new + c |  | ||||||
|             else: |  | ||||||
|                 new = new + '\\' + c |  | ||||||
|     return new |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Test program, reads sequences "pat repl str" from stdin. |  | ||||||
| # Optional argument specifies pattern used to split lines. |  | ||||||
| 
 |  | ||||||
| def test(): |  | ||||||
|     import sys |  | ||||||
|     if sys.argv[1:]: |  | ||||||
|         delpat = sys.argv[1] |  | ||||||
|     else: |  | ||||||
|         delpat = '[ \t\n]+' |  | ||||||
|     while 1: |  | ||||||
|         if sys.stdin.isatty(): sys.stderr.write('--> ') |  | ||||||
|         line = sys.stdin.readline() |  | ||||||
|         if not line: break |  | ||||||
|         if line[-1] == '\n': line = line[:-1] |  | ||||||
|         fields = split(line, delpat) |  | ||||||
|         if len(fields) != 3: |  | ||||||
|             print 'Sorry, not three fields' |  | ||||||
|             print 'split:', repr(fields) |  | ||||||
|             continue |  | ||||||
|         [pat, repl, str] = split(line, delpat) |  | ||||||
|         print 'sub :', repr(sub(pat, repl, str)) |  | ||||||
|         print 'gsub:', repr(gsub(pat, repl, str)) |  | ||||||
|  | @ -136,7 +136,7 @@ class RExec(ihooks._Verbose): | ||||||
|     ok_builtin_modules = ('audioop', 'array', 'binascii', |     ok_builtin_modules = ('audioop', 'array', 'binascii', | ||||||
|                           'cmath', 'errno', 'imageop', |                           'cmath', 'errno', 'imageop', | ||||||
|                           'marshal', 'math', 'md5', 'operator', |                           'marshal', 'math', 'md5', 'operator', | ||||||
|                           'parser', 'regex', 'select', |                           'parser', 'select', | ||||||
|                           'sha', '_sre', 'strop', 'struct', 'time', |                           'sha', '_sre', 'strop', 'struct', 'time', | ||||||
|                           '_weakref') |                           '_weakref') | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -128,8 +128,6 @@ def test_all(self): | ||||||
|         self.check_all("quopri") |         self.check_all("quopri") | ||||||
|         self.check_all("random") |         self.check_all("random") | ||||||
|         self.check_all("re") |         self.check_all("re") | ||||||
|         self.check_all("reconvert") |  | ||||||
|         self.check_all("regsub") |  | ||||||
|         self.check_all("repr") |         self.check_all("repr") | ||||||
|         self.check_all("rexec") |         self.check_all("rexec") | ||||||
|         self.check_all("rfc822") |         self.check_all("rfc822") | ||||||
|  |  | ||||||
|  | @ -1,113 +0,0 @@ | ||||||
| from test.test_support import verbose, sortdict |  | ||||||
| import warnings |  | ||||||
| warnings.filterwarnings("ignore", "the regex module is deprecated", |  | ||||||
|                         DeprecationWarning, __name__) |  | ||||||
| import regex |  | ||||||
| from regex_syntax import * |  | ||||||
| 
 |  | ||||||
| re = 'a+b+c+' |  | ||||||
| print 'no match:', regex.match(re, 'hello aaaabcccc world') |  | ||||||
| print 'successful search:', regex.search(re, 'hello aaaabcccc world') |  | ||||||
| try: |  | ||||||
|     cre = regex.compile('\(' + re) |  | ||||||
| except regex.error: |  | ||||||
|     print 'caught expected exception' |  | ||||||
| else: |  | ||||||
|     print 'expected regex.error not raised' |  | ||||||
| 
 |  | ||||||
| print 'failed awk syntax:', regex.search('(a+)|(b+)', 'cdb') |  | ||||||
| prev = regex.set_syntax(RE_SYNTAX_AWK) |  | ||||||
| print 'successful awk syntax:', regex.search('(a+)|(b+)', 'cdb') |  | ||||||
| regex.set_syntax(prev) |  | ||||||
| print 'failed awk syntax:', regex.search('(a+)|(b+)', 'cdb') |  | ||||||
| 
 |  | ||||||
| re = '\(<one>[0-9]+\) *\(<two>[0-9]+\)' |  | ||||||
| print 'matching with group names and compile()' |  | ||||||
| cre = regex.compile(re) |  | ||||||
| print cre.match('801 999') |  | ||||||
| try: |  | ||||||
|     print cre.group('one') |  | ||||||
| except regex.error: |  | ||||||
|     print 'caught expected exception' |  | ||||||
| else: |  | ||||||
|     print 'expected regex.error not raised' |  | ||||||
| 
 |  | ||||||
| print 'matching with group names and symcomp()' |  | ||||||
| cre = regex.symcomp(re) |  | ||||||
| print cre.match('801 999') |  | ||||||
| print cre.group(0) |  | ||||||
| print cre.group('one') |  | ||||||
| print cre.group(1, 2) |  | ||||||
| print cre.group('one', 'two') |  | ||||||
| print 'realpat:', cre.realpat |  | ||||||
| print 'groupindex:', sortdict(cre.groupindex) |  | ||||||
| 
 |  | ||||||
| re = 'world' |  | ||||||
| cre = regex.compile(re) |  | ||||||
| print 'not case folded search:', cre.search('HELLO WORLD') |  | ||||||
| cre = regex.compile(re, regex.casefold) |  | ||||||
| print 'case folded search:', cre.search('HELLO WORLD') |  | ||||||
| 
 |  | ||||||
| print '__members__:', cre.__members__ |  | ||||||
| print 'regs:', cre.regs |  | ||||||
| print 'last:', cre.last |  | ||||||
| print 'translate:', len(cre.translate) |  | ||||||
| print 'givenpat:', cre.givenpat |  | ||||||
| 
 |  | ||||||
| print 'match with pos:', cre.match('hello world', 7) |  | ||||||
| print 'search with pos:', cre.search('hello world there world', 7) |  | ||||||
| print 'bogus group:', cre.group(0, 1, 3) |  | ||||||
| try: |  | ||||||
|     print 'no name:', cre.group('one') |  | ||||||
| except regex.error: |  | ||||||
|     print 'caught expected exception' |  | ||||||
| else: |  | ||||||
|     print 'expected regex.error not raised' |  | ||||||
| 
 |  | ||||||
| from regex_tests import * |  | ||||||
| if verbose: print 'Running regex_tests test suite' |  | ||||||
| 
 |  | ||||||
| for t in tests: |  | ||||||
|     pattern=s=outcome=repl=expected=None |  | ||||||
|     if len(t)==5: |  | ||||||
|         pattern, s, outcome, repl, expected = t |  | ||||||
|     elif len(t)==3: |  | ||||||
|         pattern, s, outcome = t |  | ||||||
|     else: |  | ||||||
|         raise ValueError, ('Test tuples should have 3 or 5 fields',t) |  | ||||||
| 
 |  | ||||||
|     try: |  | ||||||
|         obj=regex.compile(pattern) |  | ||||||
|     except regex.error: |  | ||||||
|         if outcome==SYNTAX_ERROR: pass    # Expected a syntax error |  | ||||||
|         else: |  | ||||||
|             # Regex syntax errors aren't yet reported, so for |  | ||||||
|             # the official test suite they'll be quietly ignored. |  | ||||||
|             pass |  | ||||||
|             #print '=== Syntax error:', t |  | ||||||
|     else: |  | ||||||
|         try: |  | ||||||
|             result=obj.search(s) |  | ||||||
|         except regex.error, msg: |  | ||||||
|             print '=== Unexpected exception', t, repr(msg) |  | ||||||
|         if outcome==SYNTAX_ERROR: |  | ||||||
|             # This should have been a syntax error; forget it. |  | ||||||
|             pass |  | ||||||
|         elif outcome==FAIL: |  | ||||||
|             if result==-1: pass   # No match, as expected |  | ||||||
|             else: print '=== Succeeded incorrectly', t |  | ||||||
|         elif outcome==SUCCEED: |  | ||||||
|             if result!=-1: |  | ||||||
|                 # Matched, as expected, so now we compute the |  | ||||||
|                 # result string and compare it to our expected result. |  | ||||||
|                 start, end = obj.regs[0] |  | ||||||
|                 found=s[start:end] |  | ||||||
|                 groups=obj.group(1,2,3,4,5,6,7,8,9,10) |  | ||||||
|                 vardict=vars() |  | ||||||
|                 for i in range(len(groups)): |  | ||||||
|                     vardict['g'+str(i+1)]=str(groups[i]) |  | ||||||
|                 repl=eval(repl) |  | ||||||
|                 if repl!=expected: |  | ||||||
|                     print '=== grouping error', t, repr(repl)+' should be '+repr(expected) |  | ||||||
|             else: |  | ||||||
|                 print '=== Failed incorrectly', t |  | ||||||
|  | @ -68,7 +68,6 @@ | ||||||
| import profile | import profile | ||||||
| import pstats | import pstats | ||||||
| import py_compile | import py_compile | ||||||
| #import reconvert |  | ||||||
| import repr | import repr | ||||||
| try: | try: | ||||||
|     import rlcompleter   # not available on Windows |     import rlcompleter   # not available on Windows | ||||||
|  |  | ||||||
|  | @ -176,8 +176,6 @@ def detect_modules(self): | ||||||
|         # |         # | ||||||
| 
 | 
 | ||||||
|         # Some modules that are normally always on: |         # Some modules that are normally always on: | ||||||
|         exts.append( Extension('regex', ['regexmodule.c', 'regexpr.c']) ) |  | ||||||
| 
 |  | ||||||
|         exts.append( Extension('_weakref', ['_weakref.c']) ) |         exts.append( Extension('_weakref', ['_weakref.c']) ) | ||||||
|         exts.append( Extension('_symtable', ['symtablemodule.c']) ) |         exts.append( Extension('_symtable', ['symtablemodule.c']) ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -291,7 +291,14 @@ Core and builtins | ||||||
| Extension Modules | Extension Modules | ||||||
| ----------------- | ----------------- | ||||||
| 
 | 
 | ||||||
| - Swapped re and sre, so help(re) provides full help.  importing sre | - Everything under lib-old was removed.  This includes the following modules: | ||||||
|  |     Para, addpack, cmp, cmpcache, codehack, dircmp, dump, find, fmt, grep, | ||||||
|  |     lockfile, newdir, ni, packmail, poly, rand, statcache, tb, tzparse,  | ||||||
|  |     util, whatsound, whrandom, zmod | ||||||
|  | 
 | ||||||
|  | - The following modules were removed:  regsub, reconvert, regex, regex_syntax. | ||||||
|  | 
 | ||||||
|  | - re and sre were swapped, so help(re) provides full help.  importing sre | ||||||
|   is deprecated.  The undocumented re.engine variable no longer exists. |   is deprecated.  The undocumented re.engine variable no longer exists. | ||||||
| 
 | 
 | ||||||
| - Bug #1448490: Fixed a bug that ISO-2022 codecs could not handle | - Bug #1448490: Fixed a bug that ISO-2022 codecs could not handle | ||||||
|  |  | ||||||
|  | @ -1956,8 +1956,6 @@ quopri           Conversions to/from quoted-printable transport encoding. | ||||||
| rand             Don't use unless you want compatibility with C's rand(). | rand             Don't use unless you want compatibility with C's rand(). | ||||||
| random           Random variable generators | random           Random variable generators | ||||||
| re               Regular Expressions. | re               Regular Expressions. | ||||||
| reconvert        Convert old ("regex") regular expressions to new syntax |  | ||||||
|                  ("re"). |  | ||||||
| repr             Redo repr() but with limits on most sizes. | repr             Redo repr() but with limits on most sizes. | ||||||
| rexec            Restricted execution facilities ("safe" exec, eval, etc). | rexec            Restricted execution facilities ("safe" exec, eval, etc). | ||||||
| rfc822           RFC-822 message manipulation class. | rfc822           RFC-822 message manipulation class. | ||||||
|  | @ -2035,7 +2033,6 @@ zipfile          Read & write PK zipped files. | ||||||
|             array               Obj efficiently representing arrays of basic values |             array               Obj efficiently representing arrays of basic values | ||||||
|             math                Math functions of C standard |             math                Math functions of C standard | ||||||
|             time                Time-related functions (also the newer datetime module) |             time                Time-related functions (also the newer datetime module) | ||||||
|             regex               Regular expression matching operations |  | ||||||
|             marshal             Read and write some python values in binary format |             marshal             Read and write some python values in binary format | ||||||
|             struct              Convert between python values and C structs |             struct              Convert between python values and C structs | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,690 +0,0 @@ | ||||||
| /*
 |  | ||||||
| XXX support range parameter on search |  | ||||||
| XXX support mstop parameter on search |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* Regular expression objects */ |  | ||||||
| /* This uses Tatu Ylonen's copyleft-free reimplementation of
 |  | ||||||
|    GNU regular expressions */ |  | ||||||
| 
 |  | ||||||
| #include "Python.h" |  | ||||||
| 
 |  | ||||||
| #include <ctype.h> |  | ||||||
| 
 |  | ||||||
| #include "regexpr.h" |  | ||||||
| 
 |  | ||||||
| static PyObject *RegexError;	/* Exception */	 |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
| 	PyObject_HEAD |  | ||||||
| 	struct re_pattern_buffer re_patbuf; /* The compiled expression */ |  | ||||||
| 	struct re_registers re_regs; /* The registers from the last match */ |  | ||||||
| 	char re_fastmap[256];	/* Storage for fastmap */ |  | ||||||
| 	PyObject *re_translate;	/* String object for translate table */ |  | ||||||
| 	PyObject *re_lastok;	/* String object last matched/searched */ |  | ||||||
| 	PyObject *re_groupindex;	/* Group name to index dictionary */ |  | ||||||
| 	PyObject *re_givenpat;	/* Pattern with symbolic groups */ |  | ||||||
| 	PyObject *re_realpat;	/* Pattern without symbolic groups */ |  | ||||||
| } regexobject; |  | ||||||
| 
 |  | ||||||
| /* Regex object methods */ |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| reg_dealloc(regexobject *re) |  | ||||||
| { |  | ||||||
| 	if (re->re_patbuf.buffer) |  | ||||||
| 		free(re->re_patbuf.buffer); |  | ||||||
| 	Py_XDECREF(re->re_translate); |  | ||||||
| 	Py_XDECREF(re->re_lastok); |  | ||||||
| 	Py_XDECREF(re->re_groupindex); |  | ||||||
| 	Py_XDECREF(re->re_givenpat); |  | ||||||
| 	Py_XDECREF(re->re_realpat); |  | ||||||
| 	PyObject_Del(re); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| makeresult(struct re_registers *regs) |  | ||||||
| { |  | ||||||
| 	PyObject *v; |  | ||||||
| 	int i; |  | ||||||
| 	static PyObject *filler = NULL; |  | ||||||
| 
 |  | ||||||
| 	if (filler == NULL) { |  | ||||||
| 		filler = Py_BuildValue("(ii)", -1, -1); |  | ||||||
| 		if (filler == NULL) |  | ||||||
| 			return NULL; |  | ||||||
| 	} |  | ||||||
| 	v = PyTuple_New(RE_NREGS); |  | ||||||
| 	if (v == NULL) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	for (i = 0; i < RE_NREGS; i++) { |  | ||||||
| 		int lo = regs->start[i]; |  | ||||||
| 		int hi = regs->end[i]; |  | ||||||
| 		PyObject *w; |  | ||||||
| 		if (lo == -1 && hi == -1) { |  | ||||||
| 			w = filler; |  | ||||||
| 			Py_INCREF(w); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 			w = Py_BuildValue("(ii)", lo, hi); |  | ||||||
| 		if (w == NULL || PyTuple_SetItem(v, i, w) < 0) { |  | ||||||
| 			Py_DECREF(v); |  | ||||||
| 			return NULL; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return v; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regobj_match(regexobject *re, PyObject *args) |  | ||||||
| { |  | ||||||
| 	PyObject *argstring; |  | ||||||
| 	char *buffer; |  | ||||||
| 	int size; |  | ||||||
| 	int offset = 0; |  | ||||||
| 	int result; |  | ||||||
| 
 |  | ||||||
| 	if (!PyArg_ParseTuple(args, "O|i:match", &argstring, &offset)) |  | ||||||
| 		return NULL; |  | ||||||
| 	if (!PyArg_Parse(argstring, "t#", &buffer, &size)) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	if (offset < 0 || offset > size) { |  | ||||||
| 		PyErr_SetString(RegexError, "match offset out of range"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	Py_XDECREF(re->re_lastok); |  | ||||||
| 	re->re_lastok = NULL; |  | ||||||
| 	result = _Py_re_match(&re->re_patbuf, (unsigned char *)buffer, size, offset, |  | ||||||
| 			      &re->re_regs); |  | ||||||
| 	if (result < -1) { |  | ||||||
| 		/* Serious failure of some sort; if re_match didn't 
 |  | ||||||
| 		   set an exception, raise a generic error */ |  | ||||||
| 	        if (!PyErr_Occurred()) |  | ||||||
| 		        PyErr_SetString(RegexError, "match failure"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	if (result >= 0) { |  | ||||||
| 		Py_INCREF(argstring); |  | ||||||
| 		re->re_lastok = argstring; |  | ||||||
| 	} |  | ||||||
| 	return PyInt_FromLong((long)result); /* Length of the match or -1 */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regobj_search(regexobject *re, PyObject *args) |  | ||||||
| { |  | ||||||
| 	PyObject *argstring; |  | ||||||
| 	char *buffer; |  | ||||||
| 	int size; |  | ||||||
| 	int offset = 0; |  | ||||||
| 	int range; |  | ||||||
| 	int result; |  | ||||||
| 	 |  | ||||||
| 	if (!PyArg_ParseTuple(args, "O|i:search", &argstring, &offset)) |  | ||||||
| 		return NULL; |  | ||||||
| 	if (!PyArg_Parse(argstring, "t#:search", &buffer, &size)) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	if (offset < 0 || offset > size) { |  | ||||||
| 		PyErr_SetString(RegexError, "search offset out of range"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	/* NB: In Emacs 18.57, the documentation for re_search[_2] and
 |  | ||||||
| 	   the implementation don't match: the documentation states that |  | ||||||
| 	   |range| positions are tried, while the code tries |range|+1 |  | ||||||
| 	   positions.  It seems more productive to believe the code! */ |  | ||||||
| 	range = size - offset; |  | ||||||
| 	Py_XDECREF(re->re_lastok); |  | ||||||
| 	re->re_lastok = NULL; |  | ||||||
| 	result = _Py_re_search(&re->re_patbuf, (unsigned char *)buffer, size, offset, range, |  | ||||||
| 			   &re->re_regs); |  | ||||||
| 	if (result < -1) { |  | ||||||
| 		/* Serious failure of some sort; if re_match didn't 
 |  | ||||||
| 		   set an exception, raise a generic error */ |  | ||||||
| 	        if (!PyErr_Occurred()) |  | ||||||
| 	  	        PyErr_SetString(RegexError, "match failure"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	if (result >= 0) { |  | ||||||
| 		Py_INCREF(argstring); |  | ||||||
| 		re->re_lastok = argstring; |  | ||||||
| 	} |  | ||||||
| 	return PyInt_FromLong((long)result); /* Position of the match or -1 */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* get the group from the regex where index can be a string (group name) or
 |  | ||||||
|    an integer index [0 .. 99] |  | ||||||
|  */ |  | ||||||
| static PyObject* |  | ||||||
| group_from_index(regexobject *re, PyObject *index) |  | ||||||
| { |  | ||||||
| 	int i, a, b; |  | ||||||
| 	char *v; |  | ||||||
| 
 |  | ||||||
| 	if (PyString_Check(index)) |  | ||||||
| 		if (re->re_groupindex == NULL || |  | ||||||
| 		    !(index = PyDict_GetItem(re->re_groupindex, index))) |  | ||||||
| 		{ |  | ||||||
| 			PyErr_SetString(RegexError, |  | ||||||
| 					"group() group name doesn't exist"); |  | ||||||
| 			return NULL; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 	i = PyInt_AsLong(index); |  | ||||||
| 	if (i == -1 && PyErr_Occurred()) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	if (i < 0 || i >= RE_NREGS) { |  | ||||||
| 		PyErr_SetString(RegexError, "group() index out of range"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	if (re->re_lastok == NULL) { |  | ||||||
| 		PyErr_SetString(RegexError, |  | ||||||
| 			   "group() only valid after successful match/search"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	a = re->re_regs.start[i]; |  | ||||||
| 	b = re->re_regs.end[i]; |  | ||||||
| 	if (a < 0 || b < 0) { |  | ||||||
| 		Py_INCREF(Py_None); |  | ||||||
| 		return Py_None; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	if (!(v = PyString_AsString(re->re_lastok))) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	return PyString_FromStringAndSize(v+a, b-a); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regobj_group(regexobject *re, PyObject *args) |  | ||||||
| { |  | ||||||
| 	int n = PyTuple_Size(args); |  | ||||||
| 	int i; |  | ||||||
| 	PyObject *res = NULL; |  | ||||||
| 
 |  | ||||||
| 	if (n < 0) |  | ||||||
| 		return NULL; |  | ||||||
| 	if (n == 0) { |  | ||||||
| 		PyErr_SetString(PyExc_TypeError, "not enough arguments"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	if (n == 1) { |  | ||||||
| 		/* return value is a single string */ |  | ||||||
| 		PyObject *index = PyTuple_GetItem(args, 0); |  | ||||||
| 		if (!index) |  | ||||||
| 			return NULL; |  | ||||||
| 		 |  | ||||||
| 		return group_from_index(re, index); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* return value is a tuple */ |  | ||||||
| 	if (!(res = PyTuple_New(n))) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	for (i = 0; i < n; i++) { |  | ||||||
| 		PyObject *index = PyTuple_GetItem(args, i); |  | ||||||
| 		PyObject *group = NULL; |  | ||||||
| 
 |  | ||||||
| 		if (!index) |  | ||||||
| 			goto finally; |  | ||||||
| 		if (!(group = group_from_index(re, index))) |  | ||||||
| 			goto finally; |  | ||||||
| 		if (PyTuple_SetItem(res, i, group) < 0) |  | ||||||
| 			goto finally; |  | ||||||
| 	} |  | ||||||
| 	return res; |  | ||||||
| 
 |  | ||||||
|   finally: |  | ||||||
| 	Py_DECREF(res); |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static struct PyMethodDef reg_methods[] = { |  | ||||||
| 	{"match",	(PyCFunction)regobj_match, METH_VARARGS}, |  | ||||||
| 	{"search",	(PyCFunction)regobj_search, METH_VARARGS}, |  | ||||||
| 	{"group",	(PyCFunction)regobj_group, METH_VARARGS}, |  | ||||||
| 	{NULL,		NULL}		/* sentinel */ |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
| static char* members[] = { |  | ||||||
| 	"last", "regs", "translate", |  | ||||||
| 	"groupindex", "realpat", "givenpat", |  | ||||||
| 	NULL |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regobj_getattr(regexobject *re, char *name) |  | ||||||
| { |  | ||||||
| 	if (strcmp(name, "regs") == 0) { |  | ||||||
| 		if (re->re_lastok == NULL) { |  | ||||||
| 			Py_INCREF(Py_None); |  | ||||||
| 			return Py_None; |  | ||||||
| 		} |  | ||||||
| 		return makeresult(&re->re_regs); |  | ||||||
| 	} |  | ||||||
| 	if (strcmp(name, "last") == 0) { |  | ||||||
| 		if (re->re_lastok == NULL) { |  | ||||||
| 			Py_INCREF(Py_None); |  | ||||||
| 			return Py_None; |  | ||||||
| 		} |  | ||||||
| 		Py_INCREF(re->re_lastok); |  | ||||||
| 		return re->re_lastok; |  | ||||||
| 	} |  | ||||||
| 	if (strcmp(name, "translate") == 0) { |  | ||||||
| 		if (re->re_translate == NULL) { |  | ||||||
| 			Py_INCREF(Py_None); |  | ||||||
| 			return Py_None; |  | ||||||
| 		} |  | ||||||
| 		Py_INCREF(re->re_translate); |  | ||||||
| 		return re->re_translate; |  | ||||||
| 	} |  | ||||||
| 	if (strcmp(name, "groupindex") == 0) { |  | ||||||
| 		if (re->re_groupindex == NULL) { |  | ||||||
| 			Py_INCREF(Py_None); |  | ||||||
| 			return Py_None; |  | ||||||
| 		} |  | ||||||
| 		Py_INCREF(re->re_groupindex); |  | ||||||
| 		return re->re_groupindex; |  | ||||||
| 	} |  | ||||||
| 	if (strcmp(name, "realpat") == 0) { |  | ||||||
| 		if (re->re_realpat == NULL) { |  | ||||||
| 			Py_INCREF(Py_None); |  | ||||||
| 			return Py_None; |  | ||||||
| 		} |  | ||||||
| 		Py_INCREF(re->re_realpat); |  | ||||||
| 		return re->re_realpat; |  | ||||||
| 	} |  | ||||||
| 	if (strcmp(name, "givenpat") == 0) { |  | ||||||
| 		if (re->re_givenpat == NULL) { |  | ||||||
| 			Py_INCREF(Py_None); |  | ||||||
| 			return Py_None; |  | ||||||
| 		} |  | ||||||
| 		Py_INCREF(re->re_givenpat); |  | ||||||
| 		return re->re_givenpat; |  | ||||||
| 	} |  | ||||||
| 	if (strcmp(name, "__members__") == 0) { |  | ||||||
| 		int i = 0; |  | ||||||
| 		PyObject *list = NULL; |  | ||||||
| 
 |  | ||||||
| 		/* okay, so it's unlikely this list will change that often.
 |  | ||||||
| 		   still, it's easier to change it in just one place. |  | ||||||
| 		 */ |  | ||||||
| 		while (members[i]) |  | ||||||
| 			i++; |  | ||||||
| 		if (!(list = PyList_New(i))) |  | ||||||
| 			return NULL; |  | ||||||
| 
 |  | ||||||
| 		i = 0; |  | ||||||
| 		while (members[i]) { |  | ||||||
| 			PyObject* v = PyString_FromString(members[i]); |  | ||||||
| 			if (!v || PyList_SetItem(list, i, v) < 0) { |  | ||||||
| 				Py_DECREF(list); |  | ||||||
| 				return NULL; |  | ||||||
| 			} |  | ||||||
| 			i++; |  | ||||||
| 		} |  | ||||||
| 		return list; |  | ||||||
| 	} |  | ||||||
| 	return Py_FindMethod(reg_methods, (PyObject *)re, name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyTypeObject Regextype = { |  | ||||||
| 	PyObject_HEAD_INIT(NULL) |  | ||||||
| 	0,				     /*ob_size*/ |  | ||||||
| 	"regex.regex",			     /*tp_name*/ |  | ||||||
| 	sizeof(regexobject),		     /*tp_size*/ |  | ||||||
| 	0,				     /*tp_itemsize*/ |  | ||||||
| 	/* methods */ |  | ||||||
| 	(destructor)reg_dealloc,	     /*tp_dealloc*/ |  | ||||||
| 	0,				     /*tp_print*/ |  | ||||||
| 	(getattrfunc)regobj_getattr,	     /*tp_getattr*/ |  | ||||||
| 	0,				     /*tp_setattr*/ |  | ||||||
| 	0,				     /*tp_compare*/ |  | ||||||
| 	0,				     /*tp_repr*/ |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /* reference counting invariants:
 |  | ||||||
|    pattern: borrowed |  | ||||||
|    translate: borrowed |  | ||||||
|    givenpat: borrowed |  | ||||||
|    groupindex: transferred |  | ||||||
| */ |  | ||||||
| static PyObject * |  | ||||||
| newregexobject(PyObject *pattern, PyObject *translate, PyObject *givenpat, PyObject *groupindex) |  | ||||||
| { |  | ||||||
| 	regexobject *re; |  | ||||||
| 	char *pat; |  | ||||||
| 	int size; |  | ||||||
| 
 |  | ||||||
| 	if (!PyArg_Parse(pattern, "t#", &pat, &size)) |  | ||||||
| 		return NULL; |  | ||||||
| 	 |  | ||||||
| 	if (translate != NULL && PyString_Size(translate) != 256) { |  | ||||||
| 		PyErr_SetString(RegexError, |  | ||||||
| 				"translation table must be 256 bytes"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	re = PyObject_New(regexobject, &Regextype); |  | ||||||
| 	if (re != NULL) { |  | ||||||
| 		char *error; |  | ||||||
| 		re->re_patbuf.buffer = NULL; |  | ||||||
| 		re->re_patbuf.allocated = 0; |  | ||||||
| 		re->re_patbuf.fastmap = (unsigned char *)re->re_fastmap; |  | ||||||
| 		if (translate) { |  | ||||||
| 			re->re_patbuf.translate = (unsigned char *)PyString_AsString(translate); |  | ||||||
| 			if (!re->re_patbuf.translate) |  | ||||||
| 				goto finally; |  | ||||||
| 			Py_INCREF(translate); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 			re->re_patbuf.translate = NULL; |  | ||||||
| 		re->re_translate = translate; |  | ||||||
| 		re->re_lastok = NULL; |  | ||||||
| 		re->re_groupindex = groupindex; |  | ||||||
| 		Py_INCREF(pattern); |  | ||||||
| 		re->re_realpat = pattern; |  | ||||||
| 		Py_INCREF(givenpat); |  | ||||||
| 		re->re_givenpat = givenpat; |  | ||||||
| 		error = _Py_re_compile_pattern((unsigned char *)pat, size, &re->re_patbuf); |  | ||||||
| 		if (error != NULL) { |  | ||||||
| 			PyErr_SetString(RegexError, error); |  | ||||||
| 			goto finally; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return (PyObject *)re; |  | ||||||
|   finally: |  | ||||||
| 	Py_DECREF(re); |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regex_compile(PyObject *self, PyObject *args) |  | ||||||
| { |  | ||||||
| 	PyObject *pat = NULL; |  | ||||||
| 	PyObject *tran = NULL; |  | ||||||
| 
 |  | ||||||
| 	if (!PyArg_ParseTuple(args, "S|S:compile", &pat, &tran)) |  | ||||||
| 		return NULL; |  | ||||||
| 	return newregexobject(pat, tran, pat, NULL); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| symcomp(PyObject *pattern, PyObject *gdict) |  | ||||||
| { |  | ||||||
| 	char *opat, *oend, *o, *n, *g, *v; |  | ||||||
| 	int group_count = 0; |  | ||||||
| 	int sz; |  | ||||||
| 	int escaped = 0; |  | ||||||
| 	char name_buf[128]; |  | ||||||
| 	PyObject *npattern; |  | ||||||
| 	int require_escape = re_syntax & RE_NO_BK_PARENS ? 0 : 1; |  | ||||||
| 
 |  | ||||||
| 	if (!(opat = PyString_AsString(pattern))) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	if ((sz = PyString_Size(pattern)) < 0) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	oend = opat + sz; |  | ||||||
| 	o = opat; |  | ||||||
| 
 |  | ||||||
| 	if (oend == opat) { |  | ||||||
| 		Py_INCREF(pattern); |  | ||||||
| 		return pattern; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!(npattern = PyString_FromStringAndSize((char*)NULL, sz)) || |  | ||||||
| 	    !(n = PyString_AsString(npattern))) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	while (o < oend) { |  | ||||||
| 		if (*o == '(' && escaped == require_escape) { |  | ||||||
| 			char *backtrack; |  | ||||||
| 			escaped = 0; |  | ||||||
| 			++group_count; |  | ||||||
| 			*n++ = *o; |  | ||||||
| 			if (++o >= oend || *o != '<') |  | ||||||
| 				continue; |  | ||||||
| 			/* *o == '<' */ |  | ||||||
| 			if (o+1 < oend && *(o+1) == '>') |  | ||||||
| 				continue; |  | ||||||
| 			backtrack = o; |  | ||||||
| 			g = name_buf; |  | ||||||
| 			for (++o; o < oend;) { |  | ||||||
| 				if (*o == '>') { |  | ||||||
| 				    PyObject *group_name = NULL; |  | ||||||
| 				    PyObject *group_index = NULL; |  | ||||||
| 				    *g++ = '\0'; |  | ||||||
| 				    group_name = PyString_FromString(name_buf); |  | ||||||
| 				    group_index = PyInt_FromLong(group_count); |  | ||||||
| 				    if (group_name == NULL || |  | ||||||
| 					group_index == NULL || |  | ||||||
| 					PyDict_SetItem(gdict, group_name, |  | ||||||
| 						       group_index) != 0) |  | ||||||
| 				    { |  | ||||||
| 					    Py_XDECREF(group_name); |  | ||||||
| 					    Py_XDECREF(group_index); |  | ||||||
| 					    Py_XDECREF(npattern); |  | ||||||
| 					    return NULL; |  | ||||||
| 				    } |  | ||||||
| 				    Py_DECREF(group_name); |  | ||||||
| 				    Py_DECREF(group_index); |  | ||||||
| 				    ++o;     /* eat the '>' */ |  | ||||||
| 				    break; |  | ||||||
| 				} |  | ||||||
| 				if (!isalnum(Py_CHARMASK(*o)) && *o != '_') { |  | ||||||
| 					o = backtrack; |  | ||||||
| 					break; |  | ||||||
| 				} |  | ||||||
| 				*g++ = *o++; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		else if (*o == '[' && !escaped) { |  | ||||||
| 			*n++ = *o; |  | ||||||
| 			++o;		     /* eat the char following '[' */ |  | ||||||
| 			*n++ = *o; |  | ||||||
| 			while (o < oend && *o != ']') { |  | ||||||
| 				++o; |  | ||||||
| 				*n++ = *o; |  | ||||||
| 			} |  | ||||||
| 			if (o < oend) |  | ||||||
| 				++o; |  | ||||||
| 		} |  | ||||||
| 		else if (*o == '\\') { |  | ||||||
| 			escaped = 1; |  | ||||||
| 			*n++ = *o; |  | ||||||
| 			++o; |  | ||||||
| 		} |  | ||||||
| 		else { |  | ||||||
| 			escaped = 0; |  | ||||||
| 			*n++ = *o; |  | ||||||
| 			++o; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!(v = PyString_AsString(npattern))) { |  | ||||||
| 		Py_DECREF(npattern); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	/* _PyString_Resize() decrements npattern on failure */ |  | ||||||
| 	_PyString_Resize(&npattern, n - v); |  | ||||||
| 	return npattern; |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regex_symcomp(PyObject *self, PyObject *args) |  | ||||||
| { |  | ||||||
| 	PyObject *pattern; |  | ||||||
| 	PyObject *tran = NULL; |  | ||||||
| 	PyObject *gdict = NULL; |  | ||||||
| 	PyObject *npattern; |  | ||||||
| 	PyObject *retval = NULL; |  | ||||||
| 
 |  | ||||||
| 	if (!PyArg_ParseTuple(args, "S|S:symcomp", &pattern, &tran)) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	gdict = PyDict_New(); |  | ||||||
| 	if (gdict == NULL || (npattern = symcomp(pattern, gdict)) == NULL) { |  | ||||||
| 		Py_XDECREF(gdict); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	retval = newregexobject(npattern, tran, pattern, gdict); |  | ||||||
| 	Py_DECREF(npattern); |  | ||||||
| 	return retval; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static PyObject *cache_pat; |  | ||||||
| static PyObject *cache_prog; |  | ||||||
| 
 |  | ||||||
| static int |  | ||||||
| update_cache(PyObject *pat) |  | ||||||
| { |  | ||||||
| 	PyObject *tuple = PyTuple_Pack(1, pat); |  | ||||||
| 	int status = 0; |  | ||||||
| 
 |  | ||||||
| 	if (!tuple) |  | ||||||
| 		return -1; |  | ||||||
| 
 |  | ||||||
| 	if (pat != cache_pat) { |  | ||||||
| 		Py_XDECREF(cache_pat); |  | ||||||
| 		cache_pat = NULL; |  | ||||||
| 		Py_XDECREF(cache_prog); |  | ||||||
| 		cache_prog = regex_compile((PyObject *)NULL, tuple); |  | ||||||
| 		if (cache_prog == NULL) { |  | ||||||
| 			status = -1; |  | ||||||
| 			goto finally; |  | ||||||
| 		} |  | ||||||
| 		cache_pat = pat; |  | ||||||
| 		Py_INCREF(cache_pat); |  | ||||||
| 	} |  | ||||||
|   finally: |  | ||||||
| 	Py_DECREF(tuple); |  | ||||||
| 	return status; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regex_match(PyObject *self, PyObject *args) |  | ||||||
| { |  | ||||||
| 	PyObject *pat, *string; |  | ||||||
| 	PyObject *tuple, *v; |  | ||||||
| 
 |  | ||||||
| 	if (!PyArg_ParseTuple(args, "SS:match", &pat, &string)) |  | ||||||
| 		return NULL; |  | ||||||
| 	if (update_cache(pat) < 0) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	if (!(tuple = Py_BuildValue("(S)", string))) |  | ||||||
| 		return NULL; |  | ||||||
| 	v = regobj_match((regexobject *)cache_prog, tuple); |  | ||||||
| 	Py_DECREF(tuple); |  | ||||||
| 	return v; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regex_search(PyObject *self, PyObject *args) |  | ||||||
| { |  | ||||||
| 	PyObject *pat, *string; |  | ||||||
| 	PyObject *tuple, *v; |  | ||||||
| 
 |  | ||||||
| 	if (!PyArg_ParseTuple(args, "SS:search", &pat, &string)) |  | ||||||
| 		return NULL; |  | ||||||
| 	if (update_cache(pat) < 0) |  | ||||||
| 		return NULL; |  | ||||||
| 
 |  | ||||||
| 	if (!(tuple = Py_BuildValue("(S)", string))) |  | ||||||
| 		return NULL; |  | ||||||
| 	v = regobj_search((regexobject *)cache_prog, tuple); |  | ||||||
| 	Py_DECREF(tuple); |  | ||||||
| 	return v; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regex_set_syntax(PyObject *self, PyObject *args) |  | ||||||
| { |  | ||||||
| 	int syntax; |  | ||||||
| 	if (!PyArg_ParseTuple(args, "i:set_syntax", &syntax)) |  | ||||||
| 		return NULL; |  | ||||||
| 	syntax = re_set_syntax(syntax); |  | ||||||
| 	/* wipe the global pattern cache */ |  | ||||||
| 	Py_XDECREF(cache_pat); |  | ||||||
| 	cache_pat = NULL; |  | ||||||
| 	Py_XDECREF(cache_prog); |  | ||||||
| 	cache_prog = NULL; |  | ||||||
| 	return PyInt_FromLong((long)syntax); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| regex_get_syntax(PyObject *self) |  | ||||||
| { |  | ||||||
| 	return PyInt_FromLong((long)re_syntax); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static struct PyMethodDef regex_global_methods[] = { |  | ||||||
| 	{"compile",	regex_compile, METH_VARARGS}, |  | ||||||
| 	{"symcomp",	regex_symcomp, METH_VARARGS}, |  | ||||||
| 	{"match",	regex_match, METH_VARARGS}, |  | ||||||
| 	{"search",	regex_search, METH_VARARGS}, |  | ||||||
| 	{"set_syntax",	regex_set_syntax, METH_VARARGS}, |  | ||||||
| 	{"get_syntax",  (PyCFunction)regex_get_syntax, METH_NOARGS}, |  | ||||||
| 	{NULL,		NULL}		     /* sentinel */ |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| PyMODINIT_FUNC |  | ||||||
| initregex(void) |  | ||||||
| { |  | ||||||
| 	PyObject *m, *d, *v; |  | ||||||
| 	int i; |  | ||||||
| 	char *s; |  | ||||||
| 	 |  | ||||||
| 	/* Initialize object type */ |  | ||||||
| 	Regextype.ob_type = &PyType_Type; |  | ||||||
| 
 |  | ||||||
| 	m = Py_InitModule("regex", regex_global_methods); |  | ||||||
| 	if (m == NULL) |  | ||||||
| 		return; |  | ||||||
| 	d = PyModule_GetDict(m); |  | ||||||
| 
 |  | ||||||
| 	if (PyErr_Warn(PyExc_DeprecationWarning, |  | ||||||
| 		       "the regex module is deprecated; " |  | ||||||
| 		       "please use the re module") < 0) |  | ||||||
| 		return; |  | ||||||
| 	 |  | ||||||
| 	/* Initialize regex.error exception */ |  | ||||||
| 	v = RegexError = PyErr_NewException("regex.error", NULL, NULL); |  | ||||||
| 	if (v == NULL || PyDict_SetItemString(d, "error", v) != 0) |  | ||||||
| 		goto finally; |  | ||||||
| 	 |  | ||||||
| 	/* Initialize regex.casefold constant */ |  | ||||||
| 	if (!(v = PyString_FromStringAndSize((char *)NULL, 256))) |  | ||||||
| 		goto finally; |  | ||||||
| 	 |  | ||||||
| 	if (!(s = PyString_AsString(v))) |  | ||||||
| 		goto finally; |  | ||||||
| 
 |  | ||||||
| 	for (i = 0; i < 256; i++) { |  | ||||||
| 		if (isupper(i)) |  | ||||||
| 			s[i] = tolower(i); |  | ||||||
| 		else |  | ||||||
| 			s[i] = i; |  | ||||||
| 	} |  | ||||||
| 	if (PyDict_SetItemString(d, "casefold", v) < 0) |  | ||||||
| 		goto finally; |  | ||||||
| 	Py_DECREF(v); |  | ||||||
| 
 |  | ||||||
| 	if (!PyErr_Occurred()) |  | ||||||
| 		return; |  | ||||||
|   finally: |  | ||||||
| 	/* Nothing */ ; |  | ||||||
| } |  | ||||||
							
								
								
									
										2094
									
								
								Modules/regexpr.c
									
										
									
									
									
								
							
							
						
						
									
										2094
									
								
								Modules/regexpr.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,155 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * -*- mode: c-mode; c-file-style: python -*- |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #ifndef Py_REGEXPR_H |  | ||||||
| #define Py_REGEXPR_H |  | ||||||
| #ifdef __cplusplus |  | ||||||
| extern "C" { |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * regexpr.h |  | ||||||
|  * |  | ||||||
|  * Author: Tatu Ylonen <ylo@ngs.fi> |  | ||||||
|  * |  | ||||||
|  * Copyright (c) 1991 Tatu Ylonen, Espoo, Finland |  | ||||||
|  * |  | ||||||
|  * Permission to use, copy, modify, distribute, and sell this software |  | ||||||
|  * and its documentation for any purpose is hereby granted without fee, |  | ||||||
|  * provided that the above copyright notice appear in all copies.  This |  | ||||||
|  * software is provided "as is" without express or implied warranty. |  | ||||||
|  * |  | ||||||
|  * Created: Thu Sep 26 17:15:36 1991 ylo |  | ||||||
|  * Last modified: Mon Nov  4 15:49:46 1991 ylo |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| /* $Id$ */ |  | ||||||
| 
 |  | ||||||
| #ifndef REGEXPR_H |  | ||||||
| #define REGEXPR_H |  | ||||||
| 
 |  | ||||||
| #define RE_NREGS	100  /* number of registers available */ |  | ||||||
| 
 |  | ||||||
| typedef struct re_pattern_buffer |  | ||||||
| { |  | ||||||
| 	unsigned char *buffer;          /* compiled pattern */ |  | ||||||
| 	int allocated;         /* allocated size of compiled pattern */ |  | ||||||
| 	int used;              /* actual length of compiled pattern */ |  | ||||||
| 	unsigned char *fastmap;         /* fastmap[ch] is true if ch can start pattern */ |  | ||||||
| 	unsigned char *translate;       /* translation to apply during compilation/matching */ |  | ||||||
| 	unsigned char fastmap_accurate; /* true if fastmap is valid */ |  | ||||||
| 	unsigned char can_be_null;      /* true if can match empty string */ |  | ||||||
| 	unsigned char uses_registers;   /* registers are used and need to be initialized */ |  | ||||||
| 	int num_registers;     /* number of registers used */ |  | ||||||
| 	unsigned char anchor;           /* anchor: 0=none 1=begline 2=begbuf */ |  | ||||||
| } *regexp_t; |  | ||||||
| 
 |  | ||||||
| typedef struct re_registers |  | ||||||
| { |  | ||||||
| 	int start[RE_NREGS];  /* start offset of region */ |  | ||||||
| 	int end[RE_NREGS];    /* end offset of region */ |  | ||||||
| } *regexp_registers_t; |  | ||||||
| 
 |  | ||||||
| /* bit definitions for syntax */ |  | ||||||
| #define RE_NO_BK_PARENS		1    /* no quoting for parentheses */ |  | ||||||
| #define RE_NO_BK_VBAR		2    /* no quoting for vertical bar */ |  | ||||||
| #define RE_BK_PLUS_QM		4    /* quoting needed for + and ? */ |  | ||||||
| #define RE_TIGHT_VBAR		8    /* | binds tighter than ^ and $ */ |  | ||||||
| #define RE_NEWLINE_OR		16   /* treat newline as or */ |  | ||||||
| #define RE_CONTEXT_INDEP_OPS	32   /* ^$?*+ are special in all contexts */ |  | ||||||
| #define RE_ANSI_HEX		64   /* ansi sequences (\n etc) and \xhh */ |  | ||||||
| #define RE_NO_GNU_EXTENSIONS   128   /* no gnu extensions */ |  | ||||||
| 
 |  | ||||||
| /* definitions for some common regexp styles */ |  | ||||||
| #define RE_SYNTAX_AWK	(RE_NO_BK_PARENS|RE_NO_BK_VBAR|RE_CONTEXT_INDEP_OPS) |  | ||||||
| #define RE_SYNTAX_EGREP	(RE_SYNTAX_AWK|RE_NEWLINE_OR) |  | ||||||
| #define RE_SYNTAX_GREP	(RE_BK_PLUS_QM|RE_NEWLINE_OR) |  | ||||||
| #define RE_SYNTAX_EMACS	0 |  | ||||||
| 
 |  | ||||||
| #define Sword       1 |  | ||||||
| #define Swhitespace 2 |  | ||||||
| #define Sdigit      4 |  | ||||||
| #define Soctaldigit 8 |  | ||||||
| #define Shexdigit   16 |  | ||||||
| 
 |  | ||||||
| /* Rename all exported symbols to avoid conflicts with similarly named
 |  | ||||||
|    symbols in some systems' standard C libraries... */ |  | ||||||
| 
 |  | ||||||
| #define re_syntax _Py_re_syntax |  | ||||||
| #define re_syntax_table _Py_re_syntax_table |  | ||||||
| #define re_compile_initialize _Py_re_compile_initialize |  | ||||||
| #define re_set_syntax _Py_re_set_syntax |  | ||||||
| #define re_compile_pattern _Py_re_compile_pattern |  | ||||||
| #define re_match _Py_re_match |  | ||||||
| #define re_search _Py_re_search |  | ||||||
| #define re_compile_fastmap _Py_re_compile_fastmap |  | ||||||
| #define re_comp _Py_re_comp |  | ||||||
| #define re_exec _Py_re_exec |  | ||||||
| 
 |  | ||||||
| #ifdef HAVE_PROTOTYPES |  | ||||||
| 
 |  | ||||||
| extern int re_syntax; |  | ||||||
| /* This is the actual syntax mask.  It was added so that Python could do
 |  | ||||||
|  * syntax-dependent munging of patterns before compilation. */ |  | ||||||
| 
 |  | ||||||
| extern unsigned char re_syntax_table[256]; |  | ||||||
| 
 |  | ||||||
| void re_compile_initialize(void); |  | ||||||
| 
 |  | ||||||
| int re_set_syntax(int syntax); |  | ||||||
| /* This sets the syntax to use and returns the previous syntax.  The
 |  | ||||||
|  * syntax is specified by a bit mask of the above defined bits. */ |  | ||||||
| 
 |  | ||||||
| char *re_compile_pattern(unsigned char *regex, int regex_size, regexp_t compiled); |  | ||||||
| /* This compiles the regexp (given in regex and length in regex_size).
 |  | ||||||
|  * This returns NULL if the regexp compiled successfully, and an error |  | ||||||
|  * message if an error was encountered.  The buffer field must be |  | ||||||
|  * initialized to a memory area allocated by malloc (or to NULL) before |  | ||||||
|  * use, and the allocated field must be set to its length (or 0 if |  | ||||||
|  * buffer is NULL).  Also, the translate field must be set to point to a |  | ||||||
|  * valid translation table, or NULL if it is not used. */ |  | ||||||
| 
 |  | ||||||
| int re_match(regexp_t compiled, unsigned char *string, int size, int pos, |  | ||||||
| 	     regexp_registers_t old_regs); |  | ||||||
| /* This tries to match the regexp against the string.  This returns the
 |  | ||||||
|  * length of the matched portion, or -1 if the pattern could not be |  | ||||||
|  * matched and -2 if an error (such as failure stack overflow) is |  | ||||||
|  * encountered. */ |  | ||||||
| 
 |  | ||||||
| int re_search(regexp_t compiled, unsigned char *string, int size, int startpos, |  | ||||||
| 	      int range, regexp_registers_t regs); |  | ||||||
| /* This searches for a substring matching the regexp.  This returns the
 |  | ||||||
|  * first index at which a match is found.  range specifies at how many |  | ||||||
|  * positions to try matching; positive values indicate searching |  | ||||||
|  * forwards, and negative values indicate searching backwards.  mstop |  | ||||||
|  * specifies the offset beyond which a match must not go.  This returns |  | ||||||
|  * -1 if no match is found, and -2 if an error (such as failure stack |  | ||||||
|  * overflow) is encountered. */ |  | ||||||
| 
 |  | ||||||
| void re_compile_fastmap(regexp_t compiled); |  | ||||||
| /* This computes the fastmap for the regexp.  For this to have any effect,
 |  | ||||||
|  * the calling program must have initialized the fastmap field to point |  | ||||||
|  * to an array of 256 characters. */ |  | ||||||
| 
 |  | ||||||
| #else /* HAVE_PROTOTYPES */ |  | ||||||
| 
 |  | ||||||
| extern int re_syntax; |  | ||||||
| extern unsigned char re_syntax_table[256]; |  | ||||||
| void re_compile_initialize(); |  | ||||||
| int re_set_syntax(); |  | ||||||
| char *re_compile_pattern(); |  | ||||||
| int re_match(); |  | ||||||
| int re_search(); |  | ||||||
| void re_compile_fastmap(); |  | ||||||
| 
 |  | ||||||
| #endif /* HAVE_PROTOTYPES */ |  | ||||||
| 
 |  | ||||||
| #endif /* REGEXPR_H */ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #ifdef __cplusplus |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| #endif /* !Py_REGEXPR_H */ |  | ||||||
|  | @ -535,14 +535,6 @@ SOURCE=..\..\Objects\rangeobject.c | ||||||
| # End Source File | # End Source File | ||||||
| # Begin Source File | # Begin Source File | ||||||
| 
 | 
 | ||||||
| SOURCE=..\..\Modules\regexmodule.c |  | ||||||
| # End Source File |  | ||||||
| # Begin Source File |  | ||||||
| 
 |  | ||||||
| SOURCE=..\..\Modules\regexpr.c |  | ||||||
| # End Source File |  | ||||||
| # Begin Source File |  | ||||||
| 
 |  | ||||||
| SOURCE=..\..\Modules\rgbimgmodule.c | SOURCE=..\..\Modules\rgbimgmodule.c | ||||||
| # End Source File | # End Source File | ||||||
| # Begin Source File | # Begin Source File | ||||||
|  |  | ||||||
|  | @ -304,8 +304,6 @@ SRC.MODULES=	$(addprefix $(TOP), \ | ||||||
| 		Modules/md5module.c \
 | 		Modules/md5module.c \
 | ||||||
| 		Modules/operator.c \
 | 		Modules/operator.c \
 | ||||||
| 		Modules/_randommodule.c \
 | 		Modules/_randommodule.c \
 | ||||||
| 		Modules/regexmodule.c \
 |  | ||||||
| 		Modules/regexpr.c \
 |  | ||||||
| 		Modules/rgbimgmodule.c \
 | 		Modules/rgbimgmodule.c \
 | ||||||
| 		Modules/shamodule.c \
 | 		Modules/shamodule.c \
 | ||||||
| 		Modules/_sre.c \
 | 		Modules/_sre.c \
 | ||||||
|  |  | ||||||
|  | @ -948,34 +948,6 @@ readline.obj: $(PY_INCLUDE)\abstract.h $(PY_INCLUDE)\ceval.h $(PY_INCLUDE)\class | ||||||
| 	 $(PY_INCLUDE)\sliceobject.h $(PY_INCLUDE)\stringobject.h \
 | 	 $(PY_INCLUDE)\sliceobject.h $(PY_INCLUDE)\stringobject.h \
 | ||||||
| 	 $(PY_INCLUDE)\sysmodule.h $(PY_INCLUDE)\traceback.h $(PY_INCLUDE)\tupleobject.h | 	 $(PY_INCLUDE)\sysmodule.h $(PY_INCLUDE)\traceback.h $(PY_INCLUDE)\tupleobject.h | ||||||
| 
 | 
 | ||||||
| regexmodule.obj: $(PY_INCLUDE)\abstract.h $(PY_INCLUDE)\ceval.h \ |  | ||||||
| 	 $(PY_INCLUDE)\classobject.h $(PY_INCLUDE)\cobject.h $(PY_INCLUDE)\complexobject.h \
 |  | ||||||
| 	 pyconfig.h $(PY_INCLUDE)\dictobject.h $(PY_INCLUDE)\fileobject.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\floatobject.h $(PY_INCLUDE)\funcobject.h $(PY_INCLUDE)\import.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\intobject.h $(PY_INCLUDE)\intrcheck.h $(PY_INCLUDE)\listobject.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\longobject.h $(PY_INCLUDE)\methodobject.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\modsupport.h $(PY_INCLUDE)\moduleobject.h $(PY_INCLUDE)\mymalloc.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\myproto.h $(PY_INCLUDE)\object.h $(PY_INCLUDE)\objimpl.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\pydebug.h $(PY_INCLUDE)\pyerrors.h $(PY_INCLUDE)\pyfpe.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\pystate.h $(PY_INCLUDE)\python.h $(PY_INCLUDE)\pythonrun.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\rangeobject.h $(PY_MODULES)\regexpr.h $(PY_INCLUDE)\sliceobject.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\stringobject.h $(PY_INCLUDE)\sysmodule.h $(PY_INCLUDE)\traceback.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\tupleobject.h |  | ||||||
| 
 |  | ||||||
| regexpr.obj: $(PY_INCLUDE)\abstract.h $(PY_INCLUDE)\ceval.h \ |  | ||||||
| 	 $(PY_INCLUDE)\classobject.h $(PY_INCLUDE)\cobject.h $(PY_INCLUDE)\complexobject.h \
 |  | ||||||
| 	 pyconfig.h $(PY_INCLUDE)\dictobject.h $(PY_INCLUDE)\fileobject.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\floatobject.h $(PY_INCLUDE)\funcobject.h $(PY_INCLUDE)\import.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\intobject.h $(PY_INCLUDE)\intrcheck.h $(PY_INCLUDE)\listobject.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\longobject.h $(PY_INCLUDE)\methodobject.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\modsupport.h $(PY_INCLUDE)\moduleobject.h $(PY_INCLUDE)\mymalloc.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\myproto.h $(PY_INCLUDE)\object.h $(PY_INCLUDE)\objimpl.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\pydebug.h $(PY_INCLUDE)\pyerrors.h $(PY_INCLUDE)\pyfpe.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\pystate.h $(PY_INCLUDE)\python.h $(PY_INCLUDE)\pythonrun.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\rangeobject.h $(PY_MODULES)\regexpr.h $(PY_INCLUDE)\sliceobject.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\stringobject.h $(PY_INCLUDE)\sysmodule.h $(PY_INCLUDE)\traceback.h \
 |  | ||||||
| 	 $(PY_INCLUDE)\tupleobject.h |  | ||||||
| 
 |  | ||||||
| resource.obj: $(PY_INCLUDE)\abstract.h $(OS2TCPIP)\Include\sys\time.h $(PY_INCLUDE)\ceval.h \ | resource.obj: $(PY_INCLUDE)\abstract.h $(OS2TCPIP)\Include\sys\time.h $(PY_INCLUDE)\ceval.h \ | ||||||
| 	 $(PY_INCLUDE)\classobject.h $(PY_INCLUDE)\cobject.h $(PY_INCLUDE)\complexobject.h \
 | 	 $(PY_INCLUDE)\classobject.h $(PY_INCLUDE)\cobject.h $(PY_INCLUDE)\complexobject.h \
 | ||||||
| 	 pyconfig.h $(PY_INCLUDE)\dictobject.h $(PY_INCLUDE)\fileobject.h \
 | 	 pyconfig.h $(PY_INCLUDE)\dictobject.h $(PY_INCLUDE)\fileobject.h \
 | ||||||
|  |  | ||||||
|  | @ -699,30 +699,6 @@ readline.obj: abstract.h ceval.h classobject.h cobject.h complexobject.h \ | ||||||
| 	 pythonrun.h rangeobject.h sliceobject.h stringobject.h sysmodule.h \ | 	 pythonrun.h rangeobject.h sliceobject.h stringobject.h sysmodule.h \ | ||||||
| 	 traceback.h tupleobject.h | 	 traceback.h tupleobject.h | ||||||
| 
 | 
 | ||||||
| regexmodule.obj: abstract.h ceval.h classobject.h cobject.h complexobject.h \ |  | ||||||
| 	 pyconfig.h dictobject.h fileobject.h floatobject.h funcobject.h \ |  | ||||||
| 	 import.h intobject.h intrcheck.h listobject.h longobject.h \ |  | ||||||
| 	 methodobject.h modsupport.h moduleobject.h mymalloc.h myproto.h \ |  | ||||||
| 	 object.h objimpl.h pydebug.h pyerrors.h pyfpe.h pystate.h python.h \ |  | ||||||
| 	 pythonrun.h rangeobject.h regexpr.h sliceobject.h stringobject.h \ |  | ||||||
| 	 sysmodule.h traceback.h tupleobject.h |  | ||||||
| 
 |  | ||||||
| regexpr.obj: abstract.h ceval.h classobject.h cobject.h \ |  | ||||||
| 	 complexobject.h pyconfig.h dictobject.h fileobject.h floatobject.h \ |  | ||||||
| 	 funcobject.h import.h intobject.h intrcheck.h listobject.h \ |  | ||||||
| 	 longobject.h methodobject.h modsupport.h moduleobject.h mymalloc.h \ |  | ||||||
| 	 myproto.h object.h objimpl.h pydebug.h pyerrors.h pyfpe.h \ |  | ||||||
| 	 pystate.h python.h pythonrun.h rangeobject.h regexpr.h \ |  | ||||||
| 	 sliceobject.h stringobject.h sysmodule.h traceback.h tupleobject.h |  | ||||||
| 
 |  | ||||||
| reopmodule.obj: abstract.h ceval.h classobject.h cobject.h complexobject.h \ |  | ||||||
| 	 pyconfig.h dictobject.h fileobject.h floatobject.h funcobject.h \ |  | ||||||
| 	 import.h intobject.h intrcheck.h listobject.h longobject.h \ |  | ||||||
| 	 methodobject.h modsupport.h moduleobject.h mymalloc.h myproto.h \ |  | ||||||
| 	 object.h objimpl.h pydebug.h pyerrors.h pyfpe.h pystate.h python.h \ |  | ||||||
| 	 pythonrun.h rangeobject.h regexpr.h sliceobject.h stringobject.h \ |  | ||||||
| 	 sysmodule.h traceback.h tupleobject.h |  | ||||||
| 
 |  | ||||||
| resource.obj: abstract.h c:\mptn\include\sys\time.h ceval.h classobject.h \ | resource.obj: abstract.h c:\mptn\include\sys\time.h ceval.h classobject.h \ | ||||||
| 	 cobject.h complexobject.h pyconfig.h dictobject.h fileobject.h \ | 	 cobject.h complexobject.h pyconfig.h dictobject.h fileobject.h \ | ||||||
| 	 floatobject.h funcobject.h import.h intobject.h intrcheck.h \ | 	 floatobject.h funcobject.h import.h intobject.h intrcheck.h \ | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								PC/testpy.py
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								PC/testpy.py
									
										
									
									
									
								
							|  | @ -5,23 +5,23 @@ | ||||||
| # change this module too. | # change this module too. | ||||||
| 
 | 
 | ||||||
| try: | try: | ||||||
|     import string |     import os | ||||||
| except: | except: | ||||||
|     print """Could not import the standard "string" module. |     print """Could not import the standard "os" module. | ||||||
|   Please check your PYTHONPATH environment variable.""" |   Please check your PYTHONPATH environment variable.""" | ||||||
|     sys.exit(1) |     sys.exit(1) | ||||||
| 
 | 
 | ||||||
| try: | try: | ||||||
|     import regex_syntax |     import symbol | ||||||
| except: | except: | ||||||
|     print """Could not import the standard "regex_syntax" module.  If this is |     print """Could not import the standard "symbol" module.  If this is | ||||||
|   a PC, you should add the dos_8x3 directory to your PYTHONPATH.""" |   a PC, you should add the dos_8x3 directory to your PYTHONPATH.""" | ||||||
|     sys.exit(1) |     sys.exit(1) | ||||||
| 
 | 
 | ||||||
| import os | import os | ||||||
| 
 | 
 | ||||||
| for dir in sys.path: | for dir in sys.path: | ||||||
|     file = os.path.join(dir, "string.py") |     file = os.path.join(dir, "os.py") | ||||||
|     if os.path.isfile(file): |     if os.path.isfile(file): | ||||||
|         test = os.path.join(dir, "test") |         test = os.path.join(dir, "test") | ||||||
|         if os.path.isdir(test): |         if os.path.isdir(test): | ||||||
|  |  | ||||||
|  | @ -706,12 +706,6 @@ | ||||||
| 		<File | 		<File | ||||||
| 			RelativePath="..\Objects\rangeobject.c"> | 			RelativePath="..\Objects\rangeobject.c"> | ||||||
| 		</File> | 		</File> | ||||||
| 		<File |  | ||||||
| 			RelativePath="..\Modules\regexmodule.c"> |  | ||||||
| 		</File> |  | ||||||
| 		<File |  | ||||||
| 			RelativePath="..\Modules\regexpr.c"> |  | ||||||
| 		</File> |  | ||||||
| 		<File | 		<File | ||||||
| 			RelativePath="..\Modules\rgbimgmodule.c"> | 			RelativePath="..\Modules\rgbimgmodule.c"> | ||||||
| 		</File> | 		</File> | ||||||
|  |  | ||||||
|  | @ -74,7 +74,6 @@ MODULES_DYNAMIC =\ | ||||||
| 	@.^.Lib.md5/pyd\
 | 	@.^.Lib.md5/pyd\
 | ||||||
| 	@.^.Lib.operator/pyd\
 | 	@.^.Lib.operator/pyd\
 | ||||||
| 	@.^.Lib.parser/pyd\
 | 	@.^.Lib.parser/pyd\
 | ||||||
| 	@.^.Lib.regex/pyd\
 |  | ||||||
| 	@.^.Lib.rgbimg/pyd\
 | 	@.^.Lib.rgbimg/pyd\
 | ||||||
| 	@.^.Lib.sha/pyd\
 | 	@.^.Lib.sha/pyd\
 | ||||||
| 	@.^.Lib.signal/pyd\
 | 	@.^.Lib.signal/pyd\
 | ||||||
|  | @ -284,10 +283,6 @@ $(LIB_PYTHON):	$(OBJECTS) | ||||||
| @.^.Lib.parser/pyd: @.^.Modules.o.parsermodule s.linktab | @.^.Lib.parser/pyd: @.^.Modules.o.parsermodule s.linktab | ||||||
| 	$(MAKEDLK) -d @.^.Lib.parser/pyd -s s.linktab -o @.^.Modules.o.parsermodule -e initparser | 	$(MAKEDLK) -d @.^.Lib.parser/pyd -s s.linktab -o @.^.Modules.o.parsermodule -e initparser | ||||||
| 
 | 
 | ||||||
| @.^.Lib.regex/pyd: @.^.Modules.o.regexmodule @.^.Modules.o.regexpr s.linktab |  | ||||||
| 	$(LINK) -aof -o @.^.Modules.o.regexlink @.^.Modules.o.regexmodule @.^.Modules.o.regexpr |  | ||||||
| 	$(MAKEDLK) -d @.^.Lib.regex/pyd -s s.linktab -o @.^.Modules.o.regexlink -e initregex |  | ||||||
| 
 |  | ||||||
| @.^.Lib.rgbimg/pyd: @.^.Modules.o.rgbimgmodule s.linktab | @.^.Lib.rgbimg/pyd: @.^.Modules.o.rgbimgmodule s.linktab | ||||||
| 	$(MAKEDLK) -d @.^.Lib.rgbimg/pyd -s s.linktab -o @.^.Modules.o.rgbimgmodule -e initrgbimg | 	$(MAKEDLK) -d @.^.Lib.rgbimg/pyd -s s.linktab -o @.^.Modules.o.rgbimgmodule -e initrgbimg | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ | ||||||
| # into a program for a different change to Python programs... | # into a program for a different change to Python programs... | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import os | import os | ||||||
| from stat import * | from stat import * | ||||||
| 
 | 
 | ||||||
|  | @ -53,7 +53,7 @@ def main(): | ||||||
|             if fix(arg): bad = 1 |             if fix(arg): bad = 1 | ||||||
|     sys.exit(bad) |     sys.exit(bad) | ||||||
| 
 | 
 | ||||||
| ispythonprog = regex.compile('^[a-zA-Z0-9_]+\.py$') | ispythonprog = re.compile('^[a-zA-Z0-9_]+\.py$') | ||||||
| def ispython(name): | def ispython(name): | ||||||
|     return ispythonprog.match(name) >= 0 |     return ispythonprog.match(name) >= 0 | ||||||
| 
 | 
 | ||||||
|  | @ -148,12 +148,12 @@ def fix(filename): | ||||||
| 
 | 
 | ||||||
| # This expression doesn't catch *all* class definition headers, | # This expression doesn't catch *all* class definition headers, | ||||||
| # but it's pretty darn close. | # but it's pretty darn close. | ||||||
| classexpr = '^\([ \t]*class +[a-zA-Z0-9_]+\) *( *) *\(\(=.*\)?\):' | classexpr = '^([ \t]*class +[a-zA-Z0-9_]+) *( *) *((=.*)?):' | ||||||
| classprog = regex.compile(classexpr) | classprog = re.compile(classexpr) | ||||||
| 
 | 
 | ||||||
| # Expressions for finding base class expressions. | # Expressions for finding base class expressions. | ||||||
| baseexpr = '^ *\(.*\) *( *) *$' | baseexpr = '^ *(.*) *( *) *$' | ||||||
| baseprog = regex.compile(baseexpr) | baseprog = re.compile(baseexpr) | ||||||
| 
 | 
 | ||||||
| def fixline(line): | def fixline(line): | ||||||
|     if classprog.match(line) < 0: # No 'class' keyword -- no change |     if classprog.match(line) < 0: # No 'class' keyword -- no change | ||||||
|  |  | ||||||
|  | @ -35,7 +35,7 @@ | ||||||
| # files. | # files. | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import os | import os | ||||||
| from stat import * | from stat import * | ||||||
| import getopt | import getopt | ||||||
|  | @ -90,7 +90,7 @@ def main(): | ||||||
| # Change this regular expression to select a different set of files | # Change this regular expression to select a different set of files | ||||||
| Wanted = '^[a-zA-Z0-9_]+\.[ch]$' | Wanted = '^[a-zA-Z0-9_]+\.[ch]$' | ||||||
| def wanted(name): | def wanted(name): | ||||||
|     return regex.match(Wanted, name) >= 0 |     return re.match(Wanted, name) >= 0 | ||||||
| 
 | 
 | ||||||
| def recursedown(dirname): | def recursedown(dirname): | ||||||
|     dbg('recursedown(%r)\n' % (dirname,)) |     dbg('recursedown(%r)\n' % (dirname,)) | ||||||
|  | @ -212,12 +212,12 @@ def fix(filename): | ||||||
| # Anything else is an operator -- don't list this explicitly because of '/*' | # Anything else is an operator -- don't list this explicitly because of '/*' | ||||||
| 
 | 
 | ||||||
| OutsideComment = (Identifier, Number, String, Char, CommentStart) | OutsideComment = (Identifier, Number, String, Char, CommentStart) | ||||||
| OutsideCommentPattern = '\(' + '\|'.join(OutsideComment) + '\)' | OutsideCommentPattern = '(' + '|'.join(OutsideComment) + ')' | ||||||
| OutsideCommentProgram = regex.compile(OutsideCommentPattern) | OutsideCommentProgram = re.compile(OutsideCommentPattern) | ||||||
| 
 | 
 | ||||||
| InsideComment = (Identifier, Number, CommentEnd) | InsideComment = (Identifier, Number, CommentEnd) | ||||||
| InsideCommentPattern = '\(' + '\|'.join(InsideComment) + '\)' | InsideCommentPattern = '(' + '|'.join(InsideComment) + ')' | ||||||
| InsideCommentProgram = regex.compile(InsideCommentPattern) | InsideCommentProgram = re.compile(InsideCommentPattern) | ||||||
| 
 | 
 | ||||||
| def initfixline(): | def initfixline(): | ||||||
|     global Program |     global Program | ||||||
|  |  | ||||||
|  | @ -27,7 +27,6 @@ | ||||||
| # preprocessor commands. | # preprocessor commands. | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import regex |  | ||||||
| import getopt | import getopt | ||||||
| 
 | 
 | ||||||
| defs = [] | defs = [] | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ | ||||||
| # into a program for a different change to Python programs... | # into a program for a different change to Python programs... | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import os | import os | ||||||
| from stat import * | from stat import * | ||||||
| 
 | 
 | ||||||
|  | @ -50,7 +50,7 @@ def main(): | ||||||
|             if fix(arg): bad = 1 |             if fix(arg): bad = 1 | ||||||
|     sys.exit(bad) |     sys.exit(bad) | ||||||
| 
 | 
 | ||||||
| ispythonprog = regex.compile('^[a-zA-Z0-9_]+\.py$') | ispythonprog = re.compile('^[a-zA-Z0-9_]+\.py$') | ||||||
| def ispython(name): | def ispython(name): | ||||||
|     return ispythonprog.match(name) >= 0 |     return ispythonprog.match(name) >= 0 | ||||||
| 
 | 
 | ||||||
|  | @ -101,7 +101,7 @@ def fix(filename): | ||||||
|         if lineno == 1 and g is None and line[:2] == '#!': |         if lineno == 1 and g is None and line[:2] == '#!': | ||||||
|             # Check for non-Python scripts |             # Check for non-Python scripts | ||||||
|             words = line[2:].split() |             words = line[2:].split() | ||||||
|             if words and regex.search('[pP]ython', words[0]) < 0: |             if words and re.search('[pP]ython', words[0]) < 0: | ||||||
|                 msg = filename + ': ' + words[0] |                 msg = filename + ': ' + words[0] | ||||||
|                 msg = msg + ' script; not fixed\n' |                 msg = msg + ' script; not fixed\n' | ||||||
|                 err(msg) |                 err(msg) | ||||||
|  | @ -158,8 +158,8 @@ def fix(filename): | ||||||
|     return 0 |     return 0 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fixpat = '^[ \t]+def +[a-zA-Z0-9_]+ *( *self *, *\(( *\(.*\) *)\) *) *:' | fixpat = '^[ \t]+def +[a-zA-Z0-9_]+ *( *self *, *(( *(.*) *)) *) *:' | ||||||
| fixprog = regex.compile(fixpat) | fixprog = re.compile(fixpat) | ||||||
| 
 | 
 | ||||||
| def fixline(line): | def fixline(line): | ||||||
|     if fixprog.match(line) >= 0: |     if fixprog.match(line) >= 0: | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ | ||||||
| import sys | import sys | ||||||
| import os | import os | ||||||
| import getopt | import getopt | ||||||
| import regex | import re | ||||||
| 
 | 
 | ||||||
| # Types of symbols. | # Types of symbols. | ||||||
| # | # | ||||||
|  | @ -32,7 +32,7 @@ | ||||||
| 
 | 
 | ||||||
| # Regular expression to parse "nm -o" output. | # Regular expression to parse "nm -o" output. | ||||||
| # | # | ||||||
| matcher = regex.compile('\(.*\):\t?........ \(.\) \(.*\)$') | matcher = re.compile('(.*):\t?........ (.) (.*)$') | ||||||
| 
 | 
 | ||||||
| # Store "item" in "dict" under "key". | # Store "item" in "dict" under "key". | ||||||
| # The dictionary maps keys to lists of items. | # The dictionary maps keys to lists of items. | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ | ||||||
| # into a program for a different change to Python programs... | # into a program for a different change to Python programs... | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import os | import os | ||||||
| from stat import * | from stat import * | ||||||
| import getopt | import getopt | ||||||
|  | @ -59,7 +59,7 @@ def main(): | ||||||
|             if fix(arg): bad = 1 |             if fix(arg): bad = 1 | ||||||
|     sys.exit(bad) |     sys.exit(bad) | ||||||
| 
 | 
 | ||||||
| ispythonprog = regex.compile('^[a-zA-Z0-9_]+\.py$') | ispythonprog = re.compile('^[a-zA-Z0-9_]+\.py$') | ||||||
| def ispython(name): | def ispython(name): | ||||||
|     return ispythonprog.match(name) >= 0 |     return ispythonprog.match(name) >= 0 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,7 +21,7 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| import sys | import sys | ||||||
| import regex | import re | ||||||
| import os | import os | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -57,8 +57,8 @@ def main(): | ||||||
| 
 | 
 | ||||||
| # Compiled regular expressions to search for import statements | # Compiled regular expressions to search for import statements | ||||||
| # | # | ||||||
| m_import = regex.compile('^[ \t]*from[ \t]+\([^ \t]+\)[ \t]+') | m_import = re.compile('^[ \t]*from[ \t]+([^ \t]+)[ \t]+') | ||||||
| m_from = regex.compile('^[ \t]*import[ \t]+\([^#]+\)') | m_from = re.compile('^[ \t]*import[ \t]+([^#]+)') | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Collect data from one file | # Collect data from one file | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								setup.py
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.py
									
										
									
									
									
								
							|  | @ -326,8 +326,6 @@ def detect_modules(self): | ||||||
|         # |         # | ||||||
| 
 | 
 | ||||||
|         # Some modules that are normally always on: |         # Some modules that are normally always on: | ||||||
|         exts.append( Extension('regex', ['regexmodule.c', 'regexpr.c']) ) |  | ||||||
| 
 |  | ||||||
|         exts.append( Extension('_weakref', ['_weakref.c']) ) |         exts.append( Extension('_weakref', ['_weakref.c']) ) | ||||||
| 
 | 
 | ||||||
|         # array objects |         # array objects | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Neal Norwitz
						Neal Norwitz