gini-core 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gini_core-0.1.0/PKG-INFO +316 -0
- gini_core-0.1.0/README.md +305 -0
- gini_core-0.1.0/pyproject.toml +36 -0
- gini_core-0.1.0/setup.cfg +4 -0
- gini_core-0.1.0/src/gini/domain/__init__.py +9 -0
- gini_core-0.1.0/src/gini/domain/aop.py +563 -0
- gini_core-0.1.0/src/gini/domain/aop_assemble.py +216 -0
- gini_core-0.1.0/src/gini/domain/aop_patterns.py +331 -0
- gini_core-0.1.0/src/gini/domain/aop_report.py +201 -0
- gini_core-0.1.0/src/gini/domain/assembly.py +209 -0
- gini_core-0.1.0/src/gini/domain/authoring.py +353 -0
- gini_core-0.1.0/src/gini/domain/blueprints.py +5 -0
- gini_core-0.1.0/src/gini/domain/capabilities.py +177 -0
- gini_core-0.1.0/src/gini/domain/catalog.py +85 -0
- gini_core-0.1.0/src/gini/domain/certify.py +201 -0
- gini_core-0.1.0/src/gini/domain/compose.py +413 -0
- gini_core-0.1.0/src/gini/domain/composition.py +88 -0
- gini_core-0.1.0/src/gini/domain/concepts.py +383 -0
- gini_core-0.1.0/src/gini/domain/connection_rules.py +278 -0
- gini_core-0.1.0/src/gini/domain/constraints.py +153 -0
- gini_core-0.1.0/src/gini/domain/content.py +59 -0
- gini_core-0.1.0/src/gini/domain/cpu_journey.py +89 -0
- gini_core-0.1.0/src/gini/domain/devices.py +785 -0
- gini_core-0.1.0/src/gini/domain/diagnose.py +201 -0
- gini_core-0.1.0/src/gini/domain/element_guide.py +327 -0
- gini_core-0.1.0/src/gini/domain/explain.py +90 -0
- gini_core-0.1.0/src/gini/domain/fingerprint.py +201 -0
- gini_core-0.1.0/src/gini/domain/firewall.py +34 -0
- gini_core-0.1.0/src/gini/domain/flowlog.py +61 -0
- gini_core-0.1.0/src/gini/domain/flows.py +199 -0
- gini_core-0.1.0/src/gini/domain/flowtable.py +179 -0
- gini_core-0.1.0/src/gini/domain/fragment_yaml.py +230 -0
- gini_core-0.1.0/src/gini/domain/fragments.py +169 -0
- gini_core-0.1.0/src/gini/domain/games/__init__.py +2 -0
- gini_core-0.1.0/src/gini/domain/games/paging_games.py +119 -0
- gini_core-0.1.0/src/gini/domain/games/policy_game.py +86 -0
- gini_core-0.1.0/src/gini/domain/games/process_game.py +48 -0
- gini_core-0.1.0/src/gini/domain/games/thrash_game.py +75 -0
- gini_core-0.1.0/src/gini/domain/games/translate_game.py +60 -0
- gini_core-0.1.0/src/gini/domain/games/trap_game.py +86 -0
- gini_core-0.1.0/src/gini/domain/grader.py +155 -0
- gini_core-0.1.0/src/gini/domain/grouping.py +67 -0
- gini_core-0.1.0/src/gini/domain/kernel_board.py +397 -0
- gini_core-0.1.0/src/gini/domain/kernel_source.py +145 -0
- gini_core-0.1.0/src/gini/domain/legality.py +103 -0
- gini_core-0.1.0/src/gini/domain/lesson.py +241 -0
- gini_core-0.1.0/src/gini/domain/lexicon.py +150 -0
- gini_core-0.1.0/src/gini/domain/machine_state.py +478 -0
- gini_core-0.1.0/src/gini/domain/mcast.py +128 -0
- gini_core-0.1.0/src/gini/domain/memwatch.py +111 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/basic-lan.yaml +32 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/cache-in-front.yaml +23 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/decouple-with-queue.yaml +31 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/drive-load.yaml +20 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/fix-the-address.yaml +75 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/fix-the-lan.yaml +43 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/inspect-flows.yaml +16 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/k8s-autoscale.yaml +27 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/least-privilege.yaml +21 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/load-balanced-web.yaml +29 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/observe-it.yaml +24 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/put-in-vpc.yaml +30 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/reachability-boundary.yaml +56 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/sdn-reactive.yaml +35 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/send-request.yaml +19 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/serverless-api.yaml +25 -0
- gini_core-0.1.0/src/gini/domain/missions/networking/service-chain.yaml +33 -0
- gini_core-0.1.0/src/gini/domain/missions/os/lottery-fix.yaml +19 -0
- gini_core-0.1.0/src/gini/domain/missions/os/priority-fix.yaml +24 -0
- gini_core-0.1.0/src/gini/domain/missions.py +111 -0
- gini_core-0.1.0/src/gini/domain/modulechain.py +36 -0
- gini_core-0.1.0/src/gini/domain/narration.py +247 -0
- gini_core-0.1.0/src/gini/domain/objectives.py +549 -0
- gini_core-0.1.0/src/gini/domain/os_events.py +251 -0
- gini_core-0.1.0/src/gini/domain/os_zoo.py +79 -0
- gini_core-0.1.0/src/gini/domain/paging_sim.py +141 -0
- gini_core-0.1.0/src/gini/domain/pricing.py +199 -0
- gini_core-0.1.0/src/gini/domain/probes.py +252 -0
- gini_core-0.1.0/src/gini/domain/profile.py +142 -0
- gini_core-0.1.0/src/gini/domain/proof.py +513 -0
- gini_core-0.1.0/src/gini/domain/proof_events.py +226 -0
- gini_core-0.1.0/src/gini/domain/qos.py +66 -0
- gini_core-0.1.0/src/gini/domain/reach_strategy.py +180 -0
- gini_core-0.1.0/src/gini/domain/recipes.py +738 -0
- gini_core-0.1.0/src/gini/domain/riders.py +309 -0
- gini_core-0.1.0/src/gini/domain/router_modules.py +224 -0
- gini_core-0.1.0/src/gini/domain/router_scripts.py +63 -0
- gini_core-0.1.0/src/gini/domain/routetable.py +70 -0
- gini_core-0.1.0/src/gini/domain/routing_model.py +1013 -0
- gini_core-0.1.0/src/gini/domain/scoring.py +76 -0
- gini_core-0.1.0/src/gini/domain/staging.py +122 -0
- gini_core-0.1.0/src/gini/domain/syscall_builder.py +144 -0
- gini_core-0.1.0/src/gini/domain/ticket.py +134 -0
- gini_core-0.1.0/src/gini/domain/topic_cloud.py +62 -0
- gini_core-0.1.0/src/gini/domain/topology.py +247 -0
- gini_core-0.1.0/src/gini/domain/vocabulary.py +51 -0
- gini_core-0.1.0/src/gini/domain/xv6.py +973 -0
- gini_core-0.1.0/src/gini/domain/xv6_fs.py +317 -0
- gini_core-0.1.0/src/gini/domain/xv6_runner.py +209 -0
- gini_core-0.1.0/src/gini/domain/xv6_vm.py +433 -0
- gini_core-0.1.0/src/gini/version.py +29 -0
- gini_core-0.1.0/src/gini_core.egg-info/PKG-INFO +316 -0
- gini_core-0.1.0/src/gini_core.egg-info/SOURCES.txt +106 -0
- gini_core-0.1.0/src/gini_core.egg-info/dependency_links.txt +1 -0
- gini_core-0.1.0/src/gini_core.egg-info/requires.txt +1 -0
- gini_core-0.1.0/src/gini_core.egg-info/scm_file_list.json +103 -0
- gini_core-0.1.0/src/gini_core.egg-info/scm_version.json +8 -0
- gini_core-0.1.0/src/gini_core.egg-info/top_level.txt +1 -0
gini_core-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gini-core
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: GINI core domain model — topology, devices, and the proof-of-activity format
|
|
5
|
+
Author: GINI Toolkit
|
|
6
|
+
License: GPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://github.com/citelab/gini
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: PyYAML>=6.0
|
|
11
|
+
|
|
12
|
+
# GINI — gBuilder 6.0
|
|
13
|
+
|
|
14
|
+
**A visual lab for computer networks, cloud computing, *and* operating systems — draw a system, press Run, and it comes to life as real containers (and a real xv6 kernel) you can inspect, drive, and observe.**
|
|
15
|
+
|
|
16
|
+
💬 **Join the community:** [GINI Discord](https://discord.gg/s5zTAgdKQd) — questions, help, and discussion.
|
|
17
|
+
|
|
18
|
+
GINI lets students and instructors build a topology on a canvas, then launches it as
|
|
19
|
+
honest, running infrastructure on Docker: a real C router that actually forwards packets,
|
|
20
|
+
a real OpenFlow controller programming a real switch, and real cloud services (databases,
|
|
21
|
+
object stores, message queues, dashboards) discoverable by name — plus a real **xv6** operating-system
|
|
22
|
+
kernel you can watch and extend in a visual **Machine Lab**. A built-in AI tutor —
|
|
23
|
+
**GINI** — explains what's on the canvas, animates how packets flow, and can scaffold
|
|
24
|
+
whole working systems from a one-line description.
|
|
25
|
+
|
|
26
|
+
It's designed to anchor three courses:
|
|
27
|
+
|
|
28
|
+
- **Computer Networks** — switches, routers, subnets, firewalls, and real OpenFlow SDN.
|
|
29
|
+
- **Cloud Computing** — VPC-style networking, managed services, autoscaling, observability.
|
|
30
|
+
- **Operating Systems** — a real **xv6** (RISC-V) kernel in a visual **Machine Lab**: watch the
|
|
31
|
+
scheduler, system calls, traps, virtual memory, and the file system live, then extend the kernel
|
|
32
|
+
yourself with **shadows** — a novel way to drop your own code into a *running* xv6 machine to
|
|
33
|
+
experiment (fix the scheduler, add a syscall) without forking the kernel.
|
|
34
|
+
|
|
35
|
+
> gBuilder 6.0 is the modern rewrite of the classic GINI Toolkit. The original
|
|
36
|
+
> Python 2.7 / PyQt4 / SCons app lives under `legacy/` for reference.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Highlights
|
|
41
|
+
|
|
42
|
+
- **Visual builder** — a fast PySide6/Qt 6 canvas with a searchable palette of ~40
|
|
43
|
+
networking and cloud elements, theming, save/load, and an inspector.
|
|
44
|
+
- **It actually runs** — Run compiles the canvas to a Docker Compose project and brings it
|
|
45
|
+
up. Machines, routers, switches, controllers, and cloud services all start as containers.
|
|
46
|
+
- **The real C gRouter** — the genuine GINI router (built with `zig cc`), forwarding
|
|
47
|
+
packets over a portable user-space fabric. No kernel modules, no privileges.
|
|
48
|
+
- **Real SDN** — drop an *OpenFlow Controller* + *OpenVSwitch*; GINI runs **POX** (Python 3)
|
|
49
|
+
programming the gRouter in OpenFlow-1.0 switch mode. Watch flows install on the first
|
|
50
|
+
packet, then forward at wire speed.
|
|
51
|
+
- **Cloud services as containers** — MinIO, PostgreSQL, Redis, MongoDB, RabbitMQ, Kafka
|
|
52
|
+
(Redpanda), NATS, nginx, Traefik, Prometheus, Grafana, Jaeger, Fortio, and more — each a
|
|
53
|
+
real, off-the-shelf image reachable by service name.
|
|
54
|
+
- **Live observability** — drop *Metrics* + *Dashboards* and GINI auto-wires
|
|
55
|
+
cAdvisor → Prometheus → Grafana with a prebuilt dashboard. Generate load and watch the
|
|
56
|
+
graphs move.
|
|
57
|
+
- **A real OS to hack** — a genuine **xv6** kernel in a visual **Machine Lab** (scheduler, system
|
|
58
|
+
calls, traps, virtual memory, file system — all live over the serial, no gdb), plus **shadows**:
|
|
59
|
+
drop your own code into a running xv6 machine for experiments and graded assignments, no kernel
|
|
60
|
+
fork required.
|
|
61
|
+
- **GINI AI** — an in-app tutor with **Explain**, **Tutor**, and **Wizard** modes. Ask it
|
|
62
|
+
to explain a device, trace a path, or describe a system you want and it lays out a
|
|
63
|
+
working blueprint. Runs against a local LLM (Ollama) or fully offline.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Requirements
|
|
68
|
+
|
|
69
|
+
- **Python 3.10+** (3.12 recommended). The Qt 6 GUI — **PySide6** plus **QtWebEngine** (for the
|
|
70
|
+
embedded Desktop / OS-Zoo screens) — installs **automatically** as a dependency; you never install
|
|
71
|
+
Qt separately, whichever install route you pick.
|
|
72
|
+
- A **container runtime** — Docker, or **Colima**/**Podman** (`gini-setup` detects it and can help
|
|
73
|
+
install it) — needed to *Run* topologies. You can explore fully in **Demo mode** without one.
|
|
74
|
+
- Works on **macOS, Linux, and Windows**. *Optional:* a local **[Ollama](https://ollama.com)** model
|
|
75
|
+
for richer GINI AI answers.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Install
|
|
80
|
+
|
|
81
|
+
There are **two ways to install, both fully supported** — pick one (don't mix the two; see
|
|
82
|
+
Troubleshooting). Either way the Qt GUI (PySide6 + QtWebEngine) is pulled in automatically.
|
|
83
|
+
|
|
84
|
+
### 1. From source — the latest code
|
|
85
|
+
|
|
86
|
+
Recommended if you want the newest features, plan to build the xv6 kernel image yourself, or want to
|
|
87
|
+
contribute. You track `main`, so you always have the freshest bits.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# in your clone of the repo:
|
|
91
|
+
cd frontend-ng
|
|
92
|
+
pip install -e . # editable install; PySide6 + QtWebEngine come with it
|
|
93
|
+
gini-setup # brings in the container runtime + images (one time)
|
|
94
|
+
gbuilder # launch
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2. Pre-compiled package — the simplest, most stable
|
|
98
|
+
|
|
99
|
+
The hands-off route. It may be a version or two behind `main`, but it's the more stable, "just
|
|
100
|
+
install and go" option — good for students and classroom setups.
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pipx install gini-toolkit # the app, isolated. `pip install gini-toolkit` also works.
|
|
104
|
+
gini-setup # brings in the container runtime + images (one time)
|
|
105
|
+
gbuilder # launch
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Either way, `gbuilder` opens immediately — build, save, and explore topologies, with the AI tutor and
|
|
109
|
+
everything in **Demo mode** working right away. Live **Run** (real containers) lights up once
|
|
110
|
+
`gini-setup` finishes. After upgrading (`git pull` for source, or `pipx upgrade gini-toolkit` for the
|
|
111
|
+
package), re-run `gini-setup --update` to refresh images.
|
|
112
|
+
|
|
113
|
+
> No `pipx`? Install it once (`brew install pipx` on macOS, or `pip install pipx`), or use
|
|
114
|
+
> `pip install gini-toolkit` inside a virtual environment.
|
|
115
|
+
|
|
116
|
+
<details>
|
|
117
|
+
<summary><b>macOS details</b></summary>
|
|
118
|
+
|
|
119
|
+
`gini-setup` uses **Colima** — a free, lightweight Docker runtime, no Docker Desktop license needed.
|
|
120
|
+
On a clean Mac with [Homebrew](https://brew.sh) it offers to run:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
brew install colima docker
|
|
124
|
+
colima start --cpu 2 --memory 4 --disk 30
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If Docker Desktop (or Colima) is already running, `gini-setup` detects it and just pulls the images.
|
|
128
|
+
</details>
|
|
129
|
+
|
|
130
|
+
<details>
|
|
131
|
+
<summary><b>Linux details</b></summary>
|
|
132
|
+
|
|
133
|
+
Install **Docker Engine** first — it needs `sudo`, so `gini-setup` guides rather than auto-installs:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# https://docs.docker.com/engine/install/ for your distro, then:
|
|
137
|
+
sudo usermod -aG docker $USER # log out / back in afterwards
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Podman works too. Then run `gini-setup` to pull the images.
|
|
141
|
+
</details>
|
|
142
|
+
|
|
143
|
+
<details>
|
|
144
|
+
<summary><b>Windows details</b></summary>
|
|
145
|
+
|
|
146
|
+
Colima isn't available on Windows — use **Docker Desktop** or **Podman Desktop**:
|
|
147
|
+
|
|
148
|
+
```powershell
|
|
149
|
+
winget install -e --id Docker.DockerDesktop
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Start it, then run `gini-setup`. (Live-Run networking on Windows is still being validated;
|
|
153
|
+
Demo mode works fully.)
|
|
154
|
+
</details>
|
|
155
|
+
|
|
156
|
+
<details>
|
|
157
|
+
<summary><b>Dev tools & building images locally</b></summary>
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# extra dev tooling (tests, linters) on top of the source install:
|
|
161
|
+
cd frontend-ng && pip install -e ".[dev]"
|
|
162
|
+
|
|
163
|
+
# build the container images yourself instead of pulling them
|
|
164
|
+
# (needed to hack the xv6 kernel via shadows):
|
|
165
|
+
docker build -t gini-xv6:latest backend/xv6 # + oszoo / grouter / pox
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Point the app at a different image registry with `GINI_REGISTRY=ghcr.io/<owner>`.
|
|
169
|
+
</details>
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary><b>Troubleshooting</b></summary>
|
|
173
|
+
|
|
174
|
+
- **"runtime not set up yet"** — run `gini-setup`. Demo mode still works without it.
|
|
175
|
+
- **`gini-setup` pull says `denied` / `not found`** — images unreachable: check your network, or that
|
|
176
|
+
the registry (`ghcr.io/gini-toolkit`) is correct and its packages are public.
|
|
177
|
+
- **Two `gbuilder`s on your PATH** — you installed with both pip *and* pipx; keep one
|
|
178
|
+
(`pip uninstall gini-toolkit` or `pipx uninstall gini-toolkit`).
|
|
179
|
+
</details>
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
### Your first topology
|
|
184
|
+
|
|
185
|
+
- **Place** a device by dragging it from the palette onto the canvas.
|
|
186
|
+
- **Connect** two devices: click the **Connect** tool in the toolbar (the link icon), then
|
|
187
|
+
click the first device and then the second — a link appears. Click the tool again (or
|
|
188
|
+
press Esc) to leave Connect mode. You can also ask GINI: "connect R1 and S1".
|
|
189
|
+
- **Run** the topology with the ▶ button.
|
|
190
|
+
|
|
191
|
+
Once it's running:
|
|
192
|
+
|
|
193
|
+
- **Double-click** a machine to open a shell; a service with a web UI (Grafana, MinIO …)
|
|
194
|
+
to open its dashboard; a router to open the **Router Lab**.
|
|
195
|
+
- **Right-click** any node for **Open console**, **Log in**, **View logs**, or **Delete**.
|
|
196
|
+
- The console log prints each running service's web URL.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## GINI AI
|
|
201
|
+
|
|
202
|
+
The right-hand **Ask GINI** panel is a teaching assistant that always sees the live canvas.
|
|
203
|
+
Modes are toggle buttons; the toolbar shows the current **mode** and whether GINI is
|
|
204
|
+
**thinking**.
|
|
205
|
+
|
|
206
|
+
- **Explain** — click any device and GINI explains it on the canvas (spotlight, callouts,
|
|
207
|
+
animated packet flows). It also explains palette elements ("when do I use a switch vs a
|
|
208
|
+
hub?").
|
|
209
|
+
- **Tutor** — overlays highlights and animations as it teaches.
|
|
210
|
+
- **Wizard** — describe what you want ("something I can watch under load", "a web app with
|
|
211
|
+
a database") and GINI matches a curated, guaranteed-to-work **recipe** and lays it out
|
|
212
|
+
with one click. The model only *selects and explains*; the building is deterministic, so
|
|
213
|
+
even a small local model can't produce a broken topology.
|
|
214
|
+
|
|
215
|
+
Connect a model by pointing GINI at Ollama:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
export GINI_LLM_URL=http://localhost:11434
|
|
219
|
+
export GINI_LLM_MODEL=llama3.1 # or gemma, qwen, …
|
|
220
|
+
python -m gini
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Without a model, GINI still builds, inspects, traces paths, and ranks recipes
|
|
224
|
+
deterministically.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Software-Defined Networking
|
|
229
|
+
|
|
230
|
+
The SDN stack is the original GINI design, made real:
|
|
231
|
+
|
|
232
|
+
- **OpenVSwitch** element → the gRouter launched in `--openflow` mode (a real OpenFlow 1.0
|
|
233
|
+
switch).
|
|
234
|
+
- **OpenFlow Controller** element → a **POX** (`gar`, Python 3) container running an app
|
|
235
|
+
you choose from the inspector (`l2_learning`, `hub`, or the classic `of_tutorial`).
|
|
236
|
+
|
|
237
|
+
Draw `Controller → OVS → hosts`, Run, and ping between hosts: the first packet misses the
|
|
238
|
+
flow table → goes up to POX → a flow is installed → the rest forward in the datapath. You
|
|
239
|
+
can watch flows appear with `openflow entry all` in the OVS console, and the controller's
|
|
240
|
+
decisions in its logs.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Cloud service catalog
|
|
245
|
+
|
|
246
|
+
Each of these palette elements runs as a real container, reachable by name on the lab's
|
|
247
|
+
network (cloud-style service discovery):
|
|
248
|
+
|
|
249
|
+
| Element | Backed by | Console |
|
|
250
|
+
|---|---|---|
|
|
251
|
+
| Object Storage | MinIO | ✓ |
|
|
252
|
+
| Managed Database | PostgreSQL | — |
|
|
253
|
+
| NoSQL Database | MongoDB | — |
|
|
254
|
+
| Cache | Redis | — |
|
|
255
|
+
| Message Queue | RabbitMQ | ✓ |
|
|
256
|
+
| Event Stream | Redpanda (Kafka API) | — |
|
|
257
|
+
| Pub/Sub | NATS | ✓ |
|
|
258
|
+
| Reverse Proxy | Traefik | ✓ |
|
|
259
|
+
| Load Balancer | nginx | — |
|
|
260
|
+
| Web App | nginxdemos/hello | ✓ |
|
|
261
|
+
| Container Registry | registry:2 | — |
|
|
262
|
+
| Metrics | Prometheus | ✓ |
|
|
263
|
+
| Dashboards | Grafana | ✓ |
|
|
264
|
+
| Tracing | Jaeger | ✓ |
|
|
265
|
+
| Load Generator | Fortio | ✓ |
|
|
266
|
+
|
|
267
|
+
Compute elements (**Instance**, **Container**) run as plain containers on the same network,
|
|
268
|
+
so a program inside them reaches services by name (`psql -h database1`,
|
|
269
|
+
`http://objectstore1:9000`).
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Repository layout
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
frontend-ng/ gBuilder 6.0 — PySide6 app (domain · ui · agent · runtime · services)
|
|
277
|
+
backend/
|
|
278
|
+
src/grouter/ the real C gRouter (~20k lines) incl. OpenFlow/SDN mode
|
|
279
|
+
grouter-build/ C build + Dockerfile (gini-grouter) + e2e forwarding tests
|
|
280
|
+
sdn/ POX (gar) controller + Dockerfile (gini-pox)
|
|
281
|
+
legacy/ the original Python 2.7 / PyQt4 GINI, kept for reference
|
|
282
|
+
ARCHITECTURE.md what's active vs legacy, and how it fits together
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
See **[ARCHITECTURE.md](ARCHITECTURE.md)** for the full map.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Testing
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
cd frontend-ng
|
|
293
|
+
pytest # ~95 tests
|
|
294
|
+
# headless / CI:
|
|
295
|
+
QT_QPA_PLATFORM=offscreen pytest
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The gRouter has end-to-end forwarding proofs under `backend/grouter-build/tests/`
|
|
299
|
+
(`forward_test.py`, `multihop_test.py`, …), runnable against a built `grouter` binary.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Status
|
|
304
|
+
|
|
305
|
+
gBuilder 6.0 is under active development. Working today: the visual builder, real packet
|
|
306
|
+
forwarding through the C gRouter (single- and multi-router), OpenFlow SDN (POX + gRouter),
|
|
307
|
+
the cloud service catalog, observability auto-wiring, and the GINI AI tutor with Explain /
|
|
308
|
+
Tutor / Wizard modes. On the roadmap: configuring services from the inspector, VPC-level
|
|
309
|
+
isolation, a managed Kubernetes element, and more Wizard recipes.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## License & contact
|
|
314
|
+
|
|
315
|
+
GINI is free software — see `COPYING` for copyright information. Questions, bugs, or ideas:
|
|
316
|
+
open an issue on this repository, or email `maheswar@cs.mcgill.ca`.
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# GINI — gBuilder 6.0
|
|
2
|
+
|
|
3
|
+
**A visual lab for computer networks, cloud computing, *and* operating systems — draw a system, press Run, and it comes to life as real containers (and a real xv6 kernel) you can inspect, drive, and observe.**
|
|
4
|
+
|
|
5
|
+
💬 **Join the community:** [GINI Discord](https://discord.gg/s5zTAgdKQd) — questions, help, and discussion.
|
|
6
|
+
|
|
7
|
+
GINI lets students and instructors build a topology on a canvas, then launches it as
|
|
8
|
+
honest, running infrastructure on Docker: a real C router that actually forwards packets,
|
|
9
|
+
a real OpenFlow controller programming a real switch, and real cloud services (databases,
|
|
10
|
+
object stores, message queues, dashboards) discoverable by name — plus a real **xv6** operating-system
|
|
11
|
+
kernel you can watch and extend in a visual **Machine Lab**. A built-in AI tutor —
|
|
12
|
+
**GINI** — explains what's on the canvas, animates how packets flow, and can scaffold
|
|
13
|
+
whole working systems from a one-line description.
|
|
14
|
+
|
|
15
|
+
It's designed to anchor three courses:
|
|
16
|
+
|
|
17
|
+
- **Computer Networks** — switches, routers, subnets, firewalls, and real OpenFlow SDN.
|
|
18
|
+
- **Cloud Computing** — VPC-style networking, managed services, autoscaling, observability.
|
|
19
|
+
- **Operating Systems** — a real **xv6** (RISC-V) kernel in a visual **Machine Lab**: watch the
|
|
20
|
+
scheduler, system calls, traps, virtual memory, and the file system live, then extend the kernel
|
|
21
|
+
yourself with **shadows** — a novel way to drop your own code into a *running* xv6 machine to
|
|
22
|
+
experiment (fix the scheduler, add a syscall) without forking the kernel.
|
|
23
|
+
|
|
24
|
+
> gBuilder 6.0 is the modern rewrite of the classic GINI Toolkit. The original
|
|
25
|
+
> Python 2.7 / PyQt4 / SCons app lives under `legacy/` for reference.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Highlights
|
|
30
|
+
|
|
31
|
+
- **Visual builder** — a fast PySide6/Qt 6 canvas with a searchable palette of ~40
|
|
32
|
+
networking and cloud elements, theming, save/load, and an inspector.
|
|
33
|
+
- **It actually runs** — Run compiles the canvas to a Docker Compose project and brings it
|
|
34
|
+
up. Machines, routers, switches, controllers, and cloud services all start as containers.
|
|
35
|
+
- **The real C gRouter** — the genuine GINI router (built with `zig cc`), forwarding
|
|
36
|
+
packets over a portable user-space fabric. No kernel modules, no privileges.
|
|
37
|
+
- **Real SDN** — drop an *OpenFlow Controller* + *OpenVSwitch*; GINI runs **POX** (Python 3)
|
|
38
|
+
programming the gRouter in OpenFlow-1.0 switch mode. Watch flows install on the first
|
|
39
|
+
packet, then forward at wire speed.
|
|
40
|
+
- **Cloud services as containers** — MinIO, PostgreSQL, Redis, MongoDB, RabbitMQ, Kafka
|
|
41
|
+
(Redpanda), NATS, nginx, Traefik, Prometheus, Grafana, Jaeger, Fortio, and more — each a
|
|
42
|
+
real, off-the-shelf image reachable by service name.
|
|
43
|
+
- **Live observability** — drop *Metrics* + *Dashboards* and GINI auto-wires
|
|
44
|
+
cAdvisor → Prometheus → Grafana with a prebuilt dashboard. Generate load and watch the
|
|
45
|
+
graphs move.
|
|
46
|
+
- **A real OS to hack** — a genuine **xv6** kernel in a visual **Machine Lab** (scheduler, system
|
|
47
|
+
calls, traps, virtual memory, file system — all live over the serial, no gdb), plus **shadows**:
|
|
48
|
+
drop your own code into a running xv6 machine for experiments and graded assignments, no kernel
|
|
49
|
+
fork required.
|
|
50
|
+
- **GINI AI** — an in-app tutor with **Explain**, **Tutor**, and **Wizard** modes. Ask it
|
|
51
|
+
to explain a device, trace a path, or describe a system you want and it lays out a
|
|
52
|
+
working blueprint. Runs against a local LLM (Ollama) or fully offline.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Requirements
|
|
57
|
+
|
|
58
|
+
- **Python 3.10+** (3.12 recommended). The Qt 6 GUI — **PySide6** plus **QtWebEngine** (for the
|
|
59
|
+
embedded Desktop / OS-Zoo screens) — installs **automatically** as a dependency; you never install
|
|
60
|
+
Qt separately, whichever install route you pick.
|
|
61
|
+
- A **container runtime** — Docker, or **Colima**/**Podman** (`gini-setup` detects it and can help
|
|
62
|
+
install it) — needed to *Run* topologies. You can explore fully in **Demo mode** without one.
|
|
63
|
+
- Works on **macOS, Linux, and Windows**. *Optional:* a local **[Ollama](https://ollama.com)** model
|
|
64
|
+
for richer GINI AI answers.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
There are **two ways to install, both fully supported** — pick one (don't mix the two; see
|
|
71
|
+
Troubleshooting). Either way the Qt GUI (PySide6 + QtWebEngine) is pulled in automatically.
|
|
72
|
+
|
|
73
|
+
### 1. From source — the latest code
|
|
74
|
+
|
|
75
|
+
Recommended if you want the newest features, plan to build the xv6 kernel image yourself, or want to
|
|
76
|
+
contribute. You track `main`, so you always have the freshest bits.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# in your clone of the repo:
|
|
80
|
+
cd frontend-ng
|
|
81
|
+
pip install -e . # editable install; PySide6 + QtWebEngine come with it
|
|
82
|
+
gini-setup # brings in the container runtime + images (one time)
|
|
83
|
+
gbuilder # launch
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Pre-compiled package — the simplest, most stable
|
|
87
|
+
|
|
88
|
+
The hands-off route. It may be a version or two behind `main`, but it's the more stable, "just
|
|
89
|
+
install and go" option — good for students and classroom setups.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pipx install gini-toolkit # the app, isolated. `pip install gini-toolkit` also works.
|
|
93
|
+
gini-setup # brings in the container runtime + images (one time)
|
|
94
|
+
gbuilder # launch
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Either way, `gbuilder` opens immediately — build, save, and explore topologies, with the AI tutor and
|
|
98
|
+
everything in **Demo mode** working right away. Live **Run** (real containers) lights up once
|
|
99
|
+
`gini-setup` finishes. After upgrading (`git pull` for source, or `pipx upgrade gini-toolkit` for the
|
|
100
|
+
package), re-run `gini-setup --update` to refresh images.
|
|
101
|
+
|
|
102
|
+
> No `pipx`? Install it once (`brew install pipx` on macOS, or `pip install pipx`), or use
|
|
103
|
+
> `pip install gini-toolkit` inside a virtual environment.
|
|
104
|
+
|
|
105
|
+
<details>
|
|
106
|
+
<summary><b>macOS details</b></summary>
|
|
107
|
+
|
|
108
|
+
`gini-setup` uses **Colima** — a free, lightweight Docker runtime, no Docker Desktop license needed.
|
|
109
|
+
On a clean Mac with [Homebrew](https://brew.sh) it offers to run:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
brew install colima docker
|
|
113
|
+
colima start --cpu 2 --memory 4 --disk 30
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
If Docker Desktop (or Colima) is already running, `gini-setup` detects it and just pulls the images.
|
|
117
|
+
</details>
|
|
118
|
+
|
|
119
|
+
<details>
|
|
120
|
+
<summary><b>Linux details</b></summary>
|
|
121
|
+
|
|
122
|
+
Install **Docker Engine** first — it needs `sudo`, so `gini-setup` guides rather than auto-installs:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# https://docs.docker.com/engine/install/ for your distro, then:
|
|
126
|
+
sudo usermod -aG docker $USER # log out / back in afterwards
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Podman works too. Then run `gini-setup` to pull the images.
|
|
130
|
+
</details>
|
|
131
|
+
|
|
132
|
+
<details>
|
|
133
|
+
<summary><b>Windows details</b></summary>
|
|
134
|
+
|
|
135
|
+
Colima isn't available on Windows — use **Docker Desktop** or **Podman Desktop**:
|
|
136
|
+
|
|
137
|
+
```powershell
|
|
138
|
+
winget install -e --id Docker.DockerDesktop
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Start it, then run `gini-setup`. (Live-Run networking on Windows is still being validated;
|
|
142
|
+
Demo mode works fully.)
|
|
143
|
+
</details>
|
|
144
|
+
|
|
145
|
+
<details>
|
|
146
|
+
<summary><b>Dev tools & building images locally</b></summary>
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# extra dev tooling (tests, linters) on top of the source install:
|
|
150
|
+
cd frontend-ng && pip install -e ".[dev]"
|
|
151
|
+
|
|
152
|
+
# build the container images yourself instead of pulling them
|
|
153
|
+
# (needed to hack the xv6 kernel via shadows):
|
|
154
|
+
docker build -t gini-xv6:latest backend/xv6 # + oszoo / grouter / pox
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Point the app at a different image registry with `GINI_REGISTRY=ghcr.io/<owner>`.
|
|
158
|
+
</details>
|
|
159
|
+
|
|
160
|
+
<details>
|
|
161
|
+
<summary><b>Troubleshooting</b></summary>
|
|
162
|
+
|
|
163
|
+
- **"runtime not set up yet"** — run `gini-setup`. Demo mode still works without it.
|
|
164
|
+
- **`gini-setup` pull says `denied` / `not found`** — images unreachable: check your network, or that
|
|
165
|
+
the registry (`ghcr.io/gini-toolkit`) is correct and its packages are public.
|
|
166
|
+
- **Two `gbuilder`s on your PATH** — you installed with both pip *and* pipx; keep one
|
|
167
|
+
(`pip uninstall gini-toolkit` or `pipx uninstall gini-toolkit`).
|
|
168
|
+
</details>
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### Your first topology
|
|
173
|
+
|
|
174
|
+
- **Place** a device by dragging it from the palette onto the canvas.
|
|
175
|
+
- **Connect** two devices: click the **Connect** tool in the toolbar (the link icon), then
|
|
176
|
+
click the first device and then the second — a link appears. Click the tool again (or
|
|
177
|
+
press Esc) to leave Connect mode. You can also ask GINI: "connect R1 and S1".
|
|
178
|
+
- **Run** the topology with the ▶ button.
|
|
179
|
+
|
|
180
|
+
Once it's running:
|
|
181
|
+
|
|
182
|
+
- **Double-click** a machine to open a shell; a service with a web UI (Grafana, MinIO …)
|
|
183
|
+
to open its dashboard; a router to open the **Router Lab**.
|
|
184
|
+
- **Right-click** any node for **Open console**, **Log in**, **View logs**, or **Delete**.
|
|
185
|
+
- The console log prints each running service's web URL.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## GINI AI
|
|
190
|
+
|
|
191
|
+
The right-hand **Ask GINI** panel is a teaching assistant that always sees the live canvas.
|
|
192
|
+
Modes are toggle buttons; the toolbar shows the current **mode** and whether GINI is
|
|
193
|
+
**thinking**.
|
|
194
|
+
|
|
195
|
+
- **Explain** — click any device and GINI explains it on the canvas (spotlight, callouts,
|
|
196
|
+
animated packet flows). It also explains palette elements ("when do I use a switch vs a
|
|
197
|
+
hub?").
|
|
198
|
+
- **Tutor** — overlays highlights and animations as it teaches.
|
|
199
|
+
- **Wizard** — describe what you want ("something I can watch under load", "a web app with
|
|
200
|
+
a database") and GINI matches a curated, guaranteed-to-work **recipe** and lays it out
|
|
201
|
+
with one click. The model only *selects and explains*; the building is deterministic, so
|
|
202
|
+
even a small local model can't produce a broken topology.
|
|
203
|
+
|
|
204
|
+
Connect a model by pointing GINI at Ollama:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
export GINI_LLM_URL=http://localhost:11434
|
|
208
|
+
export GINI_LLM_MODEL=llama3.1 # or gemma, qwen, …
|
|
209
|
+
python -m gini
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Without a model, GINI still builds, inspects, traces paths, and ranks recipes
|
|
213
|
+
deterministically.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Software-Defined Networking
|
|
218
|
+
|
|
219
|
+
The SDN stack is the original GINI design, made real:
|
|
220
|
+
|
|
221
|
+
- **OpenVSwitch** element → the gRouter launched in `--openflow` mode (a real OpenFlow 1.0
|
|
222
|
+
switch).
|
|
223
|
+
- **OpenFlow Controller** element → a **POX** (`gar`, Python 3) container running an app
|
|
224
|
+
you choose from the inspector (`l2_learning`, `hub`, or the classic `of_tutorial`).
|
|
225
|
+
|
|
226
|
+
Draw `Controller → OVS → hosts`, Run, and ping between hosts: the first packet misses the
|
|
227
|
+
flow table → goes up to POX → a flow is installed → the rest forward in the datapath. You
|
|
228
|
+
can watch flows appear with `openflow entry all` in the OVS console, and the controller's
|
|
229
|
+
decisions in its logs.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Cloud service catalog
|
|
234
|
+
|
|
235
|
+
Each of these palette elements runs as a real container, reachable by name on the lab's
|
|
236
|
+
network (cloud-style service discovery):
|
|
237
|
+
|
|
238
|
+
| Element | Backed by | Console |
|
|
239
|
+
|---|---|---|
|
|
240
|
+
| Object Storage | MinIO | ✓ |
|
|
241
|
+
| Managed Database | PostgreSQL | — |
|
|
242
|
+
| NoSQL Database | MongoDB | — |
|
|
243
|
+
| Cache | Redis | — |
|
|
244
|
+
| Message Queue | RabbitMQ | ✓ |
|
|
245
|
+
| Event Stream | Redpanda (Kafka API) | — |
|
|
246
|
+
| Pub/Sub | NATS | ✓ |
|
|
247
|
+
| Reverse Proxy | Traefik | ✓ |
|
|
248
|
+
| Load Balancer | nginx | — |
|
|
249
|
+
| Web App | nginxdemos/hello | ✓ |
|
|
250
|
+
| Container Registry | registry:2 | — |
|
|
251
|
+
| Metrics | Prometheus | ✓ |
|
|
252
|
+
| Dashboards | Grafana | ✓ |
|
|
253
|
+
| Tracing | Jaeger | ✓ |
|
|
254
|
+
| Load Generator | Fortio | ✓ |
|
|
255
|
+
|
|
256
|
+
Compute elements (**Instance**, **Container**) run as plain containers on the same network,
|
|
257
|
+
so a program inside them reaches services by name (`psql -h database1`,
|
|
258
|
+
`http://objectstore1:9000`).
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Repository layout
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
frontend-ng/ gBuilder 6.0 — PySide6 app (domain · ui · agent · runtime · services)
|
|
266
|
+
backend/
|
|
267
|
+
src/grouter/ the real C gRouter (~20k lines) incl. OpenFlow/SDN mode
|
|
268
|
+
grouter-build/ C build + Dockerfile (gini-grouter) + e2e forwarding tests
|
|
269
|
+
sdn/ POX (gar) controller + Dockerfile (gini-pox)
|
|
270
|
+
legacy/ the original Python 2.7 / PyQt4 GINI, kept for reference
|
|
271
|
+
ARCHITECTURE.md what's active vs legacy, and how it fits together
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
See **[ARCHITECTURE.md](ARCHITECTURE.md)** for the full map.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Testing
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
cd frontend-ng
|
|
282
|
+
pytest # ~95 tests
|
|
283
|
+
# headless / CI:
|
|
284
|
+
QT_QPA_PLATFORM=offscreen pytest
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
The gRouter has end-to-end forwarding proofs under `backend/grouter-build/tests/`
|
|
288
|
+
(`forward_test.py`, `multihop_test.py`, …), runnable against a built `grouter` binary.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Status
|
|
293
|
+
|
|
294
|
+
gBuilder 6.0 is under active development. Working today: the visual builder, real packet
|
|
295
|
+
forwarding through the C gRouter (single- and multi-router), OpenFlow SDN (POX + gRouter),
|
|
296
|
+
the cloud service catalog, observability auto-wiring, and the GINI AI tutor with Explain /
|
|
297
|
+
Tutor / Wizard modes. On the roadmap: configuring services from the inspector, VPC-level
|
|
298
|
+
isolation, a managed Kubernetes element, and more Wizard recipes.
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## License & contact
|
|
303
|
+
|
|
304
|
+
GINI is free software — see `COPYING` for copyright information. Questions, bugs, or ideas:
|
|
305
|
+
open an issue on this repository, or email `maheswar@cs.mcgill.ca`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "setuptools-scm>=8"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "gini-core"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "GINI core domain model — topology, devices, and the proof-of-activity format"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "GPL-3.0-or-later" }
|
|
12
|
+
authors = [{ name = "GINI Toolkit" }]
|
|
13
|
+
# Pure Python and deliberately tiny: this is the code the desktop app and the Teaching Center must
|
|
14
|
+
# agree on — the proof chain, the ticket codes, the narration — so it has to install anywhere,
|
|
15
|
+
# including a headless server VM with no Qt and no compiler.
|
|
16
|
+
#
|
|
17
|
+
# PyYAML is here because `gini.domain.fragment_yaml` and `gini.domain.lesson` genuinely need it.
|
|
18
|
+
# Declaring zero dependencies looked cleaner and was a lie: `pip install gini-core` would have
|
|
19
|
+
# given you a package whose own modules raise ImportError. It is a universal wheel and about a
|
|
20
|
+
# thousandth of what Qt would have cost.
|
|
21
|
+
dependencies = ["PyYAML>=6.0"]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://github.com/citelab/gini"
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.packages.find]
|
|
27
|
+
where = ["src"]
|
|
28
|
+
include = ["gini.domain*"]
|
|
29
|
+
|
|
30
|
+
[tool.setuptools.package-data]
|
|
31
|
+
"gini.domain" = ["missions/**/*.yaml"]
|
|
32
|
+
|
|
33
|
+
[tool.setuptools_scm]
|
|
34
|
+
root = ".."
|
|
35
|
+
version_file = "src/gini/_version.py"
|
|
36
|
+
local_scheme = "no-local-version"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Pure-Python domain model — no Qt dependency."""
|
|
2
|
+
from . import devices, topology
|
|
3
|
+
from .devices import Category, DeviceType, REGISTRY, all_devices, by_category, get
|
|
4
|
+
from .topology import DeviceInstance, Link, Topology
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"devices", "topology", "Category", "DeviceType", "REGISTRY",
|
|
8
|
+
"all_devices", "by_category", "get", "DeviceInstance", "Link", "Topology",
|
|
9
|
+
]
|