I've been playing around with ideas for internationalizing Mailman, which naturally <wink> leads to string interpolation. To see why, think about making the following code translatable: def trade(yours, mine): print 'if you give me %s, i will give you %s' % (yours, mine) Because the order of the interpolated values may change in the translated string, you really have to do something like: def trade(yours, mine): print 'if you give me %(yours)s, i will give you %(mine)s' % { 'yours': yours, 'mine' : mine, } which actually will look something like this in real code: def trade(yours, mine): print _('if you give me %(yours)s, i will give you %(mine)s') % { 'yours': yours, 'mine' : mine, } The string wrapped in _() is what gets translated here. Okay, we all know that's a pain, right? Lots of people have proposed solutions. I've looked briefly at !?ng's Itpl.py, but I think it probably does too much by adding evaluation. I can define _() to make the problem somewhat more convenient: def _(s): try: raise Exception except Exception: frame = sys.exc_info()[2].tb_frame.f_back d = frame.f_globals.copy() d.update(frame.f_locals()) return the_translation_of(s) % d Now I can write the code like this: def trade(yours, mine): print _('if you give me %(yours)s, i will give you %(mine)s') All well and good and doable in Python today, except getting the current frame with the exception raising trick is slooow. A simple proposed addition to the sys module can improve the performance by about 8x: def _(s): frame = sys.getcaller(1) d = frame.f_globals.copy() d.update(frame.f_locals()) return the_translation_of(s) % d The implementation of sys.getcaller() is given in the below patch. Comments? I think this particular addition is too small for a PEP, although ?!ng still owns PEP 215 (which needs filling in). -Barry -------------------- snip snip -------------------- Index: sysmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/sysmodule.c,v retrieving revision 2.78 diff -u -r2.78 sysmodule.c --- sysmodule.c 2000/09/01 23:29:28 2.78 +++ sysmodule.c 2000/10/24 17:50:30 @@ -15,6 +15,8 @@ */ #include "Python.h" +#include "compile.h" +#include "frameobject.h" #include "osdefs.h" @@ -284,6 +286,38 @@ } #endif +static char getcaller_doc[] = +"getcaller([depth]) -> frameobject\n\ +\n\ +By default, return the frame object at the top of the call stack. If an\n\ +integer depth is given, return the frame object that many calls below the\n\ +top of the stack. If that is deeper than the call stack, a ValueError is\n\ +raised."; + + +static PyObject * +sys_getcaller(PyObject *self, PyObject *args) +{ + PyFrameObject *f = PyThreadState_Get()->frame; + int depth = -1; + + if (!PyArg_ParseTuple(args, "|i:getcaller", &depth)) + return NULL; + + while (depth > 0 && f != NULL) { + f = f->f_back; + --depth; + } + if (f == NULL) { + PyErr_SetString(PyExc_ValueError, + "call stack is not deep enough"); + return NULL; + } + Py_INCREF(f); + return (PyObject*)f; +} + + #ifdef Py_TRACE_REFS /* Defined in objects.c because it uses static globals if that file */ extern PyObject *_Py_GetObjects(PyObject *, PyObject *); @@ -313,6 +347,7 @@ {"getrefcount", sys_getrefcount, 1, getrefcount_doc}, {"getrecursionlimit", sys_getrecursionlimit, 1, getrecursionlimit_doc}, + {"getcaller", sys_getcaller, 1, getcaller_doc}, #ifdef USE_MALLOPT {"mdebug", sys_mdebug, 1}, #endif
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4