Skip to content

refactor(python): rename FormattableString field from str to fmt#4637

Merged
dbrattli merged 1 commit into
mainfrom
fix/py-formattablestring-fmt-field
Jun 9, 2026
Merged

refactor(python): rename FormattableString field from str to fmt#4637
dbrattli merged 1 commit into
mainfrom
fix/py-formattablestring-fmt-field

Conversation

@dbrattli

@dbrattli dbrattli commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Problem

The Python representation of FormattableString used a field literally named str, so a $"...{x}..." interpolation typed as FormattableString compiled to an object expression with a @property def str:

class ObjectExpr2405:
    @property
    def str(self, __unit: Unit=UNIT) -> str:   # <- field named `str`
        return "You owe: {0:N5} {1} {2}"
    @property
    def args(self, __unit: Unit=UNIT) -> Array[Any]:
        return Array[Any]([int32(100), int32.THREE, True])

This runs correctly and Pyright accepts it — under PEP 563 (from __future__ import annotations) the -> str return annotation resolves to the builtin (get_type_hints confirms {'return': <class 'str'>}), and the property never shadows the builtin since attribute names live in a separate namespace.

However, Astral's ty resolves the annotation against the class-scoped str property and reports a false positive:

error[invalid-type-form]: Variable of type `property` is not allowed in a return type annotation
    --> temp/tests/Python/test_string.py:1039:45
1039 |         def str(self, __unit: Unit=UNIT) -> str:

Fix

Rename the internal field strfmt in the Python formattableString replacement. The field is internal to that one function (written by Create, read by get_Format), so the change is fully self-contained — GetArgument/GetArguments/ArgumentCount use the separate args field, and GetStrings() is JS-only.

Verification

  • All 2350 Python tests pass (./build.sh test python)
  • ty check temp/tests/Python/test_string.pyAll checks passed!
  • Pyright remains clean

🤖 Generated with Claude Code

The Python representation of FormattableString used a field literally
named `str`, producing an object expression with a `@property def str`.
While this runs correctly (the `-> str` return annotation resolves to
the builtin under PEP 563, and Pyright accepts it), Astral's `ty` type
checker resolves the annotation against the class-scoped `str` property
and reports a false-positive `invalid-type-form` error.

Rename the internal field to `fmt`, which sidesteps the builtin-name
collision entirely. The field is internal to the `formattableString`
replacement (written by `Create`, read by `get_Format`), so the change
is fully self-contained.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dbrattli dbrattli force-pushed the fix/py-formattablestring-fmt-field branch from 3abe301 to 89f9d94 Compare June 9, 2026 21:13
@dbrattli dbrattli changed the title fix(python): rename FormattableString field from str to fmt refactor(python): rename FormattableString field from str to fmt Jun 9, 2026
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Python Type Checking Results (Pyright)

Metric Value
Total errors 34
Files with errors 4
Excluded files 4
New errors ✅ No
Excluded files with errors (4 files)

These files have known type errors and are excluded from CI. Remove from pyrightconfig.ci.json as errors are fixed.

File Errors Status
temp/tests/Python/test_hash_set.py 18 Excluded
temp/tests/Python/test_applicative.py 12 Excluded
temp/tests/Python/test_nested_and_recursive_pattern.py 2 Excluded
temp/tests/Python/fable_modules/thoth_json_python/encode.py 2 Excluded

@dbrattli dbrattli merged commit 3c7d98d into main Jun 9, 2026
32 checks passed
@dbrattli dbrattli deleted the fix/py-formattablestring-fmt-field branch June 9, 2026 21:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant