Skip to content

Commit ed43ee8

Browse files
authored
Remove legacy settings imports from CLI (#19353)
1 parent 7d02236 commit ed43ee8

File tree

13 files changed

+58
-64
lines changed

13 files changed

+58
-64
lines changed

src/prefect/cli/_types.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,22 @@
66
import functools
77
import sys
88
from datetime import datetime
9-
from typing import Any, Callable, List, Optional
9+
from typing import TYPE_CHECKING, Any, Callable, List, Optional
1010

1111
import typer
1212
from rich.console import Console
1313
from rich.theme import Theme
1414

1515
from prefect._internal.compatibility.deprecated import generate_deprecation_message
1616
from prefect.cli._utilities import with_cli_exception_handling
17-
from prefect.settings import PREFECT_CLI_COLORS, Setting
17+
from prefect.settings import get_current_settings
1818
from prefect.utilities.asyncutils import is_async_fn
1919

20+
if TYPE_CHECKING:
21+
from prefect.settings.legacy import Setting
2022

21-
def SettingsOption(setting: Setting, *args: Any, **kwargs: Any) -> Any:
23+
24+
def SettingsOption(setting: "Setting", *args: Any, **kwargs: Any) -> Any:
2225
"""Custom `typer.Option` factory to load the default value from settings"""
2326

2427
return typer.Option(
@@ -34,7 +37,7 @@ def SettingsOption(setting: Setting, *args: Any, **kwargs: Any) -> Any:
3437
)
3538

3639

37-
def SettingsArgument(setting: Setting, *args: Any, **kwargs: Any) -> Any:
40+
def SettingsArgument(setting: "Setting", *args: Any, **kwargs: Any) -> Any:
3841
"""Custom `typer.Argument` factory to load the default value from settings"""
3942

4043
# See comments in `SettingsOption`
@@ -91,7 +94,7 @@ def __init__(
9194
self.console = Console(
9295
highlight=False,
9396
theme=Theme({"prompt.choices": "bold blue"}),
94-
color_system="auto" if PREFECT_CLI_COLORS else None,
97+
color_system="auto" if get_current_settings().cli.colors else None,
9598
)
9699

97100
def add_typer(
@@ -201,7 +204,7 @@ def sync_fn(*args: Any, **kwargs: Any) -> Any:
201204
def setup_console(self, soft_wrap: bool, prompt: bool) -> None:
202205
self.console = Console(
203206
highlight=False,
204-
color_system="auto" if PREFECT_CLI_COLORS else None,
207+
color_system="auto" if get_current_settings().cli.colors else None,
205208
theme=Theme({"prompt.choices": "bold blue"}),
206209
soft_wrap=not soft_wrap,
207210
force_interactive=prompt,

src/prefect/cli/_utilities.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from click.exceptions import ClickException
1313

1414
from prefect.exceptions import MissingProfileError
15-
from prefect.settings import PREFECT_TEST_MODE
15+
from prefect.settings import get_current_settings
1616

1717

1818
def exit_with_error(message: str | Exception, code: int = 1, **kwargs: Any) -> NoReturn:
@@ -47,7 +47,7 @@ def wrapper(*args: Any, **kwargs: Any) -> Any:
4747
except MissingProfileError as exc:
4848
exit_with_error(exc)
4949
except Exception:
50-
if PREFECT_TEST_MODE.value():
50+
if get_current_settings().testing.test_mode:
5151
raise # Reraise exceptions during test mode
5252
traceback.print_exc()
5353
exit_with_error("An exception occurred.")

src/prefect/cli/block.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
ScriptError,
2929
exception_traceback,
3030
)
31-
from prefect.settings import PREFECT_UI_URL
31+
from prefect.settings import get_current_settings
3232
from prefect.utilities.asyncutils import run_sync_in_worker_thread
3333
from prefect.utilities.importtools import load_script_as_module
3434

@@ -244,7 +244,7 @@ async def register(
244244
"go to the Blocks page in the Prefect UI.\n"
245245
)
246246

247-
if ui_url := PREFECT_UI_URL:
247+
if ui_url := get_current_settings().ui_url:
248248
if determine_server_type() == ServerType.CLOUD:
249249
block_catalog_url = f"{ui_url}/settings/blocks/catalog"
250250
else:
@@ -349,17 +349,16 @@ async def block_create(
349349
app.console.print(f"Available block types: {', '.join(slugs)}")
350350
raise typer.Exit(1)
351351

352-
if not PREFECT_UI_URL:
352+
ui_url = get_current_settings().ui_url
353+
if not ui_url:
353354
exit_with_error(
354355
"Prefect must be configured to use a hosted Prefect server or "
355356
"Prefect Cloud to display the Prefect UI"
356357
)
357358
if determine_server_type() == ServerType.CLOUD:
358-
block_link = f"{PREFECT_UI_URL.value()}/settings/blocks/catalog/{block_type.slug}/create"
359+
block_link = f"{ui_url}/settings/blocks/catalog/{block_type.slug}/create"
359360
else:
360-
block_link = (
361-
f"{PREFECT_UI_URL.value()}/blocks/catalog/{block_type.slug}/create"
362-
)
361+
block_link = f"{ui_url}/blocks/catalog/{block_type.slug}/create"
363362
app.console.print(
364363
f"Create a {block_type_slug} block: {block_link}",
365364
)

src/prefect/cli/cloud/webhook.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from prefect.cli.root import app, is_interactive
1515
from prefect.client.cloud import get_cloud_client
1616
from prefect.exceptions import ObjectNotFound
17-
from prefect.settings import PREFECT_API_URL
17+
from prefect.settings import get_current_settings
1818

1919
webhook_app: PrefectTyper = PrefectTyper(
2020
name="webhook", help="Manage Prefect Cloud Webhooks"
@@ -49,7 +49,7 @@ async def ls():
4949
confirm_logged_in()
5050

5151
# The /webhooks API lives inside the /accounts/{id}/workspaces/{id} routing tree
52-
async with get_cloud_client(host=PREFECT_API_URL.value()) as client:
52+
async with get_cloud_client(host=get_current_settings().api.url) as client:
5353
retrieved_webhooks = await client.request("POST", "/webhooks/filter")
5454
display_table = _render_webhooks_into_table(retrieved_webhooks)
5555
app.console.print(display_table)
@@ -63,7 +63,7 @@ async def get(webhook_id: UUID):
6363
confirm_logged_in()
6464

6565
# The /webhooks API lives inside the /accounts/{id}/workspaces/{id} routing tree
66-
async with get_cloud_client(host=PREFECT_API_URL.value()) as client:
66+
async with get_cloud_client(host=get_current_settings().api.url) as client:
6767
webhook = await client.request("GET", f"/webhooks/{webhook_id}")
6868
display_table = _render_webhooks_into_table([webhook])
6969
app.console.print(display_table)
@@ -94,7 +94,7 @@ async def create(
9494
confirm_logged_in()
9595

9696
# The /webhooks API lives inside the /accounts/{id}/workspaces/{id} routing tree
97-
async with get_cloud_client(host=PREFECT_API_URL.value()) as client:
97+
async with get_cloud_client(host=get_current_settings().api.url) as client:
9898
response = await client.request(
9999
"POST",
100100
"/webhooks/",
@@ -122,7 +122,7 @@ async def rotate(webhook_id: UUID):
122122
return
123123

124124
# The /webhooks API lives inside the /accounts/{id}/workspaces/{id} routing tree
125-
async with get_cloud_client(host=PREFECT_API_URL.value()) as client:
125+
async with get_cloud_client(host=get_current_settings().api.url) as client:
126126
response = await client.request("POST", f"/webhooks/{webhook_id}/rotate")
127127
app.console.print(f"Successfully rotated webhook URL to {response['slug']}")
128128

@@ -138,7 +138,7 @@ async def toggle(
138138

139139
status_lookup = {True: "enabled", False: "disabled"}
140140

141-
async with get_cloud_client(host=PREFECT_API_URL.value()) as client:
141+
async with get_cloud_client(host=get_current_settings().api.url) as client:
142142
response = await client.request("GET", f"/webhooks/{webhook_id}")
143143
current_status = response["enabled"]
144144
new_status = not current_status
@@ -166,7 +166,7 @@ async def update(
166166
confirm_logged_in()
167167

168168
# The /webhooks API lives inside the /accounts/{id}/workspaces/{id} routing tree
169-
async with get_cloud_client(host=PREFECT_API_URL.value()) as client:
169+
async with get_cloud_client(host=get_current_settings().api.url) as client:
170170
response = await client.request("GET", f"/webhooks/{webhook_id}")
171171
update_payload = {
172172
"name": webhook_name or response["name"],
@@ -192,7 +192,7 @@ async def delete(webhook_id: UUID):
192192
exit_with_error("Deletion aborted.")
193193

194194
# The /webhooks API lives inside the /accounts/{id}/workspaces/{id} routing tree
195-
async with get_cloud_client(host=PREFECT_API_URL.value()) as client:
195+
async with get_cloud_client(host=get_current_settings().api.url) as client:
196196
try:
197197
await client.request("DELETE", f"/webhooks/{webhook_id}")
198198
app.console.print(f"Successfully deleted webhook {webhook_id}")

src/prefect/cli/dashboard.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from prefect.cli._types import PrefectTyper
44
from prefect.cli._utilities import exit_with_error, exit_with_success
55
from prefect.cli.root import app
6-
from prefect.settings import PREFECT_UI_URL
6+
from prefect.settings import get_current_settings
77
from prefect.utilities.asyncutils import run_sync_in_worker_thread
88

99
dashboard_app: PrefectTyper = PrefectTyper(
@@ -19,7 +19,7 @@ async def open() -> None:
1919
Open the Prefect UI in the browser.
2020
"""
2121

22-
if not (ui_url := PREFECT_UI_URL.value()):
22+
if not (ui_url := get_current_settings().ui_url):
2323
exit_with_error(
2424
"`PREFECT_UI_URL` must be set to the URL of a running Prefect server or Prefect Cloud workspace."
2525
)

src/prefect/cli/deploy/_commands.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
from rich.table import Table
99

1010
import prefect
11-
from prefect.cli._types import SettingsOption
1211
from prefect.cli._utilities import exit_with_error
1312
from prefect.cli.root import app, is_interactive
1413
from prefect.client.schemas.objects import ConcurrencyLimitConfig
1514
from prefect.deployments import initialize_project
16-
from prefect.settings import PREFECT_DEFAULT_WORK_POOL_NAME
15+
from prefect.settings import get_current_settings
1716

1817
from ._config import (
1918
_load_deploy_configs_and_actions,
@@ -178,11 +177,12 @@ async def deploy(
178177
"--collision-strategy",
179178
help="Configure the behavior for runs once the concurrency limit is reached. Falls back to `ENQUEUE` if unset.",
180179
),
181-
work_pool_name: str = SettingsOption(
182-
PREFECT_DEFAULT_WORK_POOL_NAME,
180+
work_pool_name: str = typer.Option(
181+
lambda: get_current_settings().deployments.default_work_pool_name,
183182
"-p",
184183
"--pool",
185184
help="The work pool that will handle this deployment's runs.",
185+
show_default="from PREFECT_DEFAULT_WORK_POOL_NAME",
186186
),
187187
work_queue_name: str = typer.Option(
188188
None,

src/prefect/cli/deploy/_core.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from prefect.deployments.steps.core import run_steps
2626
from prefect.exceptions import ObjectNotFound
2727
from prefect.flows import load_flow_from_entrypoint
28-
from prefect.settings import PREFECT_UI_URL
28+
from prefect.settings import get_current_settings
2929
from prefect.utilities.callables import parameter_schema
3030
from prefect.utilities.collections import get_from_dict
3131
from prefect.utilities.templating import (
@@ -373,10 +373,10 @@ async def _run_single_deploy(
373373
style="green",
374374
)
375375

376-
if PREFECT_UI_URL:
376+
if ui_url := get_current_settings().ui_url:
377377
message = (
378378
"\nView Deployment in UI:"
379-
f" {PREFECT_UI_URL.value()}/deployments/deployment/{deployment_id}\n"
379+
f" {ui_url}/deployments/deployment/{deployment_id}\n"
380380
)
381381
app.console.print(message, soft_wrap=True)
382382

src/prefect/cli/root.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,7 @@
1919
from prefect.client.base import determine_server_type
2020
from prefect.client.constants import SERVER_API_VERSION
2121
from prefect.logging.configuration import setup_logging
22-
from prefect.settings import (
23-
PREFECT_CLI_WRAP_LINES,
24-
PREFECT_TEST_MODE,
25-
)
22+
from prefect.settings import get_current_settings
2623
from prefect.types._datetime import parse_datetime
2724

2825
app: PrefectTyper = PrefectTyper(add_completion=True, no_args_is_help=True)
@@ -77,9 +74,9 @@ def main(
7774
exit(1)
7875

7976
# Configure the output console after loading the profile
80-
app.setup_console(soft_wrap=PREFECT_CLI_WRAP_LINES.value(), prompt=prompt)
77+
app.setup_console(soft_wrap=get_current_settings().cli.wrap_lines, prompt=prompt)
8178

82-
if not PREFECT_TEST_MODE:
79+
if not get_current_settings().testing.test_mode:
8380
# When testing, this entrypoint can be called multiple times per process which
8481
# can cause logging configuration conflicts. Logging is set up in conftest
8582
# during tests.
@@ -107,7 +104,6 @@ async def version(
107104

108105
from prefect.server.database.dependencies import provide_database_interface
109106
from prefect.server.utilities.database import get_dialect
110-
from prefect.settings import PREFECT_API_DATABASE_CONNECTION_URL
111107

112108
if build_date_str := prefect.__version_info__.get("date", None):
113109
build_date = parse_datetime(build_date_str).strftime("%a, %b %d, %Y %I:%M %p")
@@ -134,7 +130,8 @@ async def version(
134130

135131
version_info["Pydantic version"] = pydantic_version
136132

137-
if connection_url := PREFECT_API_DATABASE_CONNECTION_URL.value():
133+
if connection_url_setting := get_current_settings().server.database.connection_url:
134+
connection_url = connection_url_setting.get_secret_value()
138135
database = get_dialect(connection_url).name
139136
version_info["Server"] = {"Database": database}
140137
if database == "sqlite":

src/prefect/cli/shell.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from prefect.exceptions import FailedRun
2323
from prefect.logging.loggers import get_run_logger
2424
from prefect.runner import Runner
25-
from prefect.settings import PREFECT_UI_URL
25+
from prefect.settings import get_current_settings
2626
from prefect.types.entrypoint import EntrypointType
2727

2828
shell_app: PrefectTyper = PrefectTyper(
@@ -236,10 +236,10 @@ async def serve(
236236
" command:\n[blue]\n\t$ prefect deployment run"
237237
f" '{runner_deployment.flow_name}/{deployment_name}'\n[/]"
238238
)
239-
if PREFECT_UI_URL:
239+
if ui_url := get_current_settings().ui_url:
240240
help_message += (
241241
"\nYou can also run your flow via the Prefect UI:"
242-
f" [blue]{PREFECT_UI_URL.value()}/deployments/deployment/{deployment_id}[/]\n"
242+
f" [blue]{ui_url}/deployments/deployment/{deployment_id}[/]\n"
243243
)
244244

245245
app.console.print(help_message, soft_wrap=True)

src/prefect/settings/__init__.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@
1010
for settings, at which point we will not need to use the "after" model_validator.
1111
"""
1212

13-
from prefect.settings.legacy import (
14-
Setting,
15-
_get_settings_fields,
16-
_get_valid_setting_names,
17-
)
13+
from typing import TYPE_CHECKING
14+
1815
from prefect.settings.models.root import Settings, canonical_environment_prefix
1916

2017
from prefect.settings.profiles import (
@@ -29,11 +26,18 @@
2926
from prefect.settings.context import get_current_settings, temporary_settings
3027
from prefect.settings.constants import DEFAULT_PROFILES_PATH
3128

29+
if TYPE_CHECKING:
30+
from prefect.settings.legacy import Setting
3231
############################################################################
3332
# Allow traditional env var access
3433

3534

36-
def __getattr__(name: str) -> Setting:
35+
def __getattr__(name: str) -> "Setting":
36+
from prefect.settings.legacy import (
37+
_get_settings_fields,
38+
_get_valid_setting_names,
39+
)
40+
3741
if name in _get_valid_setting_names(Settings):
3842
return _get_settings_fields(Settings)[name]
3943
raise AttributeError(f"{name} is not a Prefect setting.")
@@ -42,7 +46,6 @@ def __getattr__(name: str) -> Setting:
4246
__all__ = [ # noqa: F822
4347
"Profile",
4448
"ProfilesCollection",
45-
"Setting",
4649
"Settings",
4750
"load_current_profile",
4851
"update_current_profile",

0 commit comments

Comments
 (0)