Merge alpha100 branch back to main trunk

This commit is contained in:
Guido van Rossum 1994-08-01 11:34:53 +00:00
parent 2979b01ff8
commit b6775db241
176 changed files with 5302 additions and 3668 deletions

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -30,6 +30,10 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* "allobjects.c" -- Source for precompiled header "allobjects.h" */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef THINK_C
#define macintosh
#endif
@ -37,7 +41,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdio.h>
#include <string.h>
#include "PROTO.h"
#include "myproto.h"
#include "object.h"
#include "objimpl.h"

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -28,7 +28,13 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#ifdef MPW /* This is for MPW's File command */
#define assert(e) { if (!(e)) { printf("### Python: Assertion failed:\n\
File %s; Line %d\n", __FILE__, __LINE__); abort(); } }
#else
#define assert(e) { if (!(e)) { printf("Assertion failed\n"); abort(); } }
#endif
#ifdef __cplusplus
}

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -31,6 +31,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Built-in module interface */
extern object *getbuiltin PROTO((object *));
extern int setbuiltin PROTO((char *, object *));
#ifdef __cplusplus
}

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -35,6 +35,7 @@ object *call_object PROTO((object *, object *));
object *getglobals PROTO((void));
object *getlocals PROTO((void));
object *getowner PROTO((void));
object *getframe PROTO((void));
void printtraceback PROTO((object *));
void flushline PROTO((void));
@ -87,7 +88,7 @@ extern void init_save_thread PROTO((void));
extern object *save_thread PROTO((void));
extern void restore_thread PROTO((object *));
#ifdef USE_THREAD
#ifdef WITH_THREAD
#define BGN_SAVE { \
object *_save; \
@ -97,14 +98,14 @@ extern void restore_thread PROTO((object *));
#define END_SAVE restore_thread(_save); \
}
#else /* !USE_THREAD */
#else /* !WITH_THREAD */
#define BGN_SAVE {
#define RET_SAVE
#define RES_SAVE
#define END_SAVE }
#endif /* !USE_THREAD */
#endif /* !WITH_THREAD */
#ifdef __cplusplus
}

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -35,7 +35,7 @@ typedef char *string;
#define mknewlongobject(x) newintobject(x)
#define mknewshortobject(x) newintobject((long)x)
#define mknewfloatobject(x) newfloatobject(x)
#define mknewcharobject(c) mkvalue("c", c)
#define mknewcharobject(ch) mkvalue("c", ch)
extern int getiobjectarg PROTO((object *args, int nargs, int i, object **p_a));
extern int getilongarg PROTO((object *args, int nargs, int i, long *p_a));

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -29,11 +29,15 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
/* Error codes passed around between file input, tokenizer, parser and
interpreter. This was necessary so we can turn them into Python
exceptions at a higher level. */
interpreter. This is necessary so we can turn them into Python
exceptions at a higher level. Note that some errors have a
slightly different meaning when passed from the tokenizer to the
parser than when passed from the parser to the interpreter; e.g.
the parser only returns E_EOF when it hits EOF immediately, and it
never returns E_OK. */
#define E_OK 10 /* No error */
#define E_EOF 11 /* (Unexpected) EOF read */
#define E_EOF 11 /* End Of File */
#define E_INTR 12 /* Interrupted */
#define E_TOKEN 13 /* Bad token */
#define E_SYNTAX 14 /* Syntax error */

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -33,7 +33,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
void err_set PROTO((object *));
void err_setval PROTO((object *, object *));
void err_setstr PROTO((object *, char *));
int err_occurred PROTO((void));
object *err_occurred PROTO((void));
void err_get PROTO((object **, object **));
void err_clear PROTO((void));
@ -64,12 +64,13 @@ extern object *ZeroDivisionError;
extern int err_badarg PROTO((void));
extern object *err_nomem PROTO((void));
extern object *err_errno PROTO((object *));
extern void err_input PROTO((int));
extern void err_badcall PROTO((void));
extern object *err_getexc PROTO((void));
extern int sigcheck PROTO((void)); /* In sigcheck.c or signalmodule.c */
#ifdef __cplusplus
}
#endif

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -35,6 +35,7 @@ extern typeobject Filetype;
#define is_fileobject(op) ((op)->ob_type == &Filetype)
extern object *newfileobject PROTO((char *, char *));
extern void setfilebufsize PROTO((object *, int));
extern object *newopenfileobject
PROTO((FILE *, char *, char *, int (*)FPROTO((FILE *))));
extern FILE *getfilefile PROTO((object *));

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -52,6 +52,7 @@ typedef struct _frame {
int f_iblock; /* index in f_blockstack */
int f_lasti; /* Last instruction if called */
int f_lineno; /* Current line number */
object *f_trace; /* Trace function */
} frameobject;
@ -70,11 +71,11 @@ frameobject * newframeobject PROTO(
/* List access macros */
#ifdef NDEBUG
#define GETITEM(v, i) GETLISTITEM((listobject *)(v), (i))
#define GETITEM(v, i) GETTUPLEITEM((tupleobject *)(v), (i))
#define GETITEMNAME(v, i) GETSTRINGVALUE((stringobject *)GETITEM((v), (i)))
#else
#define GETITEM(v, i) getlistitem((v), (i))
#define GETITEMNAME(v, i) getstringvalue(getlistitem((v), (i)))
#define GETITEM(v, i) gettupleitem((v), (i))
#define GETITEMNAME(v, i) getstringvalue(GETITEM(v, i))
#endif
#define GETUSTRINGVALUE(s) ((unsigned char *)GETSTRINGVALUE(s))
@ -95,6 +96,11 @@ block *pop_block PROTO((frameobject *));
object **extend_stack PROTO((frameobject *, int, int));
/* Conversions between "fast locals" and locals in dictionary */
void locals_2_fast PROTO((frameobject *, int));
void fast_2_locals PROTO((frameobject *));
#ifdef __cplusplus
}
#endif

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -35,6 +35,8 @@ typedef struct {
object *func_code;
object *func_globals;
object *func_name;
int func_argcount;
object *func_argdefs;
} funcobject;
extern typeobject Functype;
@ -44,6 +46,8 @@ extern typeobject Functype;
extern object *newfuncobject PROTO((object *, object *));
extern object *getfunccode PROTO((object *));
extern object *getfuncglobals PROTO((object *));
extern object *getfuncargstuff PROTO((object *, int *));
extern int setfuncargstuff PROTO((object *, int, object *));
#ifdef __cplusplus
}

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -34,7 +34,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* A label of an arc */
typedef struct _label {
typedef struct {
int lb_type;
char *lb_str;
} label;
@ -43,21 +43,21 @@ typedef struct _label {
/* A list of labels */
typedef struct _labellist {
typedef struct {
int ll_nlabels;
label *ll_label;
} labellist;
/* An arc from one state to another */
typedef struct _arc {
typedef struct {
short a_lbl; /* Label of this arc */
short a_arrow; /* State where this arc goes to */
} arc;
/* A state in a DFA */
typedef struct _state {
typedef struct {
int s_narcs;
arc *s_arc; /* Array of arcs */
@ -70,7 +70,7 @@ typedef struct _state {
/* A DFA */
typedef struct _dfa {
typedef struct {
int d_type; /* Non-terminal this represents */
char *d_name; /* For printing */
int d_initial; /* Initial state */
@ -81,7 +81,7 @@ typedef struct _dfa {
/* A grammar */
typedef struct _grammar {
typedef struct {
int g_ndfas;
dfa *g_dfa; /* Array of DFAs */
labellist g_ll;

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -62,6 +62,7 @@ extern int addlistitem PROTO((object *, object *));
extern object *getlistslice PROTO((object *, int, int));
extern int setlistslice PROTO((object *, int, int, object *));
extern int sortlist PROTO((object *));
extern object *listtuple PROTO((object *));
/* Macro, trading safety for speed */
#define GETLISTITEM(op, i) ((op)->ob_item[i])

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -42,6 +42,7 @@ extern long getlongvalue PROTO((object *));
extern double dgetlongvalue PROTO((object *));
object *long_scan PROTO((char *, int));
object *long_escan PROTO((char *, char **, int));
#ifdef __cplusplus
}

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -30,21 +30,28 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Module support interface */
#ifdef HAVE_PROTOTYPES
#define USE_STDARG
#ifdef HAVE_STDARG_PROTOTYPES
#include <stdarg.h>
extern int getargs PROTO((object *, char *, ...));
extern object *mkvalue PROTO((char *, ...));
#else
#include <varargs.h>
/* Better to have no prototypes at all for varargs functions in this case */
extern int getargs();
extern object *mkvalue();
#endif
#ifdef USE_STDARG
#include <stdarg.h>
#else
#include <varargs.h>
#endif
extern int vgetargs PROTO((object *, char *, va_list));
extern object *vmkvalue PROTO((char *, va_list));
extern object *initmodule PROTO((char *, struct methodlist *));
extern int getargs PROTO((object *, char *, ...));
extern int vgetargs PROTO((object *, char *, va_list));
extern object *mkvalue PROTO((char *, ...));
extern object *vmkvalue PROTO((char *, va_list));
extern object *initmodule2 PROTO((char *, struct methodlist *, object *));
/* The following are obsolete -- use getargs directly! */
#define getnoarg(v) getargs(v, "")

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -32,41 +32,35 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifdef macintosh
#define ANY void
#ifndef THINK_C_3_0
#define HAVE_STDLIB
#endif
#endif
#ifdef sun
/* Maybe not for very old versions of SunOS ? */
#define HAVE_STDLIB
#endif
#ifdef sgi
#define HAVE_STDLIB
#endif
#ifdef __STDC__
#define ANY void
#define HAVE_STDLIB
#endif
#ifdef __TURBOC__
#define ANY void
#define HAVE_STDLIB
#endif
#ifdef __GNUC__
#define ANY void
#define HAVE_STDLIB
#endif
#ifndef ANY
#define ANY char
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else /* !HAVE_STDLIB */
extern ANY *malloc PROTO((size_t));
extern ANY *calloc PROTO((size_t, size_t));
extern ANY *realloc PROTO((ANY *, size_t));
extern void free PROTO((ANY *)); /* XXX sometimes int on Unix old systems */
#endif /* !HAVE_STDLIB */
#ifndef NULL
#define NULL 0
#define NULL ((ANY *)0)
#endif
/* XXX Always allocate one extra byte, since some malloc's return NULL
@ -80,17 +74,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define DEL(p) free((ANY *)p)
#define XDEL(p) if ((p) == NULL) ; else DEL(p)
#ifdef HAVE_STDLIB
#include <stdlib.h>
#define MALLARG size_t
#else
#define MALLARG size_t
extern ANY *malloc PROTO((MALLARG));
extern ANY *calloc PROTO((MALLARG, MALLARG));
extern ANY *realloc PROTO((ANY *, MALLARG));
extern void free PROTO((ANY *)); /* XXX sometimes int on Unix old systems */
#endif
#ifdef __cplusplus
}
#endif

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -28,38 +28,28 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
/* Common definitions for files that use the BSD select system call.
This is so complicated because every UNIX variant requires that
you include a different set of headers. Customizing this one file
should be easier than patching each of the files using select()... */
/* Include file for users of select() */
/* NB caller must include <sys/types.h> */
/* XXX You may have to include some of these only if not already included */
#include <sys/types.h>
#include <sys/time.h> /* Implies <time.h> everywhere, as far as I know */
#include <sys/param.h>
#ifdef HAVE_SYS_SELECT_H
/* Hacks for various systems that need hand-holding... */
#ifdef _SEQUENT_
#include <sys/select.h>
/* Sequent doesn't seem to define struct timezone anywhere?!?! */
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
#endif
#ifdef _AIX /* I *think* this works */
/* AIX defines fd_set in a separate file. Sigh... */
#include <sys/select.h>
#endif
#ifdef SYS_SELECT_WITH_SYS_TIME
#include "mytime.h"
#else /* !SYS_SELECT_WITH_SYS_TIME */
#include <time.h>
#endif /* !SYS_SELECT_WITH_SYS_TIME */
#else /* !HAVE_SYS_SELECT_H */
#include "mytime.h"
/* (Very) old versions of BSD don't define the FD_* set of macros.
The following will usually do... */
#endif /* !HAVE_SYS_SELECT_H */
/* If the fd manipulation macros aren't defined,
here is a set that should do the job */
#ifndef FD_SETSIZE
#define FD_SETSIZE 256
@ -67,12 +57,12 @@ struct timezone {
#ifndef FD_SET
typedef long fd_mask;
typedef long fd_mask;
#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y))
#endif
#endif /* howmany */
typedef struct fd_set {
fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -133,48 +133,66 @@ NB: the methods for certain type groups are now contained in separate
method blocks.
*/
typedef object * (*unaryfunc) PROTO((object *));
typedef object * (*binaryfunc) PROTO((object *, object *));
typedef int (*inquiry) PROTO((object *));
typedef int (*coercion) PROTO((object **, object **));
typedef object *(*intargfunc) PROTO((object *, int));
typedef object *(*intintargfunc) PROTO((object *, int, int));
typedef int(*intobjargproc) PROTO((object *, int, object *));
typedef int(*intintobjargproc) PROTO((object *, int, int, object *));
typedef int(*objobjargproc) PROTO((object *, object *, object *));
typedef struct {
object *(*nb_add) FPROTO((object *, object *));
object *(*nb_subtract) FPROTO((object *, object *));
object *(*nb_multiply) FPROTO((object *, object *));
object *(*nb_divide) FPROTO((object *, object *));
object *(*nb_remainder) FPROTO((object *, object *));
object *(*nb_divmod) FPROTO((object *, object *));
object *(*nb_power) FPROTO((object *, object *));
object *(*nb_negative) FPROTO((object *));
object *(*nb_positive) FPROTO((object *));
object *(*nb_absolute) FPROTO((object *));
int (*nb_nonzero) FPROTO((object *));
object *(*nb_invert) FPROTO((object *));
object *(*nb_lshift) FPROTO((object *, object *));
object *(*nb_rshift) FPROTO((object *, object *));
object *(*nb_and) FPROTO((object *, object *));
object *(*nb_xor) FPROTO((object *, object *));
object *(*nb_or) FPROTO((object *, object *));
int (*nb_coerce) FPROTO((object **, object **));
object *(*nb_int) FPROTO((object *));
object *(*nb_long) FPROTO((object *));
object *(*nb_float) FPROTO((object *));
object *(*nb_oct) FPROTO((object *));
object *(*nb_hex) FPROTO((object *));
binaryfunc nb_add;
binaryfunc nb_subtract;
binaryfunc nb_multiply;
binaryfunc nb_divide;
binaryfunc nb_remainder;
binaryfunc nb_divmod;
binaryfunc nb_power;
unaryfunc nb_negative;
unaryfunc nb_positive;
unaryfunc nb_absolute;
inquiry nb_nonzero;
unaryfunc nb_invert;
binaryfunc nb_lshift;
binaryfunc nb_rshift;
binaryfunc nb_and;
binaryfunc nb_xor;
binaryfunc nb_or;
coercion nb_coerce;
unaryfunc nb_int;
unaryfunc nb_long;
unaryfunc nb_float;
unaryfunc nb_oct;
unaryfunc nb_hex;
} number_methods;
typedef struct {
int (*sq_length) FPROTO((object *));
object *(*sq_concat) FPROTO((object *, object *));
object *(*sq_repeat) FPROTO((object *, int));
object *(*sq_item) FPROTO((object *, int));
object *(*sq_slice) FPROTO((object *, int, int));
int (*sq_ass_item) FPROTO((object *, int, object *));
int (*sq_ass_slice) FPROTO((object *, int, int, object *));
inquiry sq_length;
binaryfunc sq_concat;
intargfunc sq_repeat;
intargfunc sq_item;
intintargfunc sq_slice;
intobjargproc sq_ass_item;
intintobjargproc sq_ass_slice;
} sequence_methods;
typedef struct {
int (*mp_length) FPROTO((object *));
object *(*mp_subscript) FPROTO((object *, object *));
int (*mp_ass_subscript) FPROTO((object *, object *, object *));
inquiry mp_length;
binaryfunc mp_subscript;
objobjargproc mp_ass_subscript;
} mapping_methods;
typedef void (*destructor) PROTO((object *));
typedef int (*printfunc) PROTO((object *, FILE *, int));
typedef object *(*getattrfunc) PROTO((object *, char *));
typedef int (*setattrfunc) PROTO((object *, char *, object *));
typedef int (*cmpfunc) PROTO((object *, object *));
typedef object *(*reprfunc) PROTO((object *));
typedef long (*hashfunc) PROTO((object *));
typedef struct _typeobject {
OB_VARHEAD
char *tp_name; /* For printing */
@ -182,12 +200,12 @@ typedef struct _typeobject {
/* Methods to implement standard operations */
void (*tp_dealloc) FPROTO((object *));
int (*tp_print) FPROTO((object *, FILE *, int));
object *(*tp_getattr) FPROTO((object *, char *));
int (*tp_setattr) FPROTO((object *, char *, object *));
int (*tp_compare) FPROTO((object *, object *));
object *(*tp_repr) FPROTO((object *));
destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
reprfunc tp_repr;
/* Method suites for standard classes */
@ -197,7 +215,8 @@ typedef struct _typeobject {
/* More standard operations (at end for binary compatibility) */
long (*tp_hash) FPROTO((object *));
hashfunc tp_hash;
binaryfunc tp_call;
#ifdef COUNT_ALLOCS
/* these must be last */
int tp_alloc;
@ -326,6 +345,29 @@ extern object NoObject; /* Don't use this directly */
#define None (&NoObject)
/*
A common programming style in Python requires the forward declaration
of static, initialized structures, e.g. for a typeobject that is used
by the functions whose address must be used in the initializer.
Some compilers (notably SCO ODT 3.0, I seem to remember early AIX as
well) botch this if you use the static keyword for both declarations
(they allocate two objects, and use the first, uninitialized one until
the second declaration is encountered). Therefore, the forward
declaration should use the 'forwardstatic' keyword. This expands to
static on most systems, but to extern on a few. The actual storage
and name will still be static because the second declaration is
static, so no linker visible symbols will be generated. (Standard C
compilers take offense to the extern forward declaration of a static
object, so I can't just put extern in all cases. :-( )
*/
#ifdef BAD_STATIC_FORWARD
#define staticforward extern
#else
#define staticforward static
#endif /* BAD_STATIC_FORWARD */
/*
123456789-123456789-123456789-123456789-123456789-123456789-123456789-12

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -119,6 +119,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define LOAD_LOCAL 115 /* Index in name list */
#define LOAD_GLOBAL 116 /* Index in name list */
#define SET_FUNC_ARGS 117 /* Argcount */
#define SETUP_LOOP 120 /* Target address (absolute) */
#define SETUP_EXCEPT 121 /* "" */
#define SETUP_FINALLY 122 /* "" */

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -36,7 +36,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define DELIM ' '
#endif
#ifdef MSDOS
#if defined(MSDOS) || defined(NT)
#define SEP '\\'
#define MAXPATHLEN 256
#define DELIM ';'

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -30,9 +30,17 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Parser-tokenizer link interface */
extern int parsestring PROTO((char *, grammar *, int, node **_ret));
extern int parsefile PROTO((FILE *, char *, grammar *, int,
char *, char *, node **));
typedef struct {
int error;
char *filename;
int lineno;
int offset;
char *text;
} perrdetail;
extern node *parsestring PROTO((char *, grammar *, int, perrdetail *));
extern node *parsefile PROTO((FILE *, char *, grammar *, int,
char *, char *, perrdetail *));
#ifdef __cplusplus
}

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -31,9 +31,12 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Include files and extern declarations used by most of the parser.
This is a precompiled header for THINK C. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef THINK_C
#define macintosh
/* #define THINK_C_3_0 /*** TURN THIS ON FOR THINK C 3.0 ***/
#endif
#include <stdio.h>
@ -44,17 +47,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#undef label
#endif
#ifdef THINK_C_3_0
#include <proto.h>
#endif
#ifdef macintosh
#ifndef THINK_C_3_0
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#endif
#include "PROTO.h"
#include "myproto.h"
#include "mymalloc.h"
extern void fatal PROTO((char *));

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -33,7 +33,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
void err_set PROTO((object *));
void err_setval PROTO((object *, object *));
void err_setstr PROTO((object *, char *));
int err_occurred PROTO((void));
object *err_occurred PROTO((void));
void err_get PROTO((object **, object **));
void err_clear PROTO((void));
@ -64,12 +64,13 @@ extern object *ZeroDivisionError;
extern int err_badarg PROTO((void));
extern object *err_nomem PROTO((void));
extern object *err_errno PROTO((object *));
extern void err_input PROTO((int));
extern void err_badcall PROTO((void));
extern object *err_getexc PROTO((void));
extern int sigcheck PROTO((void)); /* In sigcheck.c or signalmodule.c */
#ifdef __cplusplus
}
#endif

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -39,8 +39,8 @@ int run_script PROTO((FILE *, char *));
int run_tty_1 PROTO((FILE *, char *));
int run_tty_loop PROTO((FILE *, char *));
int parse_string PROTO((char *, int, struct _node **));
int parse_file PROTO((FILE *, char *, int, struct _node **));
struct _node *parse_string PROTO((char *, int));
struct _node *parse_file PROTO((FILE *, char *, int));
object *run_string PROTO((char *, int, object *, object *));
object *run_file PROTO((FILE *, char *, int, object *, object *));
@ -51,6 +51,8 @@ void print_error PROTO((void));
void goaway PROTO((int));
void cleanup PROTO((void));
#ifdef __cplusplus
}
#endif

View file

@ -1,6 +1,9 @@
#ifndef _THREAD_H_included
#define _THREAD_H_included
#define NO_EXIT_PROG /* don't define exit_prog() */
/* (the result is no use of signals on SGI) */
#ifndef PROTO
#if defined(__STDC__) || defined(__cplusplus)
#define PROTO(args) args
@ -20,6 +23,7 @@ void init_thread PROTO((void));
int start_new_thread PROTO((void (*)(void *), void *));
void exit_thread PROTO((void));
void _exit_thread PROTO((void));
long get_thread_ident PROTO((void));
type_lock allocate_lock PROTO((void));
void free_lock PROTO((type_lock));
@ -33,8 +37,10 @@ void free_sema PROTO((type_sema));
void down_sema PROTO((type_sema));
void up_sema PROTO((type_sema));
#ifndef NO_EXIT_PROG
void exit_prog PROTO((int));
void _exit_prog PROTO((int));
#endif
#ifdef __cplusplus
}

View file

@ -1,5 +1,5 @@
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@ -66,6 +66,7 @@ extern object *newstringobject PROTO((char *));
extern unsigned int getstringsize PROTO((object *));
extern char *getstringvalue PROTO((object *));
extern void joinstring PROTO((object **, object *));
extern void joinstring_decref PROTO((object **, object *));
extern int resizestring PROTO((object **, int));
extern object *formatstring PROTO((object *, object *));

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -1,6 +1,9 @@
#ifndef _THREAD_H_included
#define _THREAD_H_included
#define NO_EXIT_PROG /* don't define exit_prog() */
/* (the result is no use of signals on SGI) */
#ifndef PROTO
#if defined(__STDC__) || defined(__cplusplus)
#define PROTO(args) args
@ -20,6 +23,7 @@ void init_thread PROTO((void));
int start_new_thread PROTO((void (*)(void *), void *));
void exit_thread PROTO((void));
void _exit_thread PROTO((void));
long get_thread_ident PROTO((void));
type_lock allocate_lock PROTO((void));
void free_lock PROTO((type_lock));
@ -33,8 +37,10 @@ void free_sema PROTO((type_sema));
void down_sema PROTO((type_sema));
void up_sema PROTO((type_sema));
#ifndef NO_EXIT_PROG
void exit_prog PROTO((int));
void _exit_prog PROTO((int));
#endif
#ifdef __cplusplus
}

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -5,7 +5,7 @@ extern "C" {
#endif
/***********************************************************
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved

View file

@ -1,11 +1,9 @@
# A more or less complete user-defined wrapper around list objects
class UserList:
def __init__(self, *args):
if len(args) > 1: raise TypeError, 'too many args'
def __init__(self, list = None):
self.data = []
if args:
list = args[0]
if list is not None:
if type(list) == type(self.data):
self.data[:] = list
else:

View file

@ -179,7 +179,10 @@ def _read_short(file):
def _read_string(file):
length = ord(file.read(1))
data = file.read(length)
if length == 0:
data = ''
else:
data = file.read(length)
if length & 1 == 0:
dummy = file.read(1)
return data

View file

@ -1,28 +1,40 @@
import AL, SUNAUDIODEV
error = 'audiodev.error'
class Play_Audio_sgi:
# Private instance variables
access frameratelist, nchannelslist, sampwidthlist, oldparams, \
params, config, inited_outrate, inited_width, \
inited_nchannels, port, converter: private
inited_nchannels, port, converter, classinited: private
frameratelist = [(48000, AL.RATE_48000),
(44100, AL.RATE_44100),
(32000, AL.RATE_32000),
(22050, AL.RATE_22050),
(16000, AL.RATE_16000),
(11025, AL.RATE_11025),
( 8000, AL.RATE_8000)]
nchannelslist = [(1, AL.MONO),
(2, AL.STEREO)]
sampwidthlist = [(1, AL.SAMPLE_8),
(2, AL.SAMPLE_16),
(3, AL.SAMPLE_24)]
classinited = 0
frameratelist = nchannelslist = sampwidthlist = None
def initclass(self):
import AL
Play_Audio_sgi.frameratelist = [
(48000, AL.RATE_48000),
(44100, AL.RATE_44100),
(32000, AL.RATE_32000),
(22050, AL.RATE_22050),
(16000, AL.RATE_16000),
(11025, AL.RATE_11025),
( 8000, AL.RATE_8000),
]
Play_Audio_sgi.nchannelslist = [
(1, AL.MONO),
(2, AL.STEREO),
]
Play_Audio_sgi.sampwidthlist = [
(1, AL.SAMPLE_8),
(2, AL.SAMPLE_16),
(3, AL.SAMPLE_24),
]
Play_Audio_sgi.classinited = 1
def __init__(self):
import al
import al, AL
if not self.classinited:
self.initclass()
self.oldparams = []
self.params = [AL.OUTPUT_RATE, 0]
self.config = al.newconfig()
@ -37,7 +49,7 @@ def __del__(self):
if self.port:
self.stop()
if self.oldparams:
import al
import al, AL
al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
self.oldparams = []
@ -54,7 +66,7 @@ def stop(self):
self.port.closeport()
self.port = None
if self.oldparams:
import al
import al, AL
al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
self.oldparams = []
@ -75,6 +87,7 @@ def setsampwidth(self, width):
break
else:
if width == 0:
import AL
self.inited_width = 0
self.config.setwidth(AL.SAMPLE_16)
self.converter = self.ulaw2lin
@ -94,7 +107,7 @@ def writeframes(self, data):
if not (self.inited_outrate and self.inited_nchannels):
raise error, 'params not specified'
if not self.port:
import al
import al, AL
self.port = al.openport('Python', 'w', self.config)
self.oldparams = self.params[:]
al.getparams(AL.DEFAULT_DEVICE, self.oldparams)
@ -156,7 +169,7 @@ def writeframes(self, data):
if not (self.inited_outrate and self.inited_width and self.inited_nchannels):
raise error, 'params not specified'
if not self.port:
import sunaudiodev
import sunaudiodev, SUNAUDIODEV
self.port = sunaudiodev.open('w')
info = self.port.getinfo()
info.o_sample_rate = self.outrate

View file

@ -17,6 +17,8 @@ def __init__(self):
self.breaks = {}
def reset(self):
import linecache
linecache.checkcache()
self.botframe = None
self.stopframe = None
self.returnframe = None
@ -134,11 +136,35 @@ def set_return(self, frame):
self.returnframe = frame
self.quitting = 0
def set_trace(self):
# Start debugging from here
try:
1 + ''
except:
frame = sys.exc_traceback.tb_frame.f_back
self.reset()
while frame:
frame.f_trace = self.trace_dispatch
self.botframe = frame
frame = frame.f_back
self.set_step()
sys.settrace(self.trace_dispatch)
def set_continue(self):
# Don't stop except at breakpoints or when finished
self.stopframe = self.botframe
self.returnframe = None
self.quitting = 0
if not self.breaks:
# no breakpoints; run without debugger overhead
sys.settrace(None)
try:
1 + '' # raise an exception
except:
frame = sys.exc_traceback.tb_frame.f_back
while frame and frame is not self.botframe:
del frame.f_trace
frame = frame.f_back
def set_quit(self):
self.stopframe = self.botframe
@ -177,7 +203,7 @@ def clear_all_file_breaks(self, filename):
return 'There are no breakpoints in that file!'
del self.breaks[filename]
def clear_all_breaks(self, filename, lineno):
def clear_all_breaks(self):
if not self.breaks:
return 'There are no breakpoints!'
self.breaks = {}
@ -217,11 +243,14 @@ def get_stack(self, f, t):
#
def format_stack_entry(self, frame_lineno):
import codehack, linecache, repr, string
import linecache, repr, string
frame, lineno = frame_lineno
filename = frame.f_code.co_filename
s = filename + '(' + `lineno` + ')'
s = s + codehack.getcodename(frame.f_code)
if frame.f_code.co_name:
s = s + frame.f_code.co_name
else:
s = s + "<lambda>"
if frame.f_locals.has_key('__args__'):
args = frame.f_locals['__args__']
if args is not None:
@ -269,17 +298,19 @@ def runcall(self, func, *args):
sys.settrace(None)
def set_trace():
Bdb().set_trace()
# -------------------- testing --------------------
class Tdb(Bdb):
def user_call(self, frame, args):
import codehack
name = codehack.getcodename(frame.f_code)
name = frame.f_code.co_name
if not name: name = '???'
print '+++ call', name, args
def user_line(self, frame):
import linecache, string, codehack
name = codehack.getcodename(frame.f_code)
import linecache, string
name = frame.f_code.co_name
if not name: name = '???'
fn = frame.f_code.co_filename
line = linecache.getline(fn, frame.f_lineno)
@ -300,7 +331,5 @@ def bar(a):
return a/2
def test():
import linecache
linecache.checkcache()
t = Tdb()
t.run('import bdb; bdb.foo(10)')

View file

@ -106,12 +106,7 @@ def weekheader(width):
return str
# Print a month's calendar
def prmonth(year, month, *rest):
if rest[2:]: raise TypeError, 'too many args'
w = 0
l = 0
if rest[0:]: w = rest[0]
if rest[1:]: l = rest[1]
def prmonth(year, month, w = 0, l = 0):
w = max(2, w)
l = max(1, l)
print _center(month_name[month] + ' ' + `year`, 7*(w+1) - 1),

View file

@ -56,8 +56,36 @@ def do_help(self, arg):
else:
import newdir
names = newdir.dir(self.__class__)
cmds = []
cmds_doc = []
cmds_undoc = []
help = {}
for name in names:
if name[:5] == 'help_':
help[name[5:]]=1
for name in names:
if name[:3] == 'do_':
cmds.append(name[3:])
print cmds
cmd=name[3:]
if help.has_key(cmd):
cmds_doc.append(cmd)
del help[cmd]
else:
cmds_undoc.append(cmd)
print
self.print_topics("Documented commands (type help " \
"<topic>):",cmds_doc, 15, 80)
self.print_topics("Miscellaneous help topics:",
help.keys(), 15, 80)
self.print_topics("Undocumented commands:",
cmds_undoc, 15, 80)
def print_topics(self, header, cmds, cmdlen, maxcol):
if cmds:
print header;
print "="*len(header)
(cmds_per_line,junk)=divmod(maxcol,cmdlen)
col=cmds_per_line
for cmd in cmds:
if col==0: print
print (("%-"+`cmdlen`+"s") % cmd),
col = (col+1) % cmds_per_line
print "\n"

View file

@ -7,6 +7,10 @@
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.
# 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:

View file

@ -135,7 +135,8 @@ def jabs_op(name, op):
def_op('RAISE_EXCEPTION', 81)
def_op('LOAD_LOCALS', 82)
def_op('RETURN_VALUE', 83)
def_op('LOAD_GLOBALS', 84)
def_op('EXEC_STMT', 85)
def_op('BUILD_FUNCTION', 86)
def_op('POP_BLOCK', 87)
def_op('END_FINALLY', 88)
@ -173,6 +174,7 @@ def jabs_op(name, op):
name_op('LOAD_LOCAL', 115) # Index in name list
name_op('LOAD_GLOBAL', 116) # Index in name list
def_op('SET_FUNC_ARGS', 117) # Argcount
jrel_op('SETUP_LOOP', 120) # Distance to target address
jrel_op('SETUP_EXCEPT', 121) # ""

View file

@ -9,10 +9,7 @@
# >>> from ftplib import FTP
# >>> ftp = FTP('ftp.cwi.nl') # connect to host, default port
# >>> ftp.login() # default, i.e.: user anonymous, passwd user@hostname
# >>> def handle_one_line(line): # callback for ftp.retrlines
# ... print line
# ...
# >>> ftp.retrlines('LIST', handle_one_line) # list directory contents
# >>> ftp.retrlines('LIST') # list directory contents
# total 43
# d--x--x--x 2 root root 512 Jul 1 16:50 bin
# d--x--x--x 2 root root 512 Sep 16 1991 etc
@ -20,7 +17,7 @@
# drwxr-srwt 15 root ftp 10240 Nov 5 20:43 pub
# >>> ftp.quit()
#
# To download a file, use ftp.retrlines('RETR ' + filename, handle_one_line),
# To download a file, use ftp.retrlines('RETR ' + filename),
# or ftp.retrbinary() with slightly different arguments.
# To upload a file, use ftp.storlines() or ftp.storbinary(), which have
# an open file as argument.
@ -30,9 +27,14 @@
import os
import sys
import socket
import string
# Import SOCKS module if it exists, else standard socket module socket
try:
import SOCKS; socket = SOCKS
except ImportError:
import socket
# Magic number from <socket.h>
MSG_OOB = 0x1 # Process data out of band
@ -59,14 +61,6 @@
CRLF = '\r\n'
# Next port to be used by makeport(), with PORT_OFFSET added
# (This is now only used when the python interpreter doesn't support
# the getsockname() method yet)
nextport = 0
PORT_OFFSET = 40000
PORT_CYCLE = 1000
# The class itself
class FTP:
@ -74,7 +68,7 @@ class FTP:
# Initialize host to localhost, port to standard ftp port
# Optional arguments are host (for connect()),
# and user, passwd, acct (for login())
def __init__(self, *args):
def __init__(self, host = '', user = '', passwd = '', acct = ''):
# Initialize the instance to something mostly harmless
self.debugging = 0
self.host = ''
@ -82,18 +76,16 @@ def __init__(self, *args):
self.sock = None
self.file = None
self.welcome = None
if args:
self.connect(args[0])
if args[1:]:
apply(self.login, args[1:])
if host:
self.connect(host)
if user: self.login(user, passwd, acct)
# Connect to host. Arguments:
# - host: hostname to connect to (default previous host)
# - port: port to connect to (default previous port)
def connect(self, *args):
if args: self.host = args[0]
if args[1:]: self.port = args[1]
if args[2:]: raise TypeError, 'too many args'
def connect(self, host = '', port = 0):
if host: self.host = host
if port: self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(self.host, self.port)
self.file = self.sock.makefile('r')
@ -208,19 +200,8 @@ def sendport(self, port):
def makeport(self):
global nextport
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
getsockname = sock.getsockname
except AttributeError:
if self.debugging > 1:
print '*** getsockname not supported',
print '-- using manual port assignment ***'
port = nextport + PORT_OFFSET
nextport = (nextport + 1) % PORT_CYCLE
sock.bind('', port)
getsockname = None
sock.listen(0) # Assigns the port if not explicitly bound
if getsockname:
host, port = getsockname()
sock.listen(1)
host, port = sock.getsockname()
resp = self.sendport(port)
return sock
@ -235,13 +216,7 @@ def transfercmd(self, cmd):
return conn
# Login, default anonymous
def login(self, *args):
user = passwd = acct = ''
n = len(args)
if n > 3: raise TypeError, 'too many arguments'
if n > 0: user = args[0]
if n > 1: passwd = args[1]
if n > 2: acct = args[2]
def login(self, user = '', passwd = '', acct = ''):
if not user: user = 'anonymous'
if user == 'anonymous' and passwd in ('', '-'):
thishost = socket.gethostname()
@ -278,11 +253,7 @@ def retrbinary(self, cmd, callback, blocksize):
# The callback function is called for each line, with trailing
# CRLF stripped. This creates a new port for you.
# print_lines is the default callback
def retrlines(self, cmd, *args):
callback = None
if args:
callback = args[0]
if args[1:]: raise TypeError, 'too many args'
def retrlines(self, cmd, callback = None):
if not callback: callback = print_line
resp = self.sendcmd('TYPE A')
conn = self.transfercmd(cmd)
@ -423,30 +394,22 @@ def print_line(line):
# Usage: ftp [-d] host [-l[dir]] [-d[dir]] [file] ...
def test():
import marshal
global nextport
try:
nextport = marshal.load(open('.@nextport', 'r'))
except IOError:
pass
try:
debugging = 0
while sys.argv[1] == '-d':
debugging = debugging+1
del sys.argv[1]
host = sys.argv[1]
ftp = FTP(host)
ftp.set_debuglevel(debugging)
ftp.login()
for file in sys.argv[2:]:
if file[:2] == '-l':
ftp.dir(file[2:])
elif file[:2] == '-d':
cmd = 'CWD'
if file[2:]: cmd = cmd + ' ' + file[2:]
resp = ftp.sendcmd(cmd)
else:
ftp.retrbinary('RETR ' + file, \
sys.stdout.write, 1024)
ftp.quit()
finally:
marshal.dump(nextport, open('.@nextport', 'w'))
debugging = 0
while sys.argv[1] == '-d':
debugging = debugging+1
del sys.argv[1]
host = sys.argv[1]
ftp = FTP(host)
ftp.set_debuglevel(debugging)
ftp.login()
for file in sys.argv[2:]:
if file[:2] == '-l':
ftp.dir(file[2:])
elif file[:2] == '-d':
cmd = 'CWD'
if file[2:]: cmd = cmd + ' ' + file[2:]
resp = ftp.sendcmd(cmd)
else:
ftp.retrbinary('RETR ' + file, \
sys.stdout.write, 1024)
ftp.quit()

View file

@ -1,35 +1,35 @@
# These lines were generated by h2py.py (see demo/scripts)
# from <sys/fcntl.h> on Irix 4.0.2.
# The applicability on other systems is not clear.
# Generated by h2py from /usr/include/sys/fcntl.h
FNDELAY = 0x04
FAPPEND = 0x08
FSYNC = 0x10
FRCACH = 0x20
FASYNC = 0x40
FNONBLK = 0x80
FCREAT = 0x100
FTRUNC = 0x200
FEXCL = 0x400
FNOCTTY = 0x800
FNONBLOCK = 0x80
FASYNC = 0x1000
FNONBLK = FNONBLOCK
FDIRECT = 0x8000
FCREAT = 0x0100
FTRUNC = 0x0200
FEXCL = 0x0400
FNOCTTY = 0x0800
O_RDONLY = 0
O_WRONLY = 1
O_RDWR = 2
O_ACCMODE = 0x3
O_NDELAY = FNDELAY
O_APPEND = FAPPEND
O_SYNC = FSYNC
O_NONBLOCK = FNONBLK
O_CREAT = FCREAT
O_TRUNC = FTRUNC
O_EXCL = FEXCL
O_NOCTTY = FNOCTTY
O_NDELAY = 0x04
O_APPEND = 0x08
O_SYNC = 0x10
O_NONBLOCK = 0x80
O_DIRECT = 0x8000
O_CREAT = 0x100
O_TRUNC = 0x200
O_EXCL = 0x400
O_NOCTTY = 0x800
F_DUPFD = 0
F_GETFD = 1
F_SETFD = 2
F_GETFL = 3
F_SETFL = 4
F_GETLK = 5
F_GETLK = 14
F_O_GETLK = 5
F_GETLK = 14
F_SETLK = 6
F_SETLKW = 7
F_CHKFL = 8
@ -37,13 +37,17 @@
F_FREESP = 11
F_SETBSDLK = 12
F_SETBSDLKW = 13
F_RGETLK = 20
F_RSETLK = 21
F_DIOINFO = 30
F_RSETLK = 20
F_RGETLK = 21
F_RSETLKW = 22
F_GETOWN = 10
F_SETOWN = 11
F_GETOWN = 23
F_SETOWN = 24
F_O_GETOWN = 10
F_O_SETOWN = 11
F_RDLCK = 01
F_WRLCK = 02
F_UNLCK = 03
FD_CLOEXEC = 0x1
FD_NODUP_FORK = 0x2
O_ACCMODE = 3
FD_CLOEXEC = 1
FD_NODUP_FORK = 4

View file

@ -1,8 +1,4 @@
# Symbolic constants from <netinet/in.h>.
# These constants are SGI specific!
# See demo/scripts/h2py.py for a tool to help generate a version for
# your system.
# Generated by h2py from /usr/include/netinet/in.h
IPPROTO_IP = 0
IPPROTO_ICMP = 1
IPPROTO_IGMP = 2
@ -14,6 +10,8 @@
IPPROTO_IDP = 22
IPPROTO_TP = 29
IPPROTO_XTP = 36
IPPROTO_HELLO = 63
IPPROTO_ND = 77
IPPROTO_EON = 80
IPPROTO_RAW = 255
IPPROTO_MAX = 256
@ -42,6 +40,11 @@
INADDR_NONE = 0xffffffff
IN_LOOPBACKNET = 127
IP_OPTIONS = 1
IP_MULTICAST_IF = 2
IP_MULTICAST_TTL = 3
IP_MULTICAST_LOOP = 4
IP_ADD_MEMBERSHIP = 5
IP_DROP_MEMBERSHIP = 6
IP_HDRINCL = 7
IP_TOS = 8
IP_TTL = 9
@ -49,11 +52,32 @@
IP_RECVRETOPTS = 11
IP_RECVDSTADDR = 12
IP_RETOPTS = 13
IP_MULTICAST_IF = 2
IP_MULTICAST_TTL = 3
IP_MULTICAST_LOOP = 4
IP_ADD_MEMBERSHIP = 5
IP_DROP_MEMBERSHIP = 6
IP_OPTIONS = 1
IP_HDRINCL = 2
IP_TOS = 3
IP_TTL = 4
IP_RECVOPTS = 5
IP_RECVRETOPTS = 6
IP_RECVDSTADDR = 7
IP_RETOPTS = 8
IP_MULTICAST_IF = 20
IP_MULTICAST_TTL = 21
IP_MULTICAST_LOOP = 22
IP_ADD_MEMBERSHIP = 23
IP_DROP_MEMBERSHIP = 24
IRIX4_IP_OPTIONS = 1
IRIX4_IP_MULTICAST_IF = 2
IRIX4_IP_MULTICAST_TTL = 3
IRIX4_IP_MULTICAST_LOOP = 4
IRIX4_IP_ADD_MEMBERSHIP = 5
IRIX4_IP_DROP_MEMBERSHIP = 6
IRIX4_IP_HDRINCL = 7
IRIX4_IP_TOS = 8
IRIX4_IP_TTL = 9
IRIX4_IP_RECVOPTS = 10
IRIX4_IP_RECVRETOPTS = 11
IRIX4_IP_RECVDSTADDR = 12
IRIX4_IP_RETOPTS = 13
IP_DEFAULT_MULTICAST_TTL = 1
IP_DEFAULT_MULTICAST_LOOP = 1
IP_MAX_MEMBERSHIPS = 20

View file

@ -1,8 +1,23 @@
# Generated by h2py from /usr/include/sys/socket.h
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
NC_TPI_CLTS = 1
NC_TPI_COTS = 2
NC_TPI_COTS_ORD = 3
NC_TPI_RAW = 4
SOCK_DGRAM = NC_TPI_CLTS
SOCK_STREAM = NC_TPI_COTS
SOCK_RAW = NC_TPI_RAW
SOCK_RDM = 5
SOCK_SEQPACKET = 6
IRIX4_SOCK_STREAM = 1
IRIX4_SOCK_DGRAM = 2
IRIX4_SOCK_RAW = 3
IRIX4_SOCK_RDM = 4
IRIX4_SOCK_SEQPACKET = 5
SO_DEBUG = 0x0001
SO_ACCEPTCONN = 0x0002
SO_REUSEADDR = 0x0004
@ -13,6 +28,9 @@
SO_LINGER = 0x0080
SO_OOBINLINE = 0x0100
SO_REUSEPORT = 0x0200
SO_ORDREL = 0x0200
SO_IMASOCKET = 0x0400
SO_CHAMELEON = 0x1000
SO_SNDBUF = 0x1001
SO_RCVBUF = 0x1002
SO_SNDLOWAT = 0x1003
@ -21,6 +39,7 @@
SO_RCVTIMEO = 0x1006
SO_ERROR = 0x1007
SO_TYPE = 0x1008
SO_PROTOTYPE = 0x1009
SOL_SOCKET = 0xffff
AF_UNSPEC = 0
AF_UNIX = 1
@ -30,7 +49,6 @@
AF_CHAOS = 5
AF_NS = 6
AF_ISO = 7
AF_OSI = AF_ISO
AF_ECMA = 8
AF_DATAKIT = 9
AF_CCITT = 10
@ -44,7 +62,14 @@
AF_RAW = 18
AF_LINK = 18
pseudo_AF_XTP = 19
AF_MAX = 20
AF_NIT = 17
AF_802 = 18
AF_OSI = 19
AF_X25 = 20
AF_OSINET = 21
AF_GOSIP = 22
AF_SDL = 23
AF_MAX = (AF_SDL+1)
PF_UNSPEC = AF_UNSPEC
PF_UNIX = AF_UNIX
PF_INET = AF_INET
@ -53,7 +78,6 @@
PF_CHAOS = AF_CHAOS
PF_NS = AF_NS
PF_ISO = AF_ISO
PF_OSI = AF_ISO
PF_ECMA = AF_ECMA
PF_DATAKIT = AF_DATAKIT
PF_CCITT = AF_CCITT
@ -67,11 +91,18 @@
PF_LINK = AF_LINK
PF_XTP = pseudo_AF_XTP
PF_RAW = AF_RAW
PF_NIT = AF_NIT
PF_802 = AF_802
PF_OSI = AF_OSI
PF_X25 = AF_X25
PF_OSINET = AF_OSINET
PF_GOSIP = AF_GOSIP
PF_MAX = AF_MAX
SOMAXCONN = 5
MSG_OOB = 0x1
MSG_PEEK = 0x2
MSG_DONTROUTE = 0x4
MSG_EOR = 0x8
MSG_BTAG = 0x40
MSG_ETAG = 0x80
MSG_MAXIOVLEN = 16

View file

@ -138,6 +138,19 @@ def __init__(self, tracklist):
continue
self.track[trackno] = value
f.close()
for i in range(2, len(self.track)):
track = self.track[i]
# if track title starts with `,', use initial part
# of previous track's title
if track[0] == ',':
try:
off = string.index(self.track[i - 1],
',')
except string.index_error:
pass
else:
self.track[i] = self.track[i-1][:off] \
+ track
def write(self):
import posixpath
@ -153,6 +166,17 @@ def write(self):
f.write('album.title:\t' + self.title + '\n')
f.write('album.artist:\t' + self.artist + '\n')
f.write('album.toc:\t' + self.toc + '\n')
prevpref = None
for i in range(1, len(self.track)):
f.write('track' + `i` + '.title:\t' + self.track[i] + '\n')
track = self.track[i]
try:
off = string.index(track, ',')
except string.index_error:
prevpref = None
else:
if prevpref and track[:off] == prevpref:
track = track[off:]
else:
prevpref = track[:off]
f.write('track' + `i` + '.title:\t' + track + '\n')
f.close()

View file

@ -432,10 +432,10 @@ def _select_crfunc(fm, cl):
def test():
import time
t0 = time.millitimer()
t0 = time.time()
if len(sys.argv) == 2:
forms = parse_forms(sys.argv[1])
t1 = time.millitimer()
t1 = time.time()
print 'parse time:', 0.001*(t1-t0), 'sec.'
keys = forms.keys()
keys.sort()
@ -443,8 +443,8 @@ def test():
_printform(forms[i])
elif len(sys.argv) == 3:
form = parse_form(sys.argv[1], sys.argv[2])
t1 = time.millitimer()
print 'parse time:', 0.001*(t1-t0), 'sec.'
t1 = time.time()
print 'parse time:', round(t1-t0, 3), 'sec.'
_printform(form)
else:
print 'Usage: test fdfile [form]'

View file

@ -7,6 +7,10 @@
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.
# 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:

View file

@ -65,11 +65,9 @@ def is_function(x):
# Approximation of builtin dir(); but note that this lists the user's
# variables by default, not the current local name space.
def dir(*args):
if len(args) > 0:
if len(args) == 1:
args = args[0]
return listattrs(args)
def dir(x = None):
if x is not None:
return listattrs(x)
else:
import __main__
return listattrs(__main__)

View file

@ -41,12 +41,28 @@ def packsome(outfp, dirname, names):
# 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]
@ -67,6 +83,14 @@ 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)

View file

@ -1,5 +1,5 @@
# Combine a real-time scheduling queue and stdwin event handling.
# Uses the millisecond timer.
# Keeps times in milliseconds.
import stdwin, stdwinq
from stdwinevents import WE_TIMER
@ -19,11 +19,11 @@ def delayfunc(msecs):
mainloop.dispatch(event)
return
#
# Use millisleep for very short delays or if there are no windows
# Use sleep for very short delays or if there are no windows
#
if msecs < 100 or mainloop.countwindows() == 0:
if msecs > 0:
time.millisleep(msecs)
time.sleep(msecs * 0.001)
return
#
# Post a timer event on an arbitrary window and wait for it
@ -35,7 +35,10 @@ def delayfunc(msecs):
if event[0] <> WE_TIMER:
mainloop.dispatch(event)
q = sched.scheduler(time.millitimer, delayfunc)
def millitimer():
return int(1000 * time.time())
q = sched.scheduler(millitimer, delayfunc)
# Export functions enter, enterabs and cancel just like a scheduler
#

View file

@ -2,19 +2,19 @@
# File windows, a subclass of textwin (which is a subclass of gwin)
import textwin
import builtin
import __builtin__
# FILE WINDOW
def open_readonly(fn): # Open a file window
fp = builtin.open(fn, 'r')
fp = __builtin__.open(fn, 'r')
w = textwin.open_readonly(fn, fp.read())
w.fn = fn
return w
def open(fn): # Open a file window
fp = builtin.open(fn, 'r')
fp = __builtin__.open(fn, 'r')
w = textwin.open(fn, fp.read())
w.fn = fn
return w

View file

@ -241,7 +241,7 @@ def mouse_down(self, detail):
stdwin.fleep()
def draw(self, detail):
import linecache, codehack, string
import linecache, string
d = self.win.begindrawing()
try:
h, v = 0, 0
@ -252,7 +252,7 @@ def draw(self, detail):
else:
s = ' '
s = s + fn + '(' + `lineno` + ')'
s = s + codehack.getcodename(f.f_code)
s = s + f.f_code.co_name
if f.f_locals.has_key('__args__'):
args = f.f_locals['__args__']
if args is not None:
@ -286,6 +286,8 @@ def runcall(*args):
try: apply(x.runcall, args)
finally: x.close()
def set_trace():
Wdb().set_trace()
# Post-Mortem interface
@ -304,6 +306,4 @@ def pm():
TESTCMD = 'import x; x.main()'
def test():
import linecache
linecache.checkcache()
run(TESTCMD)

View file

@ -1,8 +1,10 @@
# Various tools used by MIME-reading or MIME-writing programs.
import string
import os
import rfc822
import string
import tempfile
# A derived class of rfc822.Message that knows about MIME headers and
@ -67,7 +69,7 @@ def getparam(self, name):
def getencoding(self):
if self.encodingheader == None:
return '7bit'
return self.encodingheader
return string.lower(self.encodingheader)
def gettype(self):
return self.type
@ -110,3 +112,75 @@ def choose_boundary():
timestamp = `int(time.time())`
seed = `rand.rand()`
return _prefix + '.' + timestamp + '.' + seed
# Subroutines for decoding some common content-transfer-types
# XXX This requires that uudecode and mmencode are in $PATH
def decode(input, output, encoding):
if decodetab.has_key(encoding):
pipethrough(input, decodetab[encoding], output)
else:
raise ValueError, \
'unknown Content-Transfer-Encoding: %s' % encoding
def encode(input, output, encoding):
if encodetab.has_key(encoding):
pipethrough(input, encodetab[encoding], output)
else:
raise ValueError, \
'unknown Content-Transfer-Encoding: %s' % encoding
uudecode_pipe = '''(
TEMP=/tmp/@uu.$$
sed "s%^begin [0-7][0-7]* .*%begin 600 $TEMP%" | uudecode
cat $TEMP
rm $TEMP
)'''
decodetab = {
'uuencode': uudecode_pipe,
'x-uuencode': uudecode_pipe,
'quoted-printable': 'mmencode -u -q',
'base64': 'mmencode -u -b',
}
encodetab = {
'x-uuencode': 'uuencode tempfile',
'uuencode': 'uuencode tempfile',
'quoted-printable': 'mmencode -q',
'base64': 'mmencode -b',
}
def pipeto(input, command):
pipe = os.popen(command, 'w')
copyliteral(input, pipe)
pipe.close()
def pipethrough(input, command, output):
tempname = tempfile.mktemp()
try:
temp = open(tempname, 'w')
except IOError:
print '*** Cannot create temp file', `tempname`
return
copyliteral(input, temp)
temp.close()
pipe = os.popen(command + ' <' + tempname, 'r')
copybinary(pipe, output)
pipe.close()
os.unlink(tempname)
def copyliteral(input, output):
while 1:
line = input.readline()
if not line: break
output.write(line)
def copybinary(input, output):
BUFSIZE = 8192
while 1:
line = input.read(BUFSIZE)
if not line: break
output.write(line)

View file

@ -85,6 +85,17 @@ def readline(self):
err('*** Missing endmarker in MultiFile.readline()\n')
return ''
#
def readlines(self):
list = []
while 1:
line = self.readline()
if not line: break
list.append(line)
return list
#
def read(self): # Note: no size argument -- read until EOF only!
return string.joinfields(self.readlines(), '')
#
def next(self):
while self.readline(): pass
if self.level > 1 or self.last:

View file

@ -65,11 +65,9 @@ def is_function(x):
# Approximation of builtin dir(); but note that this lists the user's
# variables by default, not the current local name space.
def dir(*args):
if len(args) > 0:
if len(args) == 1:
args = args[0]
return listattrs(args)
def dir(x = None):
if x is not None:
return listattrs(x)
else:
import __main__
return listattrs(__main__)

View file

@ -60,10 +60,7 @@ class NNTP:
# - host: hostname to connect to
# - port: port to connect to (default the standard NNTP port)
def __init__(self, host, *args):
if len(args) > 1: raise TypeError, 'too many args'
if args: port = args[0]
else: port = NNTP_PORT
def __init__(self, host, port = NNTP_PORT):
self.host = host
self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

View file

@ -1,15 +1,3 @@
# ospath.py is to {posix,mac}path.py what os.py is to modules {posix,mac}
try:
import posix
name = 'posix'
del posix
except ImportError:
import mac
name = 'mac'
del mac
if name == 'posix':
from posixpath import *
elif name == 'mac':
from macpath import *
# ospath.py is obsolete
import os
exec 'from %s import *' % os.name

View file

@ -41,12 +41,28 @@ def packsome(outfp, dirname, names):
# 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]
@ -67,6 +83,14 @@ 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)

View file

@ -61,9 +61,10 @@ u(p)
Move the current frame one level up in the stack trace
(to a newer frame).
b(reak) [lineno]
With a line number argument, set a break there in the current file.
Without argument, list all breaks.
b(reak) [lineno | function]
With a line number argument, set a break there in the current
file. With a function name, set a break at the entry of that
function. Without argument, list all breaks.
cl(ear) [lineno]
With a line number argument, clear that break in the current file.

View file

@ -74,17 +74,31 @@ def default(self, line):
# Return true to exit from the command loop
do_h = cmd.Cmd.do_help
def do_break(self, arg):
if not arg:
print self.get_all_breaks() # XXX
return
try:
# Try line number as argument
try:
lineno = int(eval(arg))
filename = self.curframe.f_code.co_filename
except:
print '*** Error in argument:', `arg`
return
filename = self.curframe.f_code.co_filename
# Try function name as the argument
import codehack
try:
func = eval(arg, self.curframe.f_globals,
self.curframe.f_locals)
if hasattr(func, 'im_func'):
func = func.im_func
code = func.func_code
except:
print '*** Could not eval argument:', arg
return
lineno = codehack.getlineno(code)
filename = code.co_filename
# now set the break point
err = self.set_break(filename, lineno)
if err: print '***', err
do_b = do_break
@ -159,10 +173,10 @@ def do_quit(self, arg):
do_q = do_quit
def do_args(self, arg):
if self.curframe.f_locals.has_key('__return__'):
print `self.curframe.f_locals['__return__']`
if self.curframe.f_locals.has_key('__args__'):
print `self.curframe.f_locals['__args__']`
else:
print '*** Not arguments?!'
print '*** No arguments?!'
do_a = do_args
def do_retval(self, arg):
@ -229,7 +243,6 @@ def do_list(self, arg):
do_l = do_list
def do_whatis(self, arg):
import codehack
try:
value = eval(arg, self.curframe.f_globals, \
self.curframe.f_locals)
@ -241,13 +254,13 @@ def do_whatis(self, arg):
try: code = value.func_code
except: pass
if code:
print 'Function', codehack.getcodename(code)
print 'Function', code.co_name
return
# Is it an instance method?
try: code = value.im_func.func_code
except: pass
if code:
print 'Method', codehack.getcodename(code)
print 'Method', code.co_name
return
# None of the above...
print type(value)
@ -276,6 +289,137 @@ def print_stack_entry(self, frame_lineno):
print self.format_stack_entry(frame_lineno)
# Help methods (derived from pdb.doc)
def help_help(self):
self.help_h()
def help_h(self):
print """h(elp)
Without argument, print the list of available commands.
With a command name as argument, print help about that command
"help pdb" pipes the full documentation file to the $PAGER
"help exec" gives help on the ! command"""
def help_where(self):
self.help_w()
def help_w(self):
print """w(here)
Print a stack trace, with the most recent frame at the bottom.
An arrow indicates the "current frame", which determines the
context of most commands."""
def help_down(self):
self.help_d()
def help_d(self):
print """d(own)
Move the current frame one level down in the stack trace
(to an older frame)."""
def help_up(self):
self.help_u()
def help_u(self):
print """u(p)
Move the current frame one level up in the stack trace
(to a newer frame)."""
def help_break(self):
self.help_b()
def help_b(self):
print """b(reak) [lineno | function]
With a line number argument, set a break there in the current
file. With a function name, set a break at the entry of that
function. Without argument, list all breaks."""
def help_clear(self):
self.help_cl()
def help_cl(self):
print """cl(ear) [lineno]
With a line number argument, clear that break in the current file.
Without argument, clear all breaks (but first ask confirmation)."""
def help_step(self):
self.help_s()
def help_s(self):
print """s(tep)
Execute the current line, stop at the first possible occasion
(either in a function that is called or in the current function)."""
def help_next(self):
self.help_n()
def help_n(self):
print """n(ext)
Continue execution until the next line in the current function
is reached or it returns."""
def help_return(self):
self.help_r()
def help_r(self):
print """r(eturn)
Continue execution until the current function returns."""
def help_continue(self):
self.help_c()
def help_cont(self):
self.help_c()
def help_c(self):
print """c(ont(inue))
Continue execution, only stop when a breakpoint is encountered."""
def help_list(self):
self.help_l()
def help_l(self):
print """l(ist) [first [,last]]
List source code for the current file.
Without arguments, list 11 lines around the current line
or continue the previous listing.
With one argument, list 11 lines starting at that line.
With two arguments, list the given range;
if the second argument is less than the first, it is a count."""
def help_args(self):
self.help_a()
def help_a(self):
print """a(rgs)
Print the argument list of the current function."""
def help_p(self):
print """p expression
Print the value of the expression."""
def help_exec(self):
print """(!) statement
Execute the (one-line) statement in the context of
the current stack frame.
The exclamation point can be omitted unless the first word
of the statement resembles a debugger command.
To assign to a global variable you must always prefix the
command with a 'global' command, e.g.:
(Pdb) global list_options; list_options = ['-l']
(Pdb)"""
def help_quit(self):
self.help_q()
def help_q(self):
print """q(uit) Quit from the debugger.
The program being executed is aborted."""
def help_pdb(self):
help()
# Simplified interface
def run(statement):
@ -287,6 +431,8 @@ def runctx(statement, globals, locals):
def runcall(*args):
apply(Pdb().runcall, args)
def set_trace():
Pdb().set_trace()
# Post-Mortem interface
@ -306,8 +452,6 @@ def pm():
TESTCMD = 'import x; x.main()'
def test():
import linecache
linecache.checkcache()
run(TESTCMD)
# print help

View file

@ -1,35 +1,35 @@
# These lines were generated by h2py.py (see demo/scripts)
# from <sys/fcntl.h> on Irix 4.0.2.
# The applicability on other systems is not clear.
# Generated by h2py from /usr/include/sys/fcntl.h
FNDELAY = 0x04
FAPPEND = 0x08
FSYNC = 0x10
FRCACH = 0x20
FASYNC = 0x40
FNONBLK = 0x80
FCREAT = 0x100
FTRUNC = 0x200
FEXCL = 0x400
FNOCTTY = 0x800
FNONBLOCK = 0x80
FASYNC = 0x1000
FNONBLK = FNONBLOCK
FDIRECT = 0x8000
FCREAT = 0x0100
FTRUNC = 0x0200
FEXCL = 0x0400
FNOCTTY = 0x0800
O_RDONLY = 0
O_WRONLY = 1
O_RDWR = 2
O_ACCMODE = 0x3
O_NDELAY = FNDELAY
O_APPEND = FAPPEND
O_SYNC = FSYNC
O_NONBLOCK = FNONBLK
O_CREAT = FCREAT
O_TRUNC = FTRUNC
O_EXCL = FEXCL
O_NOCTTY = FNOCTTY
O_NDELAY = 0x04
O_APPEND = 0x08
O_SYNC = 0x10
O_NONBLOCK = 0x80
O_DIRECT = 0x8000
O_CREAT = 0x100
O_TRUNC = 0x200
O_EXCL = 0x400
O_NOCTTY = 0x800
F_DUPFD = 0
F_GETFD = 1
F_SETFD = 2
F_GETFL = 3
F_SETFL = 4
F_GETLK = 5
F_GETLK = 14
F_O_GETLK = 5
F_GETLK = 14
F_SETLK = 6
F_SETLKW = 7
F_CHKFL = 8
@ -37,13 +37,17 @@
F_FREESP = 11
F_SETBSDLK = 12
F_SETBSDLKW = 13
F_RGETLK = 20
F_RSETLK = 21
F_DIOINFO = 30
F_RSETLK = 20
F_RGETLK = 21
F_RSETLKW = 22
F_GETOWN = 10
F_SETOWN = 11
F_GETOWN = 23
F_SETOWN = 24
F_O_GETOWN = 10
F_O_SETOWN = 11
F_RDLCK = 01
F_WRLCK = 02
F_UNLCK = 03
FD_CLOEXEC = 0x1
FD_NODUP_FORK = 0x2
O_ACCMODE = 3
FD_CLOEXEC = 1
FD_NODUP_FORK = 4

View file

@ -1,8 +1,4 @@
# Symbolic constants from <netinet/in.h>.
# These constants are SGI specific!
# See demo/scripts/h2py.py for a tool to help generate a version for
# your system.
# Generated by h2py from /usr/include/netinet/in.h
IPPROTO_IP = 0
IPPROTO_ICMP = 1
IPPROTO_IGMP = 2
@ -14,6 +10,8 @@
IPPROTO_IDP = 22
IPPROTO_TP = 29
IPPROTO_XTP = 36
IPPROTO_HELLO = 63
IPPROTO_ND = 77
IPPROTO_EON = 80
IPPROTO_RAW = 255
IPPROTO_MAX = 256
@ -42,6 +40,11 @@
INADDR_NONE = 0xffffffff
IN_LOOPBACKNET = 127
IP_OPTIONS = 1
IP_MULTICAST_IF = 2
IP_MULTICAST_TTL = 3
IP_MULTICAST_LOOP = 4
IP_ADD_MEMBERSHIP = 5
IP_DROP_MEMBERSHIP = 6
IP_HDRINCL = 7
IP_TOS = 8
IP_TTL = 9
@ -49,11 +52,32 @@
IP_RECVRETOPTS = 11
IP_RECVDSTADDR = 12
IP_RETOPTS = 13
IP_MULTICAST_IF = 2
IP_MULTICAST_TTL = 3
IP_MULTICAST_LOOP = 4
IP_ADD_MEMBERSHIP = 5
IP_DROP_MEMBERSHIP = 6
IP_OPTIONS = 1
IP_HDRINCL = 2
IP_TOS = 3
IP_TTL = 4
IP_RECVOPTS = 5
IP_RECVRETOPTS = 6
IP_RECVDSTADDR = 7
IP_RETOPTS = 8
IP_MULTICAST_IF = 20
IP_MULTICAST_TTL = 21
IP_MULTICAST_LOOP = 22
IP_ADD_MEMBERSHIP = 23
IP_DROP_MEMBERSHIP = 24
IRIX4_IP_OPTIONS = 1
IRIX4_IP_MULTICAST_IF = 2
IRIX4_IP_MULTICAST_TTL = 3
IRIX4_IP_MULTICAST_LOOP = 4
IRIX4_IP_ADD_MEMBERSHIP = 5
IRIX4_IP_DROP_MEMBERSHIP = 6
IRIX4_IP_HDRINCL = 7
IRIX4_IP_TOS = 8
IRIX4_IP_TTL = 9
IRIX4_IP_RECVOPTS = 10
IRIX4_IP_RECVRETOPTS = 11
IRIX4_IP_RECVDSTADDR = 12
IRIX4_IP_RETOPTS = 13
IP_DEFAULT_MULTICAST_TTL = 1
IP_DEFAULT_MULTICAST_LOOP = 1
IP_MAX_MEMBERSHIPS = 20

View file

@ -1,8 +1,23 @@
# Generated by h2py from /usr/include/sys/socket.h
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
NC_TPI_CLTS = 1
NC_TPI_COTS = 2
NC_TPI_COTS_ORD = 3
NC_TPI_RAW = 4
SOCK_DGRAM = NC_TPI_CLTS
SOCK_STREAM = NC_TPI_COTS
SOCK_RAW = NC_TPI_RAW
SOCK_RDM = 5
SOCK_SEQPACKET = 6
IRIX4_SOCK_STREAM = 1
IRIX4_SOCK_DGRAM = 2
IRIX4_SOCK_RAW = 3
IRIX4_SOCK_RDM = 4
IRIX4_SOCK_SEQPACKET = 5
SO_DEBUG = 0x0001
SO_ACCEPTCONN = 0x0002
SO_REUSEADDR = 0x0004
@ -13,6 +28,9 @@
SO_LINGER = 0x0080
SO_OOBINLINE = 0x0100
SO_REUSEPORT = 0x0200
SO_ORDREL = 0x0200
SO_IMASOCKET = 0x0400
SO_CHAMELEON = 0x1000
SO_SNDBUF = 0x1001
SO_RCVBUF = 0x1002
SO_SNDLOWAT = 0x1003
@ -21,6 +39,7 @@
SO_RCVTIMEO = 0x1006
SO_ERROR = 0x1007
SO_TYPE = 0x1008
SO_PROTOTYPE = 0x1009
SOL_SOCKET = 0xffff
AF_UNSPEC = 0
AF_UNIX = 1
@ -30,7 +49,6 @@
AF_CHAOS = 5
AF_NS = 6
AF_ISO = 7
AF_OSI = AF_ISO
AF_ECMA = 8
AF_DATAKIT = 9
AF_CCITT = 10
@ -44,7 +62,14 @@
AF_RAW = 18
AF_LINK = 18
pseudo_AF_XTP = 19
AF_MAX = 20
AF_NIT = 17
AF_802 = 18
AF_OSI = 19
AF_X25 = 20
AF_OSINET = 21
AF_GOSIP = 22
AF_SDL = 23
AF_MAX = (AF_SDL+1)
PF_UNSPEC = AF_UNSPEC
PF_UNIX = AF_UNIX
PF_INET = AF_INET
@ -53,7 +78,6 @@
PF_CHAOS = AF_CHAOS
PF_NS = AF_NS
PF_ISO = AF_ISO
PF_OSI = AF_ISO
PF_ECMA = AF_ECMA
PF_DATAKIT = AF_DATAKIT
PF_CCITT = AF_CCITT
@ -67,11 +91,18 @@
PF_LINK = AF_LINK
PF_XTP = pseudo_AF_XTP
PF_RAW = AF_RAW
PF_NIT = AF_NIT
PF_802 = AF_802
PF_OSI = AF_OSI
PF_X25 = AF_X25
PF_OSINET = AF_OSINET
PF_GOSIP = AF_GOSIP
PF_MAX = AF_MAX
SOMAXCONN = 5
MSG_OOB = 0x1
MSG_PEEK = 0x2
MSG_DONTROUTE = 0x4
MSG_EOR = 0x8
MSG_BTAG = 0x40
MSG_ETAG = 0x80
MSG_MAXIOVLEN = 16

View file

@ -138,6 +138,19 @@ def __init__(self, tracklist):
continue
self.track[trackno] = value
f.close()
for i in range(2, len(self.track)):
track = self.track[i]
# if track title starts with `,', use initial part
# of previous track's title
if track[0] == ',':
try:
off = string.index(self.track[i - 1],
',')
except string.index_error:
pass
else:
self.track[i] = self.track[i-1][:off] \
+ track
def write(self):
import posixpath
@ -153,6 +166,17 @@ def write(self):
f.write('album.title:\t' + self.title + '\n')
f.write('album.artist:\t' + self.artist + '\n')
f.write('album.toc:\t' + self.toc + '\n')
prevpref = None
for i in range(1, len(self.track)):
f.write('track' + `i` + '.title:\t' + self.track[i] + '\n')
track = self.track[i]
try:
off = string.index(track, ',')
except string.index_error:
prevpref = None
else:
if prevpref and track[:off] == prevpref:
track = track[off:]
else:
prevpref = track[:off]
f.write('track' + `i` + '.title:\t' + track + '\n')
f.close()

View file

@ -432,10 +432,10 @@ def _select_crfunc(fm, cl):
def test():
import time
t0 = time.millitimer()
t0 = time.time()
if len(sys.argv) == 2:
forms = parse_forms(sys.argv[1])
t1 = time.millitimer()
t1 = time.time()
print 'parse time:', 0.001*(t1-t0), 'sec.'
keys = forms.keys()
keys.sort()
@ -443,8 +443,8 @@ def test():
_printform(forms[i])
elif len(sys.argv) == 3:
form = parse_form(sys.argv[1], sys.argv[2])
t1 = time.millitimer()
print 'parse time:', 0.001*(t1-t0), 'sec.'
t1 = time.time()
print 'parse time:', round(t1-t0, 3), 'sec.'
_printform(form)
else:
print 'Usage: test fdfile [form]'

View file

@ -1,10 +1,10 @@
# Generated by h2py from stdin
_FOPEN = (-1)
_FREAD = 0x0001
_FWRITE = 0x0002
_FNDELAY = 0x0004
_FAPPEND = 0x0008
_FMARK = 0x0010
_FDEFER = 0x0020
_FSETBLK = 0x0010
_FASYNC = 0x0040
_FSHLOCK = 0x0080
_FEXLOCK = 0x0100
@ -15,6 +15,8 @@
_FSYNC = 0x2000
_FNONBLOCK = 0x4000
_FNOCTTY = 0x8000
_FMARK = 0x10000
_FDEFER = 0x20000
O_RDONLY = 0
O_WRONLY = 1
O_RDWR = 2
@ -25,7 +27,6 @@
O_NONBLOCK = _FNONBLOCK
O_NOCTTY = _FNOCTTY
O_SYNC = _FSYNC
O_ACCMODE = (O_RDONLY|O_WRONLY|O_RDWR)
FAPPEND = _FAPPEND
FSYNC = _FSYNC
FASYNC = _FASYNC
@ -36,6 +37,7 @@
FWRITE = _FWRITE
FMARK = _FMARK
FDEFER = _FDEFER
FSETBLK = _FSETBLK
FSHLOCK = _FSHLOCK
FEXLOCK = _FEXLOCK
FOPEN = _FOPEN
@ -62,3 +64,4 @@
F_WRLCK = 2
F_UNLCK = 3
F_UNLKSYS = 4
O_ACCMODE = (O_RDONLY|O_WRONLY|O_RDWR)

View file

@ -1,8 +1,4 @@
# Symbolic constants from <netinet/in.h>.
# These constants are SunOS specific! (Possibly even SunOS 4.1.1)
# See demo/scripts/h2py.py for a tool to help generate a version for
# your system.
# Generated by h2py from /usr/include/netinet/in.h
IPPROTO_IP = 0
IPPROTO_ICMP = 1
IPPROTO_IGMP = 2

View file

@ -1,3 +1,4 @@
# Generated by h2py from /usr/include/sys/socket.h
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3

13
Lib/plat-sunos4/WAIT.py Executable file
View file

@ -0,0 +1,13 @@
# Generated by h2py from /usr/include/sys/wait.h
WUNTRACED = 0004
WNOHANG = 0100
WEXITED = 0001
WTRAPPED = 0002
WSTOPPED = WUNTRACED
WCONTINUED = 0010
WNOWAIT = 0200
WOPTMASK = (WEXITED|WTRAPPED|WSTOPPED|WCONTINUED|WNOHANG|WNOWAIT)
WSTOPFLG = 0177
WCONTFLG = 0177777
WCOREFLG = 0200
WSIGMASK = 0177

View file

@ -8,4 +8,5 @@ set -v
h2py </usr/include/sys/fcntlcom.h >FCNTL.py
echo "O_ACCMODE = (O_RDONLY|O_WRONLY|O_RDWR)" >>FCNTL.py
h2py /usr/include/sys/socket.h
h2py /usr/include/sys/wait.h
h2py -i '(u_long)' /usr/include/netinet/in.h

View file

@ -130,7 +130,7 @@ def isdir(path):
# Is a path a regular file?
# This follows symbolic links, so both islink() and isdir() can be true
# This follows symbolic links, so both islink() and isfile() can be true
# for the same path.
def isfile(path):
@ -205,7 +205,7 @@ def walk(top, func, arg):
for name in names:
if name not in exceptions:
name = join(top, name)
if isdir(name):
if isdir(name) and not islink(name):
walk(name, func, arg)
@ -239,29 +239,35 @@ def expanduser(path):
# Expand paths containing shell variable substitutions.
# This is done by piping it through the shell.
# Shell quoting characters (\ " ' `) are protected by a backslash.
# NB: a future version may avoid starting a subprocess and do the
# substitutions internally. This may slightly change the syntax
# for variables.
# This expands the forms $variable and ${variable} only.
# Non-existant variables are left unchanged.
_varprog = None
def expandvars(path):
global _varprog
if '$' not in path:
return path
q = ''
for c in path:
if c in ('\\', '"', '\'', '`'):
c = '\\' + c
q = q + c
d = '!'
if q == d:
d = '+'
p = posix.popen('cat <<' + d + '\n' + q + '\n' + d + '\n', 'r')
res = p.read()
del p
if res[-1:] == '\n':
res = res[:-1]
return res
if not _varprog:
import regex
_varprog = regex.compile('$\([a-zA-Z0-9_]+\|{[^}]*}\)')
i = 0
while 1:
i = _varprog.search(path, i)
if i < 0:
break
name = _varprog.group(1)
j = i + len(_varprog.group(0))
if name[:1] == '{' and name[-1:] == '}':
name = name[1:-1]
if posix.environ.has_key(name):
tail = path[j:]
path = path[:i] + posix.environ[name]
i = len(path)
path = path + tail
else:
i = j
return path
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.

View file

@ -1,74 +1,702 @@
The Python Profiler
profile.doc last updated 6/23/94 [by Guido]
To use the profiler in its simplest form:
PROFILER DOCUMENTATION and (mini) USER'S MANUAL
>>> import profile
>>> profile.run(statement)
Copyright 1994, by InfoSeek Corporation, all rights reserved.
Written by James Roskind
This will execute the statement and print statistics. To get more
information out of the profiler, use:
Permission to use, copy, modify, and distribute this Python software
and its associated documentation for any purpose (subject to the
restriction in the following sentence) without fee is hereby granted,
provided that the above copyright notice appears in all copies, and
that both that copyright notice and this permission notice appear in
supporting documentation, and that the name of InfoSeek not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission. This permission is
explicitly restricted to the copying and modification of the software
to remain in Python, compiled Python, or other languages (such as C)
wherein the modified or derived code is exclusively imported into a
Python module.
>>> import profile
>>> profile.run(statement, dump_file)
INFOSEEK CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL INFOSEEK CORPORATION BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
where dump_file is a string naming a file to which the (binary)
profile statistics is to be dumped. The binary format is a dump of a
dictionary. The key is the function name in the format described
above; the value is a tuple consisting of, in order, number of calls,
total time spent in the function, total time spent in the function and
all functions called from it, a list of functions called by this
function, and a list of functions that called this function. The dump
can be read back using the following code:
>>> import marshal
>>> f = open(dump_file, 'r')
>>> dict = marshal.load(f)
>>> f.close()
The profiler was written after only programming in Python for 3 weeks.
As a result, it is probably clumsy code, but I don't know for sure yet
'cause I'm a beginner :-). I did work hard to make the code run fast,
so that profiling would be a reasonable thing to do. I tried not to
repeat code fragments, but I'm sure I did some stuff in really awkward
ways at times. Please send suggestions for improvements to:
jar@infoseek.com. I won't promise *any* support. ...but I'd
appreciate the feedback.
An easier way of doing this is by using the class `Stats' which is
also defined in profile:
>>> import profile
>>> s = profile.Stats().init(dump_file)
SECTION HEADING LIST:
INTRODUCTION
HOW IS THIS profile DIFFERENT FROM THE OLD profile MODULE?
INSTANT USERS MANUAL
WHAT IS DETERMINISTIC PROFILING?
REFERENCE MANUAL
FUNCTION profile.run(string, filename_opt)
CLASS Stats(filename, ...)
METHOD strip_dirs()
METHOD add(filename, ...)
METHOD sort_stats(key, ...)
METHOD reverse_order()
METHOD print_stats(restriction, ...)
METHOD print_callers(restrictions, ...)
METHOD print_callees(restrictions, ...)
METHOD ignore()
LIMITATIONS
CALIBRATION
EXTENSIONS: Deriving Better Profilers
The following methods are defined for instances of `Stats':
print_stats() -- Print the statistics in a format similar to
the format profile.run() uses.
print_callers() -- For each function, print all functions
which it calls.
print_callees() -- For each function, print all functions from
which it is called.
sort_stats(n) -- Sort the statistics for subsequent
printing. The argument determines on which
field the output should be sorted.
Possibilities are
-1 function name
0 number of calls
1 total time spent in a function
2 total time spent in a function
plus all functions it called
strip_dirs() -- Strip the directory names off of the file
names which are part of the function names.
This undoes the effect of sort_stats(), but
a subsequent sort_stats() does work.
The methods sort_stats and strip_dirs may change in the future.
INTRODUCTION
Output of profile.run(statement) and of the print_stats() method of
the `Stats' class consists of the following fields.
A "profiler" is a program that describes the run time performance of a
program, providing a variety of statistics. This documentation
describes the profiler functionality provided in the modules
"profile" and "pstats." This profiler provides "deterministic
profiling" of any Python programs. It also provides a series of
report generation tools to allow users to rapidly examine the results
of a profile operation.
Number of times the function was called.
Total time spent in the function.
Mean time per function call (second field divided by first).
Total time spent in the function and all functions it called,
recursively.
Mean time time spent in the function and all functions it
called (fourth field divided by first).
Name of the function in the format
<file name>:<line number>(<function name>)
The output of the print_callers and print_callees methods consists of
the name of the function and the names of all function it called or
was called from. The latter names are followed by a parenthesised
number which is the number of calls for this function.
HOW IS THIS profile DIFFERENT FROM THE OLD profile MODULE?
The big changes from standard profiling module are that you get more
information, and you pay less CPU time. It's not a trade-off, it's a
trade-up.
To be specific:
bugs removed: local stack frame is no longer molested, execution time
is now charged to correct functions, ....
accuracy increased: profiler execution time is no longer charged to
user's code, calibration for platform is supported, file reads
are not done *by* profiler *during* profiling (and charged to
user's code!), ...
speed increased: Overhead CPU cost was reduced by more than a factor of
two (perhaps a factor of five), lightweight profiler module is
all that must be loaded, and the report generating module
(pstats) is not needed during profiling.
recursive functions support: cumulative times in recursive functions
are correctly calculated; recursive entries are counted; ...
large growth in report generating UI: distinct profiles runs can be added
together forming a comprehensive report; functions that import
statistics take arbitrary lists of files; sorting criteria is now
based on keywords (instead of 4 integer options); reports shows
what functions were profiled as well as what profile file was
referenced; output format has been improved, ...
INSTANT USERS MANUAL
This section is provided for users that "don't want to read the
manual." It provides a very brief overview, and allows a user to
rapidly perform profiling on an existing application.
To profile an application with a main entry point of "foo()", you
would add the following to your module:
import profile
profile.run("foo()")
The above action would cause "foo()" to be run, and a series of
informative lines (the profile) to be printed. The above approach is
most useful when working with the interpreter. If you would like to
save the results of a profile into a file for later examination, you
can supply a file name as the second argument to the run() function:
import profile
profile.run("foo()", 'fooprof')
When you wish to review the profile, you should use the methods in the
pstats module. Typically you would load the statistics data as
follows:
import pstats
p = pstats.Stats('fooprof')
The class "Stats" (the above code just created an instance of this
class) has a variety of methods for manipulating and printing the data
that was just read into "p". When you ran profile.run() above, what
was printed was the result of three method calls:
p.strip_dirs().sort_stats(-1).print_stats()
The first method removed the extraneous path from all the module
names. The second method sorted all the entries according to the
standard module/line/name string that is printed (this is to comply
with the semantics of the old profiler). The third method printed out
all the statistics. You might try the following sort calls:
p.sort_stats('name')
p.print_stats()
The first call will actually sort the list by function name, and the
second call will print out the statistics. The following are some
interesting calls to experiment with:
p.sort_stats('cumulative').print_stats(10)
This sorts the profile by cumulative time in a function, and then only
prints the ten most significant lines. If you want to understand what
algorithms are taking time, the above line is what you would use.
If you were looking to see what functions were looping a lot, and
taking a lot of time, you would do:
p.sort_stats('time').print_stats(10)
to sort according to time spent within each function, and then print
the statistics for the top ten functions.
You might also try:
p.sort_stats('file').print_stats('__init__')
This will sort all the statistics by file name, and then print out
statistics for only the class init methods ('cause they are spelled
with "__init__" in them). As one final example, you could try:
p.sort_stats('time', 'cum').print_stats(.5, 'init')
This line sorts stats with a primary key of time, and a secondary key
of cumulative time, and then prints out some of the statistics. To be
specific, the list is first culled down to 50% (re: .5) of its
original size, then only lines containing "init" are maintained, and
that sub-sub-list is printed.
If you wondered what functions called the above functions, you could
now (p is still sorted according to the last criteria) do:
p.print_callers(.5, 'init')
and you would get a list of callers for each of the listed functions.
If you want more functionality, you're going to have to read the
manual (or guess) what the following functions do:
p.print_callees()
p.add('fooprof')
WHAT IS DETERMINISTIC PROFILING?
"Deterministic profiling" is meant to reflect the fact that all
"function call", "function return", and "exception" events are
monitored, and precise timings are made for the intervals between
these events (during which time the user's code is executing). In
contrast, "statistical profiling" (which is not done by this module)
randomly samples the effective instruction pointer, and deduces where
time is being spent. The latter technique traditionally involves less
overhead (as the code does not need to be instrumented), but provides
only relative indications of where time is being spent.
In Python, since there is an interpreter active during execution, the
presence of instrumented code is not required to do deterministic
profiling. Python automatically provides a hook (optional callback)
for each event. In addition, the interpreted nature of Python tends
to add so much overhead to execution, that deterministic profiling
tends to only add small processing overhead, in typical applications.
The result is that deterministic profiling is not that expensive, but
yet provides extensive run time statistics about the execution of a
Python program.
Call count statistics can be used to identify bugs in code (surprising
counts), and to identify possible inline-expansion points (high call
counts). Internal time statistics can be used to identify hot loops
that should be carefully optimized. Cumulative time statistics should
be used to identify high level errors in the selection of algorithms.
Note that the unusual handling of cumulative times in this profiler
allows statistics for recursive implementations of algorithms to be
directly compared to iterative implementations.
REFERENCE MANUAL
The primary entry point for the profiler is the global function
profile.run(). It is typically used to create any profile
information. The reports are formatted and printed using methods for
the class pstats.Stats. The following is a description of all of
these standard entry points and functions. For a more in-depth view
of some of the code, consider reading the later section on "Profiler
Extensions," which includes discussion of how to derive "better"
profilers from the classes presented, or reading the source code for
these modules.
FUNCTION profile.run(string, filename_opt)
This function takes a single argument that has can be passed to the
"exec" statement, and an optional file name. In all cases this
routine attempts to "exec" its first argument, and gather profiling
statistics from the execution. If no file name is present, then this
function automatically prints a simple profiling report, sorted by the
standard name string (file/line/function-name) that is presented in
each line. The following is a typical output from such a call:
cut here----
main()
2706 function calls (2004 primitive calls) in 4.504 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
2 0.006 0.003 0.953 0.477 pobject.py:75(save_objects)
43/3 0.533 0.012 0.749 0.250 pobject.py:99(evaluate)
...
cut here----
The first line indicates that this profile was generated by the call:
profile.run('main()'), and hence the exec'ed string is 'main()'. The
second line indicates that 2706 calls were monitored. Of those calls,
2004 were "primitive." We define "primitive" to mean that the call
was not induced via recursion. The next line: "Ordered by: standard
name", indicates that the text string in the far right column was used
to sort the output. The column headings include:
"ncalls" for the number of calls,
"tottime" for the total time spent in the given function
(and excluding time made in calls to sub-functions),
"percall" is the quotient of "tottime" divided by "ncalls"
"cumtime" is the total time spent in this and all subfunctions
(i.e., from invocation till exit). This figure is
accurate *even* for recursive functions.
"percall" is the quotient of "cumtime" divided by primitive
calls
"filename:lineno(function)" provides the respective data of
each function
When there are two numbers in the first column (e.g.: 43/3), then the
latter is the number of primitive calls, and the former is the actual
number of calls. Note that when the function does not recurse, these
two values are the same, and only the single figure is printed.
CLASS Stats(filename, ...)
This class constructor creates an instance of a statistics object from
a filename (or set of filenames). Stats objects are manipulated by
methods, in order to print useful reports.
The file selected by the above constructor must have been created by
the corresponding version of profile. To be specific, there is *NO*
file compatibility guaranteed with future versions of this profiler,
and there is no compatibility with files produced by other profilers
(e.g., the standard system profiler).
If several files are provided, all the statistics for identical
functions will be coalesced, so that an overall view of several
processes can be considered in a single report. If additional files
need to be combined with data in an existing Stats object, the add()
method can be used.
METHOD strip_dirs()
This method for the Stats class removes all leading path information
from file names. It is very useful in reducing the size of the
printout to fit within (close to) 80 columns. This method modifies
the object, and the striped information is lost. After performing a
strip operation, the object is considered to have its entries in a
"random" order, as it was just after object initialization and
loading. If strip_dir() causes two function names to be
indistinguishable (i.e., they are on the same line of the same
filename, and have the same function name), then the statistics for
these two entries are accumulated into a single entry.
METHOD add(filename, ...)
This methods of the Stats class accumulates additional profiling
information into the current profiling object. Its arguments should
refer to filenames created my the corresponding version of
profile.run(). Statistics for identically named (re: file, line,
name) functions are automatically accumulated into single function
statistics.
METHOD sort_stats(key, ...)
This method modifies the Stats object by sorting it according to the
supplied criteria. The argument is typically a string identifying the
basis of a sort (example: "time" or "name").
When more than one key is provided, then additional keys are used as
secondary criteria when the there is equality in all keys selected
before them. For example, sort_stats('name', 'file') will sort all
the entries according to their function name, and resolve all ties
(identical function names) by sorting by file name.
Abbreviations can be used for any key names, as long as the
abbreviation is unambiguous. The following are the keys currently
defined:
Valid Arg Meaning
"calls" call count
"cumulative" cumulative time
"file" file name
"module" file name
"pcalls" primitive call count
"line" line number
"name" function name
"nfl" name/file/line
"stdname" standard name
"time" internal time
Note that all sorts on statistics are in descending order (placing most
time consuming items first), where as name, file, and line number
searches are in ascending order (i.e., alphabetical). The subtle
distinction between "nfl" and "stdname" is that the standard name is a
sort of the name as printed, which means that the embedded line
numbers get compared in an odd way. For example, lines 3, 20, and 40
would (if the file names were the same) appear in the string order
"20" "3" and "40". In contrast, "nfl" does a numeric compare of the
line numbers. In fact, sort_stats("nfl") is the same as
sort_stats("name", "file", "line").
For compatibility with the standard profiler, the numeric argument -1,
0, 1, and 2 are permitted. They are interpreted as "stdname",
"calls", "time", and "cumulative" respectively. If this old style
format (numeric) is used, only one sort key (the numeric key) will be
used, and additionally arguments will be silently ignored.
METHOD reverse_order()
This method for the Stats class reverses the ordering of the basic
list within the object. This method is provided primarily for
compatibility with the standard profiler. Its utility is questionable
now that ascending vs descending order is properly selected based on
the sort key of choice.
METHOD print_stats(restriction, ...)
This method for the Stats class prints out a report as described in
the profile.run() definition.
The order of the printing is based on the last sort_stats() operation
done on the object (subject to caveats in add() and strip_dirs()).
The arguments provided (if any) can be used to limit the list down to
the significant entries. Initially, the list is taken to be the
complete set of profiled functions. Each restriction is either an
integer (to select a count of lines), or a decimal fraction between
0.0 and 1.0 inclusive (to select a percentage of lines), or a regular
expression (to pattern match the standard name that is printed). If
several restrictions are provided, then they are applied sequentially.
For example:
print_stats(.1, "foo:")
would first limit the printing to first 10% of list, and then only
print functions that were part of filename ".*foo:". In contrast, the
command:
print_stats("foo:", .1)
would limit the list to all functions having file names ".*foo:", and
then proceed to only print the first 10% of them.
METHOD print_callers(restrictions, ...)
This method for the Stats class prints a list of all functions that
called each function in the profiled database. The ordering is
identical to that provided by print_stats(), and the definition of the
restricting argument is also identical. For convenience, a number is
shown in parentheses after each caller to show how many times this
specific call was made. A second non-parenthesized number is the
cumulative time spent in the function at the right.
METHOD print_callees(restrictions, ...)
This method for the Stats class prints a list of all function that
were called by the indicated function. Aside from this reversal of
direction of calls (re: called vs was called by), the arguments and
ordering are identical to the print_callers() method.
METHOD ignore()
This method of the Stats class is used to dispose of the value
returned by earlier methods. All standard methods in this class
return the instance that is being processed, so that the commands can
be strung together. For example:
pstats.Stats('foofile').strip_dirs().sort_stats('cum').print_stats().ignore()
would perform all the indicated functions, but it would not return
the final reference to the Stats instance.
LIMITATIONS
There are two fundamental limitations on this profiler. The first is
that it relies on the Python interpreter to dispatch "call", "return",
and "exception" events. Compiled C code does not get interpreted,
and hence is "invisible" to the profiler. All time spent in C code
(including builtin functions) will be charged to the Python function
that was invoked the C code. IF the C code calls out to some native
Python code, then those calls will be profiled properly.
The second limitation has to do with accuracy of timing information.
There is a fundamental problem with deterministic profilers involving
accuracy. The most obvious restriction is that the underlying "clock"
is only ticking at a rate (typically) of about .001 seconds. Hence no
measurements will be more accurate that that underlying clock. If
enough measurements are taken, then the "error" will tend to average
out. Unfortunately, removing this first error induces a second source
of error...
The second problem is that it "takes a while" from when an event is
dispatched until the profiler's call to get the time actually *gets*
the state of the clock. Similarly, there is a certain lag when
exiting the profiler event handler from the time that the clock's
value was obtained (and then squirreled away), until the user's code
is once again executing. As a result, functions that are called many
times, or call many functions, will typically accumulate this error.
The error that accumulates in this fashion is typically less than the
accuracy of the clock (i.e., less than one clock tick), but it *can*
accumulate and become very significant. This profiler provides a
means of calibrating itself for a give platform so that this error can
be probabilistically (i.e., on the average) removed. After the
profiler is calibrated, it will be more accurate (in a least square
sense), but it will sometimes produce negative numbers (when call
counts are exceptionally low, and the gods of probability work against
you :-). ) Do *NOT* be alarmed by negative numbers in the profile.
They should *only* appear if you have calibrated your profiler, and
the results are actually better than without calibration.
CALIBRATION
The profiler class has a hard coded constant that is added to each
event handling time to compensate for the overhead of calling the time
function, and socking away the results. The following procedure can
be used to obtain this constant for a given platform (see discussion
in LIMITATIONS above).
import profile
pr = profile.Profile()
pr.calibrate(100)
pr.calibrate(100)
pr.calibrate(100)
The argument to calibrate() is the number of times to try to do the
sample calls to get the CPU times. If your computer is *very* fast,
you might have to do:
pr.calibrate(1000)
or even:
pr.calibrate(10000)
The object of this exercise is to get a fairly consistent result.
When you have a consistent answer, you are ready to use that number in
the source code. For a Sun Sparcstation 1000 running Solaris 2.3, the
magical number is about .00053. If you have a choice, you are better
off with a smaller constant, and your results will "less often" show
up as negative in profile statistics.
The following shows how the trace_dispatch() method in the Profile
class should be modified to install the calibration constant on a Sun
Sparcstation 1000:
def trace_dispatch(self, frame, event, arg):
t = self.timer()
t = t[0] + t[1] - self.t - .00053 # Calibration constant
if self.dispatch[event](frame,t):
t = self.timer()
self.t = t[0] + t[1]
else:
r = self.timer()
self.t = r[0] + r[1] - t # put back unrecorded delta
return
Note that if there is no calibration constant, then the line
containing the callibration constant should simply say:
t = t[0] + t[1] - self.t # no calibration constant
You can also achieve the same results using a derived class (and the
profiler will actually run equally fast!!), but the above method is
the simplest to use. I could have made the profiler "self
calibrating", but it would have made the initialization of the
profiler class slower, and would have required some *very* fancy
coding, or else the use of a variable where the constant .00053 was
placed in the code shown. This is a ****VERY**** critical performance
section, and there is no reason to use a variable lookup at this
point, when a constant can be used.
EXTENSIONS: Deriving Better Profilers
The Profile class of profile was written so that derived classes
could be developed to extend the profiler. Rather than describing all
the details of such an effort, I'll just present the following two
examples of derived classes that can be used to do profiling. If the
reader is an avid Python programmer, then it should be possible to use
these as a model and create similar (and perchance better) profile
classes.
If all you want to do is change how the timer is called, or which
timer function is used, then the basic class has an option for that in
the constructor for the class. Consider passing the name of a
function to call into the constructor:
pr = profile.Profile(your_time_func)
The resulting profiler will call your time function instead of
os.times(). The function should return either a single number, or a
list of numbers (like what os.times() returns). If the function
returns a single time number, or the list of returned numbers has
length 2, then you will get an especially fast version of the dispatch
routine.
Be warned that you *should* calibrate the profiler class for the
timer function that you choose. For most machines, a timer that
returns a lone integer value will provide the best results in terms of
low overhead during profiling. (os.times is *pretty* bad, 'cause it
returns a tuple of floating point values, so all arithmetic is
floating point in the profiler!). If you want to be substitute a
better timer in the cleanest fashion, you should derive a class, and
simply put in the replacement dispatch method that better handles your timer
call, along with the appropriate calibration constant :-).
cut here------------------------------------------------------------------
#****************************************************************************
# OldProfile class documentation
#****************************************************************************
#
# The following derived profiler simulates the old style profile, providing
# errant results on recursive functions. The reason for the usefulness of this
# profiler is that it runs faster (i.e., less overhead) than the old
# profiler. It still creates all the caller stats, and is quite
# useful when there is *no* recursion in the user's code. It is also
# a lot more accurate than the old profiler, as it does not charge all
# its overhead time to the user's code.
#****************************************************************************
class OldProfile(Profile):
def trace_dispatch_exception(self, frame, t):
rt, rtt, rct, rfn, rframe, rcur = self.cur
if rcur and not rframe is frame:
return self.trace_dispatch_return(rframe, t)
return 0
def trace_dispatch_call(self, frame, t):
fn = `frame.f_code`
self.cur = (t, 0, 0, fn, frame, self.cur)
if self.timings.has_key(fn):
tt, ct, callers = self.timings[fn]
self.timings[fn] = tt, ct, callers
else:
self.timings[fn] = 0, 0, {}
return 1
def trace_dispatch_return(self, frame, t):
rt, rtt, rct, rfn, frame, rcur = self.cur
rtt = rtt + t
sft = rtt + rct
pt, ptt, pct, pfn, pframe, pcur = rcur
self.cur = pt, ptt+rt, pct+sft, pfn, pframe, pcur
tt, ct, callers = self.timings[rfn]
if callers.has_key(pfn):
callers[pfn] = callers[pfn] + 1
else:
callers[pfn] = 1
self.timings[rfn] = tt+rtt, ct + sft, callers
return 1
def snapshot_stats(self):
self.stats = {}
for func in self.timings.keys():
tt, ct, callers = self.timings[func]
nor_func = self.func_normalize(func)
nor_callers = {}
nc = 0
for func_caller in callers.keys():
nor_callers[self.func_normalize(func_caller)]=\
callers[func_caller]
nc = nc + callers[func_caller]
self.stats[nor_func] = nc, nc, tt, ct, nor_callers
#****************************************************************************
# HotProfile class documentation
#****************************************************************************
#
# This profiler is the fastest derived profile example. It does not
# calculate caller-callee relationships, and does not calculate cumulative
# time under a function. It only calculates time spent in a function, so
# it runs very quickly (re: very low overhead). In truth, the basic
# profiler is so fast, that is probably not worth the savings to give
# up the data, but this class still provides a nice example.
#****************************************************************************
class HotProfile(Profile):
def trace_dispatch_exception(self, frame, t):
rt, rtt, rfn, rframe, rcur = self.cur
if rcur and not rframe is frame:
return self.trace_dispatch_return(rframe, t)
return 0
def trace_dispatch_call(self, frame, t):
self.cur = (t, 0, frame, self.cur)
return 1
def trace_dispatch_return(self, frame, t):
rt, rtt, frame, rcur = self.cur
rfn = `frame.f_code`
pt, ptt, pframe, pcur = rcur
self.cur = pt, ptt+rt, pframe, pcur
if self.timings.has_key(rfn):
nc, tt = self.timings[rfn]
self.timings[rfn] = nc + 1, rt + rtt + tt
else:
self.timings[rfn] = 1, rt + rtt
return 1
def snapshot_stats(self):
self.stats = {}
for func in self.timings.keys():
nc, tt = self.timings[func]
nor_func = self.func_normalize(func)
self.stats[nor_func] = nc, nc, tt, 0, {}
cut here------------------------------------------------------------------

View file

@ -1,380 +1,80 @@
#
# Class for profiling python code.
# Author: Sjoerd Mullender
# Hacked somewhat by: Guido van Rossum
# Class for profiling python code. rev 1.0 6/2/94
#
# See the accompanying document profile.doc for more information.
# Based on prior profile module by Sjoerd Mullender...
# which was hacked somewhat by: Guido van Rossum
#
# See profile.doc for more information
# Copyright 1994, by InfoSeek Corporation, all rights reserved.
# Written by James Roskind
#
# Permission to use, copy, modify, and distribute this Python software
# and its associated documentation for any purpose (subject to the
# restriction in the following sentence) without fee is hereby granted,
# provided that the above copyright notice appears in all copies, and
# that both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of InfoSeek not be used in
# advertising or publicity pertaining to distribution of the software
# without specific, written prior permission. This permission is
# explicitly restricted to the copying and modification of the software
# to remain in Python, compiled Python, or other languages (such as C)
# wherein the modified or derived code is exclusively imported into a
# Python module.
#
# INFOSEEK CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS. IN NO EVENT SHALL INFOSEEK CORPORATION BE LIABLE FOR ANY
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import sys
import codehack
import os
import time
import string
import fpformat
import marshal
class Profile:
def __init__(self):
self.timings = {}
self.debug = None
self.call_level = 0
self.profile_func = None
self.profiling = 0
def profile(self, funcname):
if not self.profile_func:
self.profile_func = {}
self.profile_func[funcname] = 1
def trace_dispatch(self, frame, event, arg):
if event == 'call':
funcname = codehack.getcodename(frame.f_code)
if self.profile_func and not self.profiling:
if self.profile_func.has_key(funcname):
return
self.profiling = 1
t = os.times()
t = t[0] + t[1]
if frame.f_locals.has_key('__key'):
key = frame.f_locals['__key']
else:
lineno = codehack.getlineno(frame.f_code)
filename = frame.f_code.co_filename
key = filename + ':' + `lineno` + '(' + funcname + ')'
frame.f_locals['__key'] = key
self.call_level = depth(frame)
self.cur_frame = frame
pframe = frame.f_back
if self.debug:
s0 = 'call: ' + key + ' depth: ' + `self.call_level` + ' time: ' + `t`
if pframe:
if pframe.f_locals.has_key('__key'):
pkey = pframe.f_locals['__key']
else:
pkey = pframe.f_code.co_filename + \
':' + \
`codehack.getlineno(pframe.f_code)` \
+ '(' + \
codehack.getcodename(pframe.f_code) \
+ ')'
pframe.f_locals['__key'] = pkey
if self.debug:
s1 = 'parent: ' + pkey
if pframe.f_locals.has_key('__start_time'):
st = pframe.f_locals['__start_time']
nc, tt, ct, callers, callees = \
self.timings[pkey]
if self.debug:
s1 = s1+' before: st='+`st`+' nc='+`nc`+' tt='+`tt`+' ct='+`ct`
if callers.has_key(key):
callers[key] = callers[key] + 1
else:
callers[key] = 1
if self.debug:
s1 = s1+' after: st='+`st`+' nc='+`nc`+' tt='+`tt+(t-st)`+' ct='+`ct`
self.timings[pkey] = nc, tt + (t - st), ct, callers, callees
if self.timings.has_key(key):
nc, tt, ct, callers, callees = self.timings[key]
else:
nc, tt, ct, callers, callees = 0, 0, 0, {}, {}
if self.debug:
s0 = s0+' before: nc='+`nc`+' tt='+`tt`+' ct='+`ct`
s0 = s0+' after: nc='+`nc+1`+' tt='+`tt`+' ct='+`ct`
if pframe:
if callees.has_key(pkey):
callees[pkey] = callees[pkey] + 1
else:
callees[pkey] = 1
self.timings[key] = nc + 1, tt, ct, callers, callees
frame.f_locals['__start_time'] = t
if self.debug:
print s0
print s1
return
if event == 'return':
if self.profile_func:
if not self.profiling:
return
if self.profile_func.has_key( \
codehack.getcodename(frame.f_code)):
self.profiling = 0
self.call_level = depth(frame)
self.cur_frame = frame
pframe = frame.f_back
if self.debug:
s0 = 'return: '
else:
s0 = None
self.handle_return(pframe, frame, s0)
return
if event == 'exception':
if self.profile_func and not self.profiling:
return
call_level = depth(frame)
if call_level < self.call_level:
if call_level <> self.call_level - 1:
print 'heh!',call_level,self.call_level
if self.debug:
s0 = 'exception: '
else:
s0 = None
self.handle_return(self.cur_frame, frame, s0)
self.call_level = call_level
self.cur_frame = frame
return
print 'profile.Profile.dispatch: unknown debugging event:',
print `event`
return
def handle_return(self, pframe, frame, s0):
t = os.times()
t = t[0] + t[1]
if frame.f_locals.has_key('__key'):
key = frame.f_locals['__key']
else:
funcname = codehack.getcodename(frame.f_code)
lineno = codehack.getlineno(frame.f_code)
filename = frame.f_code.co_filename
key = filename + ':' + `lineno` + '(' + funcname + ')'
frame.f_locals['__key'] = key
if self.debug:
s0 = s0 + key + ' depth: ' + `self.call_level` + ' time: ' + `t`
if pframe:
if pframe.f_locals.has_key('__key'):
pkey = pframe.f_locals['__key']
else:
funcname = codehack.getcodename(frame.f_code)
lineno = codehack.getlineno(frame.f_code)
filename = frame.f_code.co_filename
pkey = filename + ':' + `lineno` + '(' + funcname + ')'
pframe.f_locals['__key'] = pkey
if self.debug:
s1 = 'parent: '+pkey
if pframe.f_locals.has_key('__start_time') and \
self.timings.has_key(pkey):
st = pframe.f_locals['__start_time']
nc, tt, ct, callers, callees = \
self.timings[pkey]
if self.debug:
s1 = s1+' before: st='+`st`+' nc='+`nc`+' tt='+`tt`+' ct='+`ct`
s1 = s1+' after: st='+`t`+' nc='+`nc`+' tt='+`tt`+' ct='+`ct+(t-st)`
self.timings[pkey] = \
nc, tt, ct + (t - st), callers, callees
pframe.f_locals['__start_time'] = t
if self.timings.has_key(key):
nc, tt, ct, callers, callees = self.timings[key]
else:
nc, tt, ct, callers, callees = 0, 0, 0, {}, {}
if frame.f_locals.has_key('__start_time'):
st = frame.f_locals['__start_time']
else:
st = t
if self.debug:
s0 = s0+' before: st='+`st`+' nc='+`nc`+' tt='+`tt`+' ct='+`ct`
s0 = s0+' after: nc='+`nc`+' tt='+`tt+(t-st)`+' ct='+`ct+(t-st)`
print s0
print s1
self.timings[key] = \
nc, tt + (t - st), ct + (t - st), callers, callees
def print_stats(self):
# Print in reverse order by ct
print_title()
list = []
for key in self.timings.keys():
nc, tt, ct, callers, callees = self.timings[key]
if nc == 0:
continue
list.append(ct, tt, nc, key)
list.sort()
list.reverse()
for ct, tt, nc, key in list:
print_line(nc, tt, ct, os.path.basename(key))
def dump_stats(self, file):
f = open(file, 'w')
marshal.dump(self.timings, f)
f.close()
# The following two methods can be called by clients to use
# a profiler to profile a statement, given as a string.
def run(self, cmd):
import __main__
dict = __main__.__dict__
self.runctx(cmd, dict, dict)
def runctx(self, cmd, globals, locals):
sys.setprofile(self.trace_dispatch)
try:
exec(cmd + '\n', globals, locals)
finally:
sys.setprofile(None)
# This method is more useful to profile a single function call.
def runcall(self, func, *args):
sys.setprofile(self.trace_dispatch)
try:
apply(func, args)
finally:
sys.setprofile(None)
# Global variables
func_norm_dict = {}
func_norm_counter = 0
pid_string = `os.getpid()`
def depth(frame):
d = 0
while frame:
d = d + 1
frame = frame.f_back
return d
# Optimized intermodule references
ostimes = os.times
class Stats:
def __init__(self, file):
f = open(file, 'r')
self.stats = marshal.load(f)
f.close()
self.stats_list = None
def print_stats(self):
print_title()
if self.stats_list:
for i in range(len(self.stats_list)):
nc, tt, ct, callers, callees, key = \
self.stats_list[i]
print_line(nc, tt, ct, key)
else:
for key in self.stats.keys():
nc, tt, ct, callers, callees = self.stats[key]
print_line(nc, tt, ct, key)
# Sample timer for use with
#i_count = 0
#def integer_timer():
# global i_count
# i_count = i_count + 1
# return i_count
#itimes = integer_timer # replace with C coded timer returning integers
def print_callers(self):
if self.stats_list:
for i in range(len(self.stats_list)):
nc, tt, ct, callers, callees, key = \
self.stats_list[i]
print key,
for func in callers.keys():
print func+'('+`callers[func]`+')',
print
else:
for key in self.stats.keys():
nc, tt, ct, callers, callees = self.stats[key]
print key,
for func in callers.keys():
print func+'('+`callers[func]`+')',
print
#**************************************************************************
# The following are the static member functions for the profiler class
# Note that an instance of Profile() is *not* needed to call them.
#**************************************************************************
def print_callees(self):
if self.stats_list:
for i in range(len(self.stats_list)):
nc, tt, ct, callers, callees, key = \
self.stats_list[i]
print key,
for func in callees.keys():
print func+'('+`callees[func]`+')',
print
else:
for key in self.stats.keys():
nc, tt, ct, callers, callees = self.stats[key]
print key,
for func in callees.keys():
print func+'('+`callees[func]`+')',
print
def sort_stats(self, field):
stats_list = []
for key in self.stats.keys():
t = self.stats[key]
nt = ()
for i in range(len(t)):
if i == field:
nt = (t[i],) + nt[:]
else:
nt = nt[:] + (t[i],)
if field == -1:
nt = (key,) + nt
else:
nt = nt + (key,)
stats_list.append(nt)
stats_list.sort()
self.stats_list = []
for i in range(len(stats_list)):
t = stats_list[i]
if field == -1:
nt = t[1:] + t[0:1]
else:
nt = t[1:]
nt = nt[:field] + t[0:1] + nt[field:]
self.stats_list.append(nt)
def reverse_order(self):
self.stats_list.reverse()
def strip_dirs(self):
newstats = {}
for key in self.stats.keys():
nc, tt, ct, callers, callees = self.stats[key]
newkey = os.path.basename(key)
newcallers = {}
for c in callers.keys():
newcallers[os.path.basename(c)] = callers[c]
newcallees = {}
for c in callees.keys():
newcallees[os.path.basename(c)] = callees[c]
newstats[newkey] = nc, tt, ct, newcallers, newcallees
self.stats = newstats
self.stats_list = None
def print_title():
print string.rjust('ncalls', 8),
print string.rjust('tottime', 8),
print string.rjust('percall', 8),
print string.rjust('cumtime', 8),
print string.rjust('percall', 8),
print 'filename:lineno(function)'
def print_line(nc, tt, ct, key):
print string.rjust(`nc`, 8),
print f8(tt),
if nc == 0:
print ' '*8,
else:
print f8(tt/nc),
print f8(ct),
if nc == 0:
print ' '*8,
else:
print f8(ct/nc),
print key
def f8(x):
return string.rjust(fpformat.fix(x, 3), 8)
# simplified user interface
def run(statement, *args):
prof = Profile()
try:
prof.run(statement)
prof = prof.run(statement)
except SystemExit:
pass
if len(args) == 0:
prof.print_stats()
else:
if args:
prof.dump_stats(args[0])
# test command with debugging
def debug():
prof = Profile()
prof.debug = 1
try:
prof.run('import x; x.main()')
except SystemExit:
pass
prof.print_stats()
# test command
def test():
run('import x; x.main()')
else:
return prof.print_stats()
# print help
def help():
@ -387,3 +87,526 @@ def help():
else:
print 'Sorry, can\'t find the help file "profile.doc"',
print 'along the Python search path'
#**************************************************************************
# class Profile documentation:
#**************************************************************************
# self.cur is always a tuple. Each such tuple corresponds to a stack
# frame that is currently active (self.cur[-2]). The following are the
# definitions of its members. We use this external "parallel stack" to
# avoid contaminating the program that we are profiling. (old profiler
# used to write into the frames local dictionary!!) Derived classes
# can change the definition of some entries, as long as they leave
# [-2:] intact.
#
# [ 0] = Time that needs to be charged to the parent frame's function. It is
# used so that a function call will not have to access the timing data
# for the parents frame.
# [ 1] = Total time spent in this frame's function, excluding time in
# subfunctions
# [ 2] = Cumulative time spent in this frame's function, including time in
# all subfunctions to this frame.
# [-3] = Name of the function that corresonds to this frame.
# [-2] = Actual frame that we correspond to (used to sync exception handling)
# [-1] = Our parent 6-tuple (corresonds to frame.f_back)
#**************************************************************************
# Timing data for each function is stored as a 5-tuple in the dictionary
# self.timings[]. The index is always the name stored in self.cur[4].
# The following are the definitions of the members:
#
# [0] = The number of times this function was called, not counting direct
# or indirect recursion,
# [1] = Number of times this function appears on the stack, minus one
# [2] = Total time spent internal to this function
# [3] = Cumulative time that this function was present on the stack. In
# non-recursive functions, this is the total execution time from start
# to finish of each invocation of a function, including time spent in
# all subfunctions.
# [5] = A dictionary indicating for each function name, the number of times
# it was called by us.
#**************************************************************************
# We produce function names via a repr() call on the f_code object during
# profiling. This save a *lot* of CPU time. This results in a string that
# always looks like:
# <code object main at 87090, file "/a/lib/python-local/myfib.py", line 76>
# After we "normalize it, it is a tuple of filename, line, function-name.
# We wait till we are done profiling to do the normalization.
# *IF* this repr format changes, then only the normalization routine should
# need to be fixed.
#**************************************************************************
class Profile:
def __init__(self, *arg):
self.timings = {}
self.cur = None
self.cmd = ""
self.dispatch = { \
'call' : self.trace_dispatch_call, \
'return' : self.trace_dispatch_return, \
'exception': self.trace_dispatch_exception, \
}
if not arg:
self.timer = os.times
self.dispatcher = self.trace_dispatch
else:
self.timer = arg[0]
t = self.timer() # test out timer function
try:
if len(t) == 2:
self.dispatcher = self.trace_dispatch
else:
self.dispatcher = self.trace_dispatch_r
except:
self.dispatcher = self.trace_dispatch_i
self.t = self.get_time()
self.simulate_call('profiler')
def get_time(self): # slow simulation of method to acquire time
t = self.timer()
if type(t) == type(()) or type(t) == type([]):
t = reduce(lambda x,y: x+y, t, 0)
return t
# Heavily optimized dispatch routine for os.times() timer
def trace_dispatch(self, frame, event, arg):
t = self.timer()
t = t[0] + t[1] - self.t # No Calibration constant
# t = t[0] + t[1] - self.t - .00053 # Calibration constant
if self.dispatch[event](frame,t):
t = self.timer()
self.t = t[0] + t[1]
else:
r = self.timer()
self.t = r[0] + r[1] - t # put back unrecorded delta
return
# Dispatch routine for best timer program (return = scalar integer)
def trace_dispatch_i(self, frame, event, arg):
t = self.timer() - self.t # - 1 # Integer calibration constant
if self.dispatch[event](frame,t):
self.t = self.timer()
else:
self.t = self.timer() - t # put back unrecorded delta
return
# SLOW generic dispatch rountine for timer returning lists of numbers
def trace_dispatch_l(self, frame, event, arg):
t = self.get_time() - self.t
if self.dispatch[event](frame,t):
self.t = self.get_time()
else:
self.t = self.get_time()-t # put back unrecorded delta
return
def trace_dispatch_exception(self, frame, t):
rt, rtt, rct, rfn, rframe, rcur = self.cur
if (not rframe is frame) and rcur:
return self.trace_dispatch_return(rframe, t)
return 0
def trace_dispatch_call(self, frame, t):
fn = `frame.f_code`
# The following should be about the best approach, but
# we would need a function that maps from id() back to
# the actual code object.
# fn = id(frame.f_code)
# Note we would really use our own function, which would
# return the code address, *and* bump the ref count. We
# would then fix up the normalize function to do the
# actualy repr(fn) call.
# The following is an interesting alternative
# It doesn't do as good a job, and it doesn't run as
# fast 'cause repr() is written in C, and this is Python.
#fcode = frame.f_code
#code = fcode.co_code
#if ord(code[0]) == 127: # == SET_LINENO
# # see "opcode.h" in the Python source
# fn = (fcode.co_filename, ord(code[1]) | \
# ord(code[2]) << 8, fcode.co_name)
#else:
# fn = (fcode.co_filename, 0, fcode.co_name)
self.cur = (t, 0, 0, fn, frame, self.cur)
if self.timings.has_key(fn):
cc, ns, tt, ct, callers = self.timings[fn]
self.timings[fn] = cc, ns + 1, tt, ct, callers
else:
self.timings[fn] = 0, 0, 0, 0, {}
return 1
def trace_dispatch_return(self, frame, t):
# if not frame is self.cur[-2]: raise "Bad return", self.cur[3]
# Prefix "r" means part of the Returning or exiting frame
# Prefix "p" means part of the Previous or older frame
rt, rtt, rct, rfn, frame, rcur = self.cur
rtt = rtt + t
sft = rtt + rct
pt, ptt, pct, pfn, pframe, pcur = rcur
self.cur = pt, ptt+rt, pct+sft, pfn, pframe, pcur
cc, ns, tt, ct, callers = self.timings[rfn]
if not ns:
ct = ct + sft
cc = cc + 1
if callers.has_key(pfn):
callers[pfn] = callers[pfn] + 1 # hack: gather more
# stats such as the amount of time added to ct courtesy
# of this specific call, and the contribution to cc
# courtesy of this call.
else:
callers[pfn] = 1
self.timings[rfn] = cc, ns - 1, tt+rtt, ct, callers
return 1
# The next few function play with self.cmd. By carefully preloading
# our paralell stack, we can force the profiled result to include
# an arbitrary string as the name of the calling function.
# We use self.cmd as that string, and the resulting stats look
# very nice :-).
def set_cmd(self, cmd):
if self.cur[-1]: return # already set
self.cmd = cmd
self.simulate_call(cmd)
class fake_code:
def __init__(self, filename, line, name):
self.co_filename = filename
self.co_line = line
self.co_name = name
self.co_code = '\0' # anything but 127
def __repr__(self):
return (self.co_filename, self.co_line, self.co_name)
class fake_frame:
def __init__(self, code, prior):
self.f_code = code
self.f_back = prior
def simulate_call(self, name):
code = self.fake_code('profile', 0, name)
if self.cur:
pframe = self.cur[-2]
else:
pframe = None
frame = self.fake_frame(code, pframe)
a = self.dispatch['call'](frame, 0)
return
# collect stats from pending stack, including getting final
# timings for self.cmd frame.
def simulate_cmd_complete(self):
t = self.get_time() - self.t
while self.cur[-1]:
# We *can* cause assertion errors here if
# dispatch_trace_return checks for a frame match!
a = self.dispatch['return'](self.cur[-2], t)
t = 0
self.t = self.get_time() - t
def print_stats(self):
import pstats
pstats.Stats(self).strip_dirs().sort_stats(-1). \
print_stats()
def dump_stats(self, file):
f = open(file, 'w')
self.create_stats()
marshal.dump(self.stats, f)
f.close()
def create_stats(self):
self.simulate_cmd_complete()
self.snapshot_stats()
def snapshot_stats(self):
self.stats = {}
for func in self.timings.keys():
cc, ns, tt, ct, callers = self.timings[func]
nor_func = self.func_normalize(func)
nor_callers = {}
nc = 0
for func_caller in callers.keys():
nor_callers[self.func_normalize(func_caller)]=\
callers[func_caller]
nc = nc + callers[func_caller]
self.stats[nor_func] = cc, nc, tt, ct, nor_callers
# Override the following function if you can figure out
# a better name for the binary f_code entries. I just normalize
# them sequentially in a dictionary. It would be nice if we could
# *really* see the name of the underlying C code :-). Sometimes
# you can figure out what-is-what by looking at caller and callee
# lists (and knowing what your python code does).
def func_normalize(self, func_name):
global func_norm_dict
global func_norm_counter
global func_sequence_num
if func_norm_dict.has_key(func_name):
return func_norm_dict[func_name]
if type(func_name) == type(""):
long_name = string.split(func_name)
file_name = long_name[6][1:-2]
func = long_name[2]
lineno = long_name[8][:-1]
if '?' == func: # Until I find out how to may 'em...
file_name = 'python'
func_norm_counter = func_norm_counter + 1
func = pid_string + ".C." + `func_norm_counter`
result = file_name , string.atoi(lineno) , func
else:
result = func_name
func_norm_dict[func_name] = result
return result
# The following two methods can be called by clients to use
# a profiler to profile a statement, given as a string.
def run(self, cmd):
import __main__
dict = __main__.__dict__
self.runctx(cmd, dict, dict)
return self
def runctx(self, cmd, globals, locals):
self.set_cmd(cmd)
sys.setprofile(self.trace_dispatch)
try:
exec(cmd, globals, locals)
finally:
sys.setprofile(None)
# This method is more useful to profile a single function call.
def runcall(self, func, *args):
self.set_cmd(func.__name__)
sys.setprofile(self.trace_dispatch)
try:
apply(func, args)
finally:
sys.setprofile(None)
return self
#******************************************************************
# The following calculates the overhead for using a profiler. The
# problem is that it takes a fair amount of time for the profiler
# to stop the stopwatch (from the time it recieves an event).
# Similarly, there is a delay from the time that the profiler
# re-starts the stopwatch before the user's code really gets to
# continue. The following code tries to measure the difference on
# a per-event basis. The result can the be placed in the
# Profile.dispatch_event() routine for the given platform. Note
# that this difference is only significant if there are a lot of
# events, and relatively little user code per event. For example,
# code with small functions will typically benefit from having the
# profiler calibrated for the current platform. This *could* be
# done on the fly during init() time, but it is not worth the
# effort. Also note that if too large a value specified, then
# execution time on some functions will actually appear as a
# negative number. It is *normal* for some functions (with very
# low call counts) to have such negative stats, even if the
# calibration figure is "correct."
#
# One alternative to profile-time calibration adjustments (i.e.,
# adding in the magic little delta during each event) is to track
# more carefully the number of events (and cumulatively, the number
# of events during sub functions) that are seen. If this were
# done, then the arithmetic could be done after the fact (i.e., at
# display time). Currintly, we track only call/return events.
# These values can be deduced by examining the callees and callers
# vectors for each functions. Hence we *can* almost correct the
# internal time figure at print time (note that we currently don't
# track exception event processing counts). Unfortunately, there
# is currently no similar information for cumulative sub-function
# time. It would not be hard to "get all this info" at profiler
# time. Specifically, we would have to extend the tuples to keep
# counts of this in each frame, and then extend the defs of timing
# tuples to include the significant two figures. I'm a bit fearful
# that this additional feature will slow the heavily optimized
# event/time ratio (i.e., the profiler would run slower, fur a very
# low "value added" feature.)
#
# Plugging in the calibration constant doesn't slow down the
# profiler very much, and the accuracy goes way up.
#**************************************************************
def calibrate(self, m):
n = m
s = self.timer()
while n:
self.simple()
n = n - 1
f = self.timer()
my_simple = f[0]+f[1]-s[0]-s[1]
#print "Simple =", my_simple,
n = m
s = self.timer()
while n:
self.instrumented()
n = n - 1
f = self.timer()
my_inst = f[0]+f[1]-s[0]-s[1]
# print "Instrumented =", my_inst
avg_cost = (my_inst - my_simple)/m
#print "Delta/call =", avg_cost, "(profiler fixup constant)"
return avg_cost
# simulate a program with no profiler activity
def simple(self):
a = 1
pass
# simulate a program with call/return event processing
def instrumented(self):
a = 1
self.profiler_simulation(a, a, a)
# simulate an event processing activity (from user's perspective)
def profiler_simulation(self, x, y, z):
t = self.timer()
t = t[0] + t[1]
self.ut = t
#****************************************************************************
# OldProfile class documentation
#****************************************************************************
#
# The following derived profiler simulates the old style profile, providing
# errant results on recursive functions. The reason for the usefulnes of this
# profiler is that it runs faster (i.e., less overhead). It still creates
# all the caller stats, and is quite useful when there is *no* recursion
# in the user's code.
#
# This code also shows how easy it is to create a modified profiler.
#****************************************************************************
class OldProfile(Profile):
def trace_dispatch_exception(self, frame, t):
rt, rtt, rct, rfn, rframe, rcur = self.cur
if rcur and not rframe is frame:
return self.trace_dispatch_return(rframe, t)
return 0
def trace_dispatch_call(self, frame, t):
fn = `frame.f_code`
self.cur = (t, 0, 0, fn, frame, self.cur)
if self.timings.has_key(fn):
tt, ct, callers = self.timings[fn]
self.timings[fn] = tt, ct, callers
else:
self.timings[fn] = 0, 0, {}
return 1
def trace_dispatch_return(self, frame, t):
rt, rtt, rct, rfn, frame, rcur = self.cur
rtt = rtt + t
sft = rtt + rct
pt, ptt, pct, pfn, pframe, pcur = rcur
self.cur = pt, ptt+rt, pct+sft, pfn, pframe, pcur
tt, ct, callers = self.timings[rfn]
if callers.has_key(pfn):
callers[pfn] = callers[pfn] + 1
else:
callers[pfn] = 1
self.timings[rfn] = tt+rtt, ct + sft, callers
return 1
def snapshot_stats(self):
self.stats = {}
for func in self.timings.keys():
tt, ct, callers = self.timings[func]
nor_func = self.func_normalize(func)
nor_callers = {}
nc = 0
for func_caller in callers.keys():
nor_callers[self.func_normalize(func_caller)]=\
callers[func_caller]
nc = nc + callers[func_caller]
self.stats[nor_func] = nc, nc, tt, ct, nor_callers
#****************************************************************************
# HotProfile class documentation
#****************************************************************************
#
# This profiler is the fastest derived profile example. It does not
# calculate caller-callee relationships, and does not calculate cumulative
# time under a function. It only calculates time spent in a function, so
# it runs very quickly (re: very low overhead)
#****************************************************************************
class HotProfile(Profile):
def trace_dispatch_exception(self, frame, t):
rt, rtt, rfn, rframe, rcur = self.cur
if rcur and not rframe is frame:
return self.trace_dispatch_return(rframe, t)
return 0
def trace_dispatch_call(self, frame, t):
self.cur = (t, 0, frame, self.cur)
return 1
def trace_dispatch_return(self, frame, t):
rt, rtt, frame, rcur = self.cur
rfn = `frame.f_code`
pt, ptt, pframe, pcur = rcur
self.cur = pt, ptt+rt, pframe, pcur
if self.timings.has_key(rfn):
nc, tt = self.timings[rfn]
self.timings[rfn] = nc + 1, rt + rtt + tt
else:
self.timings[rfn] = 1, rt + rtt
return 1
def snapshot_stats(self):
self.stats = {}
for func in self.timings.keys():
nc, tt = self.timings[func]
nor_func = self.func_normalize(func)
self.stats[nor_func] = nc, nc, tt, 0, {}
#****************************************************************************
def Stats(*args):
print 'Report generating functions are in the "pstats" module\a'

View file

@ -10,13 +10,7 @@ def __init__(self, pat):
self.prog = regex.compile(pat)
finally:
xxx = regex.set_syntax(save_syntax)
def match(self, *args):
if len(args) == 2:
str, offset = args
elif len(args) == 1:
str, offset = args[0], 0
else:
raise TypeError, 'wrong argument count'
def match(self, str, offset = 0):
if self.prog.search(str, offset) < 0:
return ()
regs = self.prog.regs

View file

@ -77,6 +77,19 @@ def repr_long_int(self, x, level):
j = max(0, self.maxlong-3-i)
s = s[:i] + '...' + s[len(s)-j:]
return s
def repr_instance(self, x, level):
try:
s = `x`
# Bugs in x.__repr__() can cause arbitrary
# exceptions -- then make up something
except:
return '<' + x.__class__.__name__ + ' instance at ' + \
hex(id(x))[2:] + '>'
if len(s) > self.maxstring:
i = max(0, (self.maxstring-3)/2)
j = max(0, self.maxstring-3-i)
s = s[:i] + '...' + s[len(s)-j:]
return s
aRepr = Repr()
repr = aRepr.repr

View file

@ -1,8 +1,8 @@
# RFC-822 message manipulation class.
#
# XXX This is only a very rough sketch of a full RFC-822 parser;
# additional methods are needed to parse addresses and dates, and to
# tokenize lines according to various other syntax rules.
# in particular the tokenizing of addresses does not adhere to all the
# quoting rules.
#
# Directions for use:
#
@ -22,6 +22,17 @@
# embedded whitespace (including newlines) exactly as they are
# specified in the header, and leave the case of the text unchanged.
#
# For addresses and address lists there are functions
# realname, mailaddress = m.getaddr(name) and
# list = m.getaddrlist(name)
# where the latter returns a list of (realname, mailaddr) tuples.
#
# There is also a method
# time = m.getdate(name)
# which parses a Date-like field and returns a time-compatible tuple,
# i.e. a tuple such as returned by time.localtime() or accepted by
# time.mktime().
#
# See the class definition for lower level access methods.
#
# There are also some utility functions here.
@ -29,6 +40,7 @@
import regex
import string
import time
class Message:
@ -105,12 +117,13 @@ def readheaders(self):
# Method to determine whether a line is a legal end of
# RFC-822 headers. You may override this method if your
# application wants to bend the rules, e.g. to accept lines
# ending in '\r\n', to strip trailing whitespace, or to
# recognise MH template separators ('--------').
# application wants to bend the rules, e.g. to strip trailing
# whitespace, or to recognise MH template separators
# ('--------'). For convenience (e.g. for code reading from
# sockets) a line consisting of \r\n also matches.
def islast(self, line):
return line == '\n'
return line == '\n' or line == '\r\n'
# Look through the list of headers and find all lines matching
@ -178,27 +191,94 @@ def getheader(self, name):
return string.strip(text)
# XXX The next step would be to define self.getaddr(name)
# and self.getaddrlist(name) which would parse a header
# consisting of a single mail address and a number of mail
# addresses, respectively. Lower level functions would be
# parseaddr(string) and parseaddrlist(string).
# Retrieve a single address from a header as a tuple, e.g.
# ('Guido van Rossum', 'guido@cwi.nl').
# XXX Similar, there would be a function self.getdate(name) to
# return a date in canonical form (perhaps a number compatible
# to time.time()) and a function parsedate(string).
def getaddr(self, name):
data = self.getheader(name)
if not data:
return None, None
return parseaddr(data)
# XXX The inverses of the parse functions may also be useful.
# Retrieve a list of addresses from a header, where each
# address is a tuple as returned by getaddr().
def getaddrlist(self, name):
# XXX This function is not really correct. The split
# on ',' might fail in the case of commas within
# quoted strings.
data = self.getheader(name)
if not data:
return []
data = string.splitfields(data, ',')
for i in range(len(data)):
data[i] = parseaddr(data[i])
return data
# Retrieve a date field from a header as a tuple compatible
# with time.mktime().
def getdate(self, name):
data = self.getheader(name)
if not data:
return None
return parsedate(data)
# Access as a dictionary (only finds first header of each type):
def __len__(self):
types = {}
for line in self.headers:
if line[0] in string.whitespace: continue
i = string.find(line, ':')
if i > 0:
name = string.lower(line[:i])
types[name] = None
return len(types)
def __getitem__(self, name):
value = self.getheader(name)
if value is None: raise KeyError, name
return value
def has_key(self, name):
value = self.getheader(name)
return value is not None
def keys(self):
types = {}
for line in self.headers:
if line[0] in string.whitespace: continue
i = string.find(line, ':')
if i > 0:
name = line[:i]
key = string.lower(name)
types[key] = name
return types.values()
def values(self):
values = []
for name in self.keys():
values.append(self[name])
return values
def items(self):
items = []
for name in self.keys():
items.append(name, self[name])
return items
# Utility functions
# -----------------
# XXX Should fix these to be really conformant.
# XXX The inverses of the parse functions may also be useful.
# Remove quotes from a string.
# XXX Should fix this to be really conformant.
def unquote(str):
if len(str) > 1:
@ -207,3 +287,107 @@ def unquote(str):
if str[0] == '<' and str[-1:] == '>':
return str[1:-1]
return str
# Parse an address into (name, address) tuple
def parseaddr(address):
# This is probably not perfect
address = string.strip(address)
# Case 1: part of the address is in <xx@xx> form.
pos = regex.search('<.*>', address)
if pos >= 0:
name = address[:pos]
address = address[pos:]
length = regex.match('<.*>', address)
name = name + address[length:]
address = address[:length]
else:
# Case 2: part of the address is in (comment) form
pos = regex.search('(.*)', address)
if pos >= 0:
name = address[pos:]
address = address[:pos]
length = regex.match('(.*)', name)
address = address + name[length:]
name = name[:length]
else:
# Case 3: neither. Only an address
name = ''
name = string.strip(name)
address = string.strip(address)
if address and address[0] == '<' and address[-1] == '>':
address = address[1:-1]
if name and name[0] == '(' and name[-1] == ')':
name = name[1:-1]
return name, address
# Parse a date field
_monthnames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
def parsedate(data):
# XXX This completely ignores timezone matters at the moment...
data = string.split(data)
if data[0][-1] == ',':
# There's a dayname here. Skip it
del data[0]
if len(data) < 5:
return None
data = data[:5]
[dd, mm, yy, tm, tz] = data
if not mm in _monthnames:
return None
mm = _monthnames.index(mm)+1
tm = string.splitfields(tm, ':')
if len(tm) == 2:
[thh, tmm] = tm
tss = '0'
else:
[thh, tmm, tss] = tm
try:
yy = string.atoi(yy)
dd = string.atoi(dd)
thh = string.atoi(thh)
tmm = string.atoi(tmm)
tss = string.atoi(tss)
except string.atoi_error:
return None
tuple = (yy, mm, dd, thh, tmm, tss, 0, 0, 0)
return tuple
# When used as script, run a small test program.
# The first command line argument must be a filename containing one
# message in RFC-822 format.
if __name__ == '__main__':
import sys
file = '/ufs/guido/Mail/drafts/,1'
if sys.argv[1:]: file = sys.argv[1]
f = open(file, 'r')
m = Message(f)
print 'From:', m.getaddr('from')
print 'To:', m.getaddrlist('to')
print 'Subject:', m.getheader('subject')
print 'Date:', m.getheader('date')
date = m.getdate('date')
if date:
print 'ParsedDate:', time.asctime(date)
else:
print 'ParsedDate:', None
m.rewindbody()
n = 0
while f.readline():
n = n + 1
print 'Lines:', n
print '-'*70
print 'len =', len(m)
if m.has_key('Date'): print 'Date =', m['Date']
if m.has_key('X-Nonsense'): pass
print 'keys =', m.keys()
print 'values =', m.values()
print 'items =', m.items()

View file

@ -6,12 +6,11 @@
#
# Each instance is parametrized with two functions, one that is
# supposed to return the current time, one that is supposed to
# implement a delay. You can implement fine- or course-grained
# real-time scheduling by substituting time and sleep or millitimer
# and millisleep from the built-in module time, or you can implement
# simulated time by writing your own functions. This can also be
# used to integrate scheduling with STDWIN events; the delay function
# is allowed to modify the queue. Time can be expressed as
# implement a delay. You can implement real-time scheduling by
# substituting time and sleep from built-in module time, or you can
# implement simulated time by writing your own functions. This can
# also be used to integrate scheduling with STDWIN events; the delay
# function is allowed to modify the queue. Time can be expressed as
# integers or floating point numbers, as long as it is consistent.
# Events are specified by tuples (time, priority, action, argument).

View file

@ -1,5 +1,5 @@
# Combine a real-time scheduling queue and stdwin event handling.
# Uses the millisecond timer.
# Keeps times in milliseconds.
import stdwin, stdwinq
from stdwinevents import WE_TIMER
@ -19,11 +19,11 @@ def delayfunc(msecs):
mainloop.dispatch(event)
return
#
# Use millisleep for very short delays or if there are no windows
# Use sleep for very short delays or if there are no windows
#
if msecs < 100 or mainloop.countwindows() == 0:
if msecs > 0:
time.millisleep(msecs)
time.sleep(msecs * 0.001)
return
#
# Post a timer event on an arbitrary window and wait for it
@ -35,7 +35,10 @@ def delayfunc(msecs):
if event[0] <> WE_TIMER:
mainloop.dispatch(event)
q = sched.scheduler(time.millitimer, delayfunc)
def millitimer():
return int(1000 * time.time())
q = sched.scheduler(millitimer, delayfunc)
# Export functions enter, enterabs and cancel just like a scheduler
#

View file

@ -2,19 +2,19 @@
# File windows, a subclass of textwin (which is a subclass of gwin)
import textwin
import builtin
import __builtin__
# FILE WINDOW
def open_readonly(fn): # Open a file window
fp = builtin.open(fn, 'r')
fp = __builtin__.open(fn, 'r')
w = textwin.open_readonly(fn, fp.read())
w.fn = fn
return w
def open(fn): # Open a file window
fp = builtin.open(fn, 'r')
fp = __builtin__.open(fn, 'r')
w = textwin.open(fn, fp.read())
w.fn = fn
return w

Some files were not shown because too many files have changed in this diff Show more