Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
9248287
Implement next version of PEP 750
lysnikolaou Oct 1, 2024
450d771
First fixes; conv and format_spec still not working
lysnikolaou Oct 18, 2024
a095a9b
Change BUILD_INTERPOLATION opcode to simplify
lysnikolaou Oct 18, 2024
499d70c
Add templatelib module & clean-up types/objects etc.
lysnikolaou Oct 20, 2024
f742d45
Support explicit concatenation of template and str
lysnikolaou Oct 21, 2024
0dda3f9
Avoid folding one node template into its content
lysnikolaou Oct 22, 2024
17014e7
Implement __eq__ for template and interpolation
lysnikolaou Oct 23, 2024
94371bd
Fix debug specifier segfault
lysnikolaou Oct 23, 2024
99184cc
Add __match_args__ to Interpolation
lysnikolaou Oct 23, 2024
4e89c87
Fix syntax error prefix in t-strings
lysnikolaou Oct 23, 2024
6bfb095
Fix test_dis
lysnikolaou Oct 23, 2024
560e957
Fix test_fstring
lysnikolaou Oct 23, 2024
4d172c2
Fix test_embed
lysnikolaou Oct 23, 2024
c9362e3
Implement interleaving, hash functions and *args __init__
lysnikolaou Oct 23, 2024
d2bd673
Use Argument Clinic for interpolation_new
lysnikolaou Oct 25, 2024
7ae1b60
Revert to using different grammar rules for tstring due to format_spec
lysnikolaou Oct 25, 2024
5e7304f
Fix code generation for when there's many values in tstring
lysnikolaou Oct 25, 2024
c8f22f0
Remove duplicate parens from template repr
lysnikolaou Oct 25, 2024
b0dbe27
Fix conversion converter for interpolation __new__
lysnikolaou Oct 25, 2024
b07c419
Merge branch 'main' into tstrings
lysnikolaou Oct 27, 2024
3e84771
Fix test_embed and test_dis -- again
lysnikolaou Nov 1, 2024
9380ab9
Implement implicit concatenation with TemplateStr
lysnikolaou Nov 1, 2024
22f9dc6
Merge branch 'main' into tstrings
lysnikolaou Feb 20, 2025
f207637
Implement new specification of template type
lysnikolaou Feb 20, 2025
29b1386
Replace nb_add with sq_concat
lysnikolaou Feb 20, 2025
aad5d67
Correctly implement str + tstring
lysnikolaou Feb 21, 2025
77822be
Make changes requested by Steering Council (#57)
Wingysam Apr 9, 2025
f3ba0fe
Merge branch 'main' into tstrings
lysnikolaou Apr 9, 2025
422a515
Remove unnecessary _Py_TPFLAGS_MATCH_SELF from Template type (#60)
koxudaxi Apr 9, 2025
bb7359a
Fix memory leak in template concat error handling (#59)
koxudaxi Apr 9, 2025
6a7b448
PEP 750 bug and spec fix (#58)
davepeck Apr 9, 2025
e6d01ef
Fix for segv in `_PyInterpolation_FromStackRefSteal` (#61)
davepeck Apr 10, 2025
0801f17
More minor fixes after merge with main
lysnikolaou Apr 10, 2025
a51e954
Fix JIT build
lysnikolaou Apr 10, 2025
76816a1
Fix Windows build
lysnikolaou Apr 10, 2025
2c53f55
Remove smelly _conversion_converter symbol
lysnikolaou Apr 10, 2025
fa4b531
Fix check-c-globals
lysnikolaou Apr 10, 2025
98e5d83
Fix various stuff in the VM
lysnikolaou Apr 11, 2025
a7c57fe
Add tests
lysnikolaou Apr 11, 2025
d6c470c
Fix Windows build (#64)
AA-Turner Apr 11, 2025
101abe3
Merge branch 'main' into tstrings
lysnikolaou Apr 11, 2025
7573346
Fix lint
lysnikolaou Apr 11, 2025
4f91ea3
Skip test_tstring.py from ruff
lysnikolaou Apr 11, 2025
14d9fa4
Fix parser bug and implement ast_unparse in Python
lysnikolaou Apr 11, 2025
bf89325
Modify CODEOWNERS
lysnikolaou Apr 11, 2025
b7edcd6
Do not use _PyAST_ExprAsUnicode (unparse) for interpolation expression
lysnikolaou Apr 11, 2025
99c3bf4
Remove interpolation_compare() and interpolation_hash() (#65)
davepeck Apr 17, 2025
f09d99f
Add type check macros (#67)
AA-Turner Apr 17, 2025
878eb69
t-strings: cosmetics (#66)
AA-Turner Apr 17, 2025
7ed73fa
Implement GC protocol for template and interpolation types
lysnikolaou Apr 17, 2025
e88d111
Fix test_unparse again!
lysnikolaou Apr 17, 2025
92fd148
Remove unnecessary tp_flag from interpolation type
lysnikolaou Apr 17, 2025
c833f6d
Merge branch 'main' into tstrings
lysnikolaou Apr 17, 2025
8f8a414
Minor fixes (mostly cosmetic)
lysnikolaou Apr 17, 2025
6bfc888
Add test for interleaving
lysnikolaou Apr 17, 2025
5707837
gh-132493: Avoid eager import of annotationlib in typing (again) (#13…
JelleZijlstra Apr 17, 2025
a23ed8b
gh-132284: Don't wrap base PyCFunction slots on class creation if not…
tom-pytel Apr 17, 2025
cf59bc3
gh-127945: fix critical sections around ctypes array (#132646)
kumaraditya303 Apr 17, 2025
b87189d
gh-132649: Allow passing --include-tcltk to PC\layout on Windows ARM6…
zooba Apr 17, 2025
1d529cb
Docs: Migrate entirely to PSF hosted plausible for analytics (#132648)
ewdurbin Apr 17, 2025
2283010
gh-131173: Improve exception handling during take_ownership processin…
yoney Apr 17, 2025
ea23c89
Remove duplicate includes: Python/importdl.c (#132623)
AA-Turner Apr 18, 2025
0ee90f9
Merge branch 'main' into tstrings
terryjreedy Apr 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,13 @@ Lib/test/test__colorize.py @hugovk

# Fuzzing
Modules/_xxtestfuzz/ @ammaraskar

# t-strings
Include/internal/pycore_interpolation.h @lysnikolaou
Include/internal/pycore_template.h @lysnikolaou
Objects/interpolationobject.c @lysnikolaou
Objects/clinic/interpolationobject.c.h @lysnikolaou
Objects/templateobject.c @lysnikolaou
Modules/_templatelibmodule.c @lysnikolaou
Lib/string/templatelib.py @lysnikolaou
Lib/test/test_tstring.py @lysnikolaou
9 changes: 9 additions & 0 deletions Doc/library/token.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ The token constants are:

The token string contains the closing quote(s).

.. data:: TSTRING_START

Token value used to indicate the beginning of a t-string literal.

.. impl-detail::

The token string includes the prefix and the opening quote(s), but none
of the contents of the literal.

.. data:: ENDMARKER

Token value that indicates the end of input.
Expand Down
3 changes: 1 addition & 2 deletions Doc/tools/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@

{% block extrahead %}
{% if builder == "html" and enable_analytics %}
<script defer data-domain="docs.python.org" src="https://plausible.io/js/script.js"></script>
<script defer data-domain="docs.python.org" src="https://analytics.python.org/js/script.js"></script>
<script defer data-domain="docs.python.org" src="https://analytics.python.org/js/script.outbound-links.js"></script>
{% endif %}
<link rel="canonical" href="https://docs.python.org/3/{{pagename}}.html">
{% if builder != "htmlhelp" %}
Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,10 @@ Other language changes
of HMAC is not available.
(Contributed by BΓ©nΓ©dikt Tran in :gh:`99108`.)

* When subclassing from a pure C type, the C slots for the new type are no
longer replaced with a wrapped version on class creation if they are not
explicitly overridden in the subclass.
(Contributed by Tomasz Pytel in :gh:`132329`.)

.. _whatsnew314-pep765:

Expand Down
1 change: 1 addition & 0 deletions Grammar/Tokens
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ TYPE_IGNORE
TYPE_COMMENT
SOFT_KEYWORD
FSTRING_START
TSTRING_START
FSTRING_MIDDLE
FSTRING_END
COMMENT
Expand Down
55 changes: 39 additions & 16 deletions Grammar/python.gram
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ literal_pattern[pattern_ty]:
literal_expr[expr_ty]:
| signed_number !('+' | '-')
| complex_number
| strings
| &(STRING|FSTRING_START|TSTRING_START) strings
| 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
| 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
| 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
Expand Down Expand Up @@ -853,7 +853,7 @@ atom[expr_ty]:
| 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
| 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
| 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
| &(STRING|FSTRING_START) strings
| &(STRING|FSTRING_START|TSTRING_START) strings
| NUMBER
| &'(' (tuple | group | genexp)
| &'[' (list | listcomp)
Expand Down Expand Up @@ -940,8 +940,18 @@ fstring_format_spec[expr_ty]:
fstring[expr_ty]:
| a=FSTRING_START b=fstring_middle* c=FSTRING_END { _PyPegen_joined_str(p, a, (asdl_expr_seq*)b, c) }

tstring_replacement_field[expr_ty]:
| '{' a=annotated_rhs debug_expr='='? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' {
_PyPegen_interpolation(p, a, debug_expr, conversion, format, rbrace, EXTRA) }
| invalid_replacement_field
tstring_middle[expr_ty]:
| tstring_replacement_field
| t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
tstring[expr_ty] (memo):
| a=TSTRING_START b=tstring_middle* c=FSTRING_END { _PyPegen_template_str(p, a, (asdl_expr_seq*)b, c) }

string[expr_ty]: s[Token*]=STRING { _PyPegen_constant_from_string(p, s) }
strings[expr_ty] (memo): a[asdl_expr_seq*]=(fstring|string)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }
strings[expr_ty] (memo): a[asdl_expr_seq*]=(fstring|string|tstring)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }

list[expr_ty]:
| '[' a=[star_named_expressions] ']' { _PyAST_List(a, Load, EXTRA) }
Expand Down Expand Up @@ -1205,7 +1215,8 @@ invalid_expression:
| a[stmt_ty]=(pass_stmt|break_stmt|continue_stmt) 'if' b=disjunction 'else' c=simple_stmt {
RAISE_SYNTAX_ERROR_KNOWN_LOCATION (a, "expected expression before 'if', but statement is given") }
| a='lambda' [lambda_params] b=':' &FSTRING_MIDDLE {
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "f-string: lambda expressions are not allowed without parentheses") }
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "%c-string: lambda expressions are not allowed without parentheses",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }

invalid_named_expression(memo):
| a=expression ':=' expression {
Expand Down Expand Up @@ -1448,26 +1459,38 @@ invalid_starred_expression:
| '*' { RAISE_SYNTAX_ERROR("Invalid star expression") }

invalid_replacement_field:
| '{' a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '='") }
| '{' a='!' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '!'") }
| '{' a=':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before ':'") }
| '{' a='}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '}'") }
| '{' !annotated_rhs { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting a valid expression after '{'")}
| '{' a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "%c-string: valid expression required before '='",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '{' a='!' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "%c-string: valid expression required before '!'",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '{' a=':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "%c-string: valid expression required before ':'",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '{' a='}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "%c-string: valid expression required before '}'",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '{' !annotated_rhs { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("%c-string: expecting a valid expression after '{'",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f')}
| '{' annotated_rhs !('=' | '!' | ':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '=', or '!', or ':', or '}'") }
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("%c-string: expecting '=', or '!', or ':', or '}'",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '{' annotated_rhs '=' !('!' | ':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '!', or ':', or '}'") }
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("%c-string: expecting '!', or ':', or '}'",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '{' annotated_rhs '='? invalid_conversion_character
| '{' annotated_rhs '='? ['!' NAME] !(':' | '}') {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting ':' or '}'") }
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("%c-string: expecting ':' or '}'",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}' {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}', or format specs") }
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("%c-string: expecting '}', or format specs",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '{' annotated_rhs '='? ['!' NAME] !'}' {
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}'") }
PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("%c-string: expecting '}'",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }

invalid_conversion_character:
| '!' &(':' | '}') { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: missing conversion character") }
| '!' !NAME { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: invalid conversion character") }
| '!' &(':' | '}') { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("%c-string: missing conversion character",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }
| '!' !NAME { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("%c-string: invalid conversion character",
TOK_GET_MODE(p->tok)->tstring ? 't' : 'f') }

invalid_arithmetic:
| sum ('+'|'-'|'*'|'/'|'%'|'//'|'@') a='not' b=inversion { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "'not' after an operator must be parenthesized") }
Expand Down
24 changes: 21 additions & 3 deletions Include/internal/pycore_ast.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Include/internal/pycore_ast_state.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Include/internal/pycore_global_objects_fini_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(consts)
STRUCT_FOR_ID(context)
STRUCT_FOR_ID(contravariant)
STRUCT_FOR_ID(conversion)
STRUCT_FOR_ID(cookie)
STRUCT_FOR_ID(copy)
STRUCT_FOR_ID(copyreg)
Expand Down Expand Up @@ -428,6 +429,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(exception)
STRUCT_FOR_ID(existing_file_name)
STRUCT_FOR_ID(exp)
STRUCT_FOR_ID(expression)
STRUCT_FOR_ID(extend)
STRUCT_FOR_ID(extra_tokens)
STRUCT_FOR_ID(facility)
Expand Down
28 changes: 28 additions & 0 deletions Include/internal/pycore_interpolation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef Py_INTERNAL_INTERPOLATION_H
#define Py_INTERNAL_INTERPOLATION_H

#ifdef __cplusplus
extern "C" {
#endif

#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif

#include "pycore_stackref.h" // _PyStackRef

extern PyTypeObject _PyInterpolation_Type;

#define _PyInterpolation_Check(op) PyObject_TypeCheck((op), &_PyInterpolation_Type)
#define _PyInterpolation_CheckExact(op) Py_IS_TYPE((op), &_PyInterpolation_Type)

PyAPI_FUNC(PyObject *) _PyInterpolation_FromStackRefStealOnSuccess(_PyStackRef *values);

extern PyStatus _PyInterpolation_InitTypes(PyInterpreterState *interp);
extern PyObject *_PyInterpolation_GetValue(PyObject *interpolation);

#ifdef __cplusplus
}
#endif

#endif
3 changes: 2 additions & 1 deletion Include/internal/pycore_magic_number.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ Known values:
Python 3.14a6 3620 (Optimize bytecode for all/any/tuple called on a genexp)
Python 3.14a7 3621 (Optimize LOAD_FAST opcodes into LOAD_FAST_BORROW)
Python 3.14a7 3622 (Store annotations in different class dict keys)
Python 3.14a7 3623 (Add BUILD_INTERPOLATION & BUILD_TEMPLATE opcodes)

Python 3.15 will start with 3650

Expand All @@ -287,7 +288,7 @@ PC/launcher.c must also be updated.

*/

#define PYC_MAGIC_NUMBER 3622
#define PYC_MAGIC_NUMBER 3623
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
(little-endian) and then appending b'\r\n'. */
#define PYC_MAGIC_NUMBER_TOKEN \
Expand Down
Loading
Loading