Commit 6d6c1a35 authored by Tim Peters's avatar Tim Peters

Merge of descr-branch back into trunk.

parent 52d55a39
...@@ -89,6 +89,7 @@ ...@@ -89,6 +89,7 @@
#include "sliceobject.h" #include "sliceobject.h"
#include "cellobject.h" #include "cellobject.h"
#include "iterobject.h" #include "iterobject.h"
#include "descrobject.h"
#include "codecs.h" #include "codecs.h"
#include "pyerrors.h" #include "pyerrors.h"
......
...@@ -295,6 +295,17 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ ...@@ -295,6 +295,17 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
DL_IMPORT(PyObject *) PyObject_Call(PyObject *callable_object,
PyObject *args, PyObject *kw);
/*
Call a callable Python object, callable_object, with
arguments and keywords arguments. The 'args' argument can not be
NULL, but the 'kw' argument can be NULL.
*/
DL_IMPORT(PyObject *) PyObject_CallObject(PyObject *callable_object, DL_IMPORT(PyObject *) PyObject_CallObject(PyObject *callable_object,
PyObject *args); PyObject *args);
......
...@@ -45,6 +45,9 @@ DL_IMPORT(int) Py_MakePendingCalls(void); ...@@ -45,6 +45,9 @@ DL_IMPORT(int) Py_MakePendingCalls(void);
DL_IMPORT(void) Py_SetRecursionLimit(int); DL_IMPORT(void) Py_SetRecursionLimit(int);
DL_IMPORT(int) Py_GetRecursionLimit(void); DL_IMPORT(int) Py_GetRecursionLimit(void);
DL_IMPORT(char *) PyEval_GetFuncName(PyObject *);
DL_IMPORT(char *) PyEval_GetFuncDesc(PyObject *);
/* Interface for threads. /* Interface for threads.
A module that plans to do a blocking system call (or something else A module that plans to do a blocking system call (or something else
......
...@@ -47,10 +47,6 @@ extern DL_IMPORT(PyObject *) PyInstance_New(PyObject *, PyObject *, ...@@ -47,10 +47,6 @@ extern DL_IMPORT(PyObject *) PyInstance_New(PyObject *, PyObject *,
extern DL_IMPORT(PyObject *) PyInstance_NewRaw(PyObject *, PyObject *); extern DL_IMPORT(PyObject *) PyInstance_NewRaw(PyObject *, PyObject *);
extern DL_IMPORT(PyObject *) PyMethod_New(PyObject *, PyObject *, PyObject *); extern DL_IMPORT(PyObject *) PyMethod_New(PyObject *, PyObject *, PyObject *);
extern DL_IMPORT(PyObject *) PyMethod_Function(PyObject *);
extern DL_IMPORT(PyObject *) PyMethod_Self(PyObject *);
extern DL_IMPORT(PyObject *) PyMethod_Class(PyObject *);
/* Macros for direct access to these values. Type checks are *not* /* Macros for direct access to these values. Type checks are *not*
done, so use with care. */ done, so use with care. */
#define PyMethod_GET_FUNCTION(meth) \ #define PyMethod_GET_FUNCTION(meth) \
......
/* XXX getter, setter, getsetlist and wrapperbase need 'Py'-prefixed names */
typedef PyObject *(*getter)(PyObject *, void *);
typedef int (*setter)(PyObject *, PyObject *, void *);
struct getsetlist {
char *name;
getter get;
setter set;
void *closure;
};
typedef PyObject *(*wrapperfunc)(PyObject *self, PyObject *args,
void *wrapped);
struct wrapperbase {
char *name;
wrapperfunc wrapper;
char *doc;
};
extern DL_IMPORT(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *);
extern DL_IMPORT(PyObject *) PyDescr_NewMember(PyTypeObject *,
struct memberlist *);
extern DL_IMPORT(PyObject *) PyDescr_NewGetSet(PyTypeObject *,
struct getsetlist *);
extern DL_IMPORT(PyObject *) PyDescr_NewWrapper(PyTypeObject *,
struct wrapperbase *, void *);
extern DL_IMPORT(int) PyDescr_IsData(PyObject *);
extern DL_IMPORT(PyObject *) PyDictProxy_New(PyObject *);
extern DL_IMPORT(PyObject *) PyWrapper_New(PyObject *, PyObject *);
...@@ -7,9 +7,83 @@ extern "C" { ...@@ -7,9 +7,83 @@ extern "C" {
/* Dictionary object type -- mapping from hashable object to object */ /* Dictionary object type -- mapping from hashable object to object */
/*
There are three kinds of slots in the table:
1. Unused. me_key == me_value == NULL
Does not hold an active (key, value) pair now and never did. Unused can
transition to Active upon key insertion. This is the only case in which
me_key is NULL, and is each slot's initial state.
2. Active. me_key != NULL and me_key != dummy and me_value != NULL
Holds an active (key, value) pair. Active can transition to Dummy upon
key deletion. This is the only case in which me_value != NULL.
3. Dummy. me_key == dummy and me_value == NULL
Previously held an active (key, value) pair, but that was deleted and an
active pair has not yet overwritten the slot. Dummy can transition to
Active upon key insertion. Dummy slots cannot be made Unused again
(cannot have me_key set to NULL), else the probe sequence in case of
collision would have no way to know they were once active.
Note: .popitem() abuses the me_hash field of an Unused or Dummy slot to
hold a search finger. The me_hash field of Unused or Dummy slots has no
meaning otherwise.
*/
/* PyDict_MINSIZE is the minimum size of a dictionary. This many slots are
* allocated directly in the dict object (in the ma_smalltable member).
* It must be a power of 2, and at least 4. 8 allows dicts with no more
* than 5 active entries to live in ma_smalltable (and so avoid an
* additional malloc); instrumentation suggested this suffices for the
* majority of dicts (consisting mostly of usually-small instance dicts and
* usually-small dicts created to pass keyword arguments).
*/
#define PyDict_MINSIZE 8
typedef struct {
long me_hash; /* cached hash code of me_key */
PyObject *me_key;
PyObject *me_value;
#ifdef USE_CACHE_ALIGNED
long aligner;
#endif
} PyDictEntry;
/*
To ensure the lookup algorithm terminates, there must be at least one Unused
slot (NULL key) in the table.
The value ma_fill is the number of non-NULL keys (sum of Active and Dummy);
ma_used is the number of non-NULL, non-dummy keys (== the number of non-NULL
values == the number of Active items).
To avoid slowing down lookups on a near-full table, we resize the table when
it's two-thirds full.
*/
typedef struct _dictobject PyDictObject;
struct _dictobject {
PyObject_HEAD
int ma_fill; /* # Active + # Dummy */
int ma_used; /* # Active */
/* The table contains ma_mask + 1 slots, and that's a power of 2.
* We store the mask instead of the size because the mask is more
* frequently needed.
*/
int ma_mask;
/* ma_table points to ma_smalltable for small tables, else to
* additional malloc'ed memory. ma_table is never NULL! This rule
* saves repeated runtime null-tests in the workhorse getitem and
* setitem calls.
*/
PyDictEntry *ma_table;
PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, long hash);
PyDictEntry ma_smalltable[PyDict_MINSIZE];
};
extern DL_IMPORT(PyTypeObject) PyDict_Type; extern DL_IMPORT(PyTypeObject) PyDict_Type;
#define PyDict_Check(op) ((op)->ob_type == &PyDict_Type) #define PyDict_Check(op) PyObject_TypeCheck(op, &PyDict_Type)
extern DL_IMPORT(PyObject *) PyDict_New(void); extern DL_IMPORT(PyObject *) PyDict_New(void);
extern DL_IMPORT(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key); extern DL_IMPORT(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key);
...@@ -23,6 +97,7 @@ extern DL_IMPORT(PyObject *) PyDict_Values(PyObject *mp); ...@@ -23,6 +97,7 @@ extern DL_IMPORT(PyObject *) PyDict_Values(PyObject *mp);
extern DL_IMPORT(PyObject *) PyDict_Items(PyObject *mp); extern DL_IMPORT(PyObject *) PyDict_Items(PyObject *mp);
extern DL_IMPORT(int) PyDict_Size(PyObject *mp); extern DL_IMPORT(int) PyDict_Size(PyObject *mp);
extern DL_IMPORT(PyObject *) PyDict_Copy(PyObject *mp); extern DL_IMPORT(PyObject *) PyDict_Copy(PyObject *mp);
extern DL_IMPORT(int) PyDict_Update(PyObject *mp, PyObject *other);
extern DL_IMPORT(PyObject *) PyDict_GetItemString(PyObject *dp, char *key); extern DL_IMPORT(PyObject *) PyDict_GetItemString(PyObject *dp, char *key);
......
...@@ -9,6 +9,14 @@ extern "C" { ...@@ -9,6 +9,14 @@ extern "C" {
DL_IMPORT(PyObject *) PyEval_EvalCode(PyCodeObject *, PyObject *, PyObject *); DL_IMPORT(PyObject *) PyEval_EvalCode(PyCodeObject *, PyObject *, PyObject *);
DL_IMPORT(PyObject *) PyEval_EvalCodeEx(PyCodeObject *co,
PyObject *globals,
PyObject *locals,
PyObject **args, int argc,
PyObject **kwds, int kwdc,
PyObject **defs, int defc,
PyObject *closure);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -42,6 +42,13 @@ extern DL_IMPORT(int) PyFunction_SetClosure(PyObject *, PyObject *); ...@@ -42,6 +42,13 @@ extern DL_IMPORT(int) PyFunction_SetClosure(PyObject *, PyObject *);
#define PyFunction_GET_CLOSURE(func) \ #define PyFunction_GET_CLOSURE(func) \
(((PyFunctionObject *)func) -> func_closure) (((PyFunctionObject *)func) -> func_closure)
/* The classmethod and staticmethod types lives here, too */
extern DL_IMPORT(PyTypeObject) PyClassMethod_Type;
extern DL_IMPORT(PyTypeObject) PyStaticMethod_Type;
extern DL_IMPORT(PyObject *) PyClassMethod_New(PyObject *);
extern DL_IMPORT(PyObject *) PyStaticMethod_New(PyObject *);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -26,7 +26,7 @@ typedef struct { ...@@ -26,7 +26,7 @@ typedef struct {
extern DL_IMPORT(PyTypeObject) PyList_Type; extern DL_IMPORT(PyTypeObject) PyList_Type;
#define PyList_Check(op) ((op)->ob_type == &PyList_Type) #define PyList_Check(op) PyObject_TypeCheck(op, &PyList_Type)
extern DL_IMPORT(PyObject *) PyList_New(int size); extern DL_IMPORT(PyObject *) PyList_New(int size);
extern DL_IMPORT(int) PyList_Size(PyObject *); extern DL_IMPORT(int) PyList_Size(PyObject *);
......
...@@ -22,8 +22,8 @@ extern DL_IMPORT(int) PyModule_AddObject(PyObject *, char *, PyObject *); ...@@ -22,8 +22,8 @@ extern DL_IMPORT(int) PyModule_AddObject(PyObject *, char *, PyObject *);
extern DL_IMPORT(int) PyModule_AddIntConstant(PyObject *, char *, long); extern DL_IMPORT(int) PyModule_AddIntConstant(PyObject *, char *, long);
extern DL_IMPORT(int) PyModule_AddStringConstant(PyObject *, char *, char *); extern DL_IMPORT(int) PyModule_AddStringConstant(PyObject *, char *, char *);
#define PYTHON_API_VERSION 1010 #define PYTHON_API_VERSION 1011
#define PYTHON_API_STRING "1010" #define PYTHON_API_STRING "1011"
/* The API version is maintained (independently from the Python version) /* The API version is maintained (independently from the Python version)
so we can detect mismatches between the interpreter and dynamically so we can detect mismatches between the interpreter and dynamically
loaded modules. These are diagnosed by an error message but loaded modules. These are diagnosed by an error message but
...@@ -37,6 +37,8 @@ extern DL_IMPORT(int) PyModule_AddStringConstant(PyObject *, char *, char *); ...@@ -37,6 +37,8 @@ extern DL_IMPORT(int) PyModule_AddStringConstant(PyObject *, char *, char *);
Please add a line or two to the top of this log for each API Please add a line or two to the top of this log for each API
version change: version change:
17-Jul-2001 GvR 1011 Descr-branch, just to be on the safe side
25-Jan-2001 FLD 1010 Parameters added to PyCode_New() and 25-Jan-2001 FLD 1010 Parameters added to PyCode_New() and
PyFrame_New(); Python 2.1a2 PyFrame_New(); Python 2.1a2
......
...@@ -202,6 +202,11 @@ typedef long (*hashfunc)(PyObject *); ...@@ -202,6 +202,11 @@ typedef long (*hashfunc)(PyObject *);
typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
typedef PyObject *(*getiterfunc) (PyObject *); typedef PyObject *(*getiterfunc) (PyObject *);
typedef PyObject *(*iternextfunc) (PyObject *); typedef PyObject *(*iternextfunc) (PyObject *);
typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *);
typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *);
typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
typedef PyObject *(*allocfunc)(struct _typeobject *, int);
typedef struct _typeobject { typedef struct _typeobject {
PyObject_VAR_HEAD PyObject_VAR_HEAD
...@@ -255,18 +260,48 @@ typedef struct _typeobject { ...@@ -255,18 +260,48 @@ typedef struct _typeobject {
getiterfunc tp_iter; getiterfunc tp_iter;
iternextfunc tp_iternext; iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct memberlist *tp_members;
struct getsetlist *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
long tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
destructor tp_free; /* Low-level free-memory routine */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_defined;
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
/* these must be last and never explicitly initialized */ /* these must be last and never explicitly initialized */
int tp_alloc; int tp_allocs;
int tp_free; int tp_frees;
int tp_maxalloc; int tp_maxalloc;
struct _typeobject *tp_next; struct _typeobject *tp_next;
#endif #endif
} PyTypeObject; } PyTypeObject;
extern DL_IMPORT(PyTypeObject) PyType_Type; /* The type of type objects */
#define PyType_Check(op) ((op)->ob_type == &PyType_Type) /* Generic type check */
extern DL_IMPORT(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *);
#define PyObject_TypeCheck(ob, tp) \
((ob)->ob_type == (tp) || PyType_IsSubtype((ob)->ob_type, (tp)))
extern DL_IMPORT(PyTypeObject) PyType_Type; /* Metatype */
extern DL_IMPORT(PyTypeObject) PyBaseObject_Type; /* Most base object type */
#define PyType_Check(op) PyObject_TypeCheck(op, &PyType_Type)
extern DL_IMPORT(int) PyType_InitDict(PyTypeObject *);
extern DL_IMPORT(PyObject *) PyType_GenericAlloc(PyTypeObject *, int);
extern DL_IMPORT(PyObject *) PyType_GenericNew(PyTypeObject *,
PyObject *, PyObject *);
extern DL_IMPORT(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
/* Generic operations on objects */ /* Generic operations on objects */
extern DL_IMPORT(int) PyObject_Print(PyObject *, FILE *, int); extern DL_IMPORT(int) PyObject_Print(PyObject *, FILE *, int);
...@@ -283,6 +318,10 @@ extern DL_IMPORT(int) PyObject_HasAttrString(PyObject *, char *); ...@@ -283,6 +318,10 @@ extern DL_IMPORT(int) PyObject_HasAttrString(PyObject *, char *);
extern DL_IMPORT(PyObject *) PyObject_GetAttr(PyObject *, PyObject *); extern DL_IMPORT(PyObject *) PyObject_GetAttr(PyObject *, PyObject *);
extern DL_IMPORT(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *); extern DL_IMPORT(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *);
extern DL_IMPORT(int) PyObject_HasAttr(PyObject *, PyObject *); extern DL_IMPORT(int) PyObject_HasAttr(PyObject *, PyObject *);
extern DL_IMPORT(PyObject **) _PyObject_GetDictPtr(PyObject *);
extern DL_IMPORT(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *);
extern DL_IMPORT(int) PyObject_GenericSetAttr(PyObject *,
PyObject *, PyObject *);
extern DL_IMPORT(long) PyObject_Hash(PyObject *); extern DL_IMPORT(long) PyObject_Hash(PyObject *);
extern DL_IMPORT(int) PyObject_IsTrue(PyObject *); extern DL_IMPORT(int) PyObject_IsTrue(PyObject *);
extern DL_IMPORT(int) PyObject_Not(PyObject *); extern DL_IMPORT(int) PyObject_Not(PyObject *);
...@@ -357,6 +396,18 @@ given type object has a specified feature. ...@@ -357,6 +396,18 @@ given type object has a specified feature.
/* tp_iter is defined */ /* tp_iter is defined */
#define Py_TPFLAGS_HAVE_ITER (1L<<7) #define Py_TPFLAGS_HAVE_ITER (1L<<7)
/* Experimental stuff for healing the type/class split */
#define Py_TPFLAGS_HAVE_CLASS (1L<<8)
/* Set if the type object is dynamically allocated */
#define Py_TPFLAGS_HEAPTYPE (1L<<9)
/* Set if the type allows subclassing */
#define Py_TPFLAGS_BASETYPE (1L<<10)
/* Set if the type's __dict__ may change */
#define Py_TPFLAGS_DYNAMICTYPE (1L<<11)
#define Py_TPFLAGS_DEFAULT ( \ #define Py_TPFLAGS_DEFAULT ( \
Py_TPFLAGS_HAVE_GETCHARBUFFER | \ Py_TPFLAGS_HAVE_GETCHARBUFFER | \
Py_TPFLAGS_HAVE_SEQUENCE_IN | \ Py_TPFLAGS_HAVE_SEQUENCE_IN | \
...@@ -364,6 +415,7 @@ given type object has a specified feature. ...@@ -364,6 +415,7 @@ given type object has a specified feature.
Py_TPFLAGS_HAVE_RICHCOMPARE | \ Py_TPFLAGS_HAVE_RICHCOMPARE | \
Py_TPFLAGS_HAVE_WEAKREFS | \ Py_TPFLAGS_HAVE_WEAKREFS | \
Py_TPFLAGS_HAVE_ITER | \ Py_TPFLAGS_HAVE_ITER | \
Py_TPFLAGS_HAVE_CLASS | \
0) 0)
#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0) #define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)
...@@ -412,8 +464,8 @@ extern DL_IMPORT(void) _Py_ResetReferences(void); ...@@ -412,8 +464,8 @@ extern DL_IMPORT(void) _Py_ResetReferences(void);
#ifndef Py_TRACE_REFS #ifndef Py_TRACE_REFS
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
#define _Py_Dealloc(op) ((op)->ob_type->tp_free++, (*(op)->ob_type->tp_dealloc)((PyObject *)(op))) #define _Py_Dealloc(op) ((op)->ob_type->tp_frees++, (*(op)->ob_type->tp_dealloc)((PyObject *)(op)))
#define _Py_ForgetReference(op) ((op)->ob_type->tp_free++) #define _Py_ForgetReference(op) ((op)->ob_type->tp_frees++)
#else /* !COUNT_ALLOCS */ #else /* !COUNT_ALLOCS */
#define _Py_Dealloc(op) (*(op)->ob_type->tp_dealloc)((PyObject *)(op)) #define _Py_Dealloc(op) (*(op)->ob_type->tp_dealloc)((PyObject *)(op))
#define _Py_ForgetReference(op) /*empty*/ #define _Py_ForgetReference(op) /*empty*/
......
...@@ -236,6 +236,12 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *); ...@@ -236,6 +236,12 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
#define PyObject_GC_Fini(op) #define PyObject_GC_Fini(op)
#define PyObject_AS_GC(op) (op) #define PyObject_AS_GC(op) (op)
#define PyObject_FROM_GC(op) (op) #define PyObject_FROM_GC(op) (op)
#define PyType_IS_GC(t) 0
#define PyObject_IS_GC(o) 0
#define PyObject_AS_GC(o) (o)
#define PyObject_FROM_GC(o) (o)
#define PyType_BASICSIZE(t) ((t)->tp_basicsize)
#define PyType_SET_BASICSIZE(t, s) ((t)->tp_basicsize = (s))
#else #else
...@@ -269,6 +275,13 @@ typedef struct _gc_head { ...@@ -269,6 +275,13 @@ typedef struct _gc_head {
/* Get the object given the PyGC_Head */ /* Get the object given the PyGC_Head */
#define PyObject_FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) #define PyObject_FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1))
/* Calculate tp_basicsize excluding PyGC_HEAD_SIZE if applicable */
#define PyType_BASICSIZE(t) (!PyType_IS_GC(t) ? (t)->tp_basicsize : \
(t)->tp_basicsize - PyGC_HEAD_SIZE)
#define PyType_SET_BASICSIZE(t, s) (!PyType_IS_GC(t) ? \
((t)->tp_basicsize = (s)) : \
((t)->tp_basicsize = (s) + PyGC_HEAD_SIZE))
extern DL_IMPORT(void) _PyGC_Dump(PyGC_Head *); extern DL_IMPORT(void) _PyGC_Dump(PyGC_Head *);
#endif /* WITH_CYCLE_GC */ #endif /* WITH_CYCLE_GC */
......
...@@ -23,13 +23,13 @@ ...@@ -23,13 +23,13 @@
#define PY_MINOR_VERSION 2 #define PY_MINOR_VERSION 2
#define PY_MICRO_VERSION 0 #define PY_MICRO_VERSION 0
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA
#define PY_RELEASE_SERIAL 0 #define PY_RELEASE_SERIAL 1
/* Version as a string */ /* Version as a string */
#define PY_VERSION "2.2a0" #define PY_VERSION "2.2a1"
/* Historic */ /* Historic */
#define PATCHLEVEL "2.2a0" #define PATCHLEVEL "2.2a1"
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
Use this for numeric comparisons, e.g. #if PY_VERSION_HEX >= ... */ Use this for numeric comparisons, e.g. #if PY_VERSION_HEX >= ... */
......
...@@ -92,10 +92,10 @@ DL_IMPORT(const char *) Py_GetBuildInfo(void); ...@@ -92,10 +92,10 @@ DL_IMPORT(const char *) Py_GetBuildInfo(void);
DL_IMPORT(PyObject *) _PyBuiltin_Init(void); DL_IMPORT(PyObject *) _PyBuiltin_Init(void);
DL_IMPORT(PyObject *) _PySys_Init(void); DL_IMPORT(PyObject *) _PySys_Init(void);
DL_IMPORT(void) _PyImport_Init(void); DL_IMPORT(void) _PyImport_Init(void);
DL_IMPORT(void) init_exceptions(void); DL_IMPORT(void) _PyExc_Init(void);
/* Various internal finalizers */ /* Various internal finalizers */
DL_IMPORT(void) fini_exceptions(void); DL_IMPORT(void) _PyExc_Fini(void);
DL_IMPORT(void) _PyImport_Fini(void); DL_IMPORT(void) _PyImport_Fini(void);
DL_IMPORT(void) PyMethod_Fini(void); DL_IMPORT(void) PyMethod_Fini(void);
DL_IMPORT(void) PyFrame_Fini(void); DL_IMPORT(void) PyFrame_Fini(void);
......
...@@ -504,6 +504,7 @@ class Pickler: ...@@ -504,6 +504,7 @@ class Pickler:
dispatch[ClassType] = save_global dispatch[ClassType] = save_global
dispatch[FunctionType] = save_global dispatch[FunctionType] = save_global
dispatch[BuiltinFunctionType] = save_global dispatch[BuiltinFunctionType] = save_global
dispatch[TypeType] = save_global
def _keep_alive(x, memo): def _keep_alive(x, memo):
......
...@@ -62,7 +62,7 @@ class Repr: ...@@ -62,7 +62,7 @@ class Repr:
s = s + ': ' + self.repr1(x[key], level-1) s = s + ': ' + self.repr1(x[key], level-1)
if n > self.maxdict: s = s + ', ...' if n > self.maxdict: s = s + ', ...'
return '{' + s + '}' return '{' + s + '}'
def repr_string(self, x, level): def repr_str(self, x, level):
s = `x[:self.maxstring]` s = `x[:self.maxstring]`
if len(s) > self.maxstring: if len(s) > self.maxstring:
i = max(0, (self.maxstring-3)/2) i = max(0, (self.maxstring-3)/2)
...@@ -70,7 +70,7 @@ class Repr: ...@@ -70,7 +70,7 @@ class Repr:
s = `x[:i] + x[len(x)-j:]` s = `x[:i] + x[len(x)-j:]`
s = s[:i] + '...' + s[len(s)-j:] s = s[:i] + '...' + s[len(s)-j:]
return s return s
def repr_long_int(self, x, level): def repr_long(self, x, level):
s = `x` # XXX Hope this isn't too slow... s = `x` # XXX Hope this isn't too slow...
if len(s) > self.maxlong: if len(s) > self.maxlong:
i = max(0, (self.maxlong-3)/2) i = max(0, (self.maxlong-3)/2)
......
This diff is collapsed.
...@@ -380,10 +380,16 @@ From the Iterators list, about the types of these things. ...@@ -380,10 +380,16 @@ From the Iterators list, about the types of these things.
>>> i = g() >>> i = g()
>>> type(i) >>> type(i)
<type 'generator'> <type 'generator'>
XXX dir(object) *generally* doesn't return useful stuff in descr-branch.
>>> dir(i) >>> dir(i)
[]
Was hoping to see this instead:
['gi_frame', 'gi_running', 'next'] ['gi_frame', 'gi_running', 'next']
>>> print i.next.__doc__ >>> print i.next.__doc__
next() -- get the next value, or raise StopIteration x.next() -> the next value, or raise StopIteration
>>> iter(i) is i >>> iter(i) is i
1 1
>>> import types >>> import types
...@@ -399,7 +405,7 @@ And more, added later. ...@@ -399,7 +405,7 @@ And more, added later.
>>> i.gi_running = 42 >>> i.gi_running = 42
Traceback (most recent call last): Traceback (most recent call last):
... ...
TypeError: object has read-only attributes TypeError: 'generator' object has only read-only attributes (assign to .gi_running)
>>> def g(): >>> def g():
... yield me.gi_running ... yield me.gi_running
>>> me = g() >>> me = g()
......
...@@ -7,7 +7,8 @@ from __future__ import generators ...@@ -7,7 +7,8 @@ from __future__ import generators
import sys import sys
NoneType = type(None) NoneType = type(None)
TypeType = type(NoneType) TypeType = type
ObjectType = object
IntType = type(0) IntType = type(0)
LongType = type(0L) LongType = type(0L)
...@@ -22,8 +23,8 @@ UnicodeType = type(u'') ...@@ -22,8 +23,8 @@ UnicodeType = type(u'')
BufferType = type(buffer('')) BufferType = type(buffer(''))
TupleType = type(()) TupleType = type(())
ListType = type([]) ListType = list
DictType = DictionaryType = type({}) DictType = DictionaryType = dictionary
def _f(): pass def _f(): pass
FunctionType = type(_f) FunctionType = type(_f)
...@@ -71,4 +72,9 @@ except TypeError: ...@@ -71,4 +72,9 @@ except TypeError:
SliceType = type(slice(0)) SliceType = type(slice(0))
EllipsisType = type(Ellipsis) EllipsisType = type(Ellipsis)
DictIterType = type(iter({}))
SequenceIterType = type(iter([]))
FunctionIterType = type(iter(lambda: 0, 0))
DictProxyType = type(TypeType.__dict__)
del sys, _f, _C, _x # Not for export del sys, _f, _C, _x # Not for export
...@@ -237,6 +237,7 @@ OBJECT_OBJS= \ ...@@ -237,6 +237,7 @@ OBJECT_OBJS= \
Objects/classobject.o \ Objects/classobject.o \
Objects/cobject.o \ Objects/cobject.o \
Objects/complexobject.o \ Objects/complexobject.o \
Objects/descrobject.o \
Objects/fileobject.o \ Objects/fileobject.o \
Objects/floatobject.o \ Objects/floatobject.o \
Objects/frameobject.o \ Objects/frameobject.o \
...@@ -438,6 +439,7 @@ PYTHON_HEADERS= \ ...@@ -438,6 +439,7 @@ PYTHON_HEADERS= \
Include/tupleobject.h \ Include/tupleobject.h \
Include/listobject.h \ Include/listobject.h \
Include/iterobject.h \ Include/iterobject.h \
Include/descrobject.h \
Include/dictobject.h \ Include/dictobject.h \
Include/methodobject.h \ Include/methodobject.h \
Include/moduleobject.h \ Include/moduleobject.h \
......
...@@ -44,6 +44,17 @@ What's New in Python 2.2a1? ...@@ -44,6 +44,17 @@ What's New in Python 2.2a1?
Core Core
- TENTATIVELY, a large amount of code implementing much of what's
described in PEP 252 (Making Types Look More Like Classes) and PEP
253 (Subtyping Built-in Types) was added. This will be released
with Python 2.2a1. Documentation will be provided separately
through http://www.python.org/2.2/. The purpose of releasing this
with Python 2.2a1 is to test backwards compatibility. It is
possible, though not likely, that a decision is made not to release
this code as part of 2.2 final, if any serious backwards
incompapatibilities are found during alpha testing that cannot be
repaired.
- Generators were added; this is a new way to create an iterator (see - Generators were added; this is a new way to create an iterator (see
below) using what looks like a simple function containing one or below) using what looks like a simple function containing one or
more 'yield' statements. See PEP 255. Since this adds a new more 'yield' statements. See PEP 255. Since this adds a new
......
...@@ -464,3 +464,5 @@ GLHACK=-Dclear=__GLclear ...@@ -464,3 +464,5 @@ GLHACK=-Dclear=__GLclear
# Example -- included for reference only: # Example -- included for reference only:
# xx xxmodule.c # xx xxmodule.c
# Another example -- the 'xxsubtype' module shows C-level subtyping in action
xxsubtype xxsubtype.c
...@@ -1869,6 +1869,10 @@ save(Picklerobject *self, PyObject *args, int pers_save) { ...@@ -1869,6 +1869,10 @@ save(Picklerobject *self, PyObject *args, int pers_save) {
res = save_tuple(self, args); res = save_tuple(self, args);
goto finally; goto finally;
} }
if (type == &PyType_Type) {
res = save_global(self, args, NULL);
goto finally;
}
break; break;
case 'l': case 'l':
......
...@@ -37,7 +37,7 @@ struct _inittab _PyImport_Inittab[] = { ...@@ -37,7 +37,7 @@ struct _inittab _PyImport_Inittab[] = {
{"__main__", NULL}, {"__main__", NULL},
{"__builtin__", NULL}, {"__builtin__", NULL},
{"sys", NULL}, {"sys", NULL},
{"exceptions", init_exceptions}, {"exceptions", NULL},
/* Sentinel */ /* Sentinel */
{0, 0} {0, 0}
......
#include "Python.h"
/* Examples showing how to subtype the builtin list and dict types from C. */
/* spamlist -- a list subtype */
typedef struct {
PyListObject list;
int state;
} spamlistobject;
static PyObject *
spamlist_getstate(spamlistobject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":getstate"))
return NULL;
return PyInt_FromLong(self->state);
}
static PyObject *
spamlist_setstate(spamlistobject *self, PyObject *args)
{
int state;
if (!PyArg_ParseTuple(args, "i:setstate", &state))
return NULL;
self->state = state;
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef spamlist_methods[] = {
{"getstate", (PyCFunction)spamlist_getstate, METH_VARARGS,
"getstate() -> state"},
{"setstate", (PyCFunction)spamlist_setstate, METH_VARARGS,
"setstate(state)"},
{NULL, NULL},
};
staticforward PyTypeObject spamlist_type;
static int
spamlist_init(spamlistobject *self, PyObject *args, PyObject *kwds)
{
if (PyList_Type.tp_init((PyObject *)self, args, kwds) < 0)
return -1;
self->state = 0;
return 0;
}
static PyTypeObject spamlist_type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"spamlist",
sizeof(spamlistobject),
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
spamlist_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyList_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)spamlist_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
/* spamdict -- a dict subtype */
typedef struct {
PyDictObject dict;
int state;
} spamdictobject;
static PyObject *
spamdict_getstate(spamdictobject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ":getstate"))
return NULL;
return PyInt_FromLong(self->state);
}
static PyObject *
spamdict_setstate(spamdictobject *self, PyObject *args)
{
int state;
if (!PyArg_ParseTuple(args, "i:setstate", &state))
return NULL;
self->state = state;
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef spamdict_methods[] = {
{"getstate", (PyCFunction)spamdict_getstate, METH_VARARGS,
"getstate() -> state"},
{"setstate", (PyCFunction)spamdict_setstate, METH_VARARGS,
"setstate(state)"},
{NULL, NULL},
};
staticforward PyTypeObject spamdict_type;
static int
spamdict_init(spamdictobject *self, PyObject *args, PyObject *kwds)
{
if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
return -1;
self->state = 0;
return 0;
}
static PyTypeObject spamdict_type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"spamdict",
sizeof(spamdictobject),
0,
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
spamdict_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyDict_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)spamdict_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
PyObject *
spam_bench(PyObject *self, PyObject *args)
{
PyObject *obj, *name, *res;
int n = 1000;
time_t t0, t1;
if (!PyArg_ParseTuple(args, "OS|i", &obj, &name, &n))
return NULL;
t0 = clock();
while (--n >= 0) {
res = PyObject_GetAttr(obj, name);
if (res == NULL)
return NULL;
Py_DECREF(res);
}
t1 = clock();
return PyFloat_FromDouble((double)(t1-t0) / CLOCKS_PER_SEC);
}
static PyMethodDef xxsubtype_functions[] = {
{"bench", spam_bench, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
DL_EXPORT(void)
initxxsubtype(void)
{
PyObject *m, *d;
m = Py_InitModule("xxsubtype", xxsubtype_functions);
if (m == NULL)
return;
if (PyType_InitDict(&spamlist_type) < 0)
return;
if (PyType_InitDict(&spamdict_type) < 0)
return;
d = PyModule_GetDict(m);
if (d == NULL)
return;
Py_INCREF(&spamlist_type);
if (PyDict_SetItemString(d, "spamlist",
(PyObject *) &spamlist_type) < 0)
return;
Py_INCREF(&spamdict_type);
if (PyDict_SetItemString(d, "spamdict",
(PyObject *) &spamdict_type) < 0)
return;
}
...@@ -1588,6 +1588,24 @@ PyObject_CallObject(PyObject *o, PyObject *a) ...@@ -1588,6 +1588,24 @@ PyObject_CallObject(PyObject *o, PyObject *a)
return r; return r;
} }
PyObject *
PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
ternaryfunc call;
if ((call = func->ob_type->tp_call) != NULL) {
PyObject *result = (*call)(func, arg, kw);
if (result == NULL && !PyErr_Occurred())
PyErr_SetString(
PyExc_SystemError,
"NULL result without error in PyObject_Call");
return result;
}
PyErr_Format(PyExc_TypeError, "object is not callable: %s",
PyString_AS_STRING(PyObject_Repr(func)));
return NULL;
}
PyObject * PyObject *
PyObject_CallFunction(PyObject *callable, char *format, ...) PyObject_CallFunction(PyObject *callable, char *format, ...)
{ {
...@@ -1746,7 +1764,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) ...@@ -1746,7 +1764,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
} }
} }
else if (PyType_Check(cls)) { else if (PyType_Check(cls)) {
retval = ((PyObject *)(inst->ob_type) == cls); retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
} }
else if (!PyInstance_Check(inst)) { else if (!PyInstance_Check(inst)) {
if (__class__ == NULL) { if (__class__ == NULL) {
......
...@@ -537,21 +537,21 @@ PyTypeObject PyBuffer_Type = { ...@@ -537,21 +537,21 @@ PyTypeObject PyBuffer_Type = {
"buffer", "buffer",
sizeof(PyBufferObject), sizeof(PyBufferObject),
0, 0,
(destructor)buffer_dealloc, /*tp_dealloc*/ (destructor)buffer_dealloc, /* tp_dealloc */
0, /*tp_print*/ 0, /* tp_print */
0, /*tp_getattr*/ 0, /* tp_getattr */
0, /*tp_setattr*/ 0, /* tp_setattr */
(cmpfunc)buffer_compare, /*tp_compare*/ (cmpfunc)buffer_compare, /* tp_compare */
(reprfunc)buffer_repr, /*tp_repr*/ (reprfunc)buffer_repr, /* tp_repr */
0, /*tp_as_number*/ 0, /* tp_as_number */
&buffer_as_sequence, /*tp_as_sequence*/ &buffer_as_sequence, /* tp_as_sequence */
0, /*tp_as_mapping*/ 0, /* tp_as_mapping */
(hashfunc)buffer_hash, /*tp_hash*/ (hashfunc)buffer_hash, /* tp_hash */
0, /*tp_call*/ 0, /* tp_call */
(reprfunc)buffer_str, /*tp_str*/ (reprfunc)buffer_str, /* tp_str */
0, /*tp_getattro*/ PyObject_GenericGetAttr, /* tp_getattro */
0, /*tp_setattro*/ 0, /* tp_setattro */
&buffer_as_buffer, /*tp_as_buffer*/ &buffer_as_buffer, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /*tp_flags*/ Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /*tp_doc*/ 0, /* tp_doc */
}; };
...@@ -106,7 +106,7 @@ PyTypeObject PyCell_Type = { ...@@ -106,7 +106,7 @@ PyTypeObject PyCell_Type = {
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
......
This diff is collapsed.
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#ifndef WITHOUT_COMPLEX #ifndef WITHOUT_COMPLEX
#include "Python.h" #include "Python.h"
#include "structmember.h"
/* Precisions used by repr() and str(), respectively. /* Precisions used by repr() and str(), respectively.
...@@ -182,6 +183,17 @@ c_powi(Py_complex x, long n) ...@@ -182,6 +183,17 @@ c_powi(Py_complex x, long n)
} }
static PyObject *
complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval)
{
PyObject *op;
op = PyType_GenericAlloc(type, 0);
if (op != NULL)
((PyComplexObject *)op)->cval = cval;
return op;
}
PyObject * PyObject *
PyComplex_FromCComplex(Py_complex cval) PyComplex_FromCComplex(Py_complex cval)
{ {
...@@ -196,6 +208,15 @@ PyComplex_FromCComplex(Py_complex cval) ...@@ -196,6 +208,15 @@ PyComplex_FromCComplex(Py_complex cval)
return (PyObject *) op; return (PyObject *) op;
} }
static PyObject *
complex_subtype_from_doubles(PyTypeObject *type, double real, double imag)
{
Py_complex c;
c.real = real;
c.imag = imag;
return complex_subtype_from_c_complex(type, c);
}
PyObject * PyObject *
PyComplex_FromDoubles(double real, double imag) PyComplex_FromDoubles(double real, double imag)
{ {
...@@ -559,19 +580,261 @@ static PyMethodDef complex_methods[] = { ...@@ -559,19 +580,261 @@ static PyMethodDef complex_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static struct memberlist complex_members[] = {
{"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), 0},
{"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), 0},
{0},
};
static PyObject * static PyObject *
complex_getattr(PyComplexObject *self, char *name) complex_subtype_from_string(PyTypeObject *type, PyObject *v)
{ {
if (strcmp(name, "real") == 0) extern double strtod(const char *, char **);
return (PyObject *)PyFloat_FromDouble(self->cval.real); const char *s, *start;
else if (strcmp(name, "imag") == 0) char *end;
return (PyObject *)PyFloat_FromDouble(self->cval.imag); double x=0.0, y=0.0, z;
else if (strcmp(name, "__members__") == 0) int got_re=0, got_im=0, done=0;
return Py_BuildValue("[ss]", "imag", "real"); int digit_or_dot;
return Py_FindMethod(complex_methods, (PyObject *)self, name); int sw_error=0;
int sign;
char buffer[256]; /* For errors */
char s_buffer[256];
int len;
if (PyString_Check(v)) {
s = PyString_AS_STRING(v);
len = PyString_GET_SIZE(v);
}
else if (PyUnicode_Check(v)) {
if (PyUnicode_GET_SIZE(v) >= sizeof(s_buffer)) {
PyErr_SetString(PyExc_ValueError,
"complex() literal too large to convert");
return NULL;
}
if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
PyUnicode_GET_SIZE(v),
s_buffer,
NULL))
return NULL;
s = s_buffer;
len = (int)strlen(s);
}
else if (PyObject_AsCharBuffer(v, &s, &len)) {
PyErr_SetString(PyExc_TypeError,
"complex() arg is not a string");
return NULL;
}
/* position on first nonblank */
start = s;
while (*s && isspace(Py_CHARMASK(*s)))
s++;
if (s[0] == '\0') {
PyErr_SetString(PyExc_ValueError,
"complex() arg is an empty string");
return NULL;
}
z = -1.0;
sign = 1;
do {
switch (*s) {
case '\0':
if (s-start != len) {
PyErr_SetString(
PyExc_ValueError,
"complex() arg contains a null byte");
return NULL;
}
if(!done) sw_error=1;
break;
case '-':
sign = -1;
/* Fallthrough */
case '+':
if (done) sw_error=1;
s++;
if ( *s=='\0'||*s=='+'||*s=='-' ||
isspace(Py_CHARMASK(*s)) ) sw_error=1;
break;
case 'J':
case 'j':
if (got_im || done) {
sw_error = 1;
break;
}
if (z<0.0) {
y=sign;
}
else{
y=sign*z;
}
got_im=1;
s++;
if (*s!='+' && *s!='-' )
done=1;
break;
default:
if (isspace(Py_CHARMASK(*s))) {
while (*s && isspace(Py_CHARMASK(*s)))
s++;
if (s[0] != '\0')
sw_error=1;
else
done = 1;
break;
}
digit_or_dot =
(*s=='.' || isdigit(Py_CHARMASK(*s)));
if (done||!digit_or_dot) {
sw_error=1;
break;
}
errno = 0;
PyFPE_START_PROTECT("strtod", return 0)
z = strtod(s, &end) ;
PyFPE_END_PROTECT(z)
if (errno != 0) {
sprintf(buffer,
"float() out of range: %.150s", s);
PyErr_SetString(
PyExc_ValueError,
buffer);
return NULL;
}
s=end;
if (*s=='J' || *s=='j') {
break;
}
if (got_re) {
sw_error=1;
break;
}
/* accept a real part */
x=sign*z;
got_re=1;
if (got_im) done=1;
z = -1.0;
sign = 1;
break;
} /* end of switch */
} while (*s!='\0' && !sw_error);
if (sw_error) {
PyErr_SetString(PyExc_ValueError,
"complex() arg is a malformed string");
return NULL;
}
return complex_subtype_from_doubles(type, x, y);
}
static PyObject *
complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *r, *i, *tmp;
PyNumberMethods *nbr, *nbi = NULL;
Py_complex cr, ci;
int own_r = 0;
static char *kwlist[] = {"real", "imag", 0};
r = Py_False;
i = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist,
&r, &i))
return NULL;
if (PyString_Check(r) || PyUnicode_Check(r))
return complex_subtype_from_string(type, r);
if ((nbr = r->ob_type->tp_as_number) == NULL ||
nbr->nb_float == NULL ||
(i != NULL &&
((nbi = i->ob_type->tp_as_number) == NULL ||
nbi->nb_float == NULL))) {
PyErr_SetString(PyExc_TypeError,
"complex() arg can't be converted to complex");
return NULL;
}
/* XXX Hack to support classes with __complex__ method */
if (PyInstance_Check(r)) {
static PyObject *complexstr;
PyObject *f;
if (complexstr == NULL) {
complexstr = PyString_InternFromString("__complex__");
if (complexstr == NULL)
return NULL;
}
f = PyObject_GetAttr(r, complexstr);
if (f == NULL)
PyErr_Clear();
else {
PyObject *args = Py_BuildValue("()");
if (args == NULL)
return NULL;
r = PyEval_CallObject(f, args);
Py_DECREF(args);
Py_DECREF(f);
if (r == NULL)
return NULL;
own_r = 1;
}
}
if (PyComplex_Check(r)) {
cr = ((PyComplexObject*)r)->cval;
if (own_r) {
Py_DECREF(r);
}
}
else {
tmp = PyNumber_Float(r);
if (own_r) {
Py_DECREF(r);
}
if (tmp == NULL)
return NULL;
if (!PyFloat_Check(tmp)) {
PyErr_SetString(PyExc_TypeError,
"float(r) didn't return a float");
Py_DECREF(tmp);
return NULL;
}
cr.real = PyFloat_AsDouble(tmp);
Py_DECREF(tmp);
cr.imag = 0.0;
}
if (i == NULL) {
ci.real = 0.0;
ci.imag = 0.0;
}
else if (PyComplex_Check(i))
ci = ((PyComplexObject*)i)->cval;
else {
tmp = (*nbi->nb_float)(i);
if (tmp == NULL)
return NULL;
ci.real = PyFloat_AsDouble(tmp);
Py_DECREF(tmp);
ci.imag = 0.;
}
cr.real -= ci.imag;
cr.imag += ci.real;
return complex_subtype_from_c_complex(type, cr);
} }
static char complex_doc[] =
"complex(real[, imag]) -> complex number\n\
\n\
Create a complex number from a real part and an optional imaginary part.\n\
This is equivalent to (real + imag*1j) where imag defaults to 0.";
static PyNumberMethods complex_as_number = { static PyNumberMethods complex_as_number = {
(binaryfunc)complex_add, /* nb_add */ (binaryfunc)complex_add, /* nb_add */
(binaryfunc)complex_sub, /* nb_subtract */ (binaryfunc)complex_sub, /* nb_subtract */
...@@ -606,7 +869,7 @@ PyTypeObject PyComplex_Type = { ...@@ -606,7 +869,7 @@ PyTypeObject PyComplex_Type = {
0, 0,
(destructor)complex_dealloc, /* tp_dealloc */ (destructor)complex_dealloc, /* tp_dealloc */
(printfunc)complex_print, /* tp_print */ (printfunc)complex_print, /* tp_print */
(getattrfunc)complex_getattr, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
(reprfunc)complex_repr, /* tp_repr */ (reprfunc)complex_repr, /* tp_repr */
...@@ -616,14 +879,28 @@ PyTypeObject PyComplex_Type = { ...@@ -616,14 +879,28 @@ PyTypeObject PyComplex_Type = {
(hashfunc)complex_hash, /* tp_hash */ (hashfunc)complex_hash, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
(reprfunc)complex_str, /* tp_str */ (reprfunc)complex_str, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */ complex_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
complex_richcompare, /* tp_richcompare */ complex_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
complex_methods, /* tp_methods */
complex_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
complex_new, /* tp_new */
}; };
#endif #endif
This diff is collapsed.
This diff is collapsed.
...@@ -1273,29 +1273,15 @@ static struct memberlist file_memberlist[] = { ...@@ -1273,29 +1273,15 @@ static struct memberlist file_memberlist[] = {
}; };
static PyObject * static PyObject *
file_getattr(PyFileObject *f, char *name) get_closed(PyFileObject *f, void *closure)
{ {
PyObject *res;
res = Py_FindMethod(file_methods, (PyObject *)f, name);
if (res != NULL)
return res;
PyErr_Clear();
if (strcmp(name, "closed") == 0)
return PyInt_FromLong((long)(f->f_fp == 0)); return PyInt_FromLong((long)(f->f_fp == 0));
return PyMember_Get((char *)f, file_memberlist, name);
} }
static int static struct getsetlist file_getsetlist[] = {
file_setattr(PyFileObject *f, char *name, PyObject *v) {"closed", (getter)get_closed, NULL, NULL},
{ {0},
if (v == NULL) { };
PyErr_SetString(PyExc_AttributeError,
"can't delete file attributes");
return -1;
}
return PyMember_Set((char *)f, file_memberlist, name, v);
}
static PyObject * static PyObject *
file_getiter(PyObject *f) file_getiter(PyObject *f)
...@@ -1311,8 +1297,8 @@ PyTypeObject PyFile_Type = { ...@@ -1311,8 +1297,8 @@ PyTypeObject PyFile_Type = {
0, 0,
(destructor)file_dealloc, /* tp_dealloc */ (destructor)file_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
(getattrfunc)file_getattr, /* tp_getattr */ 0, /* tp_getattr */
(setattrfunc)file_setattr, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
(reprfunc)file_repr, /* tp_repr */ (reprfunc)file_repr, /* tp_repr */
0, /* tp_as_number */ 0, /* tp_as_number */
...@@ -1321,7 +1307,7 @@ PyTypeObject PyFile_Type = { ...@@ -1321,7 +1307,7 @@ PyTypeObject PyFile_Type = {
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */ Py_TPFLAGS_DEFAULT, /* tp_flags */
...@@ -1332,6 +1318,11 @@ PyTypeObject PyFile_Type = { ...@@ -1332,6 +1318,11 @@ PyTypeObject PyFile_Type = {
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
file_getiter, /* tp_iter */ file_getiter, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
file_methods, /* tp_methods */
file_memberlist, /* tp_members */
file_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
}; };
/* Interface for the 'soft space' between print items. */ /* Interface for the 'soft space' between print items. */
......
...@@ -636,6 +636,26 @@ float_float(PyObject *v) ...@@ -636,6 +636,26 @@ float_float(PyObject *v)
} }
static PyObject *
float_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *x = Py_False; /* Integer zero */
static char *kwlist[] = {"x", 0};
assert(type == &PyFloat_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x))
return NULL;
if (PyString_Check(x))
return PyFloat_FromString(x, NULL);
return PyNumber_Float(x);
}
static char float_doc[] =
"float(x) -> floating point number\n\
\n\
Convert a string or number to a floating point number, if possible.";
static PyNumberMethods float_as_number = { static PyNumberMethods float_as_number = {
(binaryfunc)float_add, /*nb_add*/ (binaryfunc)float_add, /*nb_add*/
(binaryfunc)float_sub, /*nb_subtract*/ (binaryfunc)float_sub, /*nb_subtract*/
...@@ -679,22 +699,40 @@ PyTypeObject PyFloat_Type = { ...@@ -679,22 +699,40 @@ PyTypeObject PyFloat_Type = {
"float", "float",
sizeof(PyFloatObject), sizeof(PyFloatObject),
0, 0,
(destructor)float_dealloc, /*tp_dealloc*/ (destructor)float_dealloc, /* tp_dealloc */
(printfunc)float_print, /*tp_print*/ (printfunc)float_print, /* tp_print */
0, /*tp_getattr*/ 0, /* tp_getattr */
0, /*tp_setattr*/ 0, /* tp_setattr */
(cmpfunc)float_compare, /*tp_compare*/ (cmpfunc)float_compare, /* tp_compare */
(reprfunc)float_repr, /*tp_repr*/ (reprfunc)float_repr, /* tp_repr */
&float_as_number, /*tp_as_number*/ &float_as_number, /* tp_as_number */
0, /*tp_as_sequence*/ 0, /* tp_as_sequence */
0, /*tp_as_mapping*/ 0, /* tp_as_mapping */
(hashfunc)float_hash, /*tp_hash*/ (hashfunc)float_hash, /* tp_hash */
0, /*tp_call*/ 0, /* tp_call */
(reprfunc)float_str, /*tp_str*/ (reprfunc)float_str, /* tp_str */
0, /*tp_getattro*/ PyObject_GenericGetAttr, /* tp_getattro */
0, /*tp_setattro*/ 0, /* tp_setattro */
0, /*tp_as_buffer*/ 0, /* tp_as_buffer */
Py_TPFLAGS_CHECKTYPES /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
float_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
float_new, /* tp_new */
}; };
void void
......
...@@ -15,7 +15,6 @@ static struct memberlist frame_memberlist[] = { ...@@ -15,7 +15,6 @@ static struct memberlist frame_memberlist[] = {
{"f_code", T_OBJECT, OFF(f_code), RO}, {"f_code", T_OBJECT, OFF(f_code), RO},
{"f_builtins", T_OBJECT, OFF(f_builtins),RO}, {"f_builtins", T_OBJECT, OFF(f_builtins),RO},
{"f_globals", T_OBJECT, OFF(f_globals), RO}, {"f_globals", T_OBJECT, OFF(f_globals), RO},
{"f_locals", T_OBJECT, OFF(f_locals), RO},
{"f_lasti", T_INT, OFF(f_lasti), RO}, {"f_lasti", T_INT, OFF(f_lasti), RO},
{"f_lineno", T_INT, OFF(f_lineno), RO}, {"f_lineno", T_INT, OFF(f_lineno), RO},
{"f_restricted",T_INT, OFF(f_restricted),RO}, {"f_restricted",T_INT, OFF(f_restricted),RO},
...@@ -27,18 +26,17 @@ static struct memberlist frame_memberlist[] = { ...@@ -27,18 +26,17 @@ static struct memberlist frame_memberlist[] = {
}; };
static PyObject * static PyObject *
frame_getattr(PyFrameObject *f, char *name) frame_getlocals(PyFrameObject *f, void *closure)
{ {
if (strcmp(name, "f_locals") == 0)
PyFrame_FastToLocals(f); PyFrame_FastToLocals(f);
return PyMember_Get((char *)f, frame_memberlist, name); Py_INCREF(f->f_locals);
return f->f_locals;
} }
static int static struct getsetlist frame_getsetlist[] = {
frame_setattr(PyFrameObject *f, char *name, PyObject *value) {"f_locals", (getter)frame_getlocals, NULL, NULL},
{ {0}
return PyMember_Set((char *)f, frame_memberlist, name, value); };
}
/* Stack frames are allocated and deallocated at a considerable rate. /* Stack frames are allocated and deallocated at a considerable rate.
In an attempt to improve the speed of function calls, we maintain a In an attempt to improve the speed of function calls, we maintain a
...@@ -177,8 +175,8 @@ PyTypeObject PyFrame_Type = { ...@@ -177,8 +175,8 @@ PyTypeObject PyFrame_Type = {
0, 0,
(destructor)frame_dealloc, /* tp_dealloc */ (destructor)frame_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
(getattrfunc)frame_getattr, /* tp_getattr */ 0, /* tp_getattr */
(setattrfunc)frame_setattr, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
0, /* tp_repr */ 0, /* tp_repr */
0, /* tp_as_number */ 0, /* tp_as_number */
...@@ -187,13 +185,22 @@ PyTypeObject PyFrame_Type = { ...@@ -187,13 +185,22 @@ PyTypeObject PyFrame_Type = {
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
(traverseproc)frame_traverse, /* tp_traverse */ (traverseproc)frame_traverse, /* tp_traverse */
(inquiry)frame_clear, /* tp_clear */ (inquiry)frame_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
frame_memberlist, /* tp_members */
frame_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
}; };
PyFrameObject * PyFrameObject *
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "Python.h" #include "Python.h"
#include "compile.h" #include "compile.h"
#include "eval.h"
#include "structmember.h" #include "structmember.h"
PyObject * PyObject *
...@@ -141,9 +142,8 @@ static struct memberlist func_memberlist[] = { ...@@ -141,9 +142,8 @@ static struct memberlist func_memberlist[] = {
}; };
static PyObject * static PyObject *
func_getattro(PyFunctionObject *op, PyObject *name) func_getattro(PyObject *op, PyObject *name)
{ {
PyObject *rtn;
char *sname = PyString_AsString(name); char *sname = PyString_AsString(name);
if (sname[0] != '_' && PyEval_GetRestricted()) { if (sname[0] != '_' && PyEval_GetRestricted()) {
...@@ -152,25 +152,12 @@ func_getattro(PyFunctionObject *op, PyObject *name) ...@@ -152,25 +152,12 @@ func_getattro(PyFunctionObject *op, PyObject *name)
return NULL; return NULL;
} }
/* no API for PyMember_HasAttr() */ return PyObject_GenericGetAttr(op, name);
rtn = PyMember_Get((char *)op, func_memberlist, sname);
if (rtn == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
if (op->func_dict != NULL) {
rtn = PyDict_GetItem(op->func_dict, name);
Py_XINCREF(rtn);
}
if (rtn == NULL)
PyErr_SetObject(PyExc_AttributeError, name);
}
return rtn;
} }
static int static int
func_setattro(PyFunctionObject *op, PyObject *name, PyObject *value) func_setattro(PyObject *op, PyObject *name, PyObject *value)
{ {
int rtn;
char *sname = PyString_AsString(name); char *sname = PyString_AsString(name);
if (PyEval_GetRestricted()) { if (PyEval_GetRestricted()) {
...@@ -216,31 +203,7 @@ func_setattro(PyFunctionObject *op, PyObject *name, PyObject *value) ...@@ -216,31 +203,7 @@ func_setattro(PyFunctionObject *op, PyObject *name, PyObject *value)
} }
} }
rtn = PyMember_Set((char *)op, func_memberlist, sname, value); return PyObject_GenericSetAttr(op, name, value);
if (rtn < 0 && PyErr_ExceptionMatches(PyExc_AttributeError)) {
PyErr_Clear();
if (op->func_dict == NULL) {
/* don't create the dict if we're deleting an
* attribute. In that case, we know we'll get an
* AttributeError.
*/
if (value == NULL) {
PyErr_SetString(PyExc_AttributeError, sname);
return -1;
}
op->func_dict = PyDict_New();
if (op->func_dict == NULL)
return -1;
}
if (value == NULL)
rtn = PyDict_DelItem(op->func_dict, name);
else
rtn = PyDict_SetItem(op->func_dict, name, value);
/* transform KeyError into AttributeError */
if (rtn < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
PyErr_SetString(PyExc_AttributeError, sname);
}
return rtn;
} }
static void static void
...@@ -314,6 +277,66 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg) ...@@ -314,6 +277,66 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
return 0; return 0;
} }
static PyObject *
function_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyObject *result;
PyObject *argdefs;
PyObject **d, **k;
int nk, nd;
argdefs = PyFunction_GET_DEFAULTS(func);
if (argdefs != NULL && PyTuple_Check(argdefs)) {
d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0);
nd = PyTuple_Size(argdefs);
}
else {
d = NULL;
nd = 0;
}
if (kw != NULL && PyDict_Check(kw)) {
int pos, i;
nk = PyDict_Size(kw);
k = PyMem_NEW(PyObject *, 2*nk);
if (k == NULL) {
PyErr_NoMemory();
Py_DECREF(arg);
return NULL;
}
pos = i = 0;
while (PyDict_Next(kw, &pos, &k[i], &k[i+1]))
i += 2;
nk = i/2;
/* XXX This is broken if the caller deletes dict items! */
}
else {
k = NULL;
nk = 0;
}
result = PyEval_EvalCodeEx(
(PyCodeObject *)PyFunction_GET_CODE(func),
PyFunction_GET_GLOBALS(func), (PyObject *)NULL,
&PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg),
k, nk, d, nd,
PyFunction_GET_CLOSURE(func));
if (k != NULL)
PyMem_DEL(k);
return result;
}
/* Bind a function to an object */
static PyObject *
func_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
if (obj == Py_None)
obj = NULL;
return PyMethod_New(func, obj, type);
}
PyTypeObject PyFunction_Type = { PyTypeObject PyFunction_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
0, 0,
...@@ -330,10 +353,10 @@ PyTypeObject PyFunction_Type = { ...@@ -330,10 +353,10 @@ PyTypeObject PyFunction_Type = {
0, /* tp_as_sequence */ 0, /* tp_as_sequence */
0, /* tp_as_mapping */ 0, /* tp_as_mapping */
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ function_call, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
(getattrofunc)func_getattro, /* tp_getattro */ func_getattro, /* tp_getattro */
(setattrofunc)func_setattro, /* tp_setattro */ func_setattro, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
...@@ -341,4 +364,237 @@ PyTypeObject PyFunction_Type = { ...@@ -341,4 +364,237 @@ PyTypeObject PyFunction_Type = {
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */ offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
func_memberlist, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
func_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
};
/* Class method object */
/* A class method receives the class as implicit first argument,
just like an instance method receives the instance.
To declare a class method, use this idiom:
class C:
def f(cls, arg1, arg2, ...): ...
f = classmethod(f)
It can be called either on the class (e.g. C.f()) or on an instance
(e.g. C().f()); the instance is ignored except for its class.
If a class method is called for a derived class, the derived class
object is passed as the implied first argument.
Class methods are different than C++ or Java static methods.
If you want those, see static methods below.
*/
typedef struct {
PyObject_HEAD
PyObject *cm_callable;
} classmethod;
static void
cm_dealloc(classmethod *cm)
{
Py_XDECREF(cm->cm_callable);
PyObject_DEL(cm);
}
static PyObject *
cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{
classmethod *cm = (classmethod *)self;
if (cm->cm_callable == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"uninitialized classmethod object");
return NULL;
}
return PyMethod_New(cm->cm_callable,
type, (PyObject *)(type->ob_type));
}
static int
cm_init(PyObject *self, PyObject *args, PyObject *kwds)
{
classmethod *cm = (classmethod *)self;
PyObject *callable;
if (!PyArg_ParseTuple(args, "O:callable", &callable))
return -1;
Py_INCREF(callable);
cm->cm_callable = callable;
return 0;
}
PyTypeObject PyClassMethod_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"classmethod",
sizeof(classmethod),
0,
(destructor)cm_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
cm_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
cm_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
};
PyObject *
PyClassMethod_New(PyObject *callable)
{
classmethod *cm = (classmethod *)
PyType_GenericAlloc(&PyClassMethod_Type, 0);
if (cm != NULL) {
Py_INCREF(callable);
cm->cm_callable = callable;
}
return (PyObject *)cm;
}
/* Static method object */
/* A static method does not receive an implicit first argument.
To declare a static method, use this idiom:
class C:
def f(arg1, arg2, ...): ...
f = staticmethod(f)
It can be called either on the class (e.g. C.f()) or on an instance
(e.g. C().f()); the instance is ignored except for its class.
Static methods in Python are similar to those found in Java or C++.
For a more advanced concept, see class methods above.
*/
typedef struct {
PyObject_HEAD
PyObject *sm_callable;
} staticmethod;
static void
sm_dealloc(staticmethod *sm)
{
Py_XDECREF(sm->sm_callable);
PyObject_DEL(sm);
}
static PyObject *
sm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{
staticmethod *sm = (staticmethod *)self;
if (sm->sm_callable == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"uninitialized staticmethod object");
return NULL;
}
Py_INCREF(sm->sm_callable);
return sm->sm_callable;
}
static int
sm_init(PyObject *self, PyObject *args, PyObject *kwds)
{
staticmethod *sm = (staticmethod *)self;
PyObject *callable;
if (!PyArg_ParseTuple(args, "O:callable", &callable))
return -1;
Py_INCREF(callable);
sm->sm_callable = callable;
return 0;
}
PyTypeObject PyStaticMethod_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"staticmethod",
sizeof(staticmethod),
0,
(destructor)sm_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
sm_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
sm_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
}; };
PyObject *
PyStaticMethod_New(PyObject *callable)
{
staticmethod *sm = (staticmethod *)
PyType_GenericAlloc(&PyStaticMethod_Type, 0);
if (sm != NULL) {
Py_INCREF(callable);
sm->sm_callable = callable;
}
return (PyObject *)sm;
}
...@@ -742,6 +742,41 @@ int_hex(PyIntObject *v) ...@@ -742,6 +742,41 @@ int_hex(PyIntObject *v)
return PyString_FromString(buf); return PyString_FromString(buf);
} }
static PyObject *
int_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *x = NULL;
int base = -909;
static char *kwlist[] = {"x", "base", 0};
assert(type == &PyInt_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist,
&x, &base))
return NULL;
if (x == NULL)
return PyInt_FromLong(0L);
if (base == -909)
return PyNumber_Int(x);
if (PyString_Check(x))
return PyInt_FromString(PyString_AS_STRING(x), NULL, base);
if (PyUnicode_Check(x))
return PyInt_FromUnicode(PyUnicode_AS_UNICODE(x),
PyUnicode_GET_SIZE(x),
base);
PyErr_SetString(PyExc_TypeError,
"int() can't convert non-string with explicit base");
return NULL;
}
static char int_doc[] =
"int(x[, base]) -> integer\n\
\n\
Convert a string or number to an integer, if possible. A floating point\n\
argument will be truncated towards zero (this does not include a string\n\
representation of a floating point number!) When converting a string, use\n\
the optional base. It is an error to supply a base when converting a\n\
non-string.";
static PyNumberMethods int_as_number = { static PyNumberMethods int_as_number = {
(binaryfunc)int_add, /*nb_add*/ (binaryfunc)int_add, /*nb_add*/
(binaryfunc)int_sub, /*nb_subtract*/ (binaryfunc)int_sub, /*nb_subtract*/
...@@ -785,22 +820,40 @@ PyTypeObject PyInt_Type = { ...@@ -785,22 +820,40 @@ PyTypeObject PyInt_Type = {
"int", "int",
sizeof(PyIntObject), sizeof(PyIntObject),
0, 0,
(destructor)int_dealloc, /*tp_dealloc*/ (destructor)int_dealloc, /* tp_dealloc */
(printfunc)int_print, /*tp_print*/ (printfunc)int_print, /* tp_print */
0, /*tp_getattr*/ 0, /* tp_getattr */
0, /*tp_setattr*/ 0, /* tp_setattr */
(cmpfunc)int_compare, /*tp_compare*/ (cmpfunc)int_compare, /* tp_compare */
(reprfunc)int_repr, /*tp_repr*/ (reprfunc)int_repr, /* tp_repr */
&int_as_number, /*tp_as_number*/ &int_as_number, /* tp_as_number */
0, /*tp_as_sequence*/ 0, /* tp_as_sequence */
0, /*tp_as_mapping*/ 0, /* tp_as_mapping */
(hashfunc)int_hash, /*tp_hash*/ (hashfunc)int_hash, /* tp_hash */
0, /*tp_call*/ 0, /* tp_call */
0, /*tp_str*/ 0, /* tp_str */
0, /*tp_getattro*/ PyObject_GenericGetAttr, /* tp_getattro */
0, /*tp_setattro*/ 0, /* tp_setattro */
0, /*tp_as_buffer*/ 0, /* tp_as_buffer */
Py_TPFLAGS_CHECKTYPES /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
int_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
int_new, /* tp_new */
}; };
void void
......
...@@ -96,12 +96,6 @@ static PyMethodDef iter_methods[] = { ...@@ -96,12 +96,6 @@ static PyMethodDef iter_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyObject *
iter_getattr(seqiterobject *it, char *name)
{
return Py_FindMethod(iter_methods, (PyObject *)it, name);
}
PyTypeObject PySeqIter_Type = { PyTypeObject PySeqIter_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */ 0, /* ob_size */
...@@ -111,7 +105,7 @@ PyTypeObject PySeqIter_Type = { ...@@ -111,7 +105,7 @@ PyTypeObject PySeqIter_Type = {
/* methods */ /* methods */
(destructor)iter_dealloc, /* tp_dealloc */ (destructor)iter_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
(getattrfunc)iter_getattr, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
0, /* tp_repr */ 0, /* tp_repr */
...@@ -121,7 +115,7 @@ PyTypeObject PySeqIter_Type = { ...@@ -121,7 +115,7 @@ PyTypeObject PySeqIter_Type = {
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
...@@ -132,6 +126,13 @@ PyTypeObject PySeqIter_Type = { ...@@ -132,6 +126,13 @@ PyTypeObject PySeqIter_Type = {
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
(getiterfunc)iter_getiter, /* tp_iter */ (getiterfunc)iter_getiter, /* tp_iter */
(iternextfunc)iter_iternext, /* tp_iternext */ (iternextfunc)iter_iternext, /* tp_iternext */
iter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
}; };
/* -------------------------------------- */ /* -------------------------------------- */
...@@ -197,12 +198,6 @@ static PyMethodDef calliter_methods[] = { ...@@ -197,12 +198,6 @@ static PyMethodDef calliter_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyObject *
calliter_getattr(calliterobject *it, char *name)
{
return Py_FindMethod(calliter_methods, (PyObject *)it, name);
}
static PyObject * static PyObject *
calliter_iternext(calliterobject *it) calliter_iternext(calliterobject *it)
{ {
...@@ -228,7 +223,7 @@ PyTypeObject PyCallIter_Type = { ...@@ -228,7 +223,7 @@ PyTypeObject PyCallIter_Type = {
/* methods */ /* methods */
(destructor)calliter_dealloc, /* tp_dealloc */ (destructor)calliter_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
(getattrfunc)calliter_getattr, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
0, /* tp_repr */ 0, /* tp_repr */
...@@ -238,7 +233,7 @@ PyTypeObject PyCallIter_Type = { ...@@ -238,7 +233,7 @@ PyTypeObject PyCallIter_Type = {
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
...@@ -249,4 +244,11 @@ PyTypeObject PyCallIter_Type = { ...@@ -249,4 +244,11 @@ PyTypeObject PyCallIter_Type = {
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
(getiterfunc)iter_getiter, /* tp_iter */ (getiterfunc)iter_getiter, /* tp_iter */
(iternextfunc)calliter_iternext, /* tp_iternext */ (iternextfunc)calliter_iternext, /* tp_iternext */
calliter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
}; };
...@@ -523,6 +523,10 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -523,6 +523,10 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
Py_XDECREF(*p); Py_XDECREF(*p);
PyMem_DEL(recycle); PyMem_DEL(recycle);
} }
if (a->ob_size == 0 && a->ob_item != NULL) {
PyMem_FREE(a->ob_item);
a->ob_item = NULL;
}
return 0; return 0;
#undef b #undef b
} }
...@@ -1289,16 +1293,18 @@ listsort(PyListObject *self, PyObject *args) ...@@ -1289,16 +1293,18 @@ listsort(PyListObject *self, PyObject *args)
{ {
int err; int err;
PyObject *compare = NULL; PyObject *compare = NULL;
PyTypeObject *savetype;
if (args != NULL) { if (args != NULL) {
if (!PyArg_ParseTuple(args, "|O:sort", &compare)) if (!PyArg_ParseTuple(args, "|O:sort", &compare))
return NULL; return NULL;
} }
savetype = self->ob_type;
self->ob_type = &immutable_list_type; self->ob_type = &immutable_list_type;
err = samplesortslice(self->ob_item, err = samplesortslice(self->ob_item,
self->ob_item + self->ob_size, self->ob_item + self->ob_size,
compare); compare);
self->ob_type = &PyList_Type; self->ob_type = savetype;
if (err < 0) if (err < 0)
return NULL; return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
...@@ -1541,6 +1547,100 @@ list_richcompare(PyObject *v, PyObject *w, int op) ...@@ -1541,6 +1547,100 @@ list_richcompare(PyObject *v, PyObject *w, int op)
return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op); return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
} }
/* Adapted from newer code by Tim */
static int
list_fill(PyListObject *result, PyObject *v)
{
PyObject *it; /* iter(v) */
int n; /* guess for result list size */
int i;
n = result->ob_size;
/* Special-case list(a_list), for speed. */
if (PyList_Check(v)) {
if (v == (PyObject *)result)
return 0; /* source is destination, we're done */
return list_ass_slice(result, 0, n, v);
}
/* Empty previous contents */
if (n != 0) {
if (list_ass_slice(result, 0, n, (PyObject *)NULL) != 0)
return -1;
}
/* Get iterator. There may be some low-level efficiency to be gained
* by caching the tp_iternext slot instead of using PyIter_Next()
* later, but premature optimization is the root etc.
*/
it = PyObject_GetIter(v);
if (it == NULL)
return -1;
/* Guess a result list size. */
n = -1; /* unknown */
if (PySequence_Check(v) &&
v->ob_type->tp_as_sequence->sq_length) {
n = PySequence_Size(v);
if (n < 0)
PyErr_Clear();
}
if (n < 0)
n = 8; /* arbitrary */
NRESIZE(result->ob_item, PyObject*, n);
if (result->ob_item == NULL)
goto error;
for (i = 0; i < n; i++)
result->ob_item[i] = NULL;
result->ob_size = n;
/* Run iterator to exhaustion. */
for (i = 0; ; i++) {
PyObject *item = PyIter_Next(it);
if (item == NULL) {
if (PyErr_Occurred())
goto error;
break;
}
if (i < n)
PyList_SET_ITEM(result, i, item); /* steals ref */
else {
int status = ins1(result, result->ob_size, item);
Py_DECREF(item); /* append creates a new ref */
if (status < 0)
goto error;
}
}
/* Cut back result list if initial guess was too large. */
if (i < n && result != NULL) {
if (list_ass_slice(result, i, n, (PyObject *)NULL) != 0)
goto error;
}
Py_DECREF(it);
return 0;
error:
Py_DECREF(it);
return -1;
}
static int
list_init(PyListObject *self, PyObject *args, PyObject *kw)
{
PyObject *arg = NULL;
static char *kwlist[] = {"sequence", 0};
if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg))
return -1;
if (arg != NULL)
return list_fill(self, arg);
if (self->ob_size > 0)
return list_ass_slice(self, 0, self->ob_size, (PyObject*)NULL);
return 0;
}
static char append_doc[] = static char append_doc[] =
"L.append(object) -- append object to end"; "L.append(object) -- append object to end";
static char extend_doc[] = static char extend_doc[] =
...@@ -1573,12 +1673,6 @@ static PyMethodDef list_methods[] = { ...@@ -1573,12 +1673,6 @@ static PyMethodDef list_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyObject *
list_getattr(PyListObject *f, char *name)
{
return Py_FindMethod(list_methods, (PyObject *)f, name);
}
static PySequenceMethods list_as_sequence = { static PySequenceMethods list_as_sequence = {
(inquiry)list_length, /* sq_length */ (inquiry)list_length, /* sq_length */
(binaryfunc)list_concat, /* sq_concat */ (binaryfunc)list_concat, /* sq_concat */
...@@ -1592,6 +1686,10 @@ static PySequenceMethods list_as_sequence = { ...@@ -1592,6 +1686,10 @@ static PySequenceMethods list_as_sequence = {
(intargfunc)list_inplace_repeat, /* sq_inplace_repeat */ (intargfunc)list_inplace_repeat, /* sq_inplace_repeat */
}; };
static char list_doc[] =
"list() -> new list\n"
"list(sequence) -> new list initialized from sequence's items";
PyTypeObject PyList_Type = { PyTypeObject PyList_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
0, 0,
...@@ -1600,7 +1698,7 @@ PyTypeObject PyList_Type = { ...@@ -1600,7 +1698,7 @@ PyTypeObject PyList_Type = {
0, 0,
(destructor)list_dealloc, /* tp_dealloc */ (destructor)list_dealloc, /* tp_dealloc */
(printfunc)list_print, /* tp_print */ (printfunc)list_print, /* tp_print */
(getattrfunc)list_getattr, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
(reprfunc)list_repr, /* tp_repr */ (reprfunc)list_repr, /* tp_repr */
...@@ -1610,14 +1708,29 @@ PyTypeObject PyList_Type = { ...@@ -1610,14 +1708,29 @@ PyTypeObject PyList_Type = {
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC |
0, /* tp_doc */ Py_TPFLAGS_BASETYPE, /* tp_flags */
list_doc, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */ (traverseproc)list_traverse, /* tp_traverse */
(inquiry)list_clear, /* tp_clear */ (inquiry)list_clear, /* tp_clear */
list_richcompare, /* tp_richcompare */ list_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
list_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)list_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
}; };
...@@ -1646,12 +1759,6 @@ static PyMethodDef immutable_list_methods[] = { ...@@ -1646,12 +1759,6 @@ static PyMethodDef immutable_list_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static PyObject *
immutable_list_getattr(PyListObject *f, char *name)
{
return Py_FindMethod(immutable_list_methods, (PyObject *)f, name);
}
static int static int
immutable_list_ass(void) immutable_list_ass(void)
{ {
...@@ -1678,7 +1785,7 @@ static PyTypeObject immutable_list_type = { ...@@ -1678,7 +1785,7 @@ static PyTypeObject immutable_list_type = {
0, 0,
0, /* Cannot happen */ /* tp_dealloc */ 0, /* Cannot happen */ /* tp_dealloc */
(printfunc)list_print, /* tp_print */ (printfunc)list_print, /* tp_print */
(getattrfunc)immutable_list_getattr, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* Won't be called */ /* tp_compare */ 0, /* Won't be called */ /* tp_compare */
(reprfunc)list_repr, /* tp_repr */ (reprfunc)list_repr, /* tp_repr */
...@@ -1688,13 +1795,24 @@ static PyTypeObject immutable_list_type = { ...@@ -1688,13 +1795,24 @@ static PyTypeObject immutable_list_type = {
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */ list_doc, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */ (traverseproc)list_traverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
list_richcompare, /* tp_richcompare */ list_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
immutable_list_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_init */
/* NOTE: This is *not* the standard list_type struct! */ /* NOTE: This is *not* the standard list_type struct! */
}; };
...@@ -2031,6 +2031,43 @@ long_hex(PyObject *v) ...@@ -2031,6 +2031,43 @@ long_hex(PyObject *v)
return long_format(v, 16, 1); return long_format(v, 16, 1);
} }
static PyObject *
long_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *x = NULL;
int base = -909; /* unlikely! */
static char *kwlist[] = {"x", "base", 0};
assert(type == &PyLong_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist,
&x, &base))
return NULL;
if (x == NULL)
return PyLong_FromLong(0L);
if (base == -909)
return PyNumber_Long(x);
else if (PyString_Check(x))
return PyLong_FromString(PyString_AS_STRING(x), NULL, base);
else if (PyUnicode_Check(x))
return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x),
PyUnicode_GET_SIZE(x),
base);
else {
PyErr_SetString(PyExc_TypeError,
"long() can't convert non-string with explicit base");
return NULL;
}
}
static char long_doc[] =
"long(x[, base]) -> integer\n\
\n\
Convert a string or number to a long integer, if possible. A floating\n\
point argument will be truncated towards zero (this does not include a\n\
string representation of a floating point number!) When converting a\n\
string, use the optional base. It is an error to supply a base when\n\
converting a non-string.";
static PyNumberMethods long_as_number = { static PyNumberMethods long_as_number = {
(binaryfunc) long_add, /*nb_add*/ (binaryfunc) long_add, /*nb_add*/
(binaryfunc) long_sub, /*nb_subtract*/ (binaryfunc) long_sub, /*nb_subtract*/
...@@ -2070,24 +2107,42 @@ static PyNumberMethods long_as_number = { ...@@ -2070,24 +2107,42 @@ static PyNumberMethods long_as_number = {
PyTypeObject PyLong_Type = { PyTypeObject PyLong_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
0, 0, /* ob_size */
"long int", "long", /* tp_name */
sizeof(PyLongObject) - sizeof(digit), sizeof(PyLongObject) - sizeof(digit), /* tp_basicsize */
sizeof(digit), sizeof(digit), /* tp_itemsize */
(destructor)long_dealloc, /*tp_dealloc*/ (destructor)long_dealloc, /* tp_dealloc */
0, /*tp_print*/ 0, /* tp_print */
0, /*tp_getattr*/ 0, /* tp_getattr */
0, /*tp_setattr*/ 0, /* tp_setattr */
(cmpfunc)long_compare, /*tp_compare*/ (cmpfunc)long_compare, /* tp_compare */
(reprfunc)long_repr, /*tp_repr*/ (reprfunc)long_repr, /* tp_repr */
&long_as_number, /*tp_as_number*/ &long_as_number, /* tp_as_number */
0, /*tp_as_sequence*/ 0, /* tp_as_sequence */
0, /*tp_as_mapping*/ 0, /* tp_as_mapping */
(hashfunc)long_hash, /*tp_hash*/ (hashfunc)long_hash, /* tp_hash */
0, /*tp_call*/ 0, /* tp_call */
(reprfunc)long_str, /*tp_str*/ (reprfunc)long_str, /* tp_str */
0, /*tp_getattro*/ PyObject_GenericGetAttr, /* tp_getattro */
0, /*tp_setattro*/ 0, /* tp_setattro */
0, /*tp_as_buffer*/ 0, /* tp_as_buffer */
Py_TPFLAGS_CHECKTYPES /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
long_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
long_new, /* tp_new */
}; };
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
#include "Python.h" #include "Python.h"
#include "token.h"
static PyCFunctionObject *free_list = NULL; static PyCFunctionObject *free_list = NULL;
PyObject * PyObject *
...@@ -69,6 +67,23 @@ meth_dealloc(PyCFunctionObject *m) ...@@ -69,6 +67,23 @@ meth_dealloc(PyCFunctionObject *m)
free_list = m; free_list = m;
} }
static PyObject *
meth_get__doc__(PyCFunctionObject *m, void *closure)
{
char *doc = m->m_ml->ml_doc;
if (doc != NULL)
return PyString_FromString(doc);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
meth_get__name__(PyCFunctionObject *m, void *closure)
{
return PyString_FromString(m->m_ml->ml_name);
}
static int static int
meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
{ {
...@@ -79,19 +94,8 @@ meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) ...@@ -79,19 +94,8 @@ meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
} }
static PyObject * static PyObject *
meth_getattr(PyCFunctionObject *m, char *name) meth_get__self__(PyCFunctionObject *m, void *closure)
{ {
if (strcmp(name, "__name__") == 0) {
return PyString_FromString(m->m_ml->ml_name);
}
if (strcmp(name, "__doc__") == 0) {
char *doc = m->m_ml->ml_doc;
if (doc != NULL)
return PyString_FromString(doc);
Py_INCREF(Py_None);
return Py_None;
}
if (strcmp(name, "__self__") == 0) {
PyObject *self; PyObject *self;
if (PyEval_GetRestricted()) { if (PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
...@@ -103,15 +107,15 @@ meth_getattr(PyCFunctionObject *m, char *name) ...@@ -103,15 +107,15 @@ meth_getattr(PyCFunctionObject *m, char *name)
self = Py_None; self = Py_None;
Py_INCREF(self); Py_INCREF(self);
return self; return self;
}
if (strcmp(name, "__members__") == 0) {
return Py_BuildValue("[sss]",
"__doc__", "__name__", "__self__");
}
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
} }
static struct getsetlist meth_getsets [] = {
{"__doc__", (getter)meth_get__doc__, NULL, NULL},
{"__name__", (getter)meth_get__name__, NULL, NULL},
{"__self__", (getter)meth_get__self__, NULL, NULL},
{0}
};
static PyObject * static PyObject *
meth_repr(PyCFunctionObject *m) meth_repr(PyCFunctionObject *m)
{ {
...@@ -159,6 +163,41 @@ meth_hash(PyCFunctionObject *a) ...@@ -159,6 +163,41 @@ meth_hash(PyCFunctionObject *a)
return x; return x;
} }
static PyObject *
meth_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyCFunctionObject* f = (PyCFunctionObject*)func;
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
int flags = PyCFunction_GET_FLAGS(func);
if (flags & METH_KEYWORDS) {
return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
}
if (kw != NULL && PyDict_Size(kw) != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword arguments",
f->m_ml->ml_name);
return NULL;
}
if (flags & METH_VARARGS) {
return (*meth)(self, arg);
}
if (!(flags & METH_VARARGS)) {
/* the really old style */
int size = PyTuple_GET_SIZE(arg);
if (size == 1)
arg = PyTuple_GET_ITEM(arg, 0);
else if (size == 0)
arg = NULL;
return (*meth)(self, arg);
}
/* should never get here ??? */
PyErr_BadInternalCall();
return NULL;
}
PyTypeObject PyCFunction_Type = { PyTypeObject PyCFunction_Type = {
PyObject_HEAD_INIT(&PyType_Type) PyObject_HEAD_INIT(&PyType_Type)
0, 0,
...@@ -167,7 +206,7 @@ PyTypeObject PyCFunction_Type = { ...@@ -167,7 +206,7 @@ PyTypeObject PyCFunction_Type = {
0, 0,
(destructor)meth_dealloc, /* tp_dealloc */ (destructor)meth_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
(getattrfunc)meth_getattr, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
(cmpfunc)meth_compare, /* tp_compare */ (cmpfunc)meth_compare, /* tp_compare */
(reprfunc)meth_repr, /* tp_repr */ (reprfunc)meth_repr, /* tp_repr */
...@@ -175,14 +214,24 @@ PyTypeObject PyCFunction_Type = { ...@@ -175,14 +214,24 @@ PyTypeObject PyCFunction_Type = {
0, /* tp_as_sequence */ 0, /* tp_as_sequence */
0, /* tp_as_mapping */ 0, /* tp_as_mapping */
(hashfunc)meth_hash, /* tp_hash */ (hashfunc)meth_hash, /* tp_hash */
0, /* tp_call */ meth_call, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
(traverseproc)meth_traverse, /* tp_traverse */ (traverseproc)meth_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
meth_getsets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
}; };
/* List all methods in a chain -- helper for findmethodinchain */ /* List all methods in a chain -- helper for findmethodinchain */
......
This diff is collapsed.
This diff is collapsed.
...@@ -322,10 +322,22 @@ PyTypeObject PyRange_Type = { ...@@ -322,10 +322,22 @@ PyTypeObject PyRange_Type = {
0, /*tp_hash*/ 0, /*tp_hash*/
0, /*tp_call*/ 0, /*tp_call*/
0, /*tp_str*/ 0, /*tp_str*/
0, /*tp_getattro*/ PyObject_GenericGetAttr, /*tp_getattro*/
0, /*tp_setattro*/ 0, /*tp_setattro*/
0, /*tp_as_buffer*/ 0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
}; };
#undef WARN #undef WARN
This diff is collapsed.
This diff is collapsed.
...@@ -480,6 +480,28 @@ tuplerichcompare(PyObject *v, PyObject *w, int op) ...@@ -480,6 +480,28 @@ tuplerichcompare(PyObject *v, PyObject *w, int op)
return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op); return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);
} }
static PyObject *
tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *arg = NULL;
static char *kwlist[] = {"sequence", 0};
assert(type == &PyTuple_Type);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))
return NULL;
if (arg == NULL)
return PyTuple_New(0);
else
return PySequence_Tuple(arg);
}
static char tuple_doc[] =
"tuple(sequence) -> list\n\
\n\
Return a tuple whose items are the same as those of the argument sequence.\n\
If the argument is a tuple, the return value is the same object.";
static PySequenceMethods tuple_as_sequence = { static PySequenceMethods tuple_as_sequence = {
(inquiry)tuplelength, /* sq_length */ (inquiry)tuplelength, /* sq_length */
(binaryfunc)tupleconcat, /* sq_concat */ (binaryfunc)tupleconcat, /* sq_concat */
...@@ -509,14 +531,28 @@ PyTypeObject PyTuple_Type = { ...@@ -509,14 +531,28 @@ PyTypeObject PyTuple_Type = {
(hashfunc)tuplehash, /* tp_hash */ (hashfunc)tuplehash, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
0, /* tp_doc */ tuple_doc, /* tp_doc */
(traverseproc)tupletraverse, /* tp_traverse */ (traverseproc)tupletraverse, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
tuplerichcompare, /* tp_richcompare */ tuplerichcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
tuple_new, /* tp_new */
}; };
/* The following function breaks the notion that tuples are immutable: /* The following function breaks the notion that tuples are immutable:
......
This diff is collapsed.
This diff is collapsed.
...@@ -44,6 +44,7 @@ extern void init_locale(void); ...@@ -44,6 +44,7 @@ extern void init_locale(void);
extern void init_codecs(void); extern void init_codecs(void);
extern void initxreadlines(void); extern void initxreadlines(void);
extern void init_weakref(void); extern void init_weakref(void);
extern void initxxsubtype(void);
/* XXX tim: what's the purpose of ADDMODULE MARKER? */ /* XXX tim: what's the purpose of ADDMODULE MARKER? */
/* -- ADDMODULE MARKER 1 -- */ /* -- ADDMODULE MARKER 1 -- */
...@@ -98,6 +99,8 @@ struct _inittab _PyImport_Inittab[] = { ...@@ -98,6 +99,8 @@ struct _inittab _PyImport_Inittab[] = {
{"xreadlines", initxreadlines}, {"xreadlines", initxreadlines},
{"_weakref", init_weakref}, {"_weakref", init_weakref},
{"xxsubtype", initxxsubtype},
/* XXX tim: what's the purpose of ADDMODULE MARKER? */ /* XXX tim: what's the purpose of ADDMODULE MARKER? */
/* -- ADDMODULE MARKER 2 -- */ /* -- ADDMODULE MARKER 2 -- */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment