From 76e077001d9c593faaec1aa5187dd7870cb4481c Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Wed, 18 Jul 2012 23:14:57 +1000 Subject: [PATCH] Close #15387: inspect.getmodulename() now uses a new importlib.machinery.all_suffixes() API rather than the deprecated inspect.getmoduleinfo() --- Doc/library/importlib.rst | 13 ++++++++++++- Doc/library/inspect.rst | 15 ++++++++++++--- Lib/importlib/machinery.py | 4 ++++ Lib/inspect.py | 11 +++++++++-- Misc/NEWS | 3 +++ 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index cea2da048e8..daf9e569dd2 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -533,12 +533,23 @@ find and load modules. .. attribute:: EXTENSION_SUFFIXES - A list of strings representing the the recognized file suffixes for + A list of strings representing the recognized file suffixes for extension modules. .. versionadded:: 3.3 +.. func:: all_suffixes() + + Returns a combined list of strings representing all file suffixes for + Python modules recognized by the standard import machinery. This is a + helper for code which simply needs to know if a filesystem path + potentially represents a Python module (for example, + :func:`inspect.getmodulename`) + + .. versionadded:: 3.3 + + .. class:: BuiltinImporter An :term:`importer` for built-in modules. All known built-in modules are diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 6568e94cc3f..ac0d6e65552 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -198,9 +198,18 @@ attributes: .. function:: getmodulename(path) Return the name of the module named by the file *path*, without including the - names of enclosing packages. This uses the same algorithm as the interpreter - uses when searching for modules. If the name cannot be matched according to the - interpreter's rules, ``None`` is returned. + names of enclosing packages. The file extension is checked against all of + the entries in :func:`importlib.machinery.all_suffixes`. If it matches, + the final path component is returned with the extension removed. + Otherwise, ``None`` is returned. + + Note that this function *only* returns a meaningful name for actual + Python modules - paths that potentially refer to Python packages will + still return ``None``. + + .. versionchanged:: 3.3 + This function is now based directly on :mod:`importlib` rather than the + deprecated :func:`getmoduleinfo`. .. function:: ismodule(object) diff --git a/Lib/importlib/machinery.py b/Lib/importlib/machinery.py index d5e7250479c..3fe0b110175 100644 --- a/Lib/importlib/machinery.py +++ b/Lib/importlib/machinery.py @@ -13,3 +13,7 @@ from ._bootstrap import SourcelessFileLoader from ._bootstrap import ExtensionFileLoader EXTENSION_SUFFIXES = _imp.extension_suffixes() + +def all_suffixes(): + """Returns a list of all recognized module suffixes for this process""" + return SOURCE_SUFFIXES + BYTECODE_SUFFIXES + EXTENSION_SUFFIXES diff --git a/Lib/inspect.py b/Lib/inspect.py index 074e1b44306..40e44548f23 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -450,8 +450,15 @@ def getmoduleinfo(path): def getmodulename(path): """Return the module name for a given file, or None.""" - info = getmoduleinfo(path) - if info: return info[0] + fname = os.path.basename(path) + # Check for paths that look like an actual module file + suffixes = [(-len(suffix), suffix) + for suffix in importlib.machinery.all_suffixes()] + suffixes.sort() # try longest suffixes first, in case they overlap + for neglen, suffix in suffixes: + if fname.endswith(suffix): + return fname[:neglen] + return None def getsourcefile(object): """Return the filename that can be used to locate an object's source. diff --git a/Misc/NEWS b/Misc/NEWS index 11732dc00ec..1f11b4a66ec 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,9 @@ Core and Builtins Library ------- +- Issue #15397: inspect.getmodulename() is now based directly on importlib + via a new importlib.machinery.all_suffixes() API. + - Issue #14635: telnetlib will use poll() rather than select() when possible to avoid failing due to the select() file descriptor limit.