| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8f24cdc commit 4f0dcc9
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,6 +17,7 @@ typedef struct { | |||
| 17 | 17 | PyObject *func_name; | |
| 18 | 18 | PyObject *func_dict; | |
| 19 | 19 | PyObject *func_weakreflist; | |
| 20 | + PyObject *func_module; | ||
| 20 | 21 | } PyFunctionObject; | |
| 21 | 22 | ||
| 22 | 23 | PyAPI_DATA(PyTypeObject) PyFunction_Type; | |
@@ -26,6 +27,7 @@ PyAPI_DATA(PyTypeObject) PyFunction_Type; | |||
| 26 | 27 | PyAPI_FUNC(PyObject *) PyFunction_New(PyObject *, PyObject *); | |
| 27 | 28 | PyAPI_FUNC(PyObject *) PyFunction_GetCode(PyObject *); | |
| 28 | 29 | PyAPI_FUNC(PyObject *) PyFunction_GetGlobals(PyObject *); | |
| 30 | + PyAPI_FUNC(PyObject *) PyFunction_GetModule(PyObject *); | ||
| 29 | 31 | PyAPI_FUNC(PyObject *) PyFunction_GetDefaults(PyObject *); | |
| 30 | 32 | PyAPI_FUNC(int) PyFunction_SetDefaults(PyObject *, PyObject *); | |
| 31 | 33 | PyAPI_FUNC(PyObject *) PyFunction_GetClosure(PyObject *); | |
@@ -37,6 +39,8 @@ PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *); | |||
| 37 | 39 | (((PyFunctionObject *)func) -> func_code) | |
| 38 | 40 | #define PyFunction_GET_GLOBALS(func) \ | |
| 39 | 41 | (((PyFunctionObject *)func) -> func_globals) | |
| 42 | + #define PyFunction_GET_MODULE(func) \ | ||
| 43 | + (((PyFunctionObject *)func) -> func_module) | ||
| 40 | 44 | #define PyFunction_GET_DEFAULTS(func) \ | |
| 41 | 45 | (((PyFunctionObject *)func) -> func_defaults) | |
| 42 | 46 | #define PyFunction_GET_CLOSURE(func) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,7 +40,9 @@ typedef struct PyMethodDef PyMethodDef; | |||
| 40 | 40 | ||
| 41 | 41 | PyAPI_FUNC(PyObject *) Py_FindMethod(PyMethodDef[], PyObject *, char *); | |
| 42 | 42 | ||
| 43 | - PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *); | ||
| 43 | + #define PyCFunction_New(ML, SELF) PyCFunction_NewEx((ML), (SELF), NULL) | ||
| 44 | + PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *, | ||
| 45 | + PyObject *); | ||
| 44 | 46 | ||
| 45 | 47 | /* Flag passed to newmethodobject */ | |
| 46 | 48 | #define METH_OLDARGS 0x0000 | |
@@ -68,6 +70,7 @@ typedef struct { | |||
| 68 | 70 | PyObject_HEAD | |
| 69 | 71 | PyMethodDef *m_ml; | |
| 70 | 72 | PyObject *m_self; | |
| 73 | + PyObject *m_module; | ||
| 71 | 74 | } PyCFunctionObject; | |
| 72 | 75 | ||
| 73 | 76 | #ifdef __cplusplus | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -787,9 +787,8 @@ def save_global(self, obj, name=None, pack=struct.pack): | |||
| 787 | 787 | if name is None: | |
| 788 | 788 | name = obj.__name__ | |
| 789 | 789 | ||
| 790 | - try: | ||
| 791 | - module = obj.__module__ | ||
| 792 | - except AttributeError: | ||
| 790 | + module = getattr(obj, "__module__", None) | ||
| 791 | + if module is None: | ||
| 793 | 792 | module = whichmodule(obj, name) | |
| 794 | 793 | ||
| 795 | 794 | try: | |
@@ -876,6 +875,10 @@ def whichmodule(func, funcname): | |||
| 876 | 875 | Return a module name. | |
| 877 | 876 | If the function cannot be found, return "__main__". | |
| 878 | 877 | """ | |
| 878 | + # Python functions should always get an __module__ from their globals. | ||
| 879 | + mod = getattr(func, "__module__", None) | ||
| 880 | + if mod is not None: | ||
| 881 | + return mod | ||
| 879 | 882 | if func in classmap: | |
| 880 | 883 | return classmap[func] | |
| 881 | 884 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,6 +9,10 @@ def b(): | |||
| 9 | 9 | 'my docstring' | |
| 10 | 10 | pass | |
| 11 | 11 | ||
| 12 | + # __module__ is a special attribute | ||
| 13 | + verify(b.__module__ == __name__) | ||
| 14 | + verify(verify.__module__ == "test.test_support") | ||
| 15 | + | ||
| 12 | 16 | # setting attributes on functions | |
| 13 | 17 | try: | |
| 14 | 18 | b.publish | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,6 +14,7 @@ PyFunction_New(PyObject *code, PyObject *globals) | |||
| 14 | 14 | if (op != NULL) { | |
| 15 | 15 | PyObject *doc; | |
| 16 | 16 | PyObject *consts; | |
| 17 | + PyObject *module; | ||
| 17 | 18 | op->func_weakreflist = NULL; | |
| 18 | 19 | Py_INCREF(code); | |
| 19 | 20 | op->func_code = code; | |
@@ -34,6 +35,16 @@ PyFunction_New(PyObject *code, PyObject *globals) | |||
| 34 | 35 | Py_INCREF(doc); | |
| 35 | 36 | op->func_doc = doc; | |
| 36 | 37 | op->func_dict = NULL; | |
| 38 | + op->func_module = NULL; | ||
| 39 | + | ||
| 40 | + /* __module__: If module name is in globals, use it. | ||
| 41 | + Otherwise, use None. | ||
| 42 | + */ | ||
| 43 | + module = PyDict_GetItemString(globals, "__name__"); | ||
| 44 | + if (module) { | ||
| 45 | + Py_INCREF(module); | ||
| 46 | + op->func_module = module; | ||
| 47 | + } | ||
| 37 | 48 | } | |
| 38 | 49 | else | |
| 39 | 50 | return NULL; | |
@@ -61,6 +72,16 @@ PyFunction_GetGlobals(PyObject *op) | |||
| 61 | 72 | return ((PyFunctionObject *) op) -> func_globals; | |
| 62 | 73 | } | |
| 63 | 74 | ||
| 75 | + PyObject * | ||
| 76 | + PyFunction_GetModule(PyObject *op) | ||
| 77 | + { | ||
| 78 | + if (!PyFunction_Check(op)) { | ||
| 79 | + PyErr_BadInternalCall(); | ||
| 80 | + return NULL; | ||
| 81 | + } | ||
| 82 | + return ((PyFunctionObject *) op) -> func_module; | ||
| 83 | + } | ||
| 84 | + | ||
| 64 | 85 | PyObject * | |
| 65 | 86 | PyFunction_GetDefaults(PyObject *op) | |
| 66 | 87 | { | |
@@ -138,6 +159,7 @@ static PyMemberDef func_memberlist[] = { | |||
| 138 | 159 | RESTRICTED|READONLY}, | |
| 139 | 160 | {"func_name", T_OBJECT, OFF(func_name), READONLY}, | |
| 140 | 161 | {"__name__", T_OBJECT, OFF(func_name), READONLY}, | |
| 162 | + {"__module__", T_OBJECT, OFF(func_module), READONLY}, | ||
| 141 | 163 | {NULL} /* Sentinel */ | |
| 142 | 164 | }; | |
| 143 | 165 | ||
@@ -373,6 +395,7 @@ func_dealloc(PyFunctionObject *op) | |||
| 373 | 395 | PyObject_ClearWeakRefs((PyObject *) op); | |
| 374 | 396 | Py_DECREF(op->func_code); | |
| 375 | 397 | Py_DECREF(op->func_globals); | |
| 398 | + Py_XDECREF(op->func_module); | ||
| 376 | 399 | Py_DECREF(op->func_name); | |
| 377 | 400 | Py_XDECREF(op->func_defaults); | |
| 378 | 401 | Py_XDECREF(op->func_doc); | |
@@ -405,6 +428,11 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg) | |||
| 405 | 428 | if (err) | |
| 406 | 429 | return err; | |
| 407 | 430 | } | |
| 431 | + if (f->func_module) { | ||
| 432 | + err = visit(f->func_module, arg); | ||
| 433 | + if (err) | ||
| 434 | + return err; | ||
| 435 | + } | ||
| 408 | 436 | if (f->func_defaults) { | |
| 409 | 437 | err = visit(f->func_defaults, arg); | |
| 410 | 438 | if (err) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,11 +2,12 @@ | |||
| 2 | 2 | /* Method object implementation */ | |
| 3 | 3 | ||
| 4 | 4 | #include "Python.h" | |
| 5 | + #include "structmember.h" | ||
| 5 | 6 | ||
| 6 | 7 | static PyCFunctionObject *free_list = NULL; | |
| 7 | 8 | ||
| 8 | 9 | PyObject * | |
| 9 | - PyCFunction_New(PyMethodDef *ml, PyObject *self) | ||
| 10 | + PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) | ||
| 10 | 11 | { | |
| 11 | 12 | PyCFunctionObject *op; | |
| 12 | 13 | op = free_list; | |
@@ -22,6 +23,8 @@ PyCFunction_New(PyMethodDef *ml, PyObject *self) | |||
| 22 | 23 | op->m_ml = ml; | |
| 23 | 24 | Py_XINCREF(self); | |
| 24 | 25 | op->m_self = self; | |
| 26 | + Py_XINCREF(module); | ||
| 27 | + op->m_module = module; | ||
| 25 | 28 | _PyObject_GC_TRACK(op); | |
| 26 | 29 | return (PyObject *)op; | |
| 27 | 30 | } | |
@@ -121,6 +124,7 @@ meth_dealloc(PyCFunctionObject *m) | |||
| 121 | 124 | { | |
| 122 | 125 | _PyObject_GC_UNTRACK(m); | |
| 123 | 126 | Py_XDECREF(m->m_self); | |
| 127 | + Py_XDECREF(m->m_module); | ||
| 124 | 128 | m->m_self = (PyObject *)free_list; | |
| 125 | 129 | free_list = m; | |
| 126 | 130 | } | |
@@ -145,10 +149,18 @@ meth_get__name__(PyCFunctionObject *m, void *closure) | |||
| 145 | 149 | static int | |
| 146 | 150 | meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) | |
| 147 | 151 | { | |
| 148 | - if (m->m_self != NULL) | ||
| 149 | - return visit(m->m_self, arg); | ||
| 150 | - else | ||
| 151 | - return 0; | ||
| 152 | + int err; | ||
| 153 | + if (m->m_self != NULL) { | ||
| 154 | + err = visit(m->m_self, arg); | ||
| 155 | + if (err) | ||
| 156 | + return err; | ||
| 157 | + } | ||
| 158 | + if (m->m_module != NULL) { | ||
| 159 | + err = visit(m->m_module, arg); | ||
| 160 | + if (err) | ||
| 161 | + return err; | ||
| 162 | + } | ||
| 163 | + return 0; | ||
| 152 | 164 | } | |
| 153 | 165 | ||
| 154 | 166 | static PyObject * | |
@@ -174,6 +186,13 @@ static PyGetSetDef meth_getsets [] = { | |||
| 174 | 186 | {0} | |
| 175 | 187 | }; | |
| 176 | 188 | ||
| 189 | + #define OFF(x) offsetof(PyCFunctionObject, x) | ||
| 190 | + | ||
| 191 | + static PyMemberDef meth_members[] = { | ||
| 192 | + {"__module__", T_OBJECT, OFF(m_module), READONLY}, | ||
| 193 | + {NULL} | ||
| 194 | + }; | ||
| 195 | + | ||
| 177 | 196 | static PyObject * | |
| 178 | 197 | meth_repr(PyCFunctionObject *m) | |
| 179 | 198 | { | |
@@ -250,7 +269,7 @@ PyTypeObject PyCFunction_Type = { | |||
| 250 | 269 | 0, /* tp_iter */ | |
| 251 | 270 | 0, /* tp_iternext */ | |
| 252 | 271 | 0, /* tp_methods */ | |
| 253 | - 0, /* tp_members */ | ||
| 272 | + meth_members, /* tp_members */ | ||
| 254 | 273 | meth_getsets, /* tp_getset */ | |
| 255 | 274 | 0, /* tp_base */ | |
| 256 | 275 | 0, /* tp_dict */ | |
@@ -308,6 +327,7 @@ Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, char *name) | |||
| 308 | 327 | for (; ml->ml_name != NULL; ml++) { | |
| 309 | 328 | if (name[0] == ml->ml_name[0] && | |
| 310 | 329 | strcmp(name+1, ml->ml_name+1) == 0) | |
| 330 | + /* XXX */ | ||
| 311 | 331 | return PyCFunction_New(ml, self); | |
| 312 | 332 | } | |
| 313 | 333 | chain = chain->link; | |
@@ -338,3 +358,17 @@ PyCFunction_Fini(void) | |||
| 338 | 358 | PyObject_GC_Del(v); | |
| 339 | 359 | } | |
| 340 | 360 | } | |
| 361 | + | ||
| 362 | + /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(), | ||
| 363 | + but it's part of the API so we need to keep a function around that | ||
| 364 | + existing C extensions can call. | ||
| 365 | + */ | ||
| 366 | + | ||
| 367 | + #undef PyCFunction_New | ||
| 368 | + PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *); | ||
| 369 | + | ||
| 370 | + PyObject * | ||
| 371 | + PyCFunction_New(PyMethodDef *ml, PyObject *self) | ||
| 372 | + { | ||
| 373 | + return PyCFunction_NewEx(ml, self, NULL); | ||
| 374 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -126,22 +126,27 @@ Exception\n\ | |||
| 126 | 126 | static int | |
| 127 | 127 | populate_methods(PyObject *klass, PyObject *dict, PyMethodDef *methods) | |
| 128 | 128 | { | |
| 129 | + PyObject *module; | ||
| 130 | + int status = -1; | ||
| 131 | + | ||
| 129 | 132 | if (!methods) | |
| 130 | 133 | return 0; | |
| 131 | 134 | ||
| 135 | + module = PyString_FromString("exceptions"); | ||
| 136 | + if (!module) | ||
| 137 | + return 0; | ||
| 132 | 138 | while (methods->ml_name) { | |
| 133 | 139 | /* get a wrapper for the built-in function */ | |
| 134 | - PyObject *func = PyCFunction_New(methods, NULL); | ||
| 140 | + PyObject *func = PyCFunction_NewEx(methods, NULL, module); | ||
| 135 | 141 | PyObject *meth; | |
| 136 | - int status; | ||
| 137 | 142 | ||
| 138 | 143 | if (!func) | |
| 139 | - return -1; | ||
| 144 | + goto status; | ||
| 140 | 145 | ||
| 141 | 146 | /* turn the function into an unbound method */ | |
| 142 | 147 | if (!(meth = PyMethod_New(func, NULL, klass))) { | |
| 143 | 148 | Py_DECREF(func); | |
| 144 | - return -1; | ||
| 149 | + goto status; | ||
| 145 | 150 | } | |
| 146 | 151 | ||
| 147 | 152 | /* add method to dictionary */ | |
@@ -151,11 +156,14 @@ populate_methods(PyObject *klass, PyObject *dict, PyMethodDef *methods) | |||
| 151 | 156 | ||
| 152 | 157 | /* stop now if an error occurred, otherwise do the next method */ | |
| 153 | 158 | if (status) | |
| 154 | - return status; | ||
| 159 | + goto status; | ||
| 155 | 160 | ||
| 156 | 161 | methods++; | |
| 157 | 162 | } | |
| 158 | - return 0; | ||
| 163 | + status = 0; | ||
| 164 | + status: | ||
| 165 | + Py_DECREF(module); | ||
| 166 | + return status; | ||
| 159 | 167 | } | |
| 160 | 168 | ||
| 161 | 169 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -33,7 +33,7 @@ PyObject * | |||
| 33 | 33 | Py_InitModule4(char *name, PyMethodDef *methods, char *doc, | |
| 34 | 34 | PyObject *passthrough, int module_api_version) | |
| 35 | 35 | { | |
| 36 | - PyObject *m, *d, *v; | ||
| 36 | + PyObject *m, *d, *v, *n; | ||
| 37 | 37 | PyMethodDef *ml; | |
| 38 | 38 | if (!Py_IsInitialized()) | |
| 39 | 39 | Py_FatalError("Interpreter not initialized (version mismatch?)"); | |
@@ -46,6 +46,15 @@ Py_InitModule4(char *name, PyMethodDef *methods, char *doc, | |||
| 46 | 46 | if (PyErr_Warn(PyExc_RuntimeWarning, message)) | |
| 47 | 47 | return NULL; | |
| 48 | 48 | } | |
| 49 | + /* Make sure name is fully qualified. | ||
| 50 | + | ||
| 51 | + This is a bit of a hack: when the shared library is loaded, | ||
| 52 | + the module name is "package.module", but the module calls | ||
| 53 | + Py_InitModule*() with just "module" for the name. The shared | ||
| 54 | + library loader squirrels away the true name of the module in | ||
| 55 | + _Py_PackageContext, and Py_InitModule*() will substitute this | ||
| 56 | + (if the name actually matches). | ||
| 57 | + */ | ||
| 49 | 58 | if (_Py_PackageContext != NULL) { | |
| 50 | 59 | char *p = strrchr(_Py_PackageContext, '.'); | |
| 51 | 60 | if (p != NULL && strcmp(name, p+1) == 0) { | |
@@ -57,6 +66,9 @@ Py_InitModule4(char *name, PyMethodDef *methods, char *doc, | |||
| 57 | 66 | return NULL; | |
| 58 | 67 | d = PyModule_GetDict(m); | |
| 59 | 68 | if (methods != NULL) { | |
| 69 | + n = PyString_FromString(name); | ||
| 70 | + if (n == NULL) | ||
| 71 | + return NULL; | ||
| 60 | 72 | for (ml = methods; ml->ml_name != NULL; ml++) { | |
| 61 | 73 | if ((ml->ml_flags & METH_CLASS) || | |
| 62 | 74 | (ml->ml_flags & METH_STATIC)) { | |
@@ -65,7 +77,7 @@ Py_InitModule4(char *name, PyMethodDef *methods, char *doc, | |||
| 65 | 77 | " METH_CLASS or METH_STATIC"); | |
| 66 | 78 | return NULL; | |
| 67 | 79 | } | |
| 68 | - v = PyCFunction_New(ml, passthrough); | ||
| 80 | + v = PyCFunction_NewEx(ml, passthrough, n); | ||
| 69 | 81 | if (v == NULL) | |
| 70 | 82 | return NULL; | |
| 71 | 83 | if (PyDict_SetItemString(d, ml->ml_name, v) != 0) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments