def markers(**config_from_cli: Any) -> NoReturn: """Show all registered markers.""" config_from_cli["command"] = "markers" try: # Duplication of the same mechanism in :func:`pytask.main.main`. pm = get_plugin_manager() from _pytask import cli pm.register(cli) pm.hook.pytask_add_hooks(pm=pm) config = pm.hook.pytask_configure(pm=pm, config_from_cli=config_from_cli) session = Session.from_config(config) except (ConfigurationError, Exception): console.print_exception() session = Session({}, None) session.exit_code = ExitCode.CONFIGURATION_FAILED else: table = Table("Marker", "Description", leading=1) for name, description in config["markers"].items(): table.add_row(f"pytask.mark.{name}", description) console.print(table) sys.exit(session.exit_code)
def build_dag(config_from_cli: dict[str, Any]) -> nx.DiGraph: """Build the DAG. This function is the programmatic interface to ``pytask dag`` and returns a preprocessed :class:`pydot.Dot` which makes plotting easier than with matplotlib. To change the style of the graph, it might be easier to convert the graph back to networkx, set attributes, and convert back to pydot or pygraphviz. Parameters ---------- config_from_cli : Dict[str, Any] The configuration usually received from the CLI. For example, use ``{"paths": "example-directory/"}`` to collect tasks from a directory. Returns ------- pydot.Dot A preprocessed graph which can be customized and exported. """ try: pm = get_plugin_manager() from _pytask import cli pm.register(cli) pm.hook.pytask_add_hooks(pm=pm) config = pm.hook.pytask_configure(pm=pm, config_from_cli=config_from_cli) session = Session.from_config(config) except (ConfigurationError, Exception): console.print_exception() session = Session({}, None) session.exit_code = ExitCode.CONFIGURATION_FAILED else: try: session.hook.pytask_log_session_header(session=session) import_optional_dependency("pydot") check_for_optional_program( session.config["layout"], extra="The layout program is part of the graphviz package which you " "can install with conda.", ) session.hook.pytask_collect(session=session) session.hook.pytask_resolve_dependencies(session=session) dag = _refine_dag(session) except Exception: raise else: return dag
def collect(**config_from_cli: Any | None) -> NoReturn: """Collect tasks and report information about them.""" config_from_cli["command"] = "collect" try: # Duplication of the same mechanism in :func:`pytask.main.main`. pm = get_plugin_manager() from _pytask import cli pm.register(cli) pm.hook.pytask_add_hooks(pm=pm) config = pm.hook.pytask_configure(pm=pm, config_from_cli=config_from_cli) session = Session.from_config(config) except (ConfigurationError, Exception): session = Session({}, None) session.exit_code = ExitCode.CONFIGURATION_FAILED console.print_exception() else: try: session.hook.pytask_log_session_header(session=session) session.hook.pytask_collect(session=session) session.hook.pytask_resolve_dependencies(session=session) tasks = _select_tasks_by_expressions_and_marker(session) common_ancestor = _find_common_ancestor_of_all_nodes( tasks, session.config["paths"], session.config["nodes"]) dictionary = _organize_tasks(tasks) if dictionary: _print_collected_tasks( dictionary, session.config["nodes"], session.config["editor_url_scheme"], common_ancestor, ) console.print() console.rule(style="neutral") except CollectionError: session.exit_code = ExitCode.COLLECTION_FAILED except ResolvingDependenciesError: session.exit_code = ExitCode.RESOLVING_DEPENDENCIES_FAILED except Exception: session.exit_code = ExitCode.FAILED console.print_exception() console.rule(style="failed") sys.exit(session.exit_code)
def profile(**config_from_cli: Any) -> NoReturn: """Show information about tasks like runtime and memory consumption of products.""" config_from_cli["command"] = "profile" try: # Duplication of the same mechanism in :func:`pytask.main.main`. pm = get_plugin_manager() from _pytask import cli pm.register(cli) pm.hook.pytask_add_hooks(pm=pm) config = pm.hook.pytask_configure(pm=pm, config_from_cli=config_from_cli) session = Session.from_config(config) except (ConfigurationError, Exception): # pragma: no cover session = Session({}, None) session.exit_code = ExitCode.CONFIGURATION_FAILED exc_info: tuple[ type[BaseException], BaseException, TracebackType | None ] = sys.exc_info() console.print(render_exc_info(*exc_info, show_locals=config["show_locals"])) else: try: session.hook.pytask_log_session_header(session=session) session.hook.pytask_collect(session=session) session.hook.pytask_resolve_dependencies(session=session) profile: dict[str, dict[str, Any]] = { task.name: {} for task in session.tasks } session.hook.pytask_profile_add_info_on_task( session=session, tasks=session.tasks, profile=profile ) profile = _process_profile(profile) _print_profile_table(profile, session.tasks, session.config) session.hook.pytask_profile_export_profile(session=session, profile=profile) console.rule(style="neutral") except CollectionError: # pragma: no cover session.exit_code = ExitCode.COLLECTION_FAILED except Exception: # pragma: no cover session.exit_code = ExitCode.FAILED console.print_exception() console.rule(style="failed") sys.exit(session.exit_code)
def dag(**config_from_cli: Any) -> NoReturn: """Create a visualization of the project's directed acyclic graph.""" try: pm = get_plugin_manager() from _pytask import cli pm.register(cli) pm.hook.pytask_add_hooks(pm=pm) config = pm.hook.pytask_configure(pm=pm, config_from_cli=config_from_cli) session = Session.from_config(config) except (ConfigurationError, Exception): console.print_exception() session = Session({}, None) session.exit_code = ExitCode.CONFIGURATION_FAILED else: try: session.hook.pytask_log_session_header(session=session) import_optional_dependency("pydot") check_for_optional_program( session.config["layout"], extra="The layout program is part of the graphviz package which you " "can install with conda.", ) session.hook.pytask_collect(session=session) session.hook.pytask_resolve_dependencies(session=session) dag = _refine_dag(session) _write_graph(dag, session.config["output_path"], session.config["layout"]) except CollectionError: session.exit_code = ExitCode.COLLECTION_FAILED except ResolvingDependenciesError: session.exit_code = ExitCode.RESOLVING_DEPENDENCIES_FAILED except Exception: session.exit_code = ExitCode.FAILED exc_info = remove_internal_traceback_frames_from_exc_info(sys.exc_info()) console.print() console.print(Traceback.from_exception(*exc_info)) console.rule(style="failed") sys.exit(session.exit_code)
def _create_session(config_from_cli: dict[str, Any]) -> nx.DiGraph: """Create a session object.""" try: pm = get_plugin_manager() from _pytask import cli pm.register(cli) pm.hook.pytask_add_hooks(pm=pm) config = pm.hook.pytask_configure(pm=pm, config_from_cli=config_from_cli) session = Session.from_config(config) except (ConfigurationError, Exception): console.print_exception() session = Session({}, None) session.exit_code = ExitCode.CONFIGURATION_FAILED else: try: session.hook.pytask_log_session_header(session=session) import_optional_dependency("pydot") check_for_optional_program(session.config["layout"]) session.hook.pytask_collect(session=session) session.hook.pytask_resolve_dependencies(session=session) except CollectionError: session.exit_code = ExitCode.COLLECTION_FAILED except ResolvingDependenciesError: session.exit_code = ExitCode.RESOLVING_DEPENDENCIES_FAILED except Exception: session.exit_code = ExitCode.FAILED console.print_exception() console.rule(style="failed") return session