This is an automated email from the ASF dual-hosted git repository.
weilee pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-1-test by this push:
new 7a1cb569750 [v3-1-test] Fix Asset URI normalization for user info
without password (#51877) (#57650) (#58485)
7a1cb569750 is described below
commit 7a1cb5697508ba5eded33f51cf1797b1742a6ae8
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Nov 19 21:42:06 2025 +0800
[v3-1-test] Fix Asset URI normalization for user info without password
(#51877) (#57650) (#58485)
Co-authored-by: jgoedeke <[email protected]>
Co-authored-by: Tzu-ping Chung <[email protected]>
---
task-sdk/src/airflow/sdk/definitions/asset/__init__.py | 9 +++++----
task-sdk/tests/task_sdk/definitions/test_asset.py | 15 ++++++++++-----
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/task-sdk/src/airflow/sdk/definitions/asset/__init__.py
b/task-sdk/src/airflow/sdk/definitions/asset/__init__.py
index 98a9e270c62..970e0385fd8 100644
--- a/task-sdk/src/airflow/sdk/definitions/asset/__init__.py
+++ b/task-sdk/src/airflow/sdk/definitions/asset/__init__.py
@@ -166,15 +166,16 @@ def _sanitize_uri(inp: str | ObjectStoragePath) -> str:
return uri
if normalized_scheme == "airflow":
raise ValueError("Asset scheme 'airflow' is reserved")
- _, auth_exists, normalized_netloc = parsed.netloc.rpartition("@")
- if auth_exists:
+ if parsed.password:
# TODO: Collect this into a DagWarning.
warnings.warn(
- "An Asset URI should not contain auth info (e.g. username or "
- "password). It has been automatically dropped.",
+ "An Asset URI should not contain a password. User info has been
automatically dropped.",
UserWarning,
stacklevel=3,
)
+ _, _, normalized_netloc = parsed.netloc.rpartition("@")
+ else:
+ normalized_netloc = parsed.netloc
if parsed.query:
normalized_query =
urllib.parse.urlencode(sorted(urllib.parse.parse_qsl(parsed.query)))
else:
diff --git a/task-sdk/tests/task_sdk/definitions/test_asset.py
b/task-sdk/tests/task_sdk/definitions/test_asset.py
index fd9b6d24bcc..603b4f44cb7 100644
--- a/task-sdk/tests/task_sdk/definitions/test_asset.py
+++ b/task-sdk/tests/task_sdk/definitions/test_asset.py
@@ -144,19 +144,24 @@ def test_uri_with_scheme(uri: str, normalized: str) ->
None:
assert os.fspath(asset) == normalized
-def test_uri_with_auth() -> None:
- with pytest.warns(UserWarning, match="username") as record:
- asset = Asset("ftp://user@localhost/foo.txt")
+def test_uri_with_password() -> None:
+ with pytest.warns(UserWarning, match="password") as record:
+ asset = Asset("ftp://user:password@localhost/foo.txt")
assert len(record) == 1
assert str(record[0].message) == (
- "An Asset URI should not contain auth info (e.g. username or "
- "password). It has been automatically dropped."
+ "An Asset URI should not contain a password. User info has been
automatically dropped."
)
EmptyOperator(task_id="task1", outlets=[asset])
assert asset.uri == "ftp://localhost/foo.txt"
assert os.fspath(asset) == "ftp://localhost/foo.txt"
+def test_uri_without_password() -> None:
+ uri = "abfss://[email protected]/path"
+ asset = Asset(uri)
+ assert asset.uri == uri
+
+
def test_uri_without_scheme():
asset = Asset(uri="example_asset")
EmptyOperator(task_id="task1", outlets=[asset])