From 0794023fec10a7064355e64240f4579cd711d542 Mon Sep 17 00:00:00 2001 From: Brad Barnett <127794626+bdbarnett@users.noreply.github.com> Date: Mon, 19 Oct 2026 12:59:02 -0500 Subject: [PATCH] Mark usbif, audioif, cameraif and displayif as moved The repository database keeps the four entries so their portal pages stay up, but as pointers: portal_grid is off, their hero apps are gone and their buttons lead to the new homes. A new _meta.moved block is rendered into the ecosystem maps (the org profile and pydevices' docs/ecosystem.md) as 'Moved into other repositories'. The site chrome's sidebar drops the four, the header's DisplayIF link becomes Firmware, and micropython-pydevices' description names its current upstream. SUPPORT.md, github-presence.md and the Cursor environment stop naming displayif as a repository. --- .cursor/environment.json | 1 - SUPPORT.md | 2 +- assets/js/site-chrome.js | 38 +--------- data/repos_db.json | 130 ++++++++++++++++------------------- docs/github-presence.md | 2 +- profile/README.md | 13 ++-- scripts/generate_sites.py | 10 +++ tests/test_generate_sites.py | 27 ++++++++ 8 files changed, 106 insertions(+), 117 deletions(-) diff --git a/.cursor/environment.json b/.cursor/environment.json index e1d2a7e..90e46d4 100644 --- a/.cursor/environment.json +++ b/.cursor/environment.json @@ -7,7 +7,6 @@ "github.com/PyDevices/PyDevices.github.io", "github.com/PyDevices/pydevices", "github.com/PyDevices/pydevices-examples", - "github.com/PyDevices/displayif", "github.com/PyDevices/audiodsp", "github.com/PyDevices/pygraphics", "github.com/PyDevices/palettes", diff --git a/SUPPORT.md b/SUPPORT.md index f8de0a8..9a28c20 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -5,7 +5,7 @@ Welcome to PyDevices! Here are the best ways to get help and ask questions acros ## πŸ’¬ Getting Help & Discussions - **Q&A & Ideas**: For questions, hardware setup discussions, or feature ideas, please use [pydevices Discussions](https://github.com/PyDevices/pydevices/discussions) β€” the single Q&A venue for the whole organization. Other repositories intentionally have Discussions disabled and use Issues only. -- **Bug Reports**: If you have found a reproducible bug in a specific package, please open an issue in the corresponding repository (e.g. `pydevices`, `displayif`, `pygraphics`, `pdwidgets`). +- **Bug Reports**: If you have found a reproducible bug in a specific package, please open an issue in the corresponding repository (e.g. `pydevices`, `micropython-pydevices`, `pygraphics`, `pdwidgets`). ## πŸ“š Live Documentation & Specs diff --git a/assets/js/site-chrome.js b/assets/js/site-chrome.js index 98b6984..37ad574 100644 --- a/assets/js/site-chrome.js +++ b/assets/js/site-chrome.js @@ -42,7 +42,7 @@ '/pydevices/">Core Stack' + 'DisplayIF' + + '/micropython-pydevices/">Firmware' + 'Workbench' + @@ -101,15 +101,6 @@ desc: "Unified display HAL & device driver abstraction", icon: '' }, - { - id: "displayif", - name: "displayif", - path: "/displayif/", - url: ROOT + "/displayif/", - tag: "C Bus", - desc: "Native C SPI, I2C, 8080 & RGB usermods", - icon: '' - }, { id: "audiodsp", name: "audiodsp", @@ -119,15 +110,6 @@ desc: "CircuitPython audio stack as MicroPython usermods", icon: '' }, - { - id: "audioif", - name: "audioif", - path: "/audioif/", - url: ROOT + "/audioif/", - tag: "C Audio Driver", - desc: "I2S drivers and the audio pump's platform threads", - icon: '' - }, { id: "audiocomponents", name: "audiocomponents", @@ -137,24 +119,6 @@ desc: "55 instruments and 45 effects on audiodsp", icon: '' }, - { - id: "usbif", - name: "usbif", - path: "/usbif/", - url: ROOT + "/usbif/", - tag: "C USB", - desc: "USB device and host classes for MicroPython", - icon: '' - }, - { - id: "cameraif", - name: "cameraif", - path: "/cameraif/", - url: ROOT + "/cameraif/", - tag: "C Camera", - desc: "MIPI-CSI camera as a MicroPython object", - icon: '' - }, { id: "pydevices-examples", name: "examples", diff --git a/data/repos_db.json b/data/repos_db.json index db27e91..2f706cd 100644 --- a/data/repos_db.json +++ b/data/repos_db.json @@ -30,6 +30,12 @@ "excluded": { ".github (dotgithub)": "No landing page by design. It holds org-wide data, scripts, and community health files, and is documented as markdown only.", "android-runner": "Exists solely to enable pydevices/bin/android.py. The APK is documented in pydevices; the runner publishes no site." + }, + "moved": { + "displayif": "now [`modules/displayif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/displayif) in micropython-pydevices. The old repository is archived.", + "audioif": "now [`modules/audioif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/audioif) in micropython-pydevices. The old repository is archived.", + "cameraif": "now [`modules/cameraif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/cameraif) in micropython-pydevices. The old repository is archived.", + "usbif": "the C module is now [`modules/usbhost`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/usbhost) in micropython-pydevices; the Python USB packages are in [pydevices](https://github.com/PyDevices/pydevices/blob/main/docs/usb.md). The old repository is archived." } }, "pydevices": { @@ -73,37 +79,32 @@ "displayif": { "tier": 1, "page": "portal-subdir", + "portal_grid": false, + "title": "PyDevices - displayif (moved)", "tier_name": "Core Platform & Board Contract", "theme_color": "var(--tier-1-amber)", - "eyebrow": "displayif", - "headline": "displayif β€” C hardware bus engine & usermod drivers.", - "description": "High-performance C hardware bus engines (SPI, I2C, Intel 8080, RGB/DPI, MIPI DSI) and native usermod display drivers for MicroPython and CircuitPython.", - "hero_canvas": { - "app": "bus_scope", - "width": 240, - "height": 240, - "shape": "square", - "app_url": "https://PyDevices.github.io/assets/apps/bus_scope.py" - }, + "eyebrow": "displayif Β· moved", + "headline": "displayif has moved into micropython-pydevices.", + "description": "Moved to micropython-pydevices as modules/displayif, with its history. It was never published on its own: it reaches you in firmware built by micropython-pydevices' build_mp.py, so that is where it is built, tested and changed now. Your code doesn't change. The old repository is archived.", "buttons": [ { - "label": "GitHub Repo", - "href": "https://github.com/PyDevices/displayif", + "label": "modules/displayif", + "href": "https://github.com/PyDevices/micropython-pydevices/tree/main/modules/displayif", "primary": true }, { - "label": "Hardware Bring-up", - "href": "https://github.com/PyDevices/displayif/blob/main/docs/soft-reset-and-bring-up.md", + "label": "Hardware bring-up", + "href": "https://github.com/PyDevices/micropython-pydevices/blob/main/modules/displayif/docs/soft-reset-and-bring-up.md", "tier_color": true }, { - "label": "pygraphics", - "href": "https://pydevices.github.io/pygraphics/", + "label": "micropython-pydevices", + "href": "https://pydevices.github.io/micropython-pydevices/", "tier_color": true }, { - "label": "pydevices Core", - "href": "https://pydevices.github.io/pydevices/", + "label": "Archived repo", + "href": "https://github.com/PyDevices/displayif", "tier_color": true } ] @@ -149,37 +150,32 @@ "audioif": { "tier": 1, "page": "portal-subdir", + "portal_grid": false, + "title": "PyDevices - audioif (moved)", "tier_name": "Core Platform & Board Contract", "theme_color": "var(--tier-1-amber)", - "eyebrow": "audioif", - "headline": "audioif β€” the audio hardware layer: the platform drivers under the audio pump.", - "description": "The part of the audio stack that knows what a thread is, where the clock comes from and where the sound goes: a pinned task and the I2S peripheral on ESP32, a native thread on unix and Windows, and a CircuitPython-shaped audiobusio.I2SOut over all of it. With it in a firmware, a graph keeps an exact clock while a screen redraws and a USB stack runs, and audiodev plays through it without being asked. The portable half of the pump, and every DSP node, is audiodsp.", - "hero_canvas": { - "app": "signal_gen", - "width": 480, - "height": 480, - "shape": "square", - "app_url": "https://PyDevices.github.io/assets/apps/signal_gen.py" - }, + "eyebrow": "audioif Β· moved", + "headline": "audioif has moved into micropython-pydevices.", + "description": "Moved to micropython-pydevices as modules/audioif, with its history. It was never published on its own: it reaches you in firmware built by micropython-pydevices' build_mp.py, so that is where it is built, tested and changed now. Your code doesn't change. The old repository is archived.", "buttons": [ { - "label": "GitHub Repo", - "href": "https://github.com/PyDevices/audioif", + "label": "modules/audioif", + "href": "https://github.com/PyDevices/micropython-pydevices/tree/main/modules/audioif", "primary": true }, { - "label": "Releases", - "href": "https://github.com/PyDevices/audioif/releases/latest", + "label": "Audio in pydevices", + "href": "https://github.com/PyDevices/pydevices/blob/main/docs/audio.md", "tier_color": true }, { - "label": "audiodsp", - "href": "https://pydevices.github.io/audiodsp/", + "label": "micropython-pydevices", + "href": "https://pydevices.github.io/micropython-pydevices/", "tier_color": true }, { - "label": "Audio in pydevices", - "href": "https://github.com/PyDevices/pydevices/blob/main/docs/audio.md", + "label": "Archived repo", + "href": "https://github.com/PyDevices/audioif", "tier_color": true } ] @@ -225,37 +221,32 @@ "usbif": { "tier": 1, "page": "portal-subdir", + "portal_grid": false, + "title": "PyDevices - usbif (moved)", "tier_name": "Core Platform & Board Contract", "theme_color": "var(--tier-1-amber)", - "eyebrow": "usbif", - "headline": "usbif β€” native USB for MicroPython: device, host, and both at once.", - "description": "A board a computer sees as a sound card, a MIDI instrument, a keyboard, a drive or a webcam β€” and, on the same board, a USB host that a keyboard, thumb drive, MIDI controller or camera plugs into. One of the PyDevices *if modules, with displayif, audioif and cameraif: a native C module with a thin, stable Python surface that runs unchanged on a workstation.", - "hero_canvas": { - "app": "encoder", - "width": 480, - "height": 480, - "shape": "square", - "app_url": "https://PyDevices.github.io/assets/apps/encoder.py" - }, + "eyebrow": "usbif Β· moved", + "headline": "usbif has moved, to two homes.", + "description": "The C module is now usbhost, in micropython-pydevices as modules/usbhost (its binding is _usbhost, it was _usbif). The Python USB packages (usb.core, the host and device classes, usb-hid) are top-level packages in pydevices, installed with mip. Code that uses the packages doesn't change. The old repository is archived.", "buttons": [ { - "label": "GitHub Repo", - "href": "https://github.com/PyDevices/usbif", + "label": "modules/usbhost", + "href": "https://github.com/PyDevices/micropython-pydevices/tree/main/modules/usbhost", "primary": true }, { - "label": "Portable API", - "href": "https://github.com/PyDevices/usbif/blob/main/lib/usbif/README.md", + "label": "USB packages in pydevices", + "href": "https://github.com/PyDevices/pydevices/blob/main/docs/usb.md", "tier_color": true }, { - "label": "Examples", - "href": "https://github.com/PyDevices/usbif/tree/main/examples", + "label": "micropython-pydevices", + "href": "https://pydevices.github.io/micropython-pydevices/", "tier_color": true }, { - "label": "audiodsp", - "href": "https://pydevices.github.io/audiodsp/", + "label": "Archived repo", + "href": "https://github.com/PyDevices/usbif", "tier_color": true } ] @@ -263,37 +254,32 @@ "cameraif": { "tier": 1, "page": "portal-subdir", + "portal_grid": false, + "title": "PyDevices - cameraif (moved)", "tier_name": "Core Platform & Board Contract", "theme_color": "var(--tier-1-amber)", - "eyebrow": "cameraif", - "headline": "cameraif β€” a MIPI-CSI camera as a MicroPython object.", - "description": "Point the board at something and read the frame. The sensor is found by probing rather than named in code, so a different camera is a build-time option away, not a rewrite. Hardware JPEG, zero-copy frames and hardware scaling straight into a display's scanout buffer, with every rate in its README measured on the board it names.", - "hero_canvas": { - "app": "encoder", - "width": 480, - "height": 480, - "shape": "square", - "app_url": "https://PyDevices.github.io/assets/apps/encoder.py" - }, + "eyebrow": "cameraif Β· moved", + "headline": "cameraif has moved into micropython-pydevices.", + "description": "Moved to micropython-pydevices as modules/cameraif, with its history. It was never published on its own: it reaches you in firmware built by micropython-pydevices' build_mp.py, so that is where it is built, tested and changed now. Your code doesn't change. The old repository is archived.", "buttons": [ { - "label": "GitHub Repo", - "href": "https://github.com/PyDevices/cameraif", + "label": "modules/cameraif", + "href": "https://github.com/PyDevices/micropython-pydevices/tree/main/modules/cameraif", "primary": true }, { "label": "Examples", - "href": "https://github.com/PyDevices/cameraif/tree/main/examples", + "href": "https://github.com/PyDevices/micropython-pydevices/tree/main/modules/cameraif/examples", "tier_color": true }, { - "label": "displayif", - "href": "https://pydevices.github.io/displayif/", + "label": "micropython-pydevices", + "href": "https://pydevices.github.io/micropython-pydevices/", "tier_color": true }, { - "label": "usbif", - "href": "https://pydevices.github.io/usbif/", + "label": "Archived repo", + "href": "https://github.com/PyDevices/cameraif", "tier_color": true } ] @@ -830,7 +816,7 @@ "theme_color": "var(--tier-5-steel)", "eyebrow": "micropython-pydevices", "headline": "micropython-pydevices β€” the versioned MicroPython runtime overlay.", - "description": "The PyDevices patch queue for MicroPython, kept like a distribution keeps one: an ordered, provenance-tracked patch series over the pinned upstream release (v1.29.0), with presets, boards and variants that build PyDevices modules into firmware with upstream's own make.", + "description": "The PyDevices patch queue for MicroPython, kept like a distribution keeps one: an ordered, provenance-tracked patch series over the pinned upstream (MicroPython v1.30.0-preview-160), with presets, boards and variants that build PyDevices modules into firmware with upstream's own make.", "hero_canvas": { "app": "radar_scope", "width": 240, diff --git a/docs/github-presence.md b/docs/github-presence.md index 9fbf505..e76e1f2 100644 --- a/docs/github-presence.md +++ b/docs/github-presence.md @@ -101,7 +101,7 @@ icons. Header brand stays on the shared org logo. | [palettes](https://github.com/PyDevices/palettes) | Color palette toolkit for PyDevices | [pydevices.github.io/palettes](https://pydevices.github.io/palettes/) | | [pdwidgets](https://github.com/PyDevices/pdwidgets) | Cross-platform widget toolkit for PyDevices | [pydevices.github.io/pdwidgets](https://pydevices.github.io/pdwidgets/) | | [lvgl-bindings](https://github.com/PyDevices/lvgl-bindings) | LVGL Cβ†’binding generator (source of truth for the native bindings consumers) | [pydevices.github.io/lvgl-bindings](https://pydevices.github.io/lvgl-bindings/) | -| [displayif](https://github.com/PyDevices/displayif) | Native display bus/framebuffer modules | [pydevices.github.io/displayif](https://pydevices.github.io/displayif/) | +| [micropython-pydevices](https://github.com/PyDevices/micropython-pydevices) | MicroPython with PyDevices' C modules (`displayif`, `audioif`, `cameraif`, `usbhost`, …) built in | [pydevices.github.io/micropython-pydevices](https://pydevices.github.io/micropython-pydevices/) (the old `displayif`, `audioif`, `cameraif` and `usbif` pages stay up as pointers) | | [audiodsp](https://github.com/PyDevices/audiodsp) | CircuitPython-compatible audio for MicroPython plus `pydevices-audiodsp` CPython/Android/Pyodide wheels | [pydevices.github.io/audiodsp](https://pydevices.github.io/audiodsp/) Β· [TestPyPI](https://test.pypi.org/project/pydevices-audiodsp/) | | [pygraphics](https://github.com/PyDevices/pygraphics) | Native + pure-Python FrameBuffer/Area (`import pygraphics`); docs on [RTD](https://pygraphics.readthedocs.io) | [pydevices.github.io/pygraphics](https://pydevices.github.io/pygraphics/) | | [lvgl-micropython](https://github.com/PyDevices/lvgl-micropython) | MicroPython user C module glue for LVGL | [pydevices.github.io/lvgl-micropython](https://pydevices.github.io/lvgl-micropython/) | diff --git a/profile/README.md b/profile/README.md index bd6ac9a..acaad3c 100644 --- a/profile/README.md +++ b/profile/README.md @@ -23,12 +23,8 @@ Welcome to **PyDevices** β€” a unified pure-Python hardware abstraction engine, Standard hardware driver engine and companion reference code. - [`pydevices`](https://github.com/PyDevices/pydevices) β€” Unified pure-Python hardware abstraction layer and core device contract for MicroPython, CircuitPython, CPython, direct WebAssembly, Pyodide, and Android. -- [`displayif`](https://github.com/PyDevices/displayif) β€” High-performance C hardware bus engines (SPI, I2C, Intel 8080, RGB/DPI, MIPI DSI) and native usermod display drivers for MicroPython and CircuitPython. - [`audiodsp`](https://github.com/PyDevices/audiodsp) β€” CircuitPython's audio system (audiocore, synthio, audiomixer, effects, audiomp3) ported to MicroPython and CPython, extending CircuitPython along the way: dynamics, routing, convolution, and offline rendering. On PyPI as pydevices-audiodsp; the instrument and effect libraries built on it ship from audiocomponents. -- [`audioif`](https://github.com/PyDevices/audioif) β€” The part of the audio stack that knows what a thread is, where the clock comes from and where the sound goes: a pinned task and the I2S peripheral on ESP32, a native thread on unix and Windows, and a CircuitPython-shaped audiobusio.I2SOut over all of it. With it in a firmware, a graph keeps an exact clock while a screen redraws and a USB stack runs, and audiodev plays through it without being asked. The portable half of the pump, and every DSP node, is audiodsp. - [`audiocomponents`](https://github.com/PyDevices/audiocomponents) β€” The instrument and effect libraries for audiodsp: audioinstruments (55 modelled classics, from the TR-808 to the DX7) and audioeffects (45 effect classes and racks), pure Python on MicroPython and CPython. Ships as pydevices-audioinstruments and pydevices-audioeffects, each a standalone distribution and a MIP package. -- [`usbif`](https://github.com/PyDevices/usbif) β€” A board a computer sees as a sound card, a MIDI instrument, a keyboard, a drive or a webcam β€” and, on the same board, a USB host that a keyboard, thumb drive, MIDI controller or camera plugs into. One of the PyDevices *if modules, with displayif, audioif and cameraif: a native C module with a thin, stable Python surface that runs unchanged on a workstation. -- [`cameraif`](https://github.com/PyDevices/cameraif) β€” Point the board at something and read the frame. The sensor is found by probing rather than named in code, so a different camera is a build-time option away, not a rewrite. Hardware JPEG, zero-copy frames and hardware scaling straight into a display's scanout buffer, with every rate in its README measured on the board it names. - [`pydevices-examples`](https://github.com/PyDevices/pydevices-examples) β€” Comprehensive example code, direct MicroPython WebAssembly demos, board configurations, and multi-interpreter showcase benchmarks. ### Tier 2: Python Framebuffers & GUI Toolkits @@ -61,10 +57,17 @@ MIP package indexing, multi-usermod builds, and serial/FTP IDE extensions. - [`mpftp`](https://github.com/PyDevices/mpftp) β€” Connect MicroPython and CircuitPython boards from VS Code, Cursor, or the CLI, over USB or Wi-Fi: dual-pane file transfer, in-editor REPL, firmware builds and flashing, mip/circup, plus RPC, MCP, and an optional browser PWA. - [`mip`](https://github.com/PyDevices/mip) β€” Single source of truth (SoT) for precompiled MicroPython .mpy bytecode packages and pure-Python library distributions across the PyDevices ecosystem. -- [`micropython-pydevices`](https://github.com/PyDevices/micropython-pydevices) β€” The PyDevices patch queue for MicroPython, kept like a distribution keeps one: an ordered, provenance-tracked patch series over the pinned upstream release (v1.29.0), with presets, boards and variants that build PyDevices modules into firmware with upstream's own make. +- [`micropython-pydevices`](https://github.com/PyDevices/micropython-pydevices) β€” The PyDevices patch queue for MicroPython, kept like a distribution keeps one: an ordered, provenance-tracked patch series over the pinned upstream (MicroPython v1.30.0-preview-160), with presets, boards and variants that build PyDevices modules into firmware with upstream's own make. - [`workbench`](https://github.com/PyDevices/workbench) β€” A ViperIDE fork with a built-in WebAssembly MicroPython simulator: edit, run, and debug PyDevices code against a simulated board entirely in the browser, no hardware required. - [`mpvst`](https://github.com/PyDevices/mpvst) β€” Programmable VST3 instruments and effects: every audiocomponents instrument and effect as a named plug-in, each instance running its Python in a sidecar process. Installers for Windows and Linux; nothing has to be built. +**Moved into other repositories:** + +- **displayif** β€” now [`modules/displayif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/displayif) in micropython-pydevices. The old repository is archived. +- **audioif** β€” now [`modules/audioif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/audioif) in micropython-pydevices. The old repository is archived. +- **cameraif** β€” now [`modules/cameraif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/cameraif) in micropython-pydevices. The old repository is archived. +- **usbif** β€” the C module is now [`modules/usbhost`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/usbhost) in micropython-pydevices; the Python USB packages are in [pydevices](https://github.com/PyDevices/pydevices/blob/main/docs/usb.md). The old repository is archived. + **Deliberately absent from this map:** - **.github (dotgithub)** β€” No landing page by design. It holds org-wide data, scripts, and community health files, and is documented as markdown only. diff --git a/scripts/generate_sites.py b/scripts/generate_sites.py index 6dd9e7a..f6b9aca 100755 --- a/scripts/generate_sites.py +++ b/scripts/generate_sites.py @@ -211,6 +211,16 @@ def build_ecosystem_markdown(db): lines.append(f'- [`{repo_name}`]({url}) β€” {data.get("description", "")}') lines.append('') + # Repos that were folded into another one and archived. Their pages stay up + # as pointers (portal_grid: false keeps them off the grid), and the map + # says where each went so a reader of the map isn't sent to an archive. + moved = db['_meta'].get('moved') + if moved: + lines += ['**Moved into other repositories:**', ''] + for repo_name, where in moved.items(): + lines.append(f'- **{repo_name}** β€” {where}') + lines.append('') + lines += ['**Deliberately absent from this map:**', ''] for repo_name, reason in db['_meta']['excluded'].items(): lines.append(f'- **{repo_name}** β€” {reason}') diff --git a/tests/test_generate_sites.py b/tests/test_generate_sites.py index cc75a34..73eee01 100644 --- a/tests/test_generate_sites.py +++ b/tests/test_generate_sites.py @@ -110,5 +110,32 @@ def test_unknown_repo_fails(self) -> None: self.assertIn("not in data/repos_db.json", result.stderr) +class MovedRepoTests(unittest.TestCase): + """A repo folded into another one stays a pointer page, off the map and grid.""" + + def setUp(self) -> None: + sys.path.insert(0, str(REPO / "scripts")) + self.addCleanup(sys.path.remove, str(REPO / "scripts")) + import generate_sites + + self.gen = generate_sites + self.db = json.loads((REPO / "data/repos_db.json").read_text(encoding="utf-8")) + + def test_moved_repos_are_named_in_the_map_not_listed_as_products(self) -> None: + moved = self.db["_meta"]["moved"] + self.assertTrue(moved) + block = self.gen.build_ecosystem_markdown(self.db) + for name in moved: + self.assertIn(f"- **{name}** \u2014 ", block) + self.assertNotIn(f"[`{name}`](https://github.com/PyDevices/{name})", block) + + def test_moved_repos_keep_their_page_but_leave_the_grid(self) -> None: + for name in self.db["_meta"]["moved"]: + entry = self.db[name] + self.assertIs(entry.get("portal_grid"), False, name) + self.assertNotEqual(self.gen.page_destination(entry), "none", name) + self.assertNotIn(f'href="/{name}/"', self.gen.build_portal_grids_html(self.db)) + + if __name__ == "__main__": unittest.main()