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; }
/* 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? */ }