From 7c8d018f957e4c9d550fc960e1bbaee8a6071b49 Mon Sep 17 00:00:00 2001 From: Yash Bhangale Date: Tue, 27 Jan 2026 03:22:20 -0800 Subject: [PATCH 1/5] BLD: python3.9 is deprecated, require python>=3.10 upto 3.13 --- .github/workflows/main.yml | 4 ++-- README.rst | 2 +- setup.py | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3b560b4..29e200e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12", 3.13] steps: - uses: actions/checkout@v4 @@ -53,7 +53,7 @@ jobs: fail-fast: false max-parallel: 4 matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12", 3.13] steps: - uses: actions/checkout@v4 diff --git a/README.rst b/README.rst index c54829e..e02c5fc 100644 --- a/README.rst +++ b/README.rst @@ -141,7 +141,7 @@ Installation Dependencies ^^^^^^^^^^^^ -The high-level dependencies for PySensors are Linux or macOS and Python 3.9-3.12. ``pip`` is also recommended as is makes managing PySensors' other dependencies much easier. You can install it by following the instructions `here `__. +The high-level dependencies for PySensors are Linux or macOS and Python 3.10-3.13. ``pip`` is also recommended as is makes managing PySensors' other dependencies much easier. You can install it by following the instructions `here `__. PySensors has not been tested on Windows. diff --git a/setup.py b/setup.py index ff72e92..7ac09b2 100644 --- a/setup.py +++ b/setup.py @@ -3,21 +3,21 @@ from setuptools import find_packages, setup -assert sys.version_info >= (3, 9, 0), "pysensors requires Python 3.9+" +assert sys.version_info >= (3, 10, 0), "pysensors requires Python 3.10+" NAME = "python-sensors" DESCRIPTION = "Sparse sensor placement" URL = "https://github.com/dynamicslab/pysensors" EMAIL = "bdesilva@uw.edu, kmanohar@uw.edu, emily.e.clark93@gmail.com" AUTHOR = "Brian de Silva, Krithika Manohar, Emily Clark" -PYTHON = ">=3.6" +PYTHON = ">=3.10" LICENSE = "MIT" CLASSIFIERS = [ "Programming Language :: Python", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Development Status :: 4 - Beta", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", From 4b6ac972676b791d38784b9e30c43adbf2a1c4c8 Mon Sep 17 00:00:00 2001 From: Yash Bhangale Date: Tue, 27 Jan 2026 20:12:10 -0800 Subject: [PATCH 2/5] BLD: store all project metadata in pyproject.toml --- pyproject.toml | 95 ++++++++++++++++++++++++++++++++++++--- requirements-dev.txt | 15 ------- requirements-examples.txt | 6 --- requirements.txt | 5 --- setup.cfg | 20 --------- setup.py | 51 --------------------- 6 files changed, 90 insertions(+), 102 deletions(-) delete mode 100644 requirements-dev.txt delete mode 100644 requirements-examples.txt delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/pyproject.toml b/pyproject.toml index c37c501..4ff1d7e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,67 @@ [build-system] -requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4", "setuptools_scm_git_archive"] -build-backend = "setuptools.build_meta:__legacy__" +requires = [ + "setuptools>=64", + "wheel", + "setuptools_scm[toml]>=8", + "setuptools_scm_git_archive", +] +build-backend = "setuptools.build_meta" -[tool.setuptools_scm] -write_to = "pysensors/version.py" +[project] +name = "python-sensors" +description = "Sparse Sensor Placement" +authors = [ + {name="Brian de Silva", email="bdesilva@uw.edu"}, + {name="Krithika Manohar", email="kmanohar@uw.edu"}, + {name="Emily Clark", email="emily.e.clark93@gmail.com"}, +] +license = {text = "MIT"} +requires-python = ">=3.10" +dynamic = ["version"] +classifiers = [ + "Programming Language :: Python", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Development Status :: 4 - Beta", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Topic :: Scientific/Engineering :: Mathematics", +] +readme = "README.rst" +dependencies = [ + "scikit-learn", + "numpy>=2.0", + "matplotlib>=3.10", + "pandas", + "scipy" +] + +[project.urls] +Homepage = "https://github.com/dynamicslab/pysensors" +Repository = "https://github.com/dynamicslab/pysensors" + +[project.optional-dependencies] +dev = [ + "pytest >=6.2.4, <8.0.0", + "pytest-cov", + "pytest-lazy-fixture", + "flake8-builtins-unleashed", + "codecov", + "sphinx >= 2", + "sphinxcontrib-apidoc", + "sphinx_rtd_theme", + "pre-commit", + "nbsphinx", +] +examples = [ + "jupyter", + "matplotlib", + "netCDF4", + "notebook", + "seaborn", +] [tool.black] line-length = 88 @@ -21,4 +79,31 @@ exclude = ''' filterwarnings = [ "ignore::RuntimeWarning", "ignore::UserWarning" -] \ No newline at end of file +] + +[tool.setuptools] +packages = { find = { exclude = ["tests", "examples"] } } + +[tool.setuptools_scm] +write_to = "pysensors/version.py" + +[tool.flake8] +exclude = [ + ".git", + ".venv", + "dist", + "build", + "__pycache__", +] +ignore = [ + "W503", # conflicts with black + "E203", # conflicts with black +] +per-file-ignores = [ + "__init__.py:F401,F403", +] +max-line-length = 88 +import-order-style = "smarkets" +statistics = true +count = true +verbose = 1 \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 20231f0..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,15 +0,0 @@ --e . --r requirements.txt --r requirements-examples.txt -pytest >=6.2.4, <8.0.0 -pytest-cov -pytest-lazy-fixture -flake8-builtins-unleashed -codecov -setuptools_scm -setuptools_scm_git_archive -sphinx >= 2 -sphinxcontrib-apidoc -sphinx_rtd_theme -pre-commit -nbsphinx \ No newline at end of file diff --git a/requirements-examples.txt b/requirements-examples.txt deleted file mode 100644 index c8a7d7c..0000000 --- a/requirements-examples.txt +++ /dev/null @@ -1,6 +0,0 @@ -jupyter -matplotlib -netCDF4 -notebook -pandas -seaborn \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 9198ba0..0000000 --- a/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -scikit-learn>=0.23 -matplotlib -numpy -pandas -scipy diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 135daaf..0000000 --- a/setup.cfg +++ /dev/null @@ -1,20 +0,0 @@ -[flake8] -exclude = - .git, - .venv, - dist, - build, - __pycache__ -ignore = - # Line break before binary operator - Conflicts black - W503 - # Whitespace before ':' - Conflicts black - E203 -per-file-ignores = - __init__.py:F401,F403 -max-line-length = 88 -import-order-style = smarkets -statistics = True -count = True -verbose = 1 -# format = [%(code)s] %(text)s @ %(path)s:%(row)d:%(col)d \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index 7ac09b2..0000000 --- a/setup.py +++ /dev/null @@ -1,51 +0,0 @@ -import pathlib -import sys - -from setuptools import find_packages, setup - -assert sys.version_info >= (3, 10, 0), "pysensors requires Python 3.10+" - -NAME = "python-sensors" -DESCRIPTION = "Sparse sensor placement" -URL = "https://github.com/dynamicslab/pysensors" -EMAIL = "bdesilva@uw.edu, kmanohar@uw.edu, emily.e.clark93@gmail.com" -AUTHOR = "Brian de Silva, Krithika Manohar, Emily Clark" -PYTHON = ">=3.10" -LICENSE = "MIT" -CLASSIFIERS = [ - "Programming Language :: Python", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Development Status :: 4 - Beta", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Topic :: Scientific/Engineering :: Mathematics", -] - -here = pathlib.Path(__file__).parent - -with open(here / "requirements.txt", "r") as f: - REQUIRED = f.readlines() - -with open(here / "README.rst", "r") as f: - LONG_DESCRIPTION = f.read() - - -setup( - name=NAME, - use_scm_version=True, - setup_requires=["setuptools_scm", "setuptools_scm_git_archive"], - description=DESCRIPTION, - long_description=LONG_DESCRIPTION, - long_description_content_type="text/x-rst", - author=AUTHOR, - author_email=EMAIL, - url=URL, - packages=find_packages(exclude=["test", "examples"]), - install_requires=REQUIRED, - python_requires=PYTHON, - license=LICENSE, - classifiers=CLASSIFIERS, -) From c7c4f5bb2a981d6010e6178ffbe51fd1b46f1748 Mon Sep 17 00:00:00 2001 From: Yash Bhangale Date: Wed, 28 Jan 2026 01:19:42 -0800 Subject: [PATCH 3/5] BLD: move flake8 config from setup to pre-commit --- .pre-commit-config.yaml | 4 +++- pyproject.toml | 16 +++------------- tests/utils/test_constraints.py | 32 ++++++++++++++++++++------------ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index de0d049..cb6801e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,4 +23,6 @@ repos: rev: 7.1.1 hooks: - id: flake8 - args: ["--config=setup.cfg"] \ No newline at end of file + args: + - --max-line-length=88 + - --extend-ignore=E203,F401 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 4ff1d7e..c58c67e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,17 +93,7 @@ exclude = [ ".venv", "dist", "build", + "docs", + "examples", "__pycache__", -] -ignore = [ - "W503", # conflicts with black - "E203", # conflicts with black -] -per-file-ignores = [ - "__init__.py:F401,F403", -] -max-line-length = 88 -import-order-style = "smarkets" -statistics = true -count = true -verbose = 1 \ No newline at end of file +] \ No newline at end of file diff --git a/tests/utils/test_constraints.py b/tests/utils/test_constraints.py index ea1eae5..b711a8e 100644 --- a/tests/utils/test_constraints.py +++ b/tests/utils/test_constraints.py @@ -3580,11 +3580,15 @@ def test_draw_with_numpy_array_and_equation(self): constraint = UserDefinedConstraints( all_sensors=all_sensors, equation="x**2 + y**2 <= 4", data=sample_array ) - with patch( - "pysensors.utils._constraints.get_coordinates_from_indices" - ) as mock_get_coords, patch("builtins.eval") as mock_eval, patch.object( - BaseConstraint, "get_functionalConstraind_sensors_indices" - ) as mock_get_func: + with ( + patch( + "pysensors.utils._constraints.get_coordinates_from_indices" + ) as mock_get_coords, + patch("builtins.eval") as mock_eval, + patch.object( + BaseConstraint, "get_functionalConstraind_sensors_indices" + ) as mock_get_func, + ): x_values = np.array([1.0, 2.0, 3.0, 4.0, 5.0]) y_values = np.array([1.0, 2.0, 3.0, 4.0, 5.0]) mock_get_coords.side_effect = [ @@ -3634,13 +3638,17 @@ def test_function(x, y): all_sensors=all_sensors, file="test_constraint.py", data=sample_array ) assert constraint.functions == test_function - with patch.object( - BaseConstraint, "functional_constraints" - ) as mock_func_constr, patch.object( - BaseConstraint, "get_functionalConstraind_sensors_indices" - ) as mock_get_func, patch( - "pysensors.utils._constraints.get_coordinates_from_indices" - ) as mock_get_coords: + with ( + patch.object( + BaseConstraint, "functional_constraints" + ) as mock_func_constr, + patch.object( + BaseConstraint, "get_functionalConstraind_sensors_indices" + ) as mock_get_func, + patch( + "pysensors.utils._constraints.get_coordinates_from_indices" + ) as mock_get_coords, + ): mock_func_constr.return_value = np.array([1.5, -0.5, 0.8, -1.2, 2.3]) mock_get_func.return_value = (np.array([0, 2, 4]), np.array([0, 1, 2])) mock_get_coords.return_value = ( From 82b4be4719f5538fee9feb3d2387cf3d7ee6ba34 Mon Sep 17 00:00:00 2001 From: Yash Bhangale Date: Wed, 28 Jan 2026 01:32:39 -0800 Subject: [PATCH 4/5] BLD: update CI testing installation --- .github/workflows/main.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 29e200e..e059ae2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -63,7 +63,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - pip install -r requirements-dev.txt + pip install --upgrade pip + pip install -e ".[dev,examples]" - name: Test with pytest run: | pytest tests --cov=pysensors --cov-report=xml @@ -71,7 +72,7 @@ jobs: uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} - file: ./coverage.xml + files: ./coverage.xml - name: Execute feature notebook with papermill run: | pip install papermill @@ -80,6 +81,6 @@ jobs: - uses: actions/cache@v4 with: path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements-dev.txt') }} + key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} restore-keys: | ${{ runner.os }}-pip- From 3f257a81beb6b1cf3a76ad24c2cf07c0162912d7 Mon Sep 17 00:00:00 2001 From: Yash Bhangale Date: Wed, 28 Jan 2026 02:47:43 -0800 Subject: [PATCH 5/5] DOC: update README installation guidelines --- README.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/README.rst b/README.rst index e02c5fc..17acc24 100644 --- a/README.rst +++ b/README.rst @@ -141,7 +141,7 @@ Installation Dependencies ^^^^^^^^^^^^ -The high-level dependencies for PySensors are Linux or macOS and Python 3.10-3.13. ``pip`` is also recommended as is makes managing PySensors' other dependencies much easier. You can install it by following the instructions `here `__. +The requirements for PySensors are Linux or macOS and Python 3.10-3.13. ``pip`` is recommended as it makes managing PySensors' other dependencies much easier. You can install it by following the instructions `here `__. PySensors has not been tested on Windows. @@ -174,13 +174,12 @@ Then, to install the package, run cd pysensors pip install . -If you do not have pip you can instead use +If you do not have root access, you should add the ``--user`` option to the install command above. +If you want an editable install (recommended for development), run .. code-block:: bash - python setup.py install - -If you do not have root access, you should add the ``--user`` option to the ``install`` commands above. + pip install -e . Features @@ -213,11 +212,11 @@ Documentation ------------- PySensors has a `documentation site `__ hosted by readthedocs. Examples are available `online `__, as static -`Jupyter notebooks `__ and as `interactive notebooks `__. To run the example notebooks locally you should install the dependencies in ``requirements-examples.txt``: +`Jupyter notebooks `__ and as `interactive notebooks `__. To run the example notebooks locally, you should install the examples dependencies: .. code-block:: bash - pip install -r requirements-examples.txt + pip install -e ".[examples]" Community guidelines -------------------- @@ -233,11 +232,11 @@ your work! Contributing code ^^^^^^^^^^^^^^^^^ -We welcome contributions to PySensors. To contribute a new feature please submit a pull request. To get started we recommend installing the packages in ``requirements-dev.txt`` via +We welcome contributions to PySensors. To contribute a new feature please submit a pull request. To get started, we recommend installing the optional dev packages .. code-block:: bash - pip install -r requirements-dev.txt + pip install -e ".[dev]" This will allow you to run unit tests and automatically format your code. To be accepted your code should conform to PEP8 and pass all unit tests. Code can be tested by invoking