Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .bumpversion.cfg

This file was deleted.

10 changes: 5 additions & 5 deletions .github/workflows/deploy_mkdocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.11"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip3 install -e .[doc]

run: uv sync --group doc

- name: Build the MkDocs site
run: mkdocs build
run: uv run mkdocs build

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
Expand Down
14 changes: 5 additions & 9 deletions .github/workflows/deploy_pypi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel build

- name: Build the package
run: |
python -m build

- name: Build package
run: uv build
Comment thread
coatet marked this conversation as resolved.
Outdated

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/pull_request_workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ jobs:
- name: Check out repository
uses: actions/checkout@v3

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
Expand Down
3 changes: 0 additions & 3 deletions .isort.cfg

This file was deleted.

15 changes: 2 additions & 13 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,12 @@ repos:
- id: check-yaml
- id: check-toml
- id: debug-statements

- repo: https://github.com/psf/black
rev: 24.10.0
hooks:
- id: black

- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
args: ["--profile", "black"]
Comment thread
coatet marked this conversation as resolved.

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.1
hooks:
- id: ruff-format
- id: ruff
args: ["--config", ".ruff.toml"]
args: ["--fix"]

- repo: https://github.com/gitleaks/gitleaks
rev: v8.23.1
Expand Down
43 changes: 0 additions & 43 deletions .ruff.toml

This file was deleted.

15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@ and this project adheres to [semantic versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.17.0] - 2026-05-08

### Added

### Changed

- Switched build system from setuptools to uv with hatchling backend.
- Consolidated `setup.cfg`, `setup.py`, `.ruff.toml`, `.isort.cfg`, and `.bumpversion.cfg` into a single `pyproject.toml`.
- Updated all GitHub Actions workflows (`deploy_pypi.yaml`, `pull_request_workflow.yaml`, `deploy_mkdocs.yaml`) to use uv.
- Replaced black and isort pre-commit hooks with ruff-format.
- Updated `contribution_guide.md` and `branch_and_deploy_guide.md` to reflect uv-based workflow.
- Bumped `ons-mkdocs-theme` minimum version from `>=1.1.3` to `>=1.2.4` and added Python version markers to doc dependencies.
### Deprecated

### Fixed

### Removed
- Removed `setup.cfg`, `setup.py`, `.bumpversion.cfg`, `.ruff.toml`, and `.isort.cfg` (consolidated into `pyproject.toml`).
- Removed `bump2version`, `black`, and `isort` from dev dependencies (replaced by uv version management and ruff).

## [0.16.1] - 2026-02-19

Expand Down
136 changes: 134 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,135 @@
[project]
name = "rdsa-utils"
dynamic = ["version"]
description = "A suite of PySpark, Pandas, and general pipeline utils for Reproducible Data Science and Analysis (RDSA) projects."
readme = "README.md"
license = "MIT"
requires-python = ">=3.8, <3.14"
authors = [
{ name = "Reproducible Data Science & Analysis, ONS", email = "RDSA.Support@ons.gov.uk" },
]
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"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",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]
dependencies = [
"cloudpathlib[gs]>=0.15.1",
"humanfriendly>=9.1",
"more-itertools>=9.0.0",
"pandas",
"pydantic>=2.6.2",
"pyyaml>=6.0.1",
"tomli>=2.0.1",
"google-cloud-bigquery>=3.17.2",
"google-cloud-storage>=2.14.0",
"boto3>=1.34.103",
"codetiming",
"standard-distutils; python_version >= '3.12'",
"xlsxwriter",
"openpyxl",
"papermill",
"nbconvert",
"matplotlib",
]

[project.urls]
Homepage = "https://github.com/ONSdigital/rdsa-utils"
Documentation = "https://onsdigital.github.io/rdsa-utils/"
Repository = "https://github.com/ONSdigital/rdsa-utils"

[dependency-groups]
dev = [
"pre-commit>=2.6.0",
"ruff>=0.9.1",
"chispa>=0.9.2",
"coverage[toml]>=7.1.0",
"pytest>=7.1.0, <8.0.0",
"pytest-cov>=4.0.0",
"pytest-lazy-fixture>=0.6.0",
"pytest-mock>=3.8.0",
"pyspark==3.5.1",
"moto>=5.0.7",
"freezegun",
]
doc = [
"ons-mkdocs-theme>=1.2.4; python_version >= '3.10'",
"mkdocstrings[python]>=0.22.0; python_version >= '3.10'",
"mkdocs-git-revision-date-localized-plugin>=1.2.1; python_version >= '3.10'",
"mkdocs-jupyter>=0.24.3; python_version >= '3.10'",
"mkdocs-mermaid2-plugin>=1.1.1; python_version >= '3.10'",
]

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"

[tool.hatch.version]
path = "rdsa_utils/__init__.py"
pattern = '__version__ = "(?P<version>[^"]+)"'

[tool.hatch.build.targets.wheel]
packages = ["rdsa_utils"]

[tool.hatch.build.targets.sdist]
include = [
"rdsa_utils/**",
"README.md",
"LICENSE",
"pyproject.toml",
]

# ---------- Ruff (linting + formatting) ----------
# Replaces .ruff.toml, black config, and .isort.cfg

[tool.ruff]
line-length = 88

[tool.ruff.lint]
select = [
"A",
"B",
"C4",
"COM",
"D",
"DTZ",
"E",
"EM",
"F",
"I", # isort rules — replaces standalone isort
"ISC",
"N",
"NPY",
"PD",
"PT",
"PTH",
"Q",
"T10",
"T20",
"W",
"YTT",
]
ignore = ["N812", "E712", "E721", "COM812"]
Comment thread
humnabaa marked this conversation as resolved.
Outdated

[tool.ruff.lint.pydocstyle]
convention = "numpy"

[tool.ruff.lint.flake8-quotes]
inline-quotes = "double"

[tool.ruff.lint.isort]
known-first-party = ["rdsa_utils"]

[tool.ruff.lint.per-file-ignores]
"*/__init__.py" = ["D104"]
"*/" = ["B006", "PTH123", "B008"]
"tests/*" = ["ANN", "D100", "E501", "F403", "F405", "PT011", "B017", "D205"]
"rdsa_utils/logging.py" = ["A005"]
"rdsa_utils/typing.py" = ["A005"]
"rdsa_utils/helpers/pyspark_log_parser/parser.py" = ["A005"]
5 changes: 2 additions & 3 deletions rdsa_utils/cdp/helpers/s3_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,7 @@ def download_folder(
if not target.parent.exists():
target.parent.mkdir(parents=True)
client.download_file(bucket_name, obj["Key"], str(target))
logger.info(f'Downloaded {obj["Key"]} to {target}')
logger.info(f"Downloaded {obj['Key']} to {target}")
return True
except client.exceptions.ClientError as e:
logger.error(f"Failed to download folder: {str(e)}")
Expand Down Expand Up @@ -1207,8 +1207,7 @@ def delete_folder(
return True
except client.exceptions.ClientError as e:
logger.error(
f"Failed to delete folder {folder_path} "
f"in bucket {bucket_name}: {str(e)}",
f"Failed to delete folder {folder_path} in bucket {bucket_name}: {str(e)}",
)
return False

Expand Down
6 changes: 2 additions & 4 deletions rdsa_utils/cdp/io/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,7 @@ def save_csv_to_hdfs(

if not overwrite and file_exists(destination_path):
error_msg = (
f"File '{destination_path}' already exists "
"and overwrite is set to False."
f"File '{destination_path}' already exists and overwrite is set to False."
)
raise IOError(error_msg)

Expand Down Expand Up @@ -517,8 +516,7 @@ def save_csv_to_s3(

if not overwrite and file_exists(s3_client, bucket_name, destination_path):
error_msg = (
f"File '{destination_path}' already exists "
"and overwrite is set to False."
f"File '{destination_path}' already exists and overwrite is set to False."
)
raise IOError(error_msg)

Expand Down
3 changes: 1 addition & 2 deletions rdsa_utils/gcp/helpers/gcp_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,6 @@ def delete_folder(
return True
except Exception as e:
logger.error(
f"Failed to delete folder {folder_path} "
f"in bucket {bucket_name}: {str(e)}",
f"Failed to delete folder {folder_path} in bucket {bucket_name}: {str(e)}",
)
return False
2 changes: 1 addition & 1 deletion rdsa_utils/gcp/io/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def read_table(
if list_cols_not_in_table_cols:
message = f"""
Columns: {list_cols_not_in_table_cols} are not in dateset.
Choose columns from: {', '.join(table_cols)}.
Choose columns from: {", ".join(table_cols)}.
"""
logger.error(message)
raise ColumnNotInDataframeError(message)
Expand Down
10 changes: 2 additions & 8 deletions rdsa_utils/helpers/pyspark.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,18 +184,12 @@ def wrapper(*args, **kwargs):
varnames = func.__code__.co_varnames
if args:
args = [
(
_convert_to_spark_col(arg)
if varnames[i] not in exclude
else arg
) # noqa: E501
(_convert_to_spark_col(arg) if varnames[i] not in exclude else arg) # noqa: E501
for i, arg in enumerate(args)
]
if kwargs:
kwargs = {
k: (
_convert_to_spark_col(kwarg) if k not in exclude else kwarg
) # noqa: E501
k: (_convert_to_spark_col(kwarg) if k not in exclude else kwarg) # noqa: E501
for k, kwarg in kwargs.items()
}
return func(*args, **kwargs)
Expand Down
Loading
Loading