Sitelet https://github.com/python/cpython/issues/70764#issuecomment-1093710189
Skip to content

inspect.getclosurevars returns incorrect variable when using class member with the same name as other variable #70764

Description

@RyanFox
mannequin
BPO 26577
Nosy @1st1, @hongweipeng, @iritkatriel

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 = None
created_at = <Date 2016-03-17.07:40:30.852>
labels = ['type-bug', 'library', '3.11']
title = 'inspect.getclosurevars returns incorrect variable when using class member with the same name as other variable'
updated_at = <Date 2021-12-18.20:30:07.566>
user = 'https://bugs.python.org/RyanFox'

bugs.python.org fields:

activity = <Date 2021-12-18.20:30:07.566>
actor = 'Ryan Fox'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2016-03-17.07:40:30.852>
creator = 'Ryan Fox'
dependencies = []
files = []
hgrepos = []
issue_num = 26577
keywords = []
message_count = 4.0
messages = ['261897', '407082', '408856', '408866']
nosy_count = 4.0
nosy_names = ['yselivanov', 'Ryan Fox', 'hongweipeng', 'iritkatriel']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue26577'
versions = ['Python 3.11']

Linked PRs

Activity

  1. RyanFox commented on Mar 17, 2016

    RyanFoxmannequin
    MannequinAuthor

    If a variable 'x' exists in the global or local scope, and a function (also defined in the same scope as 'x', or lower) refers only to a member named 'x' of an object, inspect.getclosurevars will include a reference to the variable, rather than the member.

    Okay, that's kind of confusing to describe, so here's a small example in code form:

    import inspect
    
    class Foo:
        x = int()
    
    x = 1
    f = Foo()
    assert(f.x != x)
    
    func = lambda: f.x == 0
    assert(func())
    
    cv = inspect.getclosurevars(func)
    assert(cv.globals['f'] == f)
    assert(cv.globals.get('x') != x) # <--- Assertion fails

    It is expected that 'x' would not exist in cv.globals, since func does not refer to it. Also, there should be a 'f.x' included somewhere in the ClosureVariables object returned.

  2. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Mar 17, 2016
  3. iritkatriel commented on Nov 26, 2021

    @iritkatriel
    Member

    Reproduced on 3.11.

  4. hongweipeng commented on Dec 18, 2021

    hongweipengmannequin
    Mannequin

    Why is expected that 'x' would not exist in cv.globals? I think it works normally, you can see x in func.__globals__.

  5. RyanFox commented on Dec 18, 2021

    RyanFoxmannequin
    MannequinAuthor

    If you change the class member 'x' to a different name like 'y', then cv
    doesn't include 'x', but does include an unbound 'y'.

    In both cases, the function isn't referring to a global variable, just the
    class member of that name. Besides the function itself, no other globals
    are included in cv.globals.

    On Sat, Dec 18, 2021 at 10:34 AM hongweipeng <report@bugs.python.org> wrote:

    hongweipeng hongweichen8888@sina.com added the comment:

    Why is expected that 'x' would not exist in cv.globals? I think it works
    normally, you can see x in func.__globals__.

    ----------
    nosy: +hongweipeng


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


  6. transferred this issue fromon Apr 10, 2022
  7. dansalvato commented on Jul 4, 2023

    @dansalvato

    This had me scratching my head when a class member happened to be named the same as an imported module. Example:

    import inspect
    
    class TestClass:
        def __init__(self):
            self.inspect = 123
            self.something = 456
    
    testclass = TestClass()
    print(inspect.getclosurevars(testclass.__init__))

    Output:

    ClosureVars(nonlocals={}, globals={'inspect': <module 'inspect' from '/.../python3.11/inspect.py'>}, builtins={}, unbound={'something'})
    

    Clearly, self.inspect refers to a class member and not the global module, but getclosurevars() doesn't understand this.

    It seems pretty easy for this to happen; in my case, it was a setter for self.image being conflated with an imported module image.

  8. added 2 commits that reference this issue on Jun 6, 2024
  9. added a commit that references this issue on Nov 5, 2024
  10. added 2 commits that reference this issue on Nov 5, 2024
  11. added 2 commits that reference this issue on Nov 6, 2024
  12. added a commit that references this issue on Dec 8, 2024
  13. added a commit that references this issue on Jan 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.11only security fixesstdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions