Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add inspect.locate and inspect.resolve #57124

Closed
merwok opened this issue Sep 6, 2011 · 32 comments
Closed

Add inspect.locate and inspect.resolve #57124

merwok opened this issue Sep 6, 2011 · 32 comments
Labels
3.9 only security fixes stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@merwok
Copy link
Member

merwok commented Sep 6, 2011

BPO 12915
Nosy @terryjreedy, @vsajip, @ncoghlan, @ned-deily, @ezio-melotti, @merwok, @Trundle, @meadori, @durban, @ericsnowcurrently, @berkerpeksag, @1st1, @aixtools, @RJ722
PRs
  • bpo-12915: Add pkgutil.resolve_name #18310
  • bpo-12915: Improve Unicode support for package names and attributes. #18517
  • bpo-12915: Fix test to recognize when filesystem encoding cannot encode Unicode string #18720
  • Files
  • issue12915.diff
  • issue12915_v2.diff
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2020-03-03.10:12:12.716>
    created_at = <Date 2011-09-06.16:30:32.929>
    labels = ['type-feature', 'library', '3.9']
    title = 'Add inspect.locate and inspect.resolve'
    updated_at = <Date 2020-12-31.14:16:33.047>
    user = 'https://github.com/merwok'

    bugs.python.org fields:

    activity = <Date 2020-12-31.14:16:33.047>
    actor = 'RJ722'
    assignee = 'none'
    closed = True
    closed_date = <Date 2020-03-03.10:12:12.716>
    closer = 'vstinner'
    components = ['Library (Lib)']
    creation = <Date 2011-09-06.16:30:32.929>
    creator = 'eric.araujo'
    dependencies = []
    files = ['28277', '28500']
    hgrepos = []
    issue_num = 12915
    keywords = ['patch']
    message_count = 32.0
    messages = ['143626', '143796', '143911', '143960', '145941', '146020', '147597', '178625', '182938', '183109', '183115', '209878', '209893', '209895', '209902', '209903', '360664', '360681', '360710', '362000', '362007', '362022', '362023', '362132', '362161', '362881', '362987', '363023', '363044', '363250', '363251', '372552']
    nosy_count = 15.0
    nosy_names = ['terry.reedy', 'vinay.sajip', 'ncoghlan', 'ned.deily', 'ezio.melotti', 'eric.araujo', 'Trundle', 'meador.inge', 'daniel.urban', 'python-dev', 'eric.snow', 'berker.peksag', 'yselivanov', 'Michael.Felt', 'RJ722']
    pr_nums = ['18310', '18517', '18720']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue12915'
    versions = ['Python 3.9']

    @merwok
    Copy link
    Member Author

    merwok commented Sep 6, 2011

    The need to resolve a dotted name to a Python object is spreading in the stdlib: pydoc has locate and resolve, packaging has util.resolve_name, unittest has something else, etc. For the benefit of stdlib maintainers as well as the community, I think such functionality should be exposed publicly by the inspect module.

    @merwok merwok added stdlib Python modules in the Lib dir type-feature A feature request or enhancement labels Sep 6, 2011
    @terryjreedy
    Copy link
    Member

    To be a little clearer, this is about dotted import names, not regular dotted names.
    pydoc.locate(path, forceload=0):
    """Locate an object by name or dotted path, importing as necessary"""
    pydoc.resolve(thing, forceload=0):
    """Given an object or a path to an object, get the object and its name."""

    It is not completely clear to me how this is different from using __import__ but I will believe it is. It something like this is in at least 3 places, +1 on factoring it out to one place.

    @merwok
    Copy link
    Member Author

    merwok commented Sep 12, 2011

    Sorry if I was unclear; the functions work with a dotted name as a string and resolve it to an object. __import__ works with module, whereas this kind of functions work with mod.name, pkg.mod.name.attr, etc., that is, they combine import and getattr.

    @merwok
    Copy link
    Member Author

    merwok commented Sep 13, 2011

    In addition, error handling/reporting is not trivial to get right. We’ve had to fix the code in distutils2 and it’s still not quite right (bpo-12703).

    I opened this report because I’d like to see all stdlib modules use the same functions and I’d prefer people to copy-paste the same robust code for backports.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Oct 19, 2011

    New changeset 1405df4a1535 by Éric Araujo in branch 'default':
    Expand tests and fix bugs in packaging.util.resolve_name.
    http://hg.python.org/cpython/rev/1405df4a1535

    @vsajip
    Copy link
    Member

    vsajip commented Oct 20, 2011

    The version in logging.config appears to be doing the same job, but is shorter:

    def _resolve(name):
        """Resolve a dotted name to a global object."""
        name = name.split('.')
        used = name.pop(0)
        found = __import__(used)
        for n in name:
            used = used + '.' + n
            try:
                found = getattr(found, n)
            except AttributeError:
                __import__(used)
                found = getattr(found, n)
        return found

    The line "used = used + '.' + n" could of course be improved.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Nov 14, 2011

    New changeset 5df1065ddb8b by Éric Araujo in branch 'default':
    Expand tests and fix bugs in util.resolve_name.
    http://hg.python.org/distutils2/rev/5df1065ddb8b

    @berkerpeksag
    Copy link
    Member

    Attaching new patch to address Vinay Sajip's suggestions on Rietveld. Thank you, Vinay.

    @ncoghlan
    Copy link
    Contributor

    Something to consider with these functions: it is probably desirable to also support the popular alternate notation which uses an explicit ":" to separate the module name from the reference within the module.

    For example, setuptools entry points and nose test references both use that format.

    The alternate notation should be fairly easy to both detect and handle through "name.partition(':')"

    @ezio-melotti
    Copy link
    Member

    Can you provide a couple of examples of that notation?

    @vsajip
    Copy link
    Member

    vsajip commented Feb 27, 2013

    Can you provide a couple of examples of that notation?

    entry_points = """
    [console_scripts]
    pybabel = babel.messages.frontend:main

    [distutils.commands]
    compile_catalog = babel.messages.frontend:compile_catalog
    extract_messages = babel.messages.frontend:extract_messages
    init_catalog = babel.messages.frontend:init_catalog
    update_catalog = babel.messages.frontend:update_catalog

    [distutils.setup_keywords]
    message_extractors = babel.messages.frontend:check_message_extractors

    [babel.checkers]
    num_plurals = babel.messages.checkers:num_plurals
    python_format = babel.messages.checkers:python_format

    [babel.extractors]
    ignore = babel.messages.extract:extract_nothing
    python = babel.messages.extract:extract_python
    javascript = babel.messages.extract:extract_javascript
    """

    Source:

    http://babel.edgewall.org/browser/trunk/setup.py#L38

    @vsajip
    Copy link
    Member

    vsajip commented Feb 1, 2014

    Another question to consider: is inspect the best place for this? I don't think it is, because

    (a) It's not really an inspection facility
    (b) Importing inspect to get this functionality would pull in lots
    of stuff which wouldn't be used in the typical use case.

    I think it makes more sense for it to be in importlib. Accordingly adding Brett to nosy, for his thoughts.

    @brettcannon
    Copy link
    Member

    importlib.util.resolve_name() already exists for resolving an explicit relative import name to an absolute one, so closing this as out of date.

    @vsajip
    Copy link
    Member

    vsajip commented Feb 1, 2014

    importlib.util.resolve_name() already exists

    But that's not what the proposed functionality is for, is it? This covers finding values inside an imported module which can be accessed via a dotted path from the module globals.

    @vsajip vsajip reopened this Feb 1, 2014
    @brettcannon
    Copy link
    Member

    Importlib already has importlib.import_module() (since Python 2.7) and that's as far as I'm willing to go for finding a module by name. Anything past that is a getarr() call on the resulting module and thus not worth adding to importlib.

    @vsajip
    Copy link
    Member

    vsajip commented Feb 1, 2014

    and thus not worth adding to importlib.

    Okay, fair enough. It's not purely an import function, though partly related to imports.

    @merwok
    Copy link
    Member Author

    merwok commented Jan 25, 2020

    With the lack of support, I suggest closing this.

    @vsajip
    Copy link
    Member

    vsajip commented Jan 25, 2020

    With the lack of support, I suggest closing this.

    Well, the lack of support is just for adding to importlib. It still seems useful to refactor it out ... just not clear where the best place is. Perhaps pkgutil? It's definitely useful to have in the stdlib in one place. I'll come up with a PR soon.

    @berkerpeksag
    Copy link
    Member

    FTR, Django has a similar helper:

        from django.utils.module_loading import import_string
    
        ValidationError = import_string('django.core.exceptions.ValidationError')

    https://docs.djangoproject.com/en/3.0/ref/utils/#django.utils.module_loading.import_string

    @vsajip
    Copy link
    Member

    vsajip commented Feb 14, 2020

    New changeset 1ed6161 by Vinay Sajip in branch 'master':
    bpo-12915: Add pkgutil.resolve_name (GH-18310)
    1ed6161

    @vsajip vsajip added the 3.9 only security fixes label Feb 14, 2020
    @vsajip vsajip closed this as completed Feb 14, 2020
    @vstinner
    Copy link
    Member

    The regex looks too strict. Python 3 accepts non-ASCII module names.

    Should existing functions be modified to reuse the new function?

    @vsajip
    Copy link
    Member

    vsajip commented Feb 15, 2020

    The regex looks too strict. Python 3 accepts non-ASCII module names.

    Would adding the re.U flag be enough, or are you thinking of other possibilities?

    @vsajip
    Copy link
    Member

    vsajip commented Feb 15, 2020

    To be more precise, one could use

    ^(?!\d)(\w+)(\.(?!\d)(\w+))* for _DOTTED_WORDS and use the re.U flag when compiling the pattern. That should match any packages where segments start with a letter and continue with alphanumerics. Do you agree?

    @vstinner
    Copy link
    Member

    I reopen the issue to discuss the non-ASCII identifiers.

    Currently, the code uses [a-z_]\w*, but "é" is a valid Python module name for example:

    $ echo 'print("here")' > é.py
    $ python3 -c 'import é'
    here

    I'm not sure how to design the regex. I just reported a potential issue ;-) See the PEP-3131 and str.isidentifier() method:
    https://docs.python.org/dev/library/stdtypes.html#str.isidentifier

    @vstinner vstinner reopened this Feb 17, 2020
    @vsajip
    Copy link
    Member

    vsajip commented Feb 17, 2020

    I'm not sure how to design the regex.

    Did you not look at the PR I added to address this (Unicode chars), with a regex change? I added you as a reviewer.

    @vsajip
    Copy link
    Member

    vsajip commented Feb 28, 2020

    New changeset 4f17c5c by Vinay Sajip in branch 'master':
    bpo-12915: Improve Unicode support for package names and attributes. (GH-18517)
    4f17c5c

    @aixtools
    Copy link
    Contributor

    PR18517 has, likely, a utf-8 dependency. AIX, default latin-1 does not accept the new test.

    Starting with this merge AIX bot fails with:
    ======================================================================
    ERROR: test_name_resolution (test.test_pkgutil.PkgutilTests)
    ----------------------------------------------------------------------

    Traceback (most recent call last):
      File "/home/buildbot/buildarea/3.x.aixtools-aix-power6/build/Lib/test/test_pkgutil.py", line 249, in test_name_resolution
        os.makedirs(d, exist_ok=True)
      File "/home/buildbot/buildarea/3.x.aixtools-aix-power6/build/Lib/os.py", line 223, in makedirs
        mkdir(name, mode)
    UnicodeEncodeError: 'latin-1' codec can't encode characters in position 17-19: ordinal not in range(256)

    Not completely resolved.

    @vstinner
    Copy link
    Member

    File "/home/buildbot/buildarea/3.x.aixtools-aix-power6/build/Lib/test/test_pkgutil.py", line 249, in test_name_resolution
    os.makedirs(d, exist_ok=True)
    (...)
    UnicodeEncodeError: 'latin-1' codec can't encode characters in position 17-19: ordinal not in range(256)

    The test should be modified to skip the current uw value in the loop ("continue") if the filesystem encoding cannot encode the Unicode string (catch UnicodeEncodeError on the makedirs() call).

    @aixtools
    Copy link
    Contributor

    aixtools commented Mar 1, 2020

    I am very busy with normal work this week. However I’ll attempt to add a pr with your (Victor”s) suggestion.

    Sent from my iPhone

    On 29 Feb 2020, at 23:36, STINNER Victor <report@bugs.python.org> wrote:

    
    STINNER Victor <vstinner@python.org> added the comment:

    > File "/home/buildbot/buildarea/3.x.aixtools-aix-power6/build/Lib/test/test_pkgutil.py", line 249, in test_name_resolution
    > os.makedirs(d, exist_ok=True)
    (...)
    > UnicodeEncodeError: 'latin-1' codec can't encode characters in position 17-19: ordinal not in range(256)

    The test should be modified to skip the current uw value in the loop ("continue") if the filesystem encoding cannot encode the Unicode string (catch UnicodeEncodeError on the makedirs() call).

    ----------


    Python tracker <report@bugs.python.org>
    <https://bugs.python.org/issue12915\>


    @vstinner
    Copy link
    Member

    vstinner commented Mar 3, 2020

    New changeset e0acec1 by Michael Felt in branch 'master':
    bpo-12915: Skip test_pkgutil.test_name_resolution() non-encodable filenames (GH-18720)
    e0acec1

    @vstinner
    Copy link
    Member

    vstinner commented Mar 3, 2020

    I understand that all known issues are now fixed, so I close the issue.

    @vstinner vstinner closed this as completed Mar 3, 2020
    @ned-deily
    Copy link
    Member

    See bpo-41154 for possible regression introduced by these changes.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.9 only security fixes stdlib Python modules in the Lib dir type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    10 participants