From e20056c8f71a8e289016c0cbd5adb5826cd91f64 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 29 May 2015 17:10:30 -0500 Subject: [PATCH] fix importing one char extension modules (closes #24328) --- .../test_importlib/extension/test_loader.py | 8 ++++++++ Misc/NEWS | 2 ++ Modules/_testmultiphase.c | 8 ++++++++ Python/importdl.c | 19 +++++++++---------- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 5813ade953f..d82c805fbc7 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -177,6 +177,14 @@ class MultiPhaseExtensionModuleTests(abc.LoaderTests): self.assertEqual(module.__name__, 'pkg.' + self.name) self.assertEqual(module.str_const, 'something different') + def test_load_short_name(self): + '''Test loading module with a one-character name''' + module = self.load_module_by_name('x') + self.assertIsInstance(module, types.ModuleType) + self.assertEqual(module.__name__, 'x') + self.assertEqual(module.str_const, 'something different') + assert 'x' not in sys.modules + def test_load_twice(self): '''Test that 2 loads result in 2 module objects''' module1 = self.load_module_by_name(self.name) diff --git a/Misc/NEWS b/Misc/NEWS index 3c38d3edd5b..fbd5a517741 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Release date: 2015-07-05 Core and Builtins ----------------- +- Issue #24328: Fix importing one character extension modules. + - Issue #11205: In dictionary displays, evaluate the key before the value. - Issue #24285: Fixed regression that prevented importing extension modules diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index 0d50db2f023..7b98be2b8ef 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -321,6 +321,14 @@ PyInitU_eckzbwbhc6jpgzcx415x(PyObject *spec) return PyModuleDef_Init(&def_nonascii_kana); } +/*** Module with a single-character name ***/ + +PyMODINIT_FUNC +PyInit_x(PyObject *spec) +{ + return PyModuleDef_Init(&main_def); +} + /**** Testing NULL slots ****/ static PyModuleDef null_slots_def = TEST_MODULE_DEF( diff --git a/Python/importdl.c b/Python/importdl.c index 579d2c5fada..1aa585d5e81 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -34,10 +34,11 @@ static const char *nonascii_prefix = "PyInitU"; */ static PyObject * get_encoded_name(PyObject *name, const char **hook_prefix) { - char *buf; PyObject *tmp; PyObject *encoded = NULL; - Py_ssize_t name_len, lastdot, i; + PyObject *modname = NULL; + Py_ssize_t name_len, lastdot; + _Py_IDENTIFIER(replace); /* Get the short name (substring after last dot) */ name_len = PyUnicode_GetLength(name); @@ -71,16 +72,14 @@ get_encoded_name(PyObject *name, const char **hook_prefix) { } } - buf = PyBytes_AS_STRING(encoded); - assert(Py_REFCNT(encoded) == 1); - for (i = 0; i < PyBytes_GET_SIZE(encoded) + 1; i++) { - if (buf[i] == '-') { - buf[i] = '_'; - } - } + /* Replace '-' by '_' */ + modname = _PyObject_CallMethodId(encoded, &PyId_replace, "cc", '-', '_'); + if (modname == NULL) + goto error; Py_DECREF(name); - return encoded; + Py_DECREF(encoded); + return modname; error: Py_DECREF(name); Py_XDECREF(encoded);