Merge alpha100 branch back to main trunk
This commit is contained in:
parent
2979b01ff8
commit
b6775db241
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, "")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
124
Include/object.h
124
Include/object.h
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 /* "" */
|
||||
|
|
|
@ -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 ';'
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 *));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *));
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ class Play_Audio_sgi:
|
|||
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 @@ class Play_Audio_sgi:
|
|||
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 @@ class Play_Audio_sgi:
|
|||
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 @@ class Play_Audio_sgi:
|
|||
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 @@ class Play_Audio_sun:
|
|||
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
|
||||
|
|
47
Lib/bdb.py
47
Lib/bdb.py
|
@ -17,6 +17,8 @@ class Bdb: # Basic Debugger
|
|||
self.breaks = {}
|
||||
|
||||
def reset(self):
|
||||
import linecache
|
||||
linecache.checkcache()
|
||||
self.botframe = None
|
||||
self.stopframe = None
|
||||
self.returnframe = None
|
||||
|
@ -134,11 +136,35 @@ class Bdb: # Basic Debugger
|
|||
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 @@ class Bdb: # Basic Debugger
|
|||
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 @@ class Bdb: # Basic Debugger
|
|||
#
|
||||
|
||||
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 @@ class Bdb: # Basic Debugger
|
|||
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)')
|
||||
|
|
|
@ -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),
|
||||
|
|
34
Lib/cmd.py
34
Lib/cmd.py
|
@ -56,8 +56,36 @@ class Cmd:
|
|||
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"
|
||||
|
|
|
@ -7,6 +7,10 @@ import string
|
|||
import os
|
||||
import linecache
|
||||
|
||||
# XXX The functions getcodename() and getfuncname() are now obsolete
|
||||
# XXX as code and function objects now have a name attribute --
|
||||
# XXX co.co_name and f.func_name.
|
||||
|
||||
# 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:
|
||||
|
|
|
@ -135,7 +135,8 @@ def_op('BREAK_LOOP', 80)
|
|||
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 @@ jrel_op('FOR_LOOP', 114) # Number of bytes to skip
|
|||
|
||||
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) # ""
|
||||
|
|
113
Lib/ftplib.py
113
Lib/ftplib.py
|
@ -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 @@ all_errors = (error_reply, error_temp, error_perm, error_proto, \
|
|||
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 @@ class FTP:
|
|||
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 @@ class FTP:
|
|||
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 @@ class FTP:
|
|||
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 @@ class FTP:
|
|||
# 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()
|
||||
|
|
|
@ -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_ALLOCSP = 10
|
|||
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
|
||||
|
|
|
@ -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_UDP = 17
|
|||
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_MAX_LOCAL_GROUP = 0xe00000ff
|
|||
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_RECVOPTS = 10
|
|||
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
|
||||
|
|
|
@ -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_USELOOPBACK = 0x0040
|
|||
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_SNDTIMEO = 0x1005
|
|||
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_PUP = 4
|
|||
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_ROUTE = 17
|
|||
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_PUP = AF_PUP
|
|||
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_ROUTE = AF_ROUTE
|
|||
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
|
||||
|
|
|
@ -138,6 +138,19 @@ class Cddb:
|
|||
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 @@ class Cddb:
|
|||
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()
|
||||
|
|
|
@ -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]'
|
||||
|
|
|
@ -7,6 +7,10 @@ import string
|
|||
import os
|
||||
import linecache
|
||||
|
||||
# XXX The functions getcodename() and getfuncname() are now obsolete
|
||||
# XXX as code and function objects now have a name attribute --
|
||||
# XXX co.co_name and f.func_name.
|
||||
|
||||
# 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:
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -241,7 +241,7 @@ class Wdb(bdb.Bdb, basewin.BaseWindow): # Window debugger
|
|||
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 @@ class Wdb(bdb.Bdb, basewin.BaseWindow): # Window debugger
|
|||
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)
|
||||
|
|
|
@ -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 @@ class Message(rfc822.Message):
|
|||
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)
|
||||
|
|
|
@ -85,6 +85,17 @@ class MultiFile:
|
|||
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:
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
170
Lib/pdb.py
170
Lib/pdb.py
|
@ -74,17 +74,31 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
|||
# 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 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
|||
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 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
|||
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 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
|||
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 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
|||
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
|
||||
|
|
|
@ -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_ALLOCSP = 10
|
|||
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
|
||||
|
|
|
@ -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_UDP = 17
|
|||
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_MAX_LOCAL_GROUP = 0xe00000ff
|
|||
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_RECVOPTS = 10
|
|||
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
|
||||
|
|
|
@ -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_USELOOPBACK = 0x0040
|
|||
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_SNDTIMEO = 0x1005
|
|||
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_PUP = 4
|
|||
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_ROUTE = 17
|
|||
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_PUP = AF_PUP
|
|||
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_ROUTE = AF_ROUTE
|
|||
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
|
||||
|
|
|
@ -138,6 +138,19 @@ class Cddb:
|
|||
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 @@ class Cddb:
|
|||
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()
|
||||
|
|
|
@ -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]'
|
||||
|
|
|
@ -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 @@ _FNBIO = 0x1000
|
|||
_FSYNC = 0x2000
|
||||
_FNONBLOCK = 0x4000
|
||||
_FNOCTTY = 0x8000
|
||||
_FMARK = 0x10000
|
||||
_FDEFER = 0x20000
|
||||
O_RDONLY = 0
|
||||
O_WRONLY = 1
|
||||
O_RDWR = 2
|
||||
|
@ -25,7 +27,6 @@ O_EXCL = _FEXCL
|
|||
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 @@ FREAD = _FREAD
|
|||
FWRITE = _FWRITE
|
||||
FMARK = _FMARK
|
||||
FDEFER = _FDEFER
|
||||
FSETBLK = _FSETBLK
|
||||
FSHLOCK = _FSHLOCK
|
||||
FEXLOCK = _FEXLOCK
|
||||
FOPEN = _FOPEN
|
||||
|
@ -62,3 +64,4 @@ F_RDLCK = 1
|
|||
F_WRLCK = 2
|
||||
F_UNLCK = 3
|
||||
F_UNLKSYS = 4
|
||||
O_ACCMODE = (O_RDONLY|O_WRONLY|O_RDWR)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# Generated by h2py from /usr/include/sys/socket.h
|
||||
SOCK_STREAM = 1
|
||||
SOCK_DGRAM = 2
|
||||
SOCK_RAW = 3
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
748
Lib/profile.doc
748
Lib/profile.doc
|
@ -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------------------------------------------------------------------
|
||||
|
|
931
Lib/profile.py
931
Lib/profile.py
|
@ -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'
|
||||
|
|
|
@ -10,13 +10,7 @@ class Prog:
|
|||
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
|
||||
|
|
13
Lib/repr.py
13
Lib/repr.py
|
@ -77,6 +77,19 @@ class Repr:
|
|||
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
|
||||
|
|
216
Lib/rfc822.py
216
Lib/rfc822.py
|
@ -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 @@ class Message:
|
|||
|
||||
# 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 @@ class Message:
|
|||
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()
|
||||
|
||||
|
|
11
Lib/sched.py
11
Lib/sched.py
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue