Coverage for /usr/local/lib/python3.12/site-packages/prefect/__init__.py: 50%
60 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-12-05 13:38 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-12-05 13:38 +0000
1# isort: skip_file
3# Setup version and path constants
5import sys 1a
6from . import _build_info 1a
7import importlib 1a
8import pathlib 1a
9from typing import TYPE_CHECKING, Any, Optional, TypedDict, cast 1a
11if TYPE_CHECKING: 11 ↛ 12line 11 didn't jump to line 12 because the condition on line 11 was never true1a
12 from importlib.machinery import ModuleSpec
13 from .main import (
14 allow_failure,
15 flow,
16 Flow,
17 get_client,
18 get_run_logger,
19 State,
20 tags,
21 task,
22 Task,
23 Transaction,
24 unmapped,
25 serve,
26 aserve,
27 pause_flow_run,
28 resume_flow_run,
29 suspend_flow_run,
30 )
31 from prefect.deployments.runner import deploy
33 __spec__: ModuleSpec
35 class VersionInfo(TypedDict("_FullRevisionId", {"full-revisionid": str})):
36 version: str
37 dirty: Optional[bool]
38 error: Optional[str]
39 date: Optional[str]
42__version__ = _build_info.__version__ 1a
43__version_info__: "VersionInfo" = cast( 1a
44 "VersionInfo",
45 {
46 "version": __version__,
47 "date": _build_info.__build_date__,
48 "full-revisionid": _build_info.__git_commit__,
49 "error": None,
50 "dirty": _build_info.__dirty__,
51 },
52)
54# The absolute path to this module
55__module_path__: pathlib.Path = pathlib.Path(__file__).parent 1a
56# The absolute path to the root of the repository, only valid for use during development
57__development_base_path__: pathlib.Path = __module_path__.parents[1] 1a
59# The absolute path to the built UI within the Python module, used by
60# `prefect server start` to serve a dynamic build of the UI
61__ui_static_subpath__: pathlib.Path = __module_path__ / "server" / "ui_build" 1a
63# The absolute path to the built UI within the Python module
64__ui_static_path__: pathlib.Path = __module_path__ / "server" / "ui" 1a
66del _build_info, pathlib 1a
69def _initialize_plugins() -> None: 1a
70 """
71 Initialize the experimental plugin system if enabled.
73 This runs automatically when Prefect is imported and plugins are enabled
74 via experiments.plugins.enabled setting. Errors are logged but don't prevent
75 Prefect from loading.
76 """
77 try: 1a
78 # Import here to avoid circular imports and defer cost until needed
79 from prefect.settings import get_current_settings 1a
81 if not get_current_settings().experiments.plugins.enabled: 81 ↛ 84line 81 didn't jump to line 84 because the condition on line 81 was always true1a
82 return 1a
84 import anyio
86 from prefect._experimental.plugins import run_startup_hooks
87 from prefect._experimental.plugins.spec import HookContext
88 from prefect.logging import get_logger
89 from prefect.settings import get_current_settings
91 ctx = HookContext(
92 prefect_version=__version__,
93 api_url=get_current_settings().api.url,
94 logger_factory=get_logger,
95 )
97 # Run plugin hooks synchronously during import
98 anyio.run(run_startup_hooks, ctx)
99 except SystemExit:
100 # Re-raise SystemExit from strict mode
101 raise
102 except Exception as e:
103 # Log but don't crash on plugin errors
104 try:
105 from prefect.logging import get_logger
107 logger = get_logger("prefect.plugins")
108 logger.exception("Failed to initialize plugins: %s", e)
109 except Exception:
110 # If even logging fails, print to stderr and continue
111 import sys
113 print(f"Failed to initialize plugins: {e}", file=sys.stderr)
116# Initialize plugins on import if enabled
117_initialize_plugins() 1a
119_public_api: dict[str, tuple[Optional[str], str]] = { 1a
120 "allow_failure": (__spec__.parent, ".main"),
121 "aserve": (__spec__.parent, ".main"),
122 "deploy": (__spec__.parent, ".deployments.runner"),
123 "flow": (__spec__.parent, ".main"),
124 "Flow": (__spec__.parent, ".main"),
125 "get_client": (__spec__.parent, ".main"),
126 "get_run_logger": (__spec__.parent, ".main"),
127 "pause_flow_run": (__spec__.parent, ".main"),
128 "resume_flow_run": (__spec__.parent, ".main"),
129 "serve": (__spec__.parent, ".main"),
130 "State": (__spec__.parent, ".main"),
131 "suspend_flow_run": (__spec__.parent, ".main"),
132 "tags": (__spec__.parent, ".main"),
133 "task": (__spec__.parent, ".main"),
134 "Task": (__spec__.parent, ".main"),
135 "Transaction": (__spec__.parent, ".main"),
136 "unmapped": (__spec__.parent, ".main"),
137}
139# Declare API for type-checkers
140__all__ = [ 1a
141 "__version__",
142 "allow_failure",
143 "aserve",
144 "deploy",
145 "flow",
146 "Flow",
147 "get_client",
148 "get_run_logger",
149 "pause_flow_run",
150 "resume_flow_run",
151 "serve",
152 "State",
153 "suspend_flow_run",
154 "tags",
155 "task",
156 "Task",
157 "Transaction",
158 "unmapped",
159]
162def __getattr__(attr_name: str) -> Any: 1a
163 try: 1ab
164 if (dynamic_attr := _public_api.get(attr_name)) is None: 1ab
165 return importlib.import_module(f".{attr_name}", package=__name__) 1a
167 package, mname = dynamic_attr 1ab
168 if mname == "__module__": 168 ↛ 169line 168 didn't jump to line 169 because the condition on line 168 was never true1ab
169 return importlib.import_module(f".{attr_name}", package=package)
170 else:
171 module = importlib.import_module(mname, package=package) 1ab
172 return getattr(module, attr_name) 1ab
173 except ModuleNotFoundError as ex:
174 mname, _, attr = (ex.name or "").rpartition(".")
175 ctx = {"name": mname, "obj": attr} if sys.version_info >= (3, 10) else {}
176 raise AttributeError(f"module {mname} has no attribute {attr}", **ctx) from ex