static Box* _intNew(Box* val, Box* base) { if (isSubclass(val->cls, int_cls)) { RELEASE_ASSERT(!base, ""); BoxedInt* n = static_cast<BoxedInt*>(val); if (val->cls == int_cls) return n; return new BoxedInt(n->n); } else if (isSubclass(val->cls, str_cls)) { int base_n; if (!base) base_n = 10; else { RELEASE_ASSERT(base->cls == int_cls, ""); base_n = static_cast<BoxedInt*>(base)->n; } BoxedString* s = static_cast<BoxedString*>(val); RELEASE_ASSERT(s->size() == strlen(s->data()), ""); Box* r = PyInt_FromString(s->data(), NULL, base_n); if (!r) throwCAPIException(); return r; } else if (isSubclass(val->cls, unicode_cls)) { int base_n; if (!base) base_n = 10; else { RELEASE_ASSERT(base->cls == int_cls, ""); base_n = static_cast<BoxedInt*>(base)->n; } Box* r = PyInt_FromUnicode(PyUnicode_AS_UNICODE(val), PyUnicode_GET_SIZE(val), base_n); if (!r) throwCAPIException(); return r; } else if (val->cls == float_cls) { RELEASE_ASSERT(!base, ""); double d = static_cast<BoxedFloat*>(val)->d; return new BoxedInt(d); } else { RELEASE_ASSERT(!base, ""); static const std::string int_str("__int__"); Box* r = callattr(val, &int_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); if (!r) { fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n", getTypeName(val)); raiseExcHelper(TypeError, ""); } if (!isSubclass(r->cls, int_cls) && !isSubclass(r->cls, long_cls)) { raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name); } return r; }
static Box* setRepr(BoxedSet* self) { RELEASE_ASSERT(PyAnySet_Check(self), ""); std::vector<char> chars; int status = Py_ReprEnter((PyObject*)self); if (status != 0) { if (status < 0) throwCAPIException(); std::string ty = std::string(self->cls->tp_name); chars.insert(chars.end(), ty.begin(), ty.end()); chars.push_back('('); chars.push_back('.'); chars.push_back('.'); chars.push_back('.'); chars.push_back(')'); return boxString(llvm::StringRef(&chars[0], chars.size())); } try { std::string ty = std::string(self->cls->tp_name); chars.insert(chars.end(), ty.begin(), ty.end()); chars.push_back('('); chars.push_back('['); bool first = true; for (auto&& elt : self->s) { if (!first) { chars.push_back(','); chars.push_back(' '); } BoxedString* str = static_cast<BoxedString*>(repr(elt.value)); AUTO_DECREF(str); chars.insert(chars.end(), str->s().begin(), str->s().end()); first = false; } chars.push_back(']'); chars.push_back(')'); } catch (ExcInfo e) { Py_ReprLeave((PyObject*)self); throw e; } Py_ReprLeave((PyObject*)self); return boxString(llvm::StringRef(&chars[0], chars.size())); }
BoxedLong* _longNew(Box* val, Box* _base) { BoxedLong* rtn = new BoxedLong(); if (_base) { if (!isSubclass(_base->cls, int_cls)) raiseExcHelper(TypeError, "an integer is required"); int base = static_cast<BoxedInt*>(_base)->n; if (!isSubclass(val->cls, str_cls)) raiseExcHelper(TypeError, "long() can't convert non-string with explicit base"); BoxedString* s = static_cast<BoxedString*>(val); rtn = (BoxedLong*)PyLong_FromString(s->data(), NULL, base); checkAndThrowCAPIException(); } else { if (isSubclass(val->cls, long_cls)) { BoxedLong* l = static_cast<BoxedLong*>(val); if (val->cls == long_cls) return l; BoxedLong* rtn = new BoxedLong(); mpz_init_set(rtn->n, l->n); return rtn; } else if (isSubclass(val->cls, int_cls)) { mpz_init_set_si(rtn->n, static_cast<BoxedInt*>(val)->n); } else if (val->cls == str_cls) { llvm::StringRef s = static_cast<BoxedString*>(val)->s(); assert(s.data()[s.size()] == '\0'); int r = mpz_init_set_str(rtn->n, s.data(), 10); RELEASE_ASSERT(r == 0, ""); } else if (val->cls == float_cls) { mpz_init_set_si(rtn->n, static_cast<BoxedFloat*>(val)->d); } else { static BoxedString* long_str = static_cast<BoxedString*>(PyString_InternFromString("__long__")); Box* r = callattr(val, long_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); if (!r) { fprintf(stderr, "TypeError: long() argument must be a string or a number, not '%s'\n", getTypeName(val)); raiseExcHelper(TypeError, ""); } if (isSubclass(r->cls, int_cls)) { mpz_init_set_si(rtn->n, static_cast<BoxedInt*>(r)->n); } else if (!isSubclass(r->cls, long_cls)) { raiseExcHelper(TypeError, "__long__ returned non-long (type %s)", r->cls->tp_name); } else { return static_cast<BoxedLong*>(r); } } }
Box* superGetattribute(Box* _s, Box* _attr) { RELEASE_ASSERT(_s->cls == super_cls, ""); BoxedSuper* s = static_cast<BoxedSuper*>(_s); RELEASE_ASSERT(_attr->cls == str_cls, ""); BoxedString* attr = static_cast<BoxedString*>(_attr); bool skip = s->obj_type == NULL; if (!skip) { // Looks like __class__ is supposed to be "super", not the class of the the proxied object. skip = (attr->s() == class_str); } if (!skip) { PyObject* mro, *res, *tmp, *dict; PyTypeObject* starttype; descrgetfunc f; Py_ssize_t i, n; starttype = s->obj_type; mro = starttype->tp_mro; if (mro == NULL) n = 0; else { assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); } for (i = 0; i < n; i++) { if ((PyObject*)(s->type) == PyTuple_GET_ITEM(mro, i)) break; } i++; res = NULL; for (; i < n; i++) { tmp = PyTuple_GET_ITEM(mro, i); // Pyston change: #if 0 if (PyType_Check(tmp)) dict = ((PyTypeObject *)tmp)->tp_dict; else if (PyClass_Check(tmp)) dict = ((PyClassObject *)tmp)->cl_dict; else continue; res = PyDict_GetItem(dict, name); #endif res = tmp->getattr(attr); if (res != NULL) { // Pyston change: #if 0 Py_INCREF(res); f = Py_TYPE(res)->tp_descr_get; if (f != NULL) { tmp = f(res, /* Only pass 'obj' param if this is instance-mode sper (See SF ID #743627) */ (s->obj == (PyObject *) s->obj_type ? (PyObject *)NULL : s->obj), (PyObject *)starttype); Py_DECREF(res); res = tmp; } #endif return processDescriptor(res, (s->obj == s->obj_type ? None : s->obj), s->obj_type); } } } Box* rtn = PyObject_GenericGetAttr(s, attr); if (!rtn) throwCAPIException(); return rtn; }
/* Return the package that an import is being performed in. If globals comes from the module foo.bar.bat (not itself a package), this returns the sys.modules entry for foo.bar. If globals is from a package's __init__.py, the package's entry in sys.modules is returned, as a borrowed reference. The *name* of the returned package is returned in buf. If globals doesn't come from a package or a module in a package, or a corresponding entry is not found in sys.modules, Py_None is returned. */ static Box* getParent(Box* globals, int level, std::string& buf) { int orig_level = level; if (globals == NULL || globals == None || level == 0) return None; static BoxedString* package_str = internStringImmortal("__package__"); BoxedString* pkgname = static_cast<BoxedString*>(getFromGlobals(globals, package_str)); if (pkgname != NULL && pkgname != None) { /* __package__ is set, so use it */ if (pkgname->cls != str_cls) { raiseExcHelper(ValueError, "__package__ set to non-string"); } size_t len = pkgname->size(); if (len == 0) { if (level > 0) { raiseExcHelper(ValueError, "Attempted relative import in non-package"); } return None; } if (len > PATH_MAX) { raiseExcHelper(ValueError, "Package name too long"); } buf += pkgname->s(); } else { static BoxedString* name_str = internStringImmortal("__name__"); /* __package__ not set, so figure it out and set it */ BoxedString* modname = static_cast<BoxedString*>(getFromGlobals(globals, name_str)); if (modname == NULL || modname->cls != str_cls) return None; static BoxedString* path_str = internStringImmortal("__path__"); Box* modpath = getFromGlobals(globals, path_str); if (modpath != NULL) { /* __path__ is set, so modname is already the package name */ if (modname->size() > PATH_MAX) { raiseExcHelper(ValueError, "Module name too long"); } buf += modname->s(); setGlobal(globals, package_str, modname); } else { /* Normal module, so work out the package name if any */ size_t lastdot = modname->s().rfind('.'); if (lastdot == std::string::npos && level > 0) { raiseExcHelper(ValueError, "Attempted relative import in non-package"); } if (lastdot == std::string::npos) { setGlobal(globals, package_str, None); return None; } if (lastdot >= PATH_MAX) { raiseExcHelper(ValueError, "Module name too long"); } buf = std::string(modname->s(), 0, lastdot); setGlobal(globals, package_str, boxString(buf)); } } size_t dot = buf.size() - 1; while (--level > 0) { dot = buf.rfind('.', dot); if (dot == std::string::npos) { raiseExcHelper(ValueError, "Attempted relative import beyond toplevel package"); } dot--; } buf = std::string(buf, 0, dot + 1); BoxedDict* sys_modules = getSysModulesDict(); Box* boxed_name = boxString(buf); Box* parent = sys_modules->d.find(boxed_name) != sys_modules->d.end() ? sys_modules->d[boxed_name] : NULL; if (parent == NULL) { if (orig_level < 1) { printf("Warning: Parent module '%.200s' not found " "while handling absolute import\n", buf.c_str()); } else { raiseExcHelper(SystemError, "Parent module '%.200s' not loaded, " "cannot perform relative import", buf.c_str()); } } return parent; /* We expect, but can't guarantee, if parent != None, that: - parent.__name__ == buf - parent.__dict__ is globals If this is violated... Who cares? */ }
SearchResult findModule(const std::string& name, BoxedString* full_name, BoxedList* path_list) { static BoxedString* meta_path_str = internStringImmortal("meta_path"); BoxedList* meta_path = static_cast<BoxedList*>(sys_module->getattr(meta_path_str)); if (!meta_path || meta_path->cls != list_cls) raiseExcHelper(RuntimeError, "sys.meta_path must be a list of import hooks"); static BoxedString* findmodule_str = internStringImmortal("find_module"); for (int i = 0; i < meta_path->size; i++) { Box* finder = meta_path->elts->elts[i]; auto path_pass = path_list ? path_list : None; CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(2) }; Box* loader = callattr(finder, findmodule_str, callattr_flags, full_name, path_pass, NULL, NULL, NULL); if (loader != None) return SearchResult(loader); } if (!path_list) path_list = getSysPath(); if (path_list == NULL || path_list->cls != list_cls) { raiseExcHelper(RuntimeError, "sys.path must be a list of directory names"); } static BoxedString* path_hooks_str = internStringImmortal("path_hooks"); BoxedList* path_hooks = static_cast<BoxedList*>(sys_module->getattr(path_hooks_str)); if (!path_hooks || path_hooks->cls != list_cls) raiseExcHelper(RuntimeError, "sys.path_hooks must be a list of import hooks"); static BoxedString* path_importer_cache_str = internStringImmortal("path_importer_cache"); BoxedDict* path_importer_cache = static_cast<BoxedDict*>(sys_module->getattr(path_importer_cache_str)); if (!path_importer_cache || path_importer_cache->cls != dict_cls) raiseExcHelper(RuntimeError, "sys.path_importer_cache must be a dict"); llvm::SmallString<128> joined_path; for (int i = 0; i < path_list->size; i++) { Box* _p = path_list->elts->elts[i]; if (_p->cls != str_cls) continue; BoxedString* p = static_cast<BoxedString*>(_p); joined_path.clear(); llvm::sys::path::append(joined_path, p->s(), name); std::string dn(joined_path.str()); llvm::sys::path::append(joined_path, "__init__.py"); std::string fn(joined_path.str()); PyObject* importer = get_path_importer(path_importer_cache, path_hooks, _p); if (importer == NULL) throwCAPIException(); if (importer != None) { CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(1) }; Box* loader = callattr(importer, findmodule_str, callattr_flags, full_name, NULL, NULL, NULL, NULL); if (loader != None) return SearchResult(loader); } if (pathExists(fn)) return SearchResult(std::move(dn), SearchResult::PKG_DIRECTORY); joined_path.clear(); llvm::sys::path::append(joined_path, std::string(p->s()), name + ".py"); fn = joined_path.str(); if (pathExists(fn)) return SearchResult(std::move(fn), SearchResult::PY_SOURCE); joined_path.clear(); llvm::sys::path::append(joined_path, p->s(), name + ".pyston.so"); fn = joined_path.str(); if (pathExists(fn)) return SearchResult(std::move(fn), SearchResult::C_EXTENSION); } return SearchResult("", SearchResult::SEARCH_ERROR); } PyObject* PyImport_GetImporter(PyObject* path) noexcept { PyObject* importer = NULL, * path_importer_cache = NULL, * path_hooks = NULL; if ((path_importer_cache = PySys_GetObject("path_importer_cache"))) { if ((path_hooks = PySys_GetObject("path_hooks"))) { importer = get_path_importer(path_importer_cache, path_hooks, path); } } Py_XINCREF(importer); /* get_path_importer returns a borrowed reference */ return importer; }