From e43920236b0aca8cb9052007699526f2c45b9e07 Mon Sep 17 00:00:00 2001 From: nate nowack Date: Tue, 8 Oct 2024 14:50:45 -0500 Subject: [PATCH] unset default dependent settings assigned posthoc (#15613) --- src/prefect/settings.py | 45 ++++++++++++++++++----------------------- tests/test_settings.py | 3 --- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/prefect/settings.py b/src/prefect/settings.py index ef127de23e38..abaa0844d47f 100644 --- a/src/prefect/settings.py +++ b/src/prefect/settings.py @@ -71,22 +71,6 @@ DEFAULT_PROFILES_PATH = Path(__file__).parent.joinpath("profiles.toml") _SECRET_TYPES: Tuple[Type, ...] = (Secret, SecretStr) -# see #https://github.com/pydantic/pydantic/issues/9789 -# these fields will show as "set" even though we are only setting them -# to their default values in an after model validator -DEFAULT_DEPENDENT_SETTINGS = [ - "PREFECT_UI_URL", - "PREFECT_UI_API_URL", - "PREFECT_LOGGING_SETTINGS_PATH", - "PREFECT_API_DATABASE_CONNECTION_URL", - "PREFECT_LOCAL_STORAGE_PATH", - "PREFECT_LOGGING_INTERNAL_LEVEL", - "PREFECT_LOGGING_LEVEL", - "PREFECT_PROFILES_PATH", - "PREFECT_CLOUD_UI_URL", - "PREFECT_MEMO_STORE_PATH", -] - def env_var_to_attr_name(env_var: str) -> str: """ @@ -1458,37 +1442,50 @@ def __getattribute__(self, name: str) -> Any: @model_validator(mode="after") def post_hoc_settings(self) -> Self: - # TODO: refactor on resolution of https://github.com/pydantic/pydantic/issues/9789 + """refactor on resolution of https://github.com/pydantic/pydantic/issues/9789 + + we should not be modifying __pydantic_fields_set__ directly, but until we can + define dependencies between defaults in a first-class way, we need clean up + post-hoc default assignments to keep set/unset fields correct after instantiation. + """ if self.cloud_ui_url is None: self.cloud_ui_url = default_cloud_ui_url(self) + self.__pydantic_fields_set__.remove("cloud_ui_url") + if self.ui_url is None: self.ui_url = default_ui_url(self) + self.__pydantic_fields_set__.remove("ui_url") if self.ui_api_url is None: if self.api_url: self.ui_api_url = self.api_url + self.__pydantic_fields_set__.remove("ui_api_url") else: self.ui_api_url = ( f"http://{self.server_api_host}:{self.server_api_port}" ) - + self.__pydantic_fields_set__.remove("ui_api_url") if self.profiles_path is None or "PREFECT_HOME" in str(self.profiles_path): self.profiles_path = Path(f"{self.home}/profiles.toml") + self.__pydantic_fields_set__.remove("profiles_path") if self.local_storage_path is None: self.local_storage_path = Path(f"{self.home}/storage") + self.__pydantic_fields_set__.remove("local_storage_path") if self.memo_store_path is None: self.memo_store_path = Path(f"{self.home}/memo_store.toml") - + self.__pydantic_fields_set__.remove("memo_store_path") if self.debug_mode or self.test_mode: self.logging_level = "DEBUG" self.logging_internal_level = "DEBUG" + self.__pydantic_fields_set__.remove("logging_level") + self.__pydantic_fields_set__.remove("logging_internal_level") if self.logging_settings_path is None: self.logging_settings_path = Path(f"{self.home}/logging.yml") - + self.__pydantic_fields_set__.remove("logging_settings_path") # Set default database connection URL if not provided if self.api_database_connection_url is None: self.api_database_connection_url = default_database_connection_url(self) - + self.__pydantic_fields_set__.remove("api_database_connection_url") if "PREFECT_API_DATABASE_PASSWORD" in ( db_url := ( self.api_database_connection_url.get_secret_value() @@ -1508,7 +1505,7 @@ def post_hoc_settings(self) -> Self: if self.api_database_password else "" ) - + self.__pydantic_fields_set__.remove("api_database_connection_url") return self @model_validator(mode="after") @@ -1703,9 +1700,7 @@ def temporary_settings( context = prefect.context.get_settings_context() if not restore_defaults: - restore_defaults = [ - SETTING_VARIABLES[key] for key in DEFAULT_DEPENDENT_SETTINGS - ] + restore_defaults = [] new_settings = context.settings.copy_with_update( updates=updates, set_defaults=set_defaults, restore_defaults=restore_defaults diff --git a/tests/test_settings.py b/tests/test_settings.py index 4e17d2dd04ad..0aa36c2adf86 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -12,7 +12,6 @@ import prefect.settings from prefect.exceptions import ProfileSettingsValidationError from prefect.settings import ( - DEFAULT_DEPENDENT_SETTINGS, DEFAULT_PROFILES_PATH, PREFECT_API_DATABASE_CONNECTION_URL, PREFECT_API_DATABASE_DRIVER, @@ -148,7 +147,6 @@ def test_settings_to_environment_exclude_unset_empty_if_none_set(self, monkeypat assert Settings().to_environment_variables( exclude_unset=True, - exclude={SETTING_VARIABLES[key] for key in DEFAULT_DEPENDENT_SETTINGS}, ) == { "PREFECT_TEST_MODE": "True", } @@ -161,7 +159,6 @@ def test_settings_to_environment_exclude_unset_only_includes_set(self, monkeypat assert Settings(debug_mode=True, api_key="Hello").to_environment_variables( exclude_unset=True, - exclude={SETTING_VARIABLES[key] for key in DEFAULT_DEPENDENT_SETTINGS}, ) == { "PREFECT_TEST_MODE": "True", "PREFECT_DEBUG_MODE": "True",