1
+ """
2
+ Test for raw f-string with backslash escape sequences.
3
+
4
+ This test covers the fix for issue where raw f-strings containing backslash
5
+ escape sequences in format specs would fail with "Unable to create representation
6
+ for f-string" error.
7
+ """
8
+
9
+ import ast
10
+ import sys
11
+
12
+ import pytest
13
+
14
+ from python_minifier import unparse
15
+ from python_minifier .ast_compare import compare_ast
16
+
17
+
18
+ def test_raw_fstring_backslash_format_spec ():
19
+ """Test that raw f-strings with backslash escapes in format specs can be unparsed correctly."""
20
+
21
+ if sys .version_info < (3 , 6 ):
22
+ pytest .skip ('F-strings not supported in Python < 3.6' )
23
+
24
+ # This is the minimal case that was failing before the fix
25
+ source = 'rf"{x:\\ xFF}"'
26
+
27
+ # This should round-trip correctly without "Unable to create representation for f-string"
28
+ expected_ast = ast .parse (source )
29
+ actual_code = unparse (expected_ast )
30
+ compare_ast (expected_ast , ast .parse (actual_code ))
31
+
32
+
33
+ def test_raw_fstring_backslash_outer_str ():
34
+ """Test that raw f-strings with backslashes in the outer string parts can be unparsed correctly."""
35
+
36
+ if sys .version_info < (3 , 6 ):
37
+ pytest .skip ('F-strings not supported in Python < 3.6' )
38
+
39
+ # Test backslashes in the literal parts of raw f-strings
40
+ source = r'rf"\\n{x}\\t"'
41
+
42
+ expected_ast = ast .parse (source )
43
+ actual_code = unparse (expected_ast )
44
+ compare_ast (expected_ast , ast .parse (actual_code ))
45
+
46
+
47
+ def test_raw_fstring_mixed_backslashes ():
48
+ """Test raw f-strings with backslashes in both literal parts and format specs."""
49
+
50
+ if sys .version_info < (3 , 6 ):
51
+ pytest .skip ('F-strings not supported in Python < 3.6' )
52
+
53
+ # Test combination of backslashes in literal parts and format specs
54
+ source = r'rf"\\n{x:\\xFF}\\t"'
55
+
56
+ expected_ast = ast .parse (source )
57
+ actual_code = unparse (expected_ast )
58
+ compare_ast (expected_ast , ast .parse (actual_code ))
59
+
60
+
61
+ def test_nested_fstring_backslashes ():
62
+ """Test nested f-strings with backslashes (Python 3.12+ only)."""
63
+
64
+ if sys .version_info < (3 , 12 ):
65
+ pytest .skip ('Nested f-strings not supported in Python < 3.12' )
66
+
67
+ # Test nested f-strings with backslashes in inner string parts
68
+ source = r'f"{f"\\n{x}\\t"}"'
69
+
70
+ expected_ast = ast .parse (source )
71
+ actual_code = unparse (expected_ast )
72
+ compare_ast (expected_ast , ast .parse (actual_code ))
73
+
74
+
75
+ def test_nested_raw_fstring_backslashes ():
76
+ """Test nested raw f-strings with backslashes (Python 3.12+ only)."""
77
+
78
+ if sys .version_info < (3 , 12 ):
79
+ pytest .skip ('Nested f-strings not supported in Python < 3.12' )
80
+
81
+ # Test nested raw f-strings with backslashes
82
+ source = r'f"{rf"\\xFF{y}\\n"}"'
83
+
84
+ expected_ast = ast .parse (source )
85
+ actual_code = unparse (expected_ast )
86
+ compare_ast (expected_ast , ast .parse (actual_code ))
87
+
88
+
89
+ def test_nested_fstring_format_spec_backslashes ():
90
+ """Test nested f-strings with backslashes in format specs (Python 3.12+ only)."""
91
+
92
+ if sys .version_info < (3 , 12 ):
93
+ pytest .skip ('Nested f-strings not supported in Python < 3.12' )
94
+
95
+ # Test nested f-strings with backslashes in format specifications
96
+ source = r'f"{f"{x:\\xFF}"}"'
97
+
98
+ expected_ast = ast .parse (source )
99
+ actual_code = unparse (expected_ast )
100
+ compare_ast (expected_ast , ast .parse (actual_code ))
101
+
102
+
103
+ def test_raw_fstring_literal_single_backslash ():
104
+ """Test raw f-string with single backslash in literal part only."""
105
+
106
+ if sys .version_info < (3 , 6 ):
107
+ pytest .skip ('F-strings not supported in Python < 3.6' )
108
+
109
+ source = r'rf"\n"'
110
+
111
+ expected_ast = ast .parse (source )
112
+ actual_code = unparse (expected_ast )
113
+ compare_ast (expected_ast , ast .parse (actual_code ))
114
+
115
+
116
+ def test_raw_fstring_literal_double_backslash ():
117
+ """Test raw f-string with double backslash in literal part only."""
118
+
119
+ if sys .version_info < (3 , 6 ):
120
+ pytest .skip ('F-strings not supported in Python < 3.6' )
121
+
122
+ source = r'rf"\\n"'
123
+
124
+ expected_ast = ast .parse (source )
125
+ actual_code = unparse (expected_ast )
126
+ compare_ast (expected_ast , ast .parse (actual_code ))
127
+
128
+
129
+ def test_raw_fstring_formatspec_single_backslash ():
130
+ """Test raw f-string with single backslash in format spec only."""
131
+
132
+ if sys .version_info < (3 , 6 ):
133
+ pytest .skip ('F-strings not supported in Python < 3.6' )
134
+
135
+ source = r'rf"{x:\xFF}"'
136
+
137
+ expected_ast = ast .parse (source )
138
+ actual_code = unparse (expected_ast )
139
+ compare_ast (expected_ast , ast .parse (actual_code ))
140
+
141
+
142
+ def test_raw_fstring_formatspec_double_backslash ():
143
+ """Test raw f-string with double backslash in format spec only."""
144
+
145
+ if sys .version_info < (3 , 6 ):
146
+ pytest .skip ('F-strings not supported in Python < 3.6' )
147
+
148
+ source = r'rf"{x:\\xFF}"'
149
+
150
+ expected_ast = ast .parse (source )
151
+ actual_code = unparse (expected_ast )
152
+ compare_ast (expected_ast , ast .parse (actual_code ))
153
+
154
+
155
+ def test_raw_fstring_mixed_single_backslashes ():
156
+ """Test raw f-string with single backslashes in both literal and format spec parts."""
157
+
158
+ if sys .version_info < (3 , 6 ):
159
+ pytest .skip ('F-strings not supported in Python < 3.6' )
160
+
161
+ source = r'rf"\n{x:\xFF}\t"'
162
+
163
+ expected_ast = ast .parse (source )
164
+ actual_code = unparse (expected_ast )
165
+ compare_ast (expected_ast , ast .parse (actual_code ))
0 commit comments