This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Improve the TypeError message for non-string second arguments passed to the built-in functions getattr and hasattr
Type: enhancement Stage: resolved
Components: Interpreter Core Versions: Python 3.11
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: maggyero, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2021-05-03 22:50 by maggyero, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 25863 merged maggyero, 2021-05-03 22:51
Messages (5)
msg392843 - (view) Author: Géry (maggyero) * Date: 2021-05-03 22:50
Problem
-------

Actual behaviour:

```python
>>> getattr('foobar', 123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: getattr(): attribute name must be string
>>> hasattr('foobar', 123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: hasattr(): attribute name must be string
```

Expected behaviour:

```python
>>> getattr('foobar', 123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: attribute name must be string, not 'int'
>>> hasattr('foobar', 123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: attribute name must be string, not 'int'
```

Motivation:

```python
>>> setattr('foobar', 123, 'baz')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: attribute name must be string, not 'int'
>>> delattr('foobar', 123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: attribute name must be string, not 'int'
```

Solution
--------

In the function `builtin_getattr` defined in Python/bltinmodule.c, we remove the following lines:

```c
if (!PyUnicode_Check(name)) {
        PyErr_SetString(PyExc_TypeError,
                        "getattr(): attribute name must be string");
        return NULL;
    }
```

because the expected `TypeError` message is already implemented in the subsequent call to the functions `_PyObject_LookupAttr` and `PyObject_GetAttr` defined in Objects/object.c:

```c
PyObject *
PyObject_GetAttr(PyObject *v, PyObject *name)
{
    PyTypeObject *tp = Py_TYPE(v);
    if (!PyUnicode_Check(name)) {
        PyErr_Format(PyExc_TypeError,
                     "attribute name must be string, not '%.200s'",
                     Py_TYPE(name)->tp_name);
        return NULL;
    }

[…]

int
_PyObject_LookupAttr(PyObject *v, PyObject *name, PyObject **result)
{
    PyTypeObject *tp = Py_TYPE(v);

    if (!PyUnicode_Check(name)) {
        PyErr_Format(PyExc_TypeError,
                     "attribute name must be string, not '%.200s'",
                     Py_TYPE(name)->tp_name);
        *result = NULL;
        return -1;
    }

[…]
```

Likewise, in the function `builtin_hasattr_impl` defined in Python/bltinmodule.c, we remove the following lines:

```c
if (!PyUnicode_Check(name)) {
        PyErr_SetString(PyExc_TypeError,
                        "hasattr(): attribute name must be string");
        return NULL;
    }
```

because the expected `TypeError` message is already implemented in the subsequent call to the function `_PyObject_LookupAttr` defined in Objects/object.c.
msg409745 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2022-01-05 09:56
Good point. That code was originally added in issue420304 because every exception raised in PyObject_GetAttr() (including a TypeError for non-string name) was silenced in hasattr() and 3-argument getattr(). It was changed in Python 3, so this code duplication is no longer needed.

The name of the function was added in error messages in a9b9c9fa9fe9d1ae74ba9f89c43557a7f9bc04f5. Now it will gone. It is a minor regression, but I think that it is fine. Not all error messages contain a function name. In this case the context is clear from the traceback, and the error is not specific to these two functions, setattr() and delattr() raise the same error.
msg410889 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2022-01-18 20:46
New changeset 16bf9bd157c7bf5f9c60414fa8e0fe5047c55a9b by Géry Ogam in branch 'main':
bpo-44024: Improve the TypeError message in getattr and hasattr (GH-25863)
https://github.com/python/cpython/commit/16bf9bd157c7bf5f9c60414fa8e0fe5047c55a9b
msg410890 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2022-01-18 20:47
Thank you for your contribution Géry.
msg410899 - (view) Author: Géry (maggyero) * Date: 2022-01-18 21:41
Thanks for the review Serhiy.
History
Date User Action Args
2022-04-11 14:59:45adminsetgithub: 88190
2022-01-18 21:41:03maggyerosetmessages: + msg410899
2022-01-18 20:47:30serhiy.storchakasetstatus: open -> closed
resolution: fixed
messages: + msg410890

stage: patch review -> resolved
2022-01-18 20:46:35serhiy.storchakasetmessages: + msg410889
2022-01-05 09:56:44serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg409745
2022-01-05 01:41:38eric.araujosettype: behavior -> enhancement
versions: - Python 3.9, Python 3.10
2021-05-22 07:24:04wyz23x2setversions: - Python 3.6, Python 3.7, Python 3.8
2021-05-05 12:20:20maggyerosettitle: Improve the error message for non-string second arguments passed to the built-in functions getattr and hasattr -> Improve the TypeError message for non-string second arguments passed to the built-in functions getattr and hasattr
2021-05-04 20:45:29maggyerosettitle: Use common TypeError message for built-in functions getattr and hasattr -> Improve the error message for non-string second arguments passed to the built-in functions getattr and hasattr
2021-05-03 22:51:06maggyerosetkeywords: + patch
stage: patch review
pull_requests: + pull_request24544
2021-05-03 22:50:44maggyerocreate