Commit dd3c61df authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'pwd'

parents d5ba641b 217654ec
......@@ -142,7 +142,6 @@ COMMON_CXXFLAGS += -fexceptions -fno-rtti
COMMON_CXXFLAGS += -Wno-invalid-offsetof # allow the use of "offsetof", and we'll just have to make sure to only use it legally.
COMMON_CXXFLAGS += -DENABLE_INTEL_JIT_EVENTS=$(ENABLE_INTEL_JIT_EVENTS)
COMMON_CXXFLAGS += -I$(DEPS_DIR)/pypa-install/include
COMMON_CXXFLAGS += -Wno-comment
ifeq ($(ENABLE_VALGRIND),0)
COMMON_CXXFLAGS += -DNVALGRIND
......@@ -214,6 +213,7 @@ CLANGFLAGS_RELEASE := $(CXXFLAGS_RELEASE) $(CLANG_EXTRA_FLAGS)
EXT_CFLAGS := $(COMMON_CFLAGS) -fPIC -Wimplicit -O2 -I../include
EXT_CFLAGS += -Wno-missing-field-initializers
EXT_CFLAGS += -Wno-tautological-compare -Wno-type-limits
ifneq ($(USE_CLANG),0)
EXT_CFLAGS += $(CLANG_EXTRA_FLAGS)
endif
......@@ -276,7 +276,7 @@ SRCS := $(MAIN_SRCS) $(STDLIB_SRCS)
STDLIB_OBJS := stdlib.bc.o stdlib.stripped.bc.o
STDLIB_RELEASE_OBJS := stdlib.release.bc.o
STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c $(EXTRA_STDMODULE_SRCS)
STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c $(EXTRA_STDMODULE_SRCS)
STDOBJECT_SRCS := structseq.c $(EXTRA_STDOBJECT_SRCS)
FROM_CPYTHON_SRCS := $(addprefix lib_python/2.7_Modules/,$(STDMODULE_SRCS)) $(addprefix lib_python/2.7_Objects/,$(STDOBJECT_SRCS)) $(wildcard src/capi/*.c)
......
......@@ -59,7 +59,12 @@
#include "pyerrors.h"
#include "pystate.h"
#include "pyarena.h"
#include "modsupport.h"
#include "pythonrun.h"
#include "ceval.h"
#include "import.h"
#include "abstract.h"
......
......@@ -847,10 +847,15 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
*/
// Pyston change: made this a function:
bool _PyIndex_Check(PyObject* o);
#define PyIndex_Check(obj) _PyIndex_Check((PyObject*)(obj))
#if 0
#define PyIndex_Check(obj) \
((obj)->ob_type->tp_as_number != NULL && \
PyType_HasFeature((obj)->ob_type, Py_TPFLAGS_HAVE_INDEX) && \
(obj)->ob_type->tp_as_number->nb_index != NULL)
#endif
PyAPI_FUNC(PyObject *) PyNumber_Index(PyObject *o);
......
......@@ -28,8 +28,8 @@ Don't forget to apply Py_INCREF() when returning either!!! */
//PyAPI_DATA(PyIntObject) _Py_ZeroStruct, _Py_TrueStruct;
PyAPI_DATA(PyObject) *True, *False;
/* Use these macros */
#define Py_False ((PyObject *) True)
#define Py_True ((PyObject *) False)
#define Py_False ((PyObject *) False)
#define Py_True ((PyObject *) True)
/* Macros for returning Py_True or Py_False, respectively */
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
......
// This file is originally from CPython 2.7, with modifications for Pyston
#ifndef Py_CEVAL_H
#define Py_CEVAL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Interface to random parts in ceval.c */
PyAPI_FUNC(PyObject *) PyEval_CallObjectWithKeywords(
PyObject *, PyObject *, PyObject *);
/* Inline this */
#define PyEval_CallObject(func,arg) \
PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL)
PyAPI_FUNC(PyObject *) PyEval_CallFunction(PyObject *obj,
const char *format, ...);
PyAPI_FUNC(PyObject *) PyEval_CallMethod(PyObject *obj,
const char *methodname,
const char *format, ...);
PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *);
PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *);
struct _frame; /* Avoid including frameobject.h */
PyAPI_FUNC(PyObject *) PyEval_GetBuiltins(void);
PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void);
PyAPI_FUNC(PyObject *) PyEval_GetLocals(void);
PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void);
PyAPI_FUNC(int) PyEval_GetRestricted(void);
/* Look at the current frame's (if any) code's co_flags, and turn on
the corresponding compiler flags in cf->cf_flags. Return 1 if any
flag was set, else return 0. */
PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);
PyAPI_FUNC(int) Py_FlushLine(void);
PyAPI_FUNC(int) Py_AddPendingCall(int (*func)(void *), void *arg);
PyAPI_FUNC(int) Py_MakePendingCalls(void);
/* Protection against deeply nested recursive calls */
PyAPI_FUNC(void) Py_SetRecursionLimit(int);
PyAPI_FUNC(int) Py_GetRecursionLimit(void);
#define Py_EnterRecursiveCall(where) \
(_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) && \
_Py_CheckRecursiveCall(where))
#define Py_LeaveRecursiveCall() \
(--PyThreadState_GET()->recursion_depth)
PyAPI_FUNC(int) _Py_CheckRecursiveCall(char *where);
PyAPI_DATA(int) _Py_CheckRecursionLimit;
#ifdef USE_STACKCHECK
# define _Py_MakeRecCheck(x) (++(x) > --_Py_CheckRecursionLimit)
#else
# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit)
#endif
PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *);
PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *);
PyAPI_FUNC(PyObject *) PyEval_GetCallStats(PyObject *);
PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *);
PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc);
/* this used to be handled on a per-thread basis - now just two globals */
PyAPI_DATA(volatile int) _Py_Ticker;
PyAPI_DATA(int) _Py_CheckInterval;
/* Interface for threads.
A module that plans to do a blocking system call (or something else
that lasts a long time and doesn't touch Python data) can allow other
threads to run as follows:
...preparations here...
Py_BEGIN_ALLOW_THREADS
...blocking system call here...
Py_END_ALLOW_THREADS
...interpret result here...
The Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS pair expands to a
{}-surrounded block.
To leave the block in the middle (e.g., with return), you must insert
a line containing Py_BLOCK_THREADS before the return, e.g.
if (...premature_exit...) {
Py_BLOCK_THREADS
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
An alternative is:
Py_BLOCK_THREADS
if (...premature_exit...) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
Py_UNBLOCK_THREADS
For convenience, that the value of 'errno' is restored across
Py_END_ALLOW_THREADS and Py_BLOCK_THREADS.
WARNING: NEVER NEST CALLS TO Py_BEGIN_ALLOW_THREADS AND
Py_END_ALLOW_THREADS!!!
The function PyEval_InitThreads() should be called only from
initthread() in "threadmodule.c".
Note that not yet all candidates have been converted to use this
mechanism!
*/
PyAPI_FUNC(PyThreadState *) PyEval_SaveThread(void);
PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *);
#ifdef WITH_THREAD
PyAPI_FUNC(int) PyEval_ThreadsInitialized(void);
PyAPI_FUNC(void) PyEval_InitThreads(void);
PyAPI_FUNC(void) PyEval_AcquireLock(void);
PyAPI_FUNC(void) PyEval_ReleaseLock(void);
PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate);
PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate);
PyAPI_FUNC(void) PyEval_ReInitThreads(void);
#define Py_BEGIN_ALLOW_THREADS { \
PyThreadState *_save; \
_save = PyEval_SaveThread();
#define Py_BLOCK_THREADS PyEval_RestoreThread(_save);
#define Py_UNBLOCK_THREADS _save = PyEval_SaveThread();
#define Py_END_ALLOW_THREADS PyEval_RestoreThread(_save); \
}
#else /* !WITH_THREAD */
#define Py_BEGIN_ALLOW_THREADS {
#define Py_BLOCK_THREADS
#define Py_UNBLOCK_THREADS
#define Py_END_ALLOW_THREADS }
#endif /* !WITH_THREAD */
PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *);
#ifdef __cplusplus
}
#endif
#endif /* !Py_CEVAL_H */
......@@ -903,8 +903,11 @@ PyAPI_DATA(PyObject*) None;
Py_NotImplemented is a singleton used to signal that an operation is
not implemented for a given type combination.
*/
PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
#define Py_NotImplemented (&_Py_NotImplementedStruct)
// Pyston change:
//PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
//#define Py_NotImplemented (&_Py_NotImplementedStruct)
PyAPI_DATA(PyObject*) NotImplemented; /* Don't use this directly */
#define Py_NotImplemented NotImplemented
/* Rich comparison opcodes */
#define Py_LT 0
......
// This file is originally from CPython 2.7, with modifications for Pyston
/* An arena-like memory interface for the compiler.
*/
#ifndef Py_PYARENA_H
#define Py_PYARENA_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _arena PyArena;
/* PyArena_New() and PyArena_Free() create a new arena and free it,
respectively. Once an arena has been created, it can be used
to allocate memory via PyArena_Malloc(). Pointers to PyObject can
also be registered with the arena via PyArena_AddPyObject(), and the
arena will ensure that the PyObjects stay alive at least until
PyArena_Free() is called. When an arena is freed, all the memory it
allocated is freed, the arena releases internal references to registered
PyObject*, and none of its pointers are valid.
XXX (tim) What does "none of its pointers are valid" mean? Does it
XXX mean that pointers previously obtained via PyArena_Malloc() are
XXX no longer valid? (That's clearly true, but not sure that's what
XXX the text is trying to say.)
PyArena_New() returns an arena pointer. On error, it
returns a negative number and sets an exception.
XXX (tim): Not true. On error, PyArena_New() actually returns NULL,
XXX and looks like it may or may not set an exception (e.g., if the
XXX internal PyList_New(0) returns NULL, PyArena_New() passes that on
XXX and an exception is set; OTOH, if the internal
XXX block_new(DEFAULT_BLOCK_SIZE) returns NULL, that's passed on but
XXX an exception is not set in that case).
*/
PyAPI_FUNC(PyArena *) PyArena_New(void);
PyAPI_FUNC(void) PyArena_Free(PyArena *);
/* Mostly like malloc(), return the address of a block of memory spanning
* `size` bytes, or return NULL (without setting an exception) if enough
* new memory can't be obtained. Unlike malloc(0), PyArena_Malloc() with
* size=0 does not guarantee to return a unique pointer (the pointer
* returned may equal one or more other pointers obtained from
* PyArena_Malloc()).
* Note that pointers obtained via PyArena_Malloc() must never be passed to
* the system free() or realloc(), or to any of Python's similar memory-
* management functions. PyArena_Malloc()-obtained pointers remain valid
* until PyArena_Free(ar) is called, at which point all pointers obtained
* from the arena `ar` become invalid simultaneously.
*/
PyAPI_FUNC(void *) PyArena_Malloc(PyArena *, size_t size);
/* This routine isn't a proper arena allocation routine. It takes
* a PyObject* and records it so that it can be DECREFed when the
* arena is freed.
*/
PyAPI_FUNC(int) PyArena_AddPyObject(PyArena *, PyObject *);
#ifdef __cplusplus
}
#endif
#endif /* !Py_PYARENA_H */
// This file is originally from CPython 2.7, with modifications for Pyston
/* Thread and interpreter state structures and their interfaces */
#ifndef Py_PYSTATE_H
#define Py_PYSTATE_H
#ifdef __cplusplus
extern "C" {
#endif
/* State shared between threads */
// Pyston change: this is not our format
#if 0
struct _ts; /* Forward */
struct _is; /* Forward */
typedef struct _is {
struct _is *next;
struct _ts *tstate_head;
PyObject *modules;
PyObject *sysdict;
PyObject *builtins;
PyObject *modules_reloading;
PyObject *codec_search_path;
PyObject *codec_search_cache;
PyObject *codec_error_registry;
#ifdef HAVE_DLOPEN
int dlopenflags;
#endif
#ifdef WITH_TSC
int tscdump;
#endif
} PyInterpreterState;
#endif
struct _PyInterpreterState;
typedef struct _PyInterpreterState PyInterpreterState;
/* State unique per thread */
struct _frame; /* Avoid including frameobject.h */
/* Py_tracefunc return -1 when raising an exception, or 0 for success. */
typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *);
/* The following values are used for 'what' for tracefunc functions: */
#define PyTrace_CALL 0
#define PyTrace_EXCEPTION 1
#define PyTrace_LINE 2
#define PyTrace_RETURN 3
#define PyTrace_C_CALL 4
#define PyTrace_C_EXCEPTION 5
#define PyTrace_C_RETURN 6
// Pyston change: this is not our format
#if 0
typedef struct _ts {
/* See Python/ceval.c for comments explaining most fields */
struct _ts *next;
PyInterpreterState *interp;
struct _frame *frame;
int recursion_depth;
/* 'tracing' keeps track of the execution depth when tracing/profiling.
This is to prevent the actual trace/profile code from being recorded in
the trace/profile. */
int tracing;
int use_tracing;
Py_tracefunc c_profilefunc;
Py_tracefunc c_tracefunc;
PyObject *c_profileobj;
PyObject *c_traceobj;
PyObject *curexc_type;
PyObject *curexc_value;
PyObject *curexc_traceback;
PyObject *exc_type;
PyObject *exc_value;
PyObject *exc_traceback;
PyObject *dict; /* Stores per-thread state */
/* tick_counter is incremented whenever the check_interval ticker
* reaches zero. The purpose is to give a useful measure of the number
* of interpreted bytecode instructions in a given thread. This
* extremely lightweight statistic collector may be of interest to
* profilers (like psyco.jit()), although nothing in the core uses it.
*/
int tick_counter;
int gilstate_counter;
PyObject *async_exc; /* Asynchronous exception to raise */
long thread_id; /* Thread id where this tstate was created */
int trash_delete_nesting;
PyObject *trash_delete_later;
/* XXX signal handlers should also be here */
} PyThreadState;
#endif
struct _PyThreadState;
typedef struct _PyThreadState PyThreadState;
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void);
PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *);
PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
PyAPI_FUNC(void) _PyThreadState_Init(PyThreadState *);
PyAPI_FUNC(void) PyThreadState_Clear(PyThreadState *);
PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *);
#ifdef WITH_THREAD
PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void);
#endif
PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void);
PyAPI_FUNC(PyThreadState *) PyThreadState_Swap(PyThreadState *);
PyAPI_FUNC(PyObject *) PyThreadState_GetDict(void);
PyAPI_FUNC(int) PyThreadState_SetAsyncExc(long, PyObject *);
/* Variable and macro for in-line access to current thread state */
PyAPI_DATA(PyThreadState *) _PyThreadState_Current;
#ifdef Py_DEBUG
#define PyThreadState_GET() PyThreadState_Get()
#else
#define PyThreadState_GET() (_PyThreadState_Current)
#endif
typedef
enum {PyGILState_LOCKED, PyGILState_UNLOCKED}
PyGILState_STATE;
/* Ensure that the current thread is ready to call the Python
C API, regardless of the current state of Python, or of its
thread lock. This may be called as many times as desired
by a thread so long as each call is matched with a call to
PyGILState_Release(). In general, other thread-state APIs may
be used between _Ensure() and _Release() calls, so long as the
thread-state is restored to its previous state before the Release().
For example, normal use of the Py_BEGIN_ALLOW_THREADS/
Py_END_ALLOW_THREADS macros are acceptable.
The return value is an opaque "handle" to the thread state when
PyGILState_Ensure() was called, and must be passed to
PyGILState_Release() to ensure Python is left in the same state. Even
though recursive calls are allowed, these handles can *not* be shared -
each unique call to PyGILState_Ensure must save the handle for its
call to PyGILState_Release.
When the function returns, the current thread will hold the GIL.
Failure is a fatal error.
*/
PyAPI_FUNC(PyGILState_STATE) PyGILState_Ensure(void);
/* Release any resources previously acquired. After this call, Python's
state will be the same as it was prior to the corresponding
PyGILState_Ensure() call (but generally this state will be unknown to
the caller, hence the use of the GILState API.)
Every call to PyGILState_Ensure must be matched by a call to
PyGILState_Release on the same thread.
*/
PyAPI_FUNC(void) PyGILState_Release(PyGILState_STATE);
/* Helper/diagnostic function - get the current thread state for
this thread. May return NULL if no GILState API has been used
on the current thread. Note that the main thread always has such a
thread-state, even if no auto-thread-state call has been made
on the main thread.
*/
PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void);
/* The implementation of sys._current_frames() Returns a dict mapping
thread id to that thread's current frame.
*/
PyAPI_FUNC(PyObject *) _PyThread_CurrentFrames(void);
/* Routines for advanced debuggers, requested by David Beazley.
Don't use unless you know what you are doing! */
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Head(void);
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *);
PyAPI_FUNC(PyThreadState *) PyThreadState_Next(PyThreadState *);
typedef struct _frame *(*PyThreadFrameGetter)(PyThreadState *self_);
/* hook for PyEval_GetFrame(), requested for Psyco */
PyAPI_DATA(PyThreadFrameGetter) _PyThreadState_GetFrame;
#ifdef __cplusplus
}
#endif
#endif /* !Py_PYSTATE_H */
// This file is originally from CPython 2.7, with modifications for Pyston
/* Interfaces to parse and execute pieces of python code */
#ifndef Py_PYTHONRUN_H
#define Py_PYTHONRUN_H
#ifdef __cplusplus
extern "C" {
#endif
#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \
CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \
CO_FUTURE_UNICODE_LITERALS)
#define PyCF_MASK_OBSOLETE (CO_NESTED)
#define PyCF_SOURCE_IS_UTF8 0x0100
#define PyCF_DONT_IMPLY_DEDENT 0x0200
#define PyCF_ONLY_AST 0x0400
typedef struct {
int cf_flags; /* bitmask of CO_xxx flags relevant to future */
} PyCompilerFlags;
PyAPI_FUNC(void) Py_SetProgramName(char *);
PyAPI_FUNC(char *) Py_GetProgramName(void);
PyAPI_FUNC(void) Py_SetPythonHome(char *);
PyAPI_FUNC(char *) Py_GetPythonHome(void);
PyAPI_FUNC(void) Py_Initialize(void);
PyAPI_FUNC(void) Py_InitializeEx(int);
PyAPI_FUNC(void) Py_Finalize(void);
PyAPI_FUNC(int) Py_IsInitialized(void);
PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void);
PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);
PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, const char *, PyCompilerFlags *);
PyAPI_FUNC(int) PyRun_AnyFileExFlags(FILE *, const char *, int, PyCompilerFlags *);
PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *);
PyAPI_FUNC(int) PyRun_SimpleFileExFlags(FILE *, const char *, int, PyCompilerFlags *);
PyAPI_FUNC(int) PyRun_InteractiveOneFlags(FILE *, const char *, PyCompilerFlags *);
PyAPI_FUNC(int) PyRun_InteractiveLoopFlags(FILE *, const char *, PyCompilerFlags *);
PyAPI_FUNC(struct _mod *) PyParser_ASTFromString(const char *, const char *,
int, PyCompilerFlags *flags,
PyArena *);
PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile(FILE *, const char *, int,
char *, char *,
PyCompilerFlags *, int *,
PyArena *);
#define PyParser_SimpleParseString(S, B) \
PyParser_SimpleParseStringFlags(S, B, 0)
#define PyParser_SimpleParseFile(FP, S, B) \
PyParser_SimpleParseFileFlags(FP, S, B, 0)
PyAPI_FUNC(struct _node *) PyParser_SimpleParseStringFlags(const char *, int,
int);
PyAPI_FUNC(struct _node *) PyParser_SimpleParseFileFlags(FILE *, const char *,
int, int);
PyAPI_FUNC(PyObject *) PyRun_StringFlags(const char *, int, PyObject *,
PyObject *, PyCompilerFlags *);
PyAPI_FUNC(PyObject *) PyRun_FileExFlags(FILE *, const char *, int,
PyObject *, PyObject *, int,
PyCompilerFlags *);
#define Py_CompileString(str, p, s) Py_CompileStringFlags(str, p, s, NULL)
PyAPI_FUNC(PyObject *) Py_CompileStringFlags(const char *, const char *, int,
PyCompilerFlags *);
PyAPI_FUNC(struct symtable *) Py_SymtableString(const char *, const char *, int);
PyAPI_FUNC(void) PyErr_Print(void);
PyAPI_FUNC(void) PyErr_PrintEx(int);
PyAPI_FUNC(void) PyErr_Display(PyObject *, PyObject *, PyObject *);
PyAPI_FUNC(int) Py_AtExit(void (*func)(void));
PyAPI_FUNC(void) Py_Exit(int);
PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
/* Bootstrap */
PyAPI_FUNC(int) Py_Main(int argc, char **argv);
/* Use macros for a bunch of old variants */
#define PyRun_String(str, s, g, l) PyRun_StringFlags(str, s, g, l, NULL)
#define PyRun_AnyFile(fp, name) PyRun_AnyFileExFlags(fp, name, 0, NULL)
#define PyRun_AnyFileEx(fp, name, closeit) \
PyRun_AnyFileExFlags(fp, name, closeit, NULL)
#define PyRun_AnyFileFlags(fp, name, flags) \
PyRun_AnyFileExFlags(fp, name, 0, flags)
#define PyRun_SimpleString(s) PyRun_SimpleStringFlags(s, NULL)
#define PyRun_SimpleFile(f, p) PyRun_SimpleFileExFlags(f, p, 0, NULL)
#define PyRun_SimpleFileEx(f, p, c) PyRun_SimpleFileExFlags(f, p, c, NULL)
#define PyRun_InteractiveOne(f, p) PyRun_InteractiveOneFlags(f, p, NULL)
#define PyRun_InteractiveLoop(f, p) PyRun_InteractiveLoopFlags(f, p, NULL)
#define PyRun_File(fp, p, s, g, l) \
PyRun_FileExFlags(fp, p, s, g, l, 0, NULL)
#define PyRun_FileEx(fp, p, s, g, l, c) \
PyRun_FileExFlags(fp, p, s, g, l, c, NULL)
#define PyRun_FileFlags(fp, p, s, g, l, flags) \
PyRun_FileExFlags(fp, p, s, g, l, 0, flags)
/* In getpath.c */
PyAPI_FUNC(char *) Py_GetProgramFullPath(void);
PyAPI_FUNC(char *) Py_GetPrefix(void);
PyAPI_FUNC(char *) Py_GetExecPrefix(void);
PyAPI_FUNC(char *) Py_GetPath(void);
/* In their own files */
PyAPI_FUNC(const char *) Py_GetVersion(void);
PyAPI_FUNC(const char *) Py_GetPlatform(void);
PyAPI_FUNC(const char *) Py_GetCopyright(void);
PyAPI_FUNC(const char *) Py_GetCompiler(void);
PyAPI_FUNC(const char *) Py_GetBuildInfo(void);
PyAPI_FUNC(const char *) _Py_svnversion(void);
PyAPI_FUNC(const char *) Py_SubversionRevision(void);
PyAPI_FUNC(const char *) Py_SubversionShortBranch(void);
PyAPI_FUNC(const char *) _Py_hgidentifier(void);
PyAPI_FUNC(const char *) _Py_hgversion(void);
/* Internal -- various one-time initializations */
PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
PyAPI_FUNC(PyObject *) _PySys_Init(void);
PyAPI_FUNC(void) _PyImport_Init(void);
PyAPI_FUNC(void) _PyExc_Init(void);
PyAPI_FUNC(void) _PyImportHooks_Init(void);
PyAPI_FUNC(int) _PyFrame_Init(void);
PyAPI_FUNC(int) _PyInt_Init(void);
PyAPI_FUNC(int) _PyLong_Init(void);
PyAPI_FUNC(void) _PyFloat_Init(void);
PyAPI_FUNC(int) PyByteArray_Init(void);
PyAPI_FUNC(void) _PyRandom_Init(void);
/* Various internal finalizers */
PyAPI_FUNC(void) _PyExc_Fini(void);
PyAPI_FUNC(void) _PyImport_Fini(void);
PyAPI_FUNC(void) PyMethod_Fini(void);
PyAPI_FUNC(void) PyFrame_Fini(void);
PyAPI_FUNC(void) PyCFunction_Fini(void);
PyAPI_FUNC(void) PyDict_Fini(void);
PyAPI_FUNC(void) PyTuple_Fini(void);
PyAPI_FUNC(void) PyList_Fini(void);
PyAPI_FUNC(void) PySet_Fini(void);
PyAPI_FUNC(void) PyString_Fini(void);
PyAPI_FUNC(void) PyInt_Fini(void);
PyAPI_FUNC(void) PyFloat_Fini(void);
PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
PyAPI_FUNC(void) PyByteArray_Fini(void);
/* Stuff with no proper home (yet) */
PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, char *);
PyAPI_DATA(int) (*PyOS_InputHook)(void);
PyAPI_DATA(char) *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *);
PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState;
/* Stack size, in "pointers" (so we get extra safety margins
on 64-bit platforms). On a 32-bit platform, this translates
to a 8k margin. */
#define PYOS_STACK_MARGIN 2048
#if defined(WIN32) && !defined(MS_WIN64) && defined(_MSC_VER) && _MSC_VER >= 1300
/* Enable stack checking under Microsoft C */
#define USE_STACKCHECK
#endif
#ifdef USE_STACKCHECK
/* Check that we aren't overflowing our stack */
PyAPI_FUNC(int) PyOS_CheckStack(void);
#endif
/* Signals */
typedef void (*PyOS_sighandler_t)(int);
PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
/* Random */
PyAPI_FUNC(int) _PyOS_URandom (void *buffer, Py_ssize_t size);
#ifdef __cplusplus
}
#endif
#endif /* !Py_PYTHONRUN_H */
......@@ -38,12 +38,47 @@ static int check_num_args(PyObject* ob, int n) {
return 0;
}
static PyObject* wrap_hashfunc(PyObject* self, PyObject* args, void* wrapped) {
hashfunc func = (hashfunc)wrapped;
long res;
if (!check_num_args(args, 0))
return NULL;
res = (*func)(self);
if (res == -1 && PyErr_Occurred())
return NULL;
return PyInt_FromLong(res);
}
static PyObject* wrap_call(PyObject* self, PyObject* args, void* wrapped, PyObject* kwds) {
ternaryfunc func = (ternaryfunc)wrapped;
return (*func)(self, args, kwds);
}
static PyObject* wrap_richcmpfunc(PyObject* self, PyObject* args, void* wrapped, int op) {
richcmpfunc func = (richcmpfunc)wrapped;
PyObject* other;
if (!check_num_args(args, 1))
return NULL;
other = PyTuple_GET_ITEM(args, 0);
return (*func)(self, other, op);
}
#undef RICHCMP_WRAPPER
#define RICHCMP_WRAPPER(NAME, OP) \
static PyObject* richcmp_##NAME(PyObject* self, PyObject* args, void* wrapped) { \
return wrap_richcmpfunc(self, args, wrapped, OP); \
}
RICHCMP_WRAPPER(lt, Py_LT)
RICHCMP_WRAPPER(le, Py_LE)
RICHCMP_WRAPPER(eq, Py_EQ)
RICHCMP_WRAPPER(ne, Py_NE)
RICHCMP_WRAPPER(gt, Py_GT)
RICHCMP_WRAPPER(ge, Py_GE)
static PyObject* wrap_unaryfunc(PyObject* self, PyObject* args, void* wrapped) {
unaryfunc func = (unaryfunc)wrapped;
......@@ -244,7 +279,7 @@ static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) {
static PyObject* lookup_maybe(PyObject* self, const char* attrstr, PyObject** attrobj) {
static PyObject* lookup_maybe(PyObject* self, const char* attrstr, PyObject** attrobj) noexcept {
PyObject* res;
// TODO: CPython uses the attrobj as a cache
......@@ -254,6 +289,13 @@ static PyObject* lookup_maybe(PyObject* self, const char* attrstr, PyObject** at
return obj;
}
static PyObject* lookup_method(PyObject* self, const char* attrstr, PyObject** attrobj) noexcept {
PyObject* res = lookup_maybe(self, attrstr, attrobj);
if (res == NULL && !PyErr_Occurred())
PyErr_SetObject(PyExc_AttributeError, *attrobj);
return res;
}
// Copied from CPython:
static PyObject* call_method(PyObject* o, const char* name, PyObject** nameobj, const char* format, ...) noexcept {
va_list va;
......@@ -288,19 +330,51 @@ static PyObject* call_method(PyObject* o, const char* name, PyObject** nameobj,
}
PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds) noexcept {
PyObject* slot_tp_repr(PyObject* self) noexcept {
try {
// TODO: runtime ICs?
Box* new_attr = typeLookup(self, _new_str, NULL);
assert(new_attr);
new_attr = processDescriptor(new_attr, None, self);
return runtimeCall(new_attr, ArgPassSpec(1, 0, true, true), self, args, kwds, NULL, NULL);
return repr(self);
} catch (Box* e) {
abort();
}
}
static long slot_tp_hash(PyObject* self) noexcept {
PyObject* func;
static PyObject* hash_str, *eq_str, *cmp_str;
long h;
func = lookup_method(self, "__hash__", &hash_str);
if (func != NULL && func != Py_None) {
PyObject* res = PyEval_CallObject(func, NULL);
Py_DECREF(func);
if (res == NULL)
return -1;
if (PyLong_Check(res))
h = PyLong_Type.tp_hash(res);
else
h = PyInt_AsLong(res);
Py_DECREF(res);
} else {
Py_XDECREF(func); /* may be None */
PyErr_Clear();
func = lookup_method(self, "__eq__", &eq_str);
if (func == NULL) {
PyErr_Clear();
func = lookup_method(self, "__cmp__", &cmp_str);
}
if (func != NULL) {
Py_DECREF(func);
return PyObject_HashNotImplemented(self);
}
PyErr_Clear();
h = _Py_HashPointer((void*)self);
}
if (h == -1 && !PyErr_Occurred())
h = -2;
return h;
}
PyObject* slot_tp_call(PyObject* self, PyObject* args, PyObject* kwds) noexcept {
try {
Py_FatalError("this function is untested");
......@@ -312,9 +386,59 @@ PyObject* slot_tp_call(PyObject* self, PyObject* args, PyObject* kwds) noexcept
}
}
PyObject* slot_tp_repr(PyObject* self) noexcept {
static const char* name_op[] = {
"__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__",
};
static PyObject* half_richcompare(PyObject* self, PyObject* other, int op) {
PyObject* func, *args, *res;
static PyObject* op_str[6];
func = lookup_method(self, name_op[op], &op_str[op]);
if (func == NULL) {
PyErr_Clear();
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
args = PyTuple_Pack(1, other);
if (args == NULL)
res = NULL;
else {
res = PyObject_Call(func, args, NULL);
Py_DECREF(args);
}
Py_DECREF(func);
return res;
}
static PyObject* slot_tp_richcompare(PyObject* self, PyObject* other, int op) {
PyObject* res;
if (Py_TYPE(self)->tp_richcompare == slot_tp_richcompare) {
res = half_richcompare(self, other, op);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
if (Py_TYPE(other)->tp_richcompare == slot_tp_richcompare) {
res = half_richcompare(other, self, _Py_SwappedOp[op]);
if (res != Py_NotImplemented) {
return res;
}
Py_DECREF(res);
}
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds) noexcept {
try {
return repr(self);
// TODO: runtime ICs?
Box* new_attr = typeLookup(self, _new_str, NULL);
assert(new_attr);
new_attr = processDescriptor(new_attr, None, self);
return runtimeCall(new_attr, ArgPassSpec(1, 0, true, true), self, args, kwds, NULL, NULL);
} catch (Box* e) {
abort();
}
......@@ -483,15 +607,22 @@ static void** slotptr(BoxedClass* type, int offset) {
static void update_one_slot(BoxedClass* self, const slotdef& p) {
// TODO: CPython version is significantly more sophisticated
void** ptr = slotptr(self, p.offset);
Box* attr = typeLookup(self, p.name, NULL);
if (!ptr) {
assert(!typeLookup(self, p.name, NULL) && "I don't think this case should happen? CPython handles it though");
assert(!attr && "I don't think this case should happen? CPython handles it though");
return;
}
if (typeLookup(self, p.name, NULL))
*ptr = p.function;
else
if (attr) {
if (attr == None && ptr == (void**)&self->tp_hash) {
*ptr = (void*)&PyObject_HashNotImplemented;
} else {
*ptr = p.function;
}
} else {
*ptr = NULL;
}
}
// Copied from CPython:
......@@ -519,8 +650,15 @@ static void update_one_slot(BoxedClass* self, const slotdef& p) {
static slotdef slotdefs[] = {
TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc, "x.__repr__() <==> repr(x)"),
TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc, "x.__hash__() <==> hash(x)"),
FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, "x.__call__(...) <==> x(...)",
PyWrapperFlag_KEYWORDS),
TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt, "x.__lt__(y) <==> x<y"),
TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le, "x.__le__(y) <==> x<=y"),
TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq, "x.__eq__(y) <==> x==y"),
TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne, "x.__ne__(y) <==> x!=y"),
TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt, "x.__gt__(y) <==> x>y"),
TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge, "x.__ge__(y) <==> x>=y"),
TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""),
MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, "x.__len__() <==> len(x)"),
......@@ -639,9 +777,12 @@ static void add_operators(BoxedClass* cls) {
continue;
if (cls->getattr(p.name))
continue;
// TODO PyObject_HashNotImplemented
cls->giveAttr(p.name, new BoxedWrapperDescriptor(&p, cls, *ptr));
if (*ptr == PyObject_HashNotImplemented) {
cls->giveAttr(p.name, None);
} else {
cls->giveAttr(p.name, new BoxedWrapperDescriptor(&p, cls, *ptr));
}
}
if (cls->tp_new)
......@@ -661,7 +802,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) {
RELEASE_ASSERT(cls->tp_setattr == NULL, "");
RELEASE_ASSERT(cls->tp_compare == NULL, "");
RELEASE_ASSERT(cls->tp_as_number == NULL, "");
RELEASE_ASSERT(cls->tp_hash == NULL, "");
RELEASE_ASSERT(cls->tp_str == NULL, "");
RELEASE_ASSERT(cls->tp_getattro == NULL || cls->tp_getattro == PyObject_GenericGetAttr, "");
RELEASE_ASSERT(cls->tp_setattro == NULL, "");
......@@ -670,7 +810,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) {
int ALLOWABLE_FLAGS = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC;
RELEASE_ASSERT((cls->tp_flags & ~ALLOWABLE_FLAGS) == 0, "");
RELEASE_ASSERT(cls->tp_richcompare == NULL, "");
RELEASE_ASSERT(cls->tp_iter == NULL, "");
RELEASE_ASSERT(cls->tp_iternext == NULL, "");
RELEASE_ASSERT(cls->tp_base == NULL, "");
......
......@@ -57,8 +57,33 @@ static Box* posix_getuid() {
return boxInt(getuid());
}
extern "C" {
extern char** environ;
}
static Box* convertEnviron() {
assert(environ);
BoxedDict* d = new BoxedDict();
// Ported from CPython:
for (char** e = environ; *e != NULL; e++) {
char* p = strchr(*e, '=');
if (p == NULL)
continue;
Box* k = PyString_FromStringAndSize(*e, (int)(p - *e));
Box* v = PyString_FromString(p + 1);
Box*& cur_v = d->d[k];
if (cur_v == NULL)
cur_v = v;
}
return d;
}
} // namespace posix
using namespace posix;
void setupPosix() {
posix_module = createModule("posix", "__builtin__");
......@@ -66,5 +91,120 @@ void setupPosix() {
posix_module->giveAttr("getuid", new BoxedFunction(boxRTFunction((void*)posix::posix_getuid, BOXED_INT, 0)));
posix_module->giveAttr("error", OSError);
posix_module->giveAttr("environ", convertEnviron());
}
}
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#else
#pragma GCC diagnostic ignored "-Wtype-limits"
#endif
// Copied from CPython/Modules/posixmodule.c:
extern "C" {
PyObject* _PyInt_FromUid(uid_t uid) {
if (uid <= LONG_MAX)
return PyInt_FromLong(uid);
return PyLong_FromUnsignedLong(uid);
}
PyObject* _PyInt_FromGid(gid_t gid) {
if (gid <= LONG_MAX)
return PyInt_FromLong(gid);
return PyLong_FromUnsignedLong(gid);
}
int _Py_Uid_Converter(PyObject* obj, void* p) {
int overflow;
long result;
if (PyFloat_Check(obj)) {
PyErr_SetString(PyExc_TypeError, "integer argument expected, got float");
return 0;
}
result = PyLong_AsLongAndOverflow(obj, &overflow);
if (overflow < 0)
goto OverflowDown;
if (!overflow && result == -1) {
/* error or -1 */
if (PyErr_Occurred())
return 0;
*(uid_t*)p = (uid_t)-1;
} else {
/* unsigned uid_t */
unsigned long uresult;
if (overflow > 0) {
uresult = PyLong_AsUnsignedLong(obj);
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_OverflowError))
goto OverflowUp;
return 0;
}
} else {
if (result < 0)
goto OverflowDown;
uresult = result;
}
if (sizeof(uid_t) < sizeof(long) && (unsigned long)(uid_t)uresult != uresult)
goto OverflowUp;
*(uid_t*)p = (uid_t)uresult;
}
return 1;
OverflowDown:
PyErr_SetString(PyExc_OverflowError, "user id is less than minimum");
return 0;
OverflowUp:
PyErr_SetString(PyExc_OverflowError, "user id is greater than maximum");
return 0;
}
int _Py_Gid_Converter(PyObject* obj, void* p) {
int overflow;
long result;
if (PyFloat_Check(obj)) {
PyErr_SetString(PyExc_TypeError, "integer argument expected, got float");
return 0;
}
result = PyLong_AsLongAndOverflow(obj, &overflow);
if (overflow < 0)
goto OverflowDown;
if (!overflow && result == -1) {
/* error or -1 */
if (PyErr_Occurred())
return 0;
*(gid_t*)p = (gid_t)-1;
} else {
/* unsigned gid_t */
unsigned long uresult;
if (overflow > 0) {
uresult = PyLong_AsUnsignedLong(obj);
if (PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_OverflowError))
goto OverflowUp;
return 0;
}
} else {
if (result < 0)
goto OverflowDown;
uresult = result;
}
if (sizeof(gid_t) < sizeof(long) && (unsigned long)(gid_t)uresult != uresult)
goto OverflowUp;
*(gid_t*)p = (gid_t)uresult;
}
return 1;
OverflowDown:
PyErr_SetString(PyExc_OverflowError, "group id is less than minimum");
return 0;
OverflowUp:
PyErr_SetString(PyExc_OverflowError, "group id is greater than maximum");
return 0;
}
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
......@@ -38,6 +38,7 @@ MAKE_CHECK(Long, long_cls)
MAKE_CHECK(List, list_cls)
MAKE_CHECK(Tuple, tuple_cls)
MAKE_CHECK(Dict, dict_cls)
MAKE_CHECK(Slice, slice_cls)
#ifdef Py_USING_UNICODE
MAKE_CHECK(Unicode, unicode_cls)
......@@ -45,6 +46,11 @@ MAKE_CHECK(Unicode, unicode_cls)
#undef MAKE_CHECK
extern "C" bool _PyIndex_Check(PyObject* op) {
// TODO this is wrong (the CPython version checks for things that can be coerced to a number):
return PyInt_Check(op);
}
extern "C" {
int Py_Py3kWarningFlag;
}
......@@ -299,6 +305,10 @@ extern "C" PyObject* PyObject_RichCompare(PyObject* o1, PyObject* o2, int opid)
Py_FatalError("unimplemented");
}
extern "C" {
int _Py_SwappedOp[] = { Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE };
}
extern "C" long PyObject_Hash(PyObject* o) {
try {
return hash(o)->n;
......@@ -307,6 +317,23 @@ extern "C" long PyObject_Hash(PyObject* o) {
}
}
extern "C" long PyObject_HashNotImplemented(PyObject* self) {
PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'", Py_TYPE(self)->tp_name);
return -1;
}
extern "C" long _Py_HashPointer(void* p) {
long x;
size_t y = (size_t)p;
/* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
excessive hash collisions for dicts and sets */
y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4));
x = (long)y;
if (x == -1)
x = -2;
return x;
}
extern "C" int PyObject_IsTrue(PyObject* o) {
try {
return nonzero(o);
......@@ -320,6 +347,30 @@ extern "C" int PyObject_Not(PyObject* o) {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PyEval_CallObjectWithKeywords(PyObject* func, PyObject* arg, PyObject* kw) {
PyObject* result;
if (arg == NULL) {
arg = PyTuple_New(0);
if (arg == NULL)
return NULL;
} else if (!PyTuple_Check(arg)) {
PyErr_SetString(PyExc_TypeError, "argument list must be a tuple");
return NULL;
} else
Py_INCREF(arg);
if (kw != NULL && !PyDict_Check(kw)) {
PyErr_SetString(PyExc_TypeError, "keyword list must be a dictionary");
Py_DECREF(arg);
return NULL;
}
result = PyObject_Call(func, arg, kw);
Py_DECREF(arg);
return result;
}
extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, PyObject* kw) {
try {
if (kw)
......
......@@ -43,6 +43,7 @@ extern "C" void init_sre();
extern "C" void initmath();
extern "C" void initoperator();
extern "C" void initbinascii();
extern "C" void initpwd();
namespace pyston {
......@@ -594,10 +595,6 @@ Box* sliceRepr(BoxedSlice* self) {
return new BoxedString(std::move(s));
}
extern "C" bool PySlice_Check(PyObject*) {
Py_FatalError("unimplemented");
}
extern "C" int PySlice_GetIndices(PySliceObject* r, Py_ssize_t length, Py_ssize_t* start, Py_ssize_t* stop,
Py_ssize_t* step) {
Py_FatalError("unimplemented");
......@@ -966,6 +963,7 @@ void setupRuntime() {
initmath();
initoperator();
initbinascii();
initpwd();
setupSysEnd();
......
......@@ -28,6 +28,21 @@ slots_tester_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *)obj;
}
static long slots_tester_seq_hash(slots_tester_object* obj) {
printf("slots_tester_seq.__hash__\n");
return obj->n ^ 1;
}
static PyObject* slots_tester_seq_richcmp(slots_tester_object* lhs, PyObject* rhs, int op) {
printf("slots_tester_seq.richcmp(%d, %d)\n", lhs->n, op);
Py_RETURN_TRUE;
if (op % 2)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject *
slots_tester_seq_repr(slots_tester_object *obj)
{
......@@ -84,7 +99,7 @@ static PyTypeObject slots_tester_seq = {
0, /* tp_as_number */
&slots_tester_seq_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(hashfunc)slots_tester_seq_hash, /* tp_hash */
(ternaryfunc)slots_tester_seq_call, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
......@@ -94,7 +109,7 @@ static PyTypeObject slots_tester_seq = {
slots_tester_seq_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
(richcmpfunc)slots_tester_seq_richcmp, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
......
......@@ -3,6 +3,7 @@ import slots_test
for i in xrange(3):
t = slots_test.SlotsTesterSeq(i + 5)
print t, repr(t), t(), t[2]
print hash(t), t < 1, t > 2, t != 3
# print slots_test.SlotsTesterSeq.__doc__
print slots_test.SlotsTesterSeq.set_through_tpdict, slots_test.SlotsTesterSeq(5).set_through_tpdict
......
# allow-warning: converting unicode literal to str
import pwd
import os
print pwd.getpwuid(os.getuid())[5] == os.environ["HOME"]
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