From 3c5173c179b030580d61583cfab149a8eacd3d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 30 Mar 2003 20:57:31 +0000 Subject: Patch #710576: Implement per-interpreter-state codec registries. --- Include/pystate.h | 3 ++ Misc/NEWS | 4 +++ Python/codecs.c | 102 +++++++++++++++++++++-------------------------------- Python/pystate.c | 4 +++ Python/pythonrun.c | 8 ----- 5 files changed, 51 insertions(+), 70 deletions(-) diff --git a/Include/pystate.h b/Include/pystate.h index 9aa8ec8..40d2d0d 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -27,6 +27,9 @@ typedef struct _is { int dlopenflags; #endif + PyObject *codec_search_path; + PyObject *codec_search_cache; + } PyInterpreterState; diff --git a/Misc/NEWS b/Misc/NEWS index 56f0a80..bff0d0c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,10 @@ What's New in Python 2.2.3 ? Release date: XX-XXX-2003 ============================ +- SF #710576: Backport of fix for #663074, to implement per-interpreter + codecs registries. This adds new members at the end of + PyInterpreterState. + - SF #705836: The platform-independent routines for packing floats in IEEE formats (struct.pack's f, d codes; pickle and cPickle's protocol 1 pickling of floats) ignored that rounding can diff --git a/Python/codecs.c b/Python/codecs.c index cc0fabc..c7acd55 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -11,14 +11,6 @@ Copyright (c) Corporation for National Research Initiatives. #include "Python.h" #include -/* --- Globals ------------------------------------------------------------ */ - -static PyObject *_PyCodec_SearchPath; -static PyObject *_PyCodec_SearchCache; - -/* Flag used for lazy import of the standard encodings package */ -static int import_encodings_called = 0; - /* --- Codec Registry ----------------------------------------------------- */ /* Import the standard encodings package which will register the first @@ -32,35 +24,13 @@ static int import_encodings_called = 0; */ -static -int import_encodings(void) -{ - PyObject *mod; - - import_encodings_called = 1; - mod = PyImport_ImportModule("encodings"); - if (mod == NULL) { - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - /* Ignore ImportErrors... this is done so that - distributions can disable the encodings package. Note - that other errors are not masked, e.g. SystemErrors - raised to inform the user of an error in the Python - configuration are still reported back to the user. */ - PyErr_Clear(); - return 0; - } - return -1; - } - Py_DECREF(mod); - return 0; -} +static int _PyCodecRegistry_Init(void); /* Forward */ int PyCodec_Register(PyObject *search_function) { - if (!import_encodings_called) { - if (import_encodings()) - goto onError; - } + PyInterpreterState *interp = PyThreadState_Get()->interp; + if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) + goto onError; if (search_function == NULL) { PyErr_BadArgument(); goto onError; @@ -70,7 +40,7 @@ int PyCodec_Register(PyObject *search_function) "argument must be callable"); goto onError; } - return PyList_Append(_PyCodec_SearchPath, search_function); + return PyList_Append(interp->codec_search_path, search_function); onError: return -1; @@ -124,6 +94,7 @@ PyObject *normalizestring(const char *string) PyObject *_PyCodec_Lookup(const char *encoding) { + PyInterpreterState *interp; PyObject *result, *args = NULL, *v; int i, len; @@ -131,16 +102,10 @@ PyObject *_PyCodec_Lookup(const char *encoding) PyErr_BadArgument(); goto onError; } - if (_PyCodec_SearchCache == NULL || - _PyCodec_SearchPath == NULL) { - PyErr_SetString(PyExc_SystemError, - "codec module not properly initialized"); + + interp = PyThreadState_Get()->interp; + if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) goto onError; - } - if (!import_encodings_called) { - if (import_encodings()) - goto onError; - } /* Convert the encoding to a normalized Python string: all characters are converted to lower case, spaces and hyphens are @@ -151,7 +116,7 @@ PyObject *_PyCodec_Lookup(const char *encoding) PyString_InternInPlace(&v); /* First, try to lookup the name in the registry dictionary */ - result = PyDict_GetItem(_PyCodec_SearchCache, v); + result = PyDict_GetItem(interp->codec_search_cache, v); if (result != NULL) { Py_INCREF(result); Py_DECREF(v); @@ -164,7 +129,7 @@ PyObject *_PyCodec_Lookup(const char *encoding) goto onError; PyTuple_SET_ITEM(args,0,v); - len = PyList_Size(_PyCodec_SearchPath); + len = PyList_Size(interp->codec_search_path); if (len < 0) goto onError; if (len == 0) { @@ -177,7 +142,7 @@ PyObject *_PyCodec_Lookup(const char *encoding) for (i = 0; i < len; i++) { PyObject *func; - func = PyList_GetItem(_PyCodec_SearchPath, i); + func = PyList_GetItem(interp->codec_search_path, i); if (func == NULL) goto onError; result = PyEval_CallObject(func, args); @@ -203,7 +168,7 @@ PyObject *_PyCodec_Lookup(const char *encoding) } /* Cache and return the result */ - PyDict_SetItem(_PyCodec_SearchCache, v, result); + PyDict_SetItem(interp->codec_search_cache, v, result); Py_DECREF(args); return result; @@ -422,21 +387,34 @@ PyObject *PyCodec_Decode(PyObject *object, return NULL; } -void _PyCodecRegistry_Init(void) +static int _PyCodecRegistry_Init(void) { - if (_PyCodec_SearchPath == NULL) - _PyCodec_SearchPath = PyList_New(0); - if (_PyCodec_SearchCache == NULL) - _PyCodec_SearchCache = PyDict_New(); - if (_PyCodec_SearchPath == NULL || - _PyCodec_SearchCache == NULL) + PyInterpreterState *interp = PyThreadState_Get()->interp; + PyObject *mod; + + if (interp->codec_search_path != NULL) + return 0; + + interp->codec_search_path = PyList_New(0); + interp->codec_search_cache = PyDict_New(); + + if (interp->codec_search_path == NULL || + interp->codec_search_cache == NULL) Py_FatalError("can't initialize codec registry"); -} -void _PyCodecRegistry_Fini(void) -{ - Py_XDECREF(_PyCodec_SearchPath); - _PyCodec_SearchPath = NULL; - Py_XDECREF(_PyCodec_SearchCache); - _PyCodec_SearchCache = NULL; + mod = PyImport_ImportModuleEx("encodings", NULL, NULL, NULL); + if (mod == NULL) { + if (PyErr_ExceptionMatches(PyExc_ImportError)) { + /* Ignore ImportErrors... this is done so that + distributions can disable the encodings package. Note + that other errors are not masked, e.g. SystemErrors + raised to inform the user of an error in the Python + configuration are still reported back to the user. */ + PyErr_Clear(); + return 0; + } + return -1; + } + Py_DECREF(mod); + return 0; } diff --git a/Python/pystate.c b/Python/pystate.c index e6b0d84..57fffc7 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -50,6 +50,8 @@ PyInterpreterState_New(void) interp->builtins = NULL; interp->checkinterval = 10; interp->tstate_head = NULL; + interp->codec_search_path = NULL; + interp->codec_search_cache = NULL; #ifdef HAVE_DLOPEN #ifdef RTLD_NOW interp->dlopenflags = RTLD_NOW; @@ -76,6 +78,8 @@ PyInterpreterState_Clear(PyInterpreterState *interp) for (p = interp->tstate_head; p != NULL; p = p->next) PyThreadState_Clear(p); HEAD_UNLOCK(); + ZAP(interp->codec_search_path); + ZAP(interp->codec_search_cache); ZAP(interp->modules); ZAP(interp->sysdict); ZAP(interp->builtins); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 51d71e0..2f25bfb 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -49,8 +49,6 @@ int _Py_AskYesNo(char *prompt); extern void _PyUnicode_Init(void); extern void _PyUnicode_Fini(void); -extern void _PyCodecRegistry_Init(void); -extern void _PyCodecRegistry_Fini(void); int Py_DebugFlag; /* Needed by parser.c */ int Py_VerboseFlag; /* Needed by import.c */ @@ -133,9 +131,6 @@ Py_Initialize(void) if (interp->modules == NULL) Py_FatalError("Py_Initialize: can't make modules dictionary"); - /* Init codec registry */ - _PyCodecRegistry_Init(); - #ifdef Py_USING_UNICODE /* Init Unicode implementation; relies on the codec registry */ _PyUnicode_Init(); @@ -219,9 +214,6 @@ Py_Finalize(void) /* Disable signal handling */ PyOS_FiniInterrupts(); - /* Cleanup Codec registry */ - _PyCodecRegistry_Fini(); - /* Destroy all modules */ PyImport_Cleanup(); -- cgit v0.12