Commit 5415879c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #480 from kmod/gflags

run gflags unittests
parents 610be9f5 6ec39445
......@@ -16,3 +16,6 @@
[submodule "test/integration/pycrypto"]
path = test/integration/pycrypto
url = https://github.com/dlitz/pycrypto.git
[submodule "test/integration/gflags"]
path = test/integration/gflags
url = https://github.com/google/python-gflags
......@@ -356,6 +356,7 @@ STDMODULE_SRCS := \
_sqlite/row.c \
_sqlite/statement.c \
_sqlite/util.c \
stropmodule.c \
$(EXTRA_STDMODULE_SRCS)
STDOBJECT_SRCS := \
......@@ -383,6 +384,7 @@ STDPYTHON_SRCS := \
formatter_unicode.c \
structmember.c \
marshal.c \
mystrtoul.c \
$(EXTRA_STDPYTHON_SRCS)
STDPARSER_SRCS := \
......@@ -528,6 +530,7 @@ quick_check:
$(MAKE) check_format
$(MAKE) unittests
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_dbg -j$(TEST_THREADS) -a=-S -k --order-by-mtime $(TESTS_DIR) $(ARGS)
$(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_dbg -j$(TEST_THREADS) -a=-S -k --exit-code-only --skip-failing $(TEST_DIR)/cpython $(ARGS)
Makefile.local:
echo "Creating default Makefile.local"
......
......@@ -62,6 +62,7 @@ file(GLOB_RECURSE STDMODULE_SRCS Modules
socketmodule.c
statement.c
stringio.c
stropmodule.c
textio.c
timemodule.c
unicodedata.c
......@@ -94,6 +95,7 @@ file(GLOB_RECURSE STDPYTHON_SRCS Python
formatter_unicode.c
getargs.c
marshal.c
mystrtoul.c
pyctype.c
pystrtod.c
structmember.c
......
......@@ -636,9 +636,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
is an iterator, this returns itself. */
#define PyIter_Check(obj) \
(PyType_HasFeature((obj)->ob_type, Py_TPFLAGS_HAVE_ITER) && \
(obj)->ob_type->tp_iternext != NULL && \
(obj)->ob_type->tp_iternext != &_PyObject_NextNotImplemented)
(PyType_HasFeature(Py_TYPE((obj)), Py_TPFLAGS_HAVE_ITER) && \
Py_TYPE((obj))->tp_iternext != NULL && \
Py_TYPE((obj))->tp_iternext != &_PyObject_NextNotImplemented)
PyAPI_FUNC(PyObject *) PyIter_Next(PyObject *) PYSTON_NOEXCEPT;
/* Takes an iterator object and calls its tp_iternext slot,
......
......@@ -124,6 +124,7 @@
#define HAVE_UNISTD_H 1
#define HAVE_UTIME_H 1
#define HAVE_WCHAR_H 1
#define HAVE_PUTENV 1
// Added this for some Pyston modifications:
#define MAX_PYSTRING_SIZE (PY_SSIZE_T_MAX/2 - (1<<20))
......
......@@ -9451,7 +9451,7 @@ INITFUNC(void)
#ifdef HAVE_PUTENV
if (posix_putenv_garbage == NULL)
posix_putenv_garbage = PyDict_New();
posix_putenv_garbage = PyGC_AddRoot(PyDict_New());
#endif
if (!initialized) {
......
#include "Python.h"
#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
#define _SGI_MP_SOURCE
#endif
/* strtol and strtoul, renamed to avoid conflicts */
#include <ctype.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
/* Static overflow check values for bases 2 through 36.
* smallmax[base] is the largest unsigned long i such that
* i * base doesn't overflow unsigned long.
*/
static unsigned long smallmax[] = {
0, /* bases 0 and 1 are invalid */
0,
ULONG_MAX / 2,
ULONG_MAX / 3,
ULONG_MAX / 4,
ULONG_MAX / 5,
ULONG_MAX / 6,
ULONG_MAX / 7,
ULONG_MAX / 8,
ULONG_MAX / 9,
ULONG_MAX / 10,
ULONG_MAX / 11,
ULONG_MAX / 12,
ULONG_MAX / 13,
ULONG_MAX / 14,
ULONG_MAX / 15,
ULONG_MAX / 16,
ULONG_MAX / 17,
ULONG_MAX / 18,
ULONG_MAX / 19,
ULONG_MAX / 20,
ULONG_MAX / 21,
ULONG_MAX / 22,
ULONG_MAX / 23,
ULONG_MAX / 24,
ULONG_MAX / 25,
ULONG_MAX / 26,
ULONG_MAX / 27,
ULONG_MAX / 28,
ULONG_MAX / 29,
ULONG_MAX / 30,
ULONG_MAX / 31,
ULONG_MAX / 32,
ULONG_MAX / 33,
ULONG_MAX / 34,
ULONG_MAX / 35,
ULONG_MAX / 36,
};
/* maximum digits that can't ever overflow for bases 2 through 36,
* calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].
* Note that this is pessimistic if sizeof(long) > 4.
*/
#if SIZEOF_LONG == 4
static int digitlimit[] = {
0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
#elif SIZEOF_LONG == 8
/* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */
static int digitlimit[] = {
0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */
19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */
14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */
13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */
#else
#error "Need table for SIZEOF_LONG"
#endif
/*
** strtoul
** This is a general purpose routine for converting
** an ascii string to an integer in an arbitrary base.
** Leading white space is ignored. If 'base' is zero
** it looks for a leading 0, 0b, 0B, 0o, 0O, 0x or 0X
** to tell which base. If these are absent it defaults
** to 10. Base must be 0 or between 2 and 36 (inclusive).
** If 'ptr' is non-NULL it will contain a pointer to
** the end of the scan.
** Errors due to bad pointers will probably result in
** exceptions - we don't check for them.
*/
unsigned long
PyOS_strtoul(register char *str, char **ptr, int base)
{
register unsigned long result = 0; /* return value of the function */
register int c; /* current input character */
register int ovlimit; /* required digits to overflow */
/* skip leading white space */
while (*str && isspace(Py_CHARMASK(*str)))
++str;
/* check for leading 0 or 0x for auto-base or base 16 */
switch (base) {
case 0: /* look for leading 0, 0b, 0o or 0x */
if (*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
/* there must be at least one digit after 0x */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 16;
} else if (*str == 'o' || *str == 'O') {
/* there must be at least one digit after 0o */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 8;
} else if (*str == 'b' || *str == 'B') {
/* there must be at least one digit after 0b */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 2;
} else {
base = 8;
}
}
else
base = 10;
break;
case 2: /* skip leading 0b or 0B */
if (*str == '0') {
++str;
if (*str == 'b' || *str == 'B') {
/* there must be at least one digit after 0b */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
case 8: /* skip leading 0o or 0O */
if (*str == '0') {
++str;
if (*str == 'o' || *str == 'O') {
/* there must be at least one digit after 0o */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
case 16: /* skip leading 0x or 0X */
if (*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
/* there must be at least one digit after 0x */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
}
/* catch silly bases */
if (base < 2 || base > 36) {
if (ptr)
*ptr = str;
return 0;
}
/* skip leading zeroes */
while (*str == '0')
++str;
/* base is guaranteed to be in [2, 36] at this point */
ovlimit = digitlimit[base];
/* do the conversion until non-digit character encountered */
while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
if (ovlimit > 0) /* no overflow check required */
result = result * base + c;
else { /* requires overflow check */
register unsigned long temp_result;
if (ovlimit < 0) /* guaranteed overflow */
goto overflowed;
/* there could be an overflow */
/* check overflow just from shifting */
if (result > smallmax[base])
goto overflowed;
result *= base;
/* check overflow from the digit's value */
temp_result = result + c;
if (temp_result < result)
goto overflowed;
result = temp_result;
}
++str;
--ovlimit;
}
/* set pointer to point to the last character scanned */
if (ptr)
*ptr = str;
return result;
overflowed:
if (ptr) {
/* spool through remaining digit characters */
while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
++str;
*ptr = str;
}
errno = ERANGE;
return (unsigned long)-1;
}
/* Checking for overflow in PyOS_strtol is a PITA; see comments
* about PY_ABS_LONG_MIN in longobject.c.
*/
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
long
PyOS_strtol(char *str, char **ptr, int base)
{
long result;
unsigned long uresult;
char sign;
while (*str && isspace(Py_CHARMASK(*str)))
str++;
sign = *str;
if (sign == '+' || sign == '-')
str++;
uresult = PyOS_strtoul(str, ptr, base);
if (uresult <= (unsigned long)LONG_MAX) {
result = (long)uresult;
if (sign == '-')
result = -result;
}
else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
result = LONG_MIN;
}
else {
errno = ERANGE;
result = LONG_MAX;
}
return result;
}
......@@ -346,6 +346,16 @@ public:
abort();
}
Box* getGlobalsDict() {
Box* globals = getGlobals();
if (!globals)
return NULL;
if (isSubclass(globals->cls, module_cls))
return globals->getAttrWrapper();
return globals;
}
FrameInfo* getFrameInfo() {
if (id.type == PythonFrameId::COMPILED) {
CompiledFunction* cf = getCF();
......@@ -591,13 +601,7 @@ Box* getGlobals() {
}
Box* getGlobalsDict() {
Box* globals = getGlobals();
if (!globals)
return NULL;
if (isSubclass(globals->cls, module_cls))
return globals->getAttrWrapper();
return globals;
return getTopPythonFrame()->getGlobalsDict();
}
BoxedModule* getCurrentModule() {
......@@ -890,6 +894,10 @@ CompiledFunction* PythonFrameIterator::getCF() {
return impl->getCF();
}
Box* PythonFrameIterator::getGlobalsDict() {
return impl->getGlobalsDict();
}
FrameInfo* PythonFrameIterator::getFrameInfo() {
return impl->getFrameInfo();
}
......@@ -907,6 +915,29 @@ PythonFrameIterator PythonFrameIterator::getCurrentVersion() {
return PythonFrameIterator(std::move(rtn));
}
PythonFrameIterator PythonFrameIterator::back() {
// TODO this is ineffecient: the iterator is no longer valid for libunwind iteration, so
// we have to do a full stack crawl again.
// Hopefully examination of f_back is uncommon.
std::unique_ptr<PythonFrameIteratorImpl> rtn(nullptr);
auto& impl = this->impl;
bool found = false;
unwindPythonStack([&](std::unique_ptr<PythonFrameIteratorImpl> frame_iter) {
if (found) {
rtn = std::move(frame_iter);
return true;
}
if (frame_iter->pointsToTheSameAs(*impl.get()))
found = true;
return false;
});
RELEASE_ASSERT(found, "this wasn't a valid frame?");
return PythonFrameIterator(std::move(rtn));
}
llvm::JITEventListener* makeTracebacksListener() {
return new TracebacksEventListener();
}
......
......@@ -53,15 +53,20 @@ public:
bool exists() { return impl.get() != NULL; }
std::unique_ptr<ExecutionPoint> getExecutionPoint();
Box* fastLocalsToBoxedLocals();
Box* getGlobalsDict();
// Gets the "current version" of this frame: if the frame has executed since
// the iterator was obtained, the methods may return old values. This returns
// an updated copy that returns the updated values.
// The "current version" will live at the same stack location, but any other
// similarities need to be verified by the caller.
// similarities need to be verified by the caller, ie it is up to the caller
// to determine that we didn't leave and reenter the stack frame.
// This function can only be called from the thread that created this object.
PythonFrameIterator getCurrentVersion();
// Assuming this is a valid frame iterator, return the next frame back (ie older).
PythonFrameIterator back();
PythonFrameIterator(PythonFrameIterator&& rhs);
void operator=(PythonFrameIterator&& rhs);
PythonFrameIterator(std::unique_ptr<PythonFrameIteratorImpl> impl);
......
......@@ -333,6 +333,34 @@ Box* instanceSetattr(Box* _inst, Box* _attr, Box* value) {
return None;
}
Box* instanceDelattr(Box* _inst, Box* _attr) {
RELEASE_ASSERT(_inst->cls == instance_cls, "");
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
RELEASE_ASSERT(_attr->cls == str_cls, "");
BoxedString* attr = static_cast<BoxedString*>(_attr);
// These are special cases in CPython as well:
if (attr->s[0] == '_' && attr->s[1] == '_') {
if (attr->s == "__dict__")
raiseExcHelper(TypeError, "__dict__ must be set to a dictionary");
if (attr->s == "__class__")
raiseExcHelper(TypeError, "__class__ must be set to a class");
}
static const std::string delattr_str("__delattr__");
Box* delattr = classLookup(inst->inst_cls, delattr_str);
if (delattr) {
delattr = processDescriptor(delattr, inst, inst->inst_cls);
return runtimeCall(delattr, ArgPassSpec(1), _attr, NULL, NULL, NULL, NULL);
}
_inst->delattr(attr->s, NULL);
return None;
}
static int instance_setattro(Box* cls, Box* attr, Box* value) noexcept {
try {
if (value) {
......@@ -488,6 +516,45 @@ static Box* instanceHash(BoxedInstance* inst) {
}
}
static Box* instanceIter(BoxedInstance* self) {
assert(self->cls == instance_cls);
PyObject* func;
if ((func = _instanceGetattribute(self, boxStrConstant("__iter__"), false)) != NULL) {
PyObject* res = PyEval_CallObject(func, (PyObject*)NULL);
if (!res)
throwCAPIException();
if (!PyIter_Check(res))
raiseExcHelper(TypeError, "__iter__ returned non-iterator of type '%.100s'", res->cls->tp_name);
return res;
}
if ((func = _instanceGetattribute(self, boxStrConstant("__getitem__"), false)) == NULL) {
raiseExcHelper(TypeError, "iteration over non-sequence");
}
Box* r = PySeqIter_New((PyObject*)self);
if (!r)
throwCAPIException();
return r;
}
static Box* instanceNext(BoxedInstance* inst) {
assert(inst->cls == instance_cls);
Box* next_func = _instanceGetattribute(inst, boxStrConstant("next"), false);
if (!next_func) {
// not 100% sure why this is a different error:
raiseExcHelper(TypeError, "instance has no next() method");
}
Box* r = runtimeCall(next_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
return r;
}
static PyObject* instance_index(PyObject* self) noexcept {
PyObject* func, *res;
/*
......@@ -569,6 +636,7 @@ void setupClassobj() {
instance_cls->giveAttr("__getattribute__",
new BoxedFunction(boxRTFunction((void*)instanceGetattribute, UNKNOWN, 2)));
instance_cls->giveAttr("__setattr__", new BoxedFunction(boxRTFunction((void*)instanceSetattr, UNKNOWN, 3)));
instance_cls->giveAttr("__delattr__", new BoxedFunction(boxRTFunction((void*)instanceDelattr, UNKNOWN, 2)));
instance_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)instanceStr, UNKNOWN, 1)));
instance_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)instanceRepr, UNKNOWN, 1)));
instance_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)instanceNonzero, UNKNOWN, 1)));
......@@ -578,6 +646,8 @@ void setupClassobj() {
instance_cls->giveAttr("__delitem__", new BoxedFunction(boxRTFunction((void*)instanceDelitem, UNKNOWN, 2)));
instance_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)instanceContains, UNKNOWN, 2)));
instance_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)instanceHash, UNKNOWN, 1)));
instance_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)instanceIter, UNKNOWN, 1)));
instance_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)instanceNext, UNKNOWN, 1)));
instance_cls->giveAttr("__call__",
new BoxedFunction(boxRTFunction((void*)instanceCall, UNKNOWN, 1, 0, true, true)));
instance_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)instanceEq, UNKNOWN, 2)));
......
......@@ -1647,6 +1647,8 @@ void setupFile() {
file_cls->giveAttr("tell", new BoxedFunction(boxRTFunction((void*)fileTell, UNKNOWN, 1)));
file_cls->giveAttr("softspace",
new BoxedMemberDescriptor(BoxedMemberDescriptor::INT, offsetof(BoxedFile, f_softspace), false));
file_cls->giveAttr("name",
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedFile, f_name), true));
file_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)fileNew, UNKNOWN, 4, 2, false, false),
{ boxStrConstant("r"), boxInt(-1) }));
......
......@@ -27,10 +27,12 @@ BoxedClass* frame_cls;
// - breaks c++ exceptions
// - we never free the trampolines
class BoxedFrame : public Box {
public:
BoxedFrame(PythonFrameIterator&& it) __attribute__((visibility("default")))
private:
// Call boxFrame to get a BoxedFrame object.
BoxedFrame(PythonFrameIterator it) __attribute__((visibility("default")))
: it(std::move(it)), thread_id(PyThread_get_thread_ident()) {}
public:
PythonFrameIterator it;
long thread_id;
......@@ -105,6 +107,16 @@ public:
return f->_globals;
}
static Box* back(Box* obj, void*) {
auto f = static_cast<BoxedFrame*>(obj);
f->update();
PythonFrameIterator it = f->it.back();
if (!it.exists())
return None;
return BoxedFrame::boxFrame(std::move(it));
}
static Box* lineno(Box* obj, void*) {
auto f = static_cast<BoxedFrame*>(obj);
f->update();
......@@ -113,6 +125,19 @@ public:
}
DEFAULT_CLASS(frame_cls);
static Box* boxFrame(PythonFrameIterator it) {
FrameInfo* fi = it.getFrameInfo();
if (fi->frame_obj == NULL) {
auto cf = it.getCF();
Box* globals = it.getGlobalsDict();
BoxedFrame* f = fi->frame_obj = new BoxedFrame(std::move(it));
f->_globals = globals;
f->_code = codeForCLFunction(cf->clfunc);
}
return fi->frame_obj;
}
};
Box* getFrame(int depth) {
......@@ -120,19 +145,9 @@ Box* getFrame(int depth) {
if (!it.exists())
return NULL;
FrameInfo* fi = it.getFrameInfo();
if (fi->frame_obj == NULL) {
auto cf = it.getCF();
BoxedFrame* f = fi->frame_obj = new BoxedFrame(std::move(it));
assert(cf->clfunc->source->scoping->areGlobalsFromModule());
f->_globals = cf->clfunc->source->parent_module->getAttrWrapper();
f->_code = codeForCLFunction(cf->clfunc);
}
return fi->frame_obj;
return BoxedFrame::boxFrame(std::move(it));
}
void setupFrame() {
frame_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedFrame::gchandler, 0, 0, sizeof(BoxedFrame), false,
"frame");
......@@ -143,6 +158,7 @@ void setupFrame() {
frame_cls->giveAttr("f_lineno", new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedFrame::lineno, NULL, NULL));
frame_cls->giveAttr("f_globals", new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedFrame::globals, NULL, NULL));
frame_cls->giveAttr("f_back", new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedFrame::back, NULL, NULL));
frame_cls->freeze();
}
......
......@@ -1103,6 +1103,8 @@ void setupList() {
"index", new BoxedFunction(boxRTFunction((void*)listIndex, BOXED_INT, 4, 2, false, false), { NULL, NULL }));
list_cls->giveAttr("remove", new BoxedFunction(boxRTFunction((void*)listRemove, NONE, 2)));
list_cls->giveAttr("reverse", new BoxedFunction(boxRTFunction((void*)listReverse, NONE, 1)));
list_cls->giveAttr("__hash__", None);
list_cls->freeze();
CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1);
......
......@@ -35,6 +35,27 @@ namespace pyston {
BoxedClass* long_cls;
/* Table of digit values for 8-bit string -> integer conversion.
* '0' maps to 0, ..., '9' maps to 9.
* 'a' and 'A' map to 10, ..., 'z' and 'Z' map to 35.
* All other indices map to 37.
* Note that when converting a base B string, a char c is a legitimate
* base B digit iff _PyLong_DigitValue[Py_CHARMASK(c)] < B.
*/
extern "C" {
int _PyLong_DigitValue[256] = {
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
37, 37, 37, 37, 37, 37, 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 37, 37, 37, 37, 37, 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
};
}
#define IS_LITTLE_ENDIAN (int)*(unsigned char*)&one
#define PY_ABS_LLONG_MIN (0 - (unsigned PY_LONG_LONG)PY_LLONG_MIN)
......
......@@ -320,13 +320,10 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
tp_basicsize = instance_size;
tp_weaklistoffset = weaklist_offset;
tp_flags |= Py_TPFLAGS_DEFAULT_EXTERNAL;
tp_flags |= Py_TPFLAGS_CHECKTYPES;
tp_flags |= Py_TPFLAGS_BASETYPE;
tp_flags |= Py_TPFLAGS_HAVE_CLASS;
tp_flags |= Py_TPFLAGS_HAVE_GC;
tp_flags |= Py_TPFLAGS_HAVE_WEAKREFS;
tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE;
tp_flags |= Py_TPFLAGS_HAVE_INDEX;
if (base && (base->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER))
tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
......@@ -2113,6 +2110,10 @@ extern "C" BoxedInt* hash(Box* obj) {
return static_cast<BoxedInt*>(boxInt((i64)obj));
}
if (hash == None) {
raiseExcHelper(TypeError, "unhashable type: '%s'", obj->cls->tp_name);
}
Box* rtn = runtimeCall0(hash, ArgPassSpec(0));
if (rtn->cls != int_cls) {
raiseExcHelper(TypeError, "an integer is required");
......
......@@ -78,6 +78,7 @@ extern "C" void init_csv();
extern "C" void init_ssl();
extern "C" void init_sqlite3();
extern "C" void PyMarshal_Init();
extern "C" void initstrop();
namespace pyston {
......@@ -2401,6 +2402,7 @@ void setupRuntime() {
init_ssl();
init_sqlite3();
PyMarshal_Init();
initstrop();
// some additional setup to ensure weakrefs participate in our GC
BoxedClass* weakref_ref_cls = &_PyWeakref_RefType;
......
Subproject commit 1569dd1f3855abd262ea3a7741527d4413b35bc9
import glob
import subprocess, sys, os
gflags_dir = os.path.dirname(os.path.abspath(__file__)) + "/gflags"
os.chdir(gflags_dir)
env = os.environ
env["PYTHONPATH"] = "."
TESTS_DIR = "tests"
for fn in glob.glob("%s/*.py" % TESTS_DIR):
# We don't support xml.dom.minidom yet
if "helpxml_test.py" in fn:
print "Skipping", fn
continue
print "Running", fn
subprocess.check_call([sys.executable, fn])
print "-- Tests finished"
......@@ -131,3 +131,21 @@ g = {}
l = {}
exec ("a=1; print a", g, l)
print g.keys(), l.keys()
s = """
global a
a = 1
b = 2
def inner():
print sorted(globals().keys()), sorted(locals().keys())
print a
print b
print sorted(globals().keys()), sorted(locals().keys())
inner()
"""
exec s in {}
try:
exec s in {}, {}
raise Exception()
except NameError as e:
print e
......@@ -3,6 +3,7 @@ import tempfile
f = open("/dev/null")
print repr(f.read())
print repr(f.name)
f2 = file("/dev/null")
print repr(f2.read())
......
......@@ -195,3 +195,5 @@ l.sort(cmp=mycmp, key=str)
print types_seen
print l
"""
print repr(list.__hash__)
......@@ -147,9 +147,13 @@ class SetattrTest:
def __setattr__(self, attr, value):
print "setattr", attr, value
def __delattr__(self, attr):
print "delattr", attr
s = SetattrTest()
s.b = 2
print g.__dict__.items()
print s.__dict__.items()
del s.b
class MappingTest:
def __getitem__(self, key):
......@@ -245,3 +249,29 @@ class E(C, object):
print issubclass(D, C), isinstance(D(), C)
print issubclass(E, C), isinstance(E(), C)
print isinstance(E, object), isinstance(E(), object)
class SeqTest:
class Iterator:
def __init__(self):
self.n = 5
def next(self):
print "next"
if self.n <= 0:
raise StopIteration()
r = self.n
self.n -= 1
return r
def __iter__(self):
print "iter"
return SeqTest.Iterator()
m = SeqTest()
print list(m)
class OldSeqTest:
def __getitem__(self, n):
print "getitem", n
if n > 5:
raise IndexError()
return n ** 2
m = OldSeqTest()
print list(m)
......@@ -23,8 +23,13 @@ print e.strerror
print e.filename
print OSError(1, 2).filename
# This part needs sys.exc_info() and the three-arg raise statement
# try:
# os.execvp("aoeuaoeu", ['aoeuaoeu'])
# except OSError, e:
# print e
try:
os.execvp("aoeuaoeu", ['aoeuaoeu'])
except OSError, e:
print e
# Changes to os.environ should show up in subprocesses:
import subprocess
env = os.environ
env["PYTHONPATH"] = "."
subprocess.check_call("echo PYTHONPATH is $PYTHONPATH", shell=1)
import strop
print repr(strop.whitespace)
import string
print repr(string.whitespace)
print repr(string.lowercase)
print repr(string.uppercase)
all_chars = ''.join(chr(i) for i in xrange(256))
print repr(strop.lower(all_chars))
......@@ -72,3 +72,30 @@ assert sys._getframe(0).f_globals is globals()
def f5():
assert sys._getframe(0).f_globals is globals()
f5()
# A number of libraries have functions like this:
def get_main_module():
f = sys._getframe(1)
while f.f_locals is not globals():
print f.f_code.co_filename, f.f_lineno, sorted(f.f_locals.items())
f = f.f_back
print "Main module currently at:", f.f_code.co_filename, f.f_lineno
print "f_back:", f.f_back
def f6(n):
if n:
f6(n - 1)
else:
get_main_module()
f6(10)
def custom_globals():
s = """
def inner():
import sys
return sys._getframe(1).f_globals
print sorted(inner().keys())
""".strip()
exec s
exec s in {'a':1}
exec s in {'b':2}, {'c':3}
custom_globals()
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