Repository navigation
chore: bring master into #2231 - #2400
Merged
Merged
Conversation
bcrypt 5 raises ValueError for passwords longer than 72 bytes instead of silently truncating them; PasswordUtil already truncates to 72 bytes before hashing and checking (#2299), so existing hashes and long passwords keep working. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build: bcrypt 5.0.0
Security and maintenance releases of the HTML sanitiser used for markdown rendering (6.2.0 -> 6.4.0). bleach is deprecated upstream but still gets fixes; moving to nh3 is planned separately (nh3 removes disallowed tags where bleach, configured with strip=False, escapes them, so it changes the rendered output). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build: bleach 6.4.0
- ruff lint rule I (isort), first-party packages c2corg_api and es_migration; make format / ruff check --fix sort them - devcontainer: organize imports on save; installs the pre-commit hook - .pre-commit-config.yaml: a local hook running `uv run --frozen ruff check --fix` and `ruff format`, i.e. always the ruff version locked in uv.lock (no second pin to keep in sync); pre-commit 4.6.2 as a dev dependency - docs The imports themselves are sorted in the next commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mechanical: `ruff check --select I --fix c2corg_api es_migration` (then `ruff format`), with the isort settings from the previous commit. Listed in .git-blame-ignore-revs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
style: sort imports with ruff, pre-commit hook
`make install` runs `uv run --frozen pre-commit install` after `uv sync`, like the devcontainer setup already does, so the ruff hook is set up without an extra step. HOWTO-DEV uses `make install`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build: make install also installs the pre-commit hook
6.4.0 is the highest version that kombu 5.6.2 supports (redis <6.5). With redis-py 7+, kombu 5.6.2 silently drops health_check_interval, so the syncer's BRPOP connections would lose their health checks. Kombu 5.7 fixes this and allows redis <9; bump both together once 5.7 is final. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build: bump redis-py to 6.4.0
Checked against the production command line (sync workers, --paste, --capture-output, --statsd-host, --proxy-protocol, --proxy-allow-from): since 24.1, --proxy-protocol takes a mode, and the bare flag means `auto` (PROXY v1 or v2), which still matches HAProxy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build: bump gunicorn to 26.2.0
GET /forum/private-messages/unread-count has no caller in c2c_ui. Forum notification counts will be read by the UI directly from Discourse (session/current.json) instead of going through the admin API key. Also drop APIDiscourseClient.get_username and its cache, which were only used by this endpoint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Markdown stays on 3.10.x: every 3.11 release drops the text after an unmatched backtick run (Python-Markdown#1668, fixed on master but not released). 3.10.3 fixes several cases where 3.8.1 lost text after a stray `<`, `</` or `<!--`. The new html_edge_cases fixtures pin both, so the next bump shows any change. pymdown-extensions: only its emoji1_db data is used, unchanged in 12.1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build: bump Markdown to 3.10.3 and pymdown-extensions to 12.1
chore: remove unused forum private messages unread count endpoint
Discourse now binds the DiscourseConnect nonce to the browser session that requested it (discourse_connect_csrf_protection, on by default), so the nonce the API fetches server-side for the login response (redirect_internal) is rejected with a 419 when the browser's hidden iframe uses it: logging in on the topoguide no longer opens a forum session. The UI will instead let the browser start the handshake on the forum, which sends it to /auth-sso with a signed sso/sig payload. This endpoint answers it for the already logged-in user with the signed sso_login URL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(sso): add /users/discourse-redirect for browser-initiated forum SSO
dogpile.cache 1.5.0, pyramid_tm 2.6, python-json-logger 4.2.0, python-slugify 9.1.3, requests 2.34.2, transaction 5.1, pytz 2026.5. - production.ini: use pythonjsonlogger.json.JsonFormatter, the deprecated pythonjsonlogger.jsonlogger alias still exists in 4.x. - pyramid_tm >= 2.4 annotates transactions with request.authenticated_userid, which runs groupfinder (one query) on every authenticated request. Turn tm.annotate_user off: the annotation is only used by ZODB-style transaction logs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build: bump small runtime libraries
Pin pytest and pytest-cov exactly like the other dependencies, and upgrade ipython (an ipdb dependency) from 8.18.1 to 9.17.1 in the lock. Closes #2356 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build: bump pytest to 9.1.1, pytest-cov to 7.1.0, WebTest to 3.0.7
- `make audit` runs `uv audit` on the lock; a new CI job runs it. Advisories that can't be fixed yet are listed in the Makefile with their reason: urllib3 1.26 (elasticsearch 2.4.1 requires urllib3<2) and setuptools < 83 (held below 81 for Pyramid's pkg_resources). - Fix the rest in the lock: mako 1.4.3, soupsieve 2.10. - Drop the six Snyk floor pins on indirect dependencies: the lock already satisfies them, and zipp was not needed by anything. Part of #2357 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pytz was only used for its UTC timezone. The standard library's datetime.UTC is the same, and datetime.now(UTC) also replaces the deprecated datetime.utcnow() in the two places that localized it. Part of #2357 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- uv: minor/patch updates of dev tools, the SQLAlchemy family and the Pyramid family come as one PR each; all other patch updates as one PR. Major updates keep their own PR. - uv: ignore the versions held back on purpose (elasticsearch 2.4, pyramid 2, setuptools >= 81, apscheduler 4, redis-py >= 7), each with its reason. - GitHub Actions: one grouped PR. Part of #2357 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
refactor: replace pytz with datetime.UTC
build: audit dependencies in CI, drop stale Snyk pins
ci: group Dependabot updates, ignore held-back versions
Part of the Colander → Pydantic step (#2364), stacked on coverages. types.py gets Date and Bool, which validate like colander.Date (the ISO 8601 format of iso8601.parse_date, ported; any falsy value is missing) and colander.Boolean (only 'false' and '0', in any case, are false). The parity harness generates date and boolean cases. c2corg_api/schemas/xreport.py: the xreport schema with its locale fields, its create and update schemas, and the ModelSchemas of the xreport, of its listing and of the xreport without personal information, used by the xreport views. The Colander xreport schemas stay for the parity tests only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
refactor: validate and map xreports with Pydantic
Part of the Colander → Pydantic step (#2364), stacked on xreports. types.py gets FiniteFloat (like colander_ext.FiniteFloat: NaN and infinity give null) and DateTime (like the ColanderAlchemy DateTime: ISO 8601, naive without a time zone). The parity harness generates float and datetime cases. c2corg_api/schemas/image.py: the image schema (a title may be empty), its create and update schemas, the image list schema, and the ModelSchema of the image and its listing, used by the image views. The Colander image schemas stay for the parity tests only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
refactor: validate and map images with Pydantic
Part of the Colander → Pydantic step (#2364), stacked on images. c2corg_api/schemas/user_profile.py: the profile schema (its locales have no title: the title is the user's name), its update schema, and the ModelSchemas of the profile, of its listing and the internal one the update uses (with the locale titles the view sets to ''). The Colander profile schemas stay for the parity tests only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part of the Colander → Pydantic step (#2364), stacked on profiles. Seq takes a minimum length (activities needs at least one), with Colander's message. c2corg_api/schemas/outing.py: the outing schema with its locale fields and line geometry, its create and update schemas, and its ModelSchema, which the outing views and the per-activity schema adaptors (ModelSchema.restrict) use. The Colander outing schemas stay for the parity tests only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part of the Colander → Pydantic step (#2364), stacked on outings. types.py gets Float (like colander.Float: NaN is kept, unlike FiniteFloat). The parity harness treats NaN as equal to NaN. c2corg_api/schemas/route.py: the route schema with its locale fields (title_prefix included) and line geometry, glacier_gear defaulting to 'no' as its column did, its create and update schemas, and its ModelSchema, used by the route views, the per-activity schema adaptors and the navitia views. The Colander route schemas stay for the parity tests only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part of the Colander → Pydantic step (#2364), stacked on routes. The last document type. c2corg_api/schemas/waypoint.py: the waypoint schema with its locale fields and point geometry, its create and update schemas, and its ModelSchema, used by the waypoint views, the per-type schema adaptors and the navitia views. No view uses restrict_schema any more. The Colander waypoint schemas stay for the parity tests only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part of the Colander → Pydantic step (#2364), stacked on waypoints. The body schemas of protect/unprotect, merge, revert, version mask/unmask, tags, follow/unfollow and block/unblock are now Pydantic schemas, defined where the Colander ones were. test_action_schemas.py keeps a copy of the Colander definitions and checks the new schemas validate exactly like them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dantic Part of the Colander → Pydantic step (#2364), stacked on the action schemas. - c2corg_api/schemas/association.py: the association schema and its ModelSchema (objectify), used by the association views; - the feed preferences and forum topic body schemas, defined where the Colander ones were. test_misc_schemas.py checks them against the Colander schemas (a copy of the view definitions for the two that lived in views). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part of the Colander → Pydantic step (#2364), stacked on the association, preferences and forum schemas. types.py: string fields take a list of checks, which all run and join their messages with '; ' like colander.All: minimum and maximum length, choices, email (colander.Email's regular expression and message) and function_check (like colander.Function). base.py: DROP, the default of a field left out of the validated data when missing (colander.drop). c2corg_api/schemas/user.py: the registration schema and the ModelSchemas that build a user from it and serialize a user. The login, Discourse redirect, preferred language, account update and SSO body schemas are defined where the Colander ones were. test_user_schemas.py checks them against the Colander schemas (the account update one in a database test, as its checks look up the users). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Last part of the Colander → Pydantic step (#2364): nothing uses the Colander schemas any more. - The Colander schemas, ColanderAlchemy column hints and the schema_utils helpers are removed from the models; schema_utils keeps the field lists of the listing restriction. - ext/colander_ext.py is gone, and with it the global geojson patch for 4D positions (the Pydantic geometry type checks 2/3/4D itself). The GeoJSON/WKB conversions move to ext/wkb.py. - serialize() and is_missing() no longer know colander.null. - colander, the ColanderAlchemy fork and iso8601 leave the dependencies. - The parity tests needed Colander: test_types.py now pins the behaviours they established (messages, conversions, missing values, dates, booleans, floats, joined check messages, geometries), and test_model_schema.py the model mapping. The colander_ext tests move to test_wkb.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
refactor: remove Colander and ColanderAlchemy
test: stop the Discourse client mocks leaking between tests
fix: reindex the outings of a route when its waypoints change
build: use upstream Cornice instead of the c2corg fork
A geometry whose positions have different dimensions (a LineString mixing [x, y] and [x, y, z, m] positions, say) failed in geomet during the WKB conversion, and the API answered 500. c2c_ui never sends that (OpenLayers geometries have one layout), but other clients can. The geometry type now gives all the positions the lowest dimension found in the whole geometry, dropping the trailing values: 2D + 3D gives 2D, 3D + 4D gives 3D, 2D + 4D gives 2D. A PostGIS geometry has a single dimension, so this applies across the lines of a MultiLineString too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix: give mixed-dimension geometries their lowest dimension
Contributor
|
Merge has moved since this PR, I've updated it |
The items of the array fields backed by an enum (activities,
categories, route_types, rock_types, best_periods, ...) were not
checked, by Colander before nor by the Pydantic schemas that kept that
behaviour: an invalid value reached the database enum type and the API
answered 500. The routes and outings checked only their first activity.
The schemas now check every item against its enum and answer 400 with
the error on the item (e.g. activities.1: "x" is not one of ...).
For routes and outings, an invalid first activity used to give the
error {name: activities, description: 'invalid value: x'}; it is now
the schema error above. As with any schema error, the association
checks also report their missing data.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Real profiles get a version at registration; the profiles of the global
test users did not, so they could not be updated and the profile PUT
contract test had to register a new user. The test data now creates
those versions like the registration does.
The contract test of PUT /{type}/{id} now covers profiles too. The
tests that created one of these versions themselves, or counted
versions, history entries and cache versions, are adjusted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test: give the global test users' profiles their first version
fix: validate the items of the enum arrays
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings master into #2231 and adapts the branch to it. This PR targets
feature/outings-heatmap: merging it updates #2231.8923d583):assert;assertAlmostEqual(places=N)becamepytest.approx(abs=5e-(N+1)), the same tolerance;noqaremoved.What changed on master that this PR adapts to
BaseTestCaseno longer derives fromunittest.TestCase, soself.assertEqual,self.assertTrue,self.assertRaises,self.subTest… no longer exist. Use plainassert,pytest.raises,pytest.approxand thesubtestsfixture (pytest 9).ruff formatenforced in CI. More rules are enabled: isort (I), bugbear (B), pydocstyle with the pep257 convention (D), naive datetimes (DTZ) and f-strings (UP031/UP032). Docstrings need a one-line summary, then a blank line.make lintand the full test suite pass on this branch.🤖 Generated with Claude Code