Commit eb3a4794 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #532 from undingen/ncrypt

Add PyClass_New, PyMethod_New, capifunc.__module__, missing gc handles, file.truncate
parents c02424de 60658569
......@@ -92,6 +92,7 @@
#define HAVE_ERRNO_H 1
#define HAVE_FCNTL_H 1
#define HAVE_FTIME 1
#define HAVE_FTRUNCATE 1
#define HAVE_GRP_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_LANGINFO_H 1
......
......@@ -412,8 +412,8 @@ extern "C" PyObject* Py_InitModule4(const char* name, PyMethodDef* methods, cons
while (methods && methods->ml_name) {
RELEASE_ASSERT((methods->ml_flags & (~(METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O))) == 0, "%d",
methods->ml_flags);
module->giveAttr(methods->ml_name,
new BoxedCApiFunction(methods->ml_flags, passthrough, methods->ml_name, methods->ml_meth));
module->giveAttr(methods->ml_name, new BoxedCApiFunction(methods->ml_flags, passthrough, methods->ml_name,
methods->ml_meth, boxString(name)));
methods++;
}
......
......@@ -44,8 +44,11 @@ private:
PyCFunction func;
public:
BoxedCApiFunction(int ml_flags, Box* passthrough, const char* name, PyCFunction func)
: ml_flags(ml_flags), passthrough(passthrough), name(name), func(func) {}
Box* module;
public:
BoxedCApiFunction(int ml_flags, Box* passthrough, const char* name, PyCFunction func, Box* module = NULL)
: ml_flags(ml_flags), passthrough(passthrough), name(name), func(func), module(module) {}
DEFAULT_CLASS(capifunc_cls);
......@@ -112,6 +115,15 @@ public:
static Box* callInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names);
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == capifunc_cls);
BoxedCApiFunction* o = static_cast<BoxedCApiFunction*>(_o);
boxGCHandler(v, o);
v->visit(o->passthrough);
v->visit(o->module);
}
};
class BoxedWrapperDescriptor : public Box {
......@@ -126,6 +138,14 @@ public:
static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner);
static Box* __call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args);
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == wrapperdescr_cls);
BoxedWrapperDescriptor* o = static_cast<BoxedWrapperDescriptor*>(_o);
boxGCHandler(v, o);
v->visit(o->type);
}
};
class BoxedWrapperObject : public Box {
......@@ -162,6 +182,14 @@ public:
assert(rtn && "should have set + thrown an exception!");
return rtn;
}
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == wrapperobject_cls);
BoxedWrapperObject* o = static_cast<BoxedWrapperObject*>(_o);
boxGCHandler(v, o);
v->visit(o->obj);
}
};
class BoxedMethodDescriptor : public Box {
......@@ -193,6 +221,14 @@ public:
}
static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args);
static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == method_cls);
BoxedMethodDescriptor* o = static_cast<BoxedMethodDescriptor*>(_o);
boxGCHandler(v, o);
v->visit(o->type);
}
};
} // namespace pyston
......
......@@ -1064,8 +1064,7 @@ std::string PystonSourceReader::get_line() {
break;
line.push_back(c);
} while (c != '\n' && c != '\x0c');
if (!eof())
++line_number;
++line_number;
return line;
}
......
......@@ -1196,10 +1196,9 @@ extern "C" PyObject* Py_FindMethod(PyMethodDef* methods, PyObject* self, const c
}
extern "C" PyObject* PyCFunction_NewEx(PyMethodDef* ml, PyObject* self, PyObject* module) noexcept {
RELEASE_ASSERT(module == NULL, "not implemented");
assert((ml->ml_flags & (~(METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O))) == 0);
return new BoxedCApiFunction(ml->ml_flags, self, ml->ml_name, ml->ml_meth);
return new BoxedCApiFunction(ml->ml_flags, self, ml->ml_name, ml->ml_meth, module);
}
extern "C" PyCFunction PyCFunction_GetFunction(PyObject* op) noexcept {
......@@ -1414,6 +1413,8 @@ void setupCAPI() {
capifunc_cls->giveAttr("__call__", capi_call);
capifunc_cls->giveAttr("__name__",
new (pyston_getset_cls) BoxedGetsetDescriptor(BoxedCApiFunction::getname, NULL, NULL));
capifunc_cls->giveAttr(
"__module__", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedCApiFunction, module)));
capifunc_cls->freeze();
......
......@@ -609,6 +609,33 @@ Box* instanceCall(Box* _inst, Box* _args, Box* _kwargs) {
return runtimeCall(call_func, ArgPassSpec(0, 0, true, true), _args, _kwargs, NULL, NULL, NULL);
}
extern "C" PyObject* PyClass_New(PyObject* bases, PyObject* dict, PyObject* name) noexcept {
try {
if (name == NULL || !PyString_Check(name)) {
PyErr_SetString(PyExc_TypeError, "PyClass_New: name must be a string");
return NULL;
}
if (dict == NULL || !PyDict_Check(dict)) {
PyErr_SetString(PyExc_TypeError, "PyClass_New: dict must be a dictionary");
return NULL;
}
return runtimeCall(classobj_cls, ArgPassSpec(3), name, bases, dict, NULL, NULL);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
extern "C" PyObject* PyMethod_New(PyObject* func, PyObject* self, PyObject* klass) noexcept {
try {
return new BoxedInstanceMethod(self, func, klass);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
void setupClassobj() {
classobj_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedClassobj::gcHandler,
offsetof(BoxedClassobj, attrs), 0, sizeof(BoxedClassobj), false, "classobj");
......
......@@ -1576,6 +1576,113 @@ static PyObject* get_closed(BoxedFile* f, void* closure) noexcept {
return PyBool_FromLong((long)(f->f_fp == 0));
}
static PyObject* file_truncate(BoxedFile* f, PyObject* args) {
Py_off_t newsize;
PyObject* newsizeobj = NULL;
Py_off_t initialpos;
int ret;
if (f->f_fp == NULL)
return err_closed();
if (!f->writable)
return err_mode("writing");
if (!PyArg_UnpackTuple(args, "truncate", 0, 1, &newsizeobj))
return NULL;
/* Get current file position. If the file happens to be open for
* update and the last operation was an input operation, C doesn't
* define what the later fflush() will do, but we promise truncate()
* won't change the current position (and fflush() *does* change it
* then at least on Windows). The easiest thing is to capture
* current pos now and seek back to it at the end.
*/
FILE_BEGIN_ALLOW_THREADS(f)
errno = 0;
initialpos = _portable_ftell(f->f_fp);
FILE_END_ALLOW_THREADS(f)
if (initialpos == -1)
goto onioerror;
/* Set newsize to current postion if newsizeobj NULL, else to the
* specified value.
*/
if (newsizeobj != NULL) {
#if !defined(HAVE_LARGEFILE_SUPPORT)
newsize = PyInt_AsLong(newsizeobj);
#else
newsize = PyLong_Check(newsizeobj) ? PyLong_AsLongLong(newsizeobj) : PyInt_AsLong(newsizeobj);
#endif
if (PyErr_Occurred())
return NULL;
} else /* default to current position */
newsize = initialpos;
/* Flush the stream. We're mixing stream-level I/O with lower-level
* I/O, and a flush may be necessary to synch both platform views
* of the current file state.
*/
FILE_BEGIN_ALLOW_THREADS(f)
errno = 0;
ret = fflush(f->f_fp);
FILE_END_ALLOW_THREADS(f)
if (ret != 0)
goto onioerror;
#ifdef MS_WINDOWS
/* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
so don't even try using it. */
{
HANDLE hFile;
/* Have to move current pos to desired endpoint on Windows. */
FILE_BEGIN_ALLOW_THREADS(f)
errno = 0;
ret = _portable_fseek(f->f_fp, newsize, SEEK_SET) != 0;
FILE_END_ALLOW_THREADS(f)
if (ret)
goto onioerror;
/* Truncate. Note that this may grow the file! */
FILE_BEGIN_ALLOW_THREADS(f)
errno = 0;
hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));
ret = hFile == (HANDLE)-1;
if (ret == 0) {
ret = SetEndOfFile(hFile) == 0;
if (ret)
errno = EACCES;
}
FILE_END_ALLOW_THREADS(f)
if (ret)
goto onioerror;
}
#else
FILE_BEGIN_ALLOW_THREADS(f)
errno = 0;
ret = ftruncate(fileno(f->f_fp), newsize);
FILE_END_ALLOW_THREADS(f)
if (ret != 0)
goto onioerror;
#endif /* !MS_WINDOWS */
/* Restore original file position. */
FILE_BEGIN_ALLOW_THREADS(f)
errno = 0;
ret = _portable_fseek(f->f_fp, initialpos, SEEK_SET) != 0;
FILE_END_ALLOW_THREADS(f)
if (ret)
goto onioerror;
Py_INCREF(Py_None);
return Py_None;
onioerror:
PyErr_SetFromErrno(PyExc_IOError);
clearerr(f->f_fp);
return NULL;
}
PyDoc_STRVAR(seek_doc, "seek(offset[, whence]) -> None. Move to new file position.\n"
"\n"
"Argument offset is a byte count. Optional argument whence defaults to\n"
......@@ -1588,6 +1695,10 @@ PyDoc_STRVAR(seek_doc, "seek(offset[, whence]) -> None. Move to new file positi
"\n"
"Note that not all file objects are seekable.");
PyDoc_STRVAR(truncate_doc, "truncate([size]) -> None. Truncate the file to at most size bytes.\n"
"\n"
"Size defaults to the current file position, as returned by tell().");
PyDoc_STRVAR(readlines_doc, "readlines([size]) -> list of strings, each a line from the file.\n"
"\n"
"Call readline() repeatedly and return a list of the lines so read.\n"
......@@ -1598,6 +1709,7 @@ PyDoc_STRVAR(isatty_doc, "isatty() -> true or false. True if the file is connec
static PyMethodDef file_methods[] = {
{ "seek", (PyCFunction)file_seek, METH_VARARGS, seek_doc },
{ "truncate", (PyCFunction)file_truncate, METH_VARARGS, truncate_doc },
{ "readlines", (PyCFunction)file_readlines, METH_VARARGS, readlines_doc },
{ "writelines", (PyCFunction)file_writelines, METH_O, NULL },
{ "isatty", (PyCFunction)file_isatty, METH_NOARGS, isatty_doc },
......
......@@ -936,6 +936,9 @@ Box* instancemethodGet(BoxedInstanceMethod* self, Box* obj, Box* type) {
return self;
}
if (obj == None)
obj = NULL;
return new BoxedInstanceMethod(obj, self->func, self->im_class);
}
......@@ -2235,14 +2238,17 @@ void setupRuntime() {
static_cast<BoxedString*>(boxStrConstant("module")));
member_descriptor_cls = new (0) BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMemberDescriptor), false,
static_cast<BoxedString*>(boxStrConstant("member_descriptor")));
capifunc_cls = new (0) BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedCApiFunction), false,
static_cast<BoxedString*>(boxStrConstant("capifunc")));
method_cls = new (0) BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMethodDescriptor), false,
static_cast<BoxedString*>(boxStrConstant("method")));
wrapperobject_cls = new (0) BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedWrapperObject), false,
static_cast<BoxedString*>(boxStrConstant("method-wrapper")));
wrapperdescr_cls = new (0) BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedWrapperDescriptor), false,
static_cast<BoxedString*>(boxStrConstant("wrapper_descriptor")));
capifunc_cls = new (0) BoxedHeapClass(object_cls, BoxedCApiFunction::gcHandler, 0, 0, sizeof(BoxedCApiFunction),
false, static_cast<BoxedString*>(boxStrConstant("capifunc")));
method_cls = new (0)
BoxedHeapClass(object_cls, BoxedMethodDescriptor::gcHandler, 0, 0, sizeof(BoxedMethodDescriptor), false,
static_cast<BoxedString*>(boxStrConstant("method")));
wrapperobject_cls = new (0)
BoxedHeapClass(object_cls, BoxedWrapperObject::gcHandler, 0, 0, sizeof(BoxedWrapperObject), false,
static_cast<BoxedString*>(boxStrConstant("method-wrapper")));
wrapperdescr_cls = new (0)
BoxedHeapClass(object_cls, BoxedWrapperDescriptor::gcHandler, 0, 0, sizeof(BoxedWrapperDescriptor), false,
static_cast<BoxedString*>(boxStrConstant("wrapper_descriptor")));
EmptyString = boxStrConstant("");
gc::registerPermanentRoot(EmptyString);
......
......@@ -92,4 +92,10 @@ try:
except Exception as e:
print e
with open(fn, "w") as f:
f.write("123456");
f.truncate(3)
with open(fn, "r") as f:
print f.read();
print sys.stdout.closed
......@@ -8,3 +8,5 @@ time.clock()
print time.timezone
print long(time.mktime(time.localtime(1020)))
print time.sleep.__module__
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