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: doc: Clarify error message when attempting to call function via str.format()
Type: enhancement Stage: resolved
Components: Documentation, Interpreter Core Versions: Python 3.10
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: eric.smith, iritkatriel, mickey695, miss-islington, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2017-10-31 00:35 by mickey695, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 25053 merged iritkatriel, 2021-03-28 19:11
PR 25055 merged miss-islington, 2021-03-28 20:47
PR 25056 merged miss-islington, 2021-03-28 20:47
Messages (12)
msg305263 - (view) Author: (mickey695) Date: 2017-10-31 00:35
PEP 3101 states that format strings may only use the "."(getattr) or the "[]" (getitem) operators to address either attributes or items of parameters.
Should a programmer attempt to, for example, call a function of a parameter as follows: 

>>> d = datetime.datetime(2017, 10, 31)
>>> "{0.ctime()}".format(d)

they will receive an error message such as:

AttributeError: 'datetime.datetime' object has no attribute 'ctime()'

Proposal:
Raise an error stating that cannot embed arbitrary expressions in str.format() format strings
msg305276 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2017-10-31 07:43
How would you distinguish this from the case where an actually missing attribute was given?

>>> "{0.ctimex}".format(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'datetime.datetime' object has no attribute 'ctimex'

I guess it would be possible to change the parser to only look for valid chars in an identifier and give an error if there were "extra" chars found, but I'm not sure it's worth the hassle. The error message seems clear enough to me. Also, I wouldn't want to change this to not be an AttributeError (for backward compatibility), and I'm not sure an AttributeError with a different message would be good.

Of course, this works with f-strings:

>>> f"{d.ctime()}"
'Tue Oct 31 00:00:00 2017'

And I just realized that your code actually is valid, with a custom __getattr__. And while I wouldn't recommend doing this, I also wouldn't want to break it. For all I know, people have written custom evaluators in __getattr__:

>>> class C:
...     def __getattr__(self, name):
...         if name == 'ctime()':
...             return 'okay'
...         raise AttributeError('not found')
...

>>> '{0.x}'.format(C())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __getattr__
AttributeError: not found

>>> '{0.ctime()}'.format(C())
'okay'

I'm changing versions because this would be a new feature, since it breaks valid code.
msg305287 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-10-31 11:23
I have wrote a patch that change the parser to only accept valid identifiers. But now I have the same doubts and want first to discuss this [1]. This change can break the existing code as Eric's example shows.

[1] https://mail.python.org/pipermail/python-dev/2017-October/150052.html
msg305413 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2017-11-02 10:34
Guido's suggestion in https://mail.python.org/pipermail/python-dev/2017-October/150055.html is to not change anything.

Assuming we do that, it's still an open issue as to if/how we should document and test the current behavior. I'd be surprised if it's tested, but I haven't looked.
msg305496 - (view) Author: (mickey695) Date: 2017-11-03 18:53
I think it should be documented properly.

In roughly two weeks I will have some time to look into it. 
So I could probably document the current behaviour by the start of December(unless someone beats me to it)
msg309183 - (view) Author: (mickey695) Date: 2017-12-29 17:59
Well, it has been more than the 2 weeks I promised however now I finally have time to look into this.

I did some fuzzing to build a list quickly and the following ASCII characters can not be used as part of the argument name:
exclamation mark(!)
period(.)
colon(:)
opening square bracket([)
opening/closing curly brackets({})

also, the argument name may not start with digits from zero to nine(0-9)

Basically what needs to be changed is arg_name under the section "Format String Syntax" in \Doc\library\string.rst

Problem is, I really don't understand the syntax of the Python/sphinx formal language.

The following expression is what I came up with:
arg_name ::= [^`decinteger`] [<any character except "!" | "." | "[" | "{" | "}"> | `integer` ]+

If anyone from the documentation team could look into it I would be grateful.

Moreover, I think attribute_name should probably be changed as it does not have to be a valid identifier. In fact, it can be any text. Eric V. Smiths' example can be used with any text as the attribute name. A comment should be added to the aforementioned section explaining that normally only valid identifiers are accepted, however by implementing your own __getattr__ this can be changed.
msg389405 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2021-03-23 19:23
I would suggest the following change in https://docs.python.org/3/library/string.html#format-string-syntax

replace the sentence:

The syntax is related to that of formatted string literals, but there are differences.

by:

The syntax is related to that of formatted string literals, but it is less sophisticated and, in particular, does not support arbitrary expressions.

Is this accurate? Is it enough?
msg389642 - (view) Author: (mickey695) Date: 2021-03-28 18:46
Happy passover Irit(and/or anyone else celebrating)!

While your suggestion is accurate, I can't say whether it's enough or not.
This is up to you and the other python language development forum to decide :)
msg389644 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-03-28 18:59
> The syntax is related to that of formatted string literals, but it is less sophisticated and, in particular, does not support arbitrary expressions.

That seems fine to me.
msg389648 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-03-28 20:47
New changeset fb1d01b9630b5069fe975f16e07a027d90b89434 by Irit Katriel in branch 'master':
bpo-31907: [doc] clarify that str.format() does not support arbitrary expressions (#25053)
https://github.com/python/cpython/commit/fb1d01b9630b5069fe975f16e07a027d90b89434
msg389649 - (view) Author: miss-islington (miss-islington) Date: 2021-03-28 20:57
New changeset 24ba0ea9e0160cc85e0fa24f32b1651c8b3a24b0 by Miss Islington (bot) in branch '3.8':
[3.8] bpo-31907: [doc] clarify that str.format() does not support arbitrary expressions (GH-25053) (GH-25056)
https://github.com/python/cpython/commit/24ba0ea9e0160cc85e0fa24f32b1651c8b3a24b0
msg389650 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2021-03-28 21:05
New changeset 9a8e0780247acb256dd8b04c15b3dd0f59ef2fe1 by Miss Islington (bot) in branch '3.9':
bpo-31907: [doc] clarify that str.format() does not support arbitrary expressions (GH-25053) (GH-25055)
https://github.com/python/cpython/commit/9a8e0780247acb256dd8b04c15b3dd0f59ef2fe1
History
Date User Action Args
2022-04-11 14:58:53adminsetgithub: 76088
2021-03-28 21:05:16eric.smithsetmessages: + msg389650
2021-03-28 20:58:54eric.smithsetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2021-03-28 20:57:21miss-islingtonsetmessages: + msg389649
2021-03-28 20:47:54miss-islingtonsetpull_requests: + pull_request23803
2021-03-28 20:47:47miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request23802
2021-03-28 20:47:39eric.smithsetmessages: + msg389648
2021-03-28 19:11:55iritkatrielsetkeywords: + patch
stage: patch review
pull_requests: + pull_request23801
2021-03-28 18:59:08eric.smithsetmessages: + msg389644
2021-03-28 18:47:36mickey695setversions: + Python 3.10
2021-03-28 18:46:14mickey695setmessages: + msg389642
versions: - Python 3.10
2021-03-23 19:23:33iritkatrielsetnosy: + iritkatriel
title: Clarify error message when attempting to call function via str.format() -> doc: Clarify error message when attempting to call function via str.format()
messages: + msg389405

versions: + Python 3.10, - Python 3.7
2017-12-29 17:59:42mickey695setmessages: + msg309183
components: + Documentation
2017-11-03 18:53:37mickey695setmessages: + msg305496
2017-11-02 10:34:07eric.smithsetmessages: + msg305413
2017-10-31 11:23:41serhiy.storchakasetstatus: pending -> open
nosy: + serhiy.storchaka
messages: + msg305287

2017-10-31 07:43:17eric.smithsetstatus: open -> pending

nosy: + eric.smith
versions: - Python 2.7, Python 3.4, Python 3.5, Python 3.6, Python 3.8
messages: + msg305276

assignee: eric.smith
2017-10-31 00:35:20mickey695create