Each setting is defined as a Setting type. The name of each setting is stylized in all
caps, matching the environment variable that can be used to change the setting.
All settings defined in this file are used to generate a dynamic Pydantic settings class
called Settings. When instantiated, this class will load settings from environment
variables and pull default values from the setting definitions.
The current instance of Settings being used by the application is stored in a
SettingsContext model which allows each instance of the Settings class to be
accessed in an async-safe manner.
Aside from environment variables, we allow settings to be changed during the runtime of
the process using profiles. Profiles contain setting overrides that the user may
persist without setting environment variables. Profiles are also used internally for
managing settings during task run execution where differing settings may be used
concurrently in the same process and during testing where we need to override settings
to ensure their value is respected as intended.
The SettingsContext is set when the prefect module is imported. This context is
referred to as the "root" settings context for clarity. Generally, this is the only
settings context that will be used. When this context is entered, we will instantiate
a Settings object, loading settings from environment variables and defaults, then we
will load the active profile and use it to override settings. See enter_root_settings_context
for details on determining the active profile.
Another SettingsContext may be entered at any time to change the settings being
used by the code within the context. Generally, users should not use this. Settings
management should be left to Prefect application internals.
Generally, settings should be accessed with SETTING_VARIABLE.value() which will
pull the current Settings instance from the current SettingsContext and retrieve
the value of the relevant setting.
Accessing a setting's value will also call the Setting.value_callback which allows
settings to be dynamically modified on retrieval. This allows us to make settings
dependent on the value of other settings or perform other dynamic effects.
Modules for Prefect to import when Prefect is imported.
Values should be separated by commas, e.g. my_module,my_other_module.
Objects within modules may be specified by a ':' partition, e.g. my_module:my_object.
If a callable object is provided, it will be called with no arguments on import.
If True, places the API in debug mode. This may modify
behavior to facilitate debugging, including extra logs and other verbose
assistance. Defaults to False.
If True, use interactive prompts in CLI commands. If False, no interactive
prompts will be used. If None, the value will be dynamically determined based on
the presence of an interactive-enabled terminal.
This configuration settings option specifies the path to an SSL certificate file.
When set, it allows the application to use the specified certificate for secure communication.
If left unset, the setting will default to the value provided by the SSL_CERT_FILE environment variable.
If True, disable the warning when a user accidentally misconfigure its PREFECT_API_URL
Sometimes when a user manually set PREFECT_API_URL to a custom url,reverse-proxy for example,
we would like to silence this warning so we will set it to FALSE.
A value greater than or equal to zero to control the amount of jitter added to retried
client requests. Higher values introduce larger amounts of jitter.
Set to 0 to disable jitter. See clamped_poisson_interval for details on the how jitter
can affect retry lengths.
A comma-separated list of extra HTTP status codes to retry on. Defaults to an empty string.
429, 502 and 503 are always retried. Please note that not all routes are idempotent and retrying
may result in unexpected behavior.
Determines if CSRF token handling is active in the Prefect client for API
requests.
When enabled (True), the client automatically manages CSRF tokens by
retrieving, storing, and including them in applicable state-changing requests
(POST, PUT, PATCH, DELETE) to the API.
Disabling this setting (False) means the client will not handle CSRF tokens,
which might be suitable for environments where CSRF protection is disabled.
Defaults to True, ensuring CSRF protection is enabled by default.
The default logging level for Prefect's internal machinery loggers. Defaults to
"ERROR" during normal operation. Is forced to "DEBUG" during debug mode.
The path to a custom YAML logging configuration file. If
no file is found, the default logging.yml is used.
Defaults to a logging.yml in the Prefect home directory.
Additional loggers to attach to Prefect logging at runtime.
Values should be comma separated. The handlers attached to the 'prefect' logger
will be added to these loggers. Additionally, if the level is not set, it will
be set to the same level as the 'prefect' logger.
If set, print statements in flows and tasks will be redirected to the Prefect logger
for the given run. This setting can be overridden by individual tasks and flows.
Controls the behavior when loggers attempt to send logs to the API handler from outside
of a flow.
All logs sent to the API must be associated with a flow run. The API log handler can
only be used outside of a flow by manually providing a flow run identifier. Logs
that are not associated with a flow run will not be sent to the API. This setting can
be used to determine if a warning or error is displayed when the identifier is missing.
The following options are available:
"warn": Log a warning message.
"error": Raise an error.
"ignore": Do not log a warning message or raise an error.
Controls maximum overflow of the connection pool when using a PostgreSQL database with the Prefect API. If not set, the default SQLAlchemy maximum overflow value will be used.
Whether to interpret strings wrapped in square brackets as a style.
This allows styles to be conveniently added to log messages, e.g.
[red]This is a red message.[/red]. However, the downside is,
if enabled, strings that contain square brackets may be inaccurately
interpreted and lead to incomplete output, e.g.
DROP TABLE [dbo].[SomeTable];" outputs DROP TABLE .[SomeTable];.
Threshold time in seconds for logging a warning if task parameter introspection
exceeds this duration. Parameter introspection can be a significant performance hit
when the parameter is a large collection object, e.g. a large dictionary or DataFrame,
and each element needs to be inspected. See prefect.utilities.annotations.quote
for more details.
Defaults to 10.0.
Set to 0 to disable logging the warning.
Agents will look for scheduled runs this many seconds in
the future and attempt to run them. This accounts for any additional
infrastructure spin-up time or latency in preparing a flow run. Note
flow runs will not start before their scheduled time, even if they are
prefetched. Defaults to 15.
Determines whether State.result() fetches results automatically or not.
In Prefect 2.6.0, the State.result() method was updated to be async
to facilitate automatic retrieval of results from storage which means when
writing async code you must await the call. For backwards compatibility,
the result is not retrieved by default for async users. You may opt into this
per call by passing fetch=True or toggle this setting to change the behavior
globally.
This setting does not affect users writing synchronous tasks and flows.
This setting does not affect retrieval of results when using Future.result().
If set, any block types that have been imported will be registered with the
backend on application startup. If not set, block types must be manually
registered.
Password to template into the PREFECT_API_DATABASE_CONNECTION_URL.
This is useful if the password must be provided separately from the connection URL.
To use this setting, you must include it in your connection URL.
A database connection URL in a SQLAlchemy-compatible
format. Prefect currently supports SQLite and Postgres. Note that all
Prefect database engines must use an async driver - for SQLite, use
sqlite+aiosqlite and for Postgres use postgresql+asyncpg.
SQLite in-memory databases can be used by providing the url
sqlite+aiosqlite:///file::memory:?cache=shared&uri=true&check_same_thread=false,
which will allow the database to be accessed by multiple threads. Note
that in-memory databases can not be accessed from multiple processes and
should only be used for simple tests.
Defaults to a sqlite database stored in the Prefect home directory.
If you need to provide password via a different environment variable, you use
the PREFECT_API_DATABASE_PASSWORD setting. For example:
The scheduler loop interval, in seconds. This determines
how often the scheduler will attempt to schedule new flow runs, but has no
impact on how quickly either flow runs or task runs are actually executed.
Defaults to 60.
The number of deployments the scheduler will attempt to
schedule in a single batch. If there are more deployments than the batch
size, the scheduler immediately attempts to schedule the next batch; it
does not sleep for scheduler_loop_seconds until it has visited every
deployment once. Defaults to 100.
The scheduler will attempt to schedule up to this many
auto-scheduled runs in the future. Note that runs may have fewer than
this many scheduled runs, depending on the value of
scheduler_max_scheduled_time. Defaults to 100.
The scheduler will attempt to schedule at least this many
auto-scheduled runs in the future. Note that runs may have more than
this many scheduled runs, depending on the value of
scheduler_min_scheduled_time. Defaults to 3.
The scheduler will create new runs up to this far in the
future. Note that this setting will take precedence over
scheduler_max_runs: if a flow runs once a month and
scheduler_max_scheduled_time is three months, then only three runs will be
scheduled. Defaults to 100 days (8640000 seconds).
The scheduler will create new runs at least this far in the
future. Note that this setting will take precedence over scheduler_min_runs:
if a flow runs every hour and scheduler_min_scheduled_time is three hours,
then three runs will be scheduled even if scheduler_min_runs is 1. Defaults to
1 hour (3600 seconds).
The number of flow runs the scheduler will attempt to insert
in one batch across all deployments. If the number of flow runs to
schedule exceeds this amount, the runs will be inserted in batches of this size.
Defaults to 500.
Controls the activation of CSRF protection for the Prefect server API.
When enabled (True), the server enforces CSRF validation checks on incoming
state-changing requests (POST, PUT, PATCH, DELETE), requiring a valid CSRF
token to be included in the request headers or body. This adds a layer of
security by preventing unauthorized or malicious sites from making requests on
behalf of authenticated users.
It is recommended to enable this setting in production environments where the
API is exposed to web clients to safeguard against CSRF attacks.
Note: Enabling this setting requires corresponding support in the client for
CSRF token management. See PREFECT_CLIENT_CSRF_SUPPORT_ENABLED for more.
Specifies the duration for which a CSRF token remains valid after being issued
by the server.
The default expiration time is set to 1 hour, which offers a reasonable
compromise. Adjust this setting based on your specific security requirements
and usage patterns.
The connection url for communication from the UI to the API.
Defaults to PREFECT_API_URL if set. Otherwise, the default URL is generated from
PREFECT_SERVER_API_HOST and PREFECT_SERVER_API_PORT. If providing a custom value,
the aforementioned settings may be templated into the given string.
Whether or not to start the scheduling service in the server application.
If disabled, you will need to run this service separately to schedule runs for deployments.
Whether or not to start the late runs service in the server application.
If disabled, you will need to run this service separately to have runs past their
scheduled start time marked as late.
Whether or not to start the flow run notifications service in the server application.
If disabled, you will need to run this service separately to send flow run notifications.
Whether or not to start the paused flow run expiration service in the server
application. If disabled, paused flows that have timed out will remain in a Paused state
until a resume attempt.
Whether or not to start the cancellation cleanup service in the server
application. If disabled, task runs and subflow runs belonging to cancelled flows may
remain in non-terminal states.
Whether to enable Prefect's server-side event features. Note that Prefect Cloud clients
will always emit events during flow and task runs regardless of this setting.
The number of seconds into the future a worker should query for scheduled flow runs.
Can be used to compensate for infrastructure start up time for a worker.
How long before a PENDING task are made available to another task server. In practice,
a task server should move a task from PENDING to RUNNING very quickly, so runs stuck in
PENDING for a while is a sign that the task server may have crashed.
The directory to serve static files from. This should be used when running into permissions issues
when attempting to serve the UI from the default directory (for example when running in a Docker container)
classSetting(Generic[T]):""" Setting definition type. """def__init__(self,type:Type[T],*,deprecated:bool=False,deprecated_start_date:Optional[str]=None,deprecated_end_date:Optional[str]=None,deprecated_help:str="",deprecated_when_message:str="",deprecated_when:Optional[Callable[[Any],bool]]=None,deprecated_renamed_to:Optional["Setting[T]"]=None,value_callback:Optional[Callable[["Settings",T],T]]=None,is_secret:bool=False,**kwargs:Any,)->None:self.field:fields.FieldInfo=Field(**kwargs)self.type=typeself.value_callback=value_callbackself._name=Noneself.is_secret=is_secretself.deprecated=deprecatedself.deprecated_start_date=deprecated_start_dateself.deprecated_end_date=deprecated_end_dateself.deprecated_help=deprecated_helpself.deprecated_when=deprecated_whenor(lambda_:True)self.deprecated_when_message=deprecated_when_messageself.deprecated_renamed_to=deprecated_renamed_toself.deprecated_renamed_from=Noneself.__doc__=self.field.description# Validate the deprecation settings, will throw an error at setting definition# time if the developer has not configured it correctlyifdeprecated:generate_deprecation_message(name="...",# setting names not populated until after initstart_date=self.deprecated_start_date,end_date=self.deprecated_end_date,help=self.deprecated_help,when=self.deprecated_when_message,)ifdeprecated_renamed_toisnotNone:# Track the deprecation both waysdeprecated_renamed_to.deprecated_renamed_from=selfdefvalue(self,bypass_callback:bool=False)->T:""" Get the current value of a setting. Example: ```python from prefect.settings import PREFECT_API_URL PREFECT_API_URL.value() ``` """returnself.value_from(get_current_settings(),bypass_callback=bypass_callback)defvalue_from(self,settings:"Settings",bypass_callback:bool=False)->T:""" Get the value of a setting from a settings object Example: ```python from prefect.settings import get_default_settings PREFECT_API_URL.value_from(get_default_settings()) ``` """value=settings.value_of(self,bypass_callback=bypass_callback)ifnotbypass_callbackandself.deprecatedandself.deprecated_when(value):# Check if this setting is deprecated and someone is accessing the value# via the old namewarnings.warn(self.deprecated_message,DeprecationWarning,stacklevel=3)# If the the value is empty, return the new setting's value for compatifvalueisNoneandself.deprecated_renamed_toisnotNone:returnself.deprecated_renamed_to.value_from(settings)ifnotbypass_callbackandself.deprecated_renamed_fromisnotNone:# Check if this setting is a rename of a deprecated setting and the# deprecated setting is set and should be used for compatibilitydeprecated_value=self.deprecated_renamed_from.value_from(settings,bypass_callback=True)ifdeprecated_valueisnotNone:warnings.warn((f"{self.deprecated_renamed_from.deprecated_message} Because"f" {self.deprecated_renamed_from.name!r} is set it will be used"f" instead of {self.name!r} for backwards compatibility."),DeprecationWarning,stacklevel=3,)returndeprecated_valueorvaluereturnvalue@propertydefname(self):ifself._name:returnself._name# Lookup the name on first accessforname,valintuple(globals().items()):ifval==self:self._name=namereturnnameraiseValueError("Setting not found in `prefect.settings` module.")@name.setterdefname(self,value:str):self._name=value@propertydefdeprecated_message(self):returngenerate_deprecation_message(name=f"Setting {self.name!r}",start_date=self.deprecated_start_date,end_date=self.deprecated_end_date,help=self.deprecated_help,when=self.deprecated_when_message,)def__repr__(self)->str:returnf"<{self.name}: {self.type.__name__}>"def__bool__(self)->bool:""" Returns a truthy check of the current value. """returnbool(self.value())def__eq__(self,__o:object)->bool:return__o.__eq__(self.value())def__hash__(self)->int:returnhash((type(self),self.name))
defvalue(self,bypass_callback:bool=False)->T:""" Get the current value of a setting. Example: ```python from prefect.settings import PREFECT_API_URL PREFECT_API_URL.value() ``` """returnself.value_from(get_current_settings(),bypass_callback=bypass_callback)
defvalue_from(self,settings:"Settings",bypass_callback:bool=False)->T:""" Get the value of a setting from a settings object Example: ```python from prefect.settings import get_default_settings PREFECT_API_URL.value_from(get_default_settings()) ``` """value=settings.value_of(self,bypass_callback=bypass_callback)ifnotbypass_callbackandself.deprecatedandself.deprecated_when(value):# Check if this setting is deprecated and someone is accessing the value# via the old namewarnings.warn(self.deprecated_message,DeprecationWarning,stacklevel=3)# If the the value is empty, return the new setting's value for compatifvalueisNoneandself.deprecated_renamed_toisnotNone:returnself.deprecated_renamed_to.value_from(settings)ifnotbypass_callbackandself.deprecated_renamed_fromisnotNone:# Check if this setting is a rename of a deprecated setting and the# deprecated setting is set and should be used for compatibilitydeprecated_value=self.deprecated_renamed_from.value_from(settings,bypass_callback=True)ifdeprecated_valueisnotNone:warnings.warn((f"{self.deprecated_renamed_from.deprecated_message} Because"f" {self.deprecated_renamed_from.name!r} is set it will be used"f" instead of {self.name!r} for backwards compatibility."),DeprecationWarning,stacklevel=3,)returndeprecated_valueorvaluereturnvalue
@add_cloudpickle_reductionclassSettings(SettingsFieldsMixin):""" Contains validated Prefect settings. Settings should be accessed using the relevant `Setting` object. For example: ```python from prefect.settings import PREFECT_HOME PREFECT_HOME.value() ``` Accessing a setting attribute directly will ignore any `value_callback` mutations. This is not recommended: ```python from prefect.settings import Settings Settings().PREFECT_PROFILES_PATH # PosixPath('${PREFECT_HOME}/profiles.toml') ``` """defvalue_of(self,setting:Setting[T],bypass_callback:bool=False)->T:""" Retrieve a setting's value. """value=getattr(self,setting.name)ifsetting.value_callbackandnotbypass_callback:value=setting.value_callback(self,value)returnvalue@validator(PREFECT_LOGGING_LEVEL.name,PREFECT_LOGGING_SERVER_LEVEL.name)defcheck_valid_log_level(cls,value):ifisinstance(value,str):value=value.upper()logging._checkLevel(value)returnvalue@root_validatordefpost_root_validators(cls,values):""" Add root validation functions for settings here. """# TODO: We could probably register these dynamically but this is the simpler# approach for now. We can explore more interesting validation features# in the future.values=max_log_size_smaller_than_batch_size(values)values=warn_on_database_password_value_without_usage(values)ifnotvalues["PREFECT_SILENCE_API_URL_MISCONFIGURATION"]:values=warn_on_misconfigured_api_url(values)returnvaluesdefcopy_with_update(self,updates:Mapping[Setting,Any]=None,set_defaults:Mapping[Setting,Any]=None,restore_defaults:Iterable[Setting]=None,)->"Settings":""" Create a new `Settings` object with validation. Arguments: updates: A mapping of settings to new values. Existing values for the given settings will be overridden. set_defaults: A mapping of settings to new default values. Existing values for the given settings will only be overridden if they were not set. restore_defaults: An iterable of settings to restore to their default values. Returns: A new `Settings` object. """updates=updatesor{}set_defaults=set_defaultsor{}restore_defaults=restore_defaultsorset()restore_defaults_names={setting.nameforsettinginrestore_defaults}returnself.__class__(**{**{setting.name:valueforsetting,valueinset_defaults.items()},**self.dict(exclude_unset=True,exclude=restore_defaults_names),**{setting.name:valueforsetting,valueinupdates.items()},})defwith_obfuscated_secrets(self):""" Returns a copy of this settings object with secret setting values obfuscated. """settings=self.copy(update={setting.name:obfuscate(self.value_of(setting))forsettinginSETTING_VARIABLES.values()ifsetting.is_secret# Exclude deprecated settings with null values to avoid warningsandnot(setting.deprecatedandself.value_of(setting)isNone)})# Ensure that settings that have not been marked as "set" before are still so# after we have updated their value abovesettings.__fields_set__.intersection_update(self.__fields_set__)returnsettingsdefhash_key(self)->str:""" Return a hash key for the settings object. This is needed since some settings may be unhashable. An example is lists. """env_variables=self.to_environment_variables()returnstr(hash(tuple((key,value)forkey,valueinenv_variables.items())))defto_environment_variables(self,include:Iterable[Setting]=None,exclude_unset:bool=False)->Dict[str,str]:""" Convert the settings object to environment variables. Note that setting values will not be run through their `value_callback` allowing dynamic resolution to occur when loaded from the returned environment. Args: include_keys: An iterable of settings to include in the return value. If not set, all settings are used. exclude_unset: Only include settings that have been set (i.e. the value is not from the default). If set, unset keys will be dropped even if they are set in `include_keys`. Returns: A dictionary of settings with values cast to strings """include=set(includeorSETTING_VARIABLES.values())ifexclude_unset:set_keys={# Collect all of the "set" keys and cast to `Setting` objectsSETTING_VARIABLES[key]forkeyinself.dict(exclude_unset=True)}include.intersection_update(set_keys)# Validate the types of items in `include` to prevent exclusion bugsforkeyininclude:ifnotisinstance(key,Setting):raiseTypeError("Invalid type {type(key).__name__!r} for key in `include`.")env={# Use `getattr` instead of `value_of` to avoid value callback resolutionkey:getattr(self,key)forkey,settinginSETTING_VARIABLES.items()ifsettingininclude}# Cast to strings and drop null valuesreturn{key:str(value)forkey,valueinenv.items()ifvalueisnotNone}classConfig:frozen=True
@root_validatordefpost_root_validators(cls,values):""" Add root validation functions for settings here. """# TODO: We could probably register these dynamically but this is the simpler# approach for now. We can explore more interesting validation features# in the future.values=max_log_size_smaller_than_batch_size(values)values=warn_on_database_password_value_without_usage(values)ifnotvalues["PREFECT_SILENCE_API_URL_MISCONFIGURATION"]:values=warn_on_misconfigured_api_url(values)returnvalues
defwith_obfuscated_secrets(self):""" Returns a copy of this settings object with secret setting values obfuscated. """settings=self.copy(update={setting.name:obfuscate(self.value_of(setting))forsettinginSETTING_VARIABLES.values()ifsetting.is_secret# Exclude deprecated settings with null values to avoid warningsandnot(setting.deprecatedandself.value_of(setting)isNone)})# Ensure that settings that have not been marked as "set" before are still so# after we have updated their value abovesettings.__fields_set__.intersection_update(self.__fields_set__)returnsettings
Return a hash key for the settings object. This is needed since some
settings may be unhashable. An example is lists.
Source code in src/prefect/settings.py
1892189318941895189618971898
defhash_key(self)->str:""" Return a hash key for the settings object. This is needed since some settings may be unhashable. An example is lists. """env_variables=self.to_environment_variables()returnstr(hash(tuple((key,value)forkey,valueinenv_variables.items())))
Convert the settings object to environment variables.
Note that setting values will not be run through their value_callback allowing
dynamic resolution to occur when loaded from the returned environment.
Parameters:
Name
Type
Description
Default
include_keys
An iterable of settings to include in the return value.
If not set, all settings are used.
required
exclude_unset
bool
Only include settings that have been set (i.e. the value is
not from the default). If set, unset keys will be dropped even if they
are set in include_keys.
False
Returns:
Type
Description
Dict[str, str]
A dictionary of settings with values cast to strings
defto_environment_variables(self,include:Iterable[Setting]=None,exclude_unset:bool=False)->Dict[str,str]:""" Convert the settings object to environment variables. Note that setting values will not be run through their `value_callback` allowing dynamic resolution to occur when loaded from the returned environment. Args: include_keys: An iterable of settings to include in the return value. If not set, all settings are used. exclude_unset: Only include settings that have been set (i.e. the value is not from the default). If set, unset keys will be dropped even if they are set in `include_keys`. Returns: A dictionary of settings with values cast to strings """include=set(includeorSETTING_VARIABLES.values())ifexclude_unset:set_keys={# Collect all of the "set" keys and cast to `Setting` objectsSETTING_VARIABLES[key]forkeyinself.dict(exclude_unset=True)}include.intersection_update(set_keys)# Validate the types of items in `include` to prevent exclusion bugsforkeyininclude:ifnotisinstance(key,Setting):raiseTypeError("Invalid type {type(key).__name__!r} for key in `include`.")env={# Use `getattr` instead of `value_of` to avoid value callback resolutionkey:getattr(self,key)forkey,settinginSETTING_VARIABLES.items()ifsettingininclude}# Cast to strings and drop null valuesreturn{key:str(value)forkey,valueinenv.items()ifvalueisnotNone}
classProfile(BaseModel):""" A user profile containing settings. """name:strsettings:Dict[Setting,Any]=Field(default_factory=dict)source:Optional[Path]@validator("settings",pre=True)defmap_names_to_settings(cls,value):returnvalidate_settings(value)defvalidate_settings(self)->None:""" Validate the settings contained in this profile. Raises: pydantic.ValidationError: When settings do not have valid values. """# Create a new `Settings` instance with the settings from this profile relying# on Pydantic validation to raise an error.# We do not return the `Settings` object because this is not the recommended# path for constructing settings with a profile. See `use_profile` instead.Settings(**{setting.name:valueforsetting,valueinself.settings.items()})defconvert_deprecated_renamed_settings(self)->List[Tuple[Setting,Setting]]:""" Update settings in place to replace deprecated settings with new settings when renamed. Returns a list of tuples with the old and new setting. """changed=[]forsettingintuple(self.settings):if(setting.deprecatedandsetting.deprecated_renamed_toandsetting.deprecated_renamed_tonotinself.settings):self.settings[setting.deprecated_renamed_to]=self.settings.pop(setting)changed.append((setting,setting.deprecated_renamed_to))returnchangedclassConfig:arbitrary_types_allowed=True
defvalidate_settings(self)->None:""" Validate the settings contained in this profile. Raises: pydantic.ValidationError: When settings do not have valid values. """# Create a new `Settings` instance with the settings from this profile relying# on Pydantic validation to raise an error.# We do not return the `Settings` object because this is not the recommended# path for constructing settings with a profile. See `use_profile` instead.Settings(**{setting.name:valueforsetting,valueinself.settings.items()})
defconvert_deprecated_renamed_settings(self)->List[Tuple[Setting,Setting]]:""" Update settings in place to replace deprecated settings with new settings when renamed. Returns a list of tuples with the old and new setting. """changed=[]forsettingintuple(self.settings):if(setting.deprecatedandsetting.deprecated_renamed_toandsetting.deprecated_renamed_tonotinself.settings):self.settings[setting.deprecated_renamed_to]=self.settings.pop(setting)changed.append((setting,setting.deprecated_renamed_to))returnchanged
classProfilesCollection:""" " A utility class for working with a collection of profiles. Profiles in the collection must have unique names. The collection may store the name of the active profile. """def__init__(self,profiles:Iterable[Profile],active:Optional[str]=None)->None:self.profiles_by_name={profile.name:profileforprofileinprofiles}self.active_name=active@propertydefnames(self)->Set[str]:""" Return a set of profile names in this collection. """returnset(self.profiles_by_name.keys())@propertydefactive_profile(self)->Optional[Profile]:""" Retrieve the active profile in this collection. """ifself.active_nameisNone:returnNonereturnself[self.active_name]defset_active(self,name:Optional[str],check:bool=True):""" Set the active profile name in the collection. A null value may be passed to indicate that this collection does not determine the active profile. """ifcheckandnameisnotNoneandnamenotinself.names:raiseValueError(f"Unknown profile name {name!r}.")self.active_name=namedefupdate_profile(self,name:str,settings:Mapping[Union[Dict,str],Any],source:Path=None)->Profile:""" Add a profile to the collection or update the existing on if the name is already present in this collection. If updating an existing profile, the settings will be merged. Settings can be dropped from the existing profile by setting them to `None` in the new profile. Returns the new profile object. """existing=self.profiles_by_name.get(name)# Convert the input to a `Profile` to cast settings to the correct typeprofile=Profile(name=name,settings=settings,source=source)ifexisting:new_settings={**existing.settings,**profile.settings}# Drop null keys to restore to defaultforkey,valueintuple(new_settings.items()):ifvalueisNone:new_settings.pop(key)new_profile=Profile(name=profile.name,settings=new_settings,source=sourceorprofile.source,)else:new_profile=profileself.profiles_by_name[new_profile.name]=new_profilereturnnew_profiledefadd_profile(self,profile:Profile)->None:""" Add a profile to the collection. If the profile name already exists, an exception will be raised. """ifprofile.nameinself.profiles_by_name:raiseValueError(f"Profile name {profile.name!r} already exists in collection.")self.profiles_by_name[profile.name]=profiledefremove_profile(self,name:str)->None:""" Remove a profile from the collection. """self.profiles_by_name.pop(name)defwithout_profile_source(self,path:Optional[Path])->"ProfilesCollection":""" Remove profiles that were loaded from a given path. Returns a new collection. """returnProfilesCollection([profileforprofileinself.profiles_by_name.values()ifprofile.source!=path],active=self.active_name,)defto_dict(self):""" Convert to a dictionary suitable for writing to disk. """return{"active":self.active_name,"profiles":{profile.name:{setting.name:valueforsetting,valueinprofile.settings.items()}forprofileinself.profiles_by_name.values()},}def__getitem__(self,name:str)->Profile:returnself.profiles_by_name[name]def__iter__(self):returnself.profiles_by_name.__iter__()defitems(self):returnself.profiles_by_name.items()def__eq__(self,__o:object)->bool:ifnotisinstance(__o,ProfilesCollection):returnFalsereturn(self.profiles_by_name==__o.profiles_by_nameandself.active_name==__o.active_name)def__repr__(self)->str:return(f"ProfilesCollection(profiles={list(self.profiles_by_name.values())!r},"f" active={self.active_name!r})>")
A null value may be passed to indicate that this collection does not determine
the active profile.
Source code in src/prefect/settings.py
2133213421352136213721382139214021412142
defset_active(self,name:Optional[str],check:bool=True):""" Set the active profile name in the collection. A null value may be passed to indicate that this collection does not determine the active profile. """ifcheckandnameisnotNoneandnamenotinself.names:raiseValueError(f"Unknown profile name {name!r}.")self.active_name=name
Add a profile to the collection or update the existing on if the name is already
present in this collection.
If updating an existing profile, the settings will be merged. Settings can
be dropped from the existing profile by setting them to None in the new
profile.
defupdate_profile(self,name:str,settings:Mapping[Union[Dict,str],Any],source:Path=None)->Profile:""" Add a profile to the collection or update the existing on if the name is already present in this collection. If updating an existing profile, the settings will be merged. Settings can be dropped from the existing profile by setting them to `None` in the new profile. Returns the new profile object. """existing=self.profiles_by_name.get(name)# Convert the input to a `Profile` to cast settings to the correct typeprofile=Profile(name=name,settings=settings,source=source)ifexisting:new_settings={**existing.settings,**profile.settings}# Drop null keys to restore to defaultforkey,valueintuple(new_settings.items()):ifvalueisNone:new_settings.pop(key)new_profile=Profile(name=profile.name,settings=new_settings,source=sourceorprofile.source,)else:new_profile=profileself.profiles_by_name[new_profile.name]=new_profilereturnnew_profile
If the profile name already exists, an exception will be raised.
Source code in src/prefect/settings.py
218221832184218521862187218821892190219121922193
defadd_profile(self,profile:Profile)->None:""" Add a profile to the collection. If the profile name already exists, an exception will be raised. """ifprofile.nameinself.profiles_by_name:raiseValueError(f"Profile name {profile.name!r} already exists in collection.")self.profiles_by_name[profile.name]=profile
defwithout_profile_source(self,path:Optional[Path])->"ProfilesCollection":""" Remove profiles that were loaded from a given path. Returns a new collection. """returnProfilesCollection([profileforprofileinself.profiles_by_name.values()ifprofile.source!=path],active=self.active_name,)
value_callback for PREFECT_LOGGING_EXTRA_LOGGERSthat parses the CSV string into a
list and trims whitespace from logger names.
Source code in src/prefect/settings.py
266267268269270271
defget_extra_loggers(_:"Settings",value:str)->List[str]:""" `value_callback` for `PREFECT_LOGGING_EXTRA_LOGGERS`that parses the CSV string into a list and trims whitespace from logger names. """return[name.strip()fornameinvalue.split(",")]ifvalueelse[]
value_callback for PREFECT_LOGGING_LEVEL that overrides the log level to DEBUG
when debug mode is enabled.
Source code in src/prefect/settings.py
278279280281282283284285286
defdebug_mode_log_level(settings,value):""" `value_callback` for `PREFECT_LOGGING_LEVEL` that overrides the log level to DEBUG when debug mode is enabled. """ifPREFECT_DEBUG_MODE.value_from(settings):return"DEBUG"else:returnvalue
value_callback for PREFECT_TEST_SETTING that only allows access during test mode
Source code in src/prefect/settings.py
289290291292293294295296
defonly_return_value_in_test_mode(settings,value):""" `value_callback` for `PREFECT_TEST_SETTING` that only allows access during test mode """ifPREFECT_TEST_MODE.value_from(settings):returnvalueelse:returnNone
value_callback for PREFECT_UI_API_URL that sets the default value to
relative path '/api', otherwise it constructs an API URL from the API settings.
Source code in src/prefect/settings.py
299300301302303304305306307308309310
defdefault_ui_api_url(settings,value):""" `value_callback` for `PREFECT_UI_API_URL` that sets the default value to relative path '/api', otherwise it constructs an API URL from the API settings. """ifvalueisNone:# Set a default valuevalue="/api"returntemplate_with_settings(PREFECT_SERVER_API_HOST,PREFECT_SERVER_API_PORT,PREFECT_API_URL)(settings,value)
defstatus_codes_as_integers_in_range(_,value):""" `value_callback` for `PREFECT_CLIENT_RETRY_EXTRA_CODES` that ensures status codes are integers in the range 100-599. """ifvalue=="":returnset()values={v.strip()forvinvalue.split(",")}ifany(notv.isdigit()orint(v)<100orint(v)>599forvinvalues):raiseValueError("PREFECT_CLIENT_RETRY_EXTRA_CODES must be a comma separated list of ""integers between 100 and 599.")values={int(v)forvinvalues}returnvalues
deftemplate_with_settings(*upstream_settings:Setting)->Callable[["Settings",T],T]:""" Returns a `value_callback` that will template the given settings into the runtime value for the setting. """deftemplater(settings,value):ifvalueisNone:returnvalue# Do not attempt to template a null stringoriginal_type=type(value)template_values={setting.name:setting.value_from(settings)forsettinginupstream_settings}template=string.Template(str(value))returnoriginal_type(template.substitute(template_values))returntemplater
Validator for settings asserting the batch size and match log size are compatible
Source code in src/prefect/settings.py
353354355356357358359360361362363364365
defmax_log_size_smaller_than_batch_size(values):""" Validator for settings asserting the batch size and match log size are compatible """if(values["PREFECT_LOGGING_TO_API_BATCH_SIZE"]<values["PREFECT_LOGGING_TO_API_MAX_LOG_SIZE"]):raiseValueError("`PREFECT_LOGGING_TO_API_MAX_LOG_SIZE` cannot be larger than"" `PREFECT_LOGGING_TO_API_BATCH_SIZE`")returnvalues
defwarn_on_database_password_value_without_usage(values):""" Validator for settings warning if the database password is set but not used. """value=values["PREFECT_API_DATABASE_PASSWORD"]if(valueandnotvalue.startswith(OBFUSCATED_PREFIX)and("PREFECT_API_DATABASE_PASSWORD"notinvalues["PREFECT_API_DATABASE_CONNECTION_URL"])):warnings.warn("PREFECT_API_DATABASE_PASSWORD is set but not included in the ""PREFECT_API_DATABASE_CONNECTION_URL. ""The provided password will be ignored.")returnvalues
defwarn_on_misconfigured_api_url(values):""" Validator for settings warning if the API URL is misconfigured. """api_url=values["PREFECT_API_URL"]ifapi_urlisnotNone:misconfigured_mappings={"app.prefect.cloud":("`PREFECT_API_URL` points to `app.prefect.cloud`. Did you"" mean `api.prefect.cloud`?"),"account/":("`PREFECT_API_URL` uses `/account/` but should use `/accounts/`."),"workspace/":("`PREFECT_API_URL` uses `/workspace/` but should use `/workspaces/`."),}warnings_list=[]formisconfig,warninginmisconfigured_mappings.items():ifmisconfiginapi_url:warnings_list.append(warning)parsed_url=urlparse(api_url)ifparsed_url.pathandnotparsed_url.path.startswith("/api"):warnings_list.append("`PREFECT_API_URL` should have `/api` after the base URL.")ifwarnings_list:example='e.g. PREFECT_API_URL="https://api.prefect.cloud/api/accounts/[ACCOUNT-ID]/workspaces/[WORKSPACE-ID]"'warnings_list.append(example)warnings.warn("\n".join(warnings_list),stacklevel=2)returnvalues
Returns a settings object populated with values from the current settings context
or, if no settings context is active, the environment.
Source code in src/prefect/settings.py
195619571958195919601961196219631964196519661967
defget_current_settings()->Settings:""" Returns a settings object populated with values from the current settings context or, if no settings context is active, the environment. """fromprefect.contextimportSettingsContextsettings_context=SettingsContext.get()ifsettings_contextisnotNone:returnsettings_context.settingsreturnget_settings_from_env()
defget_settings_from_env()->Settings:""" Returns a settings object populated with default values and overrides from environment variables, ignoring any values in profiles. Calls with the same environment return a cached object instead of reconstructing to avoid validation overhead. """# Since os.environ is a Dict[str, str] we can safely hash it by contents, but we# must be careful to avoid hashing a generator instead of a tuplecache_key=hash(tuple((key,value)forkey,valueinos.environ.items()))ifcache_keynotin_FROM_ENV_CACHE:_FROM_ENV_CACHE[cache_key]=Settings()return_FROM_ENV_CACHE[cache_key]
defget_default_settings()->Settings:""" Returns a settings object populated with default values, ignoring any overrides from environment variables or profiles. This is cached since the defaults should not change during the lifetime of the module. """global_DEFAULTS_CACHEifnot_DEFAULTS_CACHE:old=os.environtry:os.environ={}settings=get_settings_from_env()finally:os.environ=old_DEFAULTS_CACHE=settingsreturn_DEFAULTS_CACHE
@contextmanagerdeftemporary_settings(updates:Optional[Mapping[Setting[T],Any]]=None,set_defaults:Optional[Mapping[Setting[T],Any]]=None,restore_defaults:Optional[Iterable[Setting[T]]]=None,)->Generator[Settings,None,None]:""" Temporarily override the current settings by entering a new profile. See `Settings.copy_with_update` for details on different argument behavior. Examples: >>> from prefect.settings import PREFECT_API_URL >>> >>> with temporary_settings(updates={PREFECT_API_URL: "foo"}): >>> assert PREFECT_API_URL.value() == "foo" >>> >>> with temporary_settings(set_defaults={PREFECT_API_URL: "bar"}): >>> assert PREFECT_API_URL.value() == "foo" >>> >>> with temporary_settings(restore_defaults={PREFECT_API_URL}): >>> assert PREFECT_API_URL.value() is None >>> >>> with temporary_settings(set_defaults={PREFECT_API_URL: "bar"}) >>> assert PREFECT_API_URL.value() == "bar" >>> assert PREFECT_API_URL.value() is None """importprefect.contextcontext=prefect.context.get_settings_context()new_settings=context.settings.copy_with_update(updates=updates,set_defaults=set_defaults,restore_defaults=restore_defaults)withprefect.context.SettingsContext(profile=context.profile,settings=new_settings):yieldnew_settings
defload_profiles()->ProfilesCollection:""" Load all profiles from the default and current profile paths. """profiles=_read_profiles_from(DEFAULT_PROFILES_PATH)user_profiles_path=PREFECT_PROFILES_PATH.value()ifuser_profiles_path.exists():user_profiles=_read_profiles_from(user_profiles_path)# Merge all of the user profiles with the defaultsfornameinuser_profiles:profiles.update_profile(name,settings=user_profiles[name].settings,source=user_profiles[name].source,)ifuser_profiles.active_name:profiles.set_active(user_profiles.active_name,check=False)returnprofiles
defload_current_profile():""" Load the current profile from the default and current profile paths. This will _not_ include settings from the current settings context. Only settings that have been persisted to the profiles file will be saved. """fromprefect.contextimportSettingsContextprofiles=load_profiles()context=SettingsContext.get()ifcontext:profiles.set_active(context.profile.name)returnprofiles.active_profile
Writes all non-default profiles to the current profiles path.
Source code in src/prefect/settings.py
2352235323542355235623572358
defsave_profiles(profiles:ProfilesCollection)->None:""" Writes all non-default profiles to the current profiles path. """profiles_path=PREFECT_PROFILES_PATH.value()profiles=profiles.without_profile_source(DEFAULT_PROFILES_PATH)return_write_profiles_to(profiles_path,profiles)
defload_profile(name:str)->Profile:""" Load a single profile by name. """profiles=load_profiles()try:returnprofiles[name]exceptKeyError:raiseValueError(f"Profile {name!r} not found.")
defupdate_current_profile(settings:Dict[Union[str,Setting],Any])->Profile:""" Update the persisted data for the profile currently in-use. If the profile does not exist in the profiles file, it will be created. Given settings will be merged with the existing settings as described in `ProfilesCollection.update_profile`. Returns: The new profile. """importprefect.contextcurrent_profile=prefect.context.get_settings_context().profileifnotcurrent_profile:raiseMissingProfileError("No profile is currently in use.")profiles=load_profiles()# Ensure the current profile's settings are presentprofiles.update_profile(current_profile.name,current_profile.settings)# Then merge the new settings innew_profile=profiles.update_profile(current_profile.name,settings)# Validate before savingnew_profile.validate_settings()save_profiles(profiles)returnprofiles[current_profile.name]