Skip to content

Commit 279a706

Browse files
Merge pull request #62 from nickmaccarthy/feat/modernize
feat: 2026 modernize
2 parents 231b82c + 75280ea commit 279a706

26 files changed

Lines changed: 2676 additions & 741 deletions

.dockerignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.git
2+
.github
3+
.mypy_cache
4+
.pytest_cache
5+
.ruff_cache
6+
.venv
7+
__pycache__
8+
build
9+
dist

.github/workflows/ci.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
11+
jobs:
12+
test:
13+
runs-on: ubuntu-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Set up uv
23+
uses: astral-sh/setup-uv@v6
24+
with:
25+
python-version: ${{ matrix.python-version }}
26+
27+
- name: Install dependencies
28+
run: uv sync --group dev
29+
30+
- name: Run tests
31+
run: uv run pytest
32+
33+
- name: Lint
34+
run: uv run ruff check .
35+
36+
- name: Type-check
37+
run: uv run mypy
38+
39+
- name: Build distribution artifacts
40+
run: uv build
41+
42+
- name: Validate built package
43+
run: uv run twine check dist/*
44+
45+
- name: Verify install from wheel
46+
run: |
47+
uv venv .venv-install
48+
uv pip install --python .venv-install/bin/python dist/*.whl
49+
.venv-install/bin/python -c "from datemath import datemath; print(datemath('now-1d'))"
50+
.venv-install/bin/python -c "import datemath; print(datemath.__version__)"

.github/workflows/release.yaml

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
name: Release Packages
2+
23
on:
34
release:
4-
types:
5-
- released
5+
types:
6+
- published
7+
68
jobs:
7-
release-to-pypi:
8-
runs-on: ubuntu-20.04
9+
publish:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
id-token: write
13+
914
steps:
10-
- uses: actions/checkout@v2
11-
- name: install requirements for python3
12-
run: pip3 install -r requirements.txt
13-
- name: package and upload python3
14-
env:
15-
TWINE_USERNAME: __token__
16-
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
17-
PYTHON_DATEMATH_VERSION: ${{ github.event.release.tag_name }}
18-
run: |
19-
python3 setup.py sdist bdist_wheel
20-
twine upload dist/*
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up uv
18+
uses: astral-sh/setup-uv@v6
19+
with:
20+
python-version: "3.14"
21+
22+
- name: Build artifacts
23+
run: uv build
24+
25+
- name: Validate distribution metadata
26+
run: uv run --with twine twine check dist/*
27+
28+
- name: Publish to PyPI
29+
uses: pypa/gh-action-pypi-publish@release/v1
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Semantic Release
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
release:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
20+
- name: Set up uv
21+
uses: astral-sh/setup-uv@v6
22+
with:
23+
python-version: "3.14"
24+
25+
- name: Install development dependencies
26+
run: uv sync --group dev
27+
28+
- name: Create release
29+
env:
30+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
run: uv run semantic-release -c .releaserc.toml version

.github/workflows/tests.yaml

Lines changed: 0 additions & 27 deletions
This file was deleted.

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,3 @@ __pycache__/
1515
# due to using tox and pytest
1616
.tox
1717
.cache
18-

.pre-commit-config.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.2.0
4+
hooks:
5+
- id: check-merge-conflict
6+
- id: check-toml
7+
- id: check-yaml
8+
- id: end-of-file-fixer
9+
- id: trailing-whitespace
10+
11+
- repo: https://github.com/astral-sh/ruff-pre-commit
12+
rev: v0.14.5
13+
hooks:
14+
- id: ruff-check
15+
args: [--fix]
16+
- id: ruff-format
17+
18+
- repo: local
19+
hooks:
20+
- id: mypy
21+
name: mypy
22+
entry: uv run mypy
23+
language: system
24+
pass_filenames: false
25+
stages: [pre-push]
26+
27+
- id: pytest
28+
name: pytest
29+
entry: uv run pytest
30+
language: system
31+
pass_filenames: false
32+
stages: [pre-push]

.releaserc.toml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[semantic_release]
2+
version_variables = ["datemath/_version.py:__version__"]
3+
commit_message = "chore(release): {version} [skip ci]"
4+
commit_parser = "conventional"
5+
major_on_zero = false
6+
tag_format = "v{version}"
7+
8+
[semantic_release.branches.main]
9+
match = "(main|master)"
10+
prerelease = false
11+
prerelease_token = "rc"
12+
13+
[semantic_release.changelog]
14+
mode = "update"
15+
16+
[semantic_release.changelog.default_templates]
17+
changelog_file = "CHANGELOG.md"
18+
output_format = "md"
19+
mask_initial_release = false
20+
21+
[semantic_release.commit_author]
22+
env = "GIT_COMMIT_AUTHOR"
23+
default = "github-actions <actions@github.com>"
24+
25+
[semantic_release.commit_parser_options]
26+
minor_tags = ["feat"]
27+
patch_tags = ["fix", "perf"]
28+
other_allowed_tags = ["build", "chore", "ci", "docs", "refactor", "style", "test"]
29+
allowed_tags = ["feat", "fix", "perf", "build", "chore", "ci", "docs", "refactor", "style", "test"]
30+
default_bump_level = 0
31+
parse_squash_commits = true
32+
ignore_merge_commits = true
33+
34+
[semantic_release.remote]
35+
name = "origin"
36+
type = "github"
37+
38+
[semantic_release.publish]
39+
dist_glob_patterns = ["dist/*"]
40+
upload_to_vcs_release = true

CHANGELOG.md

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
### changed
10+
- Modernized packaging and developer workflow around `pyproject.toml`, `uv`, `pytest`, `ruff`, and `mypy`
11+
- Updated CI and release automation to use the new build and verification flow
12+
- Replaced the legacy single-file `unittest` suite with a `pytest` test layout while preserving the existing behavior coverage
13+
- Updated the Docker image to a current Python base image and removed the old `requirements.txt` and `setup.py` install path
14+
15+
### compatibility
16+
- Support remains Python `3.10+`
17+
- During the modernization pass, the floor was briefly evaluated at `3.11+`, but it was set to `3.10+` instead because the library and tooling still work cleanly there and it keeps a broader install base without adding meaningful maintenance overhead
18+
- Previous published support before this change was Python `3.8+`; this update intentionally drops `3.8` and `3.9` to align the project with a more current 2026 baseline while keeping `3.10` available
19+
- `zoneinfo` is now used in tests instead of `pytz`, but this does not require raising the runtime floor beyond Python `3.10`
20+
821
## [3.0.3] - 2024-09-12
922
Please use 3.0.3 going forward! 3.0.2 has a breaking bug.
1023

@@ -16,7 +29,7 @@ Please use 3.0.3 going forward! 3.0.2 has a breaking bug.
1629
## [3.0.2] - 2024-09-11
1730
### added
1831
- Feat: Complete typing with strict type-checking [#43](https://github.com/nickmaccarthy/python-datemath/pull/43) Thank you @Avasam!
19-
- Feat: Added `__version__` to verify the version of the module.
32+
- Feat: Added `__version__` to verify the version of the module.
2033
- Feat: Added Dockerfile and relevant verify.py to help with local development and testing
2134

2235
### chore
@@ -31,15 +44,15 @@ Please use 3.0.3 going forward! 3.0.2 has a breaking bug.
3144
- Fix: move more pypi configurations to setup.cfg and out of setup.py
3245

3346

34-
## [3.0.1] - 2024-08-23
47+
## [3.0.1] - 2024-08-23
3548
### fixed
3649
- Fix: Race condition in timezone tests: https://github.com/nickmaccarthy/python-datemath/issues/36
3750
- Fix: Updated arrow version: https://github.com/nickmaccarthy/python-datemath/issues/32
38-
- Fix: mypy type hint checking in tests: https://github.com/nickmaccarthy/python-datemath/issues/31
51+
- Fix: mypy type hint checking in tests: https://github.com/nickmaccarthy/python-datemath/issues/31
3952
- Fix: SyntaxWarning: invalid escape sequence in `re.match()`: https://github.com/nickmaccarthy/python-datemath/pull/39
4053
- Fix: Licence Classifier: https://github.com/nickmaccarthy/python-datemath/pull/34
4154
- Fix: Bump certifi to latest: https://github.com/nickmaccarthy/python-datemath/pull/38
42-
### added
55+
### added
4356
- Feat: Typehint support: https://github.com/nickmaccarthy/python-datemath/issues/31
4457
- Feat: Renamed CHANGELOG.md to keepachangelog.org format
4558

@@ -50,13 +63,13 @@ Please use 3.0.3 going forward! 3.0.2 has a breaking bug.
5063
- python 2.7 support. Python 3.8+ will only be supported going forward
5164

5265
## [1.5.5] - 2021-04-26
53-
### fixed
66+
### fixed
5467
- fix: [Issue #28](https://github.com/nickmaccarthy/python-datemath/issues/28)
5568
* `datemath()` object now returns the expected `datetime` object instead of an `Arrow` object
5669
* added tests to catch invalid object types of helpers
5770

5871
## [1.5.4] - 2021-04-20
59-
### Unused
72+
### Unused
6073
- skipped due to name conflict on pypi, all changes in this are from `1.5.3`
6174

6275
## [1.5.3] - 2021-04-16
@@ -72,7 +85,7 @@ Please use 3.0.3 going forward! 3.0.2 has a breaking bug.
7285
### fixed
7386
- FIX: [Issue #15](https://github.com/nickmaccarthy/python-datemath/issues/15) - Fixed issue with parser finding invalid timeunits and throwing correct errors
7487
### added
75-
- Feat: [Issue #16](https://github.com/nickmaccarthy/python-datemath/issues/16) - Added support for parser to accecpt a epoch/unix timestamp but throw an error on epoch milli's since arrow can't support that.
88+
- Feat: [Issue #16](https://github.com/nickmaccarthy/python-datemath/issues/16) - Added support for parser to accecpt a epoch/unix timestamp but throw an error on epoch milli's since arrow can't support that.
7689

7790
## [1.5.0] - 2019-11-09
7891

@@ -84,7 +97,7 @@ Please use 3.0.3 going forward! 3.0.2 has a breaking bug.
8497

8598
** PLEASE DO NOT USE THIS VERSION, use `1.5.0+` instead. This may not compile on your system due to a missing VERSION.txt which was fixed in `1.5.0+` **
8699

87-
### fixed
100+
### fixed
88101
- [FIX] [Issue #9](https://github.com/nickmaccarthy/python-datemath/issues/9) && [Issue #8](https://github.com/nickmaccarthy/python-datemath/issues/8) - Fixing deprecated arrow `replace()` function with `shift()`.
89102
- [FIX] Arrow upgrade to `0.15.2` to fix the above mentioned issues
90103
- [FIX] Modifed `tests.py` to account for the timestamp change (tz is now `+0000`, instead of `-0000`)
@@ -101,7 +114,7 @@ Please use 3.0.3 going forward! 3.0.2 has a breaking bug.
101114
* skipped due to name conflict on pypi, all changes are in `1.4.9`
102115

103116
## [1.4.7] - 2017-11-10
104-
### fixed
117+
### fixed
105118
- [FIX] Fixed timezone for date strings: [Issue #6](https://github.com/nickmaccarthy/python-datemath/issues/6)
106119

107120
## [1.4.5] - 2017-03-21
@@ -114,12 +127,12 @@ Please use 3.0.3 going forward! 3.0.2 has a breaking bug.
114127
<Arrow [2016-01-01T23:59:00+00:00]>
115128
>>> dm('now/d')
116129
<Arrow [2016-01-01T00:00:00+00:00]>
117-
```
130+
```
118131

119132
## [1.4.4] - 2016-12-28
120133
### fixed
121134
- [FIX] Fixed bug with expression logic and rounding: https://github.com/nickmaccarthy/python-datemath/pull/2
122135

123136
## [1.4.3] - 2016-03-31
124-
### added
125-
[NEW] Floats are now supported for days, hours, and seconds units. Example ```now-2.5d```, ```now-3.2h```. Any other unit other than days, hours, or seconds that is a float will be converted to an int and floored due to the datetime() module not being able to handle them.
137+
### added
138+
[NEW] Floats are now supported for days, hours, and seconds units. Example ```now-2.5d```, ```now-3.2h```. Any other unit other than days, hours, or seconds that is a float will be converted to an int and floored due to the datetime() module not being able to handle them.

Dockerfile

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
# Use an official Python runtime as the base image
2-
FROM python:3.9
1+
FROM python:3.14-slim
32

4-
# Set the working directory in the container
5-
WORKDIR /app
3+
ENV PYTHONDONTWRITEBYTECODE=1 \
4+
PYTHONUNBUFFERED=1 \
5+
PIP_NO_CACHE_DIR=1
66

7-
# Copy the contents of your project to the working directory
8-
COPY . .
7+
WORKDIR /app
98

10-
# Install the required dependencies
11-
RUN pip install -r requirements.txt
9+
COPY pyproject.toml uv.lock README.md LICENSE ./
10+
COPY datemath ./datemath
11+
COPY tests ./tests
12+
COPY verify.py ./
1213

13-
# Run setup.py to install your module
14-
RUN python3 setup.py install
14+
RUN pip install --upgrade pip \
15+
&& pip install uv \
16+
&& uv sync --group dev --frozen
1517

16-
# Run your tests to ensure everything works as expected
17-
RUN python3 -m unittest discover
18+
RUN uv run pytest
1819

19-
# Set the entrypoint command to run your module
20-
CMD ["python3", "verify.py"]
20+
CMD ["uv", "run", "python", "verify.py"]

0 commit comments

Comments
 (0)