python / python/cpython

Self-documenting expressions conversion + format-spec

Open
#131,176 13 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

interpreter-core topic-parser type-feature
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Bug report

Bug description:
# initialisation
foo = "hello!"
bar = "hello, world!"
long_name = bar
print(f"{foo = }")
print(f"{bar = }")
print()

# these work as I expected
# they default to !r value conversion
print(f"{f"{foo=}" = }")
print(f"{f"{bar=}" = }")
print(f"{(f"{foo=}" == f"{foo=!r}") = }")
print()

# these do not work as I expected
# they default to !s value conversion, instead of !r
print(f"{f"{foo=:}" = }")
print(f"{f"{bar=:}" = }")
print(f"{(f"{foo=:}" == f"{foo=!r}") = }")
print(f"{(f"{foo=:}" == f"{foo=!s}") = }")
print()

# these do not work as I expected
# they apply padding to the expression value
# the expression itself is not taken into account
# as a result, the true string length is dependent on the expression length
print(f"{f"{bar=!r:20}." = }")
print(f"{len(f"{bar=!r:20}.") = }")
print(f"{f"{long_name=!r:20}." = }")
print(f"{len(f"{long_name=!r:20}.") = }")
print()

# these do not work as I expected
# they apply alignment only to the expression value
# the expression itself is always left-aligned
print(f"{f"{bar=!r:>20}" = }")
print(f"{len(f"{bar=!r:>20}") = }")
print(f"{f"{long_name=!r:>20}" = }")
print(f"{len(f"{long_name=!r:>20}") = }")
Expected results
  • Default value conversion mode should be consistent regardless of whether : is present
  • The whole self-documenting expression should be padded / aligned
import unittest
from secrets import token_urlsafe as random_string


class ExpectedResults(unittest.TestCase):
    def test_consistent_default_value_conversion_mode(self):
        my_value = random_string(16)
        first_way = f"{my_value=}"
        second_way = f"{my_value=:}"
        self.assertEqual(first_way, second_way)

    def test_pad_to_length(self):
        my_value = random_string(16)
        assert len(my_value) == 22
        value_only = f"{my_value!r:35}."
        self_documenting = f"{my_value=!r:35}."
        self.assertEqual(len(value_only), len(self_documenting))

    def test_alignment(self):
        my_value = random_string(16)
        assert len(my_value) == 22
        faux_self_documenting = f"{f"my_value={my_value!r}":>35}"
        assert not faux_self_documenting.startswith("my_value=")
        assert len(faux_self_documenting) == 35
        self_documenting = f"{my_value=!r:>35}"
        self.assertEqual(faux_self_documenting, self_documenting)

    def test_consistent_default_value_conversion_mode_exact(self):
        my_value = "report poet ethics"
        expected = "my_value='report poet ethics'"
        actual = f"{my_value=:}"
        self.assertEqual(expected, actual)

    def test_pad_to_length_exact(self):
        my_value = 'sugar lemon dilemma'
        expected = "my_value='sugar lemon dilemma'      "
        assert len(expected) == 36
        actual = f"{my_value=!r:36}"
        self.assertEqual(expected, actual)
        # or alternatively
        self.assertEqual(36, len(actual))

    def test_alignment_exact(self):
        my_value = 'bonus thought skull'
        expected = "   my_value='bonus thought skull'   "
        assert len(expected) == 36
        actual = f"{my_value=!r:^36}"
        self.assertEqual(expected, actual)

if __name__ == "__main__":
    unittest.main()
CPython versions tested on:

3.13

Operating systems tested on:

Linux

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the reported f-string conversion, padding, and alignment cases on Python 3.13, then trace the f-string parsing and formatting entry points in CPython. Add regression tests covering the supplied expected results; done means colon-bearing self-documenting expressions match the no-colon conversion and format the complete expression consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.