forked from goodboy/tractor
				
			Kick off `.devx` subpkg for our dev tools B)
Where `.devx` is "developer experience", a hopefully broad enough subpkg
name for all the slick stuff planned to augment working on the actor
runtime 💥
Move the `._debug` module into the new subpkg and adjust rest of core
code base to reflect import path change. Also add a new
`.devx._debug.open_crash_handler()` manager for wrapping any sync code
outside a `trio.run()` which is handy for eventual CLI addons for
popular frameworks like `click`/`typer`.
			
			
				remotes/1757153874605917753/main
			
			
		
							parent
							
								
									93f489e263
								
							
						
					
					
						commit
						b00ba158f1
					
				|  | @ -43,7 +43,7 @@ from ._exceptions import ( | |||
|     ModuleNotExposed, | ||||
|     ContextCancelled, | ||||
| ) | ||||
| from ._debug import ( | ||||
| from .devx import ( | ||||
|     breakpoint, | ||||
|     pause, | ||||
|     pause_from_sync, | ||||
|  |  | |||
|  | @ -868,6 +868,9 @@ class Context: | |||
| 
 | ||||
|         # TODO: maybe we should also call `._res_scope.cancel()` if it | ||||
|         # exists to support cancelling any drain loop hangs? | ||||
|         # NOTE: this usage actually works here B) | ||||
|         # from .devx._debug import breakpoint | ||||
|         # await breakpoint() | ||||
| 
 | ||||
|     # TODO: add to `Channel`? | ||||
|     @property | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ from ._runtime import ( | |||
|     # Arbiter as Registry, | ||||
|     async_main, | ||||
| ) | ||||
| from . import _debug | ||||
| from .devx import _debug | ||||
| from . import _spawn | ||||
| from . import _state | ||||
| from . import log | ||||
|  | @ -90,7 +90,7 @@ async def open_root_actor( | |||
|     # https://github.com/python-trio/trio/issues/1155#issuecomment-742964018 | ||||
|     builtin_bp_handler = sys.breakpointhook | ||||
|     orig_bp_path: str | None = os.environ.get('PYTHONBREAKPOINT', None) | ||||
|     os.environ['PYTHONBREAKPOINT'] = 'tractor._debug.pause_from_sync' | ||||
|     os.environ['PYTHONBREAKPOINT'] = 'tractor.devx._debug.pause_from_sync' | ||||
| 
 | ||||
|     # attempt to retreive ``trio``'s sigint handler and stash it | ||||
|     # on our debugger lock state. | ||||
|  | @ -138,7 +138,7 @@ async def open_root_actor( | |||
| 
 | ||||
|         # expose internal debug module to every actor allowing | ||||
|         # for use of ``await tractor.breakpoint()`` | ||||
|         enable_modules.append('tractor._debug') | ||||
|         enable_modules.append('tractor.devx._debug') | ||||
| 
 | ||||
|         # if debug mode get's enabled *at least* use that level of | ||||
|         # logging for some informative console prompts. | ||||
|  |  | |||
|  | @ -78,7 +78,7 @@ from ._exceptions import ( | |||
|     TransportClosed, | ||||
| ) | ||||
| from ._discovery import get_arbiter | ||||
| from . import _debug | ||||
| from .devx import _debug | ||||
| from ._portal import Portal | ||||
| from . import _state | ||||
| from . import _mp_fixup_main | ||||
|  | @ -187,7 +187,7 @@ class Actor: | |||
|         self._parent_main_data = _mp_fixup_main._mp_figure_out_main() | ||||
| 
 | ||||
|         # always include debugging tools module | ||||
|         enable_modules.append('tractor._debug') | ||||
|         enable_modules.append('tractor.devx._debug') | ||||
| 
 | ||||
|         mods = {} | ||||
|         for name in enable_modules: | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ from typing import ( | |||
| import trio | ||||
| from trio import TaskStatus | ||||
| 
 | ||||
| from ._debug import ( | ||||
| from .devx._debug import ( | ||||
|     maybe_wait_for_debugger, | ||||
|     acquire_debug_lock, | ||||
| ) | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ import warnings | |||
| 
 | ||||
| import trio | ||||
| 
 | ||||
| from ._debug import maybe_wait_for_debugger | ||||
| from .devx._debug import maybe_wait_for_debugger | ||||
| from ._state import current_actor, is_main_process | ||||
| from .log import get_logger, get_loglevel | ||||
| from ._runtime import Actor | ||||
|  |  | |||
|  | @ -0,0 +1,45 @@ | |||
| # tractor: structured concurrent "actors". | ||||
| # Copyright 2018-eternity Tyler Goodlet. | ||||
| 
 | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU Affero General Public License as published by | ||||
| # the Free Software Foundation, either version 3 of the License, or | ||||
| # (at your option) any later version. | ||||
| 
 | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU Affero General Public License for more details. | ||||
| 
 | ||||
| # You should have received a copy of the GNU Affero General Public License | ||||
| # along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| """ | ||||
| Runtime "developer experience" utils and addons to aid our | ||||
| (advanced) users and core devs in building distributed applications | ||||
| and working with/on the actor runtime. | ||||
| 
 | ||||
| """ | ||||
| from ._debug import ( | ||||
|     maybe_wait_for_debugger, | ||||
|     acquire_debug_lock, | ||||
|     breakpoint, | ||||
|     pause, | ||||
|     pause_from_sync, | ||||
|     shield_sigint_handler, | ||||
|     MultiActorPdb, | ||||
|     open_crash_handler, | ||||
|     post_mortem, | ||||
| ) | ||||
| 
 | ||||
| __all__ = [ | ||||
|     'maybe_wait_for_debugger', | ||||
|     'acquire_debug_lock', | ||||
|     'breakpoint', | ||||
|     'pause', | ||||
|     'pause_from_sync', | ||||
|     'shield_sigint_handler', | ||||
|     'MultiActorPdb', | ||||
|     'open_crash_handler', | ||||
|     'post_mortem', | ||||
| ] | ||||
|  | @ -28,6 +28,7 @@ from functools import ( | |||
|     cached_property, | ||||
| ) | ||||
| from contextlib import asynccontextmanager as acm | ||||
| from contextlib import contextmanager as cm | ||||
| from typing import ( | ||||
|     Any, | ||||
|     Callable, | ||||
|  | @ -44,22 +45,25 @@ from trio_typing import ( | |||
|     # Task, | ||||
| ) | ||||
| 
 | ||||
| from .log import get_logger | ||||
| from ._discovery import get_root | ||||
| from ._state import ( | ||||
| from ..log import get_logger | ||||
| from .._discovery import get_root | ||||
| from .._state import ( | ||||
|     is_root_process, | ||||
|     debug_mode, | ||||
| ) | ||||
| from ._exceptions import ( | ||||
| from .._exceptions import ( | ||||
|     is_multi_cancelled, | ||||
|     ContextCancelled, | ||||
| ) | ||||
| from ._ipc import Channel | ||||
| from .._ipc import Channel | ||||
| 
 | ||||
| log = get_logger(__name__) | ||||
| 
 | ||||
| 
 | ||||
| __all__ = ['breakpoint', 'post_mortem'] | ||||
| __all__ = [ | ||||
|     'breakpoint', | ||||
|     'post_mortem', | ||||
| ] | ||||
| 
 | ||||
| 
 | ||||
| class Lock: | ||||
|  | @ -390,7 +394,7 @@ async def wait_for_parent_stdin_hijack( | |||
|                 # this syncs to child's ``Context.started()`` call. | ||||
|                 async with portal.open_context( | ||||
| 
 | ||||
|                     tractor._debug.lock_tty_for_child, | ||||
|                     lock_tty_for_child, | ||||
|                     subactor_uid=actor_uid, | ||||
| 
 | ||||
|                 ) as (ctx, val): | ||||
|  | @ -855,7 +859,7 @@ pause = partial( | |||
|     _pause, | ||||
|     _set_trace, | ||||
| ) | ||||
| pp = pause  # short-hand for "pause point" | ||||
| # pp = pause  # short-hand for "pause point" | ||||
| 
 | ||||
| 
 | ||||
| async def breakpoint(**kwargs): | ||||
|  | @ -1008,3 +1012,32 @@ async def maybe_wait_for_debugger( | |||
|             log.debug( | ||||
|                     'Root acquired TTY LOCK' | ||||
|             ) | ||||
| 
 | ||||
| 
 | ||||
| # TODO: better naming and what additionals? | ||||
| # - optional runtime plugging? | ||||
| # - detection for sync vs. async code? | ||||
| # - specialized REPL entry when in distributed mode? | ||||
| @cm | ||||
| def open_crash_handler( | ||||
|     catch: set[BaseException] = { | ||||
|         Exception, | ||||
|         BaseException, | ||||
|     } | ||||
| ): | ||||
|     ''' | ||||
|     Generic "post mortem" crash handler using `pdbp` REPL debugger. | ||||
| 
 | ||||
|     We expose this as a CLI framework addon to both `click` and | ||||
|     `typer` users so they can quickly wrap cmd endpoints which get | ||||
|     automatically wrapped to use the runtime's `debug_mode: bool` | ||||
|     AND `pdbp.pm()` around any code that is PRE-runtime entry | ||||
|     - any sync code which runs BEFORE the main call to | ||||
|       `trio.run()`. | ||||
| 
 | ||||
|     ''' | ||||
|     try: | ||||
|         yield | ||||
|     except tuple(catch): | ||||
|         pdbp.xpm() | ||||
|         raise | ||||
		Loading…
	
		Reference in New Issue