From a8763e54ff25a226e50b281671189382fd3c324c Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 26 Aug 1996 18:33:32 +0000 Subject: Another batch of updates... --- Lib/dos-8x3/ast.py | 31 +++++++--- Lib/dos-8x3/bastion.py | 15 +++++ Lib/dos-8x3/compilea.py | 2 +- Lib/dos-8x3/formatte.py | 27 +++++---- Lib/dos-8x3/mimetool.py | 10 +++- Lib/dos-8x3/mimewrit.py | 131 +++++++++++++++++++++++++++++++++++++++++ Lib/dos-8x3/posixfil.py | 9 ++- Lib/dos-8x3/posixpat.py | 2 +- Lib/dos-8x3/test_mat.py | 153 ++++++++++++++++++++++++++++++++++++++++++++++++ Lib/dos-8x3/tracebac.py | 72 ++++++++++++++++++++--- Lib/dos_8x3/ast.py | 31 +++++++--- Lib/dos_8x3/bastion.py | 15 +++++ Lib/dos_8x3/compilea.py | 2 +- Lib/dos_8x3/formatte.py | 27 +++++---- Lib/dos_8x3/mimetool.py | 10 +++- Lib/dos_8x3/mimewrit.py | 131 +++++++++++++++++++++++++++++++++++++++++ Lib/dos_8x3/posixfil.py | 9 ++- Lib/dos_8x3/posixpat.py | 2 +- Lib/dos_8x3/test_mat.py | 153 ++++++++++++++++++++++++++++++++++++++++++++++++ Lib/dos_8x3/tracebac.py | 72 ++++++++++++++++++++--- 20 files changed, 842 insertions(+), 62 deletions(-) create mode 100644 Lib/dos-8x3/mimewrit.py create mode 100644 Lib/dos-8x3/test_mat.py create mode 100644 Lib/dos_8x3/mimewrit.py create mode 100644 Lib/dos_8x3/test_mat.py diff --git a/Lib/dos-8x3/ast.py b/Lib/dos-8x3/ast.py index 6f92bee..370cfe4 100755 --- a/Lib/dos-8x3/ast.py +++ b/Lib/dos-8x3/ast.py @@ -1,13 +1,13 @@ """Object-oriented interface to the parser module. -This module exports three classes which together provide an interface +This module exports four classes which together provide an interface to the parser module. Together, the three classes represent two ways to create parsed representations of Python source and the two starting data types (source text and tuple representations). Each class provides interfaces which are identical other than the constructors. The constructors are described in detail in the documentation for each class and the remaining, shared portion of the interface is documented -below. Briefly, the three classes provided are: +below. Briefly, the classes provided are: AST Defines the primary interface to the AST objects and supports creation @@ -23,6 +23,9 @@ FileSuiteAST Convenience subclass of the `SuiteAST' class; loads source text of the suite from an external file. +Common Methods +-------------- + Aside from the constructors, several methods are provided to allow access to the various interpretations of the parse tree and to check conditions of the construct represented by the parse tree. @@ -68,8 +71,8 @@ class AST: This base class provides all of the query methods for subclass objects defined in this module. """ - _p = __import__('parser') # import internally to avoid - # namespace pollution at the + import parser # import internally to avoid + _p = parser # namespace pollution at the # top level _text = None _code = None @@ -84,7 +87,8 @@ class AST: The tuple tree to convert. The tuple-tree may represent either an expression or a suite; the - type will be determined automatically. + type will be determined automatically. Line number information may + optionally be present for any subset of the terminal tokens. """ if type(tuple) is not type(()): raise TypeError, 'Base AST class requires tuple parameter.' @@ -93,11 +97,24 @@ class AST: self._ast = self._p.tuple2ast(tuple) self._type = (self._p.isexpr(self._ast) and 'expression') or 'suite' - def tuple(self): + def list(self, line_info = 0): + """Returns a fresh list representing the parse tree. + + line_info + If true, includes line number information for terminal tokens in + the output data structure, + """ + return self._p.ast2list(self._ast, line_info) + + def tuple(self, line_info = 0): """Returns the tuple representing the parse tree. + + line_info + If true, includes line number information for terminal tokens in + the output data structure, """ if self._tupl is None: - self._tupl = self._p.ast2tuple(self._ast) + self._tupl = self._p.ast2tuple(self._ast, line_info) return self._tupl def code(self): diff --git a/Lib/dos-8x3/bastion.py b/Lib/dos-8x3/bastion.py index 7ddd93e..cb54be9 100755 --- a/Lib/dos-8x3/bastion.py +++ b/Lib/dos-8x3/bastion.py @@ -141,6 +141,7 @@ def _test(): return self.sum o = Original() b = Bastion(o) + testcode = """if 1: b.add(81) b.add(18) print "b.total() =", b.total() @@ -156,6 +157,20 @@ def _test(): print "inaccessible" else: print "accessible" + try: + print "b._get_.func_defaults =", b._get_.func_defaults, + except: + print "inaccessible" + else: + print "accessible" + \n""" + exec testcode + print '='*20, "Using rexec:", '='*20 + import rexec + r = rexec.RExec() + m = r.add_module('__main__') + m.b = b + r.r_exec(testcode) if __name__ == '__main__': diff --git a/Lib/dos-8x3/compilea.py b/Lib/dos-8x3/compilea.py index 3120284..9947569 100755 --- a/Lib/dos-8x3/compilea.py +++ b/Lib/dos-8x3/compilea.py @@ -43,7 +43,7 @@ def compile_dir(dir, maxlevels = 10): def compile_path(skip_curdir = 1): for dir in sys.path: - if dir == os.curdir and skip_curdir: + if (not dir or dir == os.curdir) and skip_curdir: print 'Skipping current directory' else: compile_dir(dir, 0) diff --git a/Lib/dos-8x3/formatte.py b/Lib/dos-8x3/formatte.py index 0266379..c192e20 100755 --- a/Lib/dos-8x3/formatte.py +++ b/Lib/dos-8x3/formatte.py @@ -10,7 +10,7 @@ AS_IS = None class NullFormatter: - def __init__(self): pass + def __init__(self, writer): pass def end_paragraph(self, blankline): pass def add_line_break(self): pass def add_hor_rule(self, abswidth=None, percentwidth=1.0, @@ -33,6 +33,11 @@ class NullFormatter: class AbstractFormatter: + # Space handling policy: blank spaces at the boundary between elements + # are handled by the outermost context. "Literal" data is not checked + # to determine context, so spaces in literal data are handled directly + # in all circumstances. + def __init__(self, writer): self.writer = writer # Output device self.align = None # Current alignment @@ -162,7 +167,8 @@ class AbstractFormatter: def add_literal_data(self, data): if not data: return - # Caller is expected to cause flush_softspace() if needed. + if self.softspace: + self.writer.send_flowing_data(" ") self.hard_break = data[-1:] == '\n' self.nospace = self.para_end = self.softspace = \ self.parskip = self.have_label = 0 @@ -170,8 +176,9 @@ class AbstractFormatter: def flush_softspace(self): if self.softspace: - self.hard_break = self.nospace = self.para_end = self.parskip = \ + self.hard_break = self.para_end = self.parskip = \ self.have_label = self.softspace = 0 + self.nospace = 1 self.writer.send_flowing_data(' ') def push_alignment(self, align): @@ -194,7 +201,8 @@ class AbstractFormatter: def push_font(self, (size, i, b, tt)): if self.softspace: - self.hard_break = self.nospace = self.para_end = self.softspace = 0 + self.hard_break = self.para_end = self.softspace = 0 + self.nospace = 1 self.writer.send_flowing_data(' ') if self.font_stack: csize, ci, cb, ctt = self.font_stack[-1] @@ -207,9 +215,6 @@ class AbstractFormatter: self.writer.new_font(font) def pop_font(self): - if self.softspace: - self.hard_break = self.nospace = self.para_end = self.softspace = 0 - self.writer.send_flowing_data(' ') if self.font_stack: del self.font_stack[-1] if self.font_stack: @@ -241,22 +246,20 @@ class AbstractFormatter: def push_style(self, *styles): if self.softspace: - self.hard_break = self.nospace = self.para_end = self.softspace = 0 + self.hard_break = self.para_end = self.softspace = 0 + self.nospace = 1 self.writer.send_flowing_data(' ') for style in styles: self.style_stack.append(style) self.writer.new_styles(tuple(self.style_stack)) def pop_style(self, n=1): - if self.softspace: - self.hard_break = self.nospace = self.para_end = self.softspace = 0 - self.writer.send_flowing_data(' ') del self.style_stack[-n:] self.writer.new_styles(tuple(self.style_stack)) def assert_line_data(self, flag=1): self.nospace = self.hard_break = not flag - self.para_end = self.have_label = 0 + self.para_end = self.parskip = self.have_label = 0 class NullWriter: diff --git a/Lib/dos-8x3/mimetool.py b/Lib/dos-8x3/mimetool.py index da33a77..baf9379 100755 --- a/Lib/dos-8x3/mimetool.py +++ b/Lib/dos-8x3/mimetool.py @@ -106,8 +106,14 @@ def choose_boundary(): import socket import os hostid = socket.gethostbyname(socket.gethostname()) - uid = `os.getuid()` - pid = `os.getpid()` + try: + uid = `os.getuid()` + except: + uid = '1' + try: + pid = `os.getpid()` + except: + pid = '1' seed = `rand.rand()` _prefix = hostid + '.' + uid + '.' + pid timestamp = `int(time.time())` diff --git a/Lib/dos-8x3/mimewrit.py b/Lib/dos-8x3/mimewrit.py new file mode 100644 index 0000000..6fbcb65 --- /dev/null +++ b/Lib/dos-8x3/mimewrit.py @@ -0,0 +1,131 @@ +"""Generic MIME writer. + +Classes: + +MimeWriter - the only thing here. + +""" + +__version__ = '$Revision$' +# $Source$ + + +import string +import mimetools + + +class MimeWriter: + + """Generic MIME writer. + + Methods: + + __init__() + addheader() + flushheaders() + startbody() + startmultipartbody() + nextpart() + lastpart() + + A MIME writer is much more primitive than a MIME parser. It + doesn't seek around on the output file, and it doesn't use large + amounts of buffer space, so you have to write the parts in the + order they should occur on the output file. It does buffer the + headers you add, allowing you to rearrange their order. + + General usage is: + + f = + w = MimeWriter(f) + ...call w.addheader(key, value) 0 or more times... + + followed by either: + + f = w.startbody(content_type) + ...call f.write(data) for body data... + + or: + + w.startmultipartbody(subtype) + for each part: + subwriter = w.nextpart() + ...use the subwriter's methods to create the subpart... + w.lastpart() + + The subwriter is another MimeWriter instance, and should be + treated in the same way as the toplevel MimeWriter. This way, + writing recursive body parts is easy. + + Warning: don't forget to call lastpart()! + + XXX There should be more state so calls made in the wrong order + are detected. + + Some special cases: + + - startbody() just returns the file passed to the constructor; + but don't use this knowledge, as it may be changed. + + - startmultipartbody() actually returns a file as well; + this can be used to write the initial 'if you can read this your + mailer is not MIME-aware' message. + + - If you call flushheaders(), the headers accumulated so far are + written out (and forgotten); this is useful if you don't need a + body part at all, e.g. for a subpart of type message/rfc822 + that's (mis)used to store some header-like information. + + - Passing a keyword argument 'prefix=' to addheader(), + start*body() affects where the header is inserted; 0 means + append at the end, 1 means insert at the start; default is + append for addheader(), but insert for start*body(), which use + it to determine where the Content-Type header goes. + + """ + + def __init__(self, fp): + self._fp = fp + self._headers = [] + + def addheader(self, key, value, prefix=0): + lines = string.splitfields(value, "\n") + while lines and not lines[-1]: del lines[-1] + while lines and not lines[0]: del lines[0] + for i in range(1, len(lines)): + lines[i] = " " + string.strip(lines[i]) + value = string.joinfields(lines, "\n") + "\n" + line = key + ": " + value + if prefix: + self._headers.insert(0, line) + else: + self._headers.append(line) + + def flushheaders(self): + self._fp.writelines(self._headers) + self._headers = [] + + def startbody(self, ctype, plist=[], prefix=1): + for name, value in plist: + ctype = ctype + ';\n %s=\"%s\"' % (name, value) + self.addheader("Content-Type", ctype, prefix=prefix) + self.flushheaders() + self._fp.write("\n") + return self._fp + + def startmultipartbody(self, subtype, boundary=None, plist=[], prefix=1): + self._boundary = boundary or mimetools.choose_boundary() + return self.startbody("multipart/" + subtype, + [("boundary", self._boundary)] + plist, + prefix=prefix) + + def nextpart(self): + self._fp.write("\n--" + self._boundary + "\n") + return self.__class__(self._fp) + + def lastpart(self): + self._fp.write("\n--" + self._boundary + "--\n") + + +if __name__ == '__main__': + print "To test the MimeWriter module, run TestMimeWriter.py." diff --git a/Lib/dos-8x3/posixfil.py b/Lib/dos-8x3/posixfil.py index 64cda98..f0df543 100755 --- a/Lib/dos-8x3/posixfil.py +++ b/Lib/dos-8x3/posixfil.py @@ -174,11 +174,15 @@ class _posixfile_: elif len(args) > 3: raise TypeError, 'too many arguments' - # Hack by davem@magnet.com to get locking to go on freebsd + # Hack by davem@magnet.com to get locking to go on freebsd; + # additions for AIX by Vladimir.Marangozov@imag.fr import sys, os if sys.platform == 'freebsd2': flock = struct.pack('lxxxxlxxxxlhh', \ l_start, l_len, os.getpid(), l_type, l_whence) + elif sys.platform in ['aix3', 'aix4']: + flock = struct.pack('hhlllii', \ + l_type, l_whence, l_start, l_len, 0, 0, 0) else: flock = struct.pack('hhllhh', \ l_type, l_whence, l_start, l_len, 0, 0) @@ -189,6 +193,9 @@ class _posixfile_: if sys.platform == 'freebsd2': l_start, l_len, l_pid, l_type, l_whence = \ struct.unpack('lxxxxlxxxxlhh', flock) + elif sys.platform in ['aix3', 'aix4']: + l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \ + struct.unpack('hhlllii', flock) else: l_type, l_whence, l_start, l_len, l_sysid, l_pid = \ struct.unpack('hhllhh', flock) diff --git a/Lib/dos-8x3/posixpat.py b/Lib/dos-8x3/posixpat.py index 4590f8d..014dfe2 100755 --- a/Lib/dos-8x3/posixpat.py +++ b/Lib/dos-8x3/posixpat.py @@ -53,7 +53,7 @@ def split(p): # Split a path in root and extension. -# The extension is everything starting at the first dot in the last +# The extension is everything starting at the last dot in the last # pathname component; the root is everything before that. # It is always true that root + ext == p. diff --git a/Lib/dos-8x3/test_mat.py b/Lib/dos-8x3/test_mat.py new file mode 100644 index 0000000..af84d2a --- /dev/null +++ b/Lib/dos-8x3/test_mat.py @@ -0,0 +1,153 @@ +# Python test set -- math module +# XXXX Should not do tests around zero only + +from test_support import * + +eps=1e-5 +print 'math module, testing with eps', eps +import math + +def testit(name, value, expected): + if abs(value-expected) > eps: + raise TestFailed, '%s returned %f, expected %f'%\ + (name, value, expected) + +print 'constants' +testit('pi', math.pi, 3.1415926) +testit('e', math.e, 2.7182818) + +print 'acos' +testit('acos(-1)', math.acos(-1), math.pi) +testit('acos(0)', math.acos(0), math.pi/2) +testit('acos(1)', math.acos(1), 0) + +print 'asin' +testit('asin(-1)', math.asin(-1), -math.pi/2) +testit('asin(0)', math.asin(0), 0) +testit('asin(1)', math.asin(1), math.pi/2) + +print 'atan' +testit('atan(-1)', math.atan(-1), -math.pi/4) +testit('atan(0)', math.atan(0), 0) +testit('atan(1)', math.atan(1), math.pi/4) + +print 'atan2' +testit('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2) +testit('atan2(-1, 1)', math.atan2(-1, 1), -math.pi/4) +testit('atan2(0, 1)', math.atan2(0, 1), 0) +testit('atan2(1, 1)', math.atan2(1, 1), math.pi/4) +testit('atan2(1, 0)', math.atan2(1, 0), math.pi/2) + +print 'ceil' +testit('ceil(0.5)', math.ceil(0.5), 1) +testit('ceil(1.0)', math.ceil(1.0), 1) +testit('ceil(1.5)', math.ceil(1.5), 2) +testit('ceil(-0.5)', math.ceil(-0.5), 0) +testit('ceil(-1.0)', math.ceil(-1.0), -1) +testit('ceil(-1.5)', math.ceil(-1.5), -1) + +print 'cos' +testit('cos(-pi/2)', math.cos(-math.pi/2), 0) +testit('cos(0)', math.cos(0), 1) +testit('cos(pi/2)', math.cos(math.pi/2), 0) +testit('cos(pi)', math.cos(math.pi), -1) + +print 'cosh' +testit('cosh(0)', math.cosh(0), 1) +testit('cosh(2)-2*cosh(1)**2', math.cosh(2)-2*math.cosh(1)**2, -1) # Thanks to Lambert + +print 'exp' +testit('exp(-1)', math.exp(-1), 1/math.e) +testit('exp(0)', math.exp(0), 1) +testit('exp(1)', math.exp(1), math.e) + +print 'fabs' +testit('fabs(-1)', math.fabs(-1), 1) +testit('fabs(0)', math.fabs(0), 0) +testit('fabs(1)', math.fabs(1), 1) + +print 'floor' +testit('floor(0.5)', math.floor(0.5), 0) +testit('floor(1.0)', math.floor(1.0), 1) +testit('floor(1.5)', math.floor(1.5), 1) +testit('floor(-0.5)', math.floor(-0.5), -1) +testit('floor(-1.0)', math.floor(-1.0), -1) +testit('floor(-1.5)', math.floor(-1.5), -2) + +print 'fmod' +testit('fmod(10,1)', math.fmod(10,1), 0) +testit('fmod(10,0.5)', math.fmod(10,0.5), 0) +testit('fmod(10,1.5)', math.fmod(10,1.5), 1) +testit('fmod(-10,1)', math.fmod(-10,1), 0) +testit('fmod(-10,0.5)', math.fmod(-10,0.5), 0) +testit('fmod(-10,1.5)', math.fmod(-10,1.5), -1) + +print 'frexp' +def testfrexp(name, (mant, exp), (emant, eexp)): + if abs(mant-emant) > eps or exp <> eexp: + raise TestFailed, '%s returned %s, expected %s'%\ + (name, `mant, exp`, `emant,eexp`) + +testfrexp('frexp(-1)', math.frexp(-1), (-0.5, 1)) +testfrexp('frexp(0)', math.frexp(0), (0, 0)) +testfrexp('frexp(1)', math.frexp(1), (0.5, 1)) +testfrexp('frexp(2)', math.frexp(2), (0.5, 2)) + +print 'hypot' +testit('hypot(0,0)', math.hypot(0,0), 0) +testit('hypot(3,4)', math.hypot(3,4), 5) + +print 'ldexp' +testit('ldexp(0,1)', math.ldexp(0,1), 0) +testit('ldexp(1,1)', math.ldexp(1,1), 2) +testit('ldexp(1,-1)', math.ldexp(1,-1), 0.5) +testit('ldexp(-1,1)', math.ldexp(-1,1), -2) + +print 'log' +testit('log(1/e)', math.log(1/math.e), -1) +testit('log(1)', math.log(1), 0) +testit('log(e)', math.log(math.e), 1) + +print 'log10' +testit('log10(0.1)', math.log10(0.1), -1) +testit('log10(1)', math.log10(1), 0) +testit('log10(10)', math.log10(10), 1) + +print 'modf' +def testmodf(name, (v1, v2), (e1, e2)): + if abs(v1-e1) > eps or abs(v2-e2): + raise TestFailed, '%s returned %s, expected %s'%\ + (name, `v1,v2`, `e1,e2`) + +testmodf('modf(1.5)', math.modf(1.5), (0.5, 1.0)) +testmodf('modf(-1.5)', math.modf(-1.5), (-0.5, -1.0)) + +print 'pow' +testit('pow(0,1)', math.pow(0,1), 0) +testit('pow(1,0)', math.pow(1,0), 1) +testit('pow(2,1)', math.pow(2,1), 2) +testit('pow(2,-1)', math.pow(2,-1), 0.5) + +print 'sin' +testit('sin(0)', math.sin(0), 0) +testit('sin(pi/2)', math.sin(math.pi/2), 1) +testit('sin(-pi/2)', math.sin(-math.pi/2), -1) + +print 'sinh' +testit('sinh(0)', math.sinh(0), 0) +testit('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1) +testit('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0) + +print 'sqrt' +testit('sqrt(0)', math.sqrt(0), 0) +testit('sqrt(1)', math.sqrt(1), 1) +testit('sqrt(4)', math.sqrt(4), 2) + +print 'tan' +testit('tan(0)', math.tan(0), 0) +testit('tan(pi/4)', math.tan(math.pi/4), 1) +testit('tan(-pi/4)', math.tan(-math.pi/4), -1) + +print 'tanh' +testit('tanh(0)', math.tanh(0), 0) +testit('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0) diff --git a/Lib/dos-8x3/tracebac.py b/Lib/dos-8x3/tracebac.py index 8d2dfdc..9823100 100755 --- a/Lib/dos-8x3/tracebac.py +++ b/Lib/dos-8x3/tracebac.py @@ -7,6 +7,25 @@ import types def _print(file, str='', terminator='\n'): file.write(str+terminator) + + +def print_list(extracted_list, file=None): + if not file: + file = sys.stderr + for filename, lineno, name, line in extracted_list: + _print(file, + ' File "%s", line %d, in %s' % (filename,lineno,name)) + if line: + _print(file, ' %s' % string.strip(line)) + +def format_list(extracted_list): + list = [] + for filename, lineno, name, line in extracted_list: + item = ' File "%s", line %d, in %s\n' % (filename,lineno,name) + if line: + item = item + ' %s\n' % string.strip(line) + list.append(item) + return list def print_tb(tb, limit=None, file=None): @@ -30,13 +49,7 @@ def print_tb(tb, limit=None, file=None): n = n+1 def format_tb(tb, limit = None): - list = [] - for filename, lineno, name, line in extract_tb(tb, limit): - item = ' File "%s", line %d, in %s\n' % (filename,lineno,name) - if line: - item = item + ' %s\n' % string.strip(line) - list.append(item) - return list + return format_list(extract_tb(tb, limit)) def extract_tb(tb, limit = None): if limit is None: @@ -123,3 +136,48 @@ def print_last(limit=None, file=None): file = sys.stderr print_exception(sys.last_type, sys.last_value, sys.last_traceback, limit, file) + + +def print_stack(f=None, limit=None, file=None): + if f is None: + try: + raise ZeroDivisionError + except ZeroDivisionError: + tb = sys.exc_traceback + f = tb.tb_frame.f_back + print_list(extract_stack(f, limit), file) + +def format_stack(f=None, limit=None): + if f is None: + try: + raise ZeroDivisionError + except ZeroDivisionError: + tb = sys.exc_traceback + f = tb.tb_frame.f_back + return format_list(extract_stack(t, limit)) + +def extract_stack(f=None, limit = None): + if f is None: + try: + raise ZeroDivisionError + except ZeroDivisionError: + tb = sys.exc_traceback + f = tb.tb_frame.f_back + if limit is None: + if hasattr(sys, 'tracebacklimit'): + limit = sys.tracebacklimit + list = [] + n = 0 + while f is not None and (limit is None or n < limit): + lineno = f.f_lineno + co = f.f_code + filename = co.co_filename + name = co.co_name + line = linecache.getline(filename, lineno) + if line: line = string.strip(line) + else: line = None + list.append(filename, lineno, name, line) + f = f.f_back + n = n+1 + list.reverse() + return list diff --git a/Lib/dos_8x3/ast.py b/Lib/dos_8x3/ast.py index 6f92bee..370cfe4 100755 --- a/Lib/dos_8x3/ast.py +++ b/Lib/dos_8x3/ast.py @@ -1,13 +1,13 @@ """Object-oriented interface to the parser module. -This module exports three classes which together provide an interface +This module exports four classes which together provide an interface to the parser module. Together, the three classes represent two ways to create parsed representations of Python source and the two starting data types (source text and tuple representations). Each class provides interfaces which are identical other than the constructors. The constructors are described in detail in the documentation for each class and the remaining, shared portion of the interface is documented -below. Briefly, the three classes provided are: +below. Briefly, the classes provided are: AST Defines the primary interface to the AST objects and supports creation @@ -23,6 +23,9 @@ FileSuiteAST Convenience subclass of the `SuiteAST' class; loads source text of the suite from an external file. +Common Methods +-------------- + Aside from the constructors, several methods are provided to allow access to the various interpretations of the parse tree and to check conditions of the construct represented by the parse tree. @@ -68,8 +71,8 @@ class AST: This base class provides all of the query methods for subclass objects defined in this module. """ - _p = __import__('parser') # import internally to avoid - # namespace pollution at the + import parser # import internally to avoid + _p = parser # namespace pollution at the # top level _text = None _code = None @@ -84,7 +87,8 @@ class AST: The tuple tree to convert. The tuple-tree may represent either an expression or a suite; the - type will be determined automatically. + type will be determined automatically. Line number information may + optionally be present for any subset of the terminal tokens. """ if type(tuple) is not type(()): raise TypeError, 'Base AST class requires tuple parameter.' @@ -93,11 +97,24 @@ class AST: self._ast = self._p.tuple2ast(tuple) self._type = (self._p.isexpr(self._ast) and 'expression') or 'suite' - def tuple(self): + def list(self, line_info = 0): + """Returns a fresh list representing the parse tree. + + line_info + If true, includes line number information for terminal tokens in + the output data structure, + """ + return self._p.ast2list(self._ast, line_info) + + def tuple(self, line_info = 0): """Returns the tuple representing the parse tree. + + line_info + If true, includes line number information for terminal tokens in + the output data structure, """ if self._tupl is None: - self._tupl = self._p.ast2tuple(self._ast) + self._tupl = self._p.ast2tuple(self._ast, line_info) return self._tupl def code(self): diff --git a/Lib/dos_8x3/bastion.py b/Lib/dos_8x3/bastion.py index 7ddd93e..cb54be9 100755 --- a/Lib/dos_8x3/bastion.py +++ b/Lib/dos_8x3/bastion.py @@ -141,6 +141,7 @@ def _test(): return self.sum o = Original() b = Bastion(o) + testcode = """if 1: b.add(81) b.add(18) print "b.total() =", b.total() @@ -156,6 +157,20 @@ def _test(): print "inaccessible" else: print "accessible" + try: + print "b._get_.func_defaults =", b._get_.func_defaults, + except: + print "inaccessible" + else: + print "accessible" + \n""" + exec testcode + print '='*20, "Using rexec:", '='*20 + import rexec + r = rexec.RExec() + m = r.add_module('__main__') + m.b = b + r.r_exec(testcode) if __name__ == '__main__': diff --git a/Lib/dos_8x3/compilea.py b/Lib/dos_8x3/compilea.py index 3120284..9947569 100755 --- a/Lib/dos_8x3/compilea.py +++ b/Lib/dos_8x3/compilea.py @@ -43,7 +43,7 @@ def compile_dir(dir, maxlevels = 10): def compile_path(skip_curdir = 1): for dir in sys.path: - if dir == os.curdir and skip_curdir: + if (not dir or dir == os.curdir) and skip_curdir: print 'Skipping current directory' else: compile_dir(dir, 0) diff --git a/Lib/dos_8x3/formatte.py b/Lib/dos_8x3/formatte.py index 0266379..c192e20 100755 --- a/Lib/dos_8x3/formatte.py +++ b/Lib/dos_8x3/formatte.py @@ -10,7 +10,7 @@ AS_IS = None class NullFormatter: - def __init__(self): pass + def __init__(self, writer): pass def end_paragraph(self, blankline): pass def add_line_break(self): pass def add_hor_rule(self, abswidth=None, percentwidth=1.0, @@ -33,6 +33,11 @@ class NullFormatter: class AbstractFormatter: + # Space handling policy: blank spaces at the boundary between elements + # are handled by the outermost context. "Literal" data is not checked + # to determine context, so spaces in literal data are handled directly + # in all circumstances. + def __init__(self, writer): self.writer = writer # Output device self.align = None # Current alignment @@ -162,7 +167,8 @@ class AbstractFormatter: def add_literal_data(self, data): if not data: return - # Caller is expected to cause flush_softspace() if needed. + if self.softspace: + self.writer.send_flowing_data(" ") self.hard_break = data[-1:] == '\n' self.nospace = self.para_end = self.softspace = \ self.parskip = self.have_label = 0 @@ -170,8 +176,9 @@ class AbstractFormatter: def flush_softspace(self): if self.softspace: - self.hard_break = self.nospace = self.para_end = self.parskip = \ + self.hard_break = self.para_end = self.parskip = \ self.have_label = self.softspace = 0 + self.nospace = 1 self.writer.send_flowing_data(' ') def push_alignment(self, align): @@ -194,7 +201,8 @@ class AbstractFormatter: def push_font(self, (size, i, b, tt)): if self.softspace: - self.hard_break = self.nospace = self.para_end = self.softspace = 0 + self.hard_break = self.para_end = self.softspace = 0 + self.nospace = 1 self.writer.send_flowing_data(' ') if self.font_stack: csize, ci, cb, ctt = self.font_stack[-1] @@ -207,9 +215,6 @@ class AbstractFormatter: self.writer.new_font(font) def pop_font(self): - if self.softspace: - self.hard_break = self.nospace = self.para_end = self.softspace = 0 - self.writer.send_flowing_data(' ') if self.font_stack: del self.font_stack[-1] if self.font_stack: @@ -241,22 +246,20 @@ class AbstractFormatter: def push_style(self, *styles): if self.softspace: - self.hard_break = self.nospace = self.para_end = self.softspace = 0 + self.hard_break = self.para_end = self.softspace = 0 + self.nospace = 1 self.writer.send_flowing_data(' ') for style in styles: self.style_stack.append(style) self.writer.new_styles(tuple(self.style_stack)) def pop_style(self, n=1): - if self.softspace: - self.hard_break = self.nospace = self.para_end = self.softspace = 0 - self.writer.send_flowing_data(' ') del self.style_stack[-n:] self.writer.new_styles(tuple(self.style_stack)) def assert_line_data(self, flag=1): self.nospace = self.hard_break = not flag - self.para_end = self.have_label = 0 + self.para_end = self.parskip = self.have_label = 0 class NullWriter: diff --git a/Lib/dos_8x3/mimetool.py b/Lib/dos_8x3/mimetool.py index da33a77..baf9379 100755 --- a/Lib/dos_8x3/mimetool.py +++ b/Lib/dos_8x3/mimetool.py @@ -106,8 +106,14 @@ def choose_boundary(): import socket import os hostid = socket.gethostbyname(socket.gethostname()) - uid = `os.getuid()` - pid = `os.getpid()` + try: + uid = `os.getuid()` + except: + uid = '1' + try: + pid = `os.getpid()` + except: + pid = '1' seed = `rand.rand()` _prefix = hostid + '.' + uid + '.' + pid timestamp = `int(time.time())` diff --git a/Lib/dos_8x3/mimewrit.py b/Lib/dos_8x3/mimewrit.py new file mode 100644 index 0000000..6fbcb65 --- /dev/null +++ b/Lib/dos_8x3/mimewrit.py @@ -0,0 +1,131 @@ +"""Generic MIME writer. + +Classes: + +MimeWriter - the only thing here. + +""" + +__version__ = '$Revision$' +# $Source$ + + +import string +import mimetools + + +class MimeWriter: + + """Generic MIME writer. + + Methods: + + __init__() + addheader() + flushheaders() + startbody() + startmultipartbody() + nextpart() + lastpart() + + A MIME writer is much more primitive than a MIME parser. It + doesn't seek around on the output file, and it doesn't use large + amounts of buffer space, so you have to write the parts in the + order they should occur on the output file. It does buffer the + headers you add, allowing you to rearrange their order. + + General usage is: + + f = + w = MimeWriter(f) + ...call w.addheader(key, value) 0 or more times... + + followed by either: + + f = w.startbody(content_type) + ...call f.write(data) for body data... + + or: + + w.startmultipartbody(subtype) + for each part: + subwriter = w.nextpart() + ...use the subwriter's methods to create the subpart... + w.lastpart() + + The subwriter is another MimeWriter instance, and should be + treated in the same way as the toplevel MimeWriter. This way, + writing recursive body parts is easy. + + Warning: don't forget to call lastpart()! + + XXX There should be more state so calls made in the wrong order + are detected. + + Some special cases: + + - startbody() just returns the file passed to the constructor; + but don't use this knowledge, as it may be changed. + + - startmultipartbody() actually returns a file as well; + this can be used to write the initial 'if you can read this your + mailer is not MIME-aware' message. + + - If you call flushheaders(), the headers accumulated so far are + written out (and forgotten); this is useful if you don't need a + body part at all, e.g. for a subpart of type message/rfc822 + that's (mis)used to store some header-like information. + + - Passing a keyword argument 'prefix=' to addheader(), + start*body() affects where the header is inserted; 0 means + append at the end, 1 means insert at the start; default is + append for addheader(), but insert for start*body(), which use + it to determine where the Content-Type header goes. + + """ + + def __init__(self, fp): + self._fp = fp + self._headers = [] + + def addheader(self, key, value, prefix=0): + lines = string.splitfields(value, "\n") + while lines and not lines[-1]: del lines[-1] + while lines and not lines[0]: del lines[0] + for i in range(1, len(lines)): + lines[i] = " " + string.strip(lines[i]) + value = string.joinfields(lines, "\n") + "\n" + line = key + ": " + value + if prefix: + self._headers.insert(0, line) + else: + self._headers.append(line) + + def flushheaders(self): + self._fp.writelines(self._headers) + self._headers = [] + + def startbody(self, ctype, plist=[], prefix=1): + for name, value in plist: + ctype = ctype + ';\n %s=\"%s\"' % (name, value) + self.addheader("Content-Type", ctype, prefix=prefix) + self.flushheaders() + self._fp.write("\n") + return self._fp + + def startmultipartbody(self, subtype, boundary=None, plist=[], prefix=1): + self._boundary = boundary or mimetools.choose_boundary() + return self.startbody("multipart/" + subtype, + [("boundary", self._boundary)] + plist, + prefix=prefix) + + def nextpart(self): + self._fp.write("\n--" + self._boundary + "\n") + return self.__class__(self._fp) + + def lastpart(self): + self._fp.write("\n--" + self._boundary + "--\n") + + +if __name__ == '__main__': + print "To test the MimeWriter module, run TestMimeWriter.py." diff --git a/Lib/dos_8x3/posixfil.py b/Lib/dos_8x3/posixfil.py index 64cda98..f0df543 100755 --- a/Lib/dos_8x3/posixfil.py +++ b/Lib/dos_8x3/posixfil.py @@ -174,11 +174,15 @@ class _posixfile_: elif len(args) > 3: raise TypeError, 'too many arguments' - # Hack by davem@magnet.com to get locking to go on freebsd + # Hack by davem@magnet.com to get locking to go on freebsd; + # additions for AIX by Vladimir.Marangozov@imag.fr import sys, os if sys.platform == 'freebsd2': flock = struct.pack('lxxxxlxxxxlhh', \ l_start, l_len, os.getpid(), l_type, l_whence) + elif sys.platform in ['aix3', 'aix4']: + flock = struct.pack('hhlllii', \ + l_type, l_whence, l_start, l_len, 0, 0, 0) else: flock = struct.pack('hhllhh', \ l_type, l_whence, l_start, l_len, 0, 0) @@ -189,6 +193,9 @@ class _posixfile_: if sys.platform == 'freebsd2': l_start, l_len, l_pid, l_type, l_whence = \ struct.unpack('lxxxxlxxxxlhh', flock) + elif sys.platform in ['aix3', 'aix4']: + l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \ + struct.unpack('hhlllii', flock) else: l_type, l_whence, l_start, l_len, l_sysid, l_pid = \ struct.unpack('hhllhh', flock) diff --git a/Lib/dos_8x3/posixpat.py b/Lib/dos_8x3/posixpat.py index 4590f8d..014dfe2 100755 --- a/Lib/dos_8x3/posixpat.py +++ b/Lib/dos_8x3/posixpat.py @@ -53,7 +53,7 @@ def split(p): # Split a path in root and extension. -# The extension is everything starting at the first dot in the last +# The extension is everything starting at the last dot in the last # pathname component; the root is everything before that. # It is always true that root + ext == p. diff --git a/Lib/dos_8x3/test_mat.py b/Lib/dos_8x3/test_mat.py new file mode 100644 index 0000000..af84d2a --- /dev/null +++ b/Lib/dos_8x3/test_mat.py @@ -0,0 +1,153 @@ +# Python test set -- math module +# XXXX Should not do tests around zero only + +from test_support import * + +eps=1e-5 +print 'math module, testing with eps', eps +import math + +def testit(name, value, expected): + if abs(value-expected) > eps: + raise TestFailed, '%s returned %f, expected %f'%\ + (name, value, expected) + +print 'constants' +testit('pi', math.pi, 3.1415926) +testit('e', math.e, 2.7182818) + +print 'acos' +testit('acos(-1)', math.acos(-1), math.pi) +testit('acos(0)', math.acos(0), math.pi/2) +testit('acos(1)', math.acos(1), 0) + +print 'asin' +testit('asin(-1)', math.asin(-1), -math.pi/2) +testit('asin(0)', math.asin(0), 0) +testit('asin(1)', math.asin(1), math.pi/2) + +print 'atan' +testit('atan(-1)', math.atan(-1), -math.pi/4) +testit('atan(0)', math.atan(0), 0) +testit('atan(1)', math.atan(1), math.pi/4) + +print 'atan2' +testit('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2) +testit('atan2(-1, 1)', math.atan2(-1, 1), -math.pi/4) +testit('atan2(0, 1)', math.atan2(0, 1), 0) +testit('atan2(1, 1)', math.atan2(1, 1), math.pi/4) +testit('atan2(1, 0)', math.atan2(1, 0), math.pi/2) + +print 'ceil' +testit('ceil(0.5)', math.ceil(0.5), 1) +testit('ceil(1.0)', math.ceil(1.0), 1) +testit('ceil(1.5)', math.ceil(1.5), 2) +testit('ceil(-0.5)', math.ceil(-0.5), 0) +testit('ceil(-1.0)', math.ceil(-1.0), -1) +testit('ceil(-1.5)', math.ceil(-1.5), -1) + +print 'cos' +testit('cos(-pi/2)', math.cos(-math.pi/2), 0) +testit('cos(0)', math.cos(0), 1) +testit('cos(pi/2)', math.cos(math.pi/2), 0) +testit('cos(pi)', math.cos(math.pi), -1) + +print 'cosh' +testit('cosh(0)', math.cosh(0), 1) +testit('cosh(2)-2*cosh(1)**2', math.cosh(2)-2*math.cosh(1)**2, -1) # Thanks to Lambert + +print 'exp' +testit('exp(-1)', math.exp(-1), 1/math.e) +testit('exp(0)', math.exp(0), 1) +testit('exp(1)', math.exp(1), math.e) + +print 'fabs' +testit('fabs(-1)', math.fabs(-1), 1) +testit('fabs(0)', math.fabs(0), 0) +testit('fabs(1)', math.fabs(1), 1) + +print 'floor' +testit('floor(0.5)', math.floor(0.5), 0) +testit('floor(1.0)', math.floor(1.0), 1) +testit('floor(1.5)', math.floor(1.5), 1) +testit('floor(-0.5)', math.floor(-0.5), -1) +testit('floor(-1.0)', math.floor(-1.0), -1) +testit('floor(-1.5)', math.floor(-1.5), -2) + +print 'fmod' +testit('fmod(10,1)', math.fmod(10,1), 0) +testit('fmod(10,0.5)', math.fmod(10,0.5), 0) +testit('fmod(10,1.5)', math.fmod(10,1.5), 1) +testit('fmod(-10,1)', math.fmod(-10,1), 0) +testit('fmod(-10,0.5)', math.fmod(-10,0.5), 0) +testit('fmod(-10,1.5)', math.fmod(-10,1.5), -1) + +print 'frexp' +def testfrexp(name, (mant, exp), (emant, eexp)): + if abs(mant-emant) > eps or exp <> eexp: + raise TestFailed, '%s returned %s, expected %s'%\ + (name, `mant, exp`, `emant,eexp`) + +testfrexp('frexp(-1)', math.frexp(-1), (-0.5, 1)) +testfrexp('frexp(0)', math.frexp(0), (0, 0)) +testfrexp('frexp(1)', math.frexp(1), (0.5, 1)) +testfrexp('frexp(2)', math.frexp(2), (0.5, 2)) + +print 'hypot' +testit('hypot(0,0)', math.hypot(0,0), 0) +testit('hypot(3,4)', math.hypot(3,4), 5) + +print 'ldexp' +testit('ldexp(0,1)', math.ldexp(0,1), 0) +testit('ldexp(1,1)', math.ldexp(1,1), 2) +testit('ldexp(1,-1)', math.ldexp(1,-1), 0.5) +testit('ldexp(-1,1)', math.ldexp(-1,1), -2) + +print 'log' +testit('log(1/e)', math.log(1/math.e), -1) +testit('log(1)', math.log(1), 0) +testit('log(e)', math.log(math.e), 1) + +print 'log10' +testit('log10(0.1)', math.log10(0.1), -1) +testit('log10(1)', math.log10(1), 0) +testit('log10(10)', math.log10(10), 1) + +print 'modf' +def testmodf(name, (v1, v2), (e1, e2)): + if abs(v1-e1) > eps or abs(v2-e2): + raise TestFailed, '%s returned %s, expected %s'%\ + (name, `v1,v2`, `e1,e2`) + +testmodf('modf(1.5)', math.modf(1.5), (0.5, 1.0)) +testmodf('modf(-1.5)', math.modf(-1.5), (-0.5, -1.0)) + +print 'pow' +testit('pow(0,1)', math.pow(0,1), 0) +testit('pow(1,0)', math.pow(1,0), 1) +testit('pow(2,1)', math.pow(2,1), 2) +testit('pow(2,-1)', math.pow(2,-1), 0.5) + +print 'sin' +testit('sin(0)', math.sin(0), 0) +testit('sin(pi/2)', math.sin(math.pi/2), 1) +testit('sin(-pi/2)', math.sin(-math.pi/2), -1) + +print 'sinh' +testit('sinh(0)', math.sinh(0), 0) +testit('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1) +testit('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0) + +print 'sqrt' +testit('sqrt(0)', math.sqrt(0), 0) +testit('sqrt(1)', math.sqrt(1), 1) +testit('sqrt(4)', math.sqrt(4), 2) + +print 'tan' +testit('tan(0)', math.tan(0), 0) +testit('tan(pi/4)', math.tan(math.pi/4), 1) +testit('tan(-pi/4)', math.tan(-math.pi/4), -1) + +print 'tanh' +testit('tanh(0)', math.tanh(0), 0) +testit('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0) diff --git a/Lib/dos_8x3/tracebac.py b/Lib/dos_8x3/tracebac.py index 8d2dfdc..9823100 100755 --- a/Lib/dos_8x3/tracebac.py +++ b/Lib/dos_8x3/tracebac.py @@ -7,6 +7,25 @@ import types def _print(file, str='', terminator='\n'): file.write(str+terminator) + + +def print_list(extracted_list, file=None): + if not file: + file = sys.stderr + for filename, lineno, name, line in extracted_list: + _print(file, + ' File "%s", line %d, in %s' % (filename,lineno,name)) + if line: + _print(file, ' %s' % string.strip(line)) + +def format_list(extracted_list): + list = [] + for filename, lineno, name, line in extracted_list: + item = ' File "%s", line %d, in %s\n' % (filename,lineno,name) + if line: + item = item + ' %s\n' % string.strip(line) + list.append(item) + return list def print_tb(tb, limit=None, file=None): @@ -30,13 +49,7 @@ def print_tb(tb, limit=None, file=None): n = n+1 def format_tb(tb, limit = None): - list = [] - for filename, lineno, name, line in extract_tb(tb, limit): - item = ' File "%s", line %d, in %s\n' % (filename,lineno,name) - if line: - item = item + ' %s\n' % string.strip(line) - list.append(item) - return list + return format_list(extract_tb(tb, limit)) def extract_tb(tb, limit = None): if limit is None: @@ -123,3 +136,48 @@ def print_last(limit=None, file=None): file = sys.stderr print_exception(sys.last_type, sys.last_value, sys.last_traceback, limit, file) + + +def print_stack(f=None, limit=None, file=None): + if f is None: + try: + raise ZeroDivisionError + except ZeroDivisionError: + tb = sys.exc_traceback + f = tb.tb_frame.f_back + print_list(extract_stack(f, limit), file) + +def format_stack(f=None, limit=None): + if f is None: + try: + raise ZeroDivisionError + except ZeroDivisionError: + tb = sys.exc_traceback + f = tb.tb_frame.f_back + return format_list(extract_stack(t, limit)) + +def extract_stack(f=None, limit = None): + if f is None: + try: + raise ZeroDivisionError + except ZeroDivisionError: + tb = sys.exc_traceback + f = tb.tb_frame.f_back + if limit is None: + if hasattr(sys, 'tracebacklimit'): + limit = sys.tracebacklimit + list = [] + n = 0 + while f is not None and (limit is None or n < limit): + lineno = f.f_lineno + co = f.f_code + filename = co.co_filename + name = co.co_name + line = linecache.getline(filename, lineno) + if line: line = string.strip(line) + else: line = None + list.append(filename, lineno, name, line) + f = f.f_back + n = n+1 + list.reverse() + return list -- cgit v0.12