New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pathlib Path objects should support __format__ #82403
Comments
Currently pathlib.Path cannot be used with string formatting directives. IMO it should. >>> from pathlib import Path
>>> path = Path('/path/to/enlightenment')
>>> print(f'path is: {path:>50}')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported format string passed to PosixPath.__format__ |
Convert it to string first: print(f'path is: {path!s:>50}') |
I agree with Serhiy that !s solves the problem. But as a convenience it might be nice to add __format__. This issue pops up from time to time on Path and other types, and I don't think !s is very discoverable. Especially because formatting works with a specifier, but fails with one: >>> format(path)
'/path/to/enlightenment'
>>> format(path, '>50')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported format string passed to PosixPath.__format__ |
Initially, the default __format__ converted the object to str and passed format specifier to str.__format__. This is defined in PEP-3101: class object:
def __format__(self, format_spec):
return format(str(self), format_spec) But later we changed the implementation, because this leaded to difficult to catch errors. Non-empty format specifier is now error in the default __format__. |
Correct: this change was made specifically so that objects could add their own format specifiers at a later time. If I recall correctly, This change was precipitated by wanting to add datetime.__format__: this change broke existing uses for format() that formatted datetimes as strings. But the result is that objects that really just want to be formatted as strings need to have their own __format__ which returns format(str(self), format_spec). |
Or use !s or !r. In some cases it may be even better to use both convertions: f'{str(path)!r:>50}'. This is all application specific, so I do not think we should rethink our old decision. Explicit is better than implicit. |
I don't think anyone is suggesting reverting the decision on object.__format__. That decision should stay. I think the suggestion is to add Path.__format__, which just converts to a string and formats with the given spec. Unless someone can think of a reason to have a different format specifier language for Path, I think this is a good usability improvement. |
I am -0 on this. It is a can of worms. Once we add a trivial __format__ in Path, we will need to handle numerous requests for adding a trivial __format__ in many other classes. It is better to teach users to use !s (and this works also on older Python versions!). As for Path, there many ways to convert it to string: str(), repr(), os.fspath(), os.fsdecode(), Path.as_posix(), Path.as_uri(), with possible normalization, converting to absolute or relative path. I would not bet that we will never have reasons to have a different format specifier language for Path. |
I'm also -0 on it. It's up to Antoine. |
I don't think it violates " Explicit is better than implicit." |
I'm -1 as PEP-519 created __fspath__ specifically so that pathlib.Path wouldn't be confused as a string by accident. You can also use os.fspath() to get a string representation of the path itself. I also don't know if Antoine wants to make this sort of call for pathlib anymore as he isn't listed in https://devguide.python.org/experts/ or https://github.com/python/cpython/blob/master/.github/CODEOWNERS for pathlib anymore (and that was an explicit choice based on code history for the experts index). |
I would like for this to be reconsidered. Yes, you can use str(), but converting back and forth becomes really clunky: log_dir = 'logs/{date}'
log_file = Path(str(path).format(time.strftime('%Y-%m-%d')) / 'log.txt' |
Sorry, that should have been: log_dir = Path('logs/{date}') |
(I think you're missing "date=" in the call to .format().) Could you show what you think this would look like if Path.__format__ existed? I don't think anyone's suggesting that path.format() would be added by this issue, but maybe that would be a reasonable proposal as a different issue. |
I would be in favour of adding Path.__format__, even though I'm not terribly convinced by the use case presented. |
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:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: