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()