Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
4ba0185
Bootstrapping shared library for configuration
amoghrajesh Oct 31, 2025
9e8d1a4
Porting over AirflowConfigParser to shared
amoghrajesh Oct 31, 2025
7e031dc
Inheriting shared config parser in core and implementing
amoghrajesh Oct 31, 2025
08e62c3
Inheriting shared config parser in sdk and implementing
amoghrajesh Oct 31, 2025
0c309b6
Updating usages in sdk
amoghrajesh Oct 31, 2025
458bac7
adding a layer of compat for AirflowConfigException
amoghrajesh Nov 3, 2025
f03c1ad
tests for shared parser
amoghrajesh Nov 3, 2025
7a7dfeb
fixing unhappy static checks
amoghrajesh Nov 3, 2025
87d3177
some more cleanup
amoghrajesh Nov 3, 2025
6a30185
handling the structure of shared conf
amoghrajesh Nov 4, 2025
4795abc
fixing static checks
amoghrajesh Nov 4, 2025
4e40f67
moving some more utils to shared
amoghrajesh Nov 12, 2025
04c49ba
moving some more utils to shared
amoghrajesh Nov 12, 2025
93a7832
adding comment on what to remove
amoghrajesh Nov 12, 2025
b53d574
moving write_section_header and write_value
amoghrajesh Nov 12, 2025
d6defec
moving over _get_config_value_from_secret_backend to shared
amoghrajesh Nov 12, 2025
57db7ab
moved _get_cmd_option_from_config_sources, _get_cmd_option_from_confi…
amoghrajesh Nov 12, 2025
8c76d05
moved include-x methods
amoghrajesh Nov 12, 2025
605c2fc
moveed _filter_by_source
amoghrajesh Nov 12, 2025
5b5cd59
moved _replace_config_with_display_sources and _replace_section_confi…
amoghrajesh Nov 12, 2025
145d449
moving getsection and is_template
amoghrajesh Nov 13, 2025
5de7a85
Merge branch 'main' into moving-conf-to-shared
amoghrajesh Nov 14, 2025
d90f647
moving lookup sequence to shared parser
amoghrajesh Nov 14, 2025
509bb08
moved as_dict to shared
amoghrajesh Nov 14, 2025
76c0c21
removed version handling and moved write_option header to shared
amoghrajesh Nov 14, 2025
fbe615f
adjustments to make it proper
amoghrajesh Nov 14, 2025
1ea665c
moving deprecated lookup too
amoghrajesh Nov 14, 2025
00a660d
overriding _get_config_sources_for_as_dict in core
amoghrajesh Nov 14, 2025
3aed41b
moved more things to shared
amoghrajesh Nov 14, 2025
feb3729
moved more things to shared
amoghrajesh Nov 14, 2025
25de605
removing duplicates
amoghrajesh Nov 14, 2025
4ca3be9
Merge branch 'main' into moving-conf-to-shared and adjust for shared lib
amoghrajesh Nov 17, 2025
aa65ceb
moving write to shared parser
amoghrajesh Nov 17, 2025
205c67e
remove unwanted override
amoghrajesh Nov 17, 2025
ed8c237
syncing main
amoghrajesh Nov 17, 2025
6c27519
fixing tests in conf
amoghrajesh Nov 17, 2025
8ef2ddf
fixing static checks
amoghrajesh Nov 18, 2025
6327432
adding methodtools
amoghrajesh Nov 18, 2025
3e0adee
fixing static checks
amoghrajesh Nov 18, 2025
499117d
fixing tests
amoghrajesh Nov 18, 2025
b9024e9
fixing task sdk tests wrt conf
amoghrajesh Nov 18, 2025
fdfd0c3
fixing task sdk tests wrt conf
amoghrajesh Nov 18, 2025
122fb0f
removing overriding configuration_description and _default_values in …
amoghrajesh Nov 18, 2025
4d5b66d
review comments from ash: part 1
amoghrajesh Nov 18, 2025
fcd47c9
handling AirflowConfigException better
amoghrajesh Nov 18, 2025
4a0e960
undo task_sdk_conf_vars and use sys modules instead
amoghrajesh Nov 18, 2025
0166f60
make conf in sdk a lazy attribute
amoghrajesh Nov 18, 2025
c582d36
conf_vars instead of patch
amoghrajesh Nov 18, 2025
9c138f0
fixing provider tests
amoghrajesh Nov 19, 2025
d330ba4
fixing core tests now
amoghrajesh Nov 19, 2025
176c96d
trying to fix the CI where provider wheel tests fail
amoghrajesh Nov 19, 2025
28b7467
override _get_config_value_from_secret_backend to use module level cu…
amoghrajesh Nov 19, 2025
bb49319
fixing core and provider tests
amoghrajesh Nov 19, 2025
fad23e7
ash comments
amoghrajesh Nov 19, 2025
7558623
fixing beam compat
amoghrajesh Nov 19, 2025
c85558b
fixing beam compat
amoghrajesh Nov 19, 2025
6109713
fixing beam compat
amoghrajesh Nov 19, 2025
81c7c21
Merge branch 'main' into moving-conf-to-shared
amoghrajesh Nov 19, 2025
90b56ee
use core conf for remote logging
amoghrajesh Nov 20, 2025
260974e
using core conf for RL
amoghrajesh Nov 20, 2025
1de6e1c
fixing remote logging
amoghrajesh Nov 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions airflow-core/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ dependencies = [
"pygtrie>=2.5.0",
"structlog>=25.4.0",
# End of shared logging dependencies
# Start of shared configuration dependencies
"pyyaml>=6.0.2",
# End of shared configuration dependencies
]


Expand Down Expand Up @@ -218,6 +221,7 @@ exclude = [
]

[tool.hatch.build.targets.sdist.force-include]
"../shared/configuration/src/airflow_shared/configuration" = "src/airflow/_shared/configuration"
"../shared/logging/src/airflow_shared/logging" = "src/airflow/_shared/logging"
"../shared/secrets_masker/src/airflow_shared/secrets_masker" = "src/airflow/_shared/secrets_masker"
"../shared/timezones/src/airflow_shared/timezones" = "src/airflow/_shared/timezones"
Expand Down Expand Up @@ -288,6 +292,7 @@ apache-airflow-devel-common = { workspace = true }

[tool.airflow]
shared_distributions = [
"apache-airflow-shared-configuration",
"apache-airflow-shared-logging",
"apache-airflow-shared-secrets-masker",
"apache-airflow-shared-timezones",
Expand Down
1 change: 1 addition & 0 deletions airflow-core/src/airflow/_shared/configuration
1,680 changes: 87 additions & 1,593 deletions airflow-core/src/airflow/configuration.py

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions airflow-core/src/airflow/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
from airflow.sdk.definitions.asset import AssetNameRef, AssetUniqueKey, AssetUriRef
from airflow.utils.state import DagRunState

# Re exporting AirflowConfigException from shared configuration
from airflow._shared.configuration.exceptions import AirflowConfigException as AirflowConfigException


class AirflowException(Exception):
"""
Expand Down Expand Up @@ -58,10 +61,6 @@ class AirflowNotFoundException(AirflowException):
status_code = HTTPStatus.NOT_FOUND


class AirflowConfigException(AirflowException):
"""Raise when there is configuration problem."""


class AirflowSensorTimeout(AirflowException):
"""Raise when there is a timeout on sensor polling."""

Expand Down
1 change: 1 addition & 0 deletions airflow-core/tests/unit/core/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ def test_config_raise_exception_from_secret_backend_connection_error(self, mock_
sql_alchemy_conn = airflow
"""
test_conf = AirflowConfigParser(default_config=parameterized_config(test_config_default))
# Configure secrets backend on test_conf itself
test_conf.read_string(test_config)
test_conf.sensitive_config_values = test_conf.sensitive_config_values | {
("test", "sql_alchemy_conn"),
Expand Down
3 changes: 3 additions & 0 deletions airflow-core/tests/unit/models/test_xcom.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ def test_resolve_xcom_class_fallback_to_basexcom(self):

@conf_vars({("core", "xcom_backend"): "to be removed"})
def test_resolve_xcom_class_fallback_to_basexcom_no_config(self):
from airflow.sdk.configuration import conf as sdk_conf

conf.remove_option("core", "xcom_backend")
sdk_conf.remove_option("core", "xcom_backend")
cls = resolve_xcom_backend()
assert issubclass(cls, BaseXCom)
assert cls.serialize_value([1]) == [1]
Expand Down
59 changes: 37 additions & 22 deletions devel-common/src/tests_common/test_utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,42 +23,57 @@

@contextlib.contextmanager
def conf_vars(overrides):
"""Automatically detects which config modules are loaded (Core, SDK, or both) and updates them accordingly temporarily."""
import sys

from airflow import settings
from airflow.configuration import conf

original = {}
configs = []
if "airflow.configuration" in sys.modules:
from airflow.configuration import conf

configs.append(conf)
if "airflow.sdk.configuration" in sys.modules:
from airflow.sdk.configuration import conf

configs.append(conf)

originals = [{} for _ in configs]
original_env_vars = {}
for (section, key), value in overrides.items():
env = conf._env_var_name(section, key)
env = configs[0]._env_var_name(section, key)
if env in os.environ:
original_env_vars[env] = os.environ.pop(env)

if conf.has_option(section, key):
original[(section, key)] = conf.get(section, key)
else:
original[(section, key)] = None
if value is not None:
if not conf.has_section(section):
conf.add_section(section)
conf.set(section, key, value)
else:
if conf.has_section(section):
conf.remove_option(section, key)
settings.configure_vars()
try:
yield
finally:
for (section, key), value in original.items():
for i, conf in enumerate(configs):
originals[i][(section, key)] = conf.get(section, key) if conf.has_option(section, key) else None
if value is not None:
if not conf.has_section(section):
conf.add_section(section)
conf.set(section, key, value)
else:
if conf.has_section(section):
elif conf.has_section(section) and conf.has_option(section, key):
conf.remove_option(section, key)

if "airflow.configuration" in sys.modules:
settings.configure_vars()

try:
yield
finally:
for i, conf in enumerate(configs):
for (section, key), value in originals[i].items():
if value is not None:
if not conf.has_section(section):
conf.add_section(section)
conf.set(section, key, value)
elif conf.has_section(section) and conf.has_option(section, key):
conf.remove_option(section, key)

for env, value in original_env_vars.items():
os.environ[env] = value
settings.configure_vars()

if "airflow.configuration" in sys.modules:
settings.configure_vars()


@contextlib.contextmanager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@
except ImportError:
APACHE_BEAM_VERSION = None

try:
from airflow._shared.configuration import AirflowConfigException as ConfigException
except ImportError:
# Compat for airflow < 3.2, where AirflowConfigException is in airflow.exceptions
ConfigException = AirflowException # type: ignore[assignment,misc]


class TestBeamHook:
@mock.patch(BEAM_STRING.format("run_beam_command"))
Expand Down Expand Up @@ -347,7 +353,7 @@ def test_start_go_pipeline_without_go_installed_raises(self, mock_which):
r"You need to have Go installed to run beam go pipeline\. See .* "
"installation guide. If you are running airflow in Docker see more info at '.*'"
)
with pytest.raises(AirflowException, match=error_message):
with pytest.raises(ConfigException, match=error_message):
hook.start_go_pipeline(
go_file=GO_FILE,
variables=copy.deepcopy(BEAM_VARIABLES_GO),
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,7 @@ dev = [
"apache-airflow-task-sdk[all]",
"apache-airflow-ctl",
"apache-airflow-ctl-tests",
"apache-airflow-shared-configuration",
"apache-airflow-shared-logging",
"apache-airflow-shared-secrets-masker",
"apache-airflow-shared-timezones",
Expand Down Expand Up @@ -1343,6 +1344,7 @@ apache-airflow-helm-tests = { workspace = true }
apache-airflow-kubernetes-tests = { workspace = true }
apache-airflow-providers = { workspace = true }
apache-aurflow-docker-stack = { workspace = true }
apache-airflow-shared-configuration = { workspace = true }
apache-airflow-shared-logging = { workspace = true }
apache-airflow-shared-secrets-masker = { workspace = true }
apache-airflow-shared-timezones = { workspace = true }
Expand Down Expand Up @@ -1463,6 +1465,7 @@ members = [
"task-sdk",
"providers-summary-docs",
"docker-stack-docs",
"shared/configuration",
"shared/logging",
"shared/secrets_masker",
"shared/timezones",
Expand Down
55 changes: 55 additions & 0 deletions shared/configuration/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

[project]
name = "apache-airflow-shared-configuration"
description = "Shared configuration parser code for Airflow distributions"
version = "0.0"
classifiers = [
"Private :: Do Not Upload",
]

dependencies = [
"packaging>=25.0",
"typing-extensions>=4.14.1",
"pendulum>=3.1.0",
"methodtools>=0.4.7",
]

[dependency-groups]
dev = [
"apache-airflow-devel-common",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/airflow_shared"]

[tool.ruff]
extend = "../../pyproject.toml"
src = ["src"]

[tool.ruff.lint.per-file-ignores]
# Ignore Doc rules et al for anything outside of tests
"!src/*" = ["D", "S101", "TRY002"]

[tool.ruff.lint.flake8-tidy-imports]
# Override the workspace level default
ban-relative-imports = "parents"
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""Shared configuration parser for Airflow distributions."""

from __future__ import annotations

__all__ = [
"AirflowConfigException",
"AirflowConfigParser",
]

from .exceptions import AirflowConfigException
from .parser import AirflowConfigParser
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""Exceptions for configuration parsing."""

from __future__ import annotations


class AirflowConfigException(Exception):
"""Raise when there is a configuration problem."""
Loading
Loading