From 24aa7ecc0b9b5d413b074b7e0aa918ea2c6610e7 Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Tue, 14 Jul 2026 17:20:21 +0200 Subject: [PATCH 01/34] Add PyCon South Africa 2026 --- _data/conferences.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/_data/conferences.yml b/_data/conferences.yml index d9eb385056..500a52596d 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -1,5 +1,24 @@ --- +- conference: PyCon South Africa + alt_name: PyCon ZA + year: 2026 + link: https://za.pycon.org/ + cfp_link: https://za.pycon.org/pages/speaking/how_to_apply/ + cfp: '2026-08-14 23:59:00' + tutorial_deadline: '2026-08-14 23:59:00' + timezone: Africa/Johannesburg + place: Rondebosch, South Africa + start: 2026-10-14 + end: 2026-10-18 + twitter: PyConZA + mastodon: https://fosstodon.org/@PyConZA + sub: PY + location: + - title: PyCon South Africa 2026 + latitude: -33.959834 + longitude: 18.473872 + - conference: PyCon Wroclaw year: 2026 link: https://www.pyconwroclaw.com/ From 072f59693318c4ae6f3c521835329ca5ae6e2340 Mon Sep 17 00:00:00 2001 From: JesperDramsch <2620316+JesperDramsch@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:47:23 +0000 Subject: [PATCH 02/34] chore: sort conferences --- _data/archive.yml | 34 ++++++++++++++++++++++++++++++++++ _data/conferences.yml | 34 ---------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/_data/archive.yml b/_data/archive.yml index ec509fa9b2..b2733187a3 100644 --- a/_data/archive.yml +++ b/_data/archive.yml @@ -1,5 +1,39 @@ --- +- conference: GeoPython + year: 2026 + link: https://2026.geopython.net/ + cfp_link: https://submit.geopython.net/geopython-2026/cfp + cfp: '2026-02-15 23:59:00' + cfp_ext: '2026-03-31 23:59:00' + tutorial_deadline: '2026-03-31 23:59:00' + place: Basel, Switzerland + start: 2026-06-08 + end: 2026-06-10 + sponsor: https://2026.geopython.net/app/sponsors + finaid: https://2026.geopython.net/app/finaid + sub: GEO + location: + - title: GeoPython 2026 + latitude: 47.3615882 + longitude: 7.354445 + +- conference: PyData London + year: 2026 + link: https://pydata.org/london2026 + cfp_link: https://pydata.org/london2026/cfp#submit + cfp: '2026-02-16 23:59:00' + timezone: Europe/London + place: London, UK + start: 2026-06-05 + end: 2026-06-07 + sponsor: https://pydata.org/london2026/sponsor + sub: DATA + location: + - title: PyData London 2025 + latitude: 51.5074456 + longitude: -0.1277653 + - conference: PyCon Italy alt_name: PyCon Italia year: 2026 diff --git a/_data/conferences.yml b/_data/conferences.yml index d9eb385056..ebc808f025 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -607,40 +607,6 @@ latitude: 44.9772995 longitude: -93.2654692 -- conference: PyData London - year: 2026 - link: https://pydata.org/london2026 - cfp_link: https://pydata.org/london2026/cfp#submit - cfp: '2026-02-16 23:59:00' - timezone: Europe/London - place: London, UK - start: 2026-06-05 - end: 2026-06-07 - sponsor: https://pydata.org/london2026/sponsor - sub: DATA - location: - - title: PyData London 2025 - latitude: 51.5074456 - longitude: -0.1277653 - -- conference: GeoPython - year: 2026 - link: https://2026.geopython.net/ - cfp_link: https://submit.geopython.net/geopython-2026/cfp - cfp: '2026-02-15 23:59:00' - cfp_ext: '2026-03-31 23:59:00' - tutorial_deadline: '2026-03-31 23:59:00' - place: Basel, Switzerland - start: 2026-06-08 - end: 2026-06-10 - sponsor: https://2026.geopython.net/app/sponsors - finaid: https://2026.geopython.net/app/finaid - sub: GEO - location: - - title: GeoPython 2026 - latitude: 47.3615882 - longitude: 7.354445 - - conference: EuroPython year: 2026 link: https://ep2026.europython.eu/ From 0cc48880e277c1da926e88f5d98898c22bb6d8b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:06:39 +0200 Subject: [PATCH 03/34] chore(deps): bump actions/setup-node from 6 to 7 (#391) Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6 to 7. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/e2e-tests.yml | 8 ++++---- .github/workflows/frontend-tests.yml | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 5fa13d1eda..e90aae25ac 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -74,7 +74,7 @@ jobs: uses: actions/checkout@v7 - name: 🟒 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: '20' cache: 'npm' @@ -168,7 +168,7 @@ jobs: uses: actions/checkout@v7 - name: 🟒 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: '20' cache: 'npm' @@ -253,7 +253,7 @@ jobs: uses: actions/checkout@v7 - name: 🟒 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: '20' cache: 'npm' @@ -307,7 +307,7 @@ jobs: uses: actions/checkout@v7 - name: 🟒 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: '20' diff --git a/.github/workflows/frontend-tests.yml b/.github/workflows/frontend-tests.yml index 5c0d633735..b5dfedd0b1 100644 --- a/.github/workflows/frontend-tests.yml +++ b/.github/workflows/frontend-tests.yml @@ -43,7 +43,7 @@ jobs: uses: actions/checkout@v7 - name: 🟒 Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: ${{ matrix.node-version }} cache: 'npm' @@ -160,7 +160,7 @@ jobs: uses: actions/checkout@v7 - name: 🟒 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: '20' cache: 'npm' @@ -185,7 +185,7 @@ jobs: uses: actions/checkout@v7 - name: 🟒 Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: '20' cache: 'npm' From 01c717618a9da951c73a989cb2d3f54fec03f11b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:07:00 +0200 Subject: [PATCH 04/34] chore(deps): bump actions/setup-python from 6 to 7 (#396) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/sync-changedetection.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-changedetection.yaml b/.github/workflows/sync-changedetection.yaml index b6912e8265..1e93ddac5c 100644 --- a/.github/workflows/sync-changedetection.yaml +++ b/.github/workflows/sync-changedetection.yaml @@ -32,7 +32,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v7 with: python-version: '3.12' From ab6b0e97a545e3f1a1931e19957d3fda4b69fcc5 Mon Sep 17 00:00:00 2001 From: JesperDramsch <2620316+JesperDramsch@users.noreply.github.com> Date: Sat, 25 Jul 2026 02:55:40 +0000 Subject: [PATCH 05/34] chore: sort conferences --- _data/conferences.yml | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/_data/conferences.yml b/_data/conferences.yml index c97580055d..31f3371ed6 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -1,24 +1,5 @@ --- -- conference: PyCon South Africa - alt_name: PyCon ZA - year: 2026 - link: https://za.pycon.org/ - cfp_link: https://za.pycon.org/pages/speaking/how_to_apply/ - cfp: '2026-08-14 23:59:00' - tutorial_deadline: '2026-08-14 23:59:00' - timezone: Africa/Johannesburg - place: Rondebosch, South Africa - start: 2026-10-14 - end: 2026-10-18 - twitter: PyConZA - mastodon: https://fosstodon.org/@PyConZA - sub: PY - location: - - title: PyCon South Africa 2026 - latitude: -33.959834 - longitude: 18.473872 - - conference: PyCon Wroclaw year: 2026 link: https://www.pyconwroclaw.com/ @@ -71,6 +52,25 @@ latitude: 50.0478 longitude: 12.5604627 +- conference: PyCon South Africa + alt_name: PyCon ZA + year: 2026 + link: https://za.pycon.org/ + cfp_link: https://za.pycon.org/pages/speaking/how_to_apply/ + cfp: '2026-08-14 23:59:00' + tutorial_deadline: '2026-08-14 23:59:00' + timezone: Africa/Johannesburg + place: Rondebosch, South Africa + start: 2026-10-14 + end: 2026-10-18 + twitter: PyConZA + mastodon: https://fosstodon.org/@PyConZA + sub: PY + location: + - title: PyCon South Africa 2026 + latitude: -33.959834 + longitude: 18.473872 + - conference: PyData Global year: 2026 link: https://pydata.org/global2026/ From 9c073c552dab1ebd0e8f1530e5e1c80d471f25e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 13:53:52 +0200 Subject: [PATCH 06/34] chore(deps): bump actions/labeler from 6 to 7 (#398) Bumps [actions/labeler](https://github.com/actions/labeler) from 6 to 7. - [Release notes](https://github.com/actions/labeler/releases) - [Commits](https://github.com/actions/labeler/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/labeler dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 16dbac1afa..593821d10d 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -9,4 +9,4 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v6 + - uses: actions/labeler@v7 From 97b0b887705dce186496dfe5cb5573f375e169e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 13:54:40 +0200 Subject: [PATCH 07/34] chore: updates (#397) Co-authored-by: github-actions[bot] --- .all-contributorsrc | 9 +++++++++ CONTRIBUTING.md | 1 + README.md | 1 + 3 files changed, 11 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 201eb17157..d2302cf320 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -234,6 +234,15 @@ "contributions": [ "conference" ] + }, + { + "login": "drnlm", + "name": "Neil Muller", + "avatar_url": "https://avatars.githubusercontent.com/u/642056?v=4", + "profile": "https://github.com/drnlm", + "contributions": [ + "conference" + ] } ], "repoType": "github" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ff2a10b3b4..c24323b69e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -209,6 +209,7 @@ Example: jungmir
jungmir

πŸ“† + Neil Muller
Neil Muller

πŸ“† diff --git a/README.md b/README.md index e33ea476ce..58362910df 100644 --- a/README.md +++ b/README.md @@ -266,6 +266,7 @@ If you'd like to add support for a new language, please open an issue. jungmir
jungmir

πŸ“† + Neil Muller
Neil Muller

πŸ“† From 803e2e500d9b11a95cd098ef827748b20a4fbe5f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 14:17:56 +0200 Subject: [PATCH 08/34] =?UTF-8?q?=F0=9F=90=8D=20Conference=20updates=20(#3?= =?UTF-8?q?93)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * conf: [Conference] Pycon Namibia 2027 πŸ†• New year detected Source: https://na.pycon.org/ * chore: enrich TBA conferences with CFP data Enrichment level: quick Triggered: 2026-07-15T08:20:11Z * chore: enrich TBA conferences with CFP data Enrichment level: quick Triggered: 2026-07-17T08:15:37Z * conf: data merge from PSF calendar Source: canonical-ics Triggered: 2026-07-19T04:02:41Z * Fix conference name and add alternative name for PyNE * Remove wrongly classified mastodon link from conference details Removed the mastodon link for the FastAPI Conference 2026. * Fix sponsor link and update CFP information for 2027 Updated the sponsor link for PyCon Germany 2027 and removed the CFP link. --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Jesper Dramsch --- _data/conferences.yml | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/_data/conferences.yml b/_data/conferences.yml index 31f3371ed6..fa745ef8f6 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -18,6 +18,22 @@ latitude: 51.1089776 longitude: 17.0326689 +- conference: PyCon Namibia + year: 2027 + link: https://na.pycon.org/ + cfp: '2026-09-21 01:59:00' + timezone: Africa/Windhoek + place: Windhoek, Namibia + start: 2027-02-19 + end: 2027-02-25 + mastodon: https://hachyderm.io/@PyConNA + bluesky: https://bsky.app/profile/pyconna.bsky.social + sub: PY + location: + - title: PyCon Namibia 2027 + latitude: -22.5597 + longitude: 17.0832 + - conference: PyCon Netherlands alt_name: PyCon NL year: 2026 @@ -167,6 +183,7 @@ longitude: 114.1628131 - conference: Python Nordeste + alt_name: PyNE year: 2026 link: https://pythonnordeste.org/ cfp: '2026-06-19 23:59:00' @@ -698,35 +715,19 @@ alt_name: PyCon Germany year: 2027 link: https://2027.pycon.de/ - cfp_link: https://2027.pycon.de/ cfp: TBA timezone: Europe/Berlin place: Heidelberg, Germany start: 2027-04-20 end: 2027-04-22 - sponsor: https://2027.pycon.de/ + sponsor: https://2027.pycon.de/sponsoring/ + mastodon: https://fosstodon.org/@pyconde sub: PY,DATA location: - title: PyCon Germany & PyData Conference 2027 latitude: 49.4093582 longitude: 8.694724 -- conference: PyCon Namibia - year: 2027 - link: https://na.pycon.org/ - cfp: TBA - timezone: Africa/Johannesburg - place: Windhoek, Namibia - start: 2027-02-19 - end: 2027-02-25 - mastodon: https://hachyderm.io/@PyConNA - bluesky: https://bsky.app/profile/pyconna.bsky.social - sub: PY - location: - - title: PyCon Namibia 2027 - latitude: -22.5597 - longitude: 17.0832 - - conference: Python E-Commerce Forum year: 2026 link: https://codehut.co.uk/2026/ From cb3aad4079bb58d41f51e0213d4c22a673ce7b5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 22:53:22 +0200 Subject: [PATCH 09/34] chore(deps): bump github/codeql-action from 4 to 4.37.3 (#401) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4 to 4.37.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v4...v4.37.3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.37.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 70eea9e00b..2286b1f135 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -24,8 +24,8 @@ jobs: steps: - uses: actions/checkout@v7 - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@v4.37.3 with: languages: python - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@v4.37.3 From 482939bc1e3d149dc4acd3a9881cd1bd08e86e4c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2026 13:04:03 +0200 Subject: [PATCH 10/34] chore: sort conferences (#402) Co-authored-by: JesperDramsch <2620316+JesperDramsch@users.noreply.github.com> --- _data/archive.yml | 14 ++++++++++++++ _data/conferences.yml | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/_data/archive.yml b/_data/archive.yml index b2733187a3..2bd8f7e57c 100644 --- a/_data/archive.yml +++ b/_data/archive.yml @@ -1,5 +1,19 @@ --- +- conference: PyCon Singapore + year: 2026 + link: http://pycon.sg/ + cfp: TBA + place: Singapore, Singapore + start: 2026-06-19 + end: 2026-06-21 + sponsor: http://pycon.sg/index.html#sponsors + sub: PY + location: + - title: PyCon Singapore 2026 + latitude: 1.2899175 + longitude: 103.8519072 + - conference: GeoPython year: 2026 link: https://2026.geopython.net/ diff --git a/_data/conferences.yml b/_data/conferences.yml index fa745ef8f6..97ccb89e80 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -865,17 +865,3 @@ - title: Python Norte 2026 latitude: -1.374035 longitude: -48.4016623 - -- conference: PyCon Singapore - year: 2026 - link: http://pycon.sg/ - cfp: TBA - place: Singapore, Singapore - start: 2026-06-19 - end: 2026-06-21 - sponsor: http://pycon.sg/index.html#sponsors - sub: PY - location: - - title: PyCon Singapore 2026 - latitude: 1.2899175 - longitude: 103.8519072 From c3e8ed8934e807d236aa5c77a6faa07ec19492a5 Mon Sep 17 00:00:00 2001 From: Jesper Dramsch Date: Sat, 1 Aug 2026 13:48:50 +0200 Subject: [PATCH 11/34] Create cfp_candidates.py --- utils/cfp_candidates.py | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 utils/cfp_candidates.py diff --git a/utils/cfp_candidates.py b/utils/cfp_candidates.py new file mode 100644 index 0000000000..8dd479cbea --- /dev/null +++ b/utils/cfp_candidates.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""Emit conference series that likely need a new edition checked. + +A candidate is a series with no entry in _data/conferences.yml (nothing +upcoming or TBA) whose latest archived edition is recent enough that the +series is plausibly still alive. Output is JSON on stdout, newest first. + +Intended for the cfp-scout routine: run once at session start, then work +from the JSON instead of re-reading the data files. +""" + +import argparse +import json +from datetime import datetime, timezone +from pathlib import Path + +import yaml + +CARRY_FIELDS = ("link", "place", "sub", "alt_name", "cfp_link") + + +def load(path: Path) -> list[dict]: + if not path.exists(): + return [] + with path.open() as fh: + return yaml.safe_load(fh) or [] + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--lookback", + type=int, + default=2, + help="Only consider series whose latest edition is within this many years (default: 2)", + ) + parser.add_argument("--base", type=Path, default=Path(), help="Repository root") + args = parser.parse_args() + + current_year = datetime.now(tz=timezone.utc).year + cutoff = current_year - args.lookback + + current_names = {c["conference"] for c in load(args.base / "_data/conferences.yml")} + + latest: dict[str, dict] = {} + for conf in load(args.base / "_data/archive.yml"): + name = conf.get("conference") + year = conf.get("year") or 0 + if not name or name in current_names: + continue + if year > latest.get(name, {}).get("latest_year", 0): + entry = {"conference": name, "latest_year": year} + entry.update({k: conf[k] for k in CARRY_FIELDS if conf.get(k)}) + latest[name] = entry + + candidates = sorted( + (info for info in latest.values() if info["latest_year"] >= cutoff), + key=lambda x: (-x["latest_year"], x["conference"]), + ) + print(json.dumps({"generated": f"{current_year}", "count": len(candidates), "candidates": candidates}, indent=2)) + + +if __name__ == "__main__": + main() From aa52ba8a7f508a021dc240b6016ea0a3d771852c Mon Sep 17 00:00:00 2001 From: Jesper Dramsch Date: Sun, 2 Aug 2026 16:39:02 +0200 Subject: [PATCH 12/34] Add 1 new CfP/edition entries (cfp-scout 2026-08-01) (#403) * Add PyCon Taiwan 2026 (cfp-scout 2026-08-01) Scouted 10 stale conference series for new editions; PyCon Taiwan 2026 is the only one with published dates and a CfP deadline. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_018AYUgjp4P84fH8Epo42j8R * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Claude Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- _data/conferences.yml | 16 ++++++++++++++++ utils/cfp_candidates.py | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/_data/conferences.yml b/_data/conferences.yml index 97ccb89e80..cc8abc8b31 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -278,6 +278,22 @@ latitude: 5.5571096 longitude: -0.2012376 +- conference: PyCon Taiwan + alt_name: PyCon TW + year: 2026 + link: https://tw.pycon.org/2026/ + cfp_link: https://tw.pycon.org/2026/en-us/speaking/cfp + cfp: '2026-06-01 23:59:59' + place: Taipei, Taiwan + start: 2026-10-17 + end: 2026-10-18 + sponsor: https://tw.pycon.org/2026/en-us/sponsor + sub: PY + location: + - title: PyCon Taiwan 2026 + latitude: 25.033 + longitude: 121.5654 + - conference: PyCon Togo year: 2026 link: https://pycontg.pytogo.org/ diff --git a/utils/cfp_candidates.py b/utils/cfp_candidates.py index 8dd479cbea..b5f160b3a1 100644 --- a/utils/cfp_candidates.py +++ b/utils/cfp_candidates.py @@ -11,7 +11,8 @@ import argparse import json -from datetime import datetime, timezone +from datetime import datetime +from datetime import timezone from pathlib import Path import yaml From f48f1d7caacd5670c8bb01806b6b5435c15f3c6f Mon Sep 17 00:00:00 2001 From: Jesper Dramsch Date: Sun, 2 Aug 2026 17:47:01 +0200 Subject: [PATCH 13/34] fix: prevent canonical-csv merge from collapsing distinct conferences (#404) * fix: prevent fuzzy merge from collapsing distinct conferences A canonical-csv run (d76e737) renamed PyCon South Africa to PyCon Africa and deleted the real PyCon Africa entry. Root cause: conference_scorer takes the max of several fuzzy strategies, and token_set_ratio returns 100 whenever one name's tokens are a subset of the other's - so 'PyCon South Africa' vs 'PyCon Africa' scored 100 and was auto-merged as an 'exact' match with no confirmation. Both YAML rows then mapped to the same remote row and were collapsed into one by deduplication. Fixes: - fuzzy_match only auto-merges when names are genuinely identical; score-100-but-different pairs now go through the confirmation path, which defaults to 'no' in CI - remote rows already claimed by an identically-named YAML entry can never be fuzzy-merged by another conference - add PyCon Africa <-> PyCon South Africa to rejections.yml - add utils/check_data_loss.py and a workflow step that fails the canonical-source-update run before committing if any (conference, year) entry disappears from the data files - regression tests reproducing the incident Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH * fix: don't treat Google Maps viewport URLs as Mastodon profiles TBA enrichment's generic Mastodon fallback accepted any URL with '/@' in the path, so a venue map link like google.com/maps/place/Venue/@52.386807,4.8698442,17z was written into the mastodon field (29e9231, FastAPI Conference). The generic fallback now requires the path to be exactly /@handle (or /@user@instance). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH * feat: drop sub-page link fields that just repeat the homepage Upstream sources sometimes fill every URL column with the conference homepage (e.g. python-organizers' Proposal URL gave PyCon DE 2027 'cfp_link: https://2027.pycon.de/'). A cfp_link/sponsor/finaid identical to the main link carries no information, so the sort pipeline now drops them. URLs only count as identical when they differ at most by scheme, 'www.' prefix, or trailing slash - a different path, subdomain, query, or #anchor is a different pointer and survives. Existing offenders on main (PyCon Hong Kong cfp_link, PyCon Greece finaid, PyCon Italy finaid, PyCon Germany finaid) will be cleaned by the next recurring sort run. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH --------- Co-authored-by: Claude --- .github/workflows/canonical-source-update.yml | 10 ++ tests/test_fuzzy_match.py | 109 ++++++++++++++++ tests/test_redundant_links.py | 122 ++++++++++++++++++ tests/test_youtube_extraction.py | 23 ++++ utils/check_data_loss.py | 90 +++++++++++++ utils/enrich_tba.py | 9 +- utils/sort_yaml.py | 6 + utils/tidy_conf/data/rejections.yml | 9 +- utils/tidy_conf/interactive_merge.py | 102 ++++++++++++--- utils/tidy_conf/links.py | 65 ++++++++++ 10 files changed, 525 insertions(+), 20 deletions(-) create mode 100644 tests/test_redundant_links.py create mode 100644 utils/check_data_loss.py diff --git a/.github/workflows/canonical-source-update.yml b/.github/workflows/canonical-source-update.yml index 6ae3d71a80..1dfe86c35d 100644 --- a/.github/workflows/canonical-source-update.yml +++ b/.github/workflows/canonical-source-update.yml @@ -117,6 +117,7 @@ jobs: run: | cp _data/conferences.yml /tmp/conferences_before.yml cp _data/archive.yml /tmp/archive_before.yml 2>/dev/null || true + cp _data/legacy.yml /tmp/legacy_before.yml 2>/dev/null || true - name: Setup Pixi uses: prefix-dev/setup-pixi@v0.10.0 @@ -150,6 +151,15 @@ jobs: # Capture which source was processed for commit message echo "source_label=$SOURCE" >> $GITHUB_OUTPUT + - name: Verify no conference data loss + run: | + # An automated merge must never delete or rename existing conferences. + # This blocks e.g. two distinct conferences being fuzzy-matched into one + # (PyCon Africa vs PyCon South Africa) before anything is committed. + pixi run python ./utils/check_data_loss.py \ + --before /tmp/conferences_before.yml /tmp/archive_before.yml /tmp/legacy_before.yml \ + --after _data/conferences.yml _data/archive.yml _data/legacy.yml + - name: Check for changes id: check_changes run: | diff --git a/tests/test_fuzzy_match.py b/tests/test_fuzzy_match.py index f7b11ea2fd..4216a4512c 100644 --- a/tests/test_fuzzy_match.py +++ b/tests/test_fuzzy_match.py @@ -495,6 +495,115 @@ def test_below_90_percent_no_prompt(self, mock_title_mappings): assert len(remote) >= 1 +class TestSubsetNameCollision: + """Regression tests for distinct conferences whose names score 100. + + token_set_ratio returns 100 when one name's tokens are a subset of the + other's (e.g. "PyCon Africa" vs "PyCon South Africa"). Such pairs must + never be auto-merged as "exact" matches - that previously renamed + PyCon South Africa to PyCon Africa and deleted the real PyCon Africa + entry (commit d76e737). + """ + + @staticmethod + def _africa_yaml(include_africa: bool) -> pd.DataFrame: + rows = { + "conference": ["PyCon South Africa"], + "year": [2026], + "cfp": ["2026-06-01 23:59:00"], + "link": ["https://za.pycon.org/"], + "place": ["Rondebosch, South Africa"], + "start": ["2026-10-14"], + "end": ["2026-10-18"], + } + df = pd.DataFrame(rows) + if include_africa: + africa = pd.DataFrame( + { + "conference": ["PyCon Africa"], + "year": [2026], + "cfp": ["2026-04-16 23:59:00"], + "link": ["https://africa.pycon.org/"], + "place": ["Kampala, Uganda"], + "start": ["2026-10-07"], + "end": ["2026-10-11"], + }, + ) + df = pd.concat([df, africa], ignore_index=True) + return df + + @staticmethod + def _africa_remote() -> pd.DataFrame: + return pd.DataFrame( + { + "conference": ["PyCon Africa"], + "year": [2026], + "cfp": [""], + "link": ["https://africa.pycon.org/"], + "place": ["Kampala, Uganda"], + "start": ["2026-10-07"], + "end": ["2026-10-11"], + "sponsor": ["https://africa.pycon.org/2026/sponsor-us/"], + }, + ) + + def test_subset_name_is_not_an_exact_match(self, mock_title_mappings): + """A token-subset name pair must not auto-merge without confirmation. + + Contract: "PyCon South Africa" vs "PyCon Africa" scores 100 via + token_set_ratio, but the names are not identical, so it must go + through the fuzzy confirmation path (which defaults to "no" in CI). + """ + df_yml = self._africa_yaml(include_africa=False) + df_remote = self._africa_remote() + + # Non-interactive / user rejects: conferences stay separate + with patch("builtins.input", return_value="n"): + result, _remote, _report = fuzzy_match(df_yml, df_remote) + + conf_list = result["conference"].tolist() + assert "PyCon South Africa" in conf_list, f"PyCon South Africa was renamed/merged away: {conf_list}" + + za_row = result[result["conference"] == "PyCon South Africa"].iloc[0] + assert za_row["link"] == "https://za.pycon.org/" + assert za_row["start"] == "2026-10-14" + + def test_both_africa_conferences_survive_merge(self, mock_title_mappings): + """Reproduce the d76e737 incident: both conferences must survive. + + YAML has PyCon Africa (Kampala) and PyCon South Africa (Rondebosch); + the remote CSV has only PyCon Africa. The remote row belongs to its + identically-named YAML entry - PyCon South Africa must be left + completely alone, without prompting. + """ + df_yml = self._africa_yaml(include_africa=True) + df_remote = self._africa_remote() + + with patch( + "builtins.input", + side_effect=AssertionError("Should not prompt: remote row belongs to identical YAML entry"), + ): + result, _remote, _report = fuzzy_match(df_yml, df_remote) + + conf_list = result["conference"].tolist() + assert "PyCon Africa" in conf_list, f"PyCon Africa was lost: {conf_list}" + assert "PyCon South Africa" in conf_list, f"PyCon South Africa was lost: {conf_list}" + + za_row = result[result["conference"] == "PyCon South Africa"].iloc[0] + assert za_row["link"] == "https://za.pycon.org/" + assert za_row["place"] == "Rondebosch, South Africa" + assert za_row["start"] == "2026-10-14" + assert pd.isna(za_row.get("sponsor")) or za_row.get("sponsor") in ( + "", + None, + ), "PyCon South Africa must not inherit PyCon Africa's sponsor link" + + africa_row = result[result["conference"] == "PyCon Africa"].iloc[0] + assert africa_row["place"] == "Kampala, Uganda" + assert africa_row["start"] == "2026-10-07" + assert africa_row["sponsor"] == "https://africa.pycon.org/2026/sponsor-us/" + + class TestDataPreservation: """Test that original data is preserved through fuzzy matching.""" diff --git a/tests/test_redundant_links.py b/tests/test_redundant_links.py new file mode 100644 index 0000000000..d47d7af1b8 --- /dev/null +++ b/tests/test_redundant_links.py @@ -0,0 +1,122 @@ +"""Tests for dropping sub-page link fields that just repeat the homepage. + +Upstream sources sometimes fill every URL column with the conference +homepage (e.g. python-organizers' Proposal URL). A cfp_link/sponsor/finaid +identical to the main link carries no information and must be dropped +during sanitation - but a different path, subdomain, query, or #anchor is a +different pointer and must survive. +""" + +import sys +from pathlib import Path + +sys.path.append(str(Path(__file__).parent.parent / "utils")) + +from tidy_conf.links import drop_redundant_link_fields +from tidy_conf.links import normalize_url_pointer + + +class TestNormalizeUrlPointer: + """Test URL normalization for same-pointer comparison.""" + + def test_scheme_ignored(self): + assert normalize_url_pointer("http://pycon.de/") == normalize_url_pointer("https://pycon.de/") + + def test_www_prefix_ignored(self): + assert normalize_url_pointer("https://www.pycon.de/") == normalize_url_pointer("https://pycon.de/") + + def test_trailing_slash_ignored(self): + assert normalize_url_pointer("https://2027.pycon.de/") == normalize_url_pointer("https://2027.pycon.de") + + def test_fragment_is_different_pointer(self): + assert normalize_url_pointer("http://pycon.sg/#sponsors") != normalize_url_pointer("http://pycon.sg/") + + def test_path_is_different_pointer(self): + assert normalize_url_pointer("https://pycon.de/sponsoring/") != normalize_url_pointer("https://pycon.de/") + + def test_subdomain_is_different_pointer(self): + assert normalize_url_pointer("https://cfp.pycon.de/") != normalize_url_pointer("https://pycon.de/") + + def test_query_is_different_pointer(self): + assert normalize_url_pointer("https://pycon.de/?page=cfp") != normalize_url_pointer("https://pycon.de/") + + +class TestDropRedundantLinkFields: + """Test removal of sub-page links identical to the main link.""" + + def test_cfp_link_same_as_link_dropped(self): + """Reproduces the PyCon DE 2027 case: cfp_link is just the homepage.""" + data = [ + { + "conference": "PyCon DE & PyData", + "year": 2027, + "link": "https://2027.pycon.de/", + "cfp_link": "https://2027.pycon.de/", + "cfp": "TBA", + }, + ] + result = drop_redundant_link_fields(data) + assert "cfp_link" not in result[0] + assert result[0]["link"] == "https://2027.pycon.de/" + + def test_all_redundant_sub_fields_dropped(self): + data = [ + { + "conference": "Cheeky Conf", + "year": 2026, + "link": "https://cheeky.conf/", + "cfp_link": "https://cheeky.conf", + "sponsor": "http://www.cheeky.conf/", + "finaid": "https://cheeky.conf/", + }, + ] + result = drop_redundant_link_fields(data) + assert "cfp_link" not in result[0] + assert "sponsor" not in result[0] + assert "finaid" not in result[0] + + def test_anchor_on_homepage_kept(self): + """A #anchor is a different pointer (e.g. PyCon SG's sponsor link).""" + data = [ + { + "conference": "PyCon Singapore", + "year": 2026, + "link": "http://pycon.sg/", + "sponsor": "http://pycon.sg/index.html#sponsors", + }, + ] + result = drop_redundant_link_fields(data) + assert result[0]["sponsor"] == "http://pycon.sg/index.html#sponsors" + + def test_sub_page_and_subdomain_kept(self): + data = [ + { + "conference": "PyCon Africa", + "year": 2026, + "link": "https://africa.pycon.org/", + "cfp_link": "https://africa.pycon.org/2026/talks/proposals/", + "sponsor": "https://africa.pycon.org/2026/sponsor-us/", + "finaid": "https://africa.pycon.org/2026/opportunity-grants/", + }, + { + "conference": "Sub Conf", + "year": 2026, + "link": "https://sub.conf/", + "cfp_link": "https://cfp.sub.conf/", + }, + ] + result = drop_redundant_link_fields(data) + assert result[0]["cfp_link"] == "https://africa.pycon.org/2026/talks/proposals/" + assert result[0]["sponsor"] == "https://africa.pycon.org/2026/sponsor-us/" + assert result[0]["finaid"] == "https://africa.pycon.org/2026/opportunity-grants/" + assert result[1]["cfp_link"] == "https://cfp.sub.conf/" + + def test_entry_without_link_untouched(self): + data = [{"conference": "No Link Conf", "year": 2026, "cfp_link": "https://example.com/"}] + result = drop_redundant_link_fields(data) + assert result[0]["cfp_link"] == "https://example.com/" + + def test_entry_without_sub_fields_untouched(self): + data = [{"conference": "Plain Conf", "year": 2026, "link": "https://plain.conf/"}] + result = drop_redundant_link_fields(data) + assert result[0] == {"conference": "Plain Conf", "year": 2026, "link": "https://plain.conf/"} diff --git a/tests/test_youtube_extraction.py b/tests/test_youtube_extraction.py index 87da528d1f..e4eee280bd 100644 --- a/tests/test_youtube_extraction.py +++ b/tests/test_youtube_extraction.py @@ -75,6 +75,29 @@ def test_generic_mastodon_still_works(self, mock_links): assert "mastodon" in result assert "youtube" not in result + @patch("enrich_tba.get_all_links") + def test_google_maps_viewport_not_mastodon(self, mock_links): + """Google Maps /@lat,lng,zoom viewport URLs must not be detected as mastodon. + + Regression test: a venue map link like + https://www.google.com/maps/place/Transformatorhuis/@52.386807,4.8698442,17z + contains "/@" but is not a Mastodon profile. + """ + mock_links.return_value = [ + "https://www.google.com/maps/place/Transformatorhuis/@52.386807,4.8698442,17z", + ] + result = extract_links_from_url("https://fastapiconf.com") + assert "mastodon" not in result + + @patch("enrich_tba.get_all_links") + def test_user_at_instance_profile_still_works(self, mock_links): + """Full /@user@instance profile paths are still detected as mastodon.""" + mock_links.return_value = [ + "https://social.example.org/@pyconf@mastodon.social", + ] + result = extract_links_from_url("https://pyconf.org") + assert result.get("mastodon") == "https://social.example.org/@pyconf@mastodon.social" + @patch("enrich_tba.get_all_links") def test_youtube_first_seen_wins(self, mock_links): """Only the first YouTube link is kept.""" diff --git a/utils/check_data_loss.py b/utils/check_data_loss.py new file mode 100644 index 0000000000..4f316088e0 --- /dev/null +++ b/utils/check_data_loss.py @@ -0,0 +1,90 @@ +"""Guard against silent conference loss during automated data merges. + +Compares snapshots of the conference data files taken before a merge with the +files after the merge. Every (conference, year) pair that existed before must +still exist afterwards - in any of the given files, since conferences may +legitimately move between conferences.yml, archive.yml and legacy.yml. + +Exits non-zero if any conference disappeared, so CI can block the commit. +A legitimate rename (via titles.yml mappings) will also trip this check; +that is intentional - renames of existing entries should be reviewed by a +human, not auto-committed. +""" + +import argparse +import sys +from pathlib import Path + +import yaml + + +def load_conference_keys(paths: list[str]) -> set[tuple[str, int | str]]: + """Collect (conference, year) pairs from a list of YAML data files. + + Missing files are skipped, so the same invocation works whether or not + optional files like legacy.yml exist. + """ + keys = set() + for path in paths: + file = Path(path) + if not file.exists(): + continue + with file.open(encoding="utf-8") as f: + data = yaml.safe_load(f) + if not data: + continue + for entry in data: + if not isinstance(entry, dict): + continue + conference = entry.get("conference") + year = entry.get("year") + if conference: + keys.add((str(conference).strip(), year)) + return keys + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Fail if conferences disappeared from the data files.", + ) + parser.add_argument( + "--before", + nargs="+", + required=True, + help="Data files snapshotted before the merge", + ) + parser.add_argument( + "--after", + nargs="+", + required=True, + help="Data files after the merge", + ) + args = parser.parse_args() + + before = load_conference_keys(args.before) + after = load_conference_keys(args.after) + missing = before - after + + if missing: + print( + f"ERROR: {len(missing)} conference(s) disappeared during the merge:", + file=sys.stderr, + ) + for conference, year in sorted(missing, key=str): + print(f" - {conference} ({year})", file=sys.stderr) + print( + "\nAn automated merge must never delete or rename existing conferences.\n" + "This usually means two distinct conferences were fuzzy-matched into one\n" + "(e.g. 'PyCon Africa' vs 'PyCon South Africa'). Add the pair to\n" + "utils/tidy_conf/data/rejections.yml, or if the rename is intentional,\n" + "apply it manually.", + file=sys.stderr, + ) + return 1 + + print(f"OK: all {len(before)} conference entries survived the merge.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/utils/enrich_tba.py b/utils/enrich_tba.py index bed4ec4bcf..93a24a6e10 100644 --- a/utils/enrich_tba.py +++ b/utils/enrich_tba.py @@ -272,6 +272,11 @@ def _domain_matches(domain: str, hosts: tuple[str, ...]) -> bool: return any(domain == h or domain.endswith(f".{h}") for h in hosts) +# A Mastodon profile URL's path is exactly "/@handle" (or "/@user@instance"). +# Requiring this shape prevents false positives from other "/@" URLs, e.g. +# Google Maps viewports like "/maps/place/Venue/@52.386807,4.8698442,17z". +MASTODON_PROFILE_RE = re.compile(r"^/@[A-Za-z0-9_][\w.-]*(?:@[\w.-]+)?/?$") + # Known Mastodon instances (common ones in tech/Python community) MASTODON_INSTANCES = { "mastodon.social", @@ -366,8 +371,8 @@ def extract_links_from_url(url: str) -> dict[str, str]: found["mastodon"] = link seen_types.add("mastodon") logger.debug(f" Found mastodon: {link}") - elif "/@" in parsed_link.path: - # Generic /@username pattern - likely Mastodon-compatible + elif MASTODON_PROFILE_RE.match(parsed_link.path): + # Path is exactly /@username - likely Mastodon-compatible found["mastodon"] = link seen_types.add("mastodon") logger.debug(f" Found mastodon (generic): {link}") diff --git a/utils/sort_yaml.py b/utils/sort_yaml.py index 2eba1ae2ed..c627ee9513 100644 --- a/utils/sort_yaml.py +++ b/utils/sort_yaml.py @@ -22,6 +22,7 @@ from tidy_conf.latlon import add_latlon from tidy_conf.links import check_link_availability from tidy_conf.links import check_mastodon_migration + from tidy_conf.links import drop_redundant_link_fields from tidy_conf.links import get_cache from tidy_conf.schema import Conference from tidy_conf.schema import get_schema @@ -35,6 +36,7 @@ from .tidy_conf.latlon import add_latlon from .tidy_conf.links import check_link_availability from .tidy_conf.links import check_mastodon_migration + from .tidy_conf.links import drop_redundant_link_fields from .tidy_conf.links import get_cache from .tidy_conf.schema import Conference from .tidy_conf.schema import get_schema @@ -289,6 +291,10 @@ def sort_data(base="", prefix="", skip_links=False): logger.info("🏷️ Cleaning titles") data = tidy_titles(data) + # Drop sub-page links that just repeat the homepage + logger.info("πŸ”— Dropping redundant link fields") + data = drop_redundant_link_fields(data) + # Add Sub logger.info("🏒 Adding submission types") data = auto_add_sub(data) diff --git a/utils/tidy_conf/data/rejections.yml b/utils/tidy_conf/data/rejections.yml index d9c6e345a3..4fa46225e0 100644 --- a/utils/tidy_conf/data/rejections.yml +++ b/utils/tidy_conf/data/rejections.yml @@ -1,4 +1,3 @@ ---- alt_name: AfroPython Conference: variations: @@ -14,6 +13,11 @@ alt_name: variations: - PyCon Australia - PyCon AU + PyCon Africa: + variations: + - PyCon South Africa + - PyCon ZA + - PyConZA PyCon Austria: variations: - PyCon Australia @@ -30,6 +34,9 @@ alt_name: PyCon Latin America: variations: - PyCon Latam + PyCon South Africa: + variations: + - PyCon Africa Python Austria: variations: - PyCon Australia diff --git a/utils/tidy_conf/interactive_merge.py b/utils/tidy_conf/interactive_merge.py index d511b802d6..c26225249a 100644 --- a/utils/tidy_conf/interactive_merge.py +++ b/utils/tidy_conf/interactive_merge.py @@ -55,6 +55,29 @@ } +def is_identical_name(s1: str, s2: str) -> bool: + """Check whether two conference names are genuinely identical. + + A fuzzy score of 100 does NOT imply identity: token_set_ratio returns 100 + whenever one name's tokens are a subset of the other's (e.g. "PyCon Africa" + vs "PyCon South Africa"). Only names that are equal after case and + whitespace normalization may be auto-merged without confirmation. + + Parameters + ---------- + s1 : str + First conference name to compare + s2 : str + Second conference name to compare + + Returns + ------- + bool + True if the names are identical after normalization + """ + return " ".join(s1.lower().split()) == " ".join(s2.lower().split()) + + def is_placeholder_value(value) -> bool: """Check if a value is a placeholder (TBA, TBD, None, empty). @@ -276,6 +299,31 @@ def is_excluded(name1, name2): """Check if two conference names are in the combined exclusion list.""" return frozenset([name1, name2]) in all_exclusions + def best_match(title_match): + """Extract (title, score) from a process.extract result (2- or 3-tuple).""" + match_result = title_match[0] + if len(match_result) == 3: + title, prob, _ = match_result + else: + title, prob = match_result + return title, prob + + # Remote titles already spoken for by a YAML row with the genuinely + # identical name. No other YAML row may merge into these - otherwise two + # distinct conferences collapse into one row and one of them is lost + # (e.g. "PyCon South Africa" must not merge into remote "PyCon Africa" + # when a YAML "PyCon Africa" also exists). + identical_titles = set() + for _, row in df.iterrows(): + if isinstance(row["title_match"], str) or not row["title_match"]: + continue + title, _prob = best_match(row["title_match"]) + if is_identical_name(row["conference"], title): + identical_titles.add(title) + + # Remote titles claimed by a YAML row during this run (title -> yaml name) + claimed_titles = {} + # Process matches and track in report for i, row in df.iterrows(): if isinstance(row["title_match"], str): @@ -283,12 +331,7 @@ def is_excluded(name1, name2): if not row["title_match"]: continue - # Handle both 2-tuple and 3-tuple results from process.extract - match_result = row["title_match"][0] - if len(match_result) == 3: - title, prob, _ = match_result - else: - title, prob = match_result + title, prob = best_match(row["title_match"]) conference_name = row["conference"] year = row.get("year", 0) @@ -311,21 +354,45 @@ def is_excluded(name1, name2): df.at[i, "title_match"] = conference_name # Use original name, not index record.match_type = "excluded" record.action = "kept_yaml" - elif prob >= EXACT_MATCH_THRESHOLD: - logger.debug( - f"Exact match: '{conference_name}' -> '{title}' (score: {prob})", - ) - df.at[i, "title_match"] = title - record.match_type = "exact" - record.action = "merged" + elif prob >= EXACT_MATCH_THRESHOLD and is_identical_name(conference_name, title): + # Only genuinely identical names merge automatically. A score of + # 100 alone is NOT sufficient: token_set_ratio scores 100 whenever + # one name's tokens are a subset of the other's. + if title in claimed_titles and claimed_titles[title] != conference_name: + logger.warning( + f"Remote '{title}' already claimed by '{claimed_titles[title]}', " + f"keeping '{conference_name}' separate", + ) + df.at[i, "title_match"] = conference_name + record.match_type = "exact" + record.action = "kept_yaml" + else: + logger.debug( + f"Exact match: '{conference_name}' -> '{title}' (score: {prob})", + ) + df.at[i, "title_match"] = title + claimed_titles[title] = conference_name + record.match_type = "exact" + record.action = "merged" elif prob >= FUZZY_MATCH_THRESHOLD: + if title in identical_titles or title in claimed_titles: + # Remote row already belongs to its identically-named YAML + # entry (or was claimed earlier) - never merge another + # conference into it. + logger.info( + f"Skipping fuzzy match: remote '{title}' already belongs to an " + f"identically-named entry, keeping '{conference_name}' separate", + ) + df.at[i, "title_match"] = conference_name + record.match_type = "fuzzy" + record.action = "kept_yaml" # Prompt user for fuzzy matches that aren't excluded - logger.info( - f"Fuzzy match candidate: '{conference_name}' -> '{title}' (score: {prob})", - ) - if not query_yes_no( + elif not query_yes_no( f"Do '{row['conference']}' and '{title}' match? (y/n): ", ): + logger.info( + f"Fuzzy match rejected: '{conference_name}' vs '{title}' (score: {prob})", + ) new_rejections[title].append(conference_name) new_rejections[conference_name].append(title) df.at[i, "title_match"] = conference_name # Use original name, not index @@ -334,6 +401,7 @@ def is_excluded(name1, name2): else: new_mappings[conference_name].append(title) df.at[i, "title_match"] = title + claimed_titles[title] = conference_name record.match_type = "fuzzy" record.action = "merged" else: diff --git a/utils/tidy_conf/links.py b/utils/tidy_conf/links.py index c630d352a2..a3adec7241 100644 --- a/utils/tidy_conf/links.py +++ b/utils/tidy_conf/links.py @@ -9,6 +9,71 @@ import requests from tqdm import tqdm +# Sub-page link fields that must point somewhere other than the main link. +# A cfp_link/sponsor/finaid that is just the homepage again carries no +# information (e.g. "cfp_link: https://2027.pycon.de/" on the PyCon DE entry +# whose link is https://2027.pycon.de/) - it should be a different page, a +# subdomain, or at least a #anchor on the homepage. +REDUNDANT_LINK_FIELDS = ("cfp_link", "sponsor", "finaid") + + +def normalize_url_pointer(url: str) -> tuple: + """Normalize a URL for same-pointer comparison. + + Two URLs are the same pointer when they only differ by scheme + (http/https), a "www." prefix, host case, or a trailing slash. + Anything else - path, subdomain, query, or #fragment - makes them + different pointers. + + Parameters + ---------- + url : str + URL to normalize + + Returns + ------- + tuple + Comparable (host, path, params, query, fragment) tuple + """ + parsed = urlparse(str(url).strip()) + netloc = parsed.netloc.lower().removeprefix("www.") + return (netloc, parsed.path.rstrip("/"), parsed.params, parsed.query, parsed.fragment) + + +def drop_redundant_link_fields(data: list) -> list: + """Drop sub-page link fields that are the same pointer as the main link. + + Goes through cfp_link/sponsor/finaid on each conference and + removes any that just repeat the conference's main link. This catches + upstream sources that fill every URL column with the homepage. + + Parameters + ---------- + data : list + List of conference dictionaries + + Returns + ------- + list + The same list with redundant link fields removed + """ + for q in data: + if not isinstance(q, dict): + continue + link = q.get("link") + if not link: + continue + base = normalize_url_pointer(link) + for field in REDUNDANT_LINK_FIELDS: + value = q.get(field) + if value and normalize_url_pointer(value) == base: + tqdm.write( + f"Dropping redundant '{field}' from {q.get('conference')} {q.get('year')}: " + f"'{value}' is the same pointer as the main link", + ) + del q[field] + return data + def get_cache_location(): # Check if the URL is cached From 9eb1f760bf3c03db6b4281ecff38660b20b660bf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:47:53 +0200 Subject: [PATCH 14/34] =?UTF-8?q?=F0=9F=90=8D=20Conference=20updates=20(#4?= =?UTF-8?q?00)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * conf: data merge from python-organizers Source: canonical-csv Triggered: 2026-07-29T05:47:14Z * chore: enrich TBA conferences with CFP data Enrichment level: quick Triggered: 2026-07-29T08:46:08Z * conf: data merge from python-organizers Source: canonical-csv Triggered: 2026-07-30T22:49:52Z * conf: PyCon Ireland Source: https://2026.pycon.ie/ Zone: extension_watch * fix: restore PyCon Africa and PyCon South Africa as separate conferences The canonical-csv merge (d76e737) fuzzy-matched 'PyCon South Africa' against the remote 'PyCon Africa' row (token_set_ratio scores 100 for token-subset names), renamed the ZA entry and collapsed the real PyCon Africa (Kampala, Uganda) entry into it. Restores the PyCon Africa 2026 entry and returns the PyCon South Africa entry to its own name without the wrongly grafted africa.pycon.org sponsor/finaid/youtube links. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH * fix: remove Google Maps link wrongly detected as Mastodon profile TBA enrichment (29e9231) matched the FastAPI Conference venue's map URL against the generic '/@username' Mastodon pattern because Google Maps viewports contain '/@lat,lng,zoom'. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH * fix: drop redundant PyCon DE 2027 cfp_link (same URL as homepage) The canonical-csv merge copied python-organizers' Proposal URL, which is just the conference homepage. Sub-page links that repeat the main link carry no information and are now dropped by the sort pipeline. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH --------- Co-authored-by: github-actions[bot] Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Jesper Dramsch Co-authored-by: Claude --- _data/conferences.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/_data/conferences.yml b/_data/conferences.yml index cc8abc8b31..efd535abf4 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -1,5 +1,19 @@ --- +- conference: PyCon Lithuania + year: 2027 + link: https://pycon.lt/2027/ + cfp_link: https://pycon.lt/2027/cfp + cfp: '2027-01-13 23:59:00' + place: Vilnius, Lithuania + start: 2027-04-28 + end: 2027-04-30 + sub: PY + location: + - title: PyCon Lithuania 2027 + latitude: 54.6870458 + longitude: 25.2829111 + - conference: PyCon Wroclaw year: 2026 link: https://www.pyconwroclaw.com/ @@ -140,6 +154,7 @@ link: https://2026.pycon.ie/ cfp_link: https://sessionize.com/pycon-ireland-2026/ cfp: '2026-07-31 23:59:00' + cfp_ext: '2026-08-30 23:59:00' place: Dublin, Ireland start: 2026-10-17 end: 2026-10-17 @@ -318,6 +333,7 @@ place: Hiroshima, Japan start: 2026-08-21 end: 2026-08-22 + sponsor: https://2026.pycon.jp/en/sponsors sub: PY location: - title: PyCon Japan 2026 From 7cd7d4998f70c8b80e89722b4943b0138ef93398 Mon Sep 17 00:00:00 2001 From: Ferran Jovell Date: Sun, 2 Aug 2026 17:50:51 +0200 Subject: [PATCH 15/34] Add PyConES 2026 (#394) * Add PyConES 2026 * fix ci * pr-comments * pr-comments --------- Co-authored-by: Ferran Jovell --- _data/conferences.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/_data/conferences.yml b/_data/conferences.yml index efd535abf4..d872a9e428 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -391,6 +391,23 @@ latitude: -27.5953778 longitude: -48.5480367 +- conference: PyCon Spain + year: 2026 + link: https://2026.es.pycon.org/ + cfp: '2026-05-17 23:59:00' + cfp_link: https://pretalx.com/pycones-2026/ + timezone: Europe/Madrid + place: Barcelona, Spain + start: 2026-11-06 + end: 2026-11-08 + sponsor: https://2026.es.pycon.org/en/sponsors/#about + finaid: https://2026.es.pycon.org/en/becas + sub: PY + location: + - title: PyCon Spain 2026 + latitude: 41.3866666 + longitude: 2.1636166 + - conference: PyCon Russia year: 2026 link: https://www.pycon.ru/ From a08788c09f52279489c7e7fa5d13d8a717d7e561 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:53:04 +0200 Subject: [PATCH 16/34] chore: updates (#405) Co-authored-by: github-actions[bot] --- .all-contributorsrc | 9 +++++++++ CONTRIBUTING.md | 1 + README.md | 1 + _data/archive.yml | 2 -- _data/conferences.yml | 23 +++-------------------- 5 files changed, 14 insertions(+), 22 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d2302cf320..d2f3485151 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -243,6 +243,15 @@ "contributions": [ "conference" ] + }, + { + "login": "mrswats", + "name": "Ferran Jovell", + "avatar_url": "https://avatars.githubusercontent.com/u/3410779?v=4", + "profile": "https://github.com/mrswats", + "contributions": [ + "conference" + ] } ], "repoType": "github" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c24323b69e..3ba122d397 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -210,6 +210,7 @@ Example: jungmir
jungmir

πŸ“† Neil Muller
Neil Muller

πŸ“† + Ferran Jovell
Ferran Jovell

πŸ“† diff --git a/README.md b/README.md index 58362910df..73e2888415 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,7 @@ If you'd like to add support for a new language, please open an issue. jungmir
jungmir

πŸ“† Neil Muller
Neil Muller

πŸ“† + Ferran Jovell
Ferran Jovell

πŸ“† diff --git a/_data/archive.yml b/_data/archive.yml index 2bd8f7e57c..4d9ab253e9 100644 --- a/_data/archive.yml +++ b/_data/archive.yml @@ -58,7 +58,6 @@ start: 2026-05-27 end: 2026-05-30 sponsor: https://2026.pycon.it/sponsor/ - finaid: https://2026.pycon.it/en mastodon: https://social.python.it/@pycon sub: PY location: @@ -174,7 +173,6 @@ start: 2026-04-14 end: 2026-04-17 sponsor: https://2026.pycon.de/sponsoring/ - finaid: https://2026.pycon.de/ sub: PY,DATA location: - title: PyCon Germany & PyData Conference 2026 diff --git a/_data/conferences.yml b/_data/conferences.yml index d872a9e428..324fbeeffd 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -183,7 +183,6 @@ - conference: PyCon Hong Kong year: 2026 link: https://www.pycon.hk/ - cfp_link: https://www.pycon.hk/ cfp: '2026-06-20 23:59:59' timezone: Asia/Hong_Kong place: Hong Kong, China @@ -393,15 +392,16 @@ - conference: PyCon Spain year: 2026 - link: https://2026.es.pycon.org/ - cfp: '2026-05-17 23:59:00' + link: https://2026.es.pycon.org/en/ cfp_link: https://pretalx.com/pycones-2026/ + cfp: '2026-05-17 23:59:00' timezone: Europe/Madrid place: Barcelona, Spain start: 2026-11-06 end: 2026-11-08 sponsor: https://2026.es.pycon.org/en/sponsors/#about finaid: https://2026.es.pycon.org/en/becas + bluesky: https://bsky.app/profile/es.pycon.org sub: PY location: - title: PyCon Spain 2026 @@ -433,7 +433,6 @@ place: Athens, Greece start: 2026-10-12 end: 2026-10-13 - finaid: https://pycon.gr/ youtube: https://www.youtube.com/@pycongreece sub: PY location: @@ -460,22 +459,6 @@ latitude: 37.5580558199932 longitude: 126.998311394625 -- conference: PyCon Spain - year: 2026 - link: https://2026.es.pycon.org/en/ - cfp: '2026-05-03 23:59:00' - timezone: Europe/Madrid - place: Barcelona, Spain - start: 2026-11-06 - end: 2026-11-08 - sponsor: https://2026.es.pycon.org/es/sponsors/ - bluesky: https://bsky.app/profile/es.pycon.org - sub: PY - location: - - title: PyCon Spain 2026 - latitude: 41.3828939 - longitude: 2.1774322 - - conference: PyCon Latin America alt_name: PyCon LatAm year: 2026 From 28769dd3cbf1a2e669c2e55425fc61ca518f3139 Mon Sep 17 00:00:00 2001 From: Jesper Dramsch Date: Sun, 2 Aug 2026 20:18:22 +0200 Subject: [PATCH 17/34] cfp: Pycon Sweden --- _data/conferences.yml | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/_data/conferences.yml b/_data/conferences.yml index 324fbeeffd..a36594a31e 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -728,6 +728,24 @@ latitude: 50.061389 longitude: 19.938333 +- conference: PyCon Sweden + year: 2026 + link: https://pycon.se/ + cfp_link: https://pretalx.com/pycon-sweden-2026/ + cfp: '2025-08-23 23:59:00' + timezone: Europe/Stockholm + place: Stockholm, Sweden + start: 2026-11-19 + end: 2026-11-20 + sponsor: https://pycon.se/#sponsorship + mastodon: https://unsplash.com/@micaelwidell?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText + youtube: https://www.youtube.com/c/PyConSweden + sub: PY + location: + - title: PyCon Sweden 2026 + latitude: 59.3251172 + longitude: 18.0710935 + - conference: PyCon Austria year: 2027 link: https://pycon.at/ @@ -773,22 +791,6 @@ latitude: 55.9533456 longitude: -3.1883749 -- conference: PyCon Sweden - year: 2026 - link: https://pycon.se/ - cfp: TBA - place: Stockholm, Sweden - start: 2026-11-19 - end: 2026-11-20 - sponsor: https://pycon.se/#sponsorship - mastodon: https://unsplash.com/@micaelwidell?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText - youtube: https://www.youtube.com/c/PyConSweden - sub: PY - location: - - title: PyCon Sweden 2026 - latitude: 59.3251172 - longitude: 18.0710935 - - conference: XtremePython year: 2026 link: https://xtremepython.dev/ From 48d697d9b19325211f8996f063479af8476a17cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 12:11:08 +0200 Subject: [PATCH 18/34] chore(deps): bump github/codeql-action from 4.37.3 to 4.37.4 (#406) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.37.3 to 4.37.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v4.37.3...v4.37.4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.37.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2286b1f135..2156330f27 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -24,8 +24,8 @@ jobs: steps: - uses: actions/checkout@v7 - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.3 + uses: github/codeql-action/init@v4.37.4 with: languages: python - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4.37.3 + uses: github/codeql-action/analyze@v4.37.4 From 10330ea23f51f423022db29e83992cc42a56f9f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 12:11:17 +0200 Subject: [PATCH 19/34] chore(deps): bump anthropics/claude-code-action from 1 to 1.0.183 (#408) Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1 to 1.0.183. - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](https://github.com/anthropics/claude-code-action/compare/v1...v1.0.183) --- updated-dependencies: - dependency-name: anthropics/claude-code-action dependency-version: 1.0.183 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-conference-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-conference-update.yml b/.github/workflows/check-conference-update.yml index 303805b156..61c1280748 100644 --- a/.github/workflows/check-conference-update.yml +++ b/.github/workflows/check-conference-update.yml @@ -913,7 +913,7 @@ jobs: run: echo "GITHUB_ACTOR=${{ github.repository_owner }}" >> "$GITHUB_ENV" - name: Run Claude Code Analysis - uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@v1.0.183 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} allowed_bots: 'github-actions[bot]' @@ -1178,7 +1178,7 @@ jobs: run: echo "GITHUB_ACTOR=${{ github.repository_owner }}" >> "$GITHUB_ENV" - name: Run Claude Code Analysis - uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@v1.0.183 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} allowed_bots: 'github-actions[bot]' From a7ca7ff3adbdf3fcef2ba8232452583d3365b967 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 12:11:44 +0200 Subject: [PATCH 20/34] =?UTF-8?q?=F0=9F=90=8D=20Conference=20updates=20(#4?= =?UTF-8?q?07)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * conf: PyData Global Source: https://pydata.org/global2026/ Zone: extension_watch * chore: enrich TBA conferences with CFP data Enrichment level: full Triggered: 2026-08-04T08:43:13Z --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] --- _data/conferences.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/_data/conferences.yml b/_data/conferences.yml index a36594a31e..4b11eaba64 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -105,6 +105,7 @@ year: 2026 link: https://pydata.org/global2026/ cfp: '2026-08-03 23:59:00' + cfp_ext: '2026-08-24 23:59:00' workshop_deadline: '2026-08-03 23:59:00' tutorial_deadline: '2026-08-03 23:59:00' place: Online @@ -833,6 +834,7 @@ year: 2026 link: https://barcamps.eu/pythoncamp-ruegen-2026/ cfp: TBA + timezone: Europe/Berlin place: RΓΌgen, Germany start: 2026-09-26 end: 2026-09-27 @@ -861,6 +863,7 @@ year: 2026 link: https://barcamps.eu/python-barcamp-leipzig-2026/ cfp: TBA + timezone: Europe/Berlin place: Leipzig, Germany start: 2026-08-01 end: 2026-08-02 From 5483e846c28ac8b92c2360fa086a76cdc44c34e5 Mon Sep 17 00:00:00 2001 From: Jesper Dramsch Date: Thu, 6 Aug 2026 09:31:35 +0200 Subject: [PATCH 21/34] Change CFP status to 'Cancelled' for PyCon EE Updated the CFP status for PyCon EE to 'Cancelled' and added a new field for the original CFP deadline. --- _data/conferences.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_data/conferences.yml b/_data/conferences.yml index 4b11eaba64..248fd3f3b7 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -645,7 +645,8 @@ year: 2026 link: https://pycon.ee/ cfp_link: https://docs.google.com/forms/d/e/1FAIpQLSewbFKG6BEsGXR9ilgsW1wqfmzRR0Pf9XDO5WXTFhrcgrrN3g/viewform - cfp: '2026-02-28 23:59:00' + cfp: Cancelled + cfp_ext: '2026-02-28 23:59:00' place: Tallinn, Estonia start: 2026-10-08 end: 2026-10-09 From f2dc574469f19fa3522a6d3fa3ef56cfcb4c9dd2 Mon Sep 17 00:00:00 2001 From: JesperDramsch <2620316+JesperDramsch@users.noreply.github.com> Date: Sat, 8 Aug 2026 01:52:20 +0000 Subject: [PATCH 22/34] chore: sort conferences --- _data/conferences.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/_data/conferences.yml b/_data/conferences.yml index 248fd3f3b7..8f93be85b9 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -640,22 +640,6 @@ latitude: 45.3349238 longitude: 14.3067834 -- conference: PyCon Estonia - alt_name: PyCon EE - year: 2026 - link: https://pycon.ee/ - cfp_link: https://docs.google.com/forms/d/e/1FAIpQLSewbFKG6BEsGXR9ilgsW1wqfmzRR0Pf9XDO5WXTFhrcgrrN3g/viewform - cfp: Cancelled - cfp_ext: '2026-02-28 23:59:00' - place: Tallinn, Estonia - start: 2026-10-08 - end: 2026-10-09 - sub: PY - location: - - title: PyCon Estonia 2026 - latitude: 59.4372155 - longitude: 24.7453688 - - conference: SciPy US alt_name: SciPy year: 2026 @@ -815,6 +799,22 @@ latitude: 52.3730796 longitude: 4.8924534 +- conference: PyCon Estonia + alt_name: PyCon EE + year: 2026 + link: https://pycon.ee/ + cfp_link: https://docs.google.com/forms/d/e/1FAIpQLSewbFKG6BEsGXR9ilgsW1wqfmzRR0Pf9XDO5WXTFhrcgrrN3g/viewform + cfp: Cancelled + cfp_ext: '2026-02-28 23:59:00' + place: Tallinn, Estonia + start: 2026-10-08 + end: 2026-10-09 + sub: PY + location: + - title: PyCon Estonia 2026 + latitude: 59.4372155 + longitude: 24.7453688 + - conference: EARL year: 2026 link: https://earl-conference.com/ From af76caafee96b206c5de4ee2178a68771d9af3f9 Mon Sep 17 00:00:00 2001 From: Jesper Dramsch Date: Sat, 8 Aug 2026 09:25:51 +0200 Subject: [PATCH 23/34] Add 2 new CfP/edition entries (cfp-scout 2026-08-08) (#416) Backfill PyGrunn 2026 and Python Sul 2026 editions (both already past today's date) so future cfp-scout runs stop re-flagging these series and instead check for 2027 editions. Co-authored-by: Claude --- _data/archive.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/_data/archive.yml b/_data/archive.yml index 4d9ab253e9..f9323b9047 100644 --- a/_data/archive.yml +++ b/_data/archive.yml @@ -96,6 +96,35 @@ latitude: 52.2319581 longitude: 21.0067249 +- conference: PyGrunn + year: 2026 + link: https://pygrunn.org/ + cfp_link: https://forms.gle/5qAYUczPptmGVCY58 + cfp: TBA + place: Groningen, Netherlands + start: 2026-05-08 + end: 2026-05-08 + sub: PY + location: + - title: PyGrunn 2026 + latitude: 53.2190652 + longitude: 6.5680077 + +- conference: Python Sul + alt_name: Python Sul (Brazil) + year: 2026 + link: https://sul.python.org.br/ + cfp: TBA + timezone: America/Sao_Paulo + place: Londrina, Brazil + start: 2026-05-01 + end: 2026-05-03 + sub: PY + location: + - title: Python Sul 2026 + latitude: -23.4761271 + longitude: -51.1179013 + - conference: North Bay Python year: 2026 link: https://northbaypython.org/ From 340f3ed8f0eec574abaffbee0aa733ed0d111db6 Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Sun, 9 Aug 2026 00:13:18 +0530 Subject: [PATCH 24/34] Add SciPy India 2026 --- _data/conferences.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/_data/conferences.yml b/_data/conferences.yml index 8f93be85b9..4692432509 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -903,3 +903,20 @@ - title: Python Norte 2026 latitude: -1.374035 longitude: -48.4016623 + +- conference: SciPy India + year: 2026 + link: https://scipy.in/2026/ + cfp: TBA + timezone: Asia/Kolkata + place: Chennai, India + start: 2026-12-19 + end: 2026-12-20 + sponsor: https://scipy.in/2026/sponsor.html + bluesky: https://bsky.app/profile/scipy.in + youtube: https://www.youtube.com/@scipy-india + sub: SCIPY + location: + - title: SciPy India 2026 + latitude: 12.9917014 + longitude: 80.2295271 From 4be8d2959971d867f2ce74ef03dc763638a12fa5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 13:53:40 +0200 Subject: [PATCH 25/34] chore(deps): bump anthropics/claude-code-action from 1.0.183 to 1.0.191 (#423) Bumps [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) from 1.0.183 to 1.0.191. - [Release notes](https://github.com/anthropics/claude-code-action/releases) - [Commits](https://github.com/anthropics/claude-code-action/compare/v1.0.183...v1.0.191) --- updated-dependencies: - dependency-name: anthropics/claude-code-action dependency-version: 1.0.191 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-conference-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-conference-update.yml b/.github/workflows/check-conference-update.yml index 61c1280748..3510f875c1 100644 --- a/.github/workflows/check-conference-update.yml +++ b/.github/workflows/check-conference-update.yml @@ -913,7 +913,7 @@ jobs: run: echo "GITHUB_ACTOR=${{ github.repository_owner }}" >> "$GITHUB_ENV" - name: Run Claude Code Analysis - uses: anthropics/claude-code-action@v1.0.183 + uses: anthropics/claude-code-action@v1.0.191 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} allowed_bots: 'github-actions[bot]' @@ -1178,7 +1178,7 @@ jobs: run: echo "GITHUB_ACTOR=${{ github.repository_owner }}" >> "$GITHUB_ENV" - name: Run Claude Code Analysis - uses: anthropics/claude-code-action@v1.0.183 + uses: anthropics/claude-code-action@v1.0.191 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} allowed_bots: 'github-actions[bot]' From a8ed9ebe2a6b34e834e6a7f8578c03fdea771cfc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 13:55:39 +0200 Subject: [PATCH 26/34] chore(deps-dev): bump brace-expansion (#420) Bumps the npm_and_yarn group with 1 update in the / directory: [brace-expansion](https://github.com/juliangruber/brace-expansion). Updates `brace-expansion` from 1.1.12 to 1.1.18 - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.12...v1.1.18) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 1.1.18 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c5b1c15e6..1d4b54c68f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1393,10 +1393,11 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" From 62dbac85f8e48bede406c77657c60262f0a65780 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 13:56:16 +0200 Subject: [PATCH 27/34] chore: updates (#424) Co-authored-by: github-actions[bot] --- .all-contributorsrc | 9 +++++++ CONTRIBUTING.md | 1 + README.md | 1 + _data/archive.yml | 28 +++++++++++++++++++ _data/conferences.yml | 62 ++++++++++++------------------------------- 5 files changed, 56 insertions(+), 45 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index d2f3485151..37373bfb46 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -252,6 +252,15 @@ "contributions": [ "conference" ] + }, + { + "login": "agriyakhetarpal", + "name": "Agriya Khetarpal", + "avatar_url": "https://avatars.githubusercontent.com/u/74401230?v=4", + "profile": "https://github.com/agriyakhetarpal", + "contributions": [ + "conference" + ] } ], "repoType": "github" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ba122d397..306a1422d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -211,6 +211,7 @@ Example: jungmir
jungmir

πŸ“† Neil Muller
Neil Muller

πŸ“† Ferran Jovell
Ferran Jovell

πŸ“† + Agriya Khetarpal
Agriya Khetarpal

πŸ“† diff --git a/README.md b/README.md index 73e2888415..e57764ec4b 100644 --- a/README.md +++ b/README.md @@ -268,6 +268,7 @@ If you'd like to add support for a new language, please open an issue. jungmir
jungmir

πŸ“† Neil Muller
Neil Muller

πŸ“† Ferran Jovell
Ferran Jovell

πŸ“† + Agriya Khetarpal
Agriya Khetarpal

πŸ“† diff --git a/_data/archive.yml b/_data/archive.yml index f9323b9047..bb0c4cdcf7 100644 --- a/_data/archive.yml +++ b/_data/archive.yml @@ -1,5 +1,33 @@ --- +- conference: Python Norte + year: 2026 + link: https://pythonnorte.org/ + cfp: TBA + timezone: America/Sao_Paulo + place: Ananindeua, Brazil + start: 2026-07-03 + end: 2026-07-05 + sub: PY + location: + - title: Python Norte 2026 + latitude: -1.374035 + longitude: -48.4016623 + +- conference: Web Summer Camp + year: 2026 + link: https://websummercamp.com/ + cfp_link: https://sessionize.com/web-summer-camp-2026/ + cfp: '2026-02-28 23:59:59' + place: Opatija, Croatia + start: 2026-07-02 + end: 2026-07-04 + sub: WEB + location: + - title: Web Summer Camp 2026 + latitude: 45.3349238 + longitude: 14.3067834 + - conference: PyCon Singapore year: 2026 link: http://pycon.sg/ diff --git a/_data/conferences.yml b/_data/conferences.yml index 4692432509..5c238ab540 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -626,20 +626,6 @@ latitude: 41.8755616 longitude: -87.6244212 -- conference: Web Summer Camp - year: 2026 - link: https://websummercamp.com/ - cfp_link: https://sessionize.com/web-summer-camp-2026/ - cfp: '2026-02-28 23:59:59' - place: Opatija, Croatia - start: 2026-07-02 - end: 2026-07-04 - sub: WEB - location: - - title: Web Summer Camp 2026 - latitude: 45.3349238 - longitude: 14.3067834 - - conference: SciPy US alt_name: SciPy year: 2026 @@ -764,6 +750,23 @@ latitude: 49.4093582 longitude: 8.694724 +- conference: SciPy India + year: 2026 + link: https://scipy.in/2026/ + cfp: TBA + timezone: Asia/Kolkata + place: Chennai, India + start: 2026-12-19 + end: 2026-12-20 + sponsor: https://scipy.in/2026/sponsor.html + bluesky: https://bsky.app/profile/scipy.in + youtube: https://www.youtube.com/@scipy-india + sub: SCIPY + location: + - title: SciPy India 2026 + latitude: 12.9917014 + longitude: 80.2295271 + - conference: Python E-Commerce Forum year: 2026 link: https://codehut.co.uk/2026/ @@ -889,34 +892,3 @@ - title: PyData PyCon Armenia 2026 latitude: 40.1777112 longitude: 44.5126233 - -- conference: Python Norte - year: 2026 - link: https://pythonnorte.org/ - cfp: TBA - timezone: America/Sao_Paulo - place: Ananindeua, Brazil - start: 2026-07-03 - end: 2026-07-05 - sub: PY - location: - - title: Python Norte 2026 - latitude: -1.374035 - longitude: -48.4016623 - -- conference: SciPy India - year: 2026 - link: https://scipy.in/2026/ - cfp: TBA - timezone: Asia/Kolkata - place: Chennai, India - start: 2026-12-19 - end: 2026-12-20 - sponsor: https://scipy.in/2026/sponsor.html - bluesky: https://bsky.app/profile/scipy.in - youtube: https://www.youtube.com/@scipy-india - sub: SCIPY - location: - - title: SciPy India 2026 - latitude: 12.9917014 - longitude: 80.2295271 From a0205ac52122935aba3445da14e26c1f422cecc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 13:56:27 +0200 Subject: [PATCH 28/34] chore(deps): bump prefix-dev/setup-pixi from 0.10.0 to 0.10.1 (#418) Bumps [prefix-dev/setup-pixi](https://github.com/prefix-dev/setup-pixi) from 0.10.0 to 0.10.1. - [Release notes](https://github.com/prefix-dev/setup-pixi/releases) - [Commits](https://github.com/prefix-dev/setup-pixi/compare/v0.10.0...v0.10.1) --- updated-dependencies: - dependency-name: prefix-dev/setup-pixi dependency-version: 0.10.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/canonical-source-update.yml | 2 +- .github/workflows/check-conference-update.yml | 4 ++-- .github/workflows/ci-core.yml | 6 +++--- .github/workflows/enrich-tba-conferences.yml | 2 +- .github/workflows/pr-sort.yml | 2 +- .github/workflows/recurring-sort.yml | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/canonical-source-update.yml b/.github/workflows/canonical-source-update.yml index 1dfe86c35d..68f8a0a138 100644 --- a/.github/workflows/canonical-source-update.yml +++ b/.github/workflows/canonical-source-update.yml @@ -120,7 +120,7 @@ jobs: cp _data/legacy.yml /tmp/legacy_before.yml 2>/dev/null || true - name: Setup Pixi - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: Run merge scripts id: merge diff --git a/.github/workflows/check-conference-update.yml b/.github/workflows/check-conference-update.yml index 3510f875c1..9db3888c77 100644 --- a/.github/workflows/check-conference-update.yml +++ b/.github/workflows/check-conference-update.yml @@ -953,7 +953,7 @@ jobs: - name: Setup Pixi if: steps.check_changes.outputs.changed == 'true' - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: Sort conferences if: steps.check_changes.outputs.changed == 'true' @@ -1216,7 +1216,7 @@ jobs: - name: Setup Pixi if: steps.check_changes.outputs.changed == 'true' - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: Sort conferences if: steps.check_changes.outputs.changed == 'true' diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 334ad88075..c905bee74a 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v7 - name: 🐍 Setup Pixi - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: βœ… Validate conference data structure run: | @@ -56,7 +56,7 @@ jobs: uses: actions/checkout@v7 - name: 🐍 Setup Pixi - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: πŸ§ͺ Run Python tests run: | @@ -77,7 +77,7 @@ jobs: uses: actions/checkout@v7 - name: 🐍 Setup Pixi - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: πŸ” Run pre-commit hooks run: | diff --git a/.github/workflows/enrich-tba-conferences.yml b/.github/workflows/enrich-tba-conferences.yml index e14c1ecaaf..4725c5e135 100644 --- a/.github/workflows/enrich-tba-conferences.yml +++ b/.github/workflows/enrich-tba-conferences.yml @@ -105,7 +105,7 @@ jobs: cp _data/conferences.yml /tmp/conferences_before.yml - name: Setup Pixi - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: Install lynx for text extraction run: sudo apt-get install -qq -y lynx > /dev/null 2>&1 || true diff --git a/.github/workflows/pr-sort.yml b/.github/workflows/pr-sort.yml index d094be6372..266f1b2989 100644 --- a/.github/workflows/pr-sort.yml +++ b/.github/workflows/pr-sort.yml @@ -38,7 +38,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Pixi - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: Set variables id: vars diff --git a/.github/workflows/recurring-sort.yml b/.github/workflows/recurring-sort.yml index 5aa55d7ba8..22a7ce76e4 100644 --- a/.github/workflows/recurring-sort.yml +++ b/.github/workflows/recurring-sort.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v7 - name: Setup Pixi - uses: prefix-dev/setup-pixi@v0.10.0 + uses: prefix-dev/setup-pixi@v0.10.1 - name: Run links command run: pixi run sort From 6d56a06331ccc85922984ae640ba3ce98c8049cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Aug 2026 13:57:10 +0200 Subject: [PATCH 29/34] chore(deps): bump github/codeql-action from 4.37.4 to 4.37.6 (#413) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.37.4 to 4.37.6. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v4.37.4...v4.37.6) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.37.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2156330f27..3e133c89df 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -24,8 +24,8 @@ jobs: steps: - uses: actions/checkout@v7 - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.4 + uses: github/codeql-action/init@v4.37.6 with: languages: python - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4.37.4 + uses: github/codeql-action/analyze@v4.37.6 From 2d6fc38ed8bd3820de1cfd94d348ee88b6c0a561 Mon Sep 17 00:00:00 2001 From: Ege Akman Date: Sat, 15 Aug 2026 16:30:53 +0300 Subject: [PATCH 30/34] Merge pull request #425 from egeakman/python-pizza-istanbul Add Python Pizza Istanbul --- _data/conferences.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/_data/conferences.yml b/_data/conferences.yml index 5c238ab540..05b4b38b21 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -48,6 +48,23 @@ latitude: -22.5597 longitude: 17.0832 +- conference: Python Pizza Istanbul + alt_name: Istanbul Python Pizza + year: 2026 + link: https://istanbul.python.pizza/ + cfp_link: https://istanbul.python.pizza/cfp/ + cfp: '2026-08-25 23:59:00' + place: Istanbul, Turkey + start: 2026-11-14 + end: 2026-11-14 + sponsor: https://istanbul.python.pizza/sponsors/ + twitter: pythonpizzaist + sub: PY + location: + - title: Python Pizza Istanbul 2026 + latitude: 41.1088 + longitude: 29.0176 + - conference: PyCon Netherlands alt_name: PyCon NL year: 2026 From 219d0b0d9fe4e7e962a780e0b3b0b7e55582c4e7 Mon Sep 17 00:00:00 2001 From: Jesper Dramsch Date: Sat, 15 Aug 2026 15:37:28 +0200 Subject: [PATCH 31/34] Add 4 new CfP/edition entries (cfp-scout 2026-08-15) (#426) * Add 4 new CfP/edition entries (cfp-scout 2026-08-15) * Delete duplicate Xtreme Python conference from conferences.yml Removed Xtreme Python conference entry for 2026. --------- Co-authored-by: Claude --- _data/archive.yml | 13 +++++++++++++ _data/conferences.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/_data/archive.yml b/_data/archive.yml index bb0c4cdcf7..fcc348b2b9 100644 --- a/_data/archive.yml +++ b/_data/archive.yml @@ -365,6 +365,19 @@ latitude: -22.611456150000002 longitude: 17.05860104184979 +- conference: Pytorch Day + year: 2026 + link: https://events.linuxfoundation.org/pytorch-day-india/ + cfp: TBA + place: Bengaluru, India + start: 2026-02-07 + end: 2026-02-07 + sub: DATA,DAY + location: + - title: Pytorch Day 2026 + latitude: 12.9767936 + longitude: 77.590082 + - conference: FOSDEM year: 2026 link: https://fosdem.org/2026/ diff --git a/_data/conferences.yml b/_data/conferences.yml index 05b4b38b21..17c4ef16fd 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -48,6 +48,17 @@ latitude: -22.5597 longitude: 17.0832 +- conference: Wagtail Space + year: 2026 + link: https://wagtail.org/wagtail-space-2026/ + cfp_link: https://pretalx.com/wagtail-space-2026/cfp + cfp: '2026-09-11 23:59:00' + timezone: UTC + place: Online + start: 2026-11-18 + end: 2026-11-20 + sub: WEB + - conference: Python Pizza Istanbul alt_name: Istanbul Python Pizza year: 2026 @@ -99,6 +110,21 @@ latitude: 50.0478 longitude: 12.5604627 +- conference: PyHEP.dev + alt_name: PyHEP + year: 2026 + link: https://indico.nikhef.nl/event/7873/ + cfp: '2026-08-14 23:59:00' + timezone: Europe/Amsterdam + place: Amsterdam, Netherlands + start: 2026-09-07 + end: 2026-09-09 + sub: SCIPY + location: + - title: PyHEP.dev 2026 + latitude: 52.4111289 + longitude: 4.877231604293446 + - conference: PyCon South Africa alt_name: PyCon ZA year: 2026 From 7189d2148a0de31de51896e30939becf98f76558 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 15:50:49 +0200 Subject: [PATCH 32/34] Conference updates (#411) * chore: enrich TBA conferences with CFP data Enrichment level: quick Triggered: 2026-08-06T08:42:05Z * chore: enrich TBA conferences with CFP data Enrichment level: quick Triggered: 2026-08-08T06:59:00Z * chore: enrich TBA conferences with CFP data Enrichment level: quick Triggered: 2026-08-15T06:42:25Z --------- Co-authored-by: github-actions[bot] Co-authored-by: Jesper Dramsch --- _data/conferences.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_data/conferences.yml b/_data/conferences.yml index 17c4ef16fd..106dd64290 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -802,6 +802,7 @@ start: 2026-12-19 end: 2026-12-20 sponsor: https://scipy.in/2026/sponsor.html + mastodon: https://fosstodon.org/@scipyindia bluesky: https://bsky.app/profile/scipy.in youtube: https://www.youtube.com/@scipy-india sub: SCIPY @@ -855,6 +856,7 @@ place: Tallinn, Estonia start: 2026-10-08 end: 2026-10-09 + sponsor: https://pycon.ee/#sponsors sub: PY location: - title: PyCon Estonia 2026 From 2b7c9f8dd74bd1667b37efa4c2651904925052b2 Mon Sep 17 00:00:00 2001 From: Jesper Dramsch Date: Tue, 25 Aug 2026 19:51:30 +0200 Subject: [PATCH 33/34] Add 2 new CfP/edition entries (cfp-scout 2026-08-22) (#432) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New editions found for PyCon PanamΓ‘ 2026 (Oct 22-23, Panama City) and PyCon Tanzania 2026 (Nov 14-16, Dar Es Salaam). Neither has a published CfP deadline yet, so both are recorded as cfp: TBA. Co-authored-by: Claude --- _data/conferences.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/_data/conferences.yml b/_data/conferences.yml index 106dd64290..78fadd6469 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -833,6 +833,20 @@ end: 2026-11-17 sub: PY +- conference: PyCon Tanzania + alt_name: Python Tanzania Conference + year: 2026 + link: https://pycon.or.tz/ + cfp: TBA + place: Dar Es Salaam, Tanzania + start: 2026-11-14 + end: 2026-11-16 + sub: PY + location: + - title: PyCon Tanzania 2026 + latitude: -6.8160837 + longitude: 39.2803583 + - conference: FastAPI Conference year: 2026 link: https://fastapiconf.com/ @@ -846,6 +860,19 @@ latitude: 52.3730796 longitude: 4.8924534 +- conference: PyCon PanamΓ‘ + year: 2026 + link: https://pycon.pa/2026/ + cfp: TBA + place: Panama City, PanamΓ‘ + start: 2026-10-22 + end: 2026-10-23 + sub: PY + location: + - title: PyCon PanamΓ‘ 2026 + latitude: 8.9714493 + longitude: -79.5341802 + - conference: PyCon Estonia alt_name: PyCon EE year: 2026 From f554750b3110ac45efa279e02b00966ecebdd34d Mon Sep 17 00:00:00 2001 From: Agriya Khetarpal <74401230+agriyakhetarpal@users.noreply.github.com> Date: Tue, 25 Aug 2026 23:22:28 +0530 Subject: [PATCH 34/34] Add CFP deadline and link for SciPy India 2026 (#435) --- _data/conferences.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_data/conferences.yml b/_data/conferences.yml index 78fadd6469..79a78caaf2 100644 --- a/_data/conferences.yml +++ b/_data/conferences.yml @@ -796,7 +796,8 @@ - conference: SciPy India year: 2026 link: https://scipy.in/2026/ - cfp: TBA + cfp: '2026-10-19 23:59:00' + cfp_link: https://cfp.scipy.in/scipy-india-2026/cfp timezone: Asia/Kolkata place: Chennai, India start: 2026-12-19