@@ -87,19 +87,23 @@ def fstrings(draw):
8787
8888 :return: A valid f-string.
8989 """
90+ character_strategy = st .characters (
91+ blacklist_characters = '\r \n \' \\ s{}' ,
92+ min_codepoint = 1 ,
93+ max_codepoint = 1000 ,
94+ )
9095 is_raw = draw (st .booleans ())
9196 integer_strategy = st .integers (min_value = 0 , max_value = 3 )
9297 expression_count = draw (integer_strategy )
9398 content = []
9499 for _ in range (expression_count ):
95100 expression = draw (expressions ())
96- # not yet : conversion not supported
97- conversion = '' #draw(st.sampled_from(('', '!s', '!r', '!a',)))
101+ conversion = draw (st .sampled_from (('' , '!s' , '!r' , '!a' ,)))
98102 has_specifier = draw (st .booleans ())
99103 specifier = ':' + draw (format_specifiers ()) if has_specifier else ''
100104 content .append ('{{{}{}}}' .format (expression , conversion , specifier ))
105+ content .append (draw (st .text (character_strategy )))
101106 content = '' .join (content )
102-
103107 return "f{}'{}'" .format ('r' if is_raw else '' , content )
104108
105109
@@ -114,23 +118,27 @@ def test_format_specifiers(format_specifier):
114118 raise
115119
116120
121+ def run_test (text ):
122+ expr = text + '\n '
123+ code = compile (expr , '<string>' , 'single' )
124+ deparsed = deparse_code (PYTHON_VERSION , code , compile_mode = 'single' )
125+ recompiled = compile (deparsed .text , '<string>' , 'single' )
126+ if recompiled != code :
127+ assert 'dis(' + deparsed .text .strip ('\n ' ) + ')' == 'dis(' + expr .strip ('\n ' ) + ')'
128+
129+
117130@pytest .mark .skipif (PYTHON_VERSION < 3.6 , reason = 'need at least python 3.6' )
118131@hypothesis .given (fstrings ())
119132def test_uncompyle_fstring (fstring ):
120133 """Verify uncompyling fstring bytecode"""
134+ run_test (fstring )
121135
122- # ignore fstring with no expressions an fsring with
123- # no expressions just gets compiled to a normal string.
124- hypothesis .assume ('{' in fstring )
125136
126- # BUG : At the moment a single expression is not supported
127- # for example f'{abc}'.
128- hypothesis .assume (fstring .count ('{' ) > 1 )
129-
130- expr = fstring + '\n '
131- code = compile (expr , '<string>' , 'single' )
132- deparsed = deparse_code (PYTHON_VERSION , code , compile_mode = 'single' )
133- recompiled = compile (deparsed .text , '<string>' , 'single' )
134-
135- if recompiled != code :
136- assert deparsed .text == expr
137+ @pytest .mark .skipif (PYTHON_VERSION < 3.6 , reason = 'need at least python 3.6' )
138+ @pytest .mark .parametrize ('fstring' , [
139+ #"f'{abc}{abc!s}'",
140+ "f'{abc!s}'" ,
141+ ])
142+ def test_uncompyle_direct (fstring ):
143+ """useful for debugging"""
144+ run_test (fstring )
0 commit comments