Skip to content

__qualname__ is not present on builtin methods and functions #57786

Closed

Description

@meadori
BPO 13577
Nosy @gvanrossum, @jcea, @pitrou, @meadori
Files
  • descr_qualname.patch
  • descr_qualname.patch
  • descr_qualname.patch
  • method_qualname.patch
  • descr_qualname.patch
  • method_qualname.patch
  • method_qualname.patch
  • method_qualname.patch
  • 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 2011-12-23.11:42:04.400>
    created_at = <Date 2011-12-11.04:27:04.637>
    labels = ['interpreter-core', 'type-bug']
    title = '__qualname__ is not present on builtin methods and functions'
    updated_at = <Date 2011-12-23.11:42:04.399>
    user = 'https://github.com/meadori'

    bugs.python.org fields:

    activity = <Date 2011-12-23.11:42:04.399>
    actor = 'pitrou'
    assignee = 'none'
    closed = True
    closed_date = <Date 2011-12-23.11:42:04.400>
    closer = 'pitrou'
    components = ['Interpreter Core']
    creation = <Date 2011-12-11.04:27:04.637>
    creator = 'meador.inge'
    dependencies = []
    files = ['23913', '23914', '23922', '23926', '23927', '23930', '23941', '24068']
    hgrepos = []
    issue_num = 13577
    keywords = ['patch']
    message_count = 19.0
    messages = ['149209', '149225', '149226', '149235', '149238', '149240', '149262', '149286', '149291', '149293', '149296', '149299', '149302', '149379', '149385', '149981', '150010', '150152', '150153']
    nosy_count = 6.0
    nosy_names = ['gvanrossum', 'jcea', 'pitrou', 'meador.inge', 'python-dev', 'sbt']
    pr_nums = []
    priority = 'high'
    resolution = 'rejected'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue13577'
    versions = ['Python 3.3']

    Activity

    1. meadori commented on Dec 11, 2011

      @meadori
      MemberAuthor

      I was recently experimenting with the new PEP-3155 '__qualname__ implementation and noticed that '__qualname__' is not present on builtin methods and functions:

      [meadori@motherbrain cpython]$ ./python 
      Python 3.3.0a0 (default:aab45b904141+, Dec 10 2011, 14:53:54) 
      [GCC 4.6.2 20111027 (Red Hat 4.6.2-1)] on linux
      Type "help", "copyright", "credits" or "license" for more information.
      >>> max.__qualname__
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      AttributeError: 'builtin_function_or_method' object has no attribute '__qualname__'
      >>> str.strip.__qualname__
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      AttributeError: 'method_descriptor' object has no attribute '__qualname__'

      I will work up a patch.

    2. added
      interpreter-core(Objects, Python, Grammar, and Parser dirs)
      type-bugAn unexpected behavior, bug, or error
      on Dec 11, 2011
    3. sbt commented on Dec 11, 2011

      sbtmannequin
      Mannequin

      I already have a patch for the descriptor types which lazily calculates the __qualname__. However test.test_sys also needs fixing because it tests that these types have expected sizes.

      I have not got round to builtin_function_or_method though.

    4. sbt commented on Dec 11, 2011

      sbtmannequin
      Mannequin

      Updated patch which fixes test.test_sys.SizeofTest. (It also adds __qualname__ to member descriptors and getset descriptors.)

    5. pitrou commented on Dec 11, 2011

      @pitrou
      Member

      The patch should add some tests for the added functionality (I'm not sure where, but perhaps test_descr is a good location).

      Also, just a nitpick, you can use _PyObject_GetAttrId and the _Py_IDENTIFIER macro instead of interning the "__qualname__" string yourself.

      Note that extension (non-builtin) types will need to have their __qualname__ fixed before their methods' __qualname__ is usable:

      >>> collections.deque.__qualname__
      'deque'
    6. sbt commented on Dec 11, 2011

      sbtmannequin
      Mannequin

      Note that extension (non-builtin) types will need to have their
      __qualname__ fixed before their methods' __qualname__ is usable:

      >>> collections.deque.__qualname__
      'deque'

      I'm confused. Isn't that the expected behaviour? Since the deque class is not nested inside another class or function, __qualname__ should be the same as __name__, shouldn't it?

    7. pitrou commented on Dec 11, 2011

      @pitrou
      Member

      > Note that extension (non-builtin) types will need to have their
      > __qualname__ fixed before their methods' __qualname__ is usable:
      >
      > >>> collections.deque.__qualname__
      > 'deque'

      I'm confused. Isn't that the expected behaviour? Since the deque
      class is not nested inside another class or function, __qualname__
      should be the same as __name__, shouldn't it?

      Uh, yes, my bad.

    8. sbt commented on Dec 12, 2011

      sbtmannequin
      Mannequin

      New version of the patch with tests and using _Py_IDENTIFIER.

    9. pitrou commented on Dec 12, 2011

      @pitrou
      Member

      Ok, a couple of further (minor) issues:

      • I don't think AssertionError is the right exception type. TypeError should be used when a type mismatches (e.g. "not an unicode object");
      • you don't need to check for d_type being NULL, since other methods don't;
      • if type_qualname == NULL, the original error should be retained.

      Otherwise, looks good, thank you.

    10. sbt commented on Dec 12, 2011

      sbtmannequin
      Mannequin

      Patch which add __qualname__ to builtin_function_or_method. Note that I had to make a builtin staticmethod have __self__ be the type instead of None.

    11. sbt commented on Dec 12, 2011

      sbtmannequin
      Mannequin

      Ok, a couple of further (minor) issues:

      • I don't think AssertionError is the right exception type. TypeError
        should be used when a type mismatches (e.g. "not an unicode object");
      • you don't need to check for d_type being NULL, since other methods don't;
      • if type_qualname == NULL, the original error should be retained.

      Fixed. (I suspect, though, that caching the value of __qualname__ is an unnecessary optimisation.)

    12. python-dev commented on Dec 12, 2011

      python-devmannequin
      Mannequin

      New changeset 24238e89f938 by Antoine Pitrou in branch 'default':
      Issue bpo-13577: various kinds of descriptors now have a __qualname__ attribute.
      http://hg.python.org/cpython/rev/24238e89f938

    13. pitrou commented on Dec 12, 2011

      @pitrou
      Member

      About method_qualname.patch:

      • apparently you forgot to add BuiltinFunctionPropertiesTest in test_main()?

      • a static method keeps a reference to the type: I think it's ok, although I'm not sure about the consequences (Guido, would you have an idea?)

      • about "XXX Note that it is not possible to use __qualname__ to distinguish a builtin bound instance method from its unbound equivalent", I don't think it's a problem. People can e.g. check for __self__:

      >>> list.append.__self__
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      AttributeError: 'method_descriptor' object has no attribute '__self__'
      >>> list().append.__self__
      []
    14. sbt commented on Dec 12, 2011

      sbtmannequin
      Mannequin
      • apparently you forgot to add BuiltinFunctionPropertiesTest in
        test_main()?

      Yes. Fixed.

      • a static method keeps a reference to the type: I think it's ok, although
        I'm not sure about the consequences (Guido, would you have an idea?)

      Interestingly, in the stdlib METH_STATIC is only used by (str|bytes|bytearray).maketrans and _multiprocessing.win32.*.

    15. meadori commented on Dec 13, 2011

      @meadori
      MemberAuthor

      For the most part this looks OK, but I am not sure about this hunk:

      diff --git a/Objects/typeobject.c b/Objects/typeobject.c
      --- a/Objects/typeobject.c
      +++ b/Objects/typeobject.c
      @@ -3724,7 +3724,7 @@ add_methods(PyTypeObject *type, PyMethod
                   descr = PyDescr_NewClassMethod(type, meth);
               }
               else if (meth->ml_flags & METH_STATIC) {
      -            PyObject *cfunc = PyCFunction_New(meth, NULL);
      +            PyObject *cfunc = PyCFunction_New(meth, (PyObject*)type);
                   if (cfunc == NULL)
                       return -1;
                   descr = PyStaticMethod_New(cfunc);

      That may be a breaking change as existing code may rely on the 'None' behavior. In
      fact, this causes a unit test to fail with the patch applied:

      [meadori@motherbrain cpython]$ ./python -m test test_descr
      [1/1] test_descr
      test test_descr failed -- Traceback (most recent call last):
        File "/home/meadori/src/python/cpython/Lib/test/test_descr.py", line 1485, in test_staticmethods_in_c
          self.assertEqual(x, None)
      AssertionError: <class 'xxsubtype.spamlist'> != None

      sbt, have you been running the test suite before submitting patches? If not, then
      please do.

    16. sbt commented on Dec 13, 2011

      sbtmannequin
      Mannequin

      sbt, have you been running the test suite before submitting patches?
      If not, then please do.

      I ran it after I submitted. Sorry.

      Here is another patch. It also makes sure that __self__ is reported as None when METH_STATIC.

    17. pitrou commented on Dec 21, 2011

      @pitrou
      Member

      Thanks for the patch. Since you modified PyCFunction_GET_SELF to return NULL for static methods, why not simply use it instead of manually looking up the flags in several places?

      I'm talking about the following changes:

      -    PyObject *self = PyCFunction_GET_SELF(func);
      +    int flags = PyCFunction_GET_FLAGS(func);
      +    PyObject *self = flags & METH_STATIC ? NULL :
      +        _PyCFunction_GET_RAW_SELF(func);

      [...]

           self = m->m_self;
      -    if (self == NULL)
      +    if (self == NULL || PyCFunction_GET_FLAGS(m) & METH_STATIC)
               self = Py_None;

      [...]

      •        PyObject \*self = PyCFunction_GET_SELF(func);
        

      + PyObject *self = flags & METH_STATIC ? NULL :
      + _PyCFunction_GET_RAW_SELF(func);

      Unless you demonstrate there's a significant performance improvement in this style, we should really favour the simpler style.

    18. sbt commented on Dec 21, 2011

      sbtmannequin
      Mannequin

      A simplified patch getting rid of _PyCFunction_GET_RAW_SELF().

    19. python-dev commented on Dec 23, 2011

      python-devmannequin
      Mannequin

      New changeset 7a7b698f6f21 by Antoine Pitrou in branch 'default':
      Issue bpo-13577: Built-in methods and functions now have a __qualname__.
      http://hg.python.org/cpython/rev/7a7b698f6f21

    20. pitrou commented on Dec 23, 2011

      @pitrou
      Member

      The patch is committed, thank you!

    21. transferred this issue fromon Apr 10, 2022
    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

      interpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions