Work I've done in the open.

Patches sent upstream, and the projects I keep alive. Everything links to the pull request on GitHub .

5 merged upstream
605 stars on what I maintain
549 public commits

Merged upstream

Frameworks I did not write. Correctness bugs, not typos.

pydantic/pydantic 28.4k merged in 14m

field_title_generator was documented with a signature it never accepted

Field(field_title_generator=lambda field_name: field_name.upper())

TypeError: <lambda>() takes 1 positional argument but 2 were given

Four docstrings promised a one-argument callable, so following the documentation was guaranteed to crash.

what I changed

The callable is handed the field name and its info object, which ConfigDict.field_title_generator already described correctly. This aligns the fields.py docstrings on Field(), FieldInfo.from_field(), computed_field() and ComputedFieldInfo with the signature the code actually calls.

pydantic/pydantic 28.4k merged in 1h 40m

SecretStr equality raised TypeError on non-ASCII values

SecretStr('café') == SecretStr('café')

TypeError: comparing strings with non-ASCII characters is not supported

A regression I caught by reading the commit that caused it, before anyone filed a bug.

what I changed

A recent switch to secrets.compare_digest() broke it: the function only accepts ASCII when handed str. Encoding both sides to bytes first restores equality for any value and keeps the constant-time guarantee that motivated the switch.

sveltejs/kit 20.7k closed a 2 yr 9 mo old issue

POST fell through to a 405 instead of the page it belonged to

POST /contact   →   +server.js exports only GET

405 Method Not Allowed — even though +page.server.js had a matching action

Core routing, plus a test fixture that did not exist before.

what I changed

Routing handed the POST to the sibling endpoint and stopped there. Now an endpoint exporting neither POST nor fallback is treated as unusable and the request falls through to the page actions, mirroring the endpoint_can_handle pattern already used for GET/HEAD.

litestar-org/litestar 8.4k breaking change, accepted

Prometheus default let metric cardinality grow without bound

/users/1   /users/2   /users/3   …

one Prometheus time series per parameter value, forever

Changing a public default was the only real fix, so I argued for it and it landed.

what I changed

group_path=True already collapsed these to the route template /users/{user_id}, but the safe behaviour was opt-in, so every default deployment leaked memory silently. I flipped the default and kept raw paths reachable through group_path=False.

litestar-org/litestar 8.4k merged in 1h 47m

Acronyms shattered into single letters across the OpenAPI spec

InvalidAPIKeyError

"Invalid A P I Key Error" — published in the public API docs

This text was shipping in the public API docs of every Litestar app.

what I changed

The splitter broke before every capital letter, including each one inside an uppercase run. Splitting only at real word boundaries keeps acronyms intact: HTTPTimeoutErrorHTTP Timeout Error, MissingJWTErrorMissing JWT Error.

Maintained by me

APIs I designed and still ship.

Also reported

Traced and filed in projects I only use.

Bishwas Bhandari PNG