Skip to content

Commit 79a494d

Browse files
committed
patch 8.1.0201: newer Python uses "importlib" instead of "imp"
Problem: Newer Python uses "importlib" instead of "imp". Solution: Use "importlib" for newer Python versions. (closes #3163)
1 parent a9604e6 commit 79a494d

File tree

3 files changed

+90
-8
lines changed

3 files changed

+90
-8
lines changed

src/if_py_both.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,12 @@ static PyObject *py_getcwd;
8888
static PyObject *vim_module;
8989
static PyObject *vim_special_path_object;
9090

91+
#if PY_VERSION_HEX >= 0x030700f0
92+
static PyObject *py_find_spec;
93+
#else
9194
static PyObject *py_find_module;
9295
static PyObject *py_load_module;
96+
#endif
9397

9498
static PyObject *VimError;
9599

@@ -539,6 +543,7 @@ PythonIO_Init_io(void)
539543
return 0;
540544
}
541545

546+
#if PY_VERSION_HEX < 0x030700f0
542547
typedef struct
543548
{
544549
PyObject_HEAD
@@ -567,6 +572,7 @@ static struct PyMethodDef LoaderMethods[] = {
567572
{"load_module", (PyCFunction)LoaderLoadModule, METH_VARARGS, ""},
568573
{ NULL, NULL, 0, NULL}
569574
};
575+
#endif
570576

571577
/* Check to see whether a Vim error has been reported, or a keyboard
572578
* interrupt has been detected.
@@ -1163,6 +1169,37 @@ Vim_GetPaths(PyObject *self UNUSED)
11631169
return ret;
11641170
}
11651171

1172+
#if PY_VERSION_HEX >= 0x030700f0
1173+
static PyObject *
1174+
FinderFindSpec(PyObject *self, PyObject *args)
1175+
{
1176+
char *fullname;
1177+
PyObject *paths;
1178+
PyObject *target = Py_None;
1179+
PyObject *spec;
1180+
1181+
if (!PyArg_ParseTuple(args, "s|O", &fullname, &target))
1182+
return NULL;
1183+
1184+
if (!(paths = Vim_GetPaths(self)))
1185+
return NULL;
1186+
1187+
spec = PyObject_CallFunction(py_find_spec, "sNN", fullname, paths, target);
1188+
1189+
Py_DECREF(paths);
1190+
1191+
if (!spec)
1192+
{
1193+
if (PyErr_Occurred())
1194+
return NULL;
1195+
1196+
Py_INCREF(Py_None);
1197+
return Py_None;
1198+
}
1199+
1200+
return spec;
1201+
}
1202+
#else
11661203
static PyObject *
11671204
call_load_module(char *name, int len, PyObject *find_module_result)
11681205
{
@@ -1305,6 +1342,7 @@ FinderFindModule(PyObject *self, PyObject *args)
13051342

13061343
return (PyObject *) loader;
13071344
}
1345+
#endif
13081346

13091347
static PyObject *
13101348
VimPathHook(PyObject *self UNUSED, PyObject *args)
@@ -1336,7 +1374,11 @@ static struct PyMethodDef VimMethods[] = {
13361374
{"chdir", (PyCFunction)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
13371375
{"fchdir", (PyCFunction)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
13381376
{"foreach_rtp", VimForeachRTP, METH_O, "Call given callable for each path in &rtp"},
1377+
#if PY_VERSION_HEX >= 0x030700f0
1378+
{"find_spec", FinderFindSpec, METH_VARARGS, "Internal use only, returns spec object for any input it receives"},
1379+
#else
13391380
{"find_module", FinderFindModule, METH_VARARGS, "Internal use only, returns loader object for any input it receives"},
1381+
#endif
13401382
{"path_hook", VimPathHook, METH_VARARGS, "Hook function to install in sys.path_hooks"},
13411383
{"_get_paths", (PyCFunction)Vim_GetPaths, METH_NOARGS, "Get &rtp-based additions to sys.path"},
13421384
{ NULL, NULL, 0, NULL}
@@ -6545,13 +6587,15 @@ init_structs(void)
65456587
OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
65466588
OptionsType.tp_clear = (inquiry)OptionsClear;
65476589

6590+
#if PY_VERSION_HEX < 0x030700f0
65486591
vim_memset(&LoaderType, 0, sizeof(LoaderType));
65496592
LoaderType.tp_name = "vim.Loader";
65506593
LoaderType.tp_basicsize = sizeof(LoaderObject);
65516594
LoaderType.tp_flags = Py_TPFLAGS_DEFAULT;
65526595
LoaderType.tp_doc = "vim message object";
65536596
LoaderType.tp_methods = LoaderMethods;
65546597
LoaderType.tp_dealloc = (destructor)LoaderDestructor;
6598+
#endif
65556599

65566600
#if PY_MAJOR_VERSION >= 3
65576601
vim_memset(&vimmodule, 0, sizeof(vimmodule));
@@ -6583,7 +6627,9 @@ init_types(void)
65836627
PYTYPE_READY(FunctionType);
65846628
PYTYPE_READY(OptionsType);
65856629
PYTYPE_READY(OutputType);
6630+
#if PY_VERSION_HEX < 0x030700f0
65866631
PYTYPE_READY(LoaderType);
6632+
#endif
65876633
return 0;
65886634
}
65896635

@@ -6707,7 +6753,9 @@ static struct object_constant {
67076753
{"List", (PyObject *)&ListType},
67086754
{"Function", (PyObject *)&FunctionType},
67096755
{"Options", (PyObject *)&OptionsType},
6756+
#if PY_VERSION_HEX < 0x030700f0
67106757
{"_Loader", (PyObject *)&LoaderType},
6758+
#endif
67116759
};
67126760

67136761
#define ADD_OBJECT(m, name, obj) \
@@ -6729,6 +6777,10 @@ populate_module(PyObject *m)
67296777
PyObject *other_module;
67306778
PyObject *attr;
67316779
PyObject *imp;
6780+
#if PY_VERSION_HEX >= 0x030700f0
6781+
PyObject *dict;
6782+
PyObject *cls;
6783+
#endif
67326784

67336785
for (i = 0; i < (int)(sizeof(numeric_constants)
67346786
/ sizeof(struct numeric_constant));
@@ -6801,6 +6853,28 @@ populate_module(PyObject *m)
68016853

68026854
ADD_OBJECT(m, "VIM_SPECIAL_PATH", vim_special_path_object);
68036855

6856+
#if PY_VERSION_HEX >= 0x030700f0
6857+
if (!(imp = PyImport_ImportModule("importlib.machinery")))
6858+
return -1;
6859+
6860+
dict = PyModule_GetDict(imp);
6861+
6862+
if (!(cls = PyDict_GetItemString(dict, "PathFinder")))
6863+
{
6864+
Py_DECREF(imp);
6865+
return -1;
6866+
}
6867+
6868+
if (!(py_find_spec = PyObject_GetAttrString(cls, "find_spec")))
6869+
{
6870+
Py_DECREF(imp);
6871+
return -1;
6872+
}
6873+
6874+
Py_DECREF(imp);
6875+
6876+
ADD_OBJECT(m, "_find_spec", py_find_spec);
6877+
#else
68046878
if (!(imp = PyImport_ImportModule("imp")))
68056879
return -1;
68066880

@@ -6821,6 +6895,7 @@ populate_module(PyObject *m)
68216895

68226896
ADD_OBJECT(m, "_find_module", py_find_module);
68236897
ADD_OBJECT(m, "_load_module", py_load_module);
6898+
#endif
68246899

68256900
return 0;
68266901
}

src/testdir/test87.in

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ import sys
219219
import re
220220

221221
py33_type_error_pattern = re.compile('^__call__\(\) takes (\d+) positional argument but (\d+) were given$')
222+
py37_exception_repr = re.compile(r'([^\(\),])(\)+)$')
222223

223224
def ee(expr, g=globals(), l=locals()):
224225
cb = vim.current.buffer
@@ -227,17 +228,17 @@ def ee(expr, g=globals(), l=locals()):
227228
exec(expr, g, l)
228229
except Exception as e:
229230
if sys.version_info >= (3, 3) and e.__class__ is AttributeError and str(e).find('has no attribute')>=0 and not str(e).startswith("'vim."):
230-
cb.append(expr + ':' + repr((e.__class__, AttributeError(str(e)[str(e).rfind(" '") + 2:-1]))))
231+
msg = repr((e.__class__, AttributeError(str(e)[str(e).rfind(" '") + 2:-1])))
231232
elif sys.version_info >= (3, 3) and e.__class__ is ImportError and str(e).find('No module named \'') >= 0:
232-
cb.append(expr + ':' + repr((e.__class__, ImportError(str(e).replace("'", '')))))
233+
msg = repr((e.__class__, ImportError(str(e).replace("'", ''))))
233234
elif sys.version_info >= (3, 6) and e.__class__ is ModuleNotFoundError:
234235
# Python 3.6 gives ModuleNotFoundError, change it to an ImportError
235-
cb.append(expr + ':' + repr((ImportError, ImportError(str(e).replace("'", '')))))
236+
msg = repr((ImportError, ImportError(str(e).replace("'", ''))))
236237
elif sys.version_info >= (3, 3) and e.__class__ is TypeError:
237238
m = py33_type_error_pattern.search(str(e))
238239
if m:
239240
msg = '__call__() takes exactly {0} positional argument ({1} given)'.format(m.group(1), m.group(2))
240-
cb.append(expr + ':' + repr((e.__class__, TypeError(msg))))
241+
msg = repr((e.__class__, TypeError(msg)))
241242
else:
242243
msg = repr((e.__class__, e))
243244
# Messages changed with Python 3.6, change new to old.
@@ -249,9 +250,8 @@ def ee(expr, g=globals(), l=locals()):
249250
oldmsg2 = '''"Can't convert 'int' object to str implicitly"'''
250251
if msg.find(newmsg2) > -1:
251252
msg = msg.replace(newmsg2, oldmsg2)
252-
cb.append(expr + ':' + msg)
253253
elif sys.version_info >= (3, 5) and e.__class__ is ValueError and str(e) == 'embedded null byte':
254-
cb.append(expr + ':' + repr((TypeError, TypeError('expected bytes with no null'))))
254+
msg = repr((TypeError, TypeError('expected bytes with no null')))
255255
else:
256256
msg = repr((e.__class__, e))
257257
# Some Python versions say can't, others cannot.
@@ -262,11 +262,16 @@ def ee(expr, g=globals(), l=locals()):
262262
msg = msg.replace('"cannot ', '\'cannot ')
263263
if msg.find(' attributes"') > -1:
264264
msg = msg.replace(' attributes"', ' attributes\'')
265-
cb.append(expr + ':' + msg)
265+
if sys.version_info >= (3, 7):
266+
msg = py37_exception_repr.sub(r'\1,\2', msg)
267+
cb.append(expr + ':' + msg)
266268
else:
267269
cb.append(expr + ':NOT FAILED')
268270
except Exception as e:
269-
cb.append(expr + '::' + repr((e.__class__, e)))
271+
msg = repr((e.__class__, e))
272+
if sys.version_info >= (3, 7):
273+
msg = py37_exception_repr.sub(r'\1,\2', msg)
274+
cb.append(expr + '::' + msg)
270275
EOF
271276
:fun New(...)
272277
: return ['NewStart']+a:000+['NewEnd']

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,8 @@ static char *(features[]) =
789789

790790
static int included_patches[] =
791791
{ /* Add new patch number below this line */
792+
/**/
793+
201,
792794
/**/
793795
200,
794796
/**/

0 commit comments

Comments
 (0)