Skip to content

Commit ef8f915

Browse files
committed
feat: migrate to modern pyproject.toml with hatchling and update CI workflow
- Create comprehensive pyproject.toml replacing setup.cfg - Migrated all metadata (name, version, description, urls, etc.) - Set minimum Python version to 3.10 (dropping 3.8 support) - Added dev and test optional dependencies - Configured hatchling as build backend - Configured ruff for linting and formatting - Configured pytest with proper test paths - Update CI workflow to modern standard - Upgrade Python versions to 3.10 and 3.12 - Add system dependencies installation (portaudio19-dev, graphviz) - Use modern GitHub Actions (checkout@v4, setup-python@v5) - Replace axblack/pylint with ruff for formatting/linting - Add Windows validation job - Update publish job with modern actions - Add GitHub Pages publishing job - Verified local build works with hatchling - All 32 tests pass successfully
1 parent e338851 commit ef8f915

File tree

2 files changed

+234
-61
lines changed

2 files changed

+234
-61
lines changed

.github/workflows/ci.yml

Lines changed: 129 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,167 @@
1-
name: Continuous Integration
1+
name: Continuous Integration (Modern)
22
on: [push, pull_request]
3+
34
env:
45
PROJECT_NAME: stream2py
6+
57
jobs:
68
validation:
79
name: Validation
810
if: "!contains(github.event.head_commit.message, '[skip ci]')"
9-
runs-on: ubuntu-18.04
11+
runs-on: ubuntu-latest
1012
strategy:
1113
matrix:
12-
python-version: [3.8]
14+
python-version: ["3.10", "3.12"]
15+
1316
steps:
14-
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
15-
- uses: actions/checkout@v2
17+
- uses: actions/checkout@v4
1618

1719
- name: Set up Python ${{ matrix.python-version }}
18-
uses: actions/setup-python@v2
20+
uses: actions/setup-python@v5
1921
with:
2022
python-version: ${{ matrix.python-version }}
2123

22-
- name: Install dependencies
24+
# Install system dependencies required by stream2py
25+
- name: Install System Dependencies
2326
run: |
24-
python -m pip install --upgrade pip
25-
pip -q install axblack pytest pylint isee
26-
sudo apt-get -qq update
27-
sudo apt-get install -y portaudio19-dev python-pyaudio
28-
sudo apt-get install graphviz
29-
isee install-requires
30-
31-
- name: Format source code
32-
run: black --line-length=88 .
33-
34-
# Documentation on "enable" codes:
35-
# http://pylint.pycqa.org/en/latest/technical_reference/features.html#basic-checker-messages
36-
# C0114: missing-module-docstring
37-
# C0115: missing-class-docstring
38-
# C0116: missing-function-docstring
39-
- name: Validate docstrings
40-
run: pylint ./$PROJECT_NAME --ignore=tests,examples,scrap --disable=all --enable=C0114
41-
42-
- name: Test
43-
run: pytest -s --doctest-modules -v $PROJECT_NAME
27+
sudo apt-get update -qq
28+
sudo apt-get install -y portaudio19-dev graphviz
29+
30+
- name: Install Dependencies
31+
uses: i2mint/wads/actions/install-deps@master
32+
with:
33+
dependency-files: pyproject.toml
34+
extras: dev,test
35+
36+
- name: Format Source Code
37+
uses: i2mint/wads/actions/ruff-format@master
38+
with:
39+
line-length: 88
40+
target-path: .
41+
42+
- name: Lint Validation
43+
uses: i2mint/wads/actions/ruff-lint@master
44+
with:
45+
root-dir: ${{ env.PROJECT_NAME }}
46+
output-format: github
47+
# Ruff will read configuration from pyproject.toml
48+
49+
- name: Run Tests
50+
uses: i2mint/wads/actions/run-tests@master
51+
with:
52+
root-dir: ${{ env.PROJECT_NAME }}
53+
exclude: examples,scrap
54+
coverage: true
55+
pytest-args: -v --tb=short
56+
57+
windows-validation:
58+
name: Windows Tests (Informational)
59+
if: "!contains(github.event.head_commit.message, '[skip ci]')"
60+
runs-on: windows-latest
61+
continue-on-error: true # Don't fail the entire workflow if Windows tests fail
62+
63+
steps:
64+
- uses: actions/checkout@v4
65+
66+
- name: Set up Python 3.10
67+
uses: actions/setup-python@v5
68+
with:
69+
python-version: "3.10"
70+
71+
- name: Install Dependencies
72+
uses: i2mint/wads/actions/install-deps@master
73+
with:
74+
dependency-files: pyproject.toml
75+
extras: dev,test
76+
77+
- name: Run Windows Tests
78+
uses: i2mint/wads/actions/windows-tests@master
79+
with:
80+
root-dir: ${{ env.PROJECT_NAME }}
81+
exclude: examples,scrap
82+
pytest-args: -v --tb=short
83+
4484
publish:
4585
name: Publish
46-
if: "!contains(github.event.head_commit.message, '[skip ci]') && github.ref == 'refs/heads/master'"
86+
if: "!contains(github.event.head_commit.message, '[skip ci]') && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main')"
4787
needs: validation
48-
runs-on: ubuntu-18.04
88+
runs-on: ubuntu-latest
4989
strategy:
5090
matrix:
51-
python-version: [3.8]
91+
python-version: ["3.12"]
92+
5293
steps:
53-
- uses: actions/checkout@v2
94+
- uses: actions/checkout@v4
5495
with:
5596
fetch-depth: 0
56-
57-
- name: Configure Git
58-
run: |
59-
git config --global user.email "[email protected]"
60-
git config --global user.name "GitHub CI Runner"
97+
token: ${{ secrets.GITHUB_TOKEN }}
6198

6299
- name: Set up Python ${{ matrix.python-version }}
63-
uses: actions/setup-python@v2
100+
uses: actions/setup-python@v5
64101
with:
65102
python-version: ${{ matrix.python-version }}
66103

67-
- name: Install dependencies
104+
# Install system dependencies required by stream2py
105+
- name: Install System Dependencies
68106
run: |
69-
python -m pip install --upgrade pip
70-
pip -q install axblack twine epythet wads isee sphinx-rtd-theme
71-
sudo apt-get -qq update
72-
sudo apt-get install portaudio19-dev python-pyaudio
73-
isee install-requires
107+
sudo apt-get update -qq
108+
sudo apt-get install -y portaudio19-dev graphviz
74109
75-
- name: Format source code
76-
run: black --line-length=88 .
110+
- name: Format Source Code
111+
uses: i2mint/wads/actions/ruff-format@master
77112

78-
- name: Update version number
79-
run: |
80-
export VERSION=$(isee gen-semver)
81-
echo "VERSION=$VERSION" >> $GITHUB_ENV
82-
isee update-setup-cfg
113+
- name: Update Version Number
114+
id: version
115+
uses: i2mint/isee/actions/bump-version-number@master
83116

84-
- name: Generate Documentation
85-
run: isee generate-documentation
117+
- name: Build Distribution
118+
uses: i2mint/wads/actions/build-dist@master
119+
with:
120+
sdist: true
121+
wheel: true
86122

87-
- name: Package
88-
run: python setup.py sdist
123+
- name: Publish to PyPI
124+
uses: i2mint/wads/actions/pypi-upload@master
125+
with:
126+
pypi-username: ${{ secrets.PYPI_USERNAME }}
127+
pypi-password: ${{ secrets.PYPI_PASSWORD }}
128+
skip-existing: false
89129

90-
- name: Publish
91-
run: |
92-
twine upload dist/$PROJECT_NAME-$VERSION.tar.gz -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} --non-interactive --skip-existing --disable-progress-bar
93-
epythet make . github
130+
- name: Track Code Metrics
131+
uses: i2mint/umpyre/actions/track-metrics@master
132+
continue-on-error: true # Don't fail CI if metrics collection fails
133+
with:
134+
github-token: ${{ secrets.GITHUB_TOKEN }}
135+
config-path: .github/umpyre-config.yml # Optional: defaults to .umpyre.yml
94136

95-
- name: Push Changes
96-
run: pack check-in "**CI** Formatted code + Updated version number and documentation. [skip ci]" --auto-choose-default-action --bypass-docstring-validation --bypass-tests --bypass-code-formatting --verbose
137+
- name: Commit Changes
138+
uses: i2mint/wads/actions/git-commit@master
139+
with:
140+
commit-message: "**CI** Formatted code + Updated version to ${{ steps.version.outputs.version }} [skip ci]"
141+
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
142+
push: true
97143

98144
- name: Tag Repository
99-
run: isee tag-repo $VERSION
145+
uses: i2mint/wads/actions/git-tag@master
146+
with:
147+
tag: ${{ steps.version.outputs.version }}
148+
message: "Release version ${{ steps.version.outputs.version }}"
149+
push: true
150+
151+
github-pages:
152+
name: Publish GitHub Pages
153+
154+
permissions:
155+
contents: write
156+
pages: write
157+
id-token: write
158+
159+
if: "!contains(github.event.head_commit.message, '[skip ci]') && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)"
160+
needs: publish
161+
runs-on: ubuntu-latest
162+
163+
steps:
164+
- uses: i2mint/epythet/actions/publish-github-pages@master
165+
with:
166+
github-token: ${{ secrets.GITHUB_TOKEN }}
167+
ignore: "tests/,scrap/,examples/"

pyproject.toml

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "stream2py"
7+
version = "1.0.42"
8+
description = "Bring data streams to python with ease"
9+
readme = "README.md"
10+
requires-python = ">=3.10"
11+
license = {text = "MIT"}
12+
keywords = ["data stream"]
13+
authors = [
14+
{name = "OtoSense"}
15+
]
16+
dependencies = []
17+
18+
[project.urls]
19+
Homepage = "https://github.com/i2mint/stream2py"
20+
Repository = "https://github.com/i2mint/stream2py"
21+
Documentation = "https://i2mint.github.io/stream2py/index.html"
22+
23+
[project.optional-dependencies]
24+
dev = [
25+
"pytest>=7.0",
26+
"pytest-cov>=4.0",
27+
"ruff>=0.1.0",
28+
]
29+
test = [
30+
"pytest>=7.0",
31+
"pytest-cov>=4.0",
32+
]
33+
docs = [
34+
"sphinx>=6.0",
35+
"sphinx-rtd-theme>=1.0",
36+
]
37+
38+
[tool.hatch.build.targets.wheel]
39+
packages = ["stream2py"]
40+
41+
[tool.hatch.build.targets.sdist]
42+
include = [
43+
"/stream2py",
44+
"/README.md",
45+
]
46+
47+
[tool.ruff]
48+
line-length = 88
49+
target-version = "py310"
50+
exclude = [
51+
"**/*.ipynb",
52+
".git",
53+
".venv",
54+
"build",
55+
"dist",
56+
"tests",
57+
"examples",
58+
"scrap",
59+
]
60+
61+
[tool.ruff.lint]
62+
# Select the rules you want to enable.
63+
# It's best practice to enable whole rule families for consistency.
64+
# See https://docs.astral.sh/ruff/rules/
65+
select = [
66+
# Docstring Rule (Your request)
67+
"D100", # D100: Missing module docstring (Required)
68+
69+
# Core Error-Catching (always good to have)
70+
# "F", # F: Pyflakes - Logical errors, unused imports (Highly recommended)
71+
# "E", # E: Pycodestyle Errors - Basic style errors (Highly recommended)
72+
# "B", # B: Flake8-Bugbear - Common bug patterns (Highly recommended)
73+
74+
# Clean-up / Modernization (Highly fixable and low-annoyance)
75+
# "UP", # UP: Pyupgrade - Suggestions for modern Python syntax
76+
# "I", # I: isort - Import sorting (If you don't use a separate tool like Black/Ruff formatter)
77+
]
78+
79+
# Ignore specific rules that conflict or are too annoying
80+
ignore = [
81+
# Docstring Ignore (Your request)
82+
"D203", # D203: 1 blank line before class docstring (Conflict with other docstring styles)
83+
84+
# Common Ignores (Enable and uncomment if you find them annoying)
85+
"E501", # E501: Line too long (If you use an auto-formatter like Black/Ruff format, ignore this)
86+
"B905", # B905: `zip()` without an explicit `strict=` parameter
87+
]
88+
89+
# Configure settings for rule families
90+
[tool.ruff.lint.pydocstyle]
91+
convention = "google" # or "numpy" or "pep257"
92+
93+
[tool.ruff.lint.per-file-ignores]
94+
"tests/*" = ["D"] # don't enforce docstrings in tests
95+
"examples/*" = ["D"]
96+
"scrap/*" = ["D"]
97+
98+
[tool.pytest.ini_options]
99+
minversion = "6.0"
100+
testpaths = ["stream2py/tests"]
101+
doctest_optionflags = ["NORMALIZE_WHITESPACE", "ELLIPSIS"]
102+
addopts = [
103+
"--doctest-modules",
104+
"-v",
105+
]

0 commit comments

Comments
 (0)