Show More
@@ -149,16 +149,15 b' def _should_be_async(cell: str) -> bool:' | |||||
149 | Not handled yet: If the block of code has a return statement as the top |
|
149 | Not handled yet: If the block of code has a return statement as the top | |
150 | level, it will be seen as async. This is a know limitation. |
|
150 | level, it will be seen as async. This is a know limitation. | |
151 | """ |
|
151 | """ | |
|
152 | if sys.version_info > (3, 8): | |||
|
153 | code = compile(cell, "<>", "exec", flags=getattr(ast,'PyCF_ALLOW_TOP_LEVEL_AWAIT', 0x0)) | |||
|
154 | return inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE | |||
152 |
|
155 | |||
153 | try: |
|
156 | try: | |
154 | # we can't limit ourself to ast.parse, as it __accepts__ to parse on |
|
157 | # we can't limit ourself to ast.parse, as it __accepts__ to parse on | |
155 | # 3.7+, but just does not _compile_ |
|
158 | # 3.7+, but just does not _compile_ | |
156 | # code = compile(cell, "<>", "exec", flags=getattr(ast,'PyCF_ALLOW_TOP_LEVEL_AWAIT', 0x0)) |
|
|||
157 | code = compile(cell, "<>", "exec") |
|
159 | code = compile(cell, "<>", "exec") | |
158 | return inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE |
|
|||
159 | except SyntaxError: |
|
160 | except SyntaxError: | |
160 | #if sys.version_info > (3, 8): |
|
|||
161 | # raise |
|
|||
162 | try: |
|
161 | try: | |
163 | parse_tree = _async_parse_cell(cell) |
|
162 | parse_tree = _async_parse_cell(cell) | |
164 |
|
163 |
@@ -17,6 +17,7 b' import asyncio' | |||||
17 | import atexit |
|
17 | import atexit | |
18 | import builtins as builtin_mod |
|
18 | import builtins as builtin_mod | |
19 | import functools |
|
19 | import functools | |
|
20 | import inspect | |||
20 | import os |
|
21 | import os | |
21 | import re |
|
22 | import re | |
22 | import runpy |
|
23 | import runpy | |
@@ -161,8 +162,9 b' def removed_co_newlocals(function:types.FunctionType) -> types.FunctionType:' | |||||
161 | # we still need to run things using the asyncio eventloop, but there is no |
|
162 | # we still need to run things using the asyncio eventloop, but there is no | |
162 | # async integration |
|
163 | # async integration | |
163 | from .async_helpers import (_asyncio_runner, _asyncify, _pseudo_sync_runner) |
|
164 | from .async_helpers import (_asyncio_runner, _asyncify, _pseudo_sync_runner) | |
164 |
|
165 | if sys.version_info > (3, 8): | ||
165 | if sys.version_info > (3, 5): |
|
166 | from .async_helpers import _curio_runner, _trio_runner | |
|
167 | elif sys.version_info > (3, 5): | |||
166 | from .async_helpers import _curio_runner, _trio_runner, _should_be_async |
|
168 | from .async_helpers import _curio_runner, _trio_runner, _should_be_async | |
167 | else : |
|
169 | else : | |
168 | _curio_runner = _trio_runner = None |
|
170 | _curio_runner = _trio_runner = None | |
@@ -3000,23 +3002,26 b' class InteractiveShell(SingletonConfigurable):' | |||||
3000 | with self.display_trap: |
|
3002 | with self.display_trap: | |
3001 | # Compile to bytecode |
|
3003 | # Compile to bytecode | |
3002 | try: |
|
3004 | try: | |
3003 | if self.autoawait and _should_be_async(cell): |
|
3005 | if sys.version_info < (3,8) and self.autoawait: | |
3004 | # the code AST below will not be user code: we wrap it |
|
3006 | if _should_be_async(cell): | |
3005 | # in an `async def`. This will likely make some AST |
|
3007 | # the code AST below will not be user code: we wrap it | |
3006 | # transformer below miss some transform opportunity and |
|
3008 | # in an `async def`. This will likely make some AST | |
3007 | # introduce a small coupling to run_code (in which we |
|
3009 | # transformer below miss some transform opportunity and | |
3008 | # bake some assumptions of what _ast_asyncify returns. |
|
3010 | # introduce a small coupling to run_code (in which we | |
3009 | # they are ways around (like grafting part of the ast |
|
3011 | # bake some assumptions of what _ast_asyncify returns. | |
3010 | # later: |
|
3012 | # they are ways around (like grafting part of the ast | |
3011 | # - Here, return code_ast.body[0].body[1:-1], as well |
|
3013 | # later: | |
3012 | # as last expression in return statement which is |
|
3014 | # - Here, return code_ast.body[0].body[1:-1], as well | |
3013 | # the user code part. |
|
3015 | # as last expression in return statement which is | |
3014 |
|
|
3016 | # the user code part. | |
3015 |
# - |
|
3017 | # - Let it go through the AST transformers, and graft | |
3016 | # But that seem unreasonable, at least while we |
|
3018 | # - it back after the AST transform | |
3017 | # do not need it. |
|
3019 | # But that seem unreasonable, at least while we | |
3018 | code_ast = _ast_asyncify(cell, 'async-def-wrapper') |
|
3020 | # do not need it. | |
3019 | _run_async = True |
|
3021 | code_ast = _ast_asyncify(cell, 'async-def-wrapper') | |
|
3022 | _run_async = True | |||
|
3023 | else: | |||
|
3024 | code_ast = compiler.ast_parse(cell, filename=cell_name) | |||
3020 | else: |
|
3025 | else: | |
3021 | code_ast = compiler.ast_parse(cell, filename=cell_name) |
|
3026 | code_ast = compiler.ast_parse(cell, filename=cell_name) | |
3022 | except self.custom_exceptions as e: |
|
3027 | except self.custom_exceptions as e: | |
@@ -3045,8 +3050,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
3045 | # Execute the user code |
|
3050 | # Execute the user code | |
3046 | interactivity = "none" if silent else self.ast_node_interactivity |
|
3051 | interactivity = "none" if silent else self.ast_node_interactivity | |
3047 | if _run_async: |
|
3052 | if _run_async: | |
3048 |
|
|
3053 | interactivity = 'async' | |
3049 | interactivity = 'last_expr' |
|
|||
3050 |
|
3054 | |||
3051 | has_raised = yield from self.run_ast_nodes(code_ast.body, cell_name, |
|
3055 | has_raised = yield from self.run_ast_nodes(code_ast.body, cell_name, | |
3052 | interactivity=interactivity, compiler=compiler, result=result) |
|
3056 | interactivity=interactivity, compiler=compiler, result=result) | |
@@ -3168,8 +3172,6 b' class InteractiveShell(SingletonConfigurable):' | |||||
3168 | """ |
|
3172 | """ | |
3169 | if not nodelist: |
|
3173 | if not nodelist: | |
3170 | return |
|
3174 | return | |
3171 | if interactivity == 'async': |
|
|||
3172 | interactivify = 'last' |
|
|||
3173 |
|
3175 | |||
3174 | if interactivity == 'last_expr_or_assign': |
|
3176 | if interactivity == 'last_expr_or_assign': | |
3175 | if isinstance(nodelist[-1], _assign_nodes): |
|
3177 | if isinstance(nodelist[-1], _assign_nodes): | |
@@ -3205,10 +3207,11 b' class InteractiveShell(SingletonConfigurable):' | |||||
3205 | else: |
|
3207 | else: | |
3206 | raise ValueError("Interactivity was %r" % interactivity) |
|
3208 | raise ValueError("Interactivity was %r" % interactivity) | |
3207 |
|
3209 | |||
3208 | print('interactivity:', interactivity) |
|
|||
3209 | try: |
|
3210 | try: | |
3210 |
if _async and sys.version_info |
|
3211 | if _async and sys.version_info > (3,8): | |
3211 | raise ValueError |
|
3212 | raise ValueError("This branch should never happen on Python 3.8 and above, " | |
|
3213 | "please try to upgrade IPython and open a bug report with your case.") | |||
|
3214 | if _async: | |||
3212 | # If interactivity is async the semantics of run_code are |
|
3215 | # If interactivity is async the semantics of run_code are | |
3213 | # completely different Skip usual machinery. |
|
3216 | # completely different Skip usual machinery. | |
3214 | mod = Module(nodelist, []) |
|
3217 | mod = Module(nodelist, []) | |
@@ -3218,31 +3221,33 b' class InteractiveShell(SingletonConfigurable):' | |||||
3218 | if (yield from self.run_code(async_code, result, async_=True)): |
|
3221 | if (yield from self.run_code(async_code, result, async_=True)): | |
3219 | return True |
|
3222 | return True | |
3220 | else: |
|
3223 | else: | |
3221 | def compare(code): |
|
3224 | if sys.version_info > (3, 8): | |
3222 |
|
|
3225 | def compare(code): | |
3223 | is_async = (inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE) |
|
3226 | is_async = (inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE) | |
3224 | print('async=', _async, 'autodetect=', is_async) |
|
3227 | return is_async | |
3225 |
|
|
3228 | else: | |
|
3229 | def compare(code): | |||
|
3230 | return _async | |||
3226 |
|
3231 | |||
3227 | # refactor that to just change the mod constructor. |
|
3232 | # refactor that to just change the mod constructor. | |
3228 | for i, node in enumerate(to_run_exec): |
|
3233 | to_run = [] | |
3229 | mod = Module([node], []) |
|
3234 | for node in to_run_exec: | |
|
3235 | to_run.append((node, 'exec')) | |||
|
3236 | ||||
|
3237 | for node in to_run_interactive: | |||
|
3238 | to_run.append((node, 'single')) | |||
|
3239 | ||||
|
3240 | for node,mode in to_run: | |||
|
3241 | if mode == 'exec': | |||
|
3242 | mod = Module([node], []) | |||
|
3243 | elif mode == 'single': | |||
|
3244 | mod = ast.Interactive([node]) | |||
3230 | with compiler.extra_flags(getattr(ast, 'PyCF_ALLOW_TOP_LEVEL_AWAIT', 0x0) if self.autoawait else 0x0): |
|
3245 | with compiler.extra_flags(getattr(ast, 'PyCF_ALLOW_TOP_LEVEL_AWAIT', 0x0) if self.autoawait else 0x0): | |
3231 |
code = compiler(mod, cell_name, |
|
3246 | code = compiler(mod, cell_name, mode) | |
3232 | asy = compare(code) |
|
3247 | asy = compare(code) | |
3233 | if (yield from self.run_code(code, result, async_=asy)): |
|
3248 | if (yield from self.run_code(code, result, async_=asy)): | |
3234 | return True |
|
3249 | return True | |
3235 |
|
3250 | |||
3236 | for i, node in enumerate(to_run_interactive): |
|
|||
3237 | print('B: interactive, async=', _async, nodelist) |
|
|||
3238 | mod = ast.Interactive([node]) |
|
|||
3239 | with compiler.extra_flags(getattr(ast, 'PyCF_ALLOW_TOP_LEVEL_AWAIT', 0x0) if self.autoawait else 0x0): |
|
|||
3240 | code = compiler(mod, cell_name, "single") |
|
|||
3241 | asy = compare(code) |
|
|||
3242 |
|
||||
3243 | if (yield from self.run_code(code, result, async_=asy)): |
|
|||
3244 | return True |
|
|||
3245 |
|
||||
3246 | # Flush softspace |
|
3251 | # Flush softspace | |
3247 | if softspace(sys.stdout, 0): |
|
3252 | if softspace(sys.stdout, 0): | |
3248 | print() |
|
3253 | print() |
General Comments 0
You need to be logged in to leave comments.
Login now