chore(deps): update python minor/patch #178

Open
renovate-bot wants to merge 1 commit from renovate/python-minorpatch into main
Contributor

This PR contains the following updates:

Package Change Age Confidence
alembic (changelog) ==1.18.5==1.19.2 age confidence
authlib ==1.7.2==1.8.0 age confidence
fastapi (changelog) ==0.140.7==0.141.1 age confidence
pydantic-settings (changelog) ==2.14.2==2.15.0 age confidence
python-dotenv ==1.2.2==1.2.3 age confidence
sqlalchemy (changelog) ==2.0.51==2.0.52 age confidence
timezonefinder ==8.2.5==8.3.0 age confidence
twilio ==9.10.9==9.11.1 age confidence
uvicorn (changelog) ==0.51.0==0.52.4 age confidence

Release Notes

authlib/authlib (authlib)

v1.8.0

Compare Source

What's Changed

New Contributors

Full Changelog: https://github.com/authlib/authlib/compare/v1.7.2...v1.8.0

fastapi/fastapi (fastapi)

v0.141.1

Compare Source

Fixes
  • 🐛 Fix support for background tasks and headers from dependencies in app.frontend(). PR #​16105 by @​tiangolo.
Docs

v0.141.0

Compare Source

Features
  • Add app.frontend(check_dir="auto"), to make local development more convenient with fastapi dev. PR #​16102 by @​tiangolo.

v0.140.13

Compare Source

Fixes
Docs

v0.140.12

Compare Source

Fixes

v0.140.11

Compare Source

Fixes
  • 🐛 Fix response_model_* params ignored for non-generator endpoints with Iterable[..] return type. PR #​15093 by @​YuriiMotov.

v0.140.10

Compare Source

Fixes
Internal

v0.140.9

Compare Source

Fixes
  • 🐛 Fix exclude_defaults not propagated to dict keys and values in jsonable_encoder. PR #​16043 by @​MBGrao.
Internal

v0.140.8

Compare Source

Fixes
pydantic/pydantic-settings (pydantic-settings)

v2.15.0

Compare Source

Highlights

Behavior changes
  • case_sensitive now applies to init kwargs and config-file sources (#​900). InitSettingsSource and the JSON/TOML/YAML config sources previously ignored case_sensitive. Since it defaults to False, case-insensitive matching is now the default for these sources — e.g. Settings(TeSt=...) now populates a test field where it previously did not. Nested keys are still matched case-sensitively.
  • Fields with unresolved forward references now emit a warning (#​901). Settings sources can silently fail to resolve such fields; they now raise IncompleteFieldDefinitionWarning telling you to call model_rebuild(). If you have filterwarnings = error configured, this may surface as a new failure.
  • Non-JSON env values for strict fields now raise ValidationError (#​926) instead of a less specific error.
New features
  • Show environment variable names in CLI help via cli_show_env_vars=True (#​860), so generated --help output doubles as configuration documentation.
  • PYDANTIC_SETTINGS_DEBUG for debugging settings resolution (#​906, #​913). Set it to a truthy value with DEBUG logging enabled to see each source's contribution in priority order, which source won for each value, and which env_file/secret files were probed, loaded, or skipped — the long-standing "why isn't my .env being picked up?" question.
  • toml_table_header for regular TOML files (#​882, #​886, #​887), letting you root settings at a nested table in any TOML file, not just pyproject.toml.
  • Traversable support for JSON/TOML/YAML file sources (#​902), so you can load config packaged inside a distribution — including files inside a zip or wheel — via importlib.resources.files(...) without casting to Path.
  • GCP: project_id can come from an earlier settings source (#​878), rather than only from the constructor or GOOGLE_CLOUD_PROJECT.
Bug fixes
  • Fix env vars not loading on Windows with case_sensitive=True (#​894). Windows upper-cases os.environ keys, so fields raised Field required instead of picking up their values.
  • Read secret files as UTF-8 instead of the platform locale encoding (#​917). On Windows code pages such as cp1252 this silently corrupted non-ASCII secrets.
  • Fix AliasPath on nested model fields not JSON-decoding env values (#​898).
  • Fix case-insensitive matching for optional nested models (#​905).
  • Fix dotenv extras being wrongly claimed by a complex field sharing a name prefix (#​912) — e.g. dbx_token being swallowed by a db: dict field.
  • Fix nested_model_default_partial_update=True corrupting discriminated unions (#​876).
  • Fix Secret subclasses crashing when loaded from the environment (#​920).
  • Fix enum names not parsing through nested annotations such as Optional[Annotated[MyEnum, ...]] with env_parse_enums=True (#​910).
  • An empty yaml_config_section now falls back to defaults instead of raising AttributeError: 'NoneType' object has no attribute 'keys' (#​914).
  • NestedSecretsSettingsSource no longer follows symlinks pointing outside secrets_dir (#​889).
  • GCP: skip the list_secrets call when case_sensitive=True (#​862), lowering the required IAM permissions to just roles/secretmanager.secretAccessor.
  • AWS: types-boto3[secretsmanager] is no longer required at runtime (#​880).
Documentation
  • Document JSON parsing of complex env values, plus a comma-separated-values recipe (#​919).
  • Recommend an async settings loading pattern (#​908).
  • Clarify behavior when an unprefixed value is present in a dotenv file (#​895).
  • Clarify environment variable helper descriptions (#​867) and fix assorted typos (#​904).
All changes (including dependency bumps and internal maintenance)

What's Changed

New Contributors

Full Changelog: https://github.com/pydantic/pydantic-settings/compare/v2.14.1...v2.15.0

theskumar/python-dotenv (python-dotenv)

v1.2.3

Compare Source

Fixed
  • Strip a leading UTF-8 BOM from .env file contents so the first variable is no longer silently lost when the file is saved with BOM (e.g. by some JetBrains IDEs on Windows) by [@​h1whelan] in [#​640]
  • set_key now escapes backslashes, so values containing them (Windows paths, regular expressions) survive a write/read round-trip. Quoted values ending in an escaped backslash are no longer mis-parsed as an escaped quote, which used to swallow the following lines by [@​dchaudhari7177] in [#​680]
  • dotenv run now prints a friendly error instead of a traceback when no command is given by [@​bbc2] in [#​606]
  • Cache the parsed result for empty .env files so repeated dotenv_values/load_dotenv calls no longer re-read the file by [@​ReinerBRO] in [#​638]
jannikmi/timezonefinder (timezonefinder)

v8.3.0

Compare Source

  • the dataset version is now exposed at runtime. TimezoneFinder().data_version (and TimezoneFinderL().data_version) return the timezone-boundary-builder release the packaged data was built from, read from a data_version.txt stamp that scripts/file_converter.py writes into the data directory it generates and that ships in the wheel. Previously an installed timezonefinder could not state it at all: the release tag lived only in a repo-root file that is not packaged. Which release a parse is stamped with comes from the input's filename (combined-with-oceans-2026c.json, which update_data.sh now produces), or from scripts/file_converter.py --data-version for an input that cannot carry it; your own GeoJSON is stamped "unknown", and an unpacked release archive that lost its tag is refused rather than compiled into data that could never say where it came from. timezonefinder.__version__ is now exposed as well, read from the installed distribution metadata. Solves issue #​498

  • fixed a BufferError: cannot close exported pointers exist raised during resource cleanup in file mode (in_memory=False). A coordinate array obtained from coords_of() is a zero-copy view onto the memory-mapped file, and mmap.close() refuses to unmap while one is alive, so an array outliving its TimezoneFinder raised on cleanup. The mapping now stays valid instead of leaving the views dangling, and FileCoordAccessor.cleanup() releases its own references so the deferred close happens as soon as the last view is dropped. The accessor must not be used after cleanup()

  • polygon coordinates are now stored one axis at a time in the packaged coordinates.bin files - all x values followed by all y values per polygon, instead of interleaved. The point in polygon test scans a single axis per iteration, so contiguous per-axis blocks halve the cache lines it touches: ~1.6x faster on a median polygon and ~2.5x faster on the largest ones via the C extension, 14-25% faster via Numba. The bundled data was regenerated accordingly, and the layout is described in the data format documentation <https://timezonefinder.readthedocs.io/en/latest/data_format.html>__

  • every packaged FlatBuffers file now carries a file identifier and a layout version, and TimezoneFinder raises a ValueError naming the offending file when either does not match - previously such a directory was read without complaint and produced wrong timezones. For coordinates.bin the version records how the coordinates are encoded and which polygons the file holds. The hybrid shortcut binaries get an identifier that differs per zone id width, because the uint8 and uint16 schemas differ only in the width of a zone id and each parses cleanly as the other; the width is now read from the buffer instead of being guessed from the file name, so a renamed or mispaired shortcut file fails loudly rather than returning wrong zones. If you compile your own data and point bin_file_location at it, regenerate it once with scripts/file_converter.py, since the coordinate layout, the hole storage, the shortcut container and the file names all changed in this release. The markers track what a file holds rather than the package version, so this is not a per-release obligation. Solves issue #​458

  • the memory footprint of every finder configuration is now measured and published in a new memory report <https://timezonefinder.readthedocs.io/en/latest/benchmark_results_memory.html>__, separating what a configuration allocates (tracemalloc) from what it makes resident (RSS, which additionally counts memory-mapped pages). The distinction is the point: the default mode maps the coordinate data instead of reading it, so it allocates an order of magnitude less than the in-memory mode, and only the pages a lookup actually touches become resident. This replaces documentation claiming a 40MB process ceiling and a 41MB data directory, both long out of date

  • restructured the two entry points a reader actually arrives at - README.rst and the documentation landing page <https://timezonefinder.readthedocs.io/en/latest/>__ - so both state what the package is and how it works instead of only what it is called. The README opens with the project banner and a one-sentence statement of what the package is for, then the badges, then the quick guide - and adds three short sections that were missing entirely: How it works (the lookup pipeline and the no-simplification trade-off), Performance (a concrete throughput figure with its configuration named, the three point-in-polygon backends and the pure-Python fallback), and Engineering notes linking the architecture, data format and benchmarking methodology pages. The maintainers-wanted notice moves from the first heading after the intro into a new Contributing section at the bottom, which also links CONTRIBUTING.md for the first time. The badge block is corrected along the way: the code style: black badge named a formatter this project has never used and is replaced by ruff, and a supported-Python-versions badge was added. The banner is referenced by absolute URL, since PyPI serves the long description without the repository and a docs/… path renders as a broken image there. The landing page gains the same How it works summary, the no-simplification trade-off and the ocean-zone consequence for timezone_at(), and its flat seventeen-entry table of contents is grouped into Using it, Design, Performance and Project, so the sidebar says what kind of project this is rather than listing pages in the order they were written

  • rewrote the package comparison <https://timezonefinder.readthedocs.io/en/latest/alternatives.html>__ page. It now states its position in prose before the first table - border correctness is what this package optimises for, speed is the constraint that work happens under - and says plainly when tzfpy is the better choice. Every quantitative cell names what it measures and links its source, and the speed row is deliberately qualitative on both sides, with a note explaining that the two packages have never been benchmarked under one harness. The decision table drops the rows on which the two packages do not differ

  • two new documentation pages: Architecture <https://timezonefinder.readthedocs.io/en/latest/architecture.html>__ describes the lookup pipeline, the three point-in-polygon backends and the memory modes, and states the ceilings this package deliberately does not exceed - unsimplified geometry, ~1 cm coordinate resolution, no general-purpose spatial code. It also documents how the package is built and shipped, which was previously described nowhere outside the workflow YAML: why one abi3 wheel per target replaces one wheel per Python version and what abi3audit is guarding, why three libc targets are built, why the end-to-end job installs the built wheel and asserts the C extension loaded rather than merely importing the package, and why a tag pushed from outside master aborts the release. The testing section gained the property-based suite and the reason the tox matrix is a matrix - the acceleration paths are bound at import time, so a passing run describes one configuration only. Both sections are linked from the README's Engineering notes. Benchmarking Methodology <https://timezonefinder.readthedocs.io/en/latest/benchmarking_methodology.html>__ documents how the published numbers are produced and what they can and cannot tell you: ubuntu-latest pins the runner image and not the CPU, which is why a pull request is measured against its own merge base on the same runner and why every alert threshold is derived from measured noise. It was previously addressed only to contributors, in the second half of CONTRIBUTING.md, which now keeps the operational instructions and links to it

  • the H3 resolution choice in the data format documentation <https://timezonefinder.readthedocs.io/en/latest/data_format.html>__ is no longer asserted to "offer a good balance" but reports the study behind it (prototypes/single_resolution_bench.py): resolution 3 keeps the hybrid index at a small fraction of the packaged polygon data, while resolution 4 would exceed 10 % of it for gains that do not justify the increase

  • the hand-written documentation no longer restates exact figures that belong to the generated pages - dataset vertex, polygon and hole counts, index and distribution sizes, memory footprints, lookup throughput. Those change with every data update and with code that shifts a footprint, which silently left the copies wrong: the memory figures had already gone stale in four places. The prose now states the magnitude that survives a data update and links the data report <https://timezonefinder.readthedocs.io/en/latest/data_report.html>__ or the relevant benchmark report <https://timezonefinder.readthedocs.io/en/latest/7_performance.html>__, which are regenerated from the packaged data and are always current

  • the three weakest hand-written documentation pages no longer answer a question by pointing at a file the reader has to open. The performance page <https://timezonefinder.readthedocs.io/en/latest/7_performance.html>__ now opens with the four benchmark reports and the trend chart instead of a bullet list of adjectives about the binary format, and its C extension and Numba sections are cut to what a user does - which call reports the active backend - with the explanation left to the architecture page that already carried a more precise version of it. Getting started lists the four runtime dependencies and what each is for, where it previously said to consult pyproject.toml, which remains linked as the authoritative source for version ranges. The use case pages carry runnable snippets for building an aware datetime and reading a UTC offset, with the examples/ scripts as the follow-up rather than the whole answer; the snippets use the standard library's zoneinfo, so neither needs an optional dependency

  • the shortcut entry distributions in the data report <https://timezonefinder.readthedocs.io/en/latest/data_report.html>__ no longer report three quarters of all H3 cells as holding 0 polygons, which is impossible for data whose ocean zones cover the globe. Those cells are covered by a single timezone and store its id directly, so a lookup there needs no point-in-polygon test at all - the column is now Polygons to test and the row reads none (unique zone). The tables are introduced by a sentence on what they measure, including why no cell ever needs exactly one test

  • the hybrid shortcut loader no longer keeps the entire shortcut binary in memory. The polygon id arrays it returns were zero-copy views onto the ~1.5 MB file buffer, so ~47 KB of live data pinned the whole thing for the lifetime of every TimezoneFinder / TimezoneFinderL instance. They are now disjoint read-only slices of a single compact array, cutting the shortcut mapping's footprint from ~7.4 MB to ~4.7 MB per instance, and every finder's resident set by ~2 MB, at unchanged initialisation time - which matters most for concurrent workloads, where the recommended one-instance-per-thread pattern multiplied the waste

  • the usage examples in README.rst and the usage documentation <https://timezonefinder.readthedocs.io/en/latest/1_usage.html>__ now show the result the packaged data actually returns. Every snippet queries the same Berlin coordinates and annotated the answer as 'Europe/Paris', which is the value from the reduced timezones-now dataset, where Europe/Berlin is merged into Europe/Paris - not from the full dataset the package ships by default. All eleven annotations now read 'Europe/Berlin', verified against the packaged data for each of timezone_at(), timezone_at_land(), certain_timezone_at(), unique_timezone_at() and TimezoneFinderL, and the get_geometry() call in the opening example asks for that same zone instead of a different one. tests/test_documented_contracts.py now re-runs each of those documented lookups, so a data update that moves the example coordinate's zone fails there rather than leaving every snippet on both pages quietly wrong again

  • holes that duplicate a timezone boundary polygon are no longer stored twice. Almost every hole is an enclave, cut into the surrounding zone with exactly the ring the upstream data also emits as the enclosed zone's own boundary polygon - the same geometry under two IDs. The packaged hole coordinate file now holds only the rings with no such twin (27 of 756 in the current data), and a new holes/poly_ref.npy records per hole which boundary polygon to read instead. Hole data drops from ~2.0 MiB to ~0.16 MiB, and in_memory=True saves the same amount of RAM, since those holes now resolve into the boundary arrays rather than materialising a second copy. Matching is exact - rings are compared as integer coordinates in a canonical form, with bounding boxes used only to narrow the search - so every timezone lookup returns what it did before. One visible consequence: get_geometry() may hand back a deduplicated hole ring starting at a different vertex or winding the other way than it used to, tracing the same closed path. The encoding is described in the data format documentation <https://timezonefinder.readthedocs.io/en/latest/data_format.html>__

  • the command line script gained a --stdin streaming mode: it reads delimited rows from standard input and writes each back out with a timezone column appended, building the finder once instead of paying full initialisation per coordinate. Which columns hold the coordinates is read off the header by name, or stated with --lng-col/--lat-col, and never inferred from their position - a swapped pair is still a valid coordinate for any longitude between -90 and 90, so guessing would answer with a real but wrong timezone instead of failing. Every input row produces exactly one output row, and a row that cannot be used warns on stderr and makes the run exit non-zero rather than ending the stream. Whether the first row is a header is worked out from the row, or stated with --header/--no-header. New flags -d/--delimiter and --in-memory apply to the whole stream. See the usage documentation <https://timezonefinder.readthedocs.io/en/latest/1_usage.html#looking-up-many-coordinates-at-once>. Solves issue #​504. Thanks to weed33834 <https://github.com/weed33834> for the PR #​516

  • the timezone boundary data now ships as its own distribution, timezonefinder-data. pip install timezonefinder is unchanged - it is a hard dependency and is installed automatically - but the dataset can now be pinned on its own (pip install timezonefinder "timezonefinder-data==1.2026.3"), where previously holding a dataset meant pinning an old timezonefinder and forfeiting every code fix since. Every release used to carry the whole ~65 MB dataset in three platform wheels plus an sdist to distinguish a few kilobytes of compiled code, which had already exhausted the PyPI project storage quota once. A data update is consequently no longer a timezonefinder release at all: it publishes timezonefinder-data under its own tag namespace and is recorded in that package's README rather than here. Its version reads <format>.<year>.<letter> - 1.2026.3 is data format generation 1 built from timezone-boundary-builder 2026c - and timezonefinder requires timezonefinder-data>=…,<2: no ceiling on the data axis, so a dataset update needs no code release, and a hard one on the format axis, so code paired with data it cannot read fails when resolving rather than at the first lookup. DATA_LICENSE moves with the database it covers and now ships inside the data wheel, and a compiled data directory additionally carries a schemas/ copy of the FlatBuffers definitions its binaries were written by, so it can be read back without the package that wrote it. Solves the first part of issue #​446

  • the packaged FlatBuffers binaries are now named .bin rather than .fbs: boundaries/coordinates.bin, holes/coordinates.bin and hybrid_shortcuts_uint16.bin. .fbs is the FlatBuffers schema extension, and the data directory now ships actual schemas next to the buffers, so one extension was naming two unrelated kinds of file. Each buffer already states what it is through the file identifier in its first bytes, which is what a rename or a mispaired copy cannot forge - the name never carried that meaning. The bytes are unchanged

Internal:

  • the release pipeline refuses to publish timezonefinder unless a compatible timezonefinder-data already exists on PyPI. The two distributions release independently, and on a data format change the order is fixed - data first, then the code requiring it - because a code wheel whose declared data version does not exist yet is uninstallable for everyone until it does, and the version number cannot be reused to fix it. The check reads the requirement out of the built wheel rather than out of pyproject.toml, and asks the index the same question a user's resolver will, so a yanked release does not count as one that satisfies it. It runs before the GitHub Release, which is the first step of the release that cannot be taken back
  • pull requests are opened against a template (.github/pull_request_template.md) prompting for the change, its motivation and the checks that were run
  • update_data.sh resolves the timezone-boundary-builder release tag before downloading and fetches that release's asset, instead of fetching releases/latest/download/ and separately asking the API what latest was - two independent questions that a release landing between them answered differently, attributing one release's data to the other. The tag now names the downloaded archive and the GeoJSON as well, so a leftover file from another release or another dataset variant cannot satisfy the "already downloaded" checks and be parsed in place of what was asked for
  • names and docstrings now describe what the code does. TimezoneFinder.timezone_at documents the optimisation it actually performs: once no other zone can be matched the last remaining zone is returned without a point in polygon test, which is always correct against the packaged data - the ocean zones cover the globe, so every point lies within one of the candidate polygons - but not against custom data that leaves areas uncovered, where a point inside none of the candidates is still attributed to that zone and certain_timezone_at is the method that tests every candidate. Three tests were named after something other than what they do: test_rectify_coords_valid/_invalid were named for a rectify_coords that exists nowhere in the package and both call validate_coordinates, and the first was subsumed entirely by test_validate_coordinates_accepts_finite_values, which covers all four of its distinct corners and additionally asserts the return value where the older test asserted only "does not raise"; and test_single_element_arrays_should_not_occur asserted that they do occur (assert single_element_count == 2) under a triple-quoted string placed after the first statement, making it a discarded expression rather than a docstring - so it reached neither --collect-only nor a failure report, which is where the contradicting name was the only thing a reader saw. A stale comment duplicated across the last two lines of tests/main_test.py, reading as a to-do for something TestTimezonefinderClassTestMEM already does, is gone
  • added DATA_VERSION file tracking which timezone-boundary-builder release the packaged data was generated from, written automatically by the data update script after a successful parse. Thanks to Lucas Hemkemeier <https://github.com/hemkdev>__ for the PR #​429
  • the packaged data now updates itself: a weekly workflow compares DATA_VERSION against the latest timezone-boundary-builder release, regenerates the data and opens a ready-to-review update PR, which is merged and released automatically once its CI passes - the version tag is pushed with a GitHub App token, since the default one would not trigger the release pipeline. The tag lives in its own data-v* namespace, which the code release pipeline excludes at its trigger and again on the job that creates the GitHub Release, and the data stream publishes by PyPI Trusted Publishing from its own deployment environment rather than with a shared token. It refuses to release when the squash it produced did not land on the master it checked, so the tag names a tree that was actually built. Failed CI takes the same manual-attention path and falls back to the previous notification issue. Each cause labels the PR automation-failed and leaves one comment naming that cause and linking the run, deduplicated per cause so re-running CI neither repeats a notice nor hides a second one; a failure past the merge is a cause of its own, since that leaves master carrying the update with no tag pushed and only a hand-pushed tag still releases it. The manual release path drops the stop condition it carried for an out-of-order CHANGELOG.rst: the automation can no longer produce one, and the test suite asserts the committed file's section order if anything else does (issues #​273, #​167 and #​510). Thanks to Lucas Hemkemeier <https://github.com/hemkdev>__ for the PRs #​434 and #​436, and to Nice6042 <https://github.com/Nice6042>__ for the PR #​518
  • update_data.sh (renamed from parse_data.sh) is CI-ready: interactive prompts replaced by flags (--dataset=full|same-since-now, --with-oceans, --rm-tmp), the release note for a data update written automatically into the data package's README, no redundant tox run, and a make reports at the end so the benchmark and data reports cannot go stale relative to the data an update PR ships. A standalone make parse/make testparse still needs a manual make reports (issues #​167 and #​510). Thanks to Lucas Hemkemeier <https://github.com/hemkdev>__ for the PRs #​432 and #​434
  • added property-based tests (hypothesis) for coordinate validation (solves issue #​143). Thanks to Lu Yicheng <https://github.com/01luyicheng>__ for the PRs #​431 and #​433
  • replaced the hand-rolled timeit timing in scripts/check_speed_*.py with pytest-benchmark suites under benchmarks/, excluded from make test/make testall via testpaths. Both they and the memory harness run over deterministic committed fixtures (tests/fixtures/benchmarks/), so two runs of the same commit execute the exact same workload; the loader rejects fixtures that no longer match the checkout. Measurement and rendering are decoupled, so docs/benchmark_results_*.rst can be regenerated from a stored JSON without re-measuring. Run via make speedtest, make benchmarks, make memory or make reports
  • memory is measured by its own harness (scripts/measure_memory.py, make memory) rather than by pytest-benchmark, which times code and would have its timings distorted by allocation tracking. It emits pytest-benchmark-shaped JSON, so the existing normalisation, noise and comparison tooling works on it unchanged given a --metric. tests/test_memory_footprint.py fails if a mode's allocation leaves its order of magnitude - the regression that would make in_memory=False stop being the low-memory option
  • added continuous benchmarking on CI (solves issue #​150), deliberately kept out of the release pipeline in build.yml: the tracked core subset and the memory harness run on every pull request and every push to master, publishing trend charts <https://jannikmi.github.io/timezonefinder/dev/bench/>__ to gh-pages and posting a same-runner base/head comparison on the pull request. The comparison reports added or removed benchmark IDs without trying to ratio unmatched measurements, which lets the trusted default-branch consumer remain compatible while the suite evolves. A pull request is measured against its own merge base in the same job rather than against a stored baseline, because runs-on: ubuntu-latest pins the runner image and not the CPU. The measurement design, the tracked estimator and every alert threshold are documented in the new benchmarking methodology <https://timezonefinder.readthedocs.io/en/latest/benchmarking_methodology.html>__ page. The measuring job holds no write permissions and no secrets, so branch and fork pull requests behave identically; the comment is posted by a separate, privileged workflow via workflow_run
  • guarded the benchmark plumbing against silent drift: tests/test_benchmark_names.py and tests/test_memory_metric_names.py pin the node ids and metric names that join a measurement to its chart history, so a rename fails loudly instead of starting an empty chart beside the orphaned old one; tests/test_benchmark_workflows.py asserts that the constants duplicated across the two workflows agree, where a one-sided edit previously had no failure mode at all, and that the cross-machine trend chart cannot creep back into the pull request comparison; and every generated report page states the inputs it describes - docs/benchmark_results_*.rst the fixture and timezone data versions they were measured against, docs/data_report.rst the timezone data version its figures were derived from. Both stamps are covered by tests: one renders each report and fails if a renderer stops emitting it, another checks the committed pages against the current fixture metadata and DATA_VERSION, so regenerating fixtures or updating the data without re-rendering fails loudly instead of leaving a page whose numbers are all plausible and all stale
  • every generator now emits output that is already pre-commit-clean, so regenerating and diffing compares like with like: write_json sorts keys the way pretty-format-json does, and neither scripts/reporting.py nor BenchmarkReporter emits trailing whitespace on empty cells or a trailing blank line. Previously every make parse/make reports left its outputs looking modified until the hooks had run, which masked whether a regeneration had actually changed anything
  • every generated benchmark report now opens with its headline figure and the configuration behind it, above the tables: how long a lookup takes and how many per second, the per-check cost across polygon sizes, construction time, footprint per mode - all derived from the same parsed JSON as the tables, never hardcoded. The banner beneath states which acceleration path and platform produced the numbers, and says whether that is the configuration CI tracks: the committed reports are rendered from a developer machine with Numba enabled, while CI measures the C extension without Numba, so their figures were never comparable to the trend chart and now say so
  • make flatbuf no longer overwrites hand-maintained __init__.py files. flatc derives its output path from the schema namespace and writes an empty __init__.py at every level of it, so generating in place wiped the __all__ in timezonefinder/__init__.py - the whole public API. The target now generates into a scratch tree, copies back only the generated packages, and runs the formatters on the result so a regeneration diff shows the codegen change rather than formatting churn
  • mypy now type-checks the whole package except the flatc-generated bindings. ignore_errors previously covered roughly 800 lines of hand-written code as well, where a blatantly wrong return type still reported "Success"; they all pass once the exemption is lifted, bar two genuine findings now fixed. tests/test_mypy_config.py keeps the list restricted to generated code, so silencing a module is a reviewed decision rather than a one-line edit
  • the hybrid shortcut reader and writer now select their FlatBuffers schema from a single registry (SHORTCUT_SCHEMAS in timezonefinder/flatbuf/io/hybrid_shortcuts.py) instead of dispatching on the zone id width in three places, each keyed differently. One ShortcutSchema per width owns the width, the file name, the uintN marker and the maximum zone id, which were previously written down across five places with nothing tying them together. Verified behaviour-preserving down to the bytes: re-writing the shipped shortcut binary produces a byte-identical file
  • each distribution's build is now asserted to contain exactly what it should. The data wheel's payload is compared against the committed dataset as a set, in both directions: a missing binary fails on first use and gets reported, but an extra one ships silently - setuptools copies package data into build/lib and never prunes it, so a file renamed in the source tree keeps being zipped into every later wheel built from that checkout, which is how a 63 MB coordinates.fbs was still shipping next to the coordinates.bin that replaced it and doubling the wheel whose size is the reason the distribution was split out. The wheel builders clear that directory first, so a local build matches the fresh checkout CI builds from, and the code sdist's checks cover its grafted test fixtures again
  • the packaged data is additionally held to a floor on how much hole deduplication achieves - the test suite fails if fewer than 90% of its holes match a boundary polygon (96.4% currently), because a future upstream release that stopped emitting enclaves as shared rings would still compile and still return correct timezones, just with the shipped data quietly re-inflated. The floor applies to that dataset and nothing else: compiling your own GeoJSON with scripts/file_converter.py is a supported use case, holes that are ordinary interior rings rather than enclaves are stored inline and answer correctly, and the converter only reports the ratio rather than refusing to compile. prototypes/hole_boundary_redundancy.py is the study behind the threshold: it reads the upstream GeoJSON, so re-running it against a new release re-verifies the assumption rather than restating it. prototypes/hole_removal_impact.py is the study behind keeping the unmatched holes stored inline rather than dropping them, which is the obvious next step and does not work: dropping holes and re-running the lookups changes answers, wrongly, because being covered by another zone only puts that zone among the shortcut candidates and says nothing about it being tested first (issue #​513)
  • removed constructs that provably did nothing, and gave two vacuous tests real assertions. Most consequentially, four __slots__ entries were declared but assigned by nothing, which silently re-permitted the very attributes __slots__ is there to forbid - assigning those names now raises AttributeError, and test_declared_slots_are_assigned keeps the list honest
  • get_corrected_hex_boundaries exists once again. An earlier refactor left two verbatim copies of the antimeridian and pole clipping rules with nothing keeping them in sync; the copy without callers is deleted, and the survivor is now covered by tests/hex_utils_test.py - it previously had no direct tests at all. scripts/configs.py no longer declares MAX_LAT/MAX_LNG as a second pair of names for timezonefinder.configs's constants
  • prototypes/ has a README.md saying what the three scripts there are: exploratory studies behind committed design decisions, run by hand, outside the package and the test suite. One of them is the measurement that chose H3 resolution 3 - the central algorithmic parameter of the package, already cited from the data format page - and another is the evidence for not building a hierarchical index. MANIFEST.in now excludes the whole directory from the source distribution rather than only its *.py files
  • plans/ is git-ignored alongside tmp/ and .venv/: implementation plans written while working on a change are local scratch, and leaving the directory untracked-but-unignored made it noise in every git status and a candidate for an over-broad git add
  • failing paths now report the input that failed. tests/auxiliaries.py's run_command assembled the child's stdout and stderr into a message and then raised a fresh CalledProcessError that never used it, with from None discarding the original too, so a packaging failure under make testint reported an exit code and nothing about the cause; it now echoes the captured streams and re-raises the original exception with its traceback intact. scripts/reporting.py passes the coordinate file paths into get_polygon_collection, whose optional file_path exists precisely so an incompatible-layout ValueError can say which of the two files was stale - make reports against an outdated data directory previously could not. Boundaries.overlaps names the type it rejected instead of raising a bare TypeError, and the RuntimeError for missing original_polygons names the polygon and resolution it was computing. The two re-raises ruff flags under B904 now say from None explicitly, so a deliberately dropped exception chain is distinguishable from a forgotten one, and timezonefinder/command_line.py drops FileNotFoundError from an except tuple that already caught its base class OSError. tests/test_error_diagnostics.py pins what each of these messages must contain
  • the command line interface no longer routes its own output through a temporary file. main redirected stdout to a mkstemp file for the duration of the lookup and then, in verbose mode, reopened it to read back a string it still held in a local variable - nothing inside the redirected block ever wrote to stdout, since the lookup functions return their result rather than printing it. The context manager, the read-back, its warning path and the file cleanup are gone, and the lookup function is now resolved once per invocation instead of twice, so -f 3/-f 4 under -v no longer construct a second TimezoneFinderL and reload its shortcut data just to read a function name. Output is unchanged character for character, across every function id in both modes. tests/cli_test.py gains the coverage that makes that checkable - verbose mode, the empty line printed when no timezone is found, and the rejected function id had none - and asserts the printed name verbatim instead of passing it through rstrip("\n\x1b[0m"), which strips a set of characters rather than a suffix and so truncates 12 of the packaged zone names (Europe/Amsterdam -> Europe/Amsterda)
  • docstrings now describe the code that exists. Six documented something the implementation contradicts: AbstractTimezoneFinder.__init__ called in_memory inert and "kept for API compatibility" when it is what selects memory-mapped against in-memory coordinate access - the claim help(TimezoneFinder) surfaces, and the opposite of what the usage docs say; both get_geometry docstrings pointed at a timezone_names.json that does not exist under that name; read_zone_names promised an empty list where it raises FileNotFoundError, and illustrated itself with a hardcoded zone count that the packaged data had since outgrown; and zone_id_of / zone_name_from_id each advertised an exception type they convert away, sending callers to write handlers that can never fire. Five further :param:/Args: entries in scripts/ and tests/ documented arguments that were removed along with the parallel shortcut compilation they belonged to. tests/test_documented_contracts.py pins the exception types and the coordinate access mode, so those promises now rest on something besides prose
  • the test and benchmark suites no longer contain checks that cannot fail. Eighteen calls sat inside four shared pytest.raises blocks in tests/main_test.py, and execution leaves such a block at the first statement to raise - so one out-of-range coordinate, one positional call shape and one rejected get_geometry input were verified while the remaining fifteen were unreachable. Each is a test case of its own now: every coordinate just outside the WGS84 range, every positional call shape of every keyword-only lookup method, and the unknown-zone-name, past-the-end and negative zone id rejections of get_geometry. The __del__ cleanup test binds its exception per iteration rather than closing over the loop variable, which decided what a garbage-collected instance would raise long after the loop had moved on. On the benchmark side, pip_inputs_by_stratum validated only the strata the fixture happened to contain, so one missing from it altogether passed and surfaced later as a bare KeyError inside a benchmark, and the points and their labels were paired from two files with a non-strict zip that truncates silently. That grouping now lives in tests/auxiliaries.py as group_pip_inputs_by_stratum, checks against the declared PIP_STRATA - which the generator no longer keeps a second copy of - and has tests for each way the two fixture files can disagree
  • both point-in-polygon acceleration paths are now covered by a local test run, whichever one the environment happens to bind. The implementation is selected at import time and Numba wins whenever it is importable - which the documented setup (uv sync --all-groups) makes it - so the C extension was reached only by direct-kernel tests on hand-built arrays, and everything about how real polygon buffers arrive at it, including the read-only memory-mapped views, was first exercised in CI's non-numba tox environments: the configuration a plain pip install timezonefinder produces. tests/test_acceleration_paths.py now rebinds utils.inside_polygon and drives the full lookup stack through both implementations, asserting that they agree across the real boundary data, that the C path returns the known-correct answers, and that the point-in-polygon stage was reached at all rather than short-circuited by the shortcut layer (issue #​482)
  • the packaging guard in tests/test_package_contents.py no longer names files that do not exist. It asserts that nothing in the built sdist and wheel matches a list of unwanted paths, which passes just as readily when a pattern matches nothing at all: .github lacked the trailing slash that directory patterns need, Agents.* stopped matching when the file was renamed to AGENTS.md, and readthedocs.yaml never matched readthedocs.yml - so the CI configuration and both of those files were unguarded while the suite stayed green. The patterns are corrected, the provider stubs, contributing/, .agents/, .claude/ and .cursor/ are covered to match what MANIFEST.in excludes, and test_every_unwanted_pattern_matches_a_project_file now fails on any hand-written pattern that matches no path in the checkout, so the next rename cannot silently disarm one. It carries the unit marker rather than the module's former blanket integration mark, since it needs no build: a mistyped pattern surfaces in make test. .gitignore re-include lines (!…) are also no longer read as exclusions, which had produced one more parametrised case that could never fail. The converse direction is checked too: test_every_manifest_exclusion_is_guarded parses the exclude/recursive-exclude/prune/global-exclude directives out of MANIFEST.in and fails when one of them keeps a path out of the build that no pattern here names - previously such a line was enforced by the build and verified by nothing, so deleting it would have shipped the file with the suite still green. The two lists are hand-maintained statements of one intent and had drifted before, in both directions. The architecture page <https://timezonefinder.readthedocs.io/en/latest/architecture.html>__ describes the guard from both sides: among the tests that exist to give an invariant a failure mode, and under How it ships as the check on what the built artifacts actually contain
  • the distributions built by the test suite are now built for the interpreter running it. uv build was invoked without --python, so it targeted the newest interpreter on the machine, while tests/test_integration.py creates its throwaway venv from sys.executable: on a checkout whose .venv is older than the newest installed Python, make testint produced a cp314 wheel and failed with pip's "not a supported wheel on this platform". Every tox environment offers a single interpreter, so the two agreed by accident in CI and the mismatch only ever hit developer machines, where the workaround was to pin UV_PYTHON. test_build_commands_pin_the_running_interpreter keeps the pin in place; it needs no build, so it fails in make test rather than waiting on a CI environment that cannot reproduce the mismatch
  • two tests no longer leak numpy's global error state into whatever pytest collects next. np.seterr and the warning filters are process-global, and test_overflow (tests/main_test.py) plus test_inside_polygon (tests/utils_test.py, six parametrisations) each set them and never restored them - so every later test in the same process ran with under promoted from ignore to warn, and which of the two modules pytest collected first decided the state the other ran under. The filters were undone only incidentally, by pytest's per-test catch_warnings(), not by the tests themselves. benchmarks/conftest.py already had the correct pattern; it now lives in tests/auxiliaries.py as the strict_numpy_errors context manager plus a thin strict_numpy_warnings fixture, re-exported through the conftest of each suite, and both call sites request it. The context manager form is what makes the restore directly testable - a leaked global otherwise surfaces only as an unrelated later failure that depends on collection order, which is the hardest kind to attribute
  • the zone id invariants in scripts/timezone_data.py are each enforced in exactly one place, and now have tests. ZoneCollection.validate_structure and zone_positions each walked poly_zone_ids element by element checking it was non-decreasing and each raised the same message built from its own locals; the scan moves into one _validate_non_decreasing helper and zone_positions drops its copy, which could only ever have fired if a caller mutated the array in place - the validator runs at construction and nothing writes to it afterwards. A if min_zone_id < 0 branch is deleted as unreachable: the same method rejects any non-unsigned dtype a dozen lines earlier, so it read as the guard against negative zone ids while being incapable of firing. The class had no tests at all, so what it actually promises - the unsigned-dtype rejection that makes a negative id unrepresentable, the ordering and maximum-id rules, and the shape zone_positions returns - is now pinned by tests/timezone_data_test.py
  • the seven out-of-range coordinates - one representable step outside the valid WGS84 range, per axis and at every corner - are declared once in tests/locations.py instead of verbatim in both tests/main_test.py and tests/utils_test.py, where only one copy carried the comment explaining what makes them interesting and adding a corner to it left the other testing a smaller set
  • the shortcut compilation chain in scripts/shortcuts.py is annotated for what it is actually passed. Both annotations were the wrong way round: check_shortcut_sorting declared np.ndarray and only ever receives the list[int] that optimise_shortcut_ordering returns, and it hands the np.ndarray it derives to has_coherent_sequences(lst: list[int]). Widened rather than swapped, since tests/shortcut_test.py calls the latter with real lists
  • the supported Python versions are declared in five places that cannot read each other - requires-python and one classifier per minor version in pyproject.toml, the py{...} factors of tox.ini's envlist, the test matrix and CIBW_BUILD_VERSIONS in build.yml, and py_limited_api in setup.py - and two "must match" comments said so while nothing enforced them. tests/test_python_version_support.py fails when they drift, in either of the two directions that fail silently: a classifier added without a matrix entry ships a version the package claims to support and CI never runs, and a requires-python raised without moving the abi3 base builds wheels tagged for an interpreter that is no longer supported. Each assertion was checked against the specific one-sided edit it targets, and both comments now name the test
  • the data report generator states figures it derives rather than ones it restates, and its annotations describe what it returns. calculate_shortcut_index_stats took the number of H3 cells existing at the shortcut resolution from a ladder of literals covering resolutions 0 to 4 and fell through, for anything else, to the number of cells actually stored - which reports coverage of exactly 100 % instead of failing - behind an except ImportError that cannot fire, since h3 is a runtime dependency rather than an optional one. It asks h3.get_num_cells, which returns precisely the numbers that were tabulated. Running mypy over scripts/reporting.py, which the pre-commit hook excludes, found seventeen further disagreements between the module and its own signatures: the statistics bag was typed as holding scalars while returning two distributions, load_binary_data's nine-key result was a bare dict indexed by string literal, the table renderer declared string rows while stringifying whatever it is handed, main was annotated None while returning exit codes to exit(), and print_polygon_distribution_table documented a return value it never produced while its one caller discarded it. The two dict results are now TypedDict\ s in scripts/configs.py, carrying tests that assert their keys against what is really returned, since CI cannot type-check scripts/. The polygon count that labels a distribution row is no longer formatted into that label and parsed back out of it to key the example lookup. docs/data_report.rst and the benchmark reports regenerate byte-identically throughout
  • removed five definitions nothing referenced - three JSON/pickle helpers in scripts/utils.py and the import pickle they kept alive, the i8 dtype shim in timezonefinder/_numba_replacements.py that the no-numba fallback never imports, and a test helper self-documented as kept for future reference - and a guard in scripts/hex_utils.py that could not fire. Hex.poly_candidates re-read its cache after initialising it and returned an empty set if it were still unset, which no path through _init_candidates leaves it: an empty set there means "no candidate polygons", so a converter bug would have surfaced as silently missing shortcuts rather than as a failure. The property had no direct test, being reached only through shortcut generation, and now has one. _memory_mode_label looks its two labels up in PARAM_LABELS instead of spelling them out, so renaming the display vocabulary can no longer leave the comparison bullets and the tables above them disagreeing
  • make parse and make testparse run again. Both invoked scripts/file_converter.py by path, which puts scripts/ on sys.path[0] instead of the repository root, so the converter's own from scripts.timezone_data import ... raised ModuleNotFoundError before any work started - a total failure that CI never sees, since it runs neither target. make testparse is the only cheap end-to-end exercise of the converter (update_data.sh needs a ~55 MB download), and nothing under tests/ covers parse_data(), so while it was broken the converter had no smoke test at all. The invocation documented in the usage docs had the same defect and is now the python -m scripts.file_converter form that update_data.sh already used; tests/test_script_invocations.py fails if a by-path invocation returns. Note that parse_data() writes its report to the checkout's committed docs/data_report.rst whatever -out it is given, so make testparse leaves that file describing the three-zone fixture - the target now says so
  • scripts/ is type-checked by the mypy pre-commit hook instead of being excluded from it. The directory holds the data converter and the benchmark tooling - most of the repository's non-library Python - and with nothing running mypy over it the annotations had drifted to fifteen errors: two # type: ignore codes mypy no longer emits, so the ignore silenced nothing; two implicit Optional defaults that no_implicit_optional = true was already configured to reject; a dict annotated with a narrower value type than it is assigned; a bucket key and four bounding-box lists annotated int while Boundaries declares float; and two missing variable annotations. All fixed as annotations, with no runtime change. Two of the four errors mypy reported in tests/auxiliaries.py, which it reaches by following imports out of scripts/, are fixed alongside. test_scripts_are_type_checked_by_the_hook guards the exclude, which is a quieter way to stop type-checking a directory than the ignore_errors list the neighbouring tests already cover: it takes no override entry and reports nothing
  • the eight __del__ cleanup tests that differed only in which exception cleanup() raised, and whether zero or one ResourceWarning was expected, are two parametrized tests over the suppressed and warned exception tuples. Each previously repeated the same subclass, the same catch_warnings block and the same filter, so adding a ninth exception to __del__'s suppression list meant copying the block a ninth time and a copy asserting the wrong count would be invisible. Coverage rises rather than falls: the hand-rolled loop asserting that __del__ never raises to user code now runs over all six exception types instead of four
  • three leftovers in the converter that read as bugs are gone: has_coherent_sequences built an iterator solely to take its first element and then looped from the start anyway (correct, but it reads as an off-by-one), compile_bboxes unpacked a pair and immediately reassigned half of it, and process_single_hex returned the hex_id it was handed so its only caller reassigned the loop variable to itself. Two shadowed builtins (dir as a loop variable, id as a parameter) are renamed and three bare generator signatures annotated. The benchmark renderer classifies its "other" group by name suffix, as the two lines above it do, rather than by deep-equality scan over lists of dicts; and the check-manifest ignore list drops two entries naming files that do not exist (CONTRIBUTING.rst, publish.py). Every converter change was verified by parsing tests/test_input.json before and after and comparing the outputs byte for byte
twilio/twilio-python (twilio)

v9.11.1

Compare Source

Library - Fix

Audiences

  • 2026-09-01

  • Backticked brace- and angle-bracket-bearing tokens in descriptions for MDX safety.
  • Updated a prose reference to the renamed FetchCohortSnapshot operation.
  • 2026-08-26

  • Removed 5 path(s):
  • /preview/Audiences (AdminListAudiences)
  • /preview/Audiences/{audienceId} (AdminGetAudience)
  • /preview/Snapshots (AdminListSnapshots)
  • /preview/Snapshots/{snapshotId} (AdminGetSnapshot)
  • /preview/Operations/{operationId} (AdminGetOperation)
  • 2026-08-25

  • Minor updates (formatting, metadata)
  • 2026-08-24

  • Added 1 new path(s):
  • /preview/Snapshots/{cohortSnapshotId}/Operations (AdminListSnapshotOperations)
  • Removed 1 path(s):
  • /preview/Snapshots/{snapshotId}/Operations (ListAdminSnapshotOperations)
  • 2026-08-20

  • Renamed all 13 operations so the operationId keyword leads (AdminGetCohort -> FetchAdminCohort) to meet standard.
  • Set info libraryVisibility to hidden to exclude this admin spec from generation.
  • Added the standard pageSize/pageToken query parameters to ListAdminSnapshotOperations, the only list operation missing them.
  • 2026-08-19

  • Added 5 new path(s):
  • /preview/Cohorts (AdminListCohorts)
  • /preview/Cohorts/{cohortId} (AdminGetCohort)
  • /preview/CohortSnapshots (AdminListCohortSnapshots)
  • /preview/CohortSnapshots/{cohortSnapshotId} (AdminGetCohortSnapshot)
  • /preview/CohortOperations/{cohortOperationId} (AdminGetCohortOperation)
  • 2026-09-01

  • Renamed 3 Get* operations to Fetch* to match the operationId standard: FetchCohort, FetchCohortSnapshot, FetchCohortOperation. The transpiler skips operations whose operationId does not start with a standard keyword, which had been dropping all three from generated output.
  • Set libraryVisibility to private (was hidden) so the spec is eligible for the private docs pipeline.
  • Backticked brace- and angle-bracket-bearing tokens in descriptions for MDX safety.
  • 2026-08-28

  • Removed 6 path(s):
  • /preview/Audiences (ListAudiences, CreateAudience)
  • /preview/Audiences/{audienceId} (FetchAudience, UpdateAudience, DeleteAudience)
  • /preview/Snapshots (ListSnapshots, CreateSnapshot)
  • /preview/Snapshots/{snapshotId} (FetchSnapshot, DeleteSnapshot)
  • /preview/Snapshots/{snapshotId}/Profiles (ListSnapshotProfiles)
  • /preview/Operations/{operationId} (FetchOperation)
  • 2026-08-20

  • Renamed 6 Get* operations to Fetch* to match the operationId standard.
  • Hid the deprecated Audiences/Snapshots paths and /preview/Operations/{operationId}.
  • Backticked 11 brace-bearing tokens in descriptions for MDX safety.

Conversations

  • Add PATCH support for partial updates to Configuration
  • Add VIDEO to the Conversations v2 Communication channel enum.

Data-ingress

  • API Changes

  • 2026-09-01

  • Minor updates (formatting, metadata)
  • 2026-08-12

  • Minor updates (formatting, metadata)
  • 2026-08-12

  • Initial release with 13 paths and 13 operations

Destinations

  • 2026-09-08

  • Added prod-ie1 to supportedRealms and iamOperationEnabledRealms for all endpoints
  • 2026-09-01

  • Removed the unused admin-api placeholder from supportedRealms on the public endpoints;
  • One Admin routes now live in admin_openapi.yaml.
  • Added 6 new path(s) (admin_openapi.yaml):
  • /v1/ControlPlane/Destinations (AdminListDestinations)
  • /v1/ControlPlane/Destinations/{destinationId} (AdminGetDestination)
  • /v1/ControlPlane/Subscriptions (AdminListSubscriptions)
  • /v1/ControlPlane/Subscriptions/{subscriptionId} (AdminGetSubscription)
  • /v1/ControlPlane/Subscriptions/{subscriptionId}/EventTypes (AdminListSubscribedEvents)
  • /v1/ControlPlane/Subscriptions/{subscriptionId}/EventTypes/{eventType} (AdminGetSubscribedEvent)
  • 2026-08-26

  • Minor updates (formatting, metadata)
  • 2026-08-26

  • Minor updates (formatting, metadata)
  • 2026-08-25

  • Content updates:
  • Updated description for CreateDestination
  • 2026-08-12

  • Minor updates (formatting, metadata)
  • 2026-08-12

  • Content updates:
  • Added properties to DestinationType: releaseStatus
  • Removed properties from DestinationType: maturity

Email

  • API Changes

  • 2026-09-02

  • Added 1 new path(s):
  • /v1/Sends/Cohorts (sendCohort)
  • 2026-08-28

  • Content updates:
  • Updated summary for sendTransactional
  • Added parameter(s) to sendTransactional: X-Twilio-Version
  • Updated schema description for SuppressionsGroup
  • Added properties to SuppressionsGroup: type
  • Removed properties from SuppressionsGroup: mode
  • Updated schema description for SuppressionsGlobal
  • Added properties to SuppressionsGlobal: type
  • Removed properties from SuppressionsGlobal: mode
  • Updated schema description for Suppressions
  • Updated schema description for LongRunningOperationResponse
  • 2026-08-27

  • Content updates:
  • Updated description for SendEmail
  • Added parameter(s) to SendEmail: Content-Encoding, Idempotency-Key
  • Updated schema description for Envelope
  • Updated schema description for SuppressionsGroup
  • Updated schema description for SuppressionsGlobal

Iam

  • Removed redirect_urls from the GET /v1/Account/AuthorizedApps/{consentSid} response
  • Added company_name, homepage_url, tos_url, and redirect_urls to the GET /v1/Account/AuthorizedApps/{consentSid} response
  • Added GET /v1/Account/AuthorizedApps/{consentSid} - fetch authorized app details, including allowed permissions, by consent identifier SID
  • added container-scoped entitlements endpoint (GET /v2/Container/{containerId}/Entitlements)

Instrumentation

  • API Changes

  • 2026-09-04

  • Content updates:
  • Added IdempotencyKeyHeader to Create/Patch/Delete AutoInstrumentationRule; corrected the shared header's description
  • Added operationId/createdAt to LongRunningOperationResponse; corrected example status from RUNNING to PENDING
  • Renamed Signal.timestampoccurredAt, HourlyStats.hourTimestamphourAt; uppercased Signal.type and ListSignals' signalType enums to SCREAMING_SNAKE_CASE
  • Renamed UserBehaviors request/response fields to camelCase; added the summaryDelivery webhook callback
  • Reshaped PaginationMeta (added required key, corrected pageSize bounds) and all 6 list operations (ListEventSources, ListEventSourceDatasets, ListEventSchemas, ListAutoInstrumentationRules, ListSignals, ListSignalStats) to the meta envelope; added ListSignalStats' 500 response
  • Narrowed the domain's default supportedRealms to dev-us1 only; POST /v1/UserBehaviors (AnalyzeUserBehaviors) keeps its own dev-us1/stage-us1 override (prod withheld pending stage validation) — every other operation is now dev-only
  • 2026-08-31

  • Content updates:
  • Fixed stale tdi_ TTID prefix throughout (path params, examples, transaction URLs) to events_; unified dataset/schema ID formats (tdi_dat_/tdi_dataset_events_dataset_, tdi_schema_events_evsch_); fixed rule-version examples to match the real version: integer field
  • Fixed operationId to use the domain-agnostic proc_job_ TTID prefix; corrected the OperationId parameter's length constraint (max=34max=35) and added a pattern
  • Fixed two length constraints hardcoded for the old tdi_ prefix length: IngestEventBatch's sourceId path parameter (maxLength 37 → 40); removed the stale, redundant Twilio-Write-Key header parameter
  • Added the missing AutoInstrumentationRuleId regex pattern
  • Fixed info.title ("Twilio Data Ingress - Instrumentation API" → "Events Domain - Instrumentation API")
  • Added 1 new API path:
  • /v1/UserBehaviors (AnalyzeUserBehaviors)
  • 2026-07-28

  • Initial release — 21 paths, 37 operations across three API surfaces:
  • Control Plane (/v1/ControlPlane/…):
  • /v1/ControlPlane/EventSources (CreateEventSource, ListEventSources)
  • /v1/ControlPlane/EventSources/{sourceId} (FetchEventSource, PatchEventSource, DeleteEventSource)
  • /v1/ControlPlane/EventSources/{sourceId}/WriteKeys (CreateWriteKey, ListWriteKeys)
  • /v1/ControlPlane/EventSources/{sourceId}/WriteKeys/{writeKey} (DeleteWriteKey)
  • /v1/ControlPlane/EventSources/{sourceId}/Datasets (CreateEventSourceDataset, ListEventSourceDatasets)
  • /v1/ControlPlane/EventSources/{sourceId}/Datasets/{datasetId} (FetchEventSourceDataset, PatchEventSourceDataset, DeleteEventSourceDataset)
  • /v1/ControlPlane/EventSources/{sourceId}/EventSchemas (CreateEventSchema, ListEventSchemas)
  • /v1/ControlPlane/EventSources/{sourceId}/EventSchemas/{schemaId} (FetchEventSchema, PatchEventSchema, DeleteEventSchema)
  • /v1/ControlPlane/EventSources/{sourceId}/AutoInstrumentationRules (CreateAutoInstrumentationRule, ListAutoInstrumentationRules)
  • /v1/ControlPlane/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId} (FetchAutoInstrumentationRule, PatchAutoInstrumentationRule, DeleteAutoInstrumentationRule)
  • /v1/ControlPlane/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}/Versions (ListAutoInstrumentationRuleVersions)
  • /v1/ControlPlane/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}/Versions/{version} (FetchAutoInstrumentationRuleVersion)
  • /v1/ControlPlane/Datasets (ListDatasets)
  • /v1/ControlPlane/Datasets/{datasetId} (FetchDataset)
  • /v1/ControlPlane/Operations/{operationId} (FetchControlPlaneOperationStatus)
  • /v1/ControlPlane/Datasets (ListDatasets)
  • /v1/ControlPlane/Datasets/{datasetId} (FetchDataset)
  • Event Ingestion (/v1/EventSources/…):
  • /v1/EventSources/{sourceId}/Batch (IngestEventBatch)
  • /v1/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}/Preview (TriggerAutoInstrumentationPreview)
  • /v1/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}/Preview/{operationId} (GetAutoInstrumentationPreviewResult)
  • Signal API (/v1/EventSources/…):
  • /v1/EventSources/{sourceId}/Signals (IngestSignals, ListSignals)
  • /v1/EventSources/{sourceId}/Signals/{signalKey} (GetSignalBySignalKey)
  • /v1/EventSources/{sourceId}/SignalStats (ListSignalStats)

Knowledge

  • 2026-07-20

  • Content updates:
  • Added new schemas: KnowledgeErrorInstance, KnowledgeErrorGroup
  • Added errors field to WebSourceDetails for reporting web crawl errors

Memory

  • 2026-08-18

  • Breaking change:
  • Removed the deprecated CSV and DATASET values from the DataMappingType enum.
  • INGRESS, DATASET_CLOUDAPP, and DATASET_WAREHOUSE are the only valid values now.
  • Removed the DataMappingFromCSV and DataMappingFromDataSet schemas and their
  • oneOf/discriminator entries on DataMappingFromTypes, along with the corresponding
  • CSV/DATASET discriminator mapping keys.
  • Any caller still sending type: CSV or type: DATASET on AdminListDataMappings
  • (filtering by those values) will get a 400.
  • 2026-08-10

  • No path changes (updated metadata only)
  • DataMappingType gains INGRESS, DATASET_CLOUDAPP, and DATASET_WAREHOUSE.
  • CSV and DATASET remain valid and unchanged; they are deprecated aliases and
  • will be removed in a follow-up change.
  • DataMappingFromTypes gains three oneOf members and three discriminator keys:
  • DataMappingFromIngress (renames DataMappingFromCSV),
  • DataMappingFromCloudAppDataSet and DataMappingFromWarehouseDataSet
  • (both split from DataMappingFromDataSet, distinguishing a cloud-app-backed
  • TDI dataset from a warehouse-backed one).
  • Additive and backwards compatible: existing CSV and DATASET payloads are
  • unaffected.
  • 2026-08-27

  • Added 2 new path(s) for Trait Extraction Strategies:
  • /v1/ControlPlane/TraitExtractionStrategies (ListTraitExtractionStrategies, CreateTraitExtractionStrategy)
  • /v1/ControlPlane/TraitExtractionStrategies/{traitStrategyId} (FetchTraitExtractionStrategy, UpdateTraitExtractionStrategy, DeleteTraitExtractionStrategy)
  • 2026-08-18

  • Breaking change:
  • Removed the deprecated CSV and DATASET values from the DataMappingType enum.
  • INGRESS, DATASET_CLOUDAPP, and DATASET_WAREHOUSE are the only valid values now.
  • Removed the DataMappingFromCSV and DataMappingFromDataSet schemas and their
  • oneOf/discriminator entries on DataMappingFromTypes, along with the corresponding
  • CSV/DATASET discriminator mapping keys.
  • Any caller still sending type: CSV or type: DATASET on CreateDataMapping or
  • UpdateDataMapping (or filtering ListDataMappings/ListDataMappingSuggestions by
  • those values) will get a 400.
  • 2026-08-10

  • No path changes (updated metadata only)
  • DataMappingType gains INGRESS, DATASET_CLOUDAPP, and DATASET_WAREHOUSE.
  • CSV and DATASET remain valid and unchanged; they are deprecated aliases and
  • will be removed in a follow-up change.
  • DataMappingFromTypes gains three oneOf members and three discriminator keys:
  • DataMappingFromIngress (renames DataMappingFromCSV),
  • DataMappingFromCloudAppDataSet and DataMappingFromWarehouseDataSet
  • (both split from DataMappingFromDataSet, distinguishing a cloud-app-backed
  • TDI dataset from a warehouse-backed one).
  • Additive and backwards compatible: existing CSV and DATASET payloads are
  • unaffected.

Messaging

  • Add SenderIdentity, SenderType, and SenderRegion filter query parameters to list numbers and senders endpoint (beta)
  • Add capabilities field to the numbers and senders response (beta)
  • Remove the WhatsApp Senders v1 endpoints (/v1/Channels/WhatsApp/Senders) from RestProxy; the sender was routed to the sunsetting messaging-whatsapp-k8s-orch downstream. Use the Senders v2 API (/v2/Channels/Senders) instead.

Verify

  • Add Templates optional parameter on Verification creation (a stringified JSON array of sid/substitutions entries). When provided, Templates takes precedence over TemplateSid.

Voice

  • 2026-09-03

  • Added links.conversation to Transcription resources as the absolute Conversations API URL for the
  • transcript's conversationId. It is present once the transcript has been stored; the links object
  • is omitted otherwise.
  • 2026-09-01

  • Removed mediaUrl from CreateRequestWithMediaUrl's required fields so a request with neither sourceId nor mediaUrl reaches the downstream service, which rejects it with the specific error code 17500 instead of a generic gateway 400
  • Set additionalProperties: false on both CreateRequestWithSourceId and CreateRequestWithMediaUrl so the two oneOf variants stay mutually exclusive: sourceId is undeclared on the media-URL variant and mediaUrl is undeclared on the source-ID variant, keeping every request shape resolvable to exactly one variant
  • 2026-08-05

  • Added GET /v3/Transcriptions to list and filter transcriptions (status, sourceId, languageCode, createdAfter/createdBefore) with pageSize/pageToken pagination. createdAfter is inclusive and createdBefore exclusive. Returns 422 (error code 17535) when a sourceId's historical item count exceeds the service scan cap

Webhooks

v9.11.0

Compare Source

Library - Fix

Twiml

  • Remove <Assistant> noun from <Connect> verb as part of the AI Assistants deprecation (breaking change)
  • Add passports attribute to <Dial> verb for SHAKEN/STIR passport passthrough

Accounts

  • Add SuppressEmailNotification parameter to the Secondary Auth Token and Auth Token promotion endpoints. Set it to true to suppress the email notification sent to account owners and administrators. Defaults to false, preserving existing behavior.
  • Add SMS Pumping Protection GET and POST API

Ai

  • Removing ai workbench apis

Api

  • Add missing uri property to the twiml_session resource

Data-ingress

  • 2026-08-07

  • Removed 1 API path:
  • /v1/DataQuery (Realtime DataQuery)
  • 2026-07-07

  • Added 1 new API path (data plane):
  • /v1/DataQuery (Realtime DataQuery)
  • 2026-06-17

  • Content updates:
  • Added properties to OAuthJWTBearerCredentials: privateKey, privateKeyPassphrase
  • 2026-06-12

  • Added 16 new path(s):
  • /v1/DataSyncs/{syncId} (FetchDataSync)
  • /v1/CloudAppSources/{sourceId}/Objects (ListCloudAppObjects)
  • /v1/WarehouseSources/{sourceId}/Preview (CreateWarehousePreview)
  • /v1/WarehouseSources/{sourceId}/Preview/{operationId} (FetchWarehousePreview)
  • /v1/DataSample/{operationId} (FetchDataSample)
  • /v1/ControlPlane/CloudAppSources/{sourceId} (FetchCloudAppSource, PatchCloudAppSource, DeleteCloudAppSource)
  • /v1/ControlPlane/CloudAppSources/{sourceId}/Datasets (ListCloudAppDatasets, CreateCloudAppDataset)
  • /v1/ControlPlane/CloudAppSources/{sourceId}/Datasets/{datasetId} (FetchCloudAppDataset, PatchCloudAppDataset, DeleteCloudAppDataset)
  • /v1/ControlPlane/WarehouseSources/{sourceId} (FetchWarehouseSource, PatchWarehouseSource, DeleteWarehouseSource)
  • /v1/ControlPlane/WarehouseSources/{sourceId}/Datasets (ListWarehouseDatasets, CreateWarehouseDataset)
  • ...and 6 more paths
  • Removed 16 path(s):
  • /v1/DataSyncs/{SyncId} (FetchDataSync)
  • /v1/CloudAppSources/{SourceId}/Objects (ListCloudAppObjects)
  • /v1/WarehouseSources/{SourceId}/Preview (CreateWarehousePreview)
  • /v1/WarehouseSources/{SourceId}/Preview/{OperationId} (FetchWarehousePreview)
  • /v1/DataSample/{OperationId} (FetchDataSample)
  • /v1/ControlPlane/CloudAppSources/{SourceId} (FetchCloudAppSource, PatchCloudAppSource, DeleteCloudAppSource)
  • /v1/ControlPlane/CloudAppSources/{SourceId}/Datasets (ListCloudAppDatasets, CreateCloudAppDataset)
  • /v1/ControlPlane/CloudAppSources/{SourceId}/Datasets/{DatasetId} (FetchCloudAppDataset, PatchCloudAppDataset, DeleteCloudAppDataset)
  • /v1/ControlPlane/WarehouseSources/{SourceId} (FetchWarehouseSource, PatchWarehouseSource, DeleteWarehouseSource)
  • /v1/ControlPlane/WarehouseSources/{SourceId}/Datasets (ListWarehouseDatasets, CreateWarehouseDataset)
  • ...and 6 more paths
  • 2026-06-11

  • Added 3 new Signal API path(s) for public exposure (data plane):
  • /v1/EventSources/{sourceId}/Signals (ListSignals)
  • /v1/EventSources/{sourceId}/Signals/{signalKey} (GetSignalBySignalKey)
  • /v1/EventSources/{sourceId}/SignalStats (ListSignalStats)
  • Added new Signal API schemas:
  • Signal, SignalListResponse, HourlyStats, SignalStatsResponse
  • 2026-05-26

  • Added 12 new path(s) for public exposure:
  • /v1/ControlPlane/EventSources (CreateEventSource, ListEventSources)
  • /v1/ControlPlane/EventSources/{SourceId} (FetchEventSource, PatchEventSource, DeleteEventSource)
  • /v1/ControlPlane/EventSources/{SourceId}/WriteKeys (CreateWriteKey, ListWriteKeys)
  • /v1/ControlPlane/EventSources/{SourceId}/WriteKeys/{WriteKey} (DeleteWriteKey)
  • /v1/ControlPlane/EventSources/{SourceId}/Datasets (CreateEventSourceDataset, ListEventSourceDatasets)
  • /v1/ControlPlane/EventSources/{SourceId}/Datasets/{DatasetId} (FetchEventSourceDataset, PatchEventSourceDataset, DeleteEventSourceDataset)
  • /v1/ControlPlane/EventSources/{SourceId}/EventSchemas (CreateEventSchema, ListEventSchemas)
  • /v1/ControlPlane/EventSources/{SourceId}/EventSchemas/{SchemaId} (FetchEventSchema, PatchEventSchema, DeleteEventSchema)
  • /v1/ControlPlane/AutoInstrumentationRule (CreateAutoInstrumentationRule, ListAutoInstrumentationRules)
  • /v1/ControlPlane/AutoInstrumentationRule/{AutoInstrumentationRuleId} (FetchAutoInstrumentationRule, PatchAutoInstrumentationRule, DeleteAutoInstrumentationRule)
  • /v1/ControlPlane/AutoInstrumentationRule/{AutoInstrumentationRuleId}/Versions (ListAutoInstrumentationRuleVersions)
  • /v1/ControlPlane/AutoInstrumentationRule/{AutoInstrumentationRuleId}/Versions/{Version} (FetchAutoInstrumentationRuleVersion)
  • Added new schemas:
  • EventSource, EventSourceCreate, EventSourceUpdate
  • WriteKey, WriteKeyCreate
  • EventSourceDataset, EventSourceDatasetCreate, EventSourceDatasetUpdate
  • EventSchema, EventSchemaCreate, EventSchemaUpdate, EventSchemaField, EventSchemaProperty
  • AutoInstrumentationRule, AutoInstrumentationRuleCreate, AutoInstrumentationRuleUpdate
  • AutoInstrumentationRuleVersion, AutoInstrumentationRuleVersionsResponse
  • 2026-06-12

  • Added 16 new path(s):
  • /v1/DataSyncs/{syncId} (FetchDataSync)
  • /v1/CloudAppSources/{sourceId}/Objects (ListCloudAppObjects)
  • /v1/WarehouseSources/{sourceId}/Preview (CreateWarehousePreview)
  • /v1/WarehouseSources/{sourceId}/Preview/{operationId} (FetchWarehousePreview)
  • /v1/DataSample/{operationId} (FetchDataSample)
  • /v1/ControlPlane/CloudAppSources/{sourceId} (FetchCloudAppSource, PatchCloudAppSource, DeleteCloudAppSource)
  • /v1/ControlPlane/CloudAppSources/{sourceId}/Datasets (ListCloudAppDatasets, CreateCloudAppDataset)
  • /v1/ControlPlane/CloudAppSources/{sourceId}/Datasets/{datasetId} (FetchCloudAppDataset, PatchCloudAppDataset, DeleteCloudAppDataset)
  • /v1/ControlPlane/WarehouseSources/{sourceId} (FetchWarehouseSource, PatchWarehouseSource, DeleteWarehouseSource)
  • /v1/ControlPlane/WarehouseSources/{sourceId}/Datasets (ListWarehouseDatasets, CreateWarehouseDataset)
  • ...and 6 more paths
  • Removed 16 path(s):
  • /v1/DataSyncs/{SyncId} (FetchDataSync)
  • /v1/CloudAppSources/{SourceId}/Objects (ListCloudAppObjects)
  • /v1/WarehouseSources/{SourceId}/Preview (CreateWarehousePreview)
  • /v1/WarehouseSources/{SourceId}/Preview/{OperationId} (FetchWarehousePreview)
  • /v1/DataSample/{OperationId} (FetchDataSample)
  • /v1/ControlPlane/CloudAppSources/{SourceId} (FetchCloudAppSource, PatchCloudAppSource, DeleteCloudAppSource)
  • /v1/ControlPlane/CloudAppSources/{SourceId}/Datasets (ListCloudAppDatasets, CreateCloudAppDataset)
  • /v1/ControlPlane/CloudAppSources/{SourceId}/Datasets/{DatasetId} (FetchCloudAppDataset, PatchCloudAppDataset, DeleteCloudAppDataset)
  • /v1/ControlPlane/WarehouseSources/{SourceId} (FetchWarehouseSource, PatchWarehouseSource, DeleteWarehouseSource)
  • /v1/ControlPlane/WarehouseSources/{SourceId}/Datasets (ListWarehouseDatasets, CreateWarehouseDataset)
  • ...and 6 more paths

Deletions

  • API Changes

  • 2026-06-23

  • Initial public Rest Proxy registration for the User Data Deletions API
  • (POST / GET /v1/UserDataDeletions, GET /v1/UserDataDeletions/{deletionId},
  • GET /v1/Operations/{operationId}).
  • A single request may mix identifier formats: E.164 phone numbers, email
  • addresses, and profile IDs.

Destinations

  • API Changes

  • 2026-08-07

  • Content updates:
  • Updated summary for ListDestinationSupportedEventTypes
  • 2026-08-07

  • Content updates:
  • Updated summary for ListDestinationSupportedEventTypes
  • 2026-08-07

  • Added 3 new path(s):
  • /v1/Catalog/DestinationSupportedEventTypes (ListDestinationSupportedEventTypes)
  • /v1/ControlPlane/Subscriptions/{subscriptionId}/EventTypes (ListSubscribedEvents, CreateSubscribedEvent)
  • /v1/ControlPlane/Subscriptions/{subscriptionId}/EventTypes/{eventType} (GetSubscribedEvent, UpdateSubscribedEvent, DeleteSubscribedEvent)
  • Removed 3 path(s):
  • /v1/ControlPlane/Subscriptions/{subscriptionId}/SubscribedEvents (ListSubscribedEvents, CreateSubscribedEvent)
  • /v1/ControlPlane/Subscriptions/{subscriptionId}/SubscribedEvents/{eventType} (GetSubscribedEvent, UpdateSubscribedEvent, DeleteSubscribedEvent)
  • /v1/Catalog/DestinationEventTypes (ListDestinationEventTypes)
  • 2026-08-04

  • Minor updates (formatting, metadata)
  • 2026-08-04

  • Minor updates (formatting, metadata)
  • 2026-08-04

  • Minor updates (formatting, metadata)
  • 2026-08-04

  • Minor updates (formatting, metadata)
  • 2026-08-04

  • Content updates:
  • Added properties to SubscriptionResponse: eventTypes
  • 2026-08-03

  • Content updates:
  • Added properties to DestinationType: documentationUrl, maturity, tier, categories
  • 2026-07-27

  • Minor updates (formatting, metadata)
  • 2026-07-23

  • Content updates:
  • meta is now a required property in the response of ListDestinations, ListSubscriptions, and ListSubscribedEvents
  • CreateSubscribedEvent request body schema consolidated onto SubscribedEventInput (previously SubscribedEventCreate, a duplicate schema)
  • Added response examples for ListDestinations, ListSubscriptions, and ListSubscribedEvents
  • 2026-07-23

  • Added 1 new path(s):
  • /v1/Catalog/DestinationEventTypes (ListDestinationEventTypes)
  • 2026-07-22

  • Content updates:
  • Added parameter(s) to ListDestinations: namePrefix
  • Updated description for UpdateSubscription
  • Added properties to SubscriptionUpdate: eventTypes
  • 2026-07-16

  • Initial release with 9 paths and 18 operations

Events

  • Add stage-ie1 realm support for EventTypes and Schemas endpoints (datataps-catalog)

Memory

  • 2026-08-10

  • Removed Events endpoints from the spec, as they were hidden, never implemented, and are not part of the public API
  • 2026-08-07

  • New functionality:
  • Added pageSize, pageToken, and orderBy query parameters to ListProfileImportsV2, plus a meta object in its response, to support pagination.
  • Content updates:
  • Updated the ListProfileImportsV2 description to document the new pagination behavior.
  • Corrected the example presigned upload URL on CreateProfilesImportV2 to match the real S3 bucket naming convention.
  • Corrected the meta.key example on ListProfileTraits's response (was profiles, now traits) to accurately describe which response field it points to.
  • 2026-08-07

  • Content updates:
  • Updated matchingRules description in IdentityResolutionSettingsCore to remove compound AND rule documentation
  • 2026-07-30

  • Content updates:
  • Increased the maximum value for the Twilio error code from 99999 to 999999
  • 2026-07-28

  • Content updates:
  • Updated the pageSize description on the pagination Meta schema to clarify it reflects the number of items actually returned, not the requested or default page size.
  • 2026-07-13

  • Content updates:
  • Renamed ListProfiles response schema references from ProfileID/ProfilesMeta to IdentityProfileID/IdentityProfilesMeta (new IdentityProfilesMeta schema added; ProfileID/ProfilesMeta retained for other operations).
  • 2026-07-08

  • Content updates:
  • Updated description for CreateDataMappingSuggestion
  • Updated description for FetchDataMappingSuggestion
  • 2026-07-06

  • Added 2 new path(s):
  • /v1/ControlPlane/Stores/{storeId}/DataMappings/Suggestions (ListDataMappingSuggestions, CreateDataMappingSuggestion)
  • /v1/ControlPlane/Stores/{storeId}/DataMappings/Suggestions/{suggestionId} (FetchDataMappingSuggestion)
  • 2026-06-26

  • Content updates:
  • Minor updates (formatting, metadata)
  • Updated x-twilio location parameter from instance to list for all endpoints that don't end with a /{param}
  • Updated description for UpdateProfileTraits
  • Updated summary for UpdateProfileTraits
  • Removed properties from MappingTraitItem: fieldName
  • Removed additionalProperties from allof schemas since it isn't supported and causes invalid lint errors on example blocks.
  • matruity ga and libraryVisibility public
  • 2026-06-24

  • Content updates:
  • Add ConversationID as an optional query parameter for ListObservations and ListConversationSummaries
  • 2026-05-01

  • Content updates:
  • Updated description & summary for UpdateProfileTraits
  • Updated description for FetchIdentityResolutionSettings
  • Removed properties from MappingTraitItem: fieldName
  • Updated patch Observations to not require occurredAt, content, or source
  • 2026-04-28

  • Content updates:
  • Updated description for UpdateProfileTraits
  • Updated summary for UpdateProfileTraits
  • Added properties to TraitDefinition: validationRule
  • Removed properties from MappingTraitItem: fieldName

Messaging_admin

  • Add Intelligent Alerts endpoints at /v1/Messaging/IntelligentAlertsEvents/*, routing to intelligent-alerts-api via messaging-monkey-backend. Account SID is a required query parameter (accountSid) on all three endpoints.
Kludex/uvicorn (uvicorn)

v0.52.4: Version 0.52.4

Compare Source

Fixed
  • Remove duplicate Date headers from accepted WebSocket handshakes with websockets-sansio (#​3078)

Full Changelog: https://github.com/Kludex/uvicorn/compare/0.52.3...0.52.4

v0.52.3: Version 0.52.3

Compare Source

Changed
  • Update zttp to 0.0.24 and use its combined receive path, improving HTTP/1.1 request parsing performance (#​3067)

Full Changelog: https://github.com/Kludex/uvicorn/compare/0.52.2...0.52.3

v0.52.2: Version 0.52.2

Compare Source

Fixed
  • Update zttp to 0.0.22, fixing bodyless request receives and improving HTTP/1 request parsing performance (#​3063)

Full Changelog: https://github.com/Kludex/uvicorn/compare/0.52.1...0.52.2

v0.52.1: Version 0.52.1

Compare Source

Fixed
  • Complete the closing handshake on server-initiated WebSocket closes in the websockets-sansio and wsproto implementations, waiting for the client's close reply with a 10 second timeout instead of resetting the connection (#​3053)
  • Add missing write flow control to the websockets-sansio implementation, preventing data truncation on server-initiated closes with large in-flight payloads (#​3048)
  • Handle connection loss while a WebSocket write is waiting on backpressure (#​3050)
  • Remove duplicate Content-Type and Content-Length headers from WebSocket denial responses on the websockets-sansio implementation, and deliver non-UTF-8 denial bodies intact (#​3041)

Full Changelog: https://github.com/Kludex/uvicorn/compare/0.52.0...0.52.1

v0.52.0: Version 0.52.0

Compare Source

This release adds an experimental HTTP/1.1 implementation backed by zttp, a sans-IO HTTP parser I've been developing on the side: a core written in Zig, with bindings to Python. It has been running under a fuzzer for some weeks now, and has been through multiple rounds of security auditing.

It is still experimental, so don't put it in front of production traffic yet. Try it with --http zttp, and please send any feedback to the issue tracker.

Added
  • Add an experimental zttp HTTP/1.1 implementation, selectable with --http zttp (#​2979)
Fixed
  • Keep non-ASCII WebSocket request headers intact with websockets 17.0, which encodes them with ISO-8859-1 (#​3036)

Full Changelog: https://github.com/Kludex/uvicorn/compare/0.51.0...0.52.0


Configuration

📅 Schedule: (in timezone America/New_York)

  • Branch creation
    • "before 6am on monday"
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate.

This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [alembic](https://github.com/sqlalchemy/alembic) ([changelog](https://alembic.sqlalchemy.org/en/latest/changelog.html)) | `==1.18.5` → `==1.19.2` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/alembic/1.19.2?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/alembic/1.18.5/1.19.2?slim=true) | | [authlib](https://github.com/authlib/authlib) | `==1.7.2` → `==1.8.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/authlib/1.8.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/authlib/1.7.2/1.8.0?slim=true) | | [fastapi](https://github.com/fastapi/fastapi) ([changelog](https://fastapi.tiangolo.com/release-notes/)) | `==0.140.7` → `==0.141.1` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/fastapi/0.141.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/fastapi/0.140.7/0.141.1?slim=true) | | [pydantic-settings](https://github.com/pydantic/pydantic-settings) ([changelog](https://github.com/pydantic/pydantic-settings/releases)) | `==2.14.2` → `==2.15.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/pydantic-settings/2.15.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/pydantic-settings/2.14.2/2.15.0?slim=true) | | [python-dotenv](https://github.com/theskumar/python-dotenv) | `==1.2.2` → `==1.2.3` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/python-dotenv/1.2.3?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/python-dotenv/1.2.2/1.2.3?slim=true) | | [sqlalchemy](https://www.sqlalchemy.org) ([changelog](https://docs.sqlalchemy.org/en/latest/changelog/)) | `==2.0.51` → `==2.0.52` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/sqlalchemy/2.0.52?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/sqlalchemy/2.0.51/2.0.52?slim=true) | | [timezonefinder](https://github.com/jannikmi/timezonefinder) | `==8.2.5` → `==8.3.0` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/timezonefinder/8.3.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/timezonefinder/8.2.5/8.3.0?slim=true) | | [twilio](https://github.com/twilio/twilio-python) | `==9.10.9` → `==9.11.1` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/twilio/9.11.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/twilio/9.10.9/9.11.1?slim=true) | | [uvicorn](https://github.com/Kludex/uvicorn) ([changelog](https://uvicorn.dev/release-notes)) | `==0.51.0` → `==0.52.4` | ![age](https://developer.mend.io/api/mc/badges/age/pypi/uvicorn/0.52.4?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/uvicorn/0.51.0/0.52.4?slim=true) | --- ### Release Notes <details> <summary>authlib/authlib (authlib)</summary> ### [`v1.8.0`](https://github.com/authlib/authlib/releases/tag/v1.8.0) [Compare Source](https://github.com/authlib/authlib/compare/v1.7.2...v1.8.0) #### What's Changed - Prefer `id_token_signed_response_alg` client metadata to guess algs by [@&#8203;azmeuk](https://github.com/azmeuk) in [#&#8203;888](https://github.com/authlib/authlib/pull/888) - fix: Catch InvalidKeyIdError in RFC 9068 JWTBearerTokenValidator by [@&#8203;liudonggalaxy](https://github.com/liudonggalaxy) in [#&#8203;891](https://github.com/authlib/authlib/pull/891) - fix: make leeway configurable in JWTBearerTokenValidator by [@&#8203;mondi04](https://github.com/mondi04) in [#&#8203;903](https://github.com/authlib/authlib/pull/903) - feat: add default jti claim to sign\_jwt\_bearer\_assertion by [@&#8203;liudonggalaxy](https://github.com/liudonggalaxy) in [#&#8203;897](https://github.com/authlib/authlib/pull/897) - fix(oauth): cast sub claim to string in JWTBearerTokenGenerator by [@&#8203;levinKaus](https://github.com/levinKaus) in [#&#8203;911](https://github.com/authlib/authlib/pull/911) - Declare lower bounds for dependencies by [@&#8203;azmeuk](https://github.com/azmeuk) in [#&#8203;912](https://github.com/authlib/authlib/pull/912) - feat(client): use httpx2 instead of httpx by [@&#8203;levinKaus](https://github.com/levinKaus) in [#&#8203;909](https://github.com/authlib/authlib/pull/909) - Fix RFC7523 malformed claims handling by [@&#8203;azmeuk](https://github.com/azmeuk) in [#&#8203;916](https://github.com/authlib/authlib/pull/916) - Fix httpx oauth1 binary form data by [@&#8203;shc261392](https://github.com/shc261392) in [#&#8203;779](https://github.com/authlib/authlib/pull/779) - fix(starlette\_client): remove default= keyword from config.get calls by [@&#8203;aliaksei-protchanka](https://github.com/aliaksei-protchanka) in [#&#8203;770](https://github.com/authlib/authlib/pull/770) - Added client\_id parameter to AssertionClient by [@&#8203;vilmar-hillow](https://github.com/vilmar-hillow) in [#&#8203;476](https://github.com/authlib/authlib/pull/476) - fix(oauth): save device credential with authenticated client id by [@&#8203;arpitjain099](https://github.com/arpitjain099) in [#&#8203;908](https://github.com/authlib/authlib/pull/908) - fix(oauth1): correct protocol name in InsecureTransportError description by [@&#8203;RavSinghChandan](https://github.com/RavSinghChandan) in [#&#8203;919](https://github.com/authlib/authlib/pull/919) - fix(client): client can be flexible with jwt's header by [@&#8203;lepture](https://github.com/lepture) in [#&#8203;922](https://github.com/authlib/authlib/pull/922) - fix(oidc): omit claims when the value is None by [@&#8203;lepture](https://github.com/lepture) in [#&#8203;923](https://github.com/authlib/authlib/pull/923) #### New Contributors - [@&#8203;mondi04](https://github.com/mondi04) made their first contribution in [#&#8203;903](https://github.com/authlib/authlib/pull/903) - [@&#8203;levinKaus](https://github.com/levinKaus) made their first contribution in [#&#8203;911](https://github.com/authlib/authlib/pull/911) - [@&#8203;aliaksei-protchanka](https://github.com/aliaksei-protchanka) made their first contribution in [#&#8203;770](https://github.com/authlib/authlib/pull/770) - [@&#8203;vilmar-hillow](https://github.com/vilmar-hillow) made their first contribution in [#&#8203;476](https://github.com/authlib/authlib/pull/476) - [@&#8203;arpitjain099](https://github.com/arpitjain099) made their first contribution in [#&#8203;908](https://github.com/authlib/authlib/pull/908) - [@&#8203;RavSinghChandan](https://github.com/RavSinghChandan) made their first contribution in [#&#8203;919](https://github.com/authlib/authlib/pull/919) **Full Changelog**: <https://github.com/authlib/authlib/compare/v1.7.2...v1.8.0> </details> <details> <summary>fastapi/fastapi (fastapi)</summary> ### [`v0.141.1`](https://github.com/fastapi/fastapi/releases/tag/0.141.1) [Compare Source](https://github.com/fastapi/fastapi/compare/0.141.0...0.141.1) ##### Fixes - 🐛 Fix support for background tasks and headers from dependencies in `app.frontend()`. PR [#&#8203;16105](https://github.com/fastapi/fastapi/pull/16105) by [@&#8203;tiangolo](https://github.com/tiangolo). ##### Docs - 📝 Document `FASTAPI_ENV` in FastAPI CLI guide. PR [#&#8203;16104](https://github.com/fastapi/fastapi/pull/16104) by [@&#8203;tiangolo](https://github.com/tiangolo). ### [`v0.141.0`](https://github.com/fastapi/fastapi/releases/tag/0.141.0) [Compare Source](https://github.com/fastapi/fastapi/compare/0.140.13...0.141.0) ##### Features - ✨ Add `app.frontend(check_dir="auto")`, to make local development more convenient with `fastapi dev`. PR [#&#8203;16102](https://github.com/fastapi/fastapi/pull/16102) by [@&#8203;tiangolo](https://github.com/tiangolo). ### [`v0.140.13`](https://github.com/fastapi/fastapi/releases/tag/0.140.13) [Compare Source](https://github.com/fastapi/fastapi/compare/0.140.12...0.140.13) ##### Fixes - 🐛 Fix `status_code` being ignored for SSE and JSONL streaming endpoints. PR [#&#8203;15937](https://github.com/fastapi/fastapi/pull/15937) by [@&#8203;SAURABHSALVE](https://github.com/SAURABHSALVE). ##### Docs - 📝 Fix `format_sse_event` docstring rendering of `\n\n` terminator. PR [#&#8203;15613](https://github.com/fastapi/fastapi/pull/15613) by [@&#8203;AshNicolus](https://github.com/AshNicolus). - 📝 Add API reference page for fastapi.sse. PR [#&#8203;15930](https://github.com/fastapi/fastapi/pull/15930) by [@&#8203;SAURABHSALVE](https://github.com/SAURABHSALVE). ### [`v0.140.12`](https://github.com/fastapi/fastapi/releases/tag/0.140.12) [Compare Source](https://github.com/fastapi/fastapi/compare/0.140.11...0.140.12) ##### Fixes - 🐛 Fix line splitting in `format_sse_event` to comply with SSE spec. PR [#&#8203;15515](https://github.com/fastapi/fastapi/pull/15515) by [@&#8203;Zawwarsami16](https://github.com/Zawwarsami16). ### [`v0.140.11`](https://github.com/fastapi/fastapi/releases/tag/0.140.11) [Compare Source](https://github.com/fastapi/fastapi/compare/0.140.10...0.140.11) ##### Fixes - 🐛 Fix `response_model_*` params ignored for non-generator endpoints with `Iterable[..]` return type. PR [#&#8203;15093](https://github.com/fastapi/fastapi/pull/15093) by [@&#8203;YuriiMotov](https://github.com/YuriiMotov). ### [`v0.140.10`](https://github.com/fastapi/fastapi/releases/tag/0.140.10) [Compare Source](https://github.com/fastapi/fastapi/compare/0.140.9...0.140.10) ##### Fixes - 🐛 Fix handling sequences with nested Annotated types. PR [#&#8203;14874](https://github.com/fastapi/fastapi/pull/14874) by [@&#8203;YuriiMotov](https://github.com/YuriiMotov). ##### Internal - 🐛 Accept any base test failure as regression. PR [#&#8203;16092](https://github.com/fastapi/fastapi/pull/16092) by [@&#8203;tiangolo](https://github.com/tiangolo). - 🐛 Preserve pytest exit code in regression check. PR [#&#8203;16091](https://github.com/fastapi/fastapi/pull/16091) by [@&#8203;tiangolo](https://github.com/tiangolo). - ✅ Test PR regressions against base code. PR [#&#8203;16090](https://github.com/fastapi/fastapi/pull/16090) by [@&#8203;tiangolo](https://github.com/tiangolo). ### [`v0.140.9`](https://github.com/fastapi/fastapi/releases/tag/0.140.9) [Compare Source](https://github.com/fastapi/fastapi/compare/0.140.8...0.140.9) ##### Fixes - 🐛 Fix `exclude_defaults` not propagated to dict keys and values in `jsonable_encoder`. PR [#&#8203;16043](https://github.com/fastapi/fastapi/pull/16043) by [@&#8203;MBGrao](https://github.com/MBGrao). ##### Internal - ⬆ Bump gitpython from 3.1.50 to 3.1.54. PR [#&#8203;16047](https://github.com/fastapi/fastapi/pull/16047) by [@&#8203;dependabot\[bot\]](https://github.com/apps/dependabot). - ⬆ Bump pymdown-extensions from 10.21.3 to 11.0. PR [#&#8203;16048](https://github.com/fastapi/fastapi/pull/16048) by [@&#8203;dependabot\[bot\]](https://github.com/apps/dependabot). - ⬆ Bump pyasn1 from 0.6.3 to 0.6.4. PR [#&#8203;16045](https://github.com/fastapi/fastapi/pull/16045) by [@&#8203;dependabot\[bot\]](https://github.com/apps/dependabot). ### [`v0.140.8`](https://github.com/fastapi/fastapi/releases/tag/0.140.8) [Compare Source](https://github.com/fastapi/fastapi/compare/0.140.7...0.140.8) ##### Fixes - 🐛 Fix stream item type lost when using `include_router()`. PR [#&#8203;15077](https://github.com/fastapi/fastapi/pull/15077) by [@&#8203;alex-raw](https://github.com/alex-raw). </details> <details> <summary>pydantic/pydantic-settings (pydantic-settings)</summary> ### [`v2.15.0`](https://github.com/pydantic/pydantic-settings/releases/tag/v2.15.0) [Compare Source](https://github.com/pydantic/pydantic-settings/compare/v2.14.2...v2.15.0) #### Highlights ##### Behavior changes - **`case_sensitive` now applies to init kwargs and config-file sources** ([#&#8203;900](https://github.com/pydantic/pydantic-settings/pull/900)). `InitSettingsSource` and the JSON/TOML/YAML config sources previously ignored `case_sensitive`. Since it defaults to `False`, **case-insensitive matching is now the default** for these sources — e.g. `Settings(TeSt=...)` now populates a `test` field where it previously did not. Nested keys are still matched case-sensitively. - **Fields with unresolved forward references now emit a warning** ([#&#8203;901](https://github.com/pydantic/pydantic-settings/pull/901)). Settings sources can silently fail to resolve such fields; they now raise `IncompleteFieldDefinitionWarning` telling you to call `model_rebuild()`. If you have `filterwarnings = error` configured, this may surface as a new failure. - **Non-JSON env values for strict fields now raise `ValidationError`** ([#&#8203;926](https://github.com/pydantic/pydantic-settings/pull/926)) instead of a less specific error. ##### New features - **Show environment variable names in CLI help** via `cli_show_env_vars=True` ([#&#8203;860](https://github.com/pydantic/pydantic-settings/pull/860)), so generated `--help` output doubles as configuration documentation. - **`PYDANTIC_SETTINGS_DEBUG` for debugging settings resolution** ([#&#8203;906](https://github.com/pydantic/pydantic-settings/pull/906), [#&#8203;913](https://github.com/pydantic/pydantic-settings/pull/913)). Set it to a truthy value with `DEBUG` logging enabled to see each source's contribution in priority order, which source won for each value, and which `env_file`/secret files were probed, loaded, or skipped — the long-standing "why isn't my `.env` being picked up?" question. - **`toml_table_header` for regular TOML files** ([#&#8203;882](https://github.com/pydantic/pydantic-settings/pull/882), [#&#8203;886](https://github.com/pydantic/pydantic-settings/pull/886), [#&#8203;887](https://github.com/pydantic/pydantic-settings/pull/887)), letting you root settings at a nested table in any TOML file, not just `pyproject.toml`. - **`Traversable` support for JSON/TOML/YAML file sources** ([#&#8203;902](https://github.com/pydantic/pydantic-settings/pull/902)), so you can load config packaged inside a distribution — including files inside a zip or wheel — via `importlib.resources.files(...)` without casting to `Path`. - **GCP: `project_id` can come from an earlier settings source** ([#&#8203;878](https://github.com/pydantic/pydantic-settings/pull/878)), rather than only from the constructor or `GOOGLE_CLOUD_PROJECT`. ##### Bug fixes - Fix env vars not loading on Windows with `case_sensitive=True` ([#&#8203;894](https://github.com/pydantic/pydantic-settings/pull/894)). Windows upper-cases `os.environ` keys, so fields raised `Field required` instead of picking up their values. - Read secret files as UTF-8 instead of the platform locale encoding ([#&#8203;917](https://github.com/pydantic/pydantic-settings/pull/917)). On Windows code pages such as cp1252 this silently corrupted non-ASCII secrets. - Fix `AliasPath` on nested model fields not JSON-decoding env values ([#&#8203;898](https://github.com/pydantic/pydantic-settings/pull/898)). - Fix case-insensitive matching for **optional** nested models ([#&#8203;905](https://github.com/pydantic/pydantic-settings/pull/905)). - Fix dotenv extras being wrongly claimed by a complex field sharing a name prefix ([#&#8203;912](https://github.com/pydantic/pydantic-settings/pull/912)) — e.g. `dbx_token` being swallowed by a `db: dict` field. - Fix `nested_model_default_partial_update=True` corrupting discriminated unions ([#&#8203;876](https://github.com/pydantic/pydantic-settings/pull/876)). - Fix `Secret` subclasses crashing when loaded from the environment ([#&#8203;920](https://github.com/pydantic/pydantic-settings/pull/920)). - Fix enum names not parsing through nested annotations such as `Optional[Annotated[MyEnum, ...]]` with `env_parse_enums=True` ([#&#8203;910](https://github.com/pydantic/pydantic-settings/pull/910)). - An empty `yaml_config_section` now falls back to defaults instead of raising `AttributeError: 'NoneType' object has no attribute 'keys'` ([#&#8203;914](https://github.com/pydantic/pydantic-settings/pull/914)). - `NestedSecretsSettingsSource` no longer follows symlinks pointing outside `secrets_dir` ([#&#8203;889](https://github.com/pydantic/pydantic-settings/pull/889)). - GCP: skip the `list_secrets` call when `case_sensitive=True` ([#&#8203;862](https://github.com/pydantic/pydantic-settings/pull/862)), lowering the required IAM permissions to just `roles/secretmanager.secretAccessor`. - AWS: `types-boto3[secretsmanager]` is no longer required at runtime ([#&#8203;880](https://github.com/pydantic/pydantic-settings/pull/880)). ##### Documentation - Document JSON parsing of complex env values, plus a comma-separated-values recipe ([#&#8203;919](https://github.com/pydantic/pydantic-settings/pull/919)). - Recommend an async settings loading pattern ([#&#8203;908](https://github.com/pydantic/pydantic-settings/pull/908)). - Clarify behavior when an unprefixed value is present in a dotenv file ([#&#8203;895](https://github.com/pydantic/pydantic-settings/pull/895)). - Clarify environment variable helper descriptions ([#&#8203;867](https://github.com/pydantic/pydantic-settings/pull/867)) and fix assorted typos ([#&#8203;904](https://github.com/pydantic/pydantic-settings/pull/904)). <details> <summary><b>All changes</b> (including dependency bumps and internal maintenance)</summary> #### What's Changed * Update documentation link for Pydantic settings by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/863 * Bump the python-packages group with 4 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/865 * docs: clarify environment variable helper descriptions by @&#8203;vip892766gma in https://github.com/pydantic/pydantic-settings/pull/867 * Bump the python-packages group with 4 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/870 * Bump the python-packages group with 4 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/875 * Skip list_secrets call when case_sensitive=True by @&#8203;ecerulm in https://github.com/pydantic/pydantic-settings/pull/862 * GoogleSecretManagerSettingsSource: read project_id from previous sources by @&#8203;ecerulm in https://github.com/pydantic/pydantic-settings/pull/878 * Bump the python-packages group with 3 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/883 * fix: move SecretsManagerClient type import under TYPE_CHECKING by @&#8203;gavin913-lss in https://github.com/pydantic/pydantic-settings/pull/880 * Skip partial update merging for discriminated union fields by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/876 * Support using a table header as root when reading a TOML file by @&#8203;whyscream in https://github.com/pydantic/pydantic-settings/pull/882 * Bump the python-packages group with 4 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/885 * Don't complain about missing table headers in a TOML file that isn't there by @&#8203;whyscream in https://github.com/pydantic/pydantic-settings/pull/886 * Address issues in toml table header implementation by @&#8203;whyscream in https://github.com/pydantic/pydantic-settings/pull/887 * Bump the python-packages group with 2 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/888 * Prevent NestedSecretsSettingsSource from following symlinks outside secrets_dir by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/889 * Add 'Part of the Pydantic Stack' footer to README by @&#8203;strawgate in https://github.com/pydantic/pydantic-settings/pull/891 * Bump the python-packages group with 3 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/893 * Add support for showing environment variable names in CLI help text by @&#8203;brad-alexander in https://github.com/pydantic/pydantic-settings/pull/860 * Fix loading env vars on Windows with case_sensitive=True by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/894 * Bump the github-actions group with 3 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/896 * Bump the python-packages group with 3 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/897 * Add explicit callout for the case where the unprefixed value is in dotenv by @&#8203;martinky24 in https://github.com/pydantic/pydantic-settings/pull/895 * Fix AliasPath on nested model fields not decoding env values (#&#8203;670) by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/898 * Support case_sensitive in InitSettingsSource and config file sources by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/900 * Warn when using fields not fully resolved at instantiation by @&#8203;Viicos in https://github.com/pydantic/pydantic-settings/pull/901 * Support Traversable for json/toml/yaml config file sources (#&#8203;299) by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/902 * docs: fix typos in docs and source comments by @&#8203;maxtaran2010 in https://github.com/pydantic/pydantic-settings/pull/904 * Apply case-insensitive field matching to optional nested models (#&#8203;903) by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/905 * Bump boto3 from 1.43.36 to 1.43.40 in the python-packages group by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/907 * Add PYDANTIC_SETTINGS_DEBUG for debugging settings sources (#&#8203;538) by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/906 * docs: recommend async settings loading pattern by @&#8203;w3lld1 in https://github.com/pydantic/pydantic-settings/pull/908 * fix: parse enum names through nested annotations by @&#8203;Sanjays2402 in https://github.com/pydantic/pydantic-settings/pull/910 * Fix dotenv extras being claimed by complex fields sharing a name prefix by @&#8203;ritsth in https://github.com/pydantic/pydantic-settings/pull/912 * Add debug logging for env_file and secret file resolution by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/913 * docs: document JSON parsing of complex env values + comma-separated recipe by @&#8203;hrithvikakb in https://github.com/pydantic/pydantic-settings/pull/919 * fix: coerce empty yaml_config_section to an empty mapping instead of crashing by @&#8203;chuenchen309 in https://github.com/pydantic/pydantic-settings/pull/914 * Bump the python-packages group with 3 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/915 * fix: read secret files as UTF-8 instead of the locale encoding by @&#8203;dchaudhari7177 in https://github.com/pydantic/pydantic-settings/pull/917 * Bump the python-packages group with 4 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/921 * Bump the github-actions group with 4 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/925 * Bump the python-packages group with 4 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/924 * fix: treat Secret subclasses as non-complex fields (#&#8203;716) by @&#8203;Rony-ZenAlden in https://github.com/pydantic/pydantic-settings/pull/920 * fix: raise ValidationError for non-JSON env values on strict fields by @&#8203;shuvamk in https://github.com/pydantic/pydantic-settings/pull/926 * test: move function-local imports to the top of test modules by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/927 * Bump the python-packages group with 4 updates by @&#8203;dependabot[bot] in https://github.com/pydantic/pydantic-settings/pull/929 * Prepare release 2.15.0 by @&#8203;hramezani in https://github.com/pydantic/pydantic-settings/pull/930 #### New Contributors * @&#8203;vip892766gma made their first contribution in https://github.com/pydantic/pydantic-settings/pull/867 * @&#8203;ecerulm made their first contribution in https://github.com/pydantic/pydantic-settings/pull/862 * @&#8203;gavin913-lss made their first contribution in https://github.com/pydantic/pydantic-settings/pull/880 * @&#8203;whyscream made their first contribution in https://github.com/pydantic/pydantic-settings/pull/882 * @&#8203;strawgate made their first contribution in https://github.com/pydantic/pydantic-settings/pull/891 * @&#8203;brad-alexander made their first contribution in https://github.com/pydantic/pydantic-settings/pull/860 * @&#8203;martinky24 made their first contribution in https://github.com/pydantic/pydantic-settings/pull/895 * @&#8203;maxtaran2010 made their first contribution in https://github.com/pydantic/pydantic-settings/pull/904 * @&#8203;w3lld1 made their first contribution in https://github.com/pydantic/pydantic-settings/pull/908 * @&#8203;Sanjays2402 made their first contribution in https://github.com/pydantic/pydantic-settings/pull/910 * @&#8203;ritsth made their first contribution in https://github.com/pydantic/pydantic-settings/pull/912 * @&#8203;hrithvikakb made their first contribution in https://github.com/pydantic/pydantic-settings/pull/919 * @&#8203;chuenchen309 made their first contribution in https://github.com/pydantic/pydantic-settings/pull/914 * @&#8203;dchaudhari7177 made their first contribution in https://github.com/pydantic/pydantic-settings/pull/917 * @&#8203;Rony-ZenAlden made their first contribution in https://github.com/pydantic/pydantic-settings/pull/920 * @&#8203;shuvamk made their first contribution in https://github.com/pydantic/pydantic-settings/pull/926 **Full Changelog**: <https://github.com/pydantic/pydantic-settings/compare/v2.14.1...v2.15.0> </details> </details> <details> <summary>theskumar/python-dotenv (python-dotenv)</summary> ### [`v1.2.3`](https://github.com/theskumar/python-dotenv/blob/HEAD/CHANGELOG.md#123---2026-08-16) [Compare Source](https://github.com/theskumar/python-dotenv/compare/v1.2.2...v1.2.3) ##### Fixed - Strip a leading UTF-8 BOM from `.env` file contents so the first variable is no longer silently lost when the file is saved with BOM (e.g. by some JetBrains IDEs on Windows) by \[[@&#8203;h1whelan](https://github.com/h1whelan)] in \[[#&#8203;640](https://github.com/theskumar/python-dotenv/issues/640)] - `set_key` now escapes backslashes, so values containing them (Windows paths, regular expressions) survive a write/read round-trip. Quoted values ending in an escaped backslash are no longer mis-parsed as an escaped quote, which used to swallow the following lines by \[[@&#8203;dchaudhari7177](https://github.com/dchaudhari7177)] in \[[#&#8203;680](https://github.com/theskumar/python-dotenv/issues/680)] - `dotenv run` now prints a friendly error instead of a traceback when no command is given by \[[@&#8203;bbc2](https://github.com/bbc2)] in \[[#&#8203;606](https://github.com/theskumar/python-dotenv/issues/606)] - Cache the parsed result for empty `.env` files so repeated `dotenv_values`/`load_dotenv` calls no longer re-read the file by \[[@&#8203;ReinerBRO](https://github.com/ReinerBRO)] in \[[#&#8203;638](https://github.com/theskumar/python-dotenv/issues/638)] </details> <details> <summary>jannikmi/timezonefinder (timezonefinder)</summary> ### [`v8.3.0`](https://github.com/jannikmi/timezonefinder/blob/HEAD/CHANGELOG.rst#830-2026-08-19) [Compare Source](https://github.com/jannikmi/timezonefinder/compare/8.2.5...8.3.0) - the dataset version is now exposed at runtime. `TimezoneFinder().data_version` (and `TimezoneFinderL().data_version`) return the timezone-boundary-builder release the packaged data was built from, read from a `data_version.txt` stamp that `scripts/file_converter.py` writes into the data directory it generates and that ships in the wheel. Previously an installed `timezonefinder` could not state it at all: the release tag lived only in a repo-root file that is not packaged. Which release a parse is stamped with comes from the input's filename (`combined-with-oceans-2026c.json`, which `update_data.sh` now produces), or from `scripts/file_converter.py --data-version` for an input that cannot carry it; your own GeoJSON is stamped `"unknown"`, and an unpacked release archive that lost its tag is refused rather than compiled into data that could never say where it came from. `timezonefinder.__version__` is now exposed as well, read from the installed distribution metadata. Solves issue [#&#8203;498](https://github.com/jannikmi/timezonefinder/issues/498) - fixed a `BufferError: cannot close exported pointers exist` raised during resource cleanup in file mode (`in_memory=False`). A coordinate array obtained from `coords_of()` is a zero-copy view onto the memory-mapped file, and `mmap.close()` refuses to unmap while one is alive, so an array outliving its `TimezoneFinder` raised on cleanup. The mapping now stays valid instead of leaving the views dangling, and `FileCoordAccessor.cleanup()` releases its own references so the deferred close happens as soon as the last view is dropped. The accessor must not be used after `cleanup()` - polygon coordinates are now stored one axis at a time in the packaged `coordinates.bin` files - all x values followed by all y values per polygon, instead of interleaved. The point in polygon test scans a single axis per iteration, so contiguous per-axis blocks halve the cache lines it touches: \~1.6x faster on a median polygon and \~2.5x faster on the largest ones via the C extension, 14-25% faster via Numba. The bundled data was regenerated accordingly, and the layout is described in the `data format documentation <https://timezonefinder.readthedocs.io/en/latest/data_format.html>`\_\_ - every packaged FlatBuffers file now carries a file identifier and a layout version, and `TimezoneFinder` raises a `ValueError` naming the offending file when either does not match - previously such a directory was read without complaint and produced wrong timezones. For `coordinates.bin` the version records how the coordinates are encoded and which polygons the file holds. The hybrid shortcut binaries get an identifier that differs per zone id width, because the uint8 and uint16 schemas differ only in the width of a zone id and each parses cleanly as the other; the width is now read from the buffer instead of being guessed from the file name, so a renamed or mispaired shortcut file fails loudly rather than returning wrong zones. If you compile your own data and point `bin_file_location` at it, regenerate it once with `scripts/file_converter.py`, since the coordinate layout, the hole storage, the shortcut container and the file names all changed in this release. The markers track what a file holds rather than the package version, so this is not a per-release obligation. Solves issue [#&#8203;458](https://github.com/jannikmi/timezonefinder/issues/458) - the memory footprint of every finder configuration is now measured and published in a new `memory report <https://timezonefinder.readthedocs.io/en/latest/benchmark_results_memory.html>`\_\_, separating what a configuration allocates (`tracemalloc`) from what it makes resident (RSS, which additionally counts memory-mapped pages). The distinction is the point: the default mode maps the coordinate data instead of reading it, so it allocates an order of magnitude less than the in-memory mode, and only the pages a lookup actually touches become resident. This replaces documentation claiming a 40MB process ceiling and a 41MB data directory, both long out of date - restructured the two entry points a reader actually arrives at - `README.rst` and the `documentation landing page <https://timezonefinder.readthedocs.io/en/latest/>`\_\_ - so both state what the package is and how it works instead of only what it is called. The README opens with the project banner and a one-sentence statement of what the package is for, then the badges, then the quick guide - and adds three short sections that were missing entirely: *How it works* (the lookup pipeline and the no-simplification trade-off), *Performance* (a concrete throughput figure with its configuration named, the three point-in-polygon backends and the pure-Python fallback), and *Engineering notes* linking the architecture, data format and benchmarking methodology pages. The maintainers-wanted notice moves from the first heading after the intro into a new `Contributing` section at the bottom, which also links `CONTRIBUTING.md` for the first time. The badge block is corrected along the way: the `code style: black` badge named a formatter this project has never used and is replaced by `ruff`, and a supported-Python-versions badge was added. The banner is referenced by absolute URL, since PyPI serves the long description without the repository and a `docs/…` path renders as a broken image there. The landing page gains the same *How it works* summary, the no-simplification trade-off and the ocean-zone consequence for `timezone_at()`, and its flat seventeen-entry table of contents is grouped into *Using it*, *Design*, *Performance* and *Project*, so the sidebar says what kind of project this is rather than listing pages in the order they were written - rewrote the `package comparison <https://timezonefinder.readthedocs.io/en/latest/alternatives.html>`\_\_ page. It now states its position in prose before the first table - border correctness is what this package optimises for, speed is the constraint that work happens under - and says plainly when `tzfpy` is the better choice. Every quantitative cell names what it measures and links its source, and the speed row is deliberately qualitative on both sides, with a note explaining that the two packages have never been benchmarked under one harness. The decision table drops the rows on which the two packages do not differ - two new documentation pages: `Architecture <https://timezonefinder.readthedocs.io/en/latest/architecture.html>`\_\_ describes the lookup pipeline, the three point-in-polygon backends and the memory modes, and states the ceilings this package deliberately does not exceed - unsimplified geometry, \~1 cm coordinate resolution, no general-purpose spatial code. It also documents how the package is built and shipped, which was previously described nowhere outside the workflow YAML: why one abi3 wheel per target replaces one wheel per Python version and what `abi3audit` is guarding, why three libc targets are built, why the end-to-end job installs the built wheel and asserts the C extension loaded rather than merely importing the package, and why a tag pushed from outside `master` aborts the release. The testing section gained the property-based suite and the reason the tox matrix is a matrix - the acceleration paths are bound at import time, so a passing run describes one configuration only. Both sections are linked from the README's *Engineering notes*. `Benchmarking Methodology <https://timezonefinder.readthedocs.io/en/latest/benchmarking_methodology.html>`\_\_ documents how the published numbers are produced and what they can and cannot tell you: `ubuntu-latest` pins the runner image and not the CPU, which is why a pull request is measured against its own merge base on the same runner and why every alert threshold is derived from measured noise. It was previously addressed only to contributors, in the second half of `CONTRIBUTING.md`, which now keeps the operational instructions and links to it - the H3 resolution choice in the `data format documentation <https://timezonefinder.readthedocs.io/en/latest/data_format.html>`\_\_ is no longer asserted to "offer a good balance" but reports the study behind it (`prototypes/single_resolution_bench.py`): resolution 3 keeps the hybrid index at a small fraction of the packaged polygon data, while resolution 4 would exceed 10 % of it for gains that do not justify the increase - the hand-written documentation no longer restates exact figures that belong to the generated pages - dataset vertex, polygon and hole counts, index and distribution sizes, memory footprints, lookup throughput. Those change with every data update and with code that shifts a footprint, which silently left the copies wrong: the memory figures had already gone stale in four places. The prose now states the magnitude that survives a data update and links `the data report <https://timezonefinder.readthedocs.io/en/latest/data_report.html>`\_\_ or the relevant `benchmark report <https://timezonefinder.readthedocs.io/en/latest/7_performance.html>`\_\_, which are regenerated from the packaged data and are always current - the three weakest hand-written documentation pages no longer answer a question by pointing at a file the reader has to open. The `performance page <https://timezonefinder.readthedocs.io/en/latest/7_performance.html>`\_\_ now opens with the four benchmark reports and the trend chart instead of a bullet list of adjectives about the binary format, and its C extension and Numba sections are cut to what a user does - which call reports the active backend - with the explanation left to the architecture page that already carried a more precise version of it. *Getting started* lists the four runtime dependencies and what each is for, where it previously said to consult `pyproject.toml`, which remains linked as the authoritative source for version ranges. The use case pages carry runnable snippets for building an aware `datetime` and reading a UTC offset, with the `examples/` scripts as the follow-up rather than the whole answer; the snippets use the standard library's `zoneinfo`, so neither needs an optional dependency - the shortcut entry distributions in the `data report <https://timezonefinder.readthedocs.io/en/latest/data_report.html>`\_\_ no longer report three quarters of all H3 cells as holding `0` polygons, which is impossible for data whose ocean zones cover the globe. Those cells are covered by a single timezone and store its id directly, so a lookup there needs no point-in-polygon test at all - the column is now *Polygons to test* and the row reads *none (unique zone)*. The tables are introduced by a sentence on what they measure, including why no cell ever needs exactly one test - the hybrid shortcut loader no longer keeps the entire shortcut binary in memory. The polygon id arrays it returns were zero-copy views onto the \~1.5 MB file buffer, so \~47 KB of live data pinned the whole thing for the lifetime of every `TimezoneFinder` / `TimezoneFinderL` instance. They are now disjoint read-only slices of a single compact array, cutting the shortcut mapping's footprint from \~7.4 MB to \~4.7 MB per instance, and every finder's resident set by \~2 MB, at unchanged initialisation time - which matters most for concurrent workloads, where the recommended one-instance-per-thread pattern multiplied the waste - the usage examples in `README.rst` and the `usage documentation <https://timezonefinder.readthedocs.io/en/latest/1_usage.html>`\_\_ now show the result the packaged data actually returns. Every snippet queries the same Berlin coordinates and annotated the answer as `'Europe/Paris'`, which is the value from the reduced `timezones-now` dataset, where `Europe/Berlin` is merged into `Europe/Paris` - not from the full dataset the package ships by default. All eleven annotations now read `'Europe/Berlin'`, verified against the packaged data for each of `timezone_at()`, `timezone_at_land()`, `certain_timezone_at()`, `unique_timezone_at()` and `TimezoneFinderL`, and the `get_geometry()` call in the opening example asks for that same zone instead of a different one. `tests/test_documented_contracts.py` now re-runs each of those documented lookups, so a data update that moves the example coordinate's zone fails there rather than leaving every snippet on both pages quietly wrong again - holes that duplicate a timezone boundary polygon are no longer stored twice. Almost every hole is an enclave, cut into the surrounding zone with exactly the ring the upstream data also emits as the enclosed zone's own boundary polygon - the same geometry under two IDs. The packaged hole coordinate file now holds only the rings with no such twin (27 of 756 in the current data), and a new `holes/poly_ref.npy` records per hole which boundary polygon to read instead. Hole data drops from \~2.0 MiB to \~0.16 MiB, and `in_memory=True` saves the same amount of RAM, since those holes now resolve into the boundary arrays rather than materialising a second copy. Matching is exact - rings are compared as integer coordinates in a canonical form, with bounding boxes used only to narrow the search - so every timezone lookup returns what it did before. One visible consequence: `get_geometry()` may hand back a deduplicated hole ring starting at a different vertex or winding the other way than it used to, tracing the same closed path. The encoding is described in the `data format documentation <https://timezonefinder.readthedocs.io/en/latest/data_format.html>`\_\_ - the command line script gained a `--stdin` streaming mode: it reads delimited rows from standard input and writes each back out with a `timezone` column appended, building the finder once instead of paying full initialisation per coordinate. Which columns hold the coordinates is read off the header by name, or stated with `--lng-col`/`--lat-col`, and never inferred from their position - a swapped pair is still a valid coordinate for any longitude between -90 and 90, so guessing would answer with a real but wrong timezone instead of failing. Every input row produces exactly one output row, and a row that cannot be used warns on stderr and makes the run exit non-zero rather than ending the stream. Whether the first row is a header is worked out from the row, or stated with `--header`/`--no-header`. New flags `-d`/`--delimiter` and `--in-memory` apply to the whole stream. See the `usage documentation <https://timezonefinder.readthedocs.io/en/latest/1_usage.html#looking-up-many-coordinates-at-once>`**. Solves issue [#&#8203;504](https://github.com/jannikmi/timezonefinder/issues/504). Thanks to `weed33834 <https://github.com/weed33834>`** for the PR [#&#8203;516](https://github.com/jannikmi/timezonefinder/issues/516) - the timezone boundary data now ships as its own distribution, `timezonefinder-data`. `pip install timezonefinder` is unchanged - it is a hard dependency and is installed automatically - but the dataset can now be pinned on its own (`pip install timezonefinder "timezonefinder-data==1.2026.3"`), where previously holding a dataset meant pinning an old `timezonefinder` and forfeiting every code fix since. Every release used to carry the whole \~65 MB dataset in three platform wheels plus an sdist to distinguish a few kilobytes of compiled code, which had already exhausted the PyPI project storage quota once. A data update is consequently no longer a `timezonefinder` release at all: it publishes `timezonefinder-data` under its own tag namespace and is recorded in that package's README rather than here. Its version reads `<format>.<year>.<letter>` - `1.2026.3` is data format generation 1 built from timezone-boundary-builder `2026c` - and `timezonefinder` requires `timezonefinder-data>=…,<2`: no ceiling on the data axis, so a dataset update needs no code release, and a hard one on the format axis, so code paired with data it cannot read fails when resolving rather than at the first lookup. `DATA_LICENSE` moves with the database it covers and now ships inside the data wheel, and a compiled data directory additionally carries a `schemas/` copy of the FlatBuffers definitions its binaries were written by, so it can be read back without the package that wrote it. Solves the first part of issue [#&#8203;446](https://github.com/jannikmi/timezonefinder/issues/446) - the packaged FlatBuffers binaries are now named `.bin` rather than `.fbs`: `boundaries/coordinates.bin`, `holes/coordinates.bin` and `hybrid_shortcuts_uint16.bin`. `.fbs` is the FlatBuffers *schema* extension, and the data directory now ships actual schemas next to the buffers, so one extension was naming two unrelated kinds of file. Each buffer already states what it is through the file identifier in its first bytes, which is what a rename or a mispaired copy cannot forge - the name never carried that meaning. The bytes are unchanged Internal: - the release pipeline refuses to publish `timezonefinder` unless a compatible `timezonefinder-data` already exists on PyPI. The two distributions release independently, and on a data format change the order is fixed - data first, then the code requiring it - because a code wheel whose declared data version does not exist yet is uninstallable for everyone until it does, and the version number cannot be reused to fix it. The check reads the requirement out of the built wheel rather than out of `pyproject.toml`, and asks the index the same question a user's resolver will, so a yanked release does not count as one that satisfies it. It runs before the GitHub Release, which is the first step of the release that cannot be taken back - pull requests are opened against a template (`.github/pull_request_template.md`) prompting for the change, its motivation and the checks that were run - `update_data.sh` resolves the timezone-boundary-builder release tag before downloading and fetches that release's asset, instead of fetching `releases/latest/download/` and separately asking the API what `latest` was - two independent questions that a release landing between them answered differently, attributing one release's data to the other. The tag now names the downloaded archive and the GeoJSON as well, so a leftover file from another release or another dataset variant cannot satisfy the "already downloaded" checks and be parsed in place of what was asked for - names and docstrings now describe what the code does. `TimezoneFinder.timezone_at` documents the optimisation it actually performs: once no other zone can be matched the last remaining zone is returned *without* a point in polygon test, which is always correct against the packaged data - the ocean zones cover the globe, so every point lies within one of the candidate polygons - but not against custom data that leaves areas uncovered, where a point inside none of the candidates is still attributed to that zone and `certain_timezone_at` is the method that tests every candidate. Three tests were named after something other than what they do: `test_rectify_coords_valid`/`_invalid` were named for a `rectify_coords` that exists nowhere in the package and both call `validate_coordinates`, and the first was subsumed entirely by `test_validate_coordinates_accepts_finite_values`, which covers all four of its distinct corners and additionally asserts the return value where the older test asserted only "does not raise"; and `test_single_element_arrays_should_not_occur` asserted that they *do* occur (`assert single_element_count == 2`) under a triple-quoted string placed after the first statement, making it a discarded expression rather than a docstring - so it reached neither `--collect-only` nor a failure report, which is where the contradicting name was the only thing a reader saw. A stale comment duplicated across the last two lines of `tests/main_test.py`, reading as a to-do for something `TestTimezonefinderClassTestMEM` already does, is gone - added `DATA_VERSION` file tracking which timezone-boundary-builder release the packaged data was generated from, written automatically by the data update script after a successful parse. Thanks to `Lucas Hemkemeier <https://github.com/hemkdev>`\_\_ for the PR [#&#8203;429](https://github.com/jannikmi/timezonefinder/issues/429) - the packaged data now updates itself: a weekly workflow compares `DATA_VERSION` against the latest timezone-boundary-builder release, regenerates the data and opens a ready-to-review update PR, which is merged and released automatically once its CI passes - the version tag is pushed with a GitHub App token, since the default one would not trigger the release pipeline. The tag lives in its own `data-v*` namespace, which the code release pipeline excludes at its trigger and again on the job that creates the GitHub Release, and the data stream publishes by PyPI Trusted Publishing from its own deployment environment rather than with a shared token. It refuses to release when the squash it produced did not land on the `master` it checked, so the tag names a tree that was actually built. Failed CI takes the same manual-attention path and falls back to the previous notification issue. Each cause labels the PR `automation-failed` and leaves one comment naming that cause and linking the run, deduplicated per cause so re-running CI neither repeats a notice nor hides a second one; a failure past the merge is a cause of its own, since that leaves master carrying the update with no tag pushed and only a hand-pushed tag still releases it. The manual release path drops the stop condition it carried for an out-of-order `CHANGELOG.rst`: the automation can no longer produce one, and the test suite asserts the committed file's section order if anything else does (issues [#&#8203;273](https://github.com/jannikmi/timezonefinder/issues/273), [#&#8203;167](https://github.com/jannikmi/timezonefinder/issues/167) and [#&#8203;510](https://github.com/jannikmi/timezonefinder/issues/510)). Thanks to `Lucas Hemkemeier <https://github.com/hemkdev>`\_\_ for the PRs [#&#8203;434](https://github.com/jannikmi/timezonefinder/issues/434) and [#&#8203;436](https://github.com/jannikmi/timezonefinder/issues/436), and to `Nice6042 <https://github.com/Nice6042>`\_\_ for the PR [#&#8203;518](https://github.com/jannikmi/timezonefinder/issues/518) - `update_data.sh` (renamed from `parse_data.sh`) is CI-ready: interactive prompts replaced by flags (`--dataset=full|same-since-now`, `--with-oceans`, `--rm-tmp`), the release note for a data update written automatically into the data package's README, no redundant `tox` run, and a `make reports` at the end so the benchmark and data reports cannot go stale relative to the data an update PR ships. A standalone `make parse`/`make testparse` still needs a manual `make reports` (issues [#&#8203;167](https://github.com/jannikmi/timezonefinder/issues/167) and [#&#8203;510](https://github.com/jannikmi/timezonefinder/issues/510)). Thanks to `Lucas Hemkemeier <https://github.com/hemkdev>`\_\_ for the PRs [#&#8203;432](https://github.com/jannikmi/timezonefinder/issues/432) and [#&#8203;434](https://github.com/jannikmi/timezonefinder/issues/434) - added property-based tests (`hypothesis`) for coordinate validation (solves issue [#&#8203;143](https://github.com/jannikmi/timezonefinder/issues/143)). Thanks to `Lu Yicheng <https://github.com/01luyicheng>`\_\_ for the PRs [#&#8203;431](https://github.com/jannikmi/timezonefinder/issues/431) and [#&#8203;433](https://github.com/jannikmi/timezonefinder/issues/433) - replaced the hand-rolled `timeit` timing in `scripts/check_speed_*.py` with `pytest-benchmark` suites under `benchmarks/`, excluded from `make test`/`make testall` via `testpaths`. Both they and the memory harness run over deterministic committed fixtures (`tests/fixtures/benchmarks/`), so two runs of the same commit execute the exact same workload; the loader rejects fixtures that no longer match the checkout. Measurement and rendering are decoupled, so `docs/benchmark_results_*.rst` can be regenerated from a stored JSON without re-measuring. Run via `make speedtest`, `make benchmarks`, `make memory` or `make reports` - memory is measured by its own harness (`scripts/measure_memory.py`, `make memory`) rather than by `pytest-benchmark`, which times code and would have its timings distorted by allocation tracking. It emits pytest-benchmark-shaped JSON, so the existing normalisation, noise and comparison tooling works on it unchanged given a `--metric`. `tests/test_memory_footprint.py` fails if a mode's allocation leaves its order of magnitude - the regression that would make `in_memory=False` stop being the low-memory option - added continuous benchmarking on CI (solves issue [#&#8203;150](https://github.com/jannikmi/timezonefinder/issues/150)), deliberately kept out of the release pipeline in `build.yml`: the tracked core subset and the memory harness run on every pull request and every push to `master`, publishing `trend charts <https://jannikmi.github.io/timezonefinder/dev/bench/>`\_\_ to `gh-pages` and posting a same-runner base/head comparison on the pull request. The comparison reports added or removed benchmark IDs without trying to ratio unmatched measurements, which lets the trusted default-branch consumer remain compatible while the suite evolves. A pull request is measured against its own merge base in the same job rather than against a stored baseline, because `runs-on: ubuntu-latest` pins the runner image and not the CPU. The measurement design, the tracked estimator and every alert threshold are documented in the new `benchmarking methodology <https://timezonefinder.readthedocs.io/en/latest/benchmarking_methodology.html>`\_\_ page. The measuring job holds no write permissions and no secrets, so branch and fork pull requests behave identically; the comment is posted by a separate, privileged workflow via `workflow_run` - guarded the benchmark plumbing against silent drift: `tests/test_benchmark_names.py` and `tests/test_memory_metric_names.py` pin the node ids and metric names that join a measurement to its chart history, so a rename fails loudly instead of starting an empty chart beside the orphaned old one; `tests/test_benchmark_workflows.py` asserts that the constants duplicated across the two workflows agree, where a one-sided edit previously had no failure mode at all, and that the cross-machine trend chart cannot creep back into the pull request comparison; and every generated report page states the inputs it describes - `docs/benchmark_results_*.rst` the fixture and timezone data versions they were measured against, `docs/data_report.rst` the timezone data version its figures were derived from. Both stamps are covered by tests: one renders each report and fails if a renderer stops emitting it, another checks the committed pages against the current fixture metadata and `DATA_VERSION`, so regenerating fixtures or updating the data without re-rendering fails loudly instead of leaving a page whose numbers are all plausible and all stale - every generator now emits output that is already pre-commit-clean, so regenerating and diffing compares like with like: `write_json` sorts keys the way `pretty-format-json` does, and neither `scripts/reporting.py` nor `BenchmarkReporter` emits trailing whitespace on empty cells or a trailing blank line. Previously every `make parse`/`make reports` left its outputs looking modified until the hooks had run, which masked whether a regeneration had actually changed anything - every generated benchmark report now opens with its headline figure and the configuration behind it, above the tables: how long a lookup takes and how many per second, the per-check cost across polygon sizes, construction time, footprint per mode - all derived from the same parsed JSON as the tables, never hardcoded. The banner beneath states which acceleration path and platform produced the numbers, and says whether that is the configuration CI tracks: the committed reports are rendered from a developer machine with Numba enabled, while CI measures the C extension without Numba, so their figures were never comparable to the trend chart and now say so - `make flatbuf` no longer overwrites hand-maintained `__init__.py` files. `flatc` derives its output path from the schema namespace and writes an empty `__init__.py` at every level of it, so generating in place wiped the `__all__` in `timezonefinder/__init__.py` - the whole public API. The target now generates into a scratch tree, copies back only the generated packages, and runs the formatters on the result so a regeneration diff shows the codegen change rather than formatting churn - mypy now type-checks the whole package except the `flatc`-generated bindings. `ignore_errors` previously covered roughly 800 lines of hand-written code as well, where a blatantly wrong return type still reported "Success"; they all pass once the exemption is lifted, bar two genuine findings now fixed. `tests/test_mypy_config.py` keeps the list restricted to generated code, so silencing a module is a reviewed decision rather than a one-line edit - the hybrid shortcut reader and writer now select their FlatBuffers schema from a single registry (`SHORTCUT_SCHEMAS` in `timezonefinder/flatbuf/io/hybrid_shortcuts.py`) instead of dispatching on the zone id width in three places, each keyed differently. One `ShortcutSchema` per width owns the width, the file name, the `uintN` marker and the maximum zone id, which were previously written down across five places with nothing tying them together. Verified behaviour-preserving down to the bytes: re-writing the shipped shortcut binary produces a byte-identical file - each distribution's build is now asserted to contain exactly what it should. The data wheel's payload is compared against the committed dataset as a set, in both directions: a missing binary fails on first use and gets reported, but an extra one ships silently - setuptools copies package data into `build/lib` and never prunes it, so a file renamed in the source tree keeps being zipped into every later wheel built from that checkout, which is how a 63 MB `coordinates.fbs` was still shipping next to the `coordinates.bin` that replaced it and doubling the wheel whose size is the reason the distribution was split out. The wheel builders clear that directory first, so a local build matches the fresh checkout CI builds from, and the code sdist's checks cover its grafted test fixtures again - the packaged data is additionally held to a floor on how much hole deduplication achieves - the test suite fails if fewer than 90% of its holes match a boundary polygon (96.4% currently), because a future upstream release that stopped emitting enclaves as shared rings would still compile and still return correct timezones, just with the shipped data quietly re-inflated. The floor applies to that dataset and nothing else: compiling your own GeoJSON with `scripts/file_converter.py` is a supported use case, holes that are ordinary interior rings rather than enclaves are stored inline and answer correctly, and the converter only reports the ratio rather than refusing to compile. `prototypes/hole_boundary_redundancy.py` is the study behind the threshold: it reads the upstream GeoJSON, so re-running it against a new release re-verifies the assumption rather than restating it. `prototypes/hole_removal_impact.py` is the study behind keeping the unmatched holes stored inline rather than dropping them, which is the obvious next step and does not work: dropping holes and re-running the lookups changes answers, wrongly, because being covered by another zone only puts that zone among the shortcut candidates and says nothing about it being tested first (issue [#&#8203;513](https://github.com/jannikmi/timezonefinder/issues/513)) - removed constructs that provably did nothing, and gave two vacuous tests real assertions. Most consequentially, four `__slots__` entries were declared but assigned by nothing, which silently re-permitted the very attributes `__slots__` is there to forbid - assigning those names now raises `AttributeError`, and `test_declared_slots_are_assigned` keeps the list honest - `get_corrected_hex_boundaries` exists once again. An earlier refactor left two verbatim copies of the antimeridian and pole clipping rules with nothing keeping them in sync; the copy without callers is deleted, and the survivor is now covered by `tests/hex_utils_test.py` - it previously had no direct tests at all. `scripts/configs.py` no longer declares `MAX_LAT`/`MAX_LNG` as a second pair of names for `timezonefinder.configs`'s constants - `prototypes/` has a `README.md` saying what the three scripts there are: exploratory studies behind committed design decisions, run by hand, outside the package and the test suite. One of them is the measurement that chose H3 resolution 3 - the central algorithmic parameter of the package, already cited from the data format page - and another is the evidence for not building a hierarchical index. `MANIFEST.in` now excludes the whole directory from the source distribution rather than only its `*.py` files - `plans/` is git-ignored alongside `tmp/` and `.venv/`: implementation plans written while working on a change are local scratch, and leaving the directory untracked-but-unignored made it noise in every `git status` and a candidate for an over-broad `git add` - failing paths now report the input that failed. `tests/auxiliaries.py`'s `run_command` assembled the child's stdout and stderr into a message and then raised a *fresh* `CalledProcessError` that never used it, with `from None` discarding the original too, so a packaging failure under `make testint` reported an exit code and nothing about the cause; it now echoes the captured streams and re-raises the original exception with its traceback intact. `scripts/reporting.py` passes the coordinate file paths into `get_polygon_collection`, whose optional `file_path` exists precisely so an incompatible-layout `ValueError` can say which of the two files was stale - `make reports` against an outdated data directory previously could not. `Boundaries.overlaps` names the type it rejected instead of raising a bare `TypeError`, and the `RuntimeError` for missing `original_polygons` names the polygon and resolution it was computing. The two re-raises ruff flags under `B904` now say `from None` explicitly, so a deliberately dropped exception chain is distinguishable from a forgotten one, and `timezonefinder/command_line.py` drops `FileNotFoundError` from an `except` tuple that already caught its base class `OSError`. `tests/test_error_diagnostics.py` pins what each of these messages must contain - the command line interface no longer routes its own output through a temporary file. `main` redirected stdout to a `mkstemp` file for the duration of the lookup and then, in verbose mode, reopened it to read back a string it still held in a local variable - nothing inside the redirected block ever wrote to stdout, since the lookup functions return their result rather than printing it. The context manager, the read-back, its warning path and the file cleanup are gone, and the lookup function is now resolved once per invocation instead of twice, so `-f 3`/`-f 4` under `-v` no longer construct a second `TimezoneFinderL` and reload its shortcut data just to read a function name. Output is unchanged character for character, across every function id in both modes. `tests/cli_test.py` gains the coverage that makes that checkable - verbose mode, the empty line printed when no timezone is found, and the rejected function id had none - and asserts the printed name verbatim instead of passing it through `rstrip("\n\x1b[0m")`, which strips a *set* of characters rather than a suffix and so truncates 12 of the packaged zone names (`Europe/Amsterdam` -> `Europe/Amsterda`) - docstrings now describe the code that exists. Six documented something the implementation contradicts: `AbstractTimezoneFinder.__init__` called `in_memory` inert and "kept for API compatibility" when it is what selects memory-mapped against in-memory coordinate access - the claim `help(TimezoneFinder)` surfaces, and the opposite of what the usage docs say; both `get_geometry` docstrings pointed at a `timezone_names.json` that does not exist under that name; `read_zone_names` promised an empty list where it raises `FileNotFoundError`, and illustrated itself with a hardcoded zone count that the packaged data had since outgrown; and `zone_id_of` / `zone_name_from_id` each advertised an exception type they convert away, sending callers to write handlers that can never fire. Five further `:param:`/`Args:` entries in `scripts/` and `tests/` documented arguments that were removed along with the parallel shortcut compilation they belonged to. `tests/test_documented_contracts.py` pins the exception types and the coordinate access mode, so those promises now rest on something besides prose - the test and benchmark suites no longer contain checks that cannot fail. Eighteen calls sat inside four shared `pytest.raises` blocks in `tests/main_test.py`, and execution leaves such a block at the first statement to raise - so one out-of-range coordinate, one positional call shape and one rejected `get_geometry` input were verified while the remaining fifteen were unreachable. Each is a test case of its own now: every coordinate just outside the WGS84 range, every positional call shape of every keyword-only lookup method, and the unknown-zone-name, past-the-end and negative zone id rejections of `get_geometry`. The `__del__` cleanup test binds its exception per iteration rather than closing over the loop variable, which decided what a garbage-collected instance would raise long after the loop had moved on. On the benchmark side, `pip_inputs_by_stratum` validated only the strata the fixture happened to contain, so one missing from it altogether passed and surfaced later as a bare `KeyError` inside a benchmark, and the points and their labels were paired from two files with a non-strict `zip` that truncates silently. That grouping now lives in `tests/auxiliaries.py` as `group_pip_inputs_by_stratum`, checks against the declared `PIP_STRATA` - which the generator no longer keeps a second copy of - and has tests for each way the two fixture files can disagree - both point-in-polygon acceleration paths are now covered by a local test run, whichever one the environment happens to bind. The implementation is selected at import time and Numba wins whenever it is importable - which the documented setup (`uv sync --all-groups`) makes it - so the C extension was reached only by direct-kernel tests on hand-built arrays, and everything about how real polygon buffers arrive at it, including the read-only memory-mapped views, was first exercised in CI's non-numba tox environments: the configuration a plain `pip install timezonefinder` produces. `tests/test_acceleration_paths.py` now rebinds `utils.inside_polygon` and drives the full lookup stack through both implementations, asserting that they agree across the real boundary data, that the C path returns the known-correct answers, and that the point-in-polygon stage was reached at all rather than short-circuited by the shortcut layer (issue [#&#8203;482](https://github.com/jannikmi/timezonefinder/issues/482)) - the packaging guard in `tests/test_package_contents.py` no longer names files that do not exist. It asserts that nothing in the built sdist and wheel matches a list of unwanted paths, which passes just as readily when a pattern matches nothing at all: `.github` lacked the trailing slash that directory patterns need, `Agents.*` stopped matching when the file was renamed to `AGENTS.md`, and `readthedocs.yaml` never matched `readthedocs.yml` - so the CI configuration and both of those files were unguarded while the suite stayed green. The patterns are corrected, the provider stubs, `contributing/`, `.agents/`, `.claude/` and `.cursor/` are covered to match what `MANIFEST.in` excludes, and `test_every_unwanted_pattern_matches_a_project_file` now fails on any hand-written pattern that matches no path in the checkout, so the next rename cannot silently disarm one. It carries the `unit` marker rather than the module's former blanket `integration` mark, since it needs no build: a mistyped pattern surfaces in `make test`. `.gitignore` re-include lines (`!…`) are also no longer read as exclusions, which had produced one more parametrised case that could never fail. The converse direction is checked too: `test_every_manifest_exclusion_is_guarded` parses the `exclude`/`recursive-exclude`/`prune`/`global-exclude` directives out of `MANIFEST.in` and fails when one of them keeps a path out of the build that no pattern here names - previously such a line was enforced by the build and verified by nothing, so deleting it would have shipped the file with the suite still green. The two lists are hand-maintained statements of one intent and had drifted before, in both directions. The `architecture page <https://timezonefinder.readthedocs.io/en/latest/architecture.html>`\_\_ describes the guard from both sides: among the tests that exist to give an invariant a failure mode, and under *How it ships* as the check on what the built artifacts actually contain - the distributions built by the test suite are now built for the interpreter running it. `uv build` was invoked without `--python`, so it targeted the newest interpreter on the machine, while `tests/test_integration.py` creates its throwaway venv from `sys.executable`: on a checkout whose `.venv` is older than the newest installed Python, `make testint` produced a `cp314` wheel and failed with pip's "not a supported wheel on this platform". Every tox environment offers a single interpreter, so the two agreed by accident in CI and the mismatch only ever hit developer machines, where the workaround was to pin `UV_PYTHON`. `test_build_commands_pin_the_running_interpreter` keeps the pin in place; it needs no build, so it fails in `make test` rather than waiting on a CI environment that cannot reproduce the mismatch - two tests no longer leak numpy's global error state into whatever pytest collects next. `np.seterr` and the warning filters are process-global, and `test_overflow` (`tests/main_test.py`) plus `test_inside_polygon` (`tests/utils_test.py`, six parametrisations) each set them and never restored them - so every later test in the same process ran with `under` promoted from `ignore` to `warn`, and which of the two modules pytest collected first decided the state the other ran under. The filters were undone only incidentally, by pytest's per-test `catch_warnings()`, not by the tests themselves. `benchmarks/conftest.py` already had the correct pattern; it now lives in `tests/auxiliaries.py` as the `strict_numpy_errors` context manager plus a thin `strict_numpy_warnings` fixture, re-exported through the conftest of each suite, and both call sites request it. The context manager form is what makes the restore directly testable - a leaked global otherwise surfaces only as an unrelated later failure that depends on collection order, which is the hardest kind to attribute - the zone id invariants in `scripts/timezone_data.py` are each enforced in exactly one place, and now have tests. `ZoneCollection.validate_structure` and `zone_positions` each walked `poly_zone_ids` element by element checking it was non-decreasing and each raised the same message built from its own locals; the scan moves into one `_validate_non_decreasing` helper and `zone_positions` drops its copy, which could only ever have fired if a caller mutated the array in place - the validator runs at construction and nothing writes to it afterwards. A `if min_zone_id < 0` branch is deleted as unreachable: the same method rejects any non-unsigned dtype a dozen lines earlier, so it read as the guard against negative zone ids while being incapable of firing. The class had no tests at all, so what it actually promises - the unsigned-dtype rejection that makes a negative id unrepresentable, the ordering and maximum-id rules, and the shape `zone_positions` returns - is now pinned by `tests/timezone_data_test.py` - the seven out-of-range coordinates - one representable step outside the valid WGS84 range, per axis and at every corner - are declared once in `tests/locations.py` instead of verbatim in both `tests/main_test.py` and `tests/utils_test.py`, where only one copy carried the comment explaining what makes them interesting and adding a corner to it left the other testing a smaller set - the shortcut compilation chain in `scripts/shortcuts.py` is annotated for what it is actually passed. Both annotations were the wrong way round: `check_shortcut_sorting` declared `np.ndarray` and only ever receives the `list[int]` that `optimise_shortcut_ordering` returns, and it hands the `np.ndarray` it derives to `has_coherent_sequences(lst: list[int])`. Widened rather than swapped, since `tests/shortcut_test.py` calls the latter with real lists - the supported Python versions are declared in five places that cannot read each other - `requires-python` and one classifier per minor version in `pyproject.toml`, the `py{...}` factors of `tox.ini`'s envlist, the test matrix and `CIBW_BUILD_VERSIONS` in `build.yml`, and `py_limited_api` in `setup.py` - and two "must match" comments said so while nothing enforced them. `tests/test_python_version_support.py` fails when they drift, in either of the two directions that fail silently: a classifier added without a matrix entry ships a version the package claims to support and CI never runs, and a `requires-python` raised without moving the abi3 base builds wheels tagged for an interpreter that is no longer supported. Each assertion was checked against the specific one-sided edit it targets, and both comments now name the test - the data report generator states figures it derives rather than ones it restates, and its annotations describe what it returns. `calculate_shortcut_index_stats` took the number of H3 cells existing at the shortcut resolution from a ladder of literals covering resolutions 0 to 4 and fell through, for anything else, to the number of cells actually stored - which reports coverage of exactly 100 % instead of failing - behind an `except ImportError` that cannot fire, since h3 is a runtime dependency rather than an optional one. It asks `h3.get_num_cells`, which returns precisely the numbers that were tabulated. Running mypy over `scripts/reporting.py`, which the pre-commit hook excludes, found seventeen further disagreements between the module and its own signatures: the statistics bag was typed as holding scalars while returning two distributions, `load_binary_data`'s nine-key result was a bare `dict` indexed by string literal, the table renderer declared string rows while stringifying whatever it is handed, `main` was annotated `None` while returning exit codes to `exit()`, and `print_polygon_distribution_table` documented a return value it never produced while its one caller discarded it. The two dict results are now `TypedDict`\ s in `scripts/configs.py`, carrying tests that assert their keys against what is really returned, since CI cannot type-check `scripts/`. The polygon count that labels a distribution row is no longer formatted into that label and parsed back out of it to key the example lookup. `docs/data_report.rst` and the benchmark reports regenerate byte-identically throughout - removed five definitions nothing referenced - three JSON/pickle helpers in `scripts/utils.py` and the `import pickle` they kept alive, the `i8` dtype shim in `timezonefinder/_numba_replacements.py` that the no-numba fallback never imports, and a test helper self-documented as kept for future reference - and a guard in `scripts/hex_utils.py` that could not fire. `Hex.poly_candidates` re-read its cache after initialising it and returned an empty set if it were still unset, which no path through `_init_candidates` leaves it: an empty set there means "no candidate polygons", so a converter bug would have surfaced as silently missing shortcuts rather than as a failure. The property had no direct test, being reached only through shortcut generation, and now has one. `_memory_mode_label` looks its two labels up in `PARAM_LABELS` instead of spelling them out, so renaming the display vocabulary can no longer leave the comparison bullets and the tables above them disagreeing - `make parse` and `make testparse` run again. Both invoked `scripts/file_converter.py` by path, which puts `scripts/` on `sys.path[0]` instead of the repository root, so the converter's own `from scripts.timezone_data import ...` raised `ModuleNotFoundError` before any work started - a total failure that CI never sees, since it runs neither target. `make testparse` is the only cheap end-to-end exercise of the converter (`update_data.sh` needs a \~55 MB download), and nothing under `tests/` covers `parse_data()`, so while it was broken the converter had no smoke test at all. The invocation documented in the usage docs had the same defect and is now the `python -m scripts.file_converter` form that `update_data.sh` already used; `tests/test_script_invocations.py` fails if a by-path invocation returns. Note that `parse_data()` writes its report to the checkout's committed `docs/data_report.rst` whatever `-out` it is given, so `make testparse` leaves that file describing the three-zone fixture - the target now says so - `scripts/` is type-checked by the mypy pre-commit hook instead of being excluded from it. The directory holds the data converter and the benchmark tooling - most of the repository's non-library Python - and with nothing running mypy over it the annotations had drifted to fifteen errors: two `# type: ignore` codes mypy no longer emits, so the ignore silenced nothing; two implicit `Optional` defaults that `no_implicit_optional = true` was already configured to reject; a dict annotated with a narrower value type than it is assigned; a bucket key and four bounding-box lists annotated `int` while `Boundaries` declares `float`; and two missing variable annotations. All fixed as annotations, with no runtime change. Two of the four errors mypy reported in `tests/auxiliaries.py`, which it reaches by following imports out of `scripts/`, are fixed alongside. `test_scripts_are_type_checked_by_the_hook` guards the exclude, which is a quieter way to stop type-checking a directory than the `ignore_errors` list the neighbouring tests already cover: it takes no override entry and reports nothing - the eight `__del__` cleanup tests that differed only in which exception `cleanup()` raised, and whether zero or one `ResourceWarning` was expected, are two parametrized tests over the suppressed and warned exception tuples. Each previously repeated the same subclass, the same `catch_warnings` block and the same filter, so adding a ninth exception to `__del__`'s suppression list meant copying the block a ninth time and a copy asserting the wrong count would be invisible. Coverage rises rather than falls: the hand-rolled loop asserting that `__del__` never raises to user code now runs over all six exception types instead of four - three leftovers in the converter that read as bugs are gone: `has_coherent_sequences` built an iterator solely to take its first element and then looped from the start anyway (correct, but it reads as an off-by-one), `compile_bboxes` unpacked a pair and immediately reassigned half of it, and `process_single_hex` returned the `hex_id` it was handed so its only caller reassigned the loop variable to itself. Two shadowed builtins (`dir` as a loop variable, `id` as a parameter) are renamed and three bare generator signatures annotated. The benchmark renderer classifies its "other" group by name suffix, as the two lines above it do, rather than by deep-equality scan over lists of dicts; and the `check-manifest` ignore list drops two entries naming files that do not exist (`CONTRIBUTING.rst`, `publish.py`). Every converter change was verified by parsing `tests/test_input.json` before and after and comparing the outputs byte for byte </details> <details> <summary>twilio/twilio-python (twilio)</summary> ### [`v9.11.1`](https://github.com/twilio/twilio-python/blob/HEAD/CHANGES.md#2026-09-09-Version-9111) [Compare Source](https://github.com/twilio/twilio-python/compare/9.11.0...9.11.1) **Library - Fix** - [PR #&#8203;954](https://github.com/twilio/twilio-python/pull/954): Fix tag validation regex in deploy.yml. Thanks to [@&#8203;kridai](https://github.com/kridai)! **Audiences** - ## 2026-09-01 - Backticked brace- and angle-bracket-bearing tokens in descriptions for MDX safety. - Updated a prose reference to the renamed `FetchCohortSnapshot` operation. - ## 2026-08-26 - **Removed 5 path(s)**: - `/preview/Audiences` (AdminListAudiences) - `/preview/Audiences/{audienceId}` (AdminGetAudience) - `/preview/Snapshots` (AdminListSnapshots) - `/preview/Snapshots/{snapshotId}` (AdminGetSnapshot) - `/preview/Operations/{operationId}` (AdminGetOperation) - ## 2026-08-25 - Minor updates (formatting, metadata) - ## 2026-08-24 - **Added 1 new path(s)**: - `/preview/Snapshots/{cohortSnapshotId}/Operations` (AdminListSnapshotOperations) - **Removed 1 path(s)**: - `/preview/Snapshots/{snapshotId}/Operations` (ListAdminSnapshotOperations) - ## 2026-08-20 - Renamed all 13 operations so the operationId keyword leads (`AdminGetCohort` -> `FetchAdminCohort`) to meet standard. - Set `info` `libraryVisibility` to `hidden` to exclude this admin spec from generation. - Added the standard `pageSize`/`pageToken` query parameters to `ListAdminSnapshotOperations`, the only list operation missing them. - ## 2026-08-19 - **Added 5 new path(s)**: - `/preview/Cohorts` (AdminListCohorts) - `/preview/Cohorts/{cohortId}` (AdminGetCohort) - `/preview/CohortSnapshots` (AdminListCohortSnapshots) - `/preview/CohortSnapshots/{cohortSnapshotId}` (AdminGetCohortSnapshot) - `/preview/CohortOperations/{cohortOperationId}` (AdminGetCohortOperation) - ## 2026-09-01 - Renamed 3 `Get*` operations to `Fetch*` to match the operationId standard: `FetchCohort`, `FetchCohortSnapshot`, `FetchCohortOperation`. The transpiler skips operations whose operationId does not start with a standard keyword, which had been dropping all three from generated output. - Set `libraryVisibility` to `private` (was `hidden`) so the spec is eligible for the private docs pipeline. - Backticked brace- and angle-bracket-bearing tokens in descriptions for MDX safety. - ## 2026-08-28 - **Removed 6 path(s)**: - `/preview/Audiences` (ListAudiences, CreateAudience) - `/preview/Audiences/{audienceId}` (FetchAudience, UpdateAudience, DeleteAudience) - `/preview/Snapshots` (ListSnapshots, CreateSnapshot) - `/preview/Snapshots/{snapshotId}` (FetchSnapshot, DeleteSnapshot) - `/preview/Snapshots/{snapshotId}/Profiles` (ListSnapshotProfiles) - `/preview/Operations/{operationId}` (FetchOperation) - ## 2026-08-20 - Renamed 6 `Get*` operations to `Fetch*` to match the operationId standard. - Hid the deprecated Audiences/Snapshots paths and `/preview/Operations/{operationId}`. - Backticked 11 brace-bearing tokens in descriptions for MDX safety. **Conversations** - Add PATCH support for partial updates to Configuration - Add `VIDEO` to the Conversations v2 Communication channel enum. **Data-ingress** - # API Changes - ## 2026-09-01 - Minor updates (formatting, metadata) - ## 2026-08-12 - Minor updates (formatting, metadata) - ## 2026-08-12 - Initial release with 13 paths and 13 operations **Destinations** - ## 2026-09-08 - Added `prod-ie1` to `supportedRealms` and `iamOperationEnabledRealms` for all endpoints - ## 2026-09-01 - Removed the unused `admin-api` placeholder from `supportedRealms` on the public endpoints; - One Admin routes now live in `admin_openapi.yaml`. - **Added 6 new path(s)** (admin\_openapi.yaml): - `/v1/ControlPlane/Destinations` (AdminListDestinations) - `/v1/ControlPlane/Destinations/{destinationId}` (AdminGetDestination) - `/v1/ControlPlane/Subscriptions` (AdminListSubscriptions) - `/v1/ControlPlane/Subscriptions/{subscriptionId}` (AdminGetSubscription) - `/v1/ControlPlane/Subscriptions/{subscriptionId}/EventTypes` (AdminListSubscribedEvents) - `/v1/ControlPlane/Subscriptions/{subscriptionId}/EventTypes/{eventType}` (AdminGetSubscribedEvent) - ## 2026-08-26 - Minor updates (formatting, metadata) - ## 2026-08-26 - Minor updates (formatting, metadata) - ## 2026-08-25 - **Content updates**: - Updated description for `CreateDestination` - ## 2026-08-12 - Minor updates (formatting, metadata) - ## 2026-08-12 - **Content updates**: - Added properties to `DestinationType`: releaseStatus - Removed properties from `DestinationType`: maturity **Email** - # API Changes - ## 2026-09-02 - **Added 1 new path(s)**: - `/v1/Sends/Cohorts` (sendCohort) - ## 2026-08-28 - **Content updates**: - Updated summary for `sendTransactional` - Added parameter(s) to `sendTransactional`: X-Twilio-Version - Updated schema description for `SuppressionsGroup` - Added properties to `SuppressionsGroup`: type - Removed properties from `SuppressionsGroup`: mode - Updated schema description for `SuppressionsGlobal` - Added properties to `SuppressionsGlobal`: type - Removed properties from `SuppressionsGlobal`: mode - Updated schema description for `Suppressions` - Updated schema description for `LongRunningOperationResponse` - ## 2026-08-27 - **Content updates**: - Updated description for `SendEmail` - Added parameter(s) to `SendEmail`: Content-Encoding, Idempotency-Key - Updated schema description for `Envelope` - Updated schema description for `SuppressionsGroup` - Updated schema description for `SuppressionsGlobal` **Iam** - Removed redirect\_urls from the GET /v1/Account/AuthorizedApps/{consentSid} response - Added company\_name, homepage\_url, tos\_url, and redirect\_urls to the GET /v1/Account/AuthorizedApps/{consentSid} response - Added GET /v1/Account/AuthorizedApps/{consentSid} - fetch authorized app details, including allowed permissions, by consent identifier SID - added container-scoped entitlements endpoint (GET /v2/Container/{containerId}/Entitlements) **Instrumentation** - # API Changes - ## 2026-09-04 - **Content updates**: - Added `IdempotencyKeyHeader` to Create/Patch/Delete `AutoInstrumentationRule`; corrected the shared header's description - Added `operationId`/`createdAt` to `LongRunningOperationResponse`; corrected example `status` from `RUNNING` to `PENDING` - Renamed `Signal.timestamp` → `occurredAt`, `HourlyStats.hourTimestamp` → `hourAt`; uppercased `Signal.type` and `ListSignals`' `signalType` enums to SCREAMING\_SNAKE\_CASE - Renamed `UserBehaviors` request/response fields to camelCase; added the `summaryDelivery` webhook callback - Reshaped `PaginationMeta` (added required `key`, corrected `pageSize` bounds) and all 6 list operations (`ListEventSources`, `ListEventSourceDatasets`, `ListEventSchemas`, `ListAutoInstrumentationRules`, `ListSignals`, `ListSignalStats`) to the `meta` envelope; added `ListSignalStats`' `500` response - Narrowed the domain's default `supportedRealms` to `dev-us1` only; `POST /v1/UserBehaviors` (`AnalyzeUserBehaviors`) keeps its own `dev-us1`/`stage-us1` override (prod withheld pending stage validation) — every other operation is now dev-only - ## 2026-08-31 - **Content updates**: - Fixed stale `tdi_` TTID prefix throughout (path params, examples, transaction URLs) to `events_`; unified dataset/schema ID formats (`tdi_dat_`/`tdi_dataset_` → `events_dataset_`, `tdi_schema_` → `events_evsch_`); fixed rule-version examples to match the real `version: integer` field - Fixed `operationId` to use the domain-agnostic `proc_job_` TTID prefix; corrected the `OperationId` parameter's length constraint (`max=34` → `max=35`) and added a `pattern` - Fixed two length constraints hardcoded for the old `tdi_` prefix length: `IngestEventBatch`'s `sourceId` path parameter (`maxLength` 37 → 40); removed the stale, redundant `Twilio-Write-Key` header parameter - Added the missing `AutoInstrumentationRuleId` regex `pattern` - Fixed `info.title` ("Twilio Data Ingress - Instrumentation API" → "Events Domain - Instrumentation API") - **Added 1 new API path**: - `/v1/UserBehaviors` (AnalyzeUserBehaviors) - ## 2026-07-28 - **Initial release** — 21 paths, 37 operations across three API surfaces: - **Control Plane** (`/v1/ControlPlane/…`): - `/v1/ControlPlane/EventSources` (CreateEventSource, ListEventSources) - `/v1/ControlPlane/EventSources/{sourceId}` (FetchEventSource, PatchEventSource, DeleteEventSource) - `/v1/ControlPlane/EventSources/{sourceId}/WriteKeys` (CreateWriteKey, ListWriteKeys) - `/v1/ControlPlane/EventSources/{sourceId}/WriteKeys/{writeKey}` (DeleteWriteKey) - `/v1/ControlPlane/EventSources/{sourceId}/Datasets` (CreateEventSourceDataset, ListEventSourceDatasets) - `/v1/ControlPlane/EventSources/{sourceId}/Datasets/{datasetId}` (FetchEventSourceDataset, PatchEventSourceDataset, DeleteEventSourceDataset) - `/v1/ControlPlane/EventSources/{sourceId}/EventSchemas` (CreateEventSchema, ListEventSchemas) - `/v1/ControlPlane/EventSources/{sourceId}/EventSchemas/{schemaId}` (FetchEventSchema, PatchEventSchema, DeleteEventSchema) - `/v1/ControlPlane/EventSources/{sourceId}/AutoInstrumentationRules` (CreateAutoInstrumentationRule, ListAutoInstrumentationRules) - `/v1/ControlPlane/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}` (FetchAutoInstrumentationRule, PatchAutoInstrumentationRule, DeleteAutoInstrumentationRule) - `/v1/ControlPlane/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}/Versions` (ListAutoInstrumentationRuleVersions) - `/v1/ControlPlane/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}/Versions/{version}` (FetchAutoInstrumentationRuleVersion) - `/v1/ControlPlane/Datasets` (ListDatasets) - `/v1/ControlPlane/Datasets/{datasetId}` (FetchDataset) - `/v1/ControlPlane/Operations/{operationId}` (FetchControlPlaneOperationStatus) - `/v1/ControlPlane/Datasets` (ListDatasets) - `/v1/ControlPlane/Datasets/{datasetId}` (FetchDataset) - **Event Ingestion** (`/v1/EventSources/…`): - `/v1/EventSources/{sourceId}/Batch` (IngestEventBatch) - `/v1/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}/Preview` (TriggerAutoInstrumentationPreview) - `/v1/EventSources/{sourceId}/AutoInstrumentationRules/{autoInstrumentationRuleId}/Preview/{operationId}` (GetAutoInstrumentationPreviewResult) - **Signal API** (`/v1/EventSources/…`): - `/v1/EventSources/{sourceId}/Signals` (IngestSignals, ListSignals) - `/v1/EventSources/{sourceId}/Signals/{signalKey}` (GetSignalBySignalKey) - `/v1/EventSources/{sourceId}/SignalStats` (ListSignalStats) **Knowledge** - ## 2026-07-20 - **Content updates**: - Added new schemas: `KnowledgeErrorInstance`, `KnowledgeErrorGroup` - Added `errors` field to `WebSourceDetails` for reporting web crawl errors **Memory** - ## 2026-08-18 - **Breaking change**: - Removed the deprecated `CSV` and `DATASET` values from the `DataMappingType` enum. - `INGRESS`, `DATASET_CLOUDAPP`, and `DATASET_WAREHOUSE` are the only valid values now. - Removed the `DataMappingFromCSV` and `DataMappingFromDataSet` schemas and their - `oneOf`/discriminator entries on `DataMappingFromTypes`, along with the corresponding - `CSV`/`DATASET` discriminator mapping keys. - Any caller still sending `type: CSV` or `type: DATASET` on `AdminListDataMappings` - (filtering by those values) will get a 400. - ## 2026-08-10 - No path changes (updated metadata only) - `DataMappingType` gains `INGRESS`, `DATASET_CLOUDAPP`, and `DATASET_WAREHOUSE`. - `CSV` and `DATASET` remain valid and unchanged; they are deprecated aliases and - will be removed in a follow-up change. - `DataMappingFromTypes` gains three `oneOf` members and three discriminator keys: - `DataMappingFromIngress` (renames `DataMappingFromCSV`), - `DataMappingFromCloudAppDataSet` and `DataMappingFromWarehouseDataSet` - (both split from `DataMappingFromDataSet`, distinguishing a cloud-app-backed - TDI dataset from a warehouse-backed one). - Additive and backwards compatible: existing `CSV` and `DATASET` payloads are - unaffected. - ## 2026-08-27 - **Added 2 new path(s)** for Trait Extraction Strategies: - `/v1/ControlPlane/TraitExtractionStrategies` (ListTraitExtractionStrategies, CreateTraitExtractionStrategy) - `/v1/ControlPlane/TraitExtractionStrategies/{traitStrategyId}` (FetchTraitExtractionStrategy, UpdateTraitExtractionStrategy, DeleteTraitExtractionStrategy) - ## 2026-08-18 - **Breaking change**: - Removed the deprecated `CSV` and `DATASET` values from the `DataMappingType` enum. - `INGRESS`, `DATASET_CLOUDAPP`, and `DATASET_WAREHOUSE` are the only valid values now. - Removed the `DataMappingFromCSV` and `DataMappingFromDataSet` schemas and their - `oneOf`/discriminator entries on `DataMappingFromTypes`, along with the corresponding - `CSV`/`DATASET` discriminator mapping keys. - Any caller still sending `type: CSV` or `type: DATASET` on `CreateDataMapping` or - `UpdateDataMapping` (or filtering `ListDataMappings`/`ListDataMappingSuggestions` by - those values) will get a 400. - ## 2026-08-10 - No path changes (updated metadata only) - `DataMappingType` gains `INGRESS`, `DATASET_CLOUDAPP`, and `DATASET_WAREHOUSE`. - `CSV` and `DATASET` remain valid and unchanged; they are deprecated aliases and - will be removed in a follow-up change. - `DataMappingFromTypes` gains three `oneOf` members and three discriminator keys: - `DataMappingFromIngress` (renames `DataMappingFromCSV`), - `DataMappingFromCloudAppDataSet` and `DataMappingFromWarehouseDataSet` - (both split from `DataMappingFromDataSet`, distinguishing a cloud-app-backed - TDI dataset from a warehouse-backed one). - Additive and backwards compatible: existing `CSV` and `DATASET` payloads are - unaffected. **Messaging** - Add SenderIdentity, SenderType, and SenderRegion filter query parameters to list numbers and senders endpoint (beta) - Add capabilities field to the numbers and senders response (beta) - Remove the WhatsApp Senders v1 endpoints (`/v1/Channels/WhatsApp/Senders`) from RestProxy; the sender was routed to the sunsetting `messaging-whatsapp-k8s-orch` downstream. Use the Senders v2 API (`/v2/Channels/Senders`) instead. **Verify** - Add `Templates` optional parameter on Verification creation (a stringified JSON array of `sid`/`substitutions` entries). When provided, `Templates` takes precedence over `TemplateSid`. **Voice** - ## 2026-09-03 - Added `links.conversation` to Transcription resources as the absolute Conversations API URL for the - transcript's `conversationId`. It is present once the transcript has been stored; the `links` object - is omitted otherwise. - ## 2026-09-01 - Removed `mediaUrl` from `CreateRequestWithMediaUrl`'s required fields so a request with neither `sourceId` nor `mediaUrl` reaches the downstream service, which rejects it with the specific error code 17500 instead of a generic gateway 400 - Set `additionalProperties: false` on both `CreateRequestWithSourceId` and `CreateRequestWithMediaUrl` so the two `oneOf` variants stay mutually exclusive: `sourceId` is undeclared on the media-URL variant and `mediaUrl` is undeclared on the source-ID variant, keeping every request shape resolvable to exactly one variant - ## 2026-08-05 - Added GET /v3/Transcriptions to list and filter transcriptions (status, sourceId, languageCode, createdAfter/createdBefore) with pageSize/pageToken pagination. createdAfter is inclusive and createdBefore exclusive. Returns 422 (error code 17535) when a sourceId's historical item count exceeds the service scan cap **Webhooks** - # API Changes - ## 2026-08-24 - **Changed**: Created Webhooks Config API ( <https://docs.google.com/document/d/1zkAJD8a8MgoxWifdYDl_d465Az3W6CcD9fuCC2xlSXE/edit?tab=t.0#heading=h.u9e0ry6oe89j> ), that includes 7 new resource(s)\*\*: SharedKeys, AuthProfiles, Settings, Rules, Operations, Tests, EdgeZones in /v1/Webhooks referencing webhooks-config downstream. ### [`v9.11.0`](https://github.com/twilio/twilio-python/blob/HEAD/CHANGES.md#2026-08-11-Version-9110) [Compare Source](https://github.com/twilio/twilio-python/compare/9.10.9...9.11.0) **Library - Fix** - [PR #&#8203;929](https://github.com/twilio/twilio-python/pull/929): mock HTTP session in TestUserAgentClients to avoid live network calls. Thanks to [@&#8203;shrutiburman](https://github.com/shrutiburman)! **Twiml** - Remove `<Assistant>` noun from `<Connect>` verb as part of the AI Assistants deprecation **(breaking change)** - Add `passports` attribute to `<Dial>` verb for SHAKEN/STIR passport passthrough **Accounts** - Add `SuppressEmailNotification` parameter to the Secondary Auth Token and Auth Token promotion endpoints. Set it to `true` to suppress the email notification sent to account owners and administrators. Defaults to `false`, preserving existing behavior. - Add SMS Pumping Protection GET and POST API **Ai** - Removing ai workbench apis **Api** - Add missing `uri` property to the `twiml_session` resource **Data-ingress** - ## 2026-08-07 - **Removed 1 API path**: - `/v1/DataQuery` (Realtime DataQuery) - ## 2026-07-07 - **Added 1 new API path (data plane)**: - `/v1/DataQuery` (Realtime DataQuery) - ## 2026-06-17 - **Content updates**: - Added properties to `OAuthJWTBearerCredentials`: privateKey, privateKeyPassphrase - ## 2026-06-12 - **Added 16 new path(s)**: - `/v1/DataSyncs/{syncId}` (FetchDataSync) - `/v1/CloudAppSources/{sourceId}/Objects` (ListCloudAppObjects) - `/v1/WarehouseSources/{sourceId}/Preview` (CreateWarehousePreview) - `/v1/WarehouseSources/{sourceId}/Preview/{operationId}` (FetchWarehousePreview) - `/v1/DataSample/{operationId}` (FetchDataSample) - `/v1/ControlPlane/CloudAppSources/{sourceId}` (FetchCloudAppSource, PatchCloudAppSource, DeleteCloudAppSource) - `/v1/ControlPlane/CloudAppSources/{sourceId}/Datasets` (ListCloudAppDatasets, CreateCloudAppDataset) - `/v1/ControlPlane/CloudAppSources/{sourceId}/Datasets/{datasetId}` (FetchCloudAppDataset, PatchCloudAppDataset, DeleteCloudAppDataset) - `/v1/ControlPlane/WarehouseSources/{sourceId}` (FetchWarehouseSource, PatchWarehouseSource, DeleteWarehouseSource) - `/v1/ControlPlane/WarehouseSources/{sourceId}/Datasets` (ListWarehouseDatasets, CreateWarehouseDataset) - ...and 6 more paths - **Removed 16 path(s)**: - `/v1/DataSyncs/{SyncId}` (FetchDataSync) - `/v1/CloudAppSources/{SourceId}/Objects` (ListCloudAppObjects) - `/v1/WarehouseSources/{SourceId}/Preview` (CreateWarehousePreview) - `/v1/WarehouseSources/{SourceId}/Preview/{OperationId}` (FetchWarehousePreview) - `/v1/DataSample/{OperationId}` (FetchDataSample) - `/v1/ControlPlane/CloudAppSources/{SourceId}` (FetchCloudAppSource, PatchCloudAppSource, DeleteCloudAppSource) - `/v1/ControlPlane/CloudAppSources/{SourceId}/Datasets` (ListCloudAppDatasets, CreateCloudAppDataset) - `/v1/ControlPlane/CloudAppSources/{SourceId}/Datasets/{DatasetId}` (FetchCloudAppDataset, PatchCloudAppDataset, DeleteCloudAppDataset) - `/v1/ControlPlane/WarehouseSources/{SourceId}` (FetchWarehouseSource, PatchWarehouseSource, DeleteWarehouseSource) - `/v1/ControlPlane/WarehouseSources/{SourceId}/Datasets` (ListWarehouseDatasets, CreateWarehouseDataset) - ...and 6 more paths - ## 2026-06-11 - **Added 3 new Signal API path(s) for public exposure (data plane)**: - `/v1/EventSources/{sourceId}/Signals` (ListSignals) - `/v1/EventSources/{sourceId}/Signals/{signalKey}` (GetSignalBySignalKey) - `/v1/EventSources/{sourceId}/SignalStats` (ListSignalStats) - **Added new Signal API schemas**: - Signal, SignalListResponse, HourlyStats, SignalStatsResponse - ## 2026-05-26 - **Added 12 new path(s) for public exposure**: - `/v1/ControlPlane/EventSources` (CreateEventSource, ListEventSources) - `/v1/ControlPlane/EventSources/{SourceId}` (FetchEventSource, PatchEventSource, DeleteEventSource) - `/v1/ControlPlane/EventSources/{SourceId}/WriteKeys` (CreateWriteKey, ListWriteKeys) - `/v1/ControlPlane/EventSources/{SourceId}/WriteKeys/{WriteKey}` (DeleteWriteKey) - `/v1/ControlPlane/EventSources/{SourceId}/Datasets` (CreateEventSourceDataset, ListEventSourceDatasets) - `/v1/ControlPlane/EventSources/{SourceId}/Datasets/{DatasetId}` (FetchEventSourceDataset, PatchEventSourceDataset, DeleteEventSourceDataset) - `/v1/ControlPlane/EventSources/{SourceId}/EventSchemas` (CreateEventSchema, ListEventSchemas) - `/v1/ControlPlane/EventSources/{SourceId}/EventSchemas/{SchemaId}` (FetchEventSchema, PatchEventSchema, DeleteEventSchema) - `/v1/ControlPlane/AutoInstrumentationRule` (CreateAutoInstrumentationRule, ListAutoInstrumentationRules) - `/v1/ControlPlane/AutoInstrumentationRule/{AutoInstrumentationRuleId}` (FetchAutoInstrumentationRule, PatchAutoInstrumentationRule, DeleteAutoInstrumentationRule) - `/v1/ControlPlane/AutoInstrumentationRule/{AutoInstrumentationRuleId}/Versions` (ListAutoInstrumentationRuleVersions) - `/v1/ControlPlane/AutoInstrumentationRule/{AutoInstrumentationRuleId}/Versions/{Version}` (FetchAutoInstrumentationRuleVersion) - **Added new schemas**: - EventSource, EventSourceCreate, EventSourceUpdate - WriteKey, WriteKeyCreate - EventSourceDataset, EventSourceDatasetCreate, EventSourceDatasetUpdate - EventSchema, EventSchemaCreate, EventSchemaUpdate, EventSchemaField, EventSchemaProperty - AutoInstrumentationRule, AutoInstrumentationRuleCreate, AutoInstrumentationRuleUpdate - AutoInstrumentationRuleVersion, AutoInstrumentationRuleVersionsResponse - ## 2026-06-12 - **Added 16 new path(s)**: - `/v1/DataSyncs/{syncId}` (FetchDataSync) - `/v1/CloudAppSources/{sourceId}/Objects` (ListCloudAppObjects) - `/v1/WarehouseSources/{sourceId}/Preview` (CreateWarehousePreview) - `/v1/WarehouseSources/{sourceId}/Preview/{operationId}` (FetchWarehousePreview) - `/v1/DataSample/{operationId}` (FetchDataSample) - `/v1/ControlPlane/CloudAppSources/{sourceId}` (FetchCloudAppSource, PatchCloudAppSource, DeleteCloudAppSource) - `/v1/ControlPlane/CloudAppSources/{sourceId}/Datasets` (ListCloudAppDatasets, CreateCloudAppDataset) - `/v1/ControlPlane/CloudAppSources/{sourceId}/Datasets/{datasetId}` (FetchCloudAppDataset, PatchCloudAppDataset, DeleteCloudAppDataset) - `/v1/ControlPlane/WarehouseSources/{sourceId}` (FetchWarehouseSource, PatchWarehouseSource, DeleteWarehouseSource) - `/v1/ControlPlane/WarehouseSources/{sourceId}/Datasets` (ListWarehouseDatasets, CreateWarehouseDataset) - ...and 6 more paths - **Removed 16 path(s)**: - `/v1/DataSyncs/{SyncId}` (FetchDataSync) - `/v1/CloudAppSources/{SourceId}/Objects` (ListCloudAppObjects) - `/v1/WarehouseSources/{SourceId}/Preview` (CreateWarehousePreview) - `/v1/WarehouseSources/{SourceId}/Preview/{OperationId}` (FetchWarehousePreview) - `/v1/DataSample/{OperationId}` (FetchDataSample) - `/v1/ControlPlane/CloudAppSources/{SourceId}` (FetchCloudAppSource, PatchCloudAppSource, DeleteCloudAppSource) - `/v1/ControlPlane/CloudAppSources/{SourceId}/Datasets` (ListCloudAppDatasets, CreateCloudAppDataset) - `/v1/ControlPlane/CloudAppSources/{SourceId}/Datasets/{DatasetId}` (FetchCloudAppDataset, PatchCloudAppDataset, DeleteCloudAppDataset) - `/v1/ControlPlane/WarehouseSources/{SourceId}` (FetchWarehouseSource, PatchWarehouseSource, DeleteWarehouseSource) - `/v1/ControlPlane/WarehouseSources/{SourceId}/Datasets` (ListWarehouseDatasets, CreateWarehouseDataset) - ...and 6 more paths **Deletions** - # API Changes - ## 2026-06-23 - Initial public Rest Proxy registration for the User Data Deletions API - (`POST` / `GET /v1/UserDataDeletions`, `GET /v1/UserDataDeletions/{deletionId}`, - `GET /v1/Operations/{operationId}`). - A single request may mix identifier formats: E.164 phone numbers, email - addresses, and profile IDs. **Destinations** - # API Changes - ## 2026-08-07 - **Content updates**: - Updated summary for `ListDestinationSupportedEventTypes` - ## 2026-08-07 - **Content updates**: - Updated summary for `ListDestinationSupportedEventTypes` - ## 2026-08-07 - **Added 3 new path(s)**: - `/v1/Catalog/DestinationSupportedEventTypes` (ListDestinationSupportedEventTypes) - `/v1/ControlPlane/Subscriptions/{subscriptionId}/EventTypes` (ListSubscribedEvents, CreateSubscribedEvent) - `/v1/ControlPlane/Subscriptions/{subscriptionId}/EventTypes/{eventType}` (GetSubscribedEvent, UpdateSubscribedEvent, DeleteSubscribedEvent) - **Removed 3 path(s)**: - `/v1/ControlPlane/Subscriptions/{subscriptionId}/SubscribedEvents` (ListSubscribedEvents, CreateSubscribedEvent) - `/v1/ControlPlane/Subscriptions/{subscriptionId}/SubscribedEvents/{eventType}` (GetSubscribedEvent, UpdateSubscribedEvent, DeleteSubscribedEvent) - `/v1/Catalog/DestinationEventTypes` (ListDestinationEventTypes) - ## 2026-08-04 - Minor updates (formatting, metadata) - ## 2026-08-04 - Minor updates (formatting, metadata) - ## 2026-08-04 - Minor updates (formatting, metadata) - ## 2026-08-04 - Minor updates (formatting, metadata) - ## 2026-08-04 - **Content updates**: - Added properties to `SubscriptionResponse`: eventTypes - ## 2026-08-03 - **Content updates**: - Added properties to `DestinationType`: documentationUrl, maturity, tier, categories - ## 2026-07-27 - Minor updates (formatting, metadata) - ## 2026-07-23 - **Content updates**: - `meta` is now a required property in the response of `ListDestinations`, `ListSubscriptions`, and `ListSubscribedEvents` - `CreateSubscribedEvent` request body schema consolidated onto `SubscribedEventInput` (previously `SubscribedEventCreate`, a duplicate schema) - Added response examples for `ListDestinations`, `ListSubscriptions`, and `ListSubscribedEvents` - ## 2026-07-23 - **Added 1 new path(s)**: - `/v1/Catalog/DestinationEventTypes` (ListDestinationEventTypes) - ## 2026-07-22 - **Content updates**: - Added parameter(s) to `ListDestinations`: namePrefix - Updated description for `UpdateSubscription` - Added properties to `SubscriptionUpdate`: eventTypes - ## 2026-07-16 - Initial release with 9 paths and 18 operations **Events** - Add `stage-ie1` realm support for EventTypes and Schemas endpoints (datataps-catalog) **Memory** - ## 2026-08-10 - Removed `Events` endpoints from the spec, as they were hidden, never implemented, and are not part of the public API - ## 2026-08-07 - **New functionality**: - Added `pageSize`, `pageToken`, and `orderBy` query parameters to `ListProfileImportsV2`, plus a `meta` object in its response, to support pagination. - **Content updates**: - Updated the `ListProfileImportsV2` description to document the new pagination behavior. - Corrected the example presigned upload URL on `CreateProfilesImportV2` to match the real S3 bucket naming convention. - Corrected the `meta.key` example on `ListProfileTraits`'s response (was `profiles`, now `traits`) to accurately describe which response field it points to. - ## 2026-08-07 - **Content updates**: - Updated `matchingRules` description in `IdentityResolutionSettingsCore` to remove compound `AND` rule documentation - ## 2026-07-30 - **Content updates**: - Increased the maximum value for the Twilio error `code` from `99999` to `999999` - ## 2026-07-28 - **Content updates**: - Updated the `pageSize` description on the pagination `Meta` schema to clarify it reflects the number of items actually returned, not the requested or default page size. - ## 2026-07-13 - **Content updates**: - Renamed `ListProfiles` response schema references from `ProfileID`/`ProfilesMeta` to `IdentityProfileID`/`IdentityProfilesMeta` (new `IdentityProfilesMeta` schema added; `ProfileID`/`ProfilesMeta` retained for other operations). - ## 2026-07-08 - **Content updates**: - Updated description for `CreateDataMappingSuggestion` - Updated description for `FetchDataMappingSuggestion` - ## 2026-07-06 - **Added 2 new path(s)**: - `/v1/ControlPlane/Stores/{storeId}/DataMappings/Suggestions` (ListDataMappingSuggestions, CreateDataMappingSuggestion) - `/v1/ControlPlane/Stores/{storeId}/DataMappings/Suggestions/{suggestionId}` (FetchDataMappingSuggestion) - ## 2026-06-26 - **Content updates**: - Minor updates (formatting, metadata) - Updated x-twilio location parameter from `instance` to `list` for all endpoints that don't end with a /{param} - Updated description for `UpdateProfileTraits` - Updated summary for `UpdateProfileTraits` - Removed properties from `MappingTraitItem`: fieldName - Removed `additionalProperties` from `allof` schemas since it isn't supported and causes invalid lint errors on example blocks. - matruity ga and libraryVisibility public - ## 2026-06-24 - **Content updates**: - Add ConversationID as an optional query parameter for ListObservations and ListConversationSummaries - ## 2026-05-01 - **Content updates**: - Updated description & summary for `UpdateProfileTraits` - Updated description for `FetchIdentityResolutionSettings` - Removed properties from `MappingTraitItem`: fieldName - Updated patch Observations to not require `occurredAt`, `content`, or `source` - ## 2026-04-28 - **Content updates**: - Updated description for `UpdateProfileTraits` - Updated summary for `UpdateProfileTraits` - Added properties to `TraitDefinition`: validationRule - Removed properties from `MappingTraitItem`: fieldName **Messaging\_admin** - Add Intelligent Alerts endpoints at `/v1/Messaging/IntelligentAlertsEvents/*`, routing to intelligent-alerts-api via messaging-monkey-backend. Account SID is a required query parameter (`accountSid`) on all three endpoints. </details> <details> <summary>Kludex/uvicorn (uvicorn)</summary> ### [`v0.52.4`](https://github.com/Kludex/uvicorn/releases/tag/0.52.4): Version 0.52.4 [Compare Source](https://github.com/Kludex/uvicorn/compare/0.52.3...0.52.4) ##### Fixed - Remove duplicate `Date` headers from accepted WebSocket handshakes with `websockets-sansio` ([#&#8203;3078](https://github.com/Kludex/uvicorn/pull/3078)) **Full Changelog**: <https://github.com/Kludex/uvicorn/compare/0.52.3...0.52.4> ### [`v0.52.3`](https://github.com/Kludex/uvicorn/releases/tag/0.52.3): Version 0.52.3 [Compare Source](https://github.com/Kludex/uvicorn/compare/0.52.2...0.52.3) ##### Changed - Update `zttp` to 0.0.24 and use its combined receive path, improving HTTP/1.1 request parsing performance ([#&#8203;3067](https://github.com/Kludex/uvicorn/issues/3067)) **Full Changelog**: <https://github.com/Kludex/uvicorn/compare/0.52.2...0.52.3> ### [`v0.52.2`](https://github.com/Kludex/uvicorn/releases/tag/0.52.2): Version 0.52.2 [Compare Source](https://github.com/Kludex/uvicorn/compare/0.52.1...0.52.2) ##### Fixed - Update `zttp` to 0.0.22, fixing bodyless request receives and improving HTTP/1 request parsing performance ([#&#8203;3063](https://github.com/Kludex/uvicorn/issues/3063)) **Full Changelog**: <https://github.com/Kludex/uvicorn/compare/0.52.1...0.52.2> ### [`v0.52.1`](https://github.com/Kludex/uvicorn/releases/tag/0.52.1): Version 0.52.1 [Compare Source](https://github.com/Kludex/uvicorn/compare/0.52.0...0.52.1) ##### Fixed - Complete the closing handshake on server-initiated WebSocket closes in the `websockets-sansio` and `wsproto` implementations, waiting for the client's close reply with a 10 second timeout instead of resetting the connection ([#&#8203;3053](https://github.com/Kludex/uvicorn/issues/3053)) - Add missing write flow control to the `websockets-sansio` implementation, preventing data truncation on server-initiated closes with large in-flight payloads ([#&#8203;3048](https://github.com/Kludex/uvicorn/issues/3048)) - Handle connection loss while a WebSocket write is waiting on backpressure ([#&#8203;3050](https://github.com/Kludex/uvicorn/issues/3050)) - Remove duplicate `Content-Type` and `Content-Length` headers from WebSocket denial responses on the `websockets-sansio` implementation, and deliver non-UTF-8 denial bodies intact ([#&#8203;3041](https://github.com/Kludex/uvicorn/issues/3041)) **Full Changelog**: <https://github.com/Kludex/uvicorn/compare/0.52.0...0.52.1> ### [`v0.52.0`](https://github.com/Kludex/uvicorn/releases/tag/0.52.0): Version 0.52.0 [Compare Source](https://github.com/Kludex/uvicorn/compare/0.51.0...0.52.0) This release adds an experimental HTTP/1.1 implementation backed by [zttp](https://zttp.marcelotryle.com/), a sans-IO HTTP parser I've been developing on the side: a core written in Zig, with bindings to Python. It has been running under a fuzzer for some weeks now, and has been through multiple rounds of security auditing. It is still **experimental**, so don't put it in front of production traffic yet. Try it with `--http zttp`, and please send any feedback to the [issue tracker](https://github.com/Kludex/uvicorn/issues). ##### Added - Add an experimental `zttp` HTTP/1.1 implementation, selectable with `--http zttp` ([#&#8203;2979](https://github.com/Kludex/uvicorn/issues/2979)) ##### Fixed - Keep non-ASCII WebSocket request headers intact with websockets 17.0, which encodes them with ISO-8859-1 ([#&#8203;3036](https://github.com/Kludex/uvicorn/issues/3036)) **Full Changelog**: <https://github.com/Kludex/uvicorn/compare/0.51.0...0.52.0> </details> --- ### Configuration 📅 **Schedule**: (in timezone America/New_York) - Branch creation - "before 6am on monday" - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMyIsInVwZGF0ZWRJblZlciI6IjQzLjI4OC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
chore(deps): update python minor/patch
All checks were successful
CI / test (pull_request) Successful in 6m8s
b0ec11f777
renovate-bot force-pushed renovate/python-minorpatch from b0ec11f777
All checks were successful
CI / test (pull_request) Successful in 6m8s
to 07435a2682
All checks were successful
CI / test (pull_request) Successful in 6m20s
2026-08-05 00:13:26 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from 07435a2682
All checks were successful
CI / test (pull_request) Successful in 6m20s
to 339b1c3c5d
All checks were successful
CI / test (pull_request) Successful in 4m6s
2026-08-07 12:10:01 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from 339b1c3c5d
All checks were successful
CI / test (pull_request) Successful in 4m6s
to 108a38839c
All checks were successful
CI / test (pull_request) Successful in 8m34s
2026-08-08 18:12:09 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from 108a38839c
All checks were successful
CI / test (pull_request) Successful in 8m34s
to 7d6f9b1646
All checks were successful
CI / test (pull_request) Successful in 4m48s
2026-08-11 12:09:55 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from 7d6f9b1646
All checks were successful
CI / test (pull_request) Successful in 4m48s
to 9b52093c8e
All checks were successful
CI / test (pull_request) Successful in 6m0s
2026-08-12 00:10:55 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from 9b52093c8e
All checks were successful
CI / test (pull_request) Successful in 6m0s
to 7e374cd903
All checks were successful
CI / test (pull_request) Successful in 5m13s
2026-08-13 12:10:31 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from 7e374cd903
All checks were successful
CI / test (pull_request) Successful in 5m13s
to 171edff1e9
All checks were successful
CI / test (pull_request) Successful in 4m33s
2026-08-13 18:10:47 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from 171edff1e9
All checks were successful
CI / test (pull_request) Successful in 4m33s
to dad1a0e75c
All checks were successful
CI / test (pull_request) Successful in 5m51s
2026-08-16 18:11:24 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from dad1a0e75c
All checks were successful
CI / test (pull_request) Successful in 5m51s
to c1f8f671d2
All checks were successful
CI / test (pull_request) Successful in 3m48s
2026-08-19 12:11:13 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from c1f8f671d2
All checks were successful
CI / test (pull_request) Successful in 3m48s
to 72cd7c8552
All checks were successful
CI / test (pull_request) Successful in 6m15s
2026-08-30 18:16:06 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from 72cd7c8552
All checks were successful
CI / test (pull_request) Successful in 6m15s
to c91fdd4714
All checks were successful
CI / test (pull_request) Successful in 4m32s
2026-09-04 18:14:13 +00:00
Compare
renovate-bot force-pushed renovate/python-minorpatch from c91fdd4714
All checks were successful
CI / test (pull_request) Successful in 4m32s
to 3c5ed19d67
All checks were successful
CI / test (pull_request) Successful in 6m40s
2026-09-10 06:21:36 +00:00
Compare
All checks were successful
CI / test (pull_request) Successful in 6m40s
Required
Details
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin renovate/python-minorpatch:renovate/python-minorpatch
git switch renovate/python-minorpatch
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/WeatherBot!178
No description provided.