fromscratch-pyos 0.3.0__py3-none-any.whl

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.
Files changed (77) hide show
  1. fromscratch_pyos-0.3.0.dist-info/METADATA +205 -0
  2. fromscratch_pyos-0.3.0.dist-info/RECORD +77 -0
  3. fromscratch_pyos-0.3.0.dist-info/WHEEL +4 -0
  4. fromscratch_pyos-0.3.0.dist-info/entry_points.txt +4 -0
  5. fromscratch_pyos-0.3.0.dist-info/licenses/LICENSE +21 -0
  6. py_os/__init__.py +1 -0
  7. py_os/__main__.py +5 -0
  8. py_os/_version.py +24 -0
  9. py_os/bootloader.py +219 -0
  10. py_os/completer.py +233 -0
  11. py_os/containers.py +328 -0
  12. py_os/env.py +64 -0
  13. py_os/fs/__init__.py +39 -0
  14. py_os/fs/fd.py +163 -0
  15. py_os/fs/filesystem.py +591 -0
  16. py_os/fs/journal.py +537 -0
  17. py_os/fs/persistence.py +94 -0
  18. py_os/fs/procfs.py +329 -0
  19. py_os/io/__init__.py +91 -0
  20. py_os/io/bridge.py +327 -0
  21. py_os/io/devices.py +193 -0
  22. py_os/io/disk.py +222 -0
  23. py_os/io/dns.py +111 -0
  24. py_os/io/framebuffer.py +185 -0
  25. py_os/io/http.py +282 -0
  26. py_os/io/interrupts.py +305 -0
  27. py_os/io/ipc.py +137 -0
  28. py_os/io/networking.py +301 -0
  29. py_os/io/shm.py +54 -0
  30. py_os/io/tcp.py +830 -0
  31. py_os/io/timer.py +148 -0
  32. py_os/jobs.py +104 -0
  33. py_os/kernel.py +3668 -0
  34. py_os/logging.py +121 -0
  35. py_os/memory/__init__.py +38 -0
  36. py_os/memory/manager.py +225 -0
  37. py_os/memory/mmap.py +52 -0
  38. py_os/memory/slab.py +481 -0
  39. py_os/memory/swap.py +438 -0
  40. py_os/memory/virtual.py +243 -0
  41. py_os/process/__init__.py +46 -0
  42. py_os/process/binary.py +389 -0
  43. py_os/process/pcb.py +382 -0
  44. py_os/process/scheduler.py +796 -0
  45. py_os/process/signals.py +93 -0
  46. py_os/process/threads.py +146 -0
  47. py_os/py.typed +0 -0
  48. py_os/repl.py +114 -0
  49. py_os/shell/__init__.py +64 -0
  50. py_os/shell/base.py +559 -0
  51. py_os/shell/commands/__init__.py +25 -0
  52. py_os/shell/commands/basics.py +106 -0
  53. py_os/shell/commands/devices.py +375 -0
  54. py_os/shell/commands/files.py +505 -0
  55. py_os/shell/commands/isolation.py +272 -0
  56. py_os/shell/commands/learn.py +31 -0
  57. py_os/shell/commands/memory.py +485 -0
  58. py_os/shell/commands/network.py +765 -0
  59. py_os/shell/commands/processes.py +1035 -0
  60. py_os/shell/commands/sync.py +460 -0
  61. py_os/shell/commands/users.py +131 -0
  62. py_os/sync/__init__.py +30 -0
  63. py_os/sync/deadlock.py +265 -0
  64. py_os/sync/inheritance.py +189 -0
  65. py_os/sync/ordering.py +227 -0
  66. py_os/sync/primitives.py +725 -0
  67. py_os/syscalls.py +2502 -0
  68. py_os/tui/__init__.py +5 -0
  69. py_os/tui/app.py +127 -0
  70. py_os/tui/widgets.py +146 -0
  71. py_os/tutorials.py +783 -0
  72. py_os/users.py +472 -0
  73. py_os/web/__init__.py +14 -0
  74. py_os/web/app.py +92 -0
  75. py_os/web/static/style.css +77 -0
  76. py_os/web/static/terminal.js +65 -0
  77. py_os/web/templates/index.html +21 -0
@@ -0,0 +1,205 @@
1
+ Metadata-Version: 2.5
2
+ Name: fromscratch-pyos
3
+ Version: 0.3.0
4
+ Summary: A simulated operating system built in Python for learning OS concepts
5
+ Project-URL: Homepage, https://github.com/robcox2910/py-os
6
+ Project-URL: Repository, https://github.com/robcox2910/py-os
7
+ Project-URL: Issues, https://github.com/robcox2910/py-os/issues
8
+ Project-URL: Documentation, https://robcox2910.github.io/py-os/
9
+ Author: Rob Cox
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: education,learning,operating-system,os-concepts,simulator
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Education
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Education
19
+ Classifier: Topic :: System :: Operating System
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.14
22
+ Provides-Extra: dev
23
+ Requires-Dist: commitizen>=4.4.0; extra == 'dev'
24
+ Requires-Dist: hypothesis>=6.170; extra == 'dev'
25
+ Requires-Dist: pip-audit>=2.10.0; extra == 'dev'
26
+ Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
27
+ Requires-Dist: pyright>=1.1.400; extra == 'dev'
28
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
29
+ Requires-Dist: pytest-cov>=6.0.0; extra == 'dev'
30
+ Requires-Dist: pytest>=8.3.4; extra == 'dev'
31
+ Requires-Dist: ruff>=0.9.3; extra == 'dev'
32
+ Provides-Extra: docs
33
+ Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
34
+ Provides-Extra: tui
35
+ Requires-Dist: textual>=0.90; extra == 'tui'
36
+ Provides-Extra: web
37
+ Requires-Dist: flask>=3.0; extra == 'web'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # PyOS
41
+
42
+ **Build your own operating system in Python -- then play with it.**
43
+
44
+ [![Python 3.14+](https://img.shields.io/badge/python-3.14%2B-blue)](https://www.python.org/downloads/)
45
+ [![CI](https://github.com/robcox2910/py-os/actions/workflows/ci.yml/badge.svg)](https://github.com/robcox2910/py-os/actions/workflows/ci.yml)
46
+ [![Docs](https://github.com/robcox2910/py-os/actions/workflows/docs.yml/badge.svg)](https://robcox2910.github.io/py-os/)
47
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
48
+
49
+ Ever wondered what happens when you open a program, save a file, or connect to the internet? PyOS is a complete operating system simulator that lets you see every piece -- processes, memory, filesystems, networking -- and poke at them from a real shell. Built with test-driven development and written for learners.
50
+
51
+ ## What Does It Look Like?
52
+
53
+ ```
54
+ ======================================
55
+ PyOS v0.1.0
56
+ A simulated operating system
57
+ ======================================
58
+
59
+ [POST] CPU ... OK
60
+ [POST] Memory ... OK
61
+ [POST] Storage ... OK
62
+ [BOOT] Loading kernel image v0.1.0 ... OK
63
+ [OK] Logger
64
+ [OK] Memory manager (256 frames)
65
+ [OK] Slab allocator
66
+ [OK] File system (journaled)
67
+ [OK] Scheduler (FCFS)
68
+ [OK] Init process (PID 1)
69
+
70
+ Kernel running. Type 'help' for commands, 'exit' to quit.
71
+
72
+ root@pyos $ ps
73
+ PID State Name
74
+ 1 READY init
75
+
76
+ root@pyos $ fork 1
77
+ Forked process 1 → child PID 2 (init)
78
+
79
+ root@pyos $ pstree
80
+ init (PID 1)
81
+ └── init (PID 2)
82
+
83
+ root@pyos $ learn
84
+ Available tutorials:
85
+ processes — What is a process and how do they work?
86
+ memory — How does the OS manage memory?
87
+ filesystem — How are files stored and organised?
88
+ shell — What is a shell and why do we need one?
89
+ scheduling — How does the CPU decide what to run next?
90
+ Type 'learn <topic>' to start a tutorial.
91
+ ```
92
+
93
+ ## Features
94
+
95
+ - **Six CPU schedulers** -- FCFS, Round Robin, Priority, Aging, MLFQ, and CFS with multi-core support
96
+ - **Virtual memory** -- page tables, address translation, swap (FIFO/LRU/Clock), slab allocator, and mmap
97
+ - **Journaled filesystem** -- inodes, directories, hard/soft links, file descriptors, /proc, and crash recovery
98
+ - **Full network stack** -- sockets, DNS, HTTP, and TCP with three-way handshake, flow control, and congestion control
99
+ - **Shell scripting** -- pipes, variables, conditionals, job control, tab completion, and 80+ built-in commands
100
+ - **Interactive tutorials** -- guided lessons that teach OS concepts hands-on using real system calls
101
+
102
+ ## Install
103
+
104
+ ```bash
105
+ pip install pyos-learn
106
+ pyos
107
+ ```
108
+
109
+ Want the browser-based terminal too?
110
+
111
+ ```bash
112
+ pip install pyos-learn[web]
113
+ pyos-web
114
+ ```
115
+
116
+ ## Learn the Concepts
117
+
118
+ Each guide explains one part of the OS with real-world analogies and simple language.
119
+
120
+ | Guide | What You'll Learn |
121
+ |-------|-------------------|
122
+ | [What Is an OS?](docs/concepts/what-is-an-os.md) | The big picture -- what an OS does and why you need one |
123
+ | [Processes](docs/concepts/processes.md) | Programs that are running, how they take turns, forking, and threads |
124
+ | [Memory](docs/concepts/memory.md) | How the OS manages limited memory with pages, virtual addresses, and swap |
125
+ | [Filesystem](docs/concepts/filesystem.md) | How files and folders are organised, and how they're saved to disk |
126
+ | [The Kernel](docs/concepts/kernel-and-syscalls.md) | The brain of the OS -- boot sequence and system calls |
127
+ | [The Shell](docs/concepts/shell.md) | Typing commands, pipes, scripting, and environment variables |
128
+ | [Devices and Networking](docs/concepts/devices-and-networking.md) | Hardware, inter-process communication, disk scheduling, and sockets |
129
+ | [Interrupts and Timers](docs/concepts/interrupts.md) | Interrupt controller, vectors, masking, timer, preemption |
130
+ | [TCP: Reliable Delivery](docs/concepts/tcp.md) | Three-way handshake, flow control, congestion control, retransmission |
131
+ | [Users and Safety](docs/concepts/users-and-safety.md) | Permissions, signals, logging, and deadlocks |
132
+ | [Synchronization](docs/concepts/synchronization.md) | Mutexes, semaphores, condition variables, and race conditions |
133
+ | [The Boot Chain](docs/concepts/bootloader.md) | What happens between pressing power and seeing a prompt |
134
+ | [Framebuffer](docs/concepts/framebuffer.md) | Pixel-level graphics, drawing shapes, and displaying images |
135
+ | [TUI Dashboard](docs/concepts/tui.md) | A live terminal dashboard that shows OS internals in real time |
136
+ | [Permissions](docs/concepts/permissions.md) | File ownership, read/write/execute bits, groups, and ACLs |
137
+ | [Binary Loader](docs/concepts/binary-loader.md) | Loading and running programs -- how `exec` works |
138
+ | [Containers](docs/concepts/containers.md) | Lightweight isolation with PID, mount, and network namespaces |
139
+ | [Inter-Machine Networking](docs/concepts/inter-machine-networking.md) | Connecting multiple kernels with bridges and clusters |
140
+ | [Interactive Tutorials](docs/concepts/tutorials.md) | Guided lessons that teach OS concepts hands-on |
141
+ | [Web UI](docs/concepts/web-ui.md) | Browser-based terminal interface |
142
+
143
+ ## Development
144
+
145
+ ```bash
146
+ git clone https://github.com/robcox2910/py-os.git
147
+ cd py-os
148
+ uv sync --all-extras
149
+ uv run pytest
150
+ ```
151
+
152
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for coding standards and PR workflow.
153
+
154
+ ## Releasing
155
+
156
+ Other projects in the series ([PyStack](https://github.com/robcox2910/pystack)) use a pinned release of this one,
157
+ not whatever is on `main`. To publish a change for them:
158
+
159
+ 1. Merge the change to `main`.
160
+ 2. Tag it: `git tag -a vX.Y.Z -m vX.Y.Z && git push origin vX.Y.Z`.
161
+ A change to the public API bumps the minor version (`v0.1.0` → `v0.2.0`);
162
+ anything else bumps the patch (`v0.1.0` → `v0.1.1`).
163
+ 3. In each project that uses it, edit the tag in `[tool.uv.sources]`, run
164
+ `uv lock --upgrade-package <name>`, and open a pull request so CI checks
165
+ the pair together.
166
+
167
+ <!-- series:start -->
168
+ ## Related Projects
169
+
170
+ This project is one of a series that builds real systems "from scratch in Python" to teach how they work. See the [series home](https://robcox2910.github.io/) for the full story.
171
+
172
+ | Project | What it teaches | Repository | Docs |
173
+ | --- | --- | --- | --- |
174
+ | **PyOS** | **Operating systems** | [py-os](https://github.com/robcox2910/py-os) | [Docs](https://robcox2910.github.io/py-os/) |
175
+ | Pebble | Compilers and programming languages | [pebble-lang](https://github.com/robcox2910/pebble-lang) | [Docs](https://robcox2910.github.io/pebble-lang/) |
176
+ | PyDB | Relational databases | [pydb](https://github.com/robcox2910/pydb) | [Docs](https://robcox2910.github.io/pydb/) |
177
+ | PyKV | Key-value stores | [pykv](https://github.com/robcox2910/pykv) | [Docs](https://robcox2910.github.io/pykv/) |
178
+ | PyDocDB | Document databases | [pydoc-db](https://github.com/robcox2910/pydoc-db) | [Docs](https://robcox2910.github.io/pydoc-db/) |
179
+ | PyGraphDB | Graph databases | [pygraphdb](https://github.com/robcox2910/pygraphdb) | [Docs](https://robcox2910.github.io/pygraphdb/) |
180
+ | PyTSDB | Time-series databases | [pytsdb](https://github.com/robcox2910/pytsdb) | [Docs](https://robcox2910.github.io/pytsdb/) |
181
+ | PyVecDB | Vector databases | [pyvecdb](https://github.com/robcox2910/pyvecdb) | [Docs](https://robcox2910.github.io/pyvecdb/) |
182
+ | PyColDB | Column-family databases | [pycoldb](https://github.com/robcox2910/pycoldb) | [Docs](https://robcox2910.github.io/pycoldb/) |
183
+ | PyCrypt | Cryptography | [pycrypt](https://github.com/robcox2910/pycrypt) | [Docs](https://robcox2910.github.io/pycrypt/) |
184
+ | PyNet | Computer networking | [pynet](https://github.com/robcox2910/pynet) | [Docs](https://robcox2910.github.io/pynet/) |
185
+ | PyWeb | HTTP web servers | [pyweb](https://github.com/robcox2910/pyweb) | [Docs](https://robcox2910.github.io/pyweb/) |
186
+ | PyGit | Version control | [pygit](https://github.com/robcox2910/pygit) | [Docs](https://robcox2910.github.io/pygit/) |
187
+ | PySearch | Search engines | [pysearch](https://github.com/robcox2910/pysearch) | [Docs](https://robcox2910.github.io/pysearch/) |
188
+ | PyMQ | Message queues | [pymq](https://github.com/robcox2910/pymq) | [Docs](https://robcox2910.github.io/pymq/) |
189
+ | PyLLM | Language models (the brain) | [pyllm](https://github.com/robcox2910/pyllm) | [Docs](https://robcox2910.github.io/pyllm/) |
190
+ | PyScheduler | Job scheduling | [pyscheduler](https://github.com/robcox2910/pyscheduler) | [Docs](https://robcox2910.github.io/pyscheduler/) |
191
+ | PyStack | Full-stack integration | [pystack](https://github.com/robcox2910/pystack) | [Docs](https://robcox2910.github.io/pystack/) |
192
+ <!-- series:end -->
193
+
194
+ ## Links
195
+
196
+ - [Documentation](https://robcox2910.github.io/py-os/)
197
+ - [Shell Reference](docs/shell-reference.md) -- all 80+ commands by category
198
+ - [Architecture](docs/architecture.md) -- technical overview of every module
199
+ - [Visual Guide](docs/diagrams.md) -- architecture diagrams
200
+
201
+ <!-- docs:start -->
202
+ ## Documentation
203
+
204
+ Full docs (with kid-friendly explanations of every idea): https://robcox2910.github.io/py-os/
205
+ <!-- docs:end -->
@@ -0,0 +1,77 @@
1
+ py_os/__init__.py,sha256=ISMnoFS4-vc0wuBPW1-JCQ106FlvOZZtqpPlLYjn0LY,84
2
+ py_os/__main__.py,sha256=eKdbA2szDY2jIcUbyGgZ08eYreUA2To5o0V04FBO7cU,88
3
+ py_os/_version.py,sha256=RCY04NY0kBCyn6ttH6lnVL6Gz2gceOrt45f0yDOOU8A,520
4
+ py_os/bootloader.py,sha256=HnpXGPh_kEUuI1kaLekayLDBYMStpGYLCm6dUhET1pg,6800
5
+ py_os/completer.py,sha256=vstLRECoP19gz_7IXd-WCitK_rquqn8Cy6HAiwcKmQ4,8370
6
+ py_os/containers.py,sha256=3gZSSHD8Y9IItkv_JKBFd7EBX0uJi-A2tnFwGhvqTUE,10786
7
+ py_os/env.py,sha256=JfW8-zSz40lqu6Xuypox8XK7atPkLDC5rgjEMld0poM,2243
8
+ py_os/jobs.py,sha256=1fbeea9Y-lcbavwKWjUVAllnE1oYTolvrdWfwF1sLfk,3236
9
+ py_os/kernel.py,sha256=YODPmFEQ8tLzi6GGFPHtwKmEAn-8sZm-4M9-lOg9o-w,128581
10
+ py_os/logging.py,sha256=HRwRBflcQ8d4eoP_FtsXvTGBKvhjEh-sqG9_Deou0Ds,3568
11
+ py_os/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ py_os/repl.py,sha256=ksn8ZoBX-2fomqE4ZaX58kvt8Vmnk9wKvms8qvtnqow,3584
13
+ py_os/syscalls.py,sha256=DU-CZkc8ex6b2sSV6Of2BEIneAQOAgGxBGRggVeGqnU,83567
14
+ py_os/tutorials.py,sha256=8hbZN2zWsl00x74zG34O-J5ZdZN4wXcI-kMjUFI8lOI,31075
15
+ py_os/users.py,sha256=VDJLlm6JMbNwLJ7BVJb6ivlc0cYnG9tSNebXmkqBk9E,15094
16
+ py_os/fs/__init__.py,sha256=xHFSdwnU-1z9PPKxO3e58UvXC_cd6X0jpUeONePwEVY,1051
17
+ py_os/fs/fd.py,sha256=zaUiFq0_vgyV9TSf5QTvu8Xpsxf30VruF613jYrxL5s,4458
18
+ py_os/fs/filesystem.py,sha256=oL-fPIJQ-6YruLogP-dknbJFrSKbW1VcUeLzAjmpKjs,20138
19
+ py_os/fs/journal.py,sha256=Nic3z508RkFXuaH7qMb5C2hXwxzhOb-mvdgQNQYnVyA,17407
20
+ py_os/fs/persistence.py,sha256=8qJXj0fn-kiSffzBs21eO9ezzDF-gEMosUntmnJRG_0,2727
21
+ py_os/fs/procfs.py,sha256=OpKhV3gLU1NC1AkKJoRT6gGoLBGlykUiJflm8vV3BH0,11878
22
+ py_os/io/__init__.py,sha256=7NF7oOlMiFS7rbKTVNCm1Kn7afv4qa209m0R_iR_Zzo,2087
23
+ py_os/io/bridge.py,sha256=meQKEbz77RONwsX5zwN7rwqji9hExLDNikE4Y8jx0gQ,10609
24
+ py_os/io/devices.py,sha256=eDoAGXxDy9MY4xVcL0j1A-AJ9lxzT0Zhf27azYARujc,5564
25
+ py_os/io/disk.py,sha256=Gl3wiEA5ZCd5jouVV2yCqS7VkRENu1dMuAsTVcQKE6Q,7823
26
+ py_os/io/dns.py,sha256=iInGYV-17AP1WtX1VgfRMl5pJ8kt6CS8laZeeMFKJ0I,3134
27
+ py_os/io/framebuffer.py,sha256=T6TbFfr5POSuJlw5n75pEzAlZTESPgHgOZ3r_TknoyQ,5663
28
+ py_os/io/http.py,sha256=cz3ugp6BiCVlB_I6xxrqoGTKdwJlQmNKobuy96u0-n8,7857
29
+ py_os/io/interrupts.py,sha256=fkp6fygpZYx_YChFsLOxzDn0xoO9MRzKRzIBzdK2DgA,9262
30
+ py_os/io/ipc.py,sha256=EgqIR831tXpehIALTMAdaoFVvCyzvTwDxzcUMRjAZwo,4100
31
+ py_os/io/networking.py,sha256=4gwm6OyC3D7h0wXGkH3SJdC2fuA6aq2C57oW7nUV61o,10391
32
+ py_os/io/shm.py,sha256=uCo2XQZLlIaWAWfEgERNbmrw378c7-_LIx8jJBCroas,1805
33
+ py_os/io/tcp.py,sha256=HN76BhDgP4C7yR1LfUwhBvy7z1L0gnntk38PHdjO7ps,26842
34
+ py_os/io/timer.py,sha256=VpGP_QqabKoryzJGZS40FCmYEU9d4jV2u7f-agkxrAE,4516
35
+ py_os/memory/__init__.py,sha256=lzh8L_MhfevqFWsK_rDelz0PDJiQLL8HUjRpBT6zPmM,892
36
+ py_os/memory/manager.py,sha256=6lP1q1IM6CjQLSwuFNaMNWn-ZFIhkfziAOMHYEeLSVY,7293
37
+ py_os/memory/mmap.py,sha256=HwQy4PO5q8SZrDnq9NyLkHJXNuiRmQlzGrOlU6qyj1s,1638
38
+ py_os/memory/slab.py,sha256=_ruRF9NoWkQm1H7sqm8nev5W5HMdQgfEPoU-wkDF6Qs,14908
39
+ py_os/memory/swap.py,sha256=rwL4Z4UYqvvbSgutfV00zUt4YinHRcjud-SUS5rRgpA,14484
40
+ py_os/memory/virtual.py,sha256=2O5YTx1mDhxkNR2hIBuY6va8ydk_HAPsjUqEIIzNgSA,8504
41
+ py_os/process/__init__.py,sha256=3Q4wA9qFMu7jxbKwibWsfHxufHjBYFIzOtD6yPJI0pc,942
42
+ py_os/process/binary.py,sha256=PljUki3MgmpphNYyaSb_sar_55AIota_05e3hPLF4og,12797
43
+ py_os/process/pcb.py,sha256=64YINo81CBRbG41xAOp_wCDjrsTyBc2GlKye8t4Wdqc,13644
44
+ py_os/process/scheduler.py,sha256=uJ1oieIuH46G9inVUX1MAnCI4I8m7urXwNAIdDCuJq8,28506
45
+ py_os/process/signals.py,sha256=hs6hjKMLkvQu60dxdnwhzwKNq_Anma-86bTevt5UB9M,3291
46
+ py_os/process/threads.py,sha256=xHRDFsokgMqhi7G8wFrIteNAc33hghX4xDt9ikAnY_k,4985
47
+ py_os/shell/__init__.py,sha256=sGqubpCnXqrdxDYIP2k0On30ZSNcl-zX8gsW54w6AEw,2153
48
+ py_os/shell/base.py,sha256=RssovgXKDuJ6l3TyUAz6R6ppdusoQmeJAutTZGyF5aY,21083
49
+ py_os/shell/commands/__init__.py,sha256=LHjz8PQ0HCvvJ0ujEEm_YJfVh5Cg0ZVoW31pK0EsjE8,859
50
+ py_os/shell/commands/basics.py,sha256=yX2a4lLjAKTDyU03CW0N1lxgQ2NNDJgxfWY5G6GNCeQ,3970
51
+ py_os/shell/commands/devices.py,sha256=fehv02H_zPNPwxWeK_verxFU-zkuA3R5Yk7eJcfTIIE,14733
52
+ py_os/shell/commands/files.py,sha256=k2VnKYK0k3dCvmCMv6RVm2jBNH8fzFmIKc3rvDjkY_Y,19192
53
+ py_os/shell/commands/isolation.py,sha256=HmRNArhuYXnayrrkppeQYfMoqC53MSqnQT1rEli5AAI,10590
54
+ py_os/shell/commands/learn.py,sha256=Ur_jM0oa7i2N_r8hFejFyJMzMa1jZX0uUkhzNnPK8Ww,1046
55
+ py_os/shell/commands/memory.py,sha256=Xe7xT8Sn2NQqeZQbC1-yXtZrLrsRRZJ47n13jd-DkKI,18159
56
+ py_os/shell/commands/network.py,sha256=9NV1n8rf5ttyQ2bC7ETFEP0rTdMX9FebNKZbx7h6FP8,30031
57
+ py_os/shell/commands/processes.py,sha256=r_zCF4AXFFCm2On_aF2gNjnA97VgVjojNenhxoF0_b8,42354
58
+ py_os/shell/commands/sync.py,sha256=aePAAG4XC5hXKTCccN8qbpQxZAw0hVRcblwBAy5435M,19561
59
+ py_os/shell/commands/users.py,sha256=YoPSGfeNVP1zelIX8CEE3hn3p_Budw2FLmjIve6jUX4,5282
60
+ py_os/sync/__init__.py,sha256=1lVOCpWesVG7RvLRvqv4RZbN055thFXjzMODltuaswA,780
61
+ py_os/sync/deadlock.py,sha256=7icCHt1CDLodJWVBGY0FMCTgBgD66VRMJDy3BjQH_ko,9487
62
+ py_os/sync/inheritance.py,sha256=FKJmBvYZCFIWvwuL_3-nuD3E2DxUFCcjfUtKBTZfQdo,6867
63
+ py_os/sync/ordering.py,sha256=RXGmLIWLpcqW-cBcO1W4wWeELSZst0oKbxCxjlnCWw4,7388
64
+ py_os/sync/primitives.py,sha256=cWoDThw1ytOVQFmYgSQH7SmoIZMJHMguq9eChTGTKzs,23024
65
+ py_os/tui/__init__.py,sha256=ivIrIDQom5BiWlpqLquwRi2j-UrdnSrutYt2_A7PMzA,206
66
+ py_os/tui/app.py,sha256=hYx6p-XJ60_ldotaR2HN5Yfzr52SRzFZjAq6sEgm0nw,4042
67
+ py_os/tui/widgets.py,sha256=coswN1G27qp766UJ51O3QkH05XMA-rfteNxX9MYtWCY,4628
68
+ py_os/web/__init__.py,sha256=CRf53S1sO59mTgd2X2d-QahHi4wchRE1t3Ry91W0ikk,485
69
+ py_os/web/app.py,sha256=vMpm26gOYuwGoN2kDdLM2hxDDU_ONctOzWIqOsTWS_c,2771
70
+ py_os/web/static/style.css,sha256=QTuER3LAe1jmSfcYqQT3LCrNrBNQpbvvjIKE4Vkwduk,1243
71
+ py_os/web/static/terminal.js,sha256=QuzO54uBYgxGUZF-Ki07EG68cEYBgsquQsL7XZa8k-0,1804
72
+ py_os/web/templates/index.html,sha256=0rhqKLLV70_2PNzD7Ctp8qRH9IMHhYuBTD7grXAXWtY,728
73
+ fromscratch_pyos-0.3.0.dist-info/METADATA,sha256=c0w65vCzLYyGa-7BZysdSbnYdmv1JiPiJ4U1UjAwskQ,10541
74
+ fromscratch_pyos-0.3.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
75
+ fromscratch_pyos-0.3.0.dist-info/entry_points.txt,sha256=4zHzRCJ_SMpscOw_jkX1gKNC-F2x9qaUJRO4KcgsyJc,100
76
+ fromscratch_pyos-0.3.0.dist-info/licenses/LICENSE,sha256=NtHM2ak--oE71VCcY50kcCoC1cKS0LRUsxq_xA89RNc,1064
77
+ fromscratch_pyos-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ pyos = py_os.repl:run
3
+ pyos-tui = py_os.tui.app:main
4
+ pyos-web = py_os.web.app:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rob Cox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
py_os/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """PyOS - A simulated operating system built in Python for learning OS concepts."""
py_os/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ """Allow running the OS with ``python -m py_os``."""
2
+
3
+ from py_os.repl import run
4
+
5
+ run()
py_os/_version.py ADDED
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.3.0'
22
+ __version_tuple__ = version_tuple = (0, 3, 0)
23
+
24
+ __commit_id__ = commit_id = None
py_os/bootloader.py ADDED
@@ -0,0 +1,219 @@
1
+ """Bootloader — simulated firmware POST and boot chain.
2
+
3
+ Every real computer follows a boot chain before you see a shell prompt:
4
+
5
+ Firmware POST → Bootloader → Kernel → Userspace
6
+
7
+ Think of it like opening a school building each morning:
8
+
9
+ 1. **Firmware POST** — Security guard checks lights, water, doors.
10
+ 2. **Bootloader** — Janitor fetches "Today's School Plan" from the
11
+ supply closet (disk) and hands it to the principal.
12
+ 3. **Kernel boot** — Principal sets up each department from the plan.
13
+ 4. **Userspace** — Vice principal opens the front desk (shell) so
14
+ students can check in.
15
+
16
+ This module simulates that chain so you can see what happens between
17
+ pressing the power button and getting a shell prompt.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import json
23
+ from dataclasses import dataclass, field
24
+ from enum import StrEnum
25
+ from typing import TYPE_CHECKING
26
+
27
+ from py_os.kernel import Kernel
28
+
29
+ if TYPE_CHECKING:
30
+ from pathlib import Path
31
+
32
+
33
+ class BootStage(StrEnum):
34
+ """Represent the current phase of the boot chain.
35
+
36
+ The boot process moves through these stages in order:
37
+ FIRMWARE → BOOTLOADER → KERNEL → USERSPACE.
38
+ """
39
+
40
+ FIRMWARE = "firmware"
41
+ BOOTLOADER = "bootloader"
42
+ KERNEL = "kernel"
43
+ USERSPACE = "userspace"
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class PostResult:
48
+ """Capture the outcome of the firmware Power-On Self-Test (POST).
49
+
50
+ POST checks that essential hardware works before the OS loads.
51
+ If any check fails, the machine cannot boot safely.
52
+ """
53
+
54
+ memory_ok: bool
55
+ disk_ok: bool
56
+ devices_ok: bool
57
+ messages: tuple[str, ...] = ()
58
+
59
+ @property
60
+ def passed(self) -> bool:
61
+ """Return True only if every hardware check passed."""
62
+ return self.memory_ok and self.disk_ok and self.devices_ok
63
+
64
+
65
+ @dataclass(frozen=True)
66
+ class KernelImage:
67
+ """Represent the kernel binary stored on disk.
68
+
69
+ In a real system the bootloader reads the kernel image from a
70
+ partition (e.g. ``/boot/vmlinuz``). Our image carries the
71
+ configuration the kernel needs to initialise itself.
72
+ """
73
+
74
+ version: str
75
+ total_frames: int
76
+ default_policy: str
77
+ boot_args: dict[str, str] = field(default_factory=lambda: {}) # noqa: PIE807
78
+ num_cpus: int = 1
79
+
80
+
81
+ class BootError(RuntimeError):
82
+ """Raise when the boot chain cannot continue.
83
+
84
+ Examples: POST failure, missing kernel image, corrupt image file.
85
+ """
86
+
87
+
88
+ class Bootloader:
89
+ """Simulate the firmware + bootloader that starts the kernel.
90
+
91
+ Usage::
92
+
93
+ bootloader = Bootloader()
94
+ kernel = bootloader.boot() # full chain, returns running kernel
95
+
96
+ """
97
+
98
+ def __init__(
99
+ self,
100
+ *,
101
+ kernel_image_path: Path | None = None,
102
+ total_frames: int = 64,
103
+ num_cpus: int = 1,
104
+ ) -> None:
105
+ """Create a bootloader with optional kernel image path.
106
+
107
+ Args:
108
+ kernel_image_path: Path to a JSON kernel image file.
109
+ If None, a default image is constructed in memory.
110
+ total_frames: Default memory frame count (used when no
111
+ image file is provided).
112
+ num_cpus: Number of CPUs to simulate (default 1).
113
+
114
+ """
115
+ self._kernel_image_path = kernel_image_path
116
+ self._total_frames = total_frames
117
+ self._num_cpus = num_cpus
118
+ self._stage: BootStage = BootStage.FIRMWARE
119
+ self._boot_log: list[str] = []
120
+ self._kernel: Kernel | None = None
121
+
122
+ @property
123
+ def stage(self) -> BootStage:
124
+ """Return the current boot stage."""
125
+ return self._stage
126
+
127
+ @property
128
+ def boot_log(self) -> list[str]:
129
+ """Return the accumulated boot log messages."""
130
+ return list(self._boot_log)
131
+
132
+ @property
133
+ def kernel(self) -> Kernel | None:
134
+ """Return the booted kernel, or None if boot has not completed."""
135
+ return self._kernel
136
+
137
+ def boot(self) -> Kernel:
138
+ """Run the full boot chain and return a running kernel.
139
+
140
+ Raises:
141
+ BootError: If POST fails or the kernel image is missing.
142
+
143
+ """
144
+ # Stage 1: Firmware POST
145
+ self._stage = BootStage.FIRMWARE
146
+ post_result = self._run_post()
147
+ if not post_result.passed:
148
+ msg = "POST failed: " + ", ".join(post_result.messages)
149
+ raise BootError(msg)
150
+ self._boot_log.extend(f"[POST] {m}" for m in post_result.messages)
151
+
152
+ # Stage 2: Load kernel image
153
+ self._stage = BootStage.BOOTLOADER
154
+ image = self._load_kernel_image()
155
+ self._boot_log.append(f"[BOOT] Loading kernel image v{image.version} ... OK")
156
+
157
+ # Stage 3: Boot kernel
158
+ self._stage = BootStage.KERNEL
159
+ kernel = Kernel(total_frames=image.total_frames, num_cpus=image.num_cpus)
160
+ kernel.boot()
161
+ self._kernel = kernel
162
+
163
+ # Stage 4: Userspace ready
164
+ self._stage = BootStage.USERSPACE
165
+ return kernel
166
+
167
+ def _run_post(self) -> PostResult:
168
+ """Simulate the Power-On Self-Test.
169
+
170
+ Check memory frames, disk accessibility, and device availability.
171
+ """
172
+ messages: list[str] = []
173
+ memory_ok = self._total_frames > 0
174
+ messages.append(
175
+ f"Memory: {self._total_frames} frames ... " + ("OK" if memory_ok else "FAIL")
176
+ )
177
+
178
+ # Disk is always accessible in our simulation
179
+ disk_ok = True
180
+ messages.append("Disk: accessible ... OK")
181
+
182
+ # Devices are always available in our simulation
183
+ devices_ok = True
184
+ messages.append("Devices: ready ... OK")
185
+
186
+ return PostResult(
187
+ memory_ok=memory_ok,
188
+ disk_ok=disk_ok,
189
+ devices_ok=devices_ok,
190
+ messages=tuple(messages),
191
+ )
192
+
193
+ def _load_kernel_image(self) -> KernelImage:
194
+ """Load the kernel image from a JSON file or construct defaults.
195
+
196
+ Raises:
197
+ BootError: If the image file is specified but cannot be read.
198
+
199
+ """
200
+ if self._kernel_image_path is not None:
201
+ try:
202
+ data = json.loads(self._kernel_image_path.read_text())
203
+ return KernelImage(
204
+ version=data.get("version", "0.1.0"),
205
+ total_frames=data.get("total_frames", self._total_frames),
206
+ default_policy=data.get("default_policy", "fcfs"),
207
+ boot_args=data.get("boot_args", {}),
208
+ num_cpus=data.get("num_cpus", self._num_cpus),
209
+ )
210
+ except (OSError, json.JSONDecodeError) as e:
211
+ msg = f"Cannot load kernel image: {e}"
212
+ raise BootError(msg) from e
213
+
214
+ return KernelImage(
215
+ version="0.1.0",
216
+ total_frames=self._total_frames,
217
+ default_policy="fcfs",
218
+ num_cpus=self._num_cpus,
219
+ )