From 2720ee89a8dd2182c8afef0605b2944dffa7229b Mon Sep 17 00:00:00 2001 From: Lingtao Xie Date: Wed, 20 Aug 2025 12:03:41 -0700 Subject: [PATCH 1/8] Fix condition in zeros() to properly check for non-empty arrays for NumPy 2.x compatibility #109 --- dask_glm/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dask_glm/utils.py b/dask_glm/utils.py index 88a4a14..2d93cd1 100644 --- a/dask_glm/utils.py +++ b/dask_glm/utils.py @@ -40,7 +40,7 @@ def normalize_inputs(X, y, *args, **kwargs): def zeros(shape, arr=None, **kwargs): - if arr: + if arr is not None and arr.size > 0: return np.zeros_like(arr, shape=shape, **kwargs) else: return np.zeros(shape=shape, **kwargs) From 5e0aca7c47e61257bc7a0bb04a1b2ab3e9315570 Mon Sep 17 00:00:00 2001 From: Matthew Rocklin Date: Fri, 23 Jan 2026 12:37:22 -0600 Subject: [PATCH 2/8] Add --slow flag to skip slow tests by default - Add conftest.py with pytest_addoption for --slow flag - Mark slow tests with @pytest.mark.slow or pytest.param(..., marks=pytest.mark.slow) - Tests now run in ~15s by default, full suite available with --slow - No test coverage removed, slow tests are just skipped by default Co-Authored-By: Claude Opus 4.5 --- dask_glm/tests/conftest.py | 47 +++++++++++++++++++++++++++ dask_glm/tests/test_admm.py | 3 +- dask_glm/tests/test_algos_families.py | 7 ++-- dask_glm/tests/test_estimators.py | 10 +++--- 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 dask_glm/tests/conftest.py diff --git a/dask_glm/tests/conftest.py b/dask_glm/tests/conftest.py new file mode 100644 index 0000000..bd9b3fa --- /dev/null +++ b/dask_glm/tests/conftest.py @@ -0,0 +1,47 @@ +import pytest + + +def pytest_addoption(parser): + parser.addoption( + "--slow", action="store_true", default=False, help="run slow tests" + ) + + +def pytest_configure(config): + config.addinivalue_line("markers", "slow: mark test as slow to run") + + +def pytest_collection_modifyitems(config, items): + if config.getoption("--slow"): + return + skip_slow = pytest.mark.skip(reason="need --slow option to run") + for item in items: + # Check for @pytest.mark.slow on the function + if item.get_closest_marker("slow"): + item.add_marker(skip_slow) + continue + # Check for pytest.param(..., marks=pytest.mark.slow) in parametrize + if not hasattr(item, "callspec"): + continue + for marker in item.iter_markers("parametrize"): + param_names = [n.strip() for n in marker.args[0].split(",")] + for param in marker.args[1]: + if not hasattr(param, "marks") or not param.marks: + continue + has_slow = any( + getattr(m, "name", None) == "slow" + or (hasattr(m, "mark") and m.mark.name == "slow") + for m in param.marks + ) + if not has_slow: + continue + # Check if all values from this param match the callspec + match = True + for i, name in enumerate(param_names): + if i < len(param.values): + if item.callspec.params.get(name) != param.values[i]: + match = False + break + if match: + item.add_marker(skip_slow) + break diff --git a/dask_glm/tests/test_admm.py b/dask_glm/tests/test_admm.py index 0cce881..e98875c 100644 --- a/dask_glm/tests/test_admm.py +++ b/dask_glm/tests/test_admm.py @@ -9,7 +9,7 @@ from dask_glm.utils import make_y, to_dask_cupy_array_xy -@pytest.mark.parametrize("N", [1000, 10000]) +@pytest.mark.parametrize("N", [1000, pytest.param(10000, marks=pytest.mark.slow)]) @pytest.mark.parametrize( "beta", [ @@ -47,6 +47,7 @@ def wrapped(beta, X, y, z, u, rho): assert np.allclose(result, z, atol=2e-3) +@pytest.mark.slow @pytest.mark.parametrize("N", [1000, 10000]) @pytest.mark.parametrize("nchunks", [5, 10]) @pytest.mark.parametrize("p", [1, 5, 10]) diff --git a/dask_glm/tests/test_algos_families.py b/dask_glm/tests/test_algos_families.py index 672f136..d592621 100644 --- a/dask_glm/tests/test_algos_families.py +++ b/dask_glm/tests/test_algos_families.py @@ -105,12 +105,12 @@ def test_basic_unreg_descent(func, kwargs, N, nchunks, family, array_type): @pytest.mark.parametrize( "func,kwargs", [ - (admm, {"abstol": 1e-4}), + pytest.param(admm, {"abstol": 1e-4}, marks=pytest.mark.slow), (proximal_grad, {"tol": 1e-7}), ], ) @pytest.mark.parametrize("N", [1000]) -@pytest.mark.parametrize("nchunks", [1, 10]) +@pytest.mark.parametrize("nchunks", [1, pytest.param(10, marks=pytest.mark.slow)]) @pytest.mark.parametrize("family", [Logistic, Normal, Poisson]) @pytest.mark.parametrize("lam", [0.01, 1.2, 4.05]) @pytest.mark.parametrize("reg", [r() for r in Regularizer.__subclasses__()]) @@ -138,6 +138,7 @@ def test_basic_reg_descent(func, kwargs, N, nchunks, family, lam, reg, array_typ assert opt < test_val +@pytest.mark.slow @pytest.mark.parametrize( "func,kwargs", [ @@ -167,6 +168,7 @@ def test_determinism(func, kwargs, scheduler, array_type): pass else: + @pytest.mark.slow @pytest.mark.parametrize( "func,kwargs", [ @@ -186,6 +188,7 @@ def test_determinism_distributed(func, kwargs, loop_in_thread): # noqa: F811 assert (a == b).all() + @pytest.mark.slow def test_broadcast_lbfgs_weight(loop_in_thread): # noqa: F811 with cluster() as (s, [a, b]): with Client(s["address"], loop=loop_in_thread) as c: diff --git a/dask_glm/tests/test_estimators.py b/dask_glm/tests/test_estimators.py index 68eb3a2..71be5e5 100644 --- a/dask_glm/tests/test_estimators.py +++ b/dask_glm/tests/test_estimators.py @@ -54,9 +54,9 @@ def _maybe_skip_sparse_error(fit_intercept, is_sparse, is_cupy): pytest.xfail(f"TODO: {msg}") -@pytest.mark.parametrize("fit_intercept", [True, False]) +@pytest.mark.parametrize("fit_intercept", [pytest.param(True, marks=pytest.mark.slow), False]) @pytest.mark.parametrize( - "is_sparse,is_cupy", [(True, False), (False, False), (False, True)] + "is_sparse,is_cupy", [pytest.param(True, False, marks=pytest.mark.slow), (False, False), (False, True)] ) def test_fit(fit_intercept, is_sparse, is_cupy): _maybe_skip_sparse_error(fit_intercept, is_sparse, is_cupy) @@ -75,9 +75,9 @@ def test_fit(fit_intercept, is_sparse, is_cupy): lr.predict_proba(X) -@pytest.mark.parametrize("fit_intercept", [True, False]) +@pytest.mark.parametrize("fit_intercept", [pytest.param(True, marks=pytest.mark.slow), False]) @pytest.mark.parametrize( - "is_sparse,is_cupy", [(True, False), (False, False), (False, True)] + "is_sparse,is_cupy", [pytest.param(True, False, marks=pytest.mark.slow), (False, False), (False, True)] ) def test_lm(fit_intercept, is_sparse, is_cupy): _maybe_skip_sparse_error(fit_intercept, is_sparse, is_cupy) @@ -95,6 +95,7 @@ def test_lm(fit_intercept, is_sparse, is_cupy): assert lr.intercept_ is not None +@pytest.mark.slow @pytest.mark.parametrize("fit_intercept", [True, False]) @pytest.mark.parametrize( "is_sparse,is_cupy", [(True, False), (False, False), (False, True)] @@ -115,6 +116,7 @@ def test_big(fit_intercept, is_sparse, is_cupy): assert lr.intercept_ is not None +@pytest.mark.slow @pytest.mark.parametrize("fit_intercept", [True, False]) @pytest.mark.parametrize( "is_sparse,is_cupy", [(True, False), (False, False), (False, True)] From dd1a1ff82755daf5b8e85b3ba9065e239ac85e72 Mon Sep 17 00:00:00 2001 From: Matthew Rocklin Date: Fri, 23 Jan 2026 14:31:43 -0600 Subject: [PATCH 3/8] Fix sparse library API compatibility - Add shape parameter to sparse.COO (now required) - Convert sparse arrays to dense before assert_eq comparison Co-Authored-By: Claude Opus 4.5 --- dask_glm/tests/test_utils.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dask_glm/tests/test_utils.py b/dask_glm/tests/test_utils.py index 5c07383..7f39fd7 100644 --- a/dask_glm/tests/test_utils.py +++ b/dask_glm/tests/test_utils.py @@ -129,7 +129,7 @@ def test_add_intercept_sparse_dask(): def test_sparse(): - x = sparse.COO({(0, 0): 1, (1, 2): 2, (2, 1): 3}) + x = sparse.COO({(0, 0): 1, (1, 2): 2, (2, 1): 3}, shape=(3, 3)) y = x.todense() assert utils.sum(x) == utils.sum(x.todense()) for func in [utils.sigmoid, utils.sum, utils.exp]: @@ -174,16 +174,16 @@ def test_dot_with_cupy(): def test_dot_with_sparse(): A = sparse.random((1024, 64)) B = sparse.random((64)) - ans = sparse.dot(A, B) + ans = sparse.dot(A, B).todense() # dot(sparse.array, sparse.array) res = utils.dot(A, B) - assert_eq(ans, res) + assert_eq(ans, res.todense()) # dot(sparse.array, dask.array) res = utils.dot(A, da.from_array(B, chunks=B.shape)) - assert_eq(ans, res.compute()) + assert_eq(ans, res.compute().todense()) # dot(dask.array, sparse.array) res = utils.dot(da.from_array(A, chunks=A.shape), B) - assert_eq(ans, res.compute()) + assert_eq(ans, res.compute().todense()) From 1d49a6fff2274311c534de25ce85815a8e01c97e Mon Sep 17 00:00:00 2001 From: Matthew Rocklin Date: Fri, 23 Jan 2026 15:06:31 -0600 Subject: [PATCH 4/8] Modernize packaging and CI - Replace setup.py/requirements.txt with pyproject.toml - Use importlib.metadata instead of deprecated pkg_resources - Update CI to use uv and Python 3.10-3.13 - Bump minimum dependency versions - Add uv.lock to .gitignore Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci.yml | 22 ++++---------- .gitignore | 1 + dask_glm/__init__.py | 6 ++-- pyproject.toml | 66 ++++++++++++++++++++++++++++++++++++++++ requirements.txt | 7 ----- setup.cfg | 6 ---- setup.py | 31 ------------------- 7 files changed, 76 insertions(+), 63 deletions(-) create mode 100644 pyproject.toml delete mode 100644 requirements.txt delete mode 100755 setup.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 852d6c8..7fe88f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,27 +9,17 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - name: Checkout source - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - name: Setup Conda Environment - uses: conda-incubator/setup-miniconda@v2.2.0 - with: - miniforge-variant: Mambaforge - miniforge-version: latest - use-mamba: true - python-version: ${{ matrix.python-version }} - activate-environment: dask-glm + - name: Install uv + uses: astral-sh/setup-uv@v5 - name: Install dask_glm - shell: bash -l {0} - run: pip install -e . + run: uv sync --python ${{ matrix.python-version }} --extra dev - name: Run pytest - shell: bash -l {0} - run: | - pip install pytest pytest-xdist - pytest dask_glm -n auto + run: uv run pytest dask_glm diff --git a/.gitignore b/.gitignore index 9ca292f..4d90334 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.swpi *.cache *.coverage +uv.lock # Distribution / packaging .Python diff --git a/dask_glm/__init__.py b/dask_glm/__init__.py index e8fa341..833c4b2 100644 --- a/dask_glm/__init__.py +++ b/dask_glm/__init__.py @@ -1,6 +1,6 @@ -from pkg_resources import DistributionNotFound, get_distribution +from importlib.metadata import PackageNotFoundError, version try: - __version__ = get_distribution(__name__).version -except DistributionNotFound: + __version__ = version(__name__) +except PackageNotFoundError: pass diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ef76714 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,66 @@ +[build-system] +requires = ["setuptools>=61", "setuptools-scm>=8"] +build-backend = "setuptools.build_meta" + +[project] +name = "dask-glm" +description = "Generalized Linear Models with Dask" +readme = "README.rst" +license = "BSD-3-Clause" +maintainers = [{ name = "Matthew Rocklin", email = "mrocklin@gmail.com" }] +keywords = ["dask", "glm", "machine-learning"] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Science/Research", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Scientific/Engineering", +] +requires-python = ">=3.10" +dependencies = [ + "cloudpickle>=1.0", + "dask[array]>=2022.1.0", + "distributed>=2022.1.0", + "multipledispatch>=0.6.0", + "numba>=0.59", + "numpy>=1.21", + "scipy>=1.7", + "scikit-learn>=1.0", + "sparse>=0.15", +] +dynamic = ["version"] + +[project.optional-dependencies] +dev = [ + "pytest>=7.0", + "pytest-xdist>=3.0", + "pre-commit>=3.0", +] +docs = [ + "jupyter", + "nbsphinx", + "notebook", + "numpydoc", + "sphinx", + "sphinx_rtd_theme", +] + +[project.urls] +Homepage = "https://github.com/dask/dask-glm" +Documentation = "https://dask-glm.readthedocs.io" +Repository = "https://github.com/dask/dask-glm" + +[tool.setuptools] +packages = ["dask_glm"] + +[tool.setuptools_scm] +version_scheme = "guess-next-dev" +local_scheme = "no-local-version" + +[tool.pytest.ini_options] +testpaths = ["dask_glm/tests"] +addopts = "-v" +markers = ["slow: mark test as slow to run"] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index f513993..0000000 --- a/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -cloudpickle>=0.2.2 -dask[array] -multipledispatch>=0.4.9 -scipy>=0.18.1 -scikit-learn>=0.18 -distributed -sparse>=0.7.0 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index add4cf3..aa5384c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,10 +1,4 @@ -[bdist_wheel] -universal=1 - [flake8] exclude = docs ignore = F811 max-line-length = 100 - -[tool:pytest] -addopts= -rsx -v \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100755 index 738c2ba..0000000 --- a/setup.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python - -from os.path import exists - -from setuptools import setup - -setup( - name="dask-glm", - description="Generalized Linear Models with Dask", - url="http://github.com/dask/dask-glm/", - maintainer="Matthew Rocklin", - maintainer_email="mrocklin@gmail.com", - license="BSD", - keywords="dask,glm", - packages=["dask_glm"], - long_description=(open("README.rst").read() if exists("README.rst") else ""), - install_requires=list(open("requirements.txt").read().strip().split("\n")), - use_scm_version=True, - setup_requires=["setuptools_scm"], - extras_require={ - "docs": [ - "jupyter", - "nbsphinx", - "notebook", - "numpydoc", - "sphinx", - "sphinx_rtd_theme", - ] - }, - zip_safe=False, -) From 374691ae05b085b5f951b2b01c021d0e11129c1f Mon Sep 17 00:00:00 2001 From: Matthew Rocklin Date: Fri, 23 Jan 2026 15:08:25 -0600 Subject: [PATCH 5/8] Add Python 3.14 support Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci.yml | 2 +- pyproject.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7fe88f6..beddb8d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - name: Checkout source diff --git a/pyproject.toml b/pyproject.toml index ef76714..83e7e20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Scientific/Engineering", ] requires-python = ">=3.10" From 903a49e044f37d5001e182b6b9147a53be564ead Mon Sep 17 00:00:00 2001 From: Matthew Rocklin Date: Fri, 23 Jan 2026 15:13:57 -0600 Subject: [PATCH 6/8] Update pre-commit hooks and apply formatting - Update black, flake8, isort, codespell to latest versions - Add W503 to flake8 ignore (conflicts with black) - Apply black formatting Co-Authored-By: Claude Opus 4.5 --- .pre-commit-config.yaml | 8 ++++---- dask_glm/algorithms.py | 9 ++++----- dask_glm/estimators.py | 1 + dask_glm/tests/test_estimators.py | 14 ++++++++++---- setup.cfg | 2 +- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 523ced6..06df533 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,25 +1,25 @@ repos: - repo: https://github.com/psf/black - rev: 22.10.0 + rev: 25.1.0 hooks: - id: black language_version: python3 - repo: https://github.com/pycqa/flake8 - rev: 5.0.4 + rev: 7.2.0 hooks: - id: flake8 language_version: python3 - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 6.0.1 hooks: - id: isort language_version: python3 args: ["--profile", "black"] - repo: https://github.com/codespell-project/codespell - rev: v2.2.4 + rev: v2.4.1 hooks: - id: codespell additional_dependencies: diff --git a/dask_glm/algorithms.py b/dask_glm/algorithms.py index 21e02f0..309e16c 100644 --- a/dask_glm/algorithms.py +++ b/dask_glm/algorithms.py @@ -1,5 +1,4 @@ -"""Optimization algorithms for solving minimizaiton problems. -""" +"""Optimization algorithms for solving minimizaiton problems.""" from __future__ import absolute_import, division, print_function @@ -233,7 +232,7 @@ def admm( abstol=1e-4, reltol=1e-2, family=Logistic, - **kwargs + **kwargs, ): """ Alternating Direction Method of Multipliers @@ -358,7 +357,7 @@ def lbfgs( tol=1e-4, family=Logistic, verbose=False, - **kwargs + **kwargs, ): """L-BFGS solver using scipy.optimize implementation @@ -428,7 +427,7 @@ def proximal_grad( family=Logistic, max_iter=100, tol=1e-8, - **kwargs + **kwargs, ): """ Proximal Gradient Method diff --git a/dask_glm/estimators.py b/dask_glm/estimators.py index b83f8dd..783cb72 100644 --- a/dask_glm/estimators.py +++ b/dask_glm/estimators.py @@ -1,6 +1,7 @@ """ Models following scikit-learn's estimator API. """ + from sklearn.base import BaseEstimator from . import algorithms, families diff --git a/dask_glm/tests/test_estimators.py b/dask_glm/tests/test_estimators.py index 71be5e5..5d0fa2d 100644 --- a/dask_glm/tests/test_estimators.py +++ b/dask_glm/tests/test_estimators.py @@ -54,9 +54,12 @@ def _maybe_skip_sparse_error(fit_intercept, is_sparse, is_cupy): pytest.xfail(f"TODO: {msg}") -@pytest.mark.parametrize("fit_intercept", [pytest.param(True, marks=pytest.mark.slow), False]) @pytest.mark.parametrize( - "is_sparse,is_cupy", [pytest.param(True, False, marks=pytest.mark.slow), (False, False), (False, True)] + "fit_intercept", [pytest.param(True, marks=pytest.mark.slow), False] +) +@pytest.mark.parametrize( + "is_sparse,is_cupy", + [pytest.param(True, False, marks=pytest.mark.slow), (False, False), (False, True)], ) def test_fit(fit_intercept, is_sparse, is_cupy): _maybe_skip_sparse_error(fit_intercept, is_sparse, is_cupy) @@ -75,9 +78,12 @@ def test_fit(fit_intercept, is_sparse, is_cupy): lr.predict_proba(X) -@pytest.mark.parametrize("fit_intercept", [pytest.param(True, marks=pytest.mark.slow), False]) @pytest.mark.parametrize( - "is_sparse,is_cupy", [pytest.param(True, False, marks=pytest.mark.slow), (False, False), (False, True)] + "fit_intercept", [pytest.param(True, marks=pytest.mark.slow), False] +) +@pytest.mark.parametrize( + "is_sparse,is_cupy", + [pytest.param(True, False, marks=pytest.mark.slow), (False, False), (False, True)], ) def test_lm(fit_intercept, is_sparse, is_cupy): _maybe_skip_sparse_error(fit_intercept, is_sparse, is_cupy) diff --git a/setup.cfg b/setup.cfg index aa5384c..940f737 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,4 +1,4 @@ [flake8] exclude = docs -ignore = F811 +ignore = F811, W503 max-line-length = 100 From 01f44c34523e8898be763c082472420cf47ba534 Mon Sep 17 00:00:00 2001 From: Matthew Rocklin Date: Fri, 23 Jan 2026 15:22:28 -0600 Subject: [PATCH 7/8] Modernize CI workflows - wheels.yml: Use uv build, update to v4 actions, simplify jobs - pre-commit.yml: Update action versions Co-Authored-By: Claude Opus 4.5 --- .github/workflows/pre-commit.yml | 6 +-- .github/workflows/wheels.yml | 83 ++++++++++---------------------- 2 files changed, 28 insertions(+), 61 deletions(-) diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 895396b..fd73665 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -7,6 +7,6 @@ jobs: name: "pre-commit hooks" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - uses: pre-commit/action@v3.0.0 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 6100f19..9e13c8f 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -1,63 +1,36 @@ -name: Build and maybe upload to PyPI +name: Build and publish to PyPI on: push: + tags: + - '*' pull_request: - release: - types: - - released - - prereleased + workflow_dispatch: jobs: - artifacts: - name: Build wheels on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - + build: + name: Build distribution + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - name: Build wheels - run: pip wheel . -w dist - - name: Build Source Dist - run: python setup.py sdist - - uses: actions/upload-artifact@v3 - with: - name: wheel - path: ./dist/dask_glm* - - uses: actions/upload-artifact@v3 - with: - name: sdist - path: ./dist/dask-glm* - list_artifacts: - name: List build artifacts - needs: [artifacts] - runs-on: ubuntu-latest - steps: - - uses: actions/download-artifact@v3 - with: - name: sdist - path: dist - - uses: actions/download-artifact@v3 + - name: Install uv + uses: astral-sh/setup-uv@v5 + + - name: Build wheel and sdist + run: uv build + + - uses: actions/upload-artifact@v4 with: - name: wheel - path: dist - - name: test - run: | - ls - ls dist + name: dist + path: dist/ - upload_pypi: - needs: [artifacts] - if: "startsWith(github.ref, 'refs/tags/')" + publish: + name: Publish to PyPI + needs: [build] + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest environment: name: releases @@ -65,15 +38,9 @@ jobs: permissions: id-token: write steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: - name: sdist - path: dist - - uses: actions/download-artifact@v3 - with: - name: wheel - path: dist + name: dist + path: dist/ + - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: dist - skip-existing: true From 12ac7faab391c003ca362569b18b5d50d7c56461 Mon Sep 17 00:00:00 2001 From: Matthew Rocklin Date: Fri, 23 Jan 2026 15:30:38 -0600 Subject: [PATCH 8/8] Clean up redundant config and obsolete imports Co-Authored-By: Claude Opus 4.5 --- dask_glm/algorithms.py | 2 -- pyproject.toml | 1 - 2 files changed, 3 deletions(-) diff --git a/dask_glm/algorithms.py b/dask_glm/algorithms.py index 309e16c..53749ab 100644 --- a/dask_glm/algorithms.py +++ b/dask_glm/algorithms.py @@ -1,7 +1,5 @@ """Optimization algorithms for solving minimizaiton problems.""" -from __future__ import absolute_import, division, print_function - import functools import dask diff --git a/pyproject.toml b/pyproject.toml index 83e7e20..d6c6523 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,4 +64,3 @@ local_scheme = "no-local-version" [tool.pytest.ini_options] testpaths = ["dask_glm/tests"] addopts = "-v" -markers = ["slow: mark test as slow to run"]