You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hamilton.apache.org by sk...@apache.org on 2026/09/24 05:23:22 UTC
(hamilton) branch fix/main-ci-current-dependencies created (now 321cb96b)
This is an automated email from the ASF dual-hosted git repository.
skrawcz pushed a change to branch fix/main-ci-current-dependencies
in repository https://gitbox.apache.org/repos/asf/hamilton.git
at 321cb96b Fix CI compatibility with current dependencies
This branch includes the following new commits:
new 321cb96b Fix CI compatibility with current dependencies
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(hamilton) 01/01: Fix CI compatibility with current dependencies
Posted by sk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
skrawcz pushed a commit to branch fix/main-ci-current-dependencies
in repository https://gitbox.apache.org/repos/asf/hamilton.git
commit 321cb96b58fb105ca9348d765ac5bd1d2508586f
Author: Stefan Krawczyk <sk...@salesforce.com>
AuthorDate: Wed Sep 23 22:23:09 2026 -0700
Fix CI compatibility with current dependencies
---
.github/workflows/hamilton-main.yml | 3 ---
hamilton/plugins/pandas_extensions.py | 25 ++++++++++++++++++++++
pyproject.toml | 2 +-
tests/plugins/test_pandas_extensions.py | 22 ++++++++++++++++++-
tests/test_base.py | 12 +++++++++--
tests/test_default_data_quality.py | 2 +-
.../tests/test_db_methods/test_permissions.py | 4 +---
.../tests/test_lifecycle/test_run_tracking.py | 24 ++++++---------------
8 files changed, 65 insertions(+), 29 deletions(-)
diff --git a/.github/workflows/hamilton-main.yml b/.github/workflows/hamilton-main.yml
index aecae09b..fb055c5b 100644
--- a/.github/workflows/hamilton-main.yml
+++ b/.github/workflows/hamilton-main.yml
@@ -18,8 +18,6 @@ jobs:
static-checks:
name: "Static Checks"
runs-on: ubuntu-latest
- env:
- UV_PRERELEASE: "allow"
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -52,7 +50,6 @@ jobs:
- '3.13'
- '3.14'
env:
- UV_PRERELEASE: "allow"
HAMILTON_TELEMETRY_ENABLED: false
steps:
diff --git a/hamilton/plugins/pandas_extensions.py b/hamilton/plugins/pandas_extensions.py
index 77cdc30f..b645a9e5 100644
--- a/hamilton/plugins/pandas_extensions.py
+++ b/hamilton/plugins/pandas_extensions.py
@@ -1640,6 +1640,31 @@ class PandasTableReader(DataLoader):
# but we send it separately
del kwargs["filepath_or_buffer"]
+ if self.delim_whitespace:
+ if self.sep is not None or self.delimiter is not None:
+ raise ValueError("delim_whitespace cannot be combined with sep or delimiter")
+ kwargs["sep"] = r"\s+"
+ del kwargs["delim_whitespace"]
+
+ if Version(pd.__version__) >= Version("3.0"):
+ removed_parameters = {
+ "verbose": self.verbose,
+ "infer_datetime_format": self.infer_datetime_format or None,
+ "keep_date_col": self.keep_date_col,
+ "date_parser": self.date_parser,
+ }
+ requested_parameters = [
+ name for name, value in removed_parameters.items() if value is not None
+ ]
+ if requested_parameters:
+ raise ValueError(
+ f"pandas 3.0 removed these read_table parameters: "
+ f"{', '.join(requested_parameters)}"
+ )
+ for parameter in removed_parameters:
+ del kwargs[parameter]
+ kwargs.pop("delim_whitespace", None)
+
return kwargs
def load_data(self, type_: type) -> tuple[DATAFRAME_TYPE, dict[str, Any]]:
diff --git a/pyproject.toml b/pyproject.toml
index 9ad9d332..820ba11e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -133,7 +133,7 @@ test = [
"pytest-cov",
"PyYAML",
"scikit-learn",
- "sqlalchemy[asyncio]",
+ "sqlalchemy[asyncio]<2.1",
"typer>=0.16.0",
"xgboost; python_version < '3.14'",
"xlsx2csv", # for excel data loader
diff --git a/tests/plugins/test_pandas_extensions.py b/tests/plugins/test_pandas_extensions.py
index 784919d0..2f396310 100644
--- a/tests/plugins/test_pandas_extensions.py
+++ b/tests/plugins/test_pandas_extensions.py
@@ -129,7 +129,7 @@ def test_pandas_sql(df: pd.DataFrame, conn: str | sqlite3.Connection) -> None:
assert metadata1["sql_metadata"]["rows"] == 1
assert metadata2["sql_metadata"]["rows"] == 1
- assert metadata1["dataframe_metadata"]["datatypes"] == ["object"]
+ assert metadata1["dataframe_metadata"]["datatypes"] == [str(df["foo"].dtype)]
if hasattr(conn, "close"):
conn.close()
@@ -321,6 +321,26 @@ def test_pandas_table_reader(tmp_path: pathlib.Path) -> None:
]
+def test_pandas_table_reader_translates_delim_whitespace_for_pandas_3(tmp_path) -> None:
+ path = tmp_path / "table.txt"
+ path.write_text("name value\nfoo 1\n")
+
+ reader = PandasTableReader(filepath_or_buffer=path, delim_whitespace=True)
+ df, _ = reader.load_data(pd.DataFrame)
+
+ assert df.to_dict(orient="records") == [{"name": "foo", "value": 1}]
+
+
+def test_pandas_table_reader_rejects_removed_parameter_on_pandas_3() -> None:
+ reader = PandasTableReader(filepath_or_buffer="unused", verbose=True)
+
+ if int(pd.__version__.split(".", maxsplit=1)[0]) >= 3:
+ with pytest.raises(ValueError, match="pandas 3.0 removed.*verbose"):
+ reader._get_loading_kwargs()
+ else:
+ assert reader._get_loading_kwargs()["verbose"] is True
+
+
@pytest.mark.skipif(sys.version_info >= (3, 14), reason="pyreadstat not available on Python 3.14")
def test_pandas_spss_reader(tmp_path: pathlib.Path) -> None:
import pyreadstat
diff --git a/tests/test_base.py b/tests/test_base.py
index 6c9d6406..617cb838 100644
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -311,7 +311,11 @@ PD_VERSION = version.parse(pd.__version__)
(
{
"b": pd.Series(
- [3, 4, 5], index=pd.DatetimeIndex(["2022-01", "2022-02", "2022-03"], freq="MS")
+ [3, 4, 5],
+ index=pd.DatetimeIndex(
+ np.array(["2022-01", "2022-02", "2022-03"], dtype="datetime64[ns]"),
+ freq="MS",
+ ),
)
},
(
@@ -326,7 +330,11 @@ PD_VERSION = version.parse(pd.__version__)
"a": pd.Series([1, 2, 3]),
"b": 1,
"c": pd.Series(
- [3, 4, 5], index=pd.DatetimeIndex(["2022-01", "2022-02", "2022-03"], freq="MS")
+ [3, 4, 5],
+ index=pd.DatetimeIndex(
+ np.array(["2022-01", "2022-02", "2022-03"], dtype="datetime64[ns]"),
+ freq="MS",
+ ),
),
},
(
diff --git a/tests/test_default_data_quality.py b/tests/test_default_data_quality.py
index 924442e1..64a6097a 100644
--- a/tests/test_default_data_quality.py
+++ b/tests/test_default_data_quality.py
@@ -198,7 +198,7 @@ def test_resolve_default_validators_error(output_type, kwargs, importance):
(
default_validators.DataTypeValidatorPandasSeries,
numpy.dtype("object"),
- pd.Series(["hello", "goodbye"]),
+ pd.Series(["hello", "goodbye"], dtype="object"),
True,
),
(
diff --git a/ui/backend/server/tests/test_db_methods/test_permissions.py b/ui/backend/server/tests/test_db_methods/test_permissions.py
index 40b81349..b029a7e2 100644
--- a/ui/backend/server/tests/test_db_methods/test_permissions.py
+++ b/ui/backend/server/tests/test_db_methods/test_permissions.py
@@ -657,9 +657,7 @@ async def test_visible_project_ids_for_user_only_returns_member_projects(db):
"user_individual@no_team.com", "write"
)
# Project B is accessible by user B only.
- project_b, user_b = await _setup_project_accessible_only_by(
- "user_1_team_1@team1.com", "write"
- )
+ project_b, user_b = await _setup_project_accessible_only_by("user_1_team_1@team1.com", "write")
request_a = await _get_authenticated_request("user_individual@no_team.com")
request_b = await _get_authenticated_request("user_1_team_1@team1.com")
user_a_obj, teams_a = request_a.auth
diff --git a/ui/backend/server/tests/test_lifecycle/test_run_tracking.py b/ui/backend/server/tests/test_lifecycle/test_run_tracking.py
index 6d76fc46..7534ca12 100644
--- a/ui/backend/server/tests/test_lifecycle/test_run_tracking.py
+++ b/ui/backend/server/tests/test_lifecycle/test_run_tracking.py
@@ -342,17 +342,11 @@ async def test_get_latest_dag_runs_without_params_excludes_other_users_runs(
dag_template_a, _ = await _setup_dag_template(async_client, user_a)
dag_template_b, _ = await _setup_dag_template(async_client, user_b)
- run_a_id = await _create_dag_run_via_api(
- async_client, user_a, dag_template_a, {"owner": "a"}
- )
- run_b_id = await _create_dag_run_via_api(
- async_client, user_b, dag_template_b, {"owner": "b"}
- )
+ run_a_id = await _create_dag_run_via_api(async_client, user_a, dag_template_a, {"owner": "a"})
+ run_b_id = await _create_dag_run_via_api(async_client, user_b, dag_template_b, {"owner": "b"})
# User A asks for latest runs with no filter -- must not see user B's run.
- response = await async_client.get(
- "/api/v1/dag_runs/latest/", headers={"test_username": user_a}
- )
+ response = await async_client.get("/api/v1/dag_runs/latest/", headers={"test_username": user_a})
assert response.status_code == 200, response.content
returned_ids = {item["id"] for item in response.json()}
assert run_a_id in returned_ids
@@ -390,17 +384,13 @@ async def test_get_latest_dag_runs_with_other_users_project_id_is_rejected(
@pytest.mark.asyncio
-async def test_get_latest_dag_runs_with_own_project_id_still_works(
- async_client: AsyncClient, db
-):
+async def test_get_latest_dag_runs_with_own_project_id_still_works(async_client: AsyncClient, db):
"""The legitimate case -- user asking for runs in a project they own --
must keep returning their runs after the visibility filter is applied.
"""
user_a = "user_individual@no_team.com"
dag_template_a, _ = await _setup_dag_template(async_client, user_a)
- run_id = await _create_dag_run_via_api(
- async_client, user_a, dag_template_a, {"owner": "a"}
- )
+ run_id = await _create_dag_run_via_api(async_client, user_a, dag_template_a, {"owner": "a"})
# By dag_template_id.
response = await async_client.get(
@@ -415,9 +405,7 @@ async def test_get_latest_dag_runs_with_own_project_id_still_works(
project_a_id, *_ = await _setup_sample_project(async_client, user_a)
# New template in this project, new run.
dag_template_a2, _ = await _setup_dag_template(async_client, user_a)
- run_id_2 = await _create_dag_run_via_api(
- async_client, user_a, dag_template_a2, {"owner": "a2"}
- )
+ run_id_2 = await _create_dag_run_via_api(async_client, user_a, dag_template_a2, {"owner": "a2"})
response = await async_client.get(
f"/api/v1/dag_runs/latest/?{urlencode({'project_id': project_a_id})}",
headers={"test_username": user_a},