From d7d0c10b4942c2091f6529c512d9b75363c6ec69 Mon Sep 17 00:00:00 2001 From: NowanIlfideme Date: Sun, 15 Jun 2025 16:47:38 +0200 Subject: [PATCH 1/6] Switched to using uv, ruff, mypy. Fix mypy error. --- .flake8 | 8 ----- .gitignore | 5 ++- .python-version | 1 + MANIFEST.in | 3 -- README.md | 3 -- environment.yml | 8 ----- pyproject.toml | 44 ++++++++++++++++++++++++-- setup.cfg | 56 --------------------------------- setup.py | 6 ---- src/tsdata/__init__.py | 10 ++---- src/tsdata/_version.py | 5 +++ src/tsdata/py.typed | 2 ++ src/tsdata/raw/fpp3/__init__.py | 3 +- src/tsdata/raw/registry.py | 44 ++++++++++++++++---------- 14 files changed, 85 insertions(+), 113 deletions(-) delete mode 100644 .flake8 create mode 100644 .python-version delete mode 100644 MANIFEST.in delete mode 100644 environment.yml delete mode 100644 setup.cfg delete mode 100644 setup.py create mode 100644 src/tsdata/_version.py create mode 100644 src/tsdata/py.typed diff --git a/.flake8 b/.flake8 deleted file mode 100644 index a3ea75b..0000000 --- a/.flake8 +++ /dev/null @@ -1,8 +0,0 @@ -[flake8] -max-line-length = 80 - -select = C,E,F,W,B,B950 -ignore = - W291, W293, W391, # whitespace - E501, # allow some beyond lines - W503, # line break before binary operator diff --git a/.gitignore b/.gitignore index 650ba23..64eba64 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,10 @@ __pycache__ **.ipynb_checkpoints -# setuptools files +# Build files src/*.egg-info /build /dist + +# uv-specific files +/uv.lock \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..c8cfe39 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10 diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 47c98e2..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -global-include *.csv -global-include *.parquet -global-include *.nc \ No newline at end of file diff --git a/README.md b/README.md index 982b45d..db32ce1 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,6 @@ The `tsdata` package itself contains a way of loading these into Pandas. **NOTE**: The PyPI name is `py-tsdata` due to confict with a removed package. -**NOTE**: This package currently only includes the bare requirements. -However, I will keep adding data and functionality over time. - ## Installing You can install this as a regular Python package via pip: diff --git a/environment.yml b/environment.yml deleted file mode 100644 index c0e6d4f..0000000 --- a/environment.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: tsdata -channels: - - conda-forge -dependencies: - - python=3.9 - - pip=21.2 - - pip: - - --editable .[dev] diff --git a/pyproject.toml b/pyproject.toml index 9787c3b..bcba5c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,43 @@ +[project] +name = "py-tsdata" +version = "0.4.0" +description = "Time Series Datasets" +keywords = ["time series", "data", "pandas"] +readme = "README.md" +license = { file = "LICENSE" } +authors = [{ name = "NowanIlfideme", email = "git@nowan.dev" }] +classifiers = [ + "Programming Language :: Python :: 3 :: Only", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Topic :: Software Development", + "Typing :: Typed", +] + +# Requirements +requires-python = ">=3.10" +dependencies = ["pandas>=2.0.0"] + +[project.optional-dependencies] + +[dependency-groups] +dev = [ + "mypy>=1.16.0", + "pandas-stubs>=2.2.3.250527", + "pytest>=8.4.0", + "ruff>=0.11.13", +] + [build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" +requires = ["uv_build>=0.7.13,<0.8"] +build-backend = "uv_build" + +[tool.uv] +package = true +default-groups = ["dev"] + +[tool.uv.build-backend] +module-name = "tsdata" +module-root = "src" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 67a7cbb..0000000 --- a/setup.cfg +++ /dev/null @@ -1,56 +0,0 @@ -[bumpversion] -current_version = 0.3.4 -commit = False -tag = False - -[metadata] -name = py-tsdata -version = attr: tsdata.__version__ -author = Anatoly Makarevich -author_email = git@nowan.dev -description = Time Series Datasets -long_description = file: README.md -long_description_content_type = text/markdown -url = https://github.com/NowanIlfideme/tsdata -project_urls = - Bug Tracker = https://github.com/NowanIlfideme/tsdata/issues -license_files = LICENSE -platform = any -classifiers = - Programming Language :: Python :: 3 - License :: OSI Approved :: MIT License - Operating System :: OS Independent - -[options] -zip_safe = false -include_package_data = True -package_dir = - = src -packages = find: -python_requires = >=3.7 -install_requires = - pandas -tests_require = - pytest - -[options.packages.find] -where = src - -[options.package_data] -* = *.csv, *.parquet, *.nc - -[options.extras_require] -dev = - flake8 - black - isort - bump2version - pytest - mypy - -[bdist_wheel] -universal = true - -[bumpversion:file:setup.cfg] - -[bumpversion:file:src/tsdata/__init__.py] diff --git a/setup.py b/setup.py deleted file mode 100644 index d8fd8f6..0000000 --- a/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Minimal setup.py shim for setup.""" - -from setuptools import setup - -if __name__ == "__main__": - setup() diff --git a/src/tsdata/__init__.py b/src/tsdata/__init__.py index f7a40db..d174b2c 100644 --- a/src/tsdata/__init__.py +++ b/src/tsdata/__init__.py @@ -1,9 +1,5 @@ -"""Time Series Data package. +"""Time Series Data package.""" -The version is managed by bump2version. -""" +__all__ = ["__version__"] -from pathlib import Path - -__version__ = "0.3.4" -__root__ = Path(__file__).parent +from ._version import __version__ diff --git a/src/tsdata/_version.py b/src/tsdata/_version.py new file mode 100644 index 0000000..731e153 --- /dev/null +++ b/src/tsdata/_version.py @@ -0,0 +1,5 @@ +"""Version package.""" + +from importlib.metadata import version as _getversion + +__version__ = _getversion("py-tsdata") diff --git a/src/tsdata/py.typed b/src/tsdata/py.typed new file mode 100644 index 0000000..5540977 --- /dev/null +++ b/src/tsdata/py.typed @@ -0,0 +1,2 @@ +# This package includes type annotations +# See https://peps.python.org/pep-0561/ \ No newline at end of file diff --git a/src/tsdata/raw/fpp3/__init__.py b/src/tsdata/raw/fpp3/__init__.py index 25e8ccb..7121d75 100644 --- a/src/tsdata/raw/fpp3/__init__.py +++ b/src/tsdata/raw/fpp3/__init__.py @@ -4,14 +4,13 @@ """ from pathlib import Path -from typing import Dict import pandas as pd from ..registry import Loader, register_loader __all__ = [] -_funcs: Dict[str, Loader] = {} +_funcs: dict[str, Loader] = {} for _filename in Path(__file__).parent.glob("*.csv"): _name = _filename.stem diff --git a/src/tsdata/raw/registry.py b/src/tsdata/raw/registry.py index c6c1c74..2ae46b3 100644 --- a/src/tsdata/raw/registry.py +++ b/src/tsdata/raw/registry.py @@ -1,6 +1,8 @@ """Data registry. This is very much a work-in-progress.""" -from typing import Callable, Dict, List, Union +from collections.abc import Callable +from functools import partial +from typing import TypeVar, overload import pandas as pd @@ -8,10 +10,10 @@ Loader = Callable[[], pd.DataFrame] -__DATA_LOADERS__: Dict[str, Callable] = {} +__DATA_LOADERS__: dict[str, Callable] = {} -def available_data() -> List[str]: +def available_data() -> list[str]: """Returns all available datasets.""" global __DATA_LOADERS__ return list(sorted(__DATA_LOADERS__.keys())) @@ -32,7 +34,20 @@ def load_data(name: str) -> pd.DataFrame: return loader() -def register_loader(name_or_func: Union[str, Loader]) -> Callable[[Loader], Loader]: +TLoader = TypeVar("TLoader", bound=Loader) + + +@overload +def register_loader(name_or_func: str) -> Callable[[TLoader], TLoader]: ... + + +@overload +def register_loader(name_or_func: TLoader, *, name: str | None = None) -> TLoader: ... + + +def register_loader( + name_or_func: str | Loader, *, name: str | None = None +) -> Loader | Callable[[Loader], Loader]: """Decorator factory to register a data loader for a particular named dataset. Usage @@ -55,20 +70,17 @@ def my_dataset() -> pd.DataFrame: Both cases will register as: `df = load_data("my_dataset")` """ + global __DATA_LOADERS__ if isinstance(name_or_func, str): name = name_or_func - is_func = False - elif callable(name_or_func): - # FIXME: Check signature for a legal loader - name = name_or_func.__qualname__ - is_func = True - else: - raise TypeError(f"Expected str or callable, got {name_or_func!r}.") + return partial(register_loader, name=name) # type: ignore - def register(func: Loader) -> Loader: - """Registers a function as a loader for a particular dataset.""" - global __DATA_LOADERS__ + if callable(name_or_func): + # FIXME: Check signature for a legal loader + if name is None: + name = name_or_func.__qualname__ + func = name_or_func if name in __DATA_LOADERS__.keys(): raise ValueError(f"Attempted to redefine loader for {name!r}.") @@ -77,6 +89,4 @@ def register(func: Loader) -> Loader: return func - if is_func: - return register(name_or_func) - return register + raise TypeError(f"Expected str or callable, got {name_or_func!r}.") From dfc8d1a514cfbc4e17e147eb396184d727c53e3d Mon Sep 17 00:00:00 2001 From: NowanIlfideme Date: Sun, 15 Jun 2025 16:54:30 +0200 Subject: [PATCH 2/6] Update testing )CI_ workflow --- .github/workflows/python-testing.yml | 37 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/.github/workflows/python-testing.yml b/.github/workflows/python-testing.yml index 8d676c5..467885d 100644 --- a/.github/workflows/python-testing.yml +++ b/.github/workflows/python-testing.yml @@ -15,27 +15,28 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8, 3.9] - deps: - - dev + python-version: + - "3.10" + - "3.12" steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 with: + version: "0.7.13" python-version: ${{ matrix.python-version }} - - name: Install Package with dependencies ${{ matrix.deps }} - run: | - pip install -e ".[${{ matrix.deps }}]" - - name: Lint with flake8 + enable-cache: true + cache-dependency-glob: "uv.lock" + + + - name: Install the project + run: uv sync --locked --all-extras --dev + + - name: Lint with ruff run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + uv run ruff + - name: Test with pytest run: | - pytest - # - name: Test with mypy - # run: | - # mypy -m tsdata + uv run pytest From 693f6f3dde58b4cf823d3bbd3d5ff20bcb3a0e5f Mon Sep 17 00:00:00 2001 From: NowanIlfideme Date: Sun, 15 Jun 2025 17:05:08 +0200 Subject: [PATCH 3/6] Revert package bump, just in case. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index bcba5c3..b119e01 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "py-tsdata" -version = "0.4.0" +version = "0.3.4" description = "Time Series Datasets" keywords = ["time series", "data", "pandas"] readme = "README.md" From 404610aca41fe7eef674ae017b89b8c9c9b05d0d Mon Sep 17 00:00:00 2001 From: NowanIlfideme Date: Sun, 15 Jun 2025 17:29:26 +0200 Subject: [PATCH 4/6] Redone publishing via UV --- .github/workflows/python-publish.yml | 67 ++++++++++++++++++++-------- .github/workflows/python-testing.yml | 2 +- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index abcf20e..9b589dd 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -8,29 +8,58 @@ on: types: [created] jobs: - deploy: + ci-check: runs-on: ubuntu-latest - + strategy: + fail-fast: false + matrix: + python-version: + - "3.10" + - "3.12" steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 with: - python-version: "3.8" - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel twine - - name: Install Package + version: "0.7.13" + python-version: ${{ matrix.python-version }} + enable-cache: true + cache-dependency-glob: "uv.lock" + + - name: Install the project + run: uv sync --locked --all-extras --dev + + - name: Lint with ruff run: | - pip install -e ".[dev, ruamel]" + uv run ruff + - name: Test with pytest run: | - pytest - - name: Build and publish - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + uv run pytest + + + publish-pypi: + name: "Publish to PyPI" + needs: + - "ci-check" + runs-on: ubuntu-latest + environment: "publish-pypi" + permissions: + id-token: write # required for trusted publishing + steps: + - uses: actions/checkout@v4 + + - name: Install uv and set the python version + uses: astral-sh/setup-uv@v5 + with: + version: "0.7.13" + + - name: Install the project + run: | + uv sync --locked --all-extras --dev + + - name: Publish the project to PyPI run: | - python setup.py sdist bdist_wheel - twine upload dist/* + uv publish + # NOTE: This works because of trusted publishing diff --git a/.github/workflows/python-testing.yml b/.github/workflows/python-testing.yml index 467885d..768a872 100644 --- a/.github/workflows/python-testing.yml +++ b/.github/workflows/python-testing.yml @@ -10,7 +10,7 @@ on: branches: [main] jobs: - build: + ci-check: runs-on: ubuntu-latest strategy: fail-fast: false From e229694c3d9ad1b063c2715cb3fbdb5633c608c4 Mon Sep 17 00:00:00 2001 From: NowanIlfideme Date: Sun, 15 Jun 2025 17:33:10 +0200 Subject: [PATCH 5/6] Removed `--locked` to `uv sync` command. --- .github/workflows/python-publish.yml | 4 ++-- .github/workflows/python-testing.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 9b589dd..9b07839 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -28,7 +28,7 @@ jobs: cache-dependency-glob: "uv.lock" - name: Install the project - run: uv sync --locked --all-extras --dev + run: uv sync --all-extras --dev - name: Lint with ruff run: | @@ -57,7 +57,7 @@ jobs: - name: Install the project run: | - uv sync --locked --all-extras --dev + uv sync --all-extras - name: Publish the project to PyPI run: | diff --git a/.github/workflows/python-testing.yml b/.github/workflows/python-testing.yml index 768a872..49857b8 100644 --- a/.github/workflows/python-testing.yml +++ b/.github/workflows/python-testing.yml @@ -31,7 +31,7 @@ jobs: - name: Install the project - run: uv sync --locked --all-extras --dev + run: uv sync --all-extras --dev - name: Lint with ruff run: | From 8814bfcabbd90c2dd2660eb69a7927711b2320a7 Mon Sep 17 00:00:00 2001 From: NowanIlfideme Date: Sun, 15 Jun 2025 17:34:18 +0200 Subject: [PATCH 6/6] Ruff check :P --- .github/workflows/python-publish.yml | 2 +- .github/workflows/python-testing.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 9b07839..d975a57 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -32,7 +32,7 @@ jobs: - name: Lint with ruff run: | - uv run ruff + uv run ruff check - name: Test with pytest run: | diff --git a/.github/workflows/python-testing.yml b/.github/workflows/python-testing.yml index 49857b8..84d269b 100644 --- a/.github/workflows/python-testing.yml +++ b/.github/workflows/python-testing.yml @@ -35,7 +35,7 @@ jobs: - name: Lint with ruff run: | - uv run ruff + uv run ruff check - name: Test with pytest run: |