Skip to content

bizdays 2.0.0: v2 integration (WIL-154 go/no-go) - #68

Merged
wilsonfreitas merged 172 commits into
masterfrom
feature/typing
Nov 8, 2026
Merged

wilsonfreitas merged 172 commits into
masterfrom
feature/typing

Conversation

@wilsonfreitas

@wilsonfreitas wilsonfreitas commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

What this is

This PR merges feature/typing into master. It is bizdays 2.0.0: a new Calendar built on NumPy, with every method vectorized, a frozen public API, and a release workflow with trusted publishing.

This PR is the WIL-154 go/no-go review target. Do not merge it by hand. WIL-157 merges it, after Wilson posts GO on WIL-154 and gives a separate go-ahead for the merge.

  • Head to release (H): cc1868bad2978ab0fb13d8306081b853c2cc943e
  • Release candidate: v2.0.0rc3 (commit 458ee3f, parent H; it only changes the version to 2.0.0rc3 in pyproject.toml and uv.lock)
  • PR WIL-146: migration guide baseline is 1.0.20 #93 (after the first go/no-go): the migration guide compares with 1.0.20, and the CHANGELOG has the dated 1.0.20 entry. Docs and CHANGELOG only; the wheel is byte-identical to rc2, and the sdist differs only by CHANGELOG.md. rc3 re-validated the new head.
  • origin/master (2d9051c) is an ancestor of H: 0 commits behind, 170 ahead.

Breaking changes

2.0.0 breaks the 1.x API. The full list, with one "how to migrate" entry per change, is in docs/source/migration.rst and in the 2.0.0 section of CHANGELOG.md. The main ones:

  • Python 3.10 to 3.14; numpy>=1.24, pandas>=2 (pandas 3 tested).
  • Calendar providers are optional extras: bizdays[pmc], bizdays[xcal], bizdays[work].
  • Only three top-level names: Calendar, list_calendars, DateOutOfRange. get_option/set_option, the pandas/ISO modes and cal.vec are gone.
  • Results are NumPy values (datetime64, float64, bool_, arrays); missing values are NaN/NaT.
  • Calendar.load() takes keywords only (name= or filename=) and reads only JSON calendar files.
  • Strict input: dates as YYYY-MM-DD; whole-number counts; equal vector lengths (or length 1).
  • Any input or result outside the calendar range raises DateOutOfRange (now a ValueError).
  • getdate(expr, ref) replaces getdate(expr, year, month) and follows the R bizdays grammar.

API inventory

Public names: Calendar, list_calendars, DateOutOfRange. Reference: docs/source/api.rst.

Group Calendar members
Build Calendar(...), Calendar.load(name=... | filename=...)
Attributes name, holidays, weekdays, startdate, enddate, financial
Tests isbizday, inrange
Counts bizdays, diff, getbizdays
Moves offset, following, preceding, modified_following, modified_preceding, adjust_next, adjust_previous
Sequences and dates seq, getdate

DateOutOfRange is a ValueError and has positions (every element out of range). list_calendars() lists the packaged calendars (ANBIMA, B3, Actual) and the provider calendars (PMC/, XCAL/, WORK/).

Linear issues

Milestone "python-bizdays 2.0.0". All issues are Done except WIL-154 (this review), and WIL-157 and WIL-156, which by design run after Wilson's GO.

Issue Title PR into feature/typing
WIL-139 Finalize and freeze the v2 public API contract #70
WIL-149 Timezone-aware and invalid date-input behaviour #71
WIL-144 Vector recycling and empty-input semantics #72
WIL-140 DateIndex boundary failures and out-of-range offsets #73
WIL-226 Non-financial bizdays count when both ends are non-business days #74
WIL-227 getdate parity with R #75
WIL-138 Calendar.getbizdays for v2 #76
WIL-141 Reconcile feature/typing with master merge commit a3229b1
WIL-229 Project B3 holidays for 2027-2099, calendar-coverage test #77
WIL-150 2.0.0 metadata and clean release artifacts #79
WIL-143 Performance and memory baselines #80
WIL-148 Static typing metadata (py.typed, overloads) #81
WIL-151 CI gates and supported Python versions #69, #82
WIL-152 Release workflow with TestPyPI/PyPI trusted publishing #83
WIL-142 Calendar data and range contracts #84
WIL-145 v1-to-v2 behaviour matrix #85
WIL-146 v1-to-v2 migration guide #86
WIL-147 API reference and executable examples #87
WIL-155 2.0.0 changelog and release notes #89, #91
WIL-153 Validate the release candidate from clean installs #90 (rc3 run below)
WIL-231 WIL-153 Step 7: project URLs (GitHub web 504) no PR (links proved through the GitHub API)
WIL-154 This review: hygiene and review fixes #88, #92
WIL-157 Publish and tag 2.0.0 after GO
WIL-156 Post-release smoke test and monitoring after the release

Risks and accepted findings

  • Final review (WIL-154 Task 4): 8 confirmed findings (2 important, 6 minor). 7 are fixed in WIL-154: final review fixes #92. One minor is accepted: the CHANGELOG.md 1.0.20 entry keeps its fallback text, because 1.0.20 (WIL-228, on the 1.x branch) is not released yet; copy the real entry when it ships.
  • Python 3.10-only dev/docs alerts: filelock 4.1.0, pillow 12.3.0, tornado 6.5.10 in uv.lock. They are contributor tools, not shipped. The fixed versions (4.2.1, 13.0.0, 6.6) need Python 3.11 or newer. Accepted.
  • Projected holidays: B3 after 2026 and ANBIMA after 2079 are projected, not official. Written in the CHANGELOG "Known limitations".
  • Test-only NumPy deprecation warnings with NumPy 2.5 (WIL-232, backlog). The library code is clean; only tests use the old units.
  • Single maintainer: GitHub cannot record an approval by the PR author. Wilson's GO comment on WIL-154 is the approval of record.

Test evidence (on H)

uv sync --extra dev --extra docs
uv run pytest -q tests            -> 1219 passed, 3 warnings
uv run mypy                       -> Success: no issues found in 11 source files
uv run ruff check .               -> All checks passed!
make -C docs clean html           -> rc 0, 0 warnings
uv lock --check                   -> Resolved 131 packages, rc 0
clean clone: uv build --no-sources && tests/check_dist.py dist --version 2.0.0
                                  -> dist OK: bizdays-2.0.0-py3-none-any.whl bizdays-2.0.0.tar.gz
sha256 (same as WIL-153 VAL_SUMS):
  ae5fb8f0f4e77d74098fae8ef0e43b5b7f61fac8a8b59567f42b17939cf1cd28  bizdays-2.0.0-py3-none-any.whl
  da2a57bbcad22f72fb5b877b15bf9827f62243eff049123d5094cfca41ce7ac0  bizdays-2.0.0.tar.gz
pip-audit (runtime set, Python 3.10 and 3.14) -> No known vulnerabilities found
pip-audit (all extras, Python 3.14)           -> No known vulnerabilities found

CI on H: all 13 checks pass, including the required ci-ok and docs.

Dependabot

Today master has 115 open alerts (4 critical, 60 high, 46 medium, 5 low). All of them are on poetry.lock, which this PR deletes. None is a runtime dependency.

Alerts Where Shipped? After the merge
115 (certifi, Pillow, urllib3, tornado, mistune, ...) poetry.lock on master No (dev/docs tools) closed: the file is deleted
filelock, pillow, tornado (Python 3.10 markers only) uv.lock No may be raised; dismiss as tolerable risk (WIL-154 record)
runtime set (numpy, pandas, python-dateutil, pytz, six, tzdata) wheel metadata Yes none found on 3.10 or 3.14

Merge plan

  • Method: merge commit (not squash, not rebase), so the 2.0.0 history and the per-issue merges stay, and the merge tree equals the tested tree of H.
  • Run by WIL-157 Task 1, with --match-head-commit cc1868bad2978ab0fb13d8306081b853c2cc943e, only after Wilson's GO on WIL-154 and his go-ahead for WIL-157.
  • master is protected by a ruleset: PR required, required checks ci-ok and docs, no force push, no deletion, no bypass.
  • After the merge, WIL-157 builds 2.0.0 and checks the files by bytes against WIL-153's VAL_SUMS, then tags and publishes.

🤖 Generated with Claude Code

- Implemented comprehensive tests for the DateIndex class in `test_dateindex_numpy.py`, covering various scenarios for business day calculations, including normal and reversed date ranges, as well as vectorized operations.
- Created utility tests in `test_utils.py` for the `match` function and `isstr` type checker, ensuring correct behavior for various input cases.
- Introduced utility functions in `utils.py`, including a custom exception `DateOutOfRange`, and implemented the `match` function to find indices of elements in a table.
- Created ANBIMA.txt with holiday dates from 2000 to 2078.
- Added B3.cal with weekends and holiday dates from 2000 to 2024.
- Introduced Actual.cal as a placeholder for actual calendar data.
- Added Test.cal with sample holiday data for testing purposes.
- Updated import statement in test_calendar.py to reflect new module structure.
wilsonfreitas and others added 12 commits November 7, 2026 21:50
Checked against bizdays 1.0.19: DateOutOfRange was already exported
(only its base class changed), offset past the end raised IndexError,
offset(d, 0) keeps a holiday unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e wheel

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n guide

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Calendar() and Calendar.load() raise ValueError for wrong argument
  types (weekdays, name, financial, filename), as the Errors section says.
- Use a neutral payment example instead of the wrong NTN-B coupon date.
- getdate docstring lists every accepted ref and expr type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WIL-145: v1-to-v2 behaviour matrix
WIL-146: complete the v1-to-v2 migration guide
WIL-147: API reference and executable v2 examples
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iles

Upgrade only the dev/docs packages that pip-audit flags on Python 3.10
and 3.14 (bleach, certifi, filelock, fonttools, idna, lxml, mistune,
nbconvert, pillow, pygments, pytest, requests, soupsieve, tornado,
urllib3, virtualenv), plus packaging and typing-extensions so that
virtualenv can reach a fixed version on Python 3.10 too.

The runtime export (numpy, pandas, python-dateutil, pytz, six, tzdata)
and the bizdays version (2.0.0) do not change.

Delete GUIA_MIGRACAO_PYTEST.md and
docs/plans/2026-03-08-code-quality-improvements.md: nothing references
them, and plans live in Linear, not in the repo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wilsonfreitas and others added 10 commits November 7, 2026 22:08
bizdays has no "all" extra, so bizdays[all] installed core only. The smoke
script now also turns any error in run_checks into a problem in its JSON line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 1.0.20: use the design 4.3 fallback heading, since 1.x has no date yet
- test: reject YYYY-MM-DD placeholder headings
- breaking: drop the KeyError clause, it is already a bug fix
- breaking: v1 needed Python 3.9 or newer, not only 3.9

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The temporary repo had no commit, so main also failed on the
'no commit' path and the test passed without the dirty check.
Add an empty commit and assert the 'not a clean git tree' message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WIL-154: release hygiene (uv.lock security refresh, stray files)
WIL-155: 2.0.0 changelog and release notes
WIL-153: validate the release candidate from clean installations
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WIL-155: date the 2.0.0 changelog entry
- Calendar(name=None), the 1.0.19 default, gives name "" again
- weekdays may be a NumPy array or pandas Series
- structured NumPy arrays as dates raise ValueError
- long date strings accept ASCII digits only
- getdate year refs beyond 2**53 raise ValueError
- JSON calendar files with a UTF-8 BOM load
- README/API docs: ANBIMA is official up to 2079, projected after

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WIL-154: final review fixes
@wilsonfreitas wilsonfreitas changed the title bizdays 2.0.0: NumPy-backed Calendar (v2 integration) bizdays 2.0.0: v2 integration (WIL-154 go/no-go) Nov 8, 2026
@wilsonfreitas
wilsonfreitas marked this pull request as ready for review November 8, 2026 09:29
…changelog entry

1.0.20 is now the last 1.x release on PyPI. It has the same API as 1.0.19
and only extends the B3 data, so the guide compares 2.0 with 1.0.20 and
says where 1.0.19 differs (B3 ended in 2026). The CHANGELOG gets the real
1.0.20 entry from origin/1.x (final-review finding 8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WIL-146: migration guide baseline is 1.0.20
@wilsonfreitas
wilsonfreitas merged commit 0160256 into master Nov 8, 2026
13 checks passed
@wilsonfreitas
wilsonfreitas deleted the feature/typing branch November 8, 2026 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant