GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Inaccurate emulation of _PyType_Lookup() in the Descriptor HOWTO · Issue #95822 · python/cpython

Inaccurate emulation of _PyType_Lookup() in the Descriptor HOWTO #95822

New issue
Copy link
New issue
Copy link
Closed
Closed
Inaccurate emulation of _PyType_Lookup() in the Descriptor HOWTO#95822
Copy link
Assignees
rhettinger
Labels
docsDocumentation in the Doc dirDocumentation in the Doc dir

Description

@iyume
iyume
opened on Aug 9, 2022
Issue body actions

Documentation

Doc link: https://docs.python.org/3.10/howto/descriptor.html#invocation-from-an-instance

Source: https://github.com/python/cpython/blame/eb81c1aea16914347919745e843c982ed831a9fb/Doc/howto/descriptor.rst#L585-L601

The code example is bad at https://github.com/python/cpython/blame/eb81c1aea16914347919745e843c982ed831a9fb/Doc/howto/descriptor.rst#L589

getattr(objtype, name) will go through descriptor.__get__.

Code Snippet:

class A:
    def __get__(self, obj, objtype):
        return obj, objtype

class B:
    a = A()

print(B().a)
# (<__main__.B object at 0x7ff56d0915e0>, <class '__main__.B'>)
print(B.a)  # same as getattr
# (None, <class '__main__.B'>)

Solution

Using __dict__ (or vars) instead of getattr:

print(vars(B)['a'])
# <__main__.A object at 0x7ff56cfef2b0>

Activity

  1. iyume
    added
    docsDocumentation in the Doc dirDocumentation in the Doc dir
    on Aug 9, 2022
  2. AlexWaygood
    assigned
    rhettinger
    on Aug 9, 2022
  3. rhettinger commented on Aug 10, 2022

    @rhettinger
    rhettinger
    on Aug 10, 2022
    Contributor
    More actions

    Thanks for the bug report. Here's a proposed update that replaces getattr(objtype, name) with find_name_in_mro(objtype, name, null):

    def find_name_in_mro(cls, name, default):
        "Emulate _PyType_Lookup() in Objects/typeobject.c"
        for base in cls.__mro__:
            if name in vars(base):
                return vars(base)[name]
        return default
    
    def object_getattribute(obj, name):
        "Emulate PyObject_GenericGetAttr() in Objects/object.c"
        null = object()
        objtype = type(obj)
        cls_var = find_name_in_mro(objtype, name, null)    
        descr_get = getattr(type(cls_var), '__get__', null)
        if descr_get is not null:
            if (hasattr(type(cls_var), '__set__')
                or hasattr(type(cls_var), '__delete__')):
                return descr_get(cls_var, obj, objtype)     # data descriptor
        if hasattr(obj, '__dict__') and name in vars(obj):
            return vars(obj)[name]                          # instance variable
        if descr_get is not null:
            return descr_get(cls_var, obj, objtype)         # non-data descriptor
        if cls_var is not null:
            return cls_var                                  # class variable
        raise AttributeError(name)
    

    Also, I want to add tests to cover your example and to cover why the fix proposed in the PR was incorrect.

  4. rhettinger
    changed the title [-]Doc: descriptior HOWTO bad example[/-] [+]Inaccurate emulation of _PyType_Lookup() in the Descriptor HOWTO[/+] on Aug 10, 2022
  5. rhettinger
    added a commit that references this issue on Aug 13, 2022

    pythonGH-95822: Need _PyType_Lookup() in descriptor howto code equiva…

    013ab10
  6. miss-islington
    added a commit that references this issue on Aug 19, 2022

    pythonGH-95822: Need _PyType_Lookup() in descriptor howto code equiva…

    4272abc
  7. rhettinger
    added a commit that references this issue on Aug 19, 2022

    GH-95822: Need _PyType_Lookup() in descriptor howto code equivalent. (G…

    6740680
  8. miss-islington
    added a commit that references this issue on Aug 19, 2022

    pythonGH-95822: Need _PyType_Lookup() in descriptor howto code equiva…

    2d206e7
  9. rhettinger
    added 2 commits that reference this issue on Aug 19, 2022

    GH-95822: Need _PyType_Lookup() in descriptor howto code equivalent. (G…

    b6e8304

    GH-95822: Need _PyType_Lookup() in descriptor howto code equivalent. (G…

    d699068
  10. rhettinger commented on Aug 19, 2022

    @rhettinger
    rhettinger
    on Aug 19, 2022
    Contributor
    More actions

    Thanks for the report. This is fixed now.

  11. rhettinger
    closed this as completedon Aug 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @rhettinger
    rhettinger

Labels

docsDocumentation in the Doc dirDocumentation in the Doc dir

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.