Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r46676:e3bdbe573e9d Date: 2011-08-20 21:56 +0000 http://bitbucket.org/pypy/pypy/changeset/e3bdbe573e9d/
Log: merge heads diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py --- a/pypy/module/cpyext/eval.py +++ b/pypy/module/cpyext/eval.py @@ -1,11 +1,16 @@ from pypy.interpreter.error import OperationError from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( - cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP) + cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP, + cpython_struct) from pypy.module.cpyext.pyobject import PyObject, borrow_from from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno from pypy.module.__builtin__ import compiling +PyCompilerFlags = cpython_struct( + "PyCompilerFlags", ()) +PyCompilerFlagsPtr = lltype.Ptr(PyCompilerFlags) + @cpython_api([PyObject, PyObject, PyObject], PyObject) def PyEval_CallObjectWithKeywords(space, w_obj, w_arg, w_kwds): return space.call(w_obj, w_arg, w_kwds) @@ -69,7 +74,7 @@ Py_file_input = 257 Py_eval_input = 258 -def run_string(space, source, filename, start, w_globals, w_locals): +def compile_string(space, source, filename, start): w_source = space.wrap(source) start = rffi.cast(lltype.Signed, start) if start == Py_file_input: @@ -80,8 +85,11 @@ mode = 'single' else: raise OperationError(space.w_ValueError, space.wrap( - "invalid mode parameter for PyRun_String")) - w_code = compiling.compile(space, w_source, filename, mode) + "invalid mode parameter for compilation")) + return compiling.compile(space, w_source, filename, mode) + +def run_string(space, source, filename, start, w_globals, w_locals): + w_code = compile_string(space, source, filename, start) return compiling.eval(space, w_code, w_globals, w_locals) @cpython_api([CONST_STRING], rffi.INT_real, error=-1) @@ -140,3 +148,19 @@ pi[0] = space.getindex_w(w_obj, None) return 1 +@cpython_api([rffi.CCHARP, rffi.CCHARP, rffi.INT_real, PyCompilerFlagsPtr], + PyObject) +def Py_CompileStringFlags(space, source, filename, start, flags): + """Parse and compile the Python source code in str, returning the + resulting code object. The start token is given by start; this + can be used to constrain the code which can be compiled and should + be Py_eval_input, Py_file_input, or Py_single_input. The filename + specified by filename is used to construct the code object and may + appear in tracebacks or SyntaxError exception messages. This + returns NULL if the code cannot be parsed or compiled.""" + source = rffi.charp2str(source) + filename = rffi.charp2str(filename) + if flags: + raise OperationError(space.w_NotImplementedError, space.wrap( + "cpyext Py_CompileStringFlags does not accept flags")) + return compile_string(space, source, filename, start) diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py --- a/pypy/module/cpyext/import_.py +++ b/pypy/module/cpyext/import_.py @@ -2,9 +2,11 @@ from pypy.module.cpyext.api import ( generic_cpy_call, cpython_api, PyObject, CONST_STRING) from pypy.module.cpyext.pyobject import borrow_from -from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype, rffi from pypy.interpreter.error import OperationError from pypy.interpreter.module import Module +from pypy.interpreter.pycode import PyCode +from pypy.module.imp import importing @cpython_api([PyObject], PyObject) def PyImport_Import(space, w_name): @@ -80,3 +82,44 @@ w_modulesDict = space.sys.get('modules') return borrow_from(None, w_modulesDict) +@cpython_api([rffi.CCHARP, PyObject], PyObject) +def PyImport_ExecCodeModule(space, name, w_code): + """Given a module name (possibly of the form package.module) and a code + object read from a Python bytecode file or obtained from the built-in + function compile(), load the module. Return a new reference to the module + object, or NULL with an exception set if an error occurred. Before Python + 2.4, the module could still be created in error cases. Starting with Python + 2.4, name is removed from sys.modules in error cases, and even if name was + already in sys.modules on entry to PyImport_ExecCodeModule(). Leaving + incompletely initialized modules in sys.modules is dangerous, as imports of + such modules have no way to know that the module object is an unknown (and + probably damaged with respect to the module author's intents) state. + + The module's __file__ attribute will be set to the code object's + co_filename. + + This function will reload the module if it was already imported. See + PyImport_ReloadModule() for the intended way to reload a module. + + If name points to a dotted name of the form package.module, any package + structures not already created will still not be created. + + name is removed from sys.modules in error cases.""" + return PyImport_ExecCodeModuleEx(space, name, w_code, + lltype.nullptr(rffi.CCHARP.TO)) + + +@cpython_api([rffi.CCHARP, PyObject, rffi.CCHARP], PyObject) +def PyImport_ExecCodeModuleEx(space, name, w_code, pathname): + """Like PyImport_ExecCodeModule(), but the __file__ attribute of + the module object is set to pathname if it is non-NULL.""" + code = space.interp_w(PyCode, w_code) + w_name = space.wrap(rffi.charp2str(name)) + if pathname: + pathname = rffi.charp2str(pathname) + else: + pathname = code.co_filename + w_mod = importing.add_module(space, w_name) + space.setattr(w_mod, space.wrap('__file__'), space.wrap(pathname)) + importing.exec_code_module(space, w_mod, code) + return w_mod diff --git a/pypy/module/cpyext/include/pythonrun.h b/pypy/module/cpyext/include/pythonrun.h --- a/pypy/module/cpyext/include/pythonrun.h +++ b/pypy/module/cpyext/include/pythonrun.h @@ -13,6 +13,12 @@ #define Py_FrozenFlag 0 +typedef struct { + int cf_flags; /* bitmask of CO_xxx flags relevant to future */ +} PyCompilerFlags; + +#define Py_CompileString(str, filename, start) Py_CompileStringFlags(str, filename, start, NULL) + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/presetup.py b/pypy/module/cpyext/presetup.py --- a/pypy/module/cpyext/presetup.py +++ b/pypy/module/cpyext/presetup.py @@ -42,4 +42,4 @@ patch_distutils() del sys.argv[0] -execfile(sys.argv[0]) +execfile(sys.argv[0], {'__file__': sys.argv[0]}) diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py --- a/pypy/module/cpyext/setobject.py +++ b/pypy/module/cpyext/setobject.py @@ -14,6 +14,11 @@ @cpython_api([PyObject], PyObject) def PySet_New(space, w_iterable): + """Return a new set containing objects returned by the iterable. The + iterable may be NULL to create a new empty set. Return the new set on + success or NULL on failure. Raise TypeError if iterable is not + actually iterable. The constructor is also useful for copying a set + (c=set(s)).""" if w_iterable is None: return space.call_function(space.w_set) else: @@ -21,6 +26,15 @@ @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1) def PySet_Add(space, w_s, w_obj): + """Add key to a set instance. Does not apply to frozenset + instances. Return 0 on success or -1 on failure. Raise a TypeError if + the key is unhashable. Raise a MemoryError if there is no room to grow. + Raise a SystemError if set is an not an instance of set or its + subtype. + + Now works with instances of frozenset or its subtypes. + Like PyTuple_SetItem() in that it can be used to fill-in the + values of brand new frozensets before they are exposed to other code.""" if not PySet_Check(space, w_s): PyErr_BadInternalCall(space) space.call_method(w_s, 'add', w_obj) @@ -28,6 +42,12 @@ @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1) def PySet_Discard(space, w_s, w_obj): + """Return 1 if found and removed, 0 if not found (no action taken), and -1 if an + error is encountered. Does not raise KeyError for missing keys. Raise a + TypeError if the key is unhashable. Unlike the Python discard() + method, this function does not automatically convert unhashable sets into + temporary frozensets. Raise PyExc_SystemError if set is an not an + instance of set or its subtype.""" if not PySet_Check(space, w_s): PyErr_BadInternalCall(space) space.call_method(w_s, 'discard', w_obj) @@ -36,11 +56,25 @@ @cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL) def PySet_GET_SIZE(space, w_s): + """Macro form of PySet_Size() without error checking.""" return space.int_w(space.len(w_s)) @cpython_api([PyObject], Py_ssize_t, error=-1) def PySet_Size(space, ref): + """Return the length of a set or frozenset object. Equivalent to + len(anyset). Raises a PyExc_SystemError if anyset is not a set, frozenset, + or an instance of a subtype.""" if not PySet_Check(space, ref): raise OperationError(space.w_TypeError, space.wrap("expected set object")) return PySet_GET_SIZE(space, ref) + +@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1) +def PySet_Contains(space, w_obj, w_key): + """Return 1 if found, 0 if not found, and -1 if an error is encountered. Unlike + the Python __contains__() method, this function does not automatically + convert unhashable sets into temporary frozensets. Raise a TypeError if + the key is unhashable. Raise PyExc_SystemError if anyset is not a + set, frozenset, or an instance of a subtype.""" + w_res = space.contains(w_obj, w_key) + return space.int_w(w_res) diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py --- a/pypy/module/cpyext/stubs.py +++ b/pypy/module/cpyext/stubs.py @@ -1048,37 +1048,6 @@ """ raise NotImplementedError -@cpython_api([rffi.CCHARP, PyObject], PyObject) -def PyImport_ExecCodeModule(space, name, co): - """Given a module name (possibly of the form package.module) and a code - object read from a Python bytecode file or obtained from the built-in - function compile(), load the module. Return a new reference to the module - object, or NULL with an exception set if an error occurred. Before Python - 2.4, the module could still be created in error cases. Starting with Python - 2.4, name is removed from sys.modules in error cases, and even if name was - already in sys.modules on entry to PyImport_ExecCodeModule(). Leaving - incompletely initialized modules in sys.modules is dangerous, as imports of - such modules have no way to know that the module object is an unknown (and - probably damaged with respect to the module author's intents) state. - - The module's __file__ attribute will be set to the code object's - co_filename. - - This function will reload the module if it was already imported. See - PyImport_ReloadModule() for the intended way to reload a module. - - If name points to a dotted name of the form package.module, any package - structures not already created will still not be created. - - name is removed from sys.modules in error cases.""" - raise NotImplementedError - -@cpython_api([rffi.CCHARP, PyObject, rffi.CCHARP], PyObject) -def PyImport_ExecCodeModuleEx(space, name, co, pathname): - """Like PyImport_ExecCodeModule(), but the __file__ attribute of - the module object is set to pathname if it is non-NULL.""" - raise NotImplementedError - @cpython_api([], lltype.Signed, error=CANNOT_FAIL) def PyImport_GetMagicNumber(space): """Return the magic number for Python bytecode files (a.k.a. .pyc and @@ -1958,12 +1927,6 @@ raise NotImplementedError @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PySet_Check(space, p): - """Return true if p is a set object or an instance of a subtype. - """ - raise NotImplementedError - -@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyFrozenSet_Check(space, p): """Return true if p is a frozenset object or an instance of a subtype. @@ -1989,15 +1952,6 @@ raise NotImplementedError @cpython_api([PyObject], PyObject) -def PySet_New(space, iterable): - """Return a new set containing objects returned by the iterable. The - iterable may be NULL to create a new empty set. Return the new set on - success or NULL on failure. Raise TypeError if iterable is not - actually iterable. The constructor is also useful for copying a set - (c=set(s)).""" - raise NotImplementedError - -@cpython_api([PyObject], PyObject) def PyFrozenSet_New(space, iterable): """Return a new frozenset containing objects returned by the iterable. The iterable may be NULL to create a new empty frozenset. Return the new @@ -2009,53 +1963,6 @@ building-up new frozensets with PySet_Add().""" raise NotImplementedError -@cpython_api([PyObject], Py_ssize_t, error=-1) -def PySet_Size(space, anyset): - """Return the length of a set or frozenset object. Equivalent to - len(anyset). Raises a PyExc_SystemError if anyset is not a set, frozenset, - or an instance of a subtype. - - This function returned an int. This might require changes in - your code for properly supporting 64-bit systems.""" - raise NotImplementedError - -@cpython_api([PyObject], Py_ssize_t, error=-1) -def PySet_GET_SIZE(space, anyset): - """Macro form of PySet_Size() without error checking.""" - raise NotImplementedError - -@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1) -def PySet_Contains(space, anyset, key): - """Return 1 if found, 0 if not found, and -1 if an error is encountered. Unlike - the Python __contains__() method, this function does not automatically - convert unhashable sets into temporary frozensets. Raise a TypeError if - the key is unhashable. Raise PyExc_SystemError if anyset is not a - set, frozenset, or an instance of a subtype.""" - raise NotImplementedError - -@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1) -def PySet_Add(space, set, key): - """Add key to a set instance. Does not apply to frozenset - instances. Return 0 on success or -1 on failure. Raise a TypeError if - the key is unhashable. Raise a MemoryError if there is no room to grow. - Raise a SystemError if set is an not an instance of set or its - subtype. - - Now works with instances of frozenset or its subtypes. - Like PyTuple_SetItem() in that it can be used to fill-in the - values of brand new frozensets before they are exposed to other code.""" - raise NotImplementedError - -@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1) -def PySet_Discard(space, set, key): - """Return 1 if found and removed, 0 if not found (no action taken), and -1 if an - error is encountered. Does not raise KeyError for missing keys. Raise a - TypeError if the key is unhashable. Unlike the Python discard() - method, this function does not automatically convert unhashable sets into - temporary frozensets. Raise PyExc_SystemError if set is an not an - instance of set or its subtype.""" - raise NotImplementedError - @cpython_api([PyObject], PyObject) def PySet_Pop(space, set): """Return a new reference to an arbitrary object in the set, and removes the @@ -2224,29 +2131,6 @@ """Return 1 or 0 depending on whether ch is an alphabetic character.""" raise NotImplementedError -@cpython_api([Py_UNICODE], Py_UNICODE, error=CANNOT_FAIL) -def Py_UNICODE_TOTITLE(space, ch): - """Return the character ch converted to title case.""" - raise NotImplementedError - -@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) -def Py_UNICODE_TODECIMAL(space, ch): - """Return the character ch converted to a decimal positive integer. Return - -1 if this is not possible. This macro does not raise exceptions.""" - raise NotImplementedError - -@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) -def Py_UNICODE_TODIGIT(space, ch): - """Return the character ch converted to a single digit integer. Return -1 if - this is not possible. This macro does not raise exceptions.""" - raise NotImplementedError - -@cpython_api([Py_UNICODE], rffi.DOUBLE, error=CANNOT_FAIL) -def Py_UNICODE_TONUMERIC(space, ch): - """Return the character ch converted to a double. Return -1.0 if this is not - possible. This macro does not raise exceptions.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP], PyObject) def PyUnicode_FromFormat(space, format): """Take a C printf()-style format string and a variable number of @@ -2732,12 +2616,6 @@ use the default error handling.""" raise NotImplementedError -@cpython_api([PyObject, PyObject], PyObject) -def PyUnicode_Join(space, separator, seq): - """Join a sequence of strings using the given separator and return the resulting - Unicode string.""" - raise NotImplementedError - @cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t, rffi.INT_real], rffi.INT_real, error=-1) def PyUnicode_Tailmatch(space, str, substr, start, end, direction): """Return 1 if substr matches str*[*start:end] at the given tail end @@ -2800,12 +2678,6 @@ Py_NE, Py_LT, and Py_LE.""" raise NotImplementedError -@cpython_api([PyObject, PyObject], PyObject) -def PyUnicode_Format(space, format, args): - """Return a new string object from format and args; this is analogous to - format % args. The args argument must be a tuple.""" - raise NotImplementedError - @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1) def PyUnicode_Contains(space, container, element): """Check whether element is contained in container and return true or false @@ -2992,23 +2864,6 @@ returns.""" raise NotImplementedError -@cpython_api([rffi.CCHARP, rffi.CCHARP, rffi.INT_real], PyObject) -def Py_CompileString(space, str, filename, start): - """This is a simplified interface to Py_CompileStringFlags() below, leaving - flags set to NULL.""" - raise NotImplementedError - -@cpython_api([rffi.CCHARP, rffi.CCHARP, rffi.INT_real, PyCompilerFlags], PyObject) -def Py_CompileStringFlags(space, str, filename, start, flags): - """Parse and compile the Python source code in str, returning the resulting code - object. The start token is given by start; this can be used to constrain the - code which can be compiled and should be Py_eval_input, - Py_file_input, or Py_single_input. The filename specified by - filename is used to construct the code object and may appear in tracebacks or - SyntaxError exception messages. This returns NULL if the code cannot - be parsed or compiled.""" - raise NotImplementedError - @cpython_api([PyCodeObject, PyObject, PyObject], PyObject) def PyEval_EvalCode(space, co, globals, locals): """This is a simplified interface to PyEval_EvalCodeEx(), with just @@ -3076,11 +2931,3 @@ None, or NULL, this will return NULL and raise TypeError. """ raise NotImplementedError - -@cpython_api([PyObject], PyObject) -def PyWeakref_GET_OBJECT(space, ref): - """Similar to PyWeakref_GetObject(), but implemented as a macro that does no - error checking. - """ - borrow_from() - raise NotImplementedError diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py --- a/pypy/module/cpyext/test/test_eval.py +++ b/pypy/module/cpyext/test/test_eval.py @@ -221,4 +221,38 @@ return args assert module.call_func(f) == (None,) assert module.call_method("text") == 2 - + + def test_CompileString_and_Exec(self): + module = self.import_extension('foo', [ + ("compile_string", "METH_NOARGS", + """ + return Py_CompileString( + "f = lambda x: x+5", "someFile", Py_file_input); + """), + ("exec_code", "METH_O", + """ + return PyImport_ExecCodeModule("cpyext_test_modname", args); + """), + ("exec_code_ex", "METH_O", + """ + return PyImport_ExecCodeModuleEx("cpyext_test_modname", + args, "otherFile"); + """), + ]) + code = module.compile_string() + assert code.co_filename == "someFile" + assert code.co_name == "<module>" + + mod = module.exec_code(code) + assert mod.__name__ == "cpyext_test_modname" + assert mod.__file__ == "someFile" + print dir(mod) + print mod.__dict__ + assert mod.f(42) == 47 + + mod = module.exec_code_ex(code) + assert mod.__name__ == "cpyext_test_modname" + assert mod.__file__ == "otherFile" + print dir(mod) + print mod.__dict__ + assert mod.f(42) == 47 diff --git a/pypy/module/cpyext/test/test_setobject.py b/pypy/module/cpyext/test/test_setobject.py --- a/pypy/module/cpyext/test/test_setobject.py +++ b/pypy/module/cpyext/test/test_setobject.py @@ -27,3 +27,8 @@ assert api.PySet_Size(w_set) == 5 api.PySet_Discard(w_set, space.wrap(6)) assert api.PySet_Size(w_set) == 4 + + def test_set_contains(self, space, api): + w_set = api.PySet_New(space.wrap([1,2,3,4])) + assert api.PySet_Contains(w_set, space.wrap(1)) + assert not api.PySet_Contains(w_set, space.wrap(0)) diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py --- a/pypy/module/cpyext/test/test_unicodeobject.py +++ b/pypy/module/cpyext/test/test_unicodeobject.py @@ -219,6 +219,24 @@ assert api.Py_UNICODE_TOUPPER(u'�') == u'�' assert api.Py_UNICODE_TOUPPER(u'�') == u'�' + def test_TOTITLE(self, space, api): + assert api.Py_UNICODE_TOTITLE(u'/') == u'/' + assert api.Py_UNICODE_TOTITLE(u'�') == u'�' + assert api.Py_UNICODE_TOTITLE(u'�') == u'�' + + def test_TODECIMAL(self, space, api): + assert api.Py_UNICODE_TODECIMAL(u'6') == 6 + assert api.Py_UNICODE_TODECIMAL(u'A') == -1 + + def test_TODIGIT(self, space, api): + assert api.Py_UNICODE_TODIGIT(u'6') == 6 + assert api.Py_UNICODE_TODIGIT(u'A') == -1 + + def test_TONUMERIC(self, space, api): + assert api.Py_UNICODE_TONUMERIC(u'6') == 6.0 + assert api.Py_UNICODE_TONUMERIC(u'A') == -1.0 + assert api.Py_UNICODE_TONUMERIC(u'\N{VULGAR FRACTION ONE HALF}') == .5 + def test_fromobject(self, space, api): w_u = space.wrap(u'a') assert api.PyUnicode_FromObject(w_u) is w_u diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py --- a/pypy/module/cpyext/unicodeobject.py +++ b/pypy/module/cpyext/unicodeobject.py @@ -122,6 +122,38 @@ """Return the character ch converted to upper case.""" return unichr(unicodedb.toupper(ord(ch))) +@cpython_api([Py_UNICODE], Py_UNICODE, error=CANNOT_FAIL) +def Py_UNICODE_TOTITLE(space, ch): + """Return the character ch converted to title case.""" + return unichr(unicodedb.totitle(ord(ch))) + +@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) +def Py_UNICODE_TODECIMAL(space, ch): + """Return the character ch converted to a decimal positive integer. Return + -1 if this is not possible. This macro does not raise exceptions.""" + try: + return unicodedb.decimal(ord(ch)) + except KeyError: + return -1 + +@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) +def Py_UNICODE_TODIGIT(space, ch): + """Return the character ch converted to a single digit integer. Return -1 if + this is not possible. This macro does not raise exceptions.""" + try: + return unicodedb.digit(ord(ch)) + except KeyError: + return -1 + +@cpython_api([Py_UNICODE], rffi.DOUBLE, error=CANNOT_FAIL) +def Py_UNICODE_TONUMERIC(space, ch): + """Return the character ch converted to a double. Return -1.0 if this is not + possible. This macro does not raise exceptions.""" + try: + return unicodedb.numeric(ord(ch)) + except KeyError: + return -1.0 + @cpython_api([PyObject], rffi.CCHARP, error=CANNOT_FAIL) def PyUnicode_AS_DATA(space, ref): """Return a pointer to the internal buffer of the object. o has to be a @@ -526,8 +558,12 @@ @cpython_api([PyObject, PyObject], PyObject) def PyUnicode_Format(space, w_format, w_args): + """Return a new string object from format and args; this is analogous to + format % args. The args argument must be a tuple.""" return space.mod(w_format, w_args) @cpython_api([PyObject, PyObject], PyObject) def PyUnicode_Join(space, w_sep, w_seq): + """Join a sequence of strings using the given separator and return the resulting + Unicode string.""" return space.call_method(w_sep, 'join', w_seq) diff --git a/pypy/module/cpyext/weakrefobject.py b/pypy/module/cpyext/weakrefobject.py --- a/pypy/module/cpyext/weakrefobject.py +++ b/pypy/module/cpyext/weakrefobject.py @@ -25,6 +25,9 @@ @cpython_api([PyObject], PyObject) def PyWeakref_GET_OBJECT(space, w_ref): + """Similar to PyWeakref_GetObject(), but implemented as a macro that does no + error checking. + """ return borrow_from(w_ref, space.call_function(w_ref)) @cpython_api([PyObject], PyObject) diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py --- a/pypy/module/imp/importing.py +++ b/pypy/module/imp/importing.py @@ -540,6 +540,13 @@ if pkgdir is not None: space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) +def add_module(space, w_name): + w_mod = check_sys_modules(space, w_name) + if w_mod is None: + w_mod = space.wrap(Module(space, w_name)) + space.sys.setmodule(w_mod) + return w_mod + def load_c_extension(space, filename, modulename): # the next line is mandatory to init cpyext space.getbuiltinmodule("cpyext") _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit