Commit a53ab1a8 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #465 from kmod/virtualenv

bcrypt support
parents 7b71c6f8 578f9b6a
......@@ -207,7 +207,7 @@ add_test(NAME analysis_unittest COMMAND analysis_unittest)
add_test(NAME pyston_defaults COMMAND ${PYTHON_EXE} ${CMAKE_SOURCE_DIR}/tools/tester.py -R ./pyston -j${TEST_THREADS} -a=-S -k ${CMAKE_SOURCE_DIR}/test/tests)
# we pass -I to cpython tests and skip failing ones b/c they are slooow otherwise
add_test(NAME pyston_defaults_cpython_tests COMMAND ${PYTHON_EXE} ${CMAKE_SOURCE_DIR}/tools/tester.py -R ./pyston -j${TEST_THREADS} -a=-S -k --exit-code-only --skip-failing -t30 ${CMAKE_SOURCE_DIR}/test/cpython)
add_test(NAME pyston_defaults_integration_tests COMMAND ${PYTHON_EXE} ${CMAKE_SOURCE_DIR}/tools/tester.py -R ./pyston -j${TEST_THREADS} -a=-S -k --exit-code-only --skip-failing -t120 ${CMAKE_SOURCE_DIR}/test/integration)
add_test(NAME pyston_defaults_integration_tests COMMAND ${PYTHON_EXE} ${CMAKE_SOURCE_DIR}/tools/tester.py -R ./pyston -j${TEST_THREADS} -a=-S -k --exit-code-only --skip-failing -t180 ${CMAKE_SOURCE_DIR}/test/integration)
add_test(NAME pyston_max_compilation_tier COMMAND ${PYTHON_EXE} ${CMAKE_SOURCE_DIR}/tools/tester.py -R ./pyston -j${TEST_THREADS} -a=-O -a=-S -k ${CMAKE_SOURCE_DIR}/test/tests)
add_test(NAME pyston_old_parser COMMAND ${PYTHON_EXE} ${CMAKE_SOURCE_DIR}/tools/tester.py -a=-x -R ./pyston -j1 -a=-n -a=-S -k ${CMAKE_SOURCE_DIR}/test/tests)
......
......@@ -366,6 +366,7 @@ STDOBJECT_SRCS := \
memoryobject.c \
iterobject.c \
bufferobject.c \
cobject.c \
$(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS := \
......@@ -494,7 +495,7 @@ check:
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_dbg -j$(TEST_THREADS) -k -a=-S $(TESTS_DIR) $(ARGS)
@# we pass -I to cpython tests & skip failing ones because they are sloooow otherwise
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_dbg -j$(TEST_THREADS) -k -a=-S --exit-code-only --skip-failing -t30 $(TEST_DIR)/cpython $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_dbg -j$(TEST_THREADS) -k -a=-S --exit-code-only --skip-failing -t120 $(TEST_DIR)/integration $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_dbg -j$(TEST_THREADS) -k -a=-S --exit-code-only --skip-failing -t180 $(TEST_DIR)/integration $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_dbg -j$(TEST_THREADS) -k -a=-n -a=-x -a=-S $(TESTS_DIR) $(ARGS)
@# skip -O for dbg
......@@ -511,7 +512,7 @@ check:
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_release -j$(TEST_THREADS) -k -a=-S $(TESTS_DIR) $(ARGS)
@# we pass -I to cpython tests and skip failing ones because they are sloooow otherwise
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_release -j$(TEST_THREADS) -k -a=-S --exit-code-only --skip-failing $(TEST_DIR)/cpython $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_release -j$(TEST_THREADS) -k -a=-S --exit-code-only --skip-failing -t60 $(TEST_DIR)/integration $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_release -j$(TEST_THREADS) -k -a=-S --exit-code-only --skip-failing -t120 $(TEST_DIR)/integration $(ARGS)
@# skip -n for dbg
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_release -j$(TEST_THREADS) -k -a=-O -a=-x -a=-S $(TESTS_DIR) $(ARGS)
......@@ -956,7 +957,7 @@ check$1 test$1: $(PYTHON_EXE_DEPS) pyston$1 ext_pyston
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -a=-S -k $(TESTS_DIR) $(ARGS)
@# we pass -I to cpython tests and skip failing ones because they are sloooow otherwise
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -a=-S -k --exit-code-only --skip-failing -t30 $(TEST_DIR)/cpython $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -k -a=-S --exit-code-only --skip-failing -t120 $(TEST_DIR)/integration $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -k -a=-S --exit-code-only --skip-failing -t180 $(TEST_DIR)/integration $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -a=-x -R pyston$1 -j$(TEST_THREADS) -a=-n -a=-S -k $(TESTS_DIR) $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston$1 -j$(TEST_THREADS) -a=-O -a=-S -k $(TESTS_DIR) $(ARGS)
......
......@@ -76,6 +76,7 @@ file(GLOB_RECURSE STDOBJECT_SRCS Objects
bytearrayobject.c
bytes_methods.c
capsule.c
cobject.c
exceptions.c
iterobject.c
memoryobject.c
......
......@@ -75,6 +75,7 @@
#include "methodobject.h"
#include "moduleobject.h"
#include "classobject.h"
#include "cobject.h"
#include "fileobject.h"
#include "pycapsule.h"
#include "traceback.h"
......
// This file is originally from CPython 2.7, with modifications for Pyston
/*
CObjects are marked Pending Deprecation as of Python 2.7.
The full schedule for 2.x is as follows:
- CObjects are marked Pending Deprecation in Python 2.7.
- CObjects will be marked Deprecated in Python 2.8
(if there is one).
- CObjects will be removed in Python 2.9 (if there is one).
Additionally, for the Python 3.x series:
- CObjects were marked Deprecated in Python 3.1.
- CObjects will be removed in Python 3.2.
You should switch all use of CObjects to capsules. Capsules
have a safer and more consistent API. For more information,
see Include/pycapsule.h, or read the "Capsules" topic in
the "Python/C API Reference Manual".
Python 2.7 no longer uses CObjects itself; all objects which
were formerly CObjects are now capsules. Note that this change
does not by itself break binary compatibility with extensions
built for previous versions of Python--PyCObject_AsVoidPtr()
has been changed to also understand capsules.
*/
/* original file header comment follows: */
/* C objects to be exported from one extension module to another.
C objects are used for communication between extension modules.
They provide a way for an extension module to export a C interface
to other extension modules, so that extension modules can use the
Python import mechanism to link to one another.
*/
#ifndef Py_COBJECT_H
#define Py_COBJECT_H
#ifdef __cplusplus
extern "C" {
#endif
PyAPI_DATA(PyTypeObject) PyCObject_Type;
#define PyCObject_Check(op) (Py_TYPE(op) == &PyCObject_Type)
/* Create a PyCObject from a pointer to a C object and an optional
destructor function. If the second argument is non-null, then it
will be called with the first argument if and when the PyCObject is
destroyed.
*/
PyAPI_FUNC(PyObject *) PyCObject_FromVoidPtr(
void *cobj, void (*destruct)(void*)) PYSTON_NOEXCEPT;
/* Create a PyCObject from a pointer to a C object, a description object,
and an optional destructor function. If the third argument is non-null,
then it will be called with the first and second arguments if and when
the PyCObject is destroyed.
*/
PyAPI_FUNC(PyObject *) PyCObject_FromVoidPtrAndDesc(
void *cobj, void *desc, void (*destruct)(void*,void*)) PYSTON_NOEXCEPT;
/* Retrieve a pointer to a C object from a PyCObject. */
PyAPI_FUNC(void *) PyCObject_AsVoidPtr(PyObject *) PYSTON_NOEXCEPT;
/* Retrieve a pointer to a description object from a PyCObject. */
PyAPI_FUNC(void *) PyCObject_GetDesc(PyObject *) PYSTON_NOEXCEPT;
/* Import a pointer to a C object from a module using a PyCObject. */
PyAPI_FUNC(void *) PyCObject_Import(char *module_name, char *cobject_name) PYSTON_NOEXCEPT;
/* Modify a C object. Fails (==0) if object has a destructor. */
PyAPI_FUNC(int) PyCObject_SetVoidPtr(PyObject *self, void *cobj) PYSTON_NOEXCEPT;
typedef struct {
PyObject_HEAD
void *cobject;
void *desc;
void (*destructor)(void *);
} PyCObject;
#ifdef __cplusplus
}
#endif
#endif /* !Py_COBJECT_H */
......@@ -553,7 +553,7 @@ PyAPI_FUNC(int) PyNumber_CoerceEx(PyObject **, PyObject **) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *) PYSTON_NOEXCEPT;
/* A slot function whose address we need to compare */
extern int _PyObject_SlotCompare(PyObject *, PyObject *);
extern int _PyObject_SlotCompare(PyObject *, PyObject *) PYSTON_NOEXCEPT;
/* Same as PyObject_Generic{Get,Set}Attr, but passing the attributes
dict as the last parameter. */
PyAPI_FUNC(PyObject *)
......
......@@ -312,13 +312,13 @@ extern PyGC_Head *_PyGC_generation0;
(PyObject_IS_GC(obj) && \
(!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))
#endif
PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) PyObject_GC_Track(void *) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) PyObject_GC_UnTrack(void *) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) PyObject_GC_Del(void *) PYSTON_NOEXCEPT;
#endif
#define PyType_IS_GC(t) ((t),1)
#define _PyObject_GC_TRACK(o) ((void)(o))
#define _PyObject_GC_UNTRACK(o) ((void)(o))
......
......@@ -36,13 +36,16 @@ PyAPI_DATA(int) Py_HashRandomizationFlag;
// Pyston change: make Py_FatalError a macro so that it can access linenumber info, similar to assert:
//PyAPI_FUNC(void) Py_FatalError(const char *message) __attribute__((__noreturn__)) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) _Py_FatalError(const char *fmt, const char *function, const char *message)
__attribute__((__noreturn__));
#define _PYSTON_STRINGIFY(N) #N
#define PYSTON_STRINGIFY(N) _PYSTON_STRINGIFY(N)
#define Py_FatalError(message) \
do { \
fprintf(stderr, __FILE__ ":" PYSTON_STRINGIFY(__LINE__) ": %s: Fatal Python error: %s\n", __PRETTY_FUNCTION__, message); \
abort(); \
} while (0)
// Defer the real work of Py_FatalError to a function, since some users expect it to be a real function,
// ie can be used as an expression (a do-while(0) loop would fail that).
#define Py_FatalError(message) \
_Py_FatalError(__FILE__ \
":" PYSTON_STRINGIFY(__LINE__) ": %s: Fatal Python error: %s\n", \
__PRETTY_FUNCTION__, message)
#ifdef __cplusplus
}
......
......@@ -371,6 +371,7 @@ class CCompiler:
cc_args[:0] = ['-g']
if before:
cc_args[:0] = before
cc_args = cc_args + ["-Werror=implicit-function-declaration"]
return cc_args
def _fix_compile_args(self, output_dir, macros, include_dirs):
......
// This file is originally from CPython 2.7, with modifications for Pyston
/* Wrap void* pointers to be passed between C modules */
#include "Python.h"
/* Declarations for objects of type PyCObject */
typedef void (*destructor1)(void *);
typedef void (*destructor2)(void *, void*);
static int cobject_deprecation_warning(void)
{
return PyErr_WarnPy3k("CObject type is not supported in 3.x. "
"Please use capsule objects instead.", 1);
}
PyObject *
PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *))
{
PyCObject *self;
if (cobject_deprecation_warning()) {
return NULL;
}
self = PyObject_NEW(PyCObject, &PyCObject_Type);
if (self == NULL)
return NULL;
self->cobject=cobj;
self->destructor=destr;
self->desc=NULL;
return (PyObject *)self;
}
PyObject *
PyCObject_FromVoidPtrAndDesc(void *cobj, void *desc,
void (*destr)(void *, void *))
{
PyCObject *self;
if (cobject_deprecation_warning()) {
return NULL;
}
if (!desc) {
PyErr_SetString(PyExc_TypeError,
"PyCObject_FromVoidPtrAndDesc called with null"
" description");
return NULL;
}
self = PyObject_NEW(PyCObject, &PyCObject_Type);
if (self == NULL)
return NULL;
self->cobject = cobj;
self->destructor = (destructor1)destr;
self->desc = desc;
return (PyObject *)self;
}
void *
PyCObject_AsVoidPtr(PyObject *self)
{
if (self) {
if (PyCapsule_CheckExact(self)) {
const char *name = PyCapsule_GetName(self);
return (void *)PyCapsule_GetPointer(self, name);
}
if (self->ob_type == &PyCObject_Type)
return ((PyCObject *)self)->cobject;
PyErr_SetString(PyExc_TypeError,
"PyCObject_AsVoidPtr with non-C-object");
}
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError,
"PyCObject_AsVoidPtr called with null pointer");
return NULL;
}
void *
PyCObject_GetDesc(PyObject *self)
{
if (self) {
if (self->ob_type == &PyCObject_Type)
return ((PyCObject *)self)->desc;
PyErr_SetString(PyExc_TypeError,
"PyCObject_GetDesc with non-C-object");
}
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError,
"PyCObject_GetDesc called with null pointer");
return NULL;
}
void *
PyCObject_Import(char *module_name, char *name)
{
PyObject *m, *c;
void *r = NULL;
if ((m = PyImport_ImportModule(module_name))) {
if ((c = PyObject_GetAttrString(m,name))) {
r = PyCObject_AsVoidPtr(c);
Py_DECREF(c);
}
Py_DECREF(m);
}
return r;
}
int
PyCObject_SetVoidPtr(PyObject *self, void *cobj)
{
PyCObject* cself = (PyCObject*)self;
if (cself == NULL || !PyCObject_Check(cself) ||
cself->destructor != NULL) {
PyErr_SetString(PyExc_TypeError,
"Invalid call to PyCObject_SetVoidPtr");
return 0;
}
cself->cobject = cobj;
return 1;
}
static void
PyCObject_dealloc(PyCObject *self)
{
if (self->destructor) {
if(self->desc)
((destructor2)(self->destructor))(self->cobject, self->desc);
else
(self->destructor)(self->cobject);
}
PyObject_DEL(self);
}
PyDoc_STRVAR(PyCObject_Type__doc__,
"C objects to be exported from one extension module to another\n\
\n\
C objects are used for communication between extension modules. They\n\
provide a way for an extension module to export a C interface to other\n\
extension modules, so that extension modules can use the Python import\n\
mechanism to link to one another.");
PyTypeObject PyCObject_Type = {
PyVarObject_HEAD_INIT(/* Pyston change: &PyType_Type */ NULL, 0)
"PyCObject", /*tp_name*/
sizeof(PyCObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)PyCObject_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*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
0, /*tp_flags*/
PyCObject_Type__doc__ /*tp_doc*/
};
......@@ -27,6 +27,31 @@
namespace pyston {
static PyObject* type_error(const char* msg, PyObject* obj) noexcept {
PyErr_Format(PyExc_TypeError, msg, Py_TYPE(obj)->tp_name);
return NULL;
}
static PyObject* null_error(void) noexcept {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_SystemError, "null argument to internal routine");
return NULL;
}
extern "C" int PyObject_Cmp(PyObject* o1, PyObject* o2, int* result) noexcept {
int r;
if (o1 == NULL || o2 == NULL) {
null_error();
return -1;
}
r = PyObject_Compare(o1, o2);
if (PyErr_Occurred())
return -1;
*result = r;
return 0;
}
extern "C" Py_ssize_t _PyObject_LengthHint(PyObject* o, Py_ssize_t defaultvalue) noexcept {
static PyObject* hintstrobj = NULL;
PyObject* ro, *hintmeth;
......@@ -227,17 +252,6 @@ extern "C" void PyBuffer_Release(Py_buffer* view) noexcept {
view->obj = NULL;
}
static PyObject* type_error(const char* msg, PyObject* obj) noexcept {
PyErr_Format(PyExc_TypeError, msg, Py_TYPE(obj)->tp_name);
return NULL;
}
static PyObject* null_error(void) noexcept {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_SystemError, "null argument to internal routine");
return NULL;
}
static PyObject* objargs_mktuple(va_list va) noexcept {
int i, n = 0;
va_list countva;
......@@ -1516,9 +1530,28 @@ extern "C" int PyNumber_Coerce(PyObject**, PyObject**) noexcept {
return -1;
}
extern "C" int PyNumber_CoerceEx(PyObject**, PyObject**) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
extern "C" int PyNumber_CoerceEx(PyObject** pv, PyObject** pw) noexcept {
PyObject* v = *pv;
PyObject* w = *pw;
int res;
/* Shortcut only for old-style types */
if (v->cls == w->cls && !PyType_HasFeature(v->cls, Py_TPFLAGS_CHECKTYPES)) {
Py_INCREF(v);
Py_INCREF(w);
return 0;
}
if (v->cls->tp_as_number && v->cls->tp_as_number->nb_coerce) {
res = (*v->cls->tp_as_number->nb_coerce)(pv, pw);
if (res <= 0)
return res;
}
if (w->cls->tp_as_number && w->cls->tp_as_number->nb_coerce) {
res = (*w->cls->tp_as_number->nb_coerce)(pw, pv);
if (res <= 0)
return res;
}
return 1;
}
extern "C" PyObject* _PyNumber_ConvertIntegralToInt(PyObject* integral, const char* error_format) noexcept {
......
This diff is collapsed.
......@@ -461,6 +461,26 @@ static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) noe
return Py_None;
}
static PyObject* wrap_cmpfunc(PyObject* self, PyObject* args, void* wrapped) noexcept {
cmpfunc func = (cmpfunc)wrapped;
int res;
PyObject* other;
if (!check_num_args(args, 1))
return NULL;
other = PyTuple_GET_ITEM(args, 0);
if (Py_TYPE(other)->tp_compare != func && !PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) {
PyErr_Format(PyExc_TypeError, "%s.__cmp__(x,y) requires y to be a '%s', not a '%s'", Py_TYPE(self)->tp_name,
Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name);
return NULL;
}
res = (*func)(self, other);
if (PyErr_Occurred())
return NULL;
return PyInt_FromLong((long)res);
}
static PyObject* wrap_init(PyObject* self, PyObject* args, void* wrapped, PyObject* kwds) noexcept {
initproc func = (initproc)wrapped;
......@@ -565,7 +585,57 @@ static PyObject* call_maybe(PyObject* o, const char* name, PyObject** nameobj, c
return retval;
}
PyObject* slot_tp_repr(PyObject* self) noexcept {
static int half_compare(PyObject* self, PyObject* other) noexcept {
PyObject* func, *args, *res;
static PyObject* cmp_str;
Py_ssize_t c;
func = lookup_method(self, "__cmp__", &cmp_str);
if (func == NULL) {
PyErr_Clear();
} else {
args = PyTuple_Pack(1, other);
if (args == NULL)
res = NULL;
else {
res = PyObject_Call(func, args, NULL);
Py_DECREF(args);
}
Py_DECREF(func);
if (res != Py_NotImplemented) {
if (res == NULL)
return -2;
c = PyInt_AsLong(res);
Py_DECREF(res);
if (c == -1 && PyErr_Occurred())
return -2;
return (c < 0) ? -1 : (c > 0) ? 1 : 0;
}
Py_DECREF(res);
}
return 2;
}
/* This slot is published for the benefit of try_3way_compare in object.c */
extern "C" int _PyObject_SlotCompare(PyObject* self, PyObject* other) noexcept {
int c;
if (Py_TYPE(self)->tp_compare == _PyObject_SlotCompare) {
c = half_compare(self, other);
if (c <= 1)
return c;
}
if (Py_TYPE(other)->tp_compare == _PyObject_SlotCompare) {
c = half_compare(other, self);
if (c < -1)
return -2;
if (c <= 1)
return -c;
}
return (void*)self < (void*)other ? -1 : (void*)self > (void*)other ? 1 : 0;
}
static PyObject* slot_tp_repr(PyObject* self) noexcept {
try {
return repr(self);
} catch (ExcInfo e) {
......@@ -574,7 +644,7 @@ PyObject* slot_tp_repr(PyObject* self) noexcept {
}
}
PyObject* slot_tp_str(PyObject* self) noexcept {
static PyObject* slot_tp_str(PyObject* self) noexcept {
try {
return str(self);
} catch (ExcInfo e) {
......@@ -1264,6 +1334,7 @@ static slotdef slotdefs[]
TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),
TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""),
TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc, "x.__cmp__(y) <==> cmp(x,y)"),
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)"),
......@@ -2596,8 +2667,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
// unhandled fields:
RELEASE_ASSERT(cls->tp_compare == NULL, "");
RELEASE_ASSERT(cls->tp_getattro == NULL || cls->tp_getattro == PyObject_GenericGetAttr, "");
int ALLOWABLE_FLAGS = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES
| Py_TPFLAGS_HAVE_NEWBUFFER;
ALLOWABLE_FLAGS |= Py_TPFLAGS_INT_SUBCLASS | Py_TPFLAGS_LONG_SUBCLASS | Py_TPFLAGS_LIST_SUBCLASS
......
......@@ -1427,6 +1427,8 @@ public:
bool visit_functiondef(AST_FunctionDef* node) override {
auto def = new AST_FunctionDef();
def->lineno = node->lineno;
def->col_offset = node->col_offset;
def->name = node->name;
def->body = node->body; // expensive vector copy
// Decorators are evaluated before the defaults, so this *must* go before remapArguments().
......
......@@ -969,9 +969,11 @@ Box* builtinRound(Box* _number, Box* _ndigits) {
throwCAPIException();
}
Box* builtinCmp(Box* lhs, Box* rhs) {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
throwCAPIException();
Box* builtinCmp(Box* a, Box* b) {
int c;
if (PyObject_Cmp(a, b, &c) < 0)
throwCAPIException();
return PyInt_FromLong((long)c);
}
Box* builtinApply(Box* func, Box* args, Box* keywords) {
......
......@@ -105,7 +105,7 @@ public:
RELEASE_ASSERT(_self->cls == thread_lock_cls, "");
BoxedThreadLock* self = static_cast<BoxedThreadLock*>(_self);
RELEASE_ASSERT(_waitflag->cls == int_cls, "");
RELEASE_ASSERT(isSubclass(_waitflag->cls, int_cls), "");
int waitflag = static_cast<BoxedInt*>(_waitflag)->n;
// Copied + adapted from CPython:
......
......@@ -306,44 +306,6 @@ extern "C" int PyObject_DelItem(PyObject* o, PyObject* key) noexcept {
return -1;
}
extern "C" PyObject* PyObject_RichCompare(PyObject* o1, PyObject* o2, int opid) noexcept {
int translated_op;
switch (opid) {
case Py_LT:
translated_op = AST_TYPE::Lt;
break;
case Py_LE:
translated_op = AST_TYPE::LtE;
break;
case Py_EQ:
translated_op = AST_TYPE::Eq;
break;
case Py_NE:
translated_op = AST_TYPE::NotEq;
break;
case Py_GT:
translated_op = AST_TYPE::Gt;
break;
case Py_GE:
translated_op = AST_TYPE::GtE;
break;
default:
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
};
try {
return compare(o1, o2, translated_op);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
extern "C" {
int _Py_SwappedOp[] = { Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE };
}
extern "C" long PyObject_Hash(PyObject* o) noexcept {
try {
return hash(o)->n;
......@@ -1374,6 +1336,44 @@ static Box* methodGetDoc(Box* b, void*) {
return None;
}
/* extension modules might be compiled with GC support so these
functions must always be available */
#undef PyObject_GC_Track
#undef PyObject_GC_UnTrack
#undef PyObject_GC_Del
#undef _PyObject_GC_Malloc
extern "C" PyObject* _PyObject_GC_Malloc(size_t basicsize) noexcept {
Box* r = ((PyObject*)PyObject_MALLOC(basicsize));
RELEASE_ASSERT(gc::isValidGCObject(r), "");
return r;
}
#undef _PyObject_GC_New
extern "C" PyObject* _PyObject_GC_New(PyTypeObject* tp) noexcept {
PyObject* op = _PyObject_GC_Malloc(_PyObject_SIZE(tp));
if (op != NULL)
op = PyObject_INIT(op, tp);
RELEASE_ASSERT(gc::isValidGCObject(op), "");
return op;
}
extern "C" PyVarObject* _PyObject_GC_NewVar(PyTypeObject* tp, Py_ssize_t nitems) noexcept {
const size_t size = _PyObject_VAR_SIZE(tp, nitems);
PyVarObject* op = (PyVarObject*)_PyObject_GC_Malloc(size);
if (op != NULL)
op = PyObject_INIT_VAR(op, tp, nitems);
RELEASE_ASSERT(gc::isValidGCObject(op), "");
return op;
}
extern "C" void _Py_FatalError(const char* fmt, const char* function, const char* message) {
fprintf(stderr, fmt, function, message);
fflush(stderr); /* it helps in Windows debug build */
abort();
}
void setupCAPI() {
capifunc_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
......
......@@ -51,6 +51,20 @@ public:
return boxString(static_cast<BoxedCode*>(b)->f->source->fn);
}
static Box* firstlineno(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
CLFunction* cl = code->f;
if (!cl->source) {
// I don't think it really matters what we return here;
// in CPython, builtin functions don't have code objects.
return boxInt(-1);
}
return boxInt(cl->source->ast->lineno);
}
static Box* argcount(Box* b, void*) {
RELEASE_ASSERT(b->cls == code_cls, "");
......@@ -114,6 +128,8 @@ void setupCode() {
code_cls->giveAttr("co_name", new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCode::name, NULL, NULL));
code_cls->giveAttr("co_filename", new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCode::filename, NULL, NULL));
code_cls->giveAttr("co_firstlineno",
new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCode::firstlineno, NULL, NULL));
code_cls->giveAttr("co_argcount", new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCode::argcount, NULL, NULL));
code_cls->giveAttr("co_varnames", new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCode::varnames, NULL, NULL));
code_cls->giveAttr("co_flags", new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCode::flags, NULL, NULL));
......
......@@ -690,7 +690,14 @@ Box* impFindModule(Box* _name, BoxedList* path) {
return BoxedTuple::create({ None, path, BoxedTuple::create({ mode, mode, boxInt(sr.type) }) });
}
Py_FatalError("unimplemented");
if (sr.type == SearchResult::C_EXTENSION) {
Box* path = boxString(sr.path);
Box* mode = boxStrConstant("rb");
Box* f = runtimeCall(file_cls, ArgPassSpec(2), path, mode, NULL, NULL, NULL);
return BoxedTuple::create({ f, path, BoxedTuple::create({ boxStrConstant(".so"), mode, boxInt(sr.type) }) });
}
RELEASE_ASSERT(0, "unknown type: %d", sr.type);
}
Box* impLoadModule(Box* _name, Box* _file, Box* _pathname, Box** args) {
......@@ -724,6 +731,26 @@ Box* impLoadModule(Box* _name, Box* _file, Box* _pathname, Box** args) {
Py_FatalError("unimplemented");
}
Box* impLoadDynamic(Box* _name, Box* _pathname, Box* _file) {
RELEASE_ASSERT(_name->cls == str_cls, "");
RELEASE_ASSERT(_pathname->cls == str_cls, "");
RELEASE_ASSERT(_file == None, "");
BoxedString* name = (BoxedString*)_name;
BoxedString* pathname = (BoxedString*)_pathname;
const char* lastdot = strrchr(name->s.data(), '.');
const char* shortname;
if (lastdot == NULL) {
shortname = name->s.data();
} else {
shortname = lastdot + 1;
}
return importCExtension(name->s, shortname, pathname->s);
}
Box* impGetSuffixes() {
BoxedList* list = new BoxedList;
// For now only add *.py
......@@ -772,9 +799,12 @@ void setupImport() {
CLFunction* load_module_func = boxRTFunction((void*)impLoadModule, UNKNOWN, 4,
ParamNames({ "name", "file", "pathname", "description" }, "", ""));
imp_module->giveAttr("load_module", new BoxedBuiltinFunctionOrMethod(load_module_func, "load_module"));
CLFunction* load_dynamic_func = boxRTFunction((void*)impLoadDynamic, UNKNOWN, 3, 1, false, false,
ParamNames({ "name", "pathname", "file" }, "", ""));
imp_module->giveAttr("load_dynamic", new BoxedBuiltinFunctionOrMethod(load_dynamic_func, "load_dynamic", { None }));
imp_module->giveAttr("get_suffixes", new BoxedBuiltinFunctionOrMethod(
boxRTFunction((void*)impGetSuffixes, UNKNOWN, 0), "get_suffixes"));
imp_module->giveAttr("acquire_lock", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)impAcquireLock, NONE, 0),
......
......@@ -325,6 +325,7 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
tp_flags |= Py_TPFLAGS_HAVE_CLASS;
tp_flags |= Py_TPFLAGS_HAVE_GC;
tp_flags |= Py_TPFLAGS_HAVE_WEAKREFS;
tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE;
if (base && (base->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER))
tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
......
......@@ -2273,6 +2273,7 @@ void setupRuntime() {
PyType_Ready(&PyByteArrayIter_Type);
PyType_Ready(&PyCapsule_Type);
PyType_Ready(&PyCallIter_Type);
PyType_Ready(&PyCObject_Type);
initerrno();
init_sha();
......
# expected: fail
# - misc issues
import os
import sys
import subprocess
import shutil
VIRTUALENV_SCRIPT = os.path.dirname(__file__) + "/virtualenv/virtualenv.py"
if os.path.exists("test_env"):
print "Removing the existing 'test_env/' directory"
subprocess.check_call(["rm", "-rf", "test_env"])
# shutil follows symlinks to directories, and deletes whatever those contain.
# shutil.rmtree("test_env")
args = [sys.executable, VIRTUALENV_SCRIPT, "-p", sys.executable, "test_env"]
print "Running", args
subprocess.check_call(args)
sh_script = """
set -e
. test_env/bin/activate
set -ux
python -c 'import __future__'
python -c 'import sys; print sys.executable'
pip install bcrypt==1.1.0
python -c 'import bcrypt; assert bcrypt.__version__ == "1.1.0"; assert bcrypt.hashpw("password1", "$2a$12$0123456789012345678901").endswith("I1hdtg4K"); print "bcrypt seems to work"'
""".strip()
# print sh_script
subprocess.check_call(["sh", "-c", sh_script])
......@@ -21,9 +21,12 @@ set -e
set -ux
python -c 'import __future__'
python -c 'import sys; print sys.executable'
pip install six==1.9.0 cffi==0.9.2
python -c 'import six; print six.__version__'
pip install bcrypt==1.1.0
python -c 'import bcrypt; assert bcrypt.__version__ == "1.1.0"; assert bcrypt.hashpw("password1", "$2a$12$0123456789012345678901").endswith("I1hdtg4K"); print "bcrypt seems to work"'
""".strip()
# print sh_script
subprocess.check_call(["sh", "-c", sh_script])
print
print "PASSED"
class C(object):
def __eq__(self, rhs):
print "eq", type(self), type(rhs)
return False
def __lt__(self, rhs):
print "lt", type(self), type(rhs)
return False
def __gt__(self, rhs):
print "gt", type(self), type(rhs)
return True
class D(C):
def __cmp__(self, rhs):
print "cmp", type(self), type(rhs)
return 0
l = [C(), D()]
for lhs in l:
for rhs in l:
r = cmp(lhs, rhs)
print type(lhs), type(rhs), r
......@@ -4,6 +4,7 @@ def f(a, b=2, *args, **kw):
c = f.func_code
print c.co_argcount
print c.co_varnames
print c.co_firstlineno
print hex(c.co_flags & 0x0c)
def f(l=[]):
......@@ -15,3 +16,4 @@ f()
def f():
pass
print f.func_defaults
print f.func_code.co_firstlineno
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