Simple library to keep useful Python utilities in one place.
Project description
hv-utils
Typed utility library for consolidating reusable Python helpers. The project is in early alpha; the current public
surface includes the cron expression parser (parse_cron) and expiration helpers (Expiration, ExpiresIn,
ExpiresAfter, ExpiresAtTS, ExpiresAtDT).
Requirements
- Use: Python 3.12+; install from PyPI with pip/uv/Poetry (see install commands below); no external runtime dependencies.
Install
- pip:
pip install hv-utils - uv:
uv add hv-utils - Poetry:
poetry add hv-utils
Quick start
- Install:
pip install hv-utils(or add an extra such aspip install hv-utils[cron]). - Use:
from datetime import UTC, datetime, timedelta
from hv_utils.cron import cron_matches, parse_cron
from hv_utils.expiration import ExpiresAfter
schedule = parse_cron("*/15 0-12/6 1,15 1-3 MON-FRI")
print(schedule.minute) # (0, 15, 30, 45)
print(cron_matches(schedule, datetime(2025, 1, 13, 12, 0, tzinfo=UTC)))
expires = ExpiresAfter(ttl=timedelta(hours=1), since=datetime.now(tz=UTC))
print(expires.as_ttl()) # Remaining time before expiration, clamped to zero
Cron utility
- Parse:
hv_utils.cron.parse_cron(expression: str) -> CronSchedule— expands a 5-field cron string into concrete minute, hour, day-of-month, month, and day-of-week tuples. Supports literals, ranges, steps (*/n), comma lists, and case-insensitive month/day names. Day-of-week treats both0and7as Sunday; invalid input raisesValueErrorwith a consistent message. - Match:
hv_utils.cron.cron_matches(expression: str | CronSchedule, when: datetime) -> bool— checks whether a datetime satisfies a schedule. Day-of-month and day-of-week use cron OR semantics: if both are restricted, a match occurs when either field matches (all other fields must also match). If one is a wildcard, only the other is considered. - Schedule helpers:
CronSchedule.from_exp(expr: str)— convenience constructor aroundparse_cron.CronSchedule.matches(dt: datetime) -> bool— instance wrapper overcron_matches.CronSchedule.next(start: datetime, *, inclusive: bool = False, max_lookahead_days: int = 366) -> datetime— returns the next occurrence afterstart, optionally includingstart, bounded bymax_lookahead_days.
CronSchedule.iter(start: datetime, *, inclusive: bool = False, max_lookahead_days: int = 366) -> Iterable[datetime]— yields successive matching datetimes; callers should consume responsibly to avoid unbounded iteration.
Expiration utilities
- Interfaces:
Expirationstandardizes conversion to timestamp (as_timestamp()), datetime (as_datetime(tz=UTC)), and remaining TTL (as_ttl()). - Relative TTL:
ExpiresIncomputes expiration relative to the call time; TTL is constant because the target is always "now + ttl". - Anchored TTL:
ExpiresAfteradds a TTL to a timezone-aware start datetime and clamps negative TTL to zero. - Absolute:
ExpiresAtTStargets a Unix timestamp;ExpiresAtDTtargets a timezone-aware datetime. Both clamp expired TTLs to zero.
Development requirements
- Python 3.12+ for development; optionally install 3.13/3.14 to run the full test matrix.
- uv for dependency management; sync dev tools via
uv sync --group dev. - Pre-commit hooks available; install with
pre-commit install.
How we work
- Functional-first utilities; keep state to a minimum.
- Standard library only at runtime. If an optional dependency is unavoidable, add an extra in
pyproject.toml, guard the import withtry/except ImportError, and raise a friendly install hint. - Absolute imports only. Expose public helpers from
src/hv_utils/__init__.py. - Always type everything and keep
mypy --strictgreen. - TDD over heroics: write or update tests before implementing behavior, cover edge cases, and keep functions small and composable.
- Follow
ruff/PEP 8 style (line length 120).
Common commands
- Format:
uv run ruff format . - Lint (autofix):
uv run ruff check --fix . - Type-check:
uv run mypy src tests - Tests (current Python):
uv run pytest - Tests on a specific interpreter:
uv run --python 3.13 pytest - Full matrix (requires those interpreters installed):
uv run --python 3.12 pytestuv run --python 3.13 pytestuv run --python 3.14 pytest
Pre-commit
- Install hooks:
pre-commit install(uses your machine-level pre-commit) - Run all hooks manually:
pre-commit run --all-files - Hooks auto-add the BSD-3 header (via
python -m tools.copyright_header), then run the same uv-powered format, lint, type-check, and test commands listed above.
Contributing
- Keep PRs small and focused on one utility or fix.
- Add tests, docstrings, and
__init__exports alongside new utilities. - Run format, lint, mypy, and pytest before opening a PR; for compatibility-sensitive changes, run the full matrix.
- Note: uv commands may need escalated permission in some environments. I will ask for escalation before running
uvso tasks can proceed. The uv cache directory is already configured inpyproject.toml; no need to setUV_CACHE_DIRmanually.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hv_utils-0.0.2.post1.tar.gz.
File metadata
- Download URL: hv_utils-0.0.2.post1.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e5b807b5aa2ab455428bd0924e41d52d0373ec49ccc1dd40cd420d2ffa49fb6
|
|
| MD5 |
715c89418b5cd9c6d6c3bae7254fb64f
|
|
| BLAKE2b-256 |
110364b74ed45594d887f8f3dc00293410184def2e2fd8859f1a408db674959f
|
File details
Details for the file hv_utils-0.0.2.post1-py3-none-any.whl.
File metadata
- Download URL: hv_utils-0.0.2.post1-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fdd43ac27dea23a5dc7d9f1a64b3b175b8fd5d3dadabcb764ea4394dd334088
|
|
| MD5 |
42046c76def66bd743d423ab4720c9ef
|
|
| BLAKE2b-256 |
1b15547b09d90ef877a3ac4b3144b46bfb5d98ef20b37e3d4bf2cb282bb2b21b
|