freedos_micro_python
🤖 No Primate policy
The code in this repository is written by AI. No primate wrote it.
Code: AI. Documentation: AI. Deciding what to build, what is correct, and what ships: primate.
Stated up front so nobody has to work it out later, and so anyone deciding whether to package or redistribute this can weigh it against whatever rules they apply.
What is verifiable regardless of who typed it: MIT throughout, every third-party component catalogued with its license in
docs/THIRD_PARTY.md, upstreams pinned to exact commits, and the whole binary reproducible from source with two commands.
MicroPython port for
FreeDOS / i386, built end-to-end through the
uc386 C23 compiler. Produces a
runnable flat-binary or PMODE/W .exe with a fully-functional
Python REPL — arithmetic, control flow, classes, list comprehensions,
exception handling, and ~25 named builtins all work.
📖 User manual: https://avwohl.github.io/freedos_micro_python/
MicroPython uc386-triage on 2026-05-01; uc386-dos with i386
Type "help()" for more information.
>>> def fib(n):
... if n < 2: return n
... return fib(n-1) + fib(n-2)
...
>>> print([fib(i) for i in range(10)])
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Status
- ~444 KB binary at the EXTRA_FEATURES + axtls TLS configuration
- ~70 smoke tests pin REPL banner, builtins, comprehensions, exceptions,
module imports (
os,time,re,json,hashlib,ssl, ...), and the long-int / float code paths - See
NOTES.mdfor the full per-slice development log
Install on FreeDOS
If you just want to run MicroPython on a DOS machine, you don't need
any of the build tooling below. The port ships as a standard FreeDOS
package — copy mpython.zip to the machine and:
FDNPKG install MPYTHON.ZIP
That puts MP.EXE in C:\DEVEL\MPYTHON, registers the package, and
puts MP on your %PATH%. Then MP starts the REPL and
MP SCRIPT.PY runs a script.
FDINST install MPYTHON.ZIP does the same on pre-386 machines and
needs no network. See
docs/FREEDOS_PACKAGING.md for the
package layout, how to serve it as an FDNPKG repository, and where it
stands with the official FreeDOS repository.
Install the build tooling
pip install freedos_micro_python
This pulls in uc386 (the compiler) automatically. You also need:
- a Unix-y shell to drive the
build_port.shscript (macOS / Linux) git(for fetching the upstream MicroPython sources)makeis not required
Quick start
mkdir mp-build && cd mp-build
freedos-micropython fetch # clones upstream MicroPython into ./upstream
freedos-micropython build # per-TU triage build (generates qstrdefs)
freedos-micropython port # multi-TU build → ./build/micropython.bin
Wall-clock for the port step is ~14 minutes on a recent Mac. The
output is ./build/micropython.bin, a flat i386 DOS binary runnable
under uc386's emulator:
from uc386.dos_emu import run
res = run("build/micropython.bin", timeout_seconds=10.0,
instruction_limit=2_000_000_000)
print(res.stdout) # → "MicroPython uc386-triage on ...\n..."
To produce a real DOS .exe (PMODE/W bound, ~12 KB stub overhead):
use uc386's addons/harness/exe.py.
Testing
After a successful port build:
pytest --pyargs freedos_micro_python # parametric: tests live in tests/
# or, against a checkout:
pytest tests/
The smoke tests skip cleanly if build/micropython.bin doesn't exist.
Bundled networking utilities
The port ships three pure-MicroPython programs that double as regression tests and as usable standalone tools — drop them into a DOS image (or run them in the REPL) and they work end-to-end against real servers.
Running a program
MP.EXE SCRIPT.PY [args ...]
runs SCRIPT.PY and exits; the remaining words land in sys.argv.
Exit status is 0, or 1 on an uncaught exception. With no argument
MP.EXE starts the interactive REPL.
You can also paste a program straight into the REPL: press Ctrl-E,
paste, then Ctrl-D. This needs no file at all, which makes it the
reliable option in the environment noted below.
Reading files from disk works. Verified with one binary on QEMU + FreeDOS, DOSBox-X and dosiz:
MP.EXE SCRIPT.PYwithsys.argv,open()/read()/write()/ append,importof a.py, and theos/shutilcalls.The build bundles the DOS/32A extender. PMODE/W is still selectable with
--extender=pmodew, but its real-mode call path hangs on any DOS call that touches a physical sector — seedocs/WIP.mditem 2.
-
examples/wget.py— HTTPS streaming downloader. Built onsocket(lwIP-backed) andssl(axtls CERT_REQUIRED supported via--ca-certs). Streams in 4 KB chunks so the whole body never sits in RAM. Follows up to 5 redirects.MP.EXE WGET.PY -O OUT.TXT https://example.com/file -
examples/scp.py— SCP client wrapping_ssh.Session.scp_recv()and_ssh.Session.scp_send()(which bind libssh2'sscp_recv2/scp_send_ex). Password auth only for now; up/down inferred from which arg has thehost:/pathcolon.MP.EXE SCP.PY user@10.0.2.2:/etc/motd MOTD.TXT MP.EXE SCP.PY DATA.BIN user@10.0.2.2:/uploads/data.bin -
examples/sftp.py— SFTP client wrapping_ssh.Session.sftp()+SFTP.open()/SFTPFile.read|write|close.MP.EXE SFTP.PY get user@10.0.2.2:/etc/hostname HOST.TXT MP.EXE SFTP.PY put REPORT.TXT user@10.0.2.2:/incoming/report.txt
All three run inside the SSH rig harness (rigs/ssh-rig/,
rigs/tls-rig/) against a paramiko/local-server fixture and confirm
PASS end-to-end; see docs/TESTS.md for the full
catalog.
Layout
src/freedos_micro_python/scripts/— the three shell scripts (fetch.sh,build.sh,build_port.sh); invoked via the CLI wrapper, which setsUC386_LIB_INCLUDEfrom the installeduc386src/freedos_micro_python/port/— the FreeDOS port files (mpconfigport.h,*_uc386dos.c, lwIP + axtls glue)src/freedos_micro_python/gen_qstrdefs.py— qstr table generator (mirrors upstream'stools/makeqstrdata.py)src/freedos_micro_python/cli.py— thefreedos-micropythonCLIexamples/— standalone MicroPython programs (wget.py,scp.py,sftp.py) shipped as both regression tests and usable utilitiestests/— pytest smoke tests + qstr unit testsrigs/dosbox-x-rig/— DOSBox-X regression rig (network packet driver)rigs/tls-rig/— axtls TLS regression rigrigs/ssh-rig/— paramiko-fixture SSH/SFTP/SCP rigrigs/fdpkg-rig/— installs the FreeDOS package with the real FreeDOS installer on a real FreeDOS kernel under QEMUrelease/mkfdpkg.py— builds the FreeDOS package and a drop-in FDNPKG repository from a builtMP.EXE
A debt to FreeDOS
This project targets FreeDOS. FreeDOS is the reason a 32-bit i386 Python REPL on a 1990s-era PC makes any sense in 2026 at all — without a maintained, open-source DOS kernel
- shell + utilities, there'd be no plausible host for this binary to run on.
We mostly use FreeDOS as a target: the rigs boot a stock FreeDOS
1.4 MB floppy image into QEMU (or DOSBox-X), run MP.EXE against
its kernel + COMMAND.COM + PMODE/W, and tear down. We do not
modify the FreeDOS kernel or utilities. But debugging PMODE/W's
INT 21h reflection, the DOS packet-driver interface, the FAT
write path, and a handful of NLS / RTC quirks would have been
impossible without the FreeDOS source tree to read.
In the spirit of paying that debt forward, the release/ directory
ships a copy of the FreeDOS sources we leaned on, regardless of
whether our limited use strictly requires source redistribution
under their license. See release/README.md
for the catalog. License + copyright notices for FreeDOS and every
other third-party project bundled or fetched by the build are in
docs/THIRD_PARTY.md.
License
MIT, matching upstream MicroPython. The integration glue
(scripts, port files, CLI, tests) is what's covered here. Third-party
sources fetched by build_port.sh (MicroPython, axtls, lwIP,
libssh2, TweetNaCl, crypto-algorithms) retain their own licenses;
the FreeDOS sources in release/ retain GPLv2 / their own
per-project licenses. The full catalog with attributions is in
docs/THIRD_PARTY.md.
Related projects
- FreeDOS — The target operating system. This port runs on FreeDOS on i386.
- uc386 — C23 compiler for the i386 processor and MS-DOS. It builds this port and hosts the
dos_emutest harness. - uc_core — Shared C23 frontend and AST optimizer that the uc386 compiler and its Z80 sibling uc80 both use.
- MicroPython — The upstream project. This repository is its port for FreeDOS on i386.
MicroPython feature matrix
Settings come from
src/freedos_micro_python/port/mpconfigport.h.
The port runs at MICROPY_CONFIG_ROM_LEVEL = EXTRA_FEATURES, the
richest preset upstream ships.
Enabled
The EXTRA_FEATURES preset itself turns on the language-surface knobs listed first; everything below it is an explicit override on top.
Language surface (from EXTRA_FEATURES)
compile() / eval() / exec() input()
memoryview frozenset
f-strings collections.deque + iter/subscr
__add__ / __radd__ / __iadd__ etc. function attribute access
delattr() / setattr() math.pi / e / tau / inf / nan
math.factorial / math.isclose bytes.hex / fromhex
str.center / partition / splitlines bytearray slice-assign
Emacs REPL keys + auto-indent Ctrl-C → KeyboardInterrupt
Runtime
ENABLE_COMPILER ENABLE_GC HELPER_REPL
ENABLE_EXTERNAL_IMPORT STACK_CHECK NLR_SETJMP
MODULE___FILE__ PY_BUILTINS_HELP PY_BUILTINS_RANGE_BINOP
USE_INTERNAL_ERRNO STREAMS_POSIX_API
Numerics
FLOAT_IMPL = DOUBLE (full x87 double-precision)
FLOAT_FORMAT_IMPL = EXACT (round-trip shortest decimal)
LONGINT_IMPL = LONGLONG (heap-allocated big ints)
PY_MATH_SPECIAL_FUNCTIONS (erf, gamma, ...)
PY_MATH_{ATAN2,FMOD,MODF,POW,GAMMA}_FIX (CPython-matching edges)
Standard library (extmod)
io open(), IOBase, BytesIO, StringIO
sys modules / exit / path / argv / exc_info / tracebacklimit
time time / time_ns / sleep_ms / ticks_ms / localtime / gmtime / mktime
random EXTRA_FUNCS, seeded from BIOS tick counter
hashlib SHA-256 + SHA-1 + MD5 (real axtls implementations)
binascii full surface incl. CRC32
deflate uzlib decoder + DEFLATE_COMPRESS encoder
re + sub, match groups, span/start/end
heapq, json, struct, uctypes, select, _asyncio
machine mem8/mem16/mem32 (direct linear-address poke in PMODE/W)
Networking + crypto (the harder lift)
socket BSD-style via lwIP (TCP/UDP/DNS, IPv4)
ssl axtls (handshake + CERT_REQUIRED with --ca-certs)
_ssh libssh2 1.11.1 over axtls + TweetNaCl
Session.userauth_password / exec / sftp() /
scp_recv / scp_send / close
uc386_net NE2000 packet driver, eth_init / eth_status / eth_set_static
lwip lwIP raw module (RX poll, callbacks)
pktdrv DOS packet-driver INT 60h harness
dosint21 raw INT 21h access for DOS-native syscalls
Not implemented
_thread / PY_THREAD DOS is single-threaded; emulating
pre-emptive threads would mislead.
Cooperative asyncio runs fine.
cmath / PY_CMATH Complex numbers — not on the path
for any user we serve today.
weakref / PY_WEAKREF Off at CORE; default at EXTRA.
Skipped: no concrete use yet.
VFS / PY_VFS MICROPY_VFS abstraction (mount,
multiple FS backends) — we have a
flat-file import path through INT
21h instead. Adding VFS would buy
FAT/Lit/Posix mounts and overlay
semantics; not a current need.
network module extmod/modnetwork.c (the Network
ABC + cyw43/wiznet/... drivers).
DOS NICs are managed via the
packet-driver interface instead;
uc386_net + lwip cover the same
ground at a lower level.
machine.Pin / I2C / SPI / UART No DOS-level device model. ISA bus
/Timer/ADC/DAC/PWM/WDT access works via machine.mem32, but
the typed peripherals would each
need a driver. Not on the path.
bluetooth / espnow / btree Hardware/RTOS-specific upstream
modules. No DOS analogue exists.
PERSISTENT_CODE_LOAD / .mpy We don't run mpy-tool, so the
FROZEN_MPY frozen-module symbols would be
undefined externs at link time.
Pure-source .py imports work.
In progress
SSH publickey auth Today only userauth_password is
wired up. session.userauth_publickey
needs real RSA / DH / Ed25519
key-parse in port/libssh2_axtls.c
(currently stubs returning -1).
Tracked in docs/WIP.md.
Frozen-bytecode loading Wiring mpy-tool.py + the
mp_frozen_* symbols into the
build would let us ship the
asyncio Python files baked into
the .exe. Mechanical, not
research.
Wider lwIP surface IPv6 is off; UDP multicast and
raw sockets are exposed at the
lwIP layer but not surfaced
through PY_SOCKET. Add as
demand appears.
TCP_NODELAY modlwip's setsockopt(TCP_NODELAY)
matches lwIP's TF_NODELAY=0x40
constant, not POSIX TCP_NODELAY=1.
Trivial to fix — open while we
decide whether to break the
lwIP-native users.
Release files for freedos-micro-python 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| freedos_micro_python-0.2.2.tar.gz | 190.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| freedos_micro_python-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 351.2 kB
Release files / freedos_micro_python-0.2.2.tar.gz
| Download URL | freedos_micro_python-0.2.2.tar.gz |
|---|---|
| Size | 190.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c9ac2f6c269d692e7b0e7a32cf7f2e33681ca94597e1d40fdb82990ccf4c8ba1
|
|
BLAKE2b-256 checksum How to use checksums |
ec89ff95b612785fbdb2eef924e4128c456726048d755fcb946e7815b52ff85c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.
Transparency logRelease files / freedos_micro_python-0.2.2-py3-none-any.whl
| Download URL | freedos_micro_python-0.2.2-py3-none-any.whl |
|---|---|
| Size | 160.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5d9fe04ec1f0996f40b0675d63ada7461254391c53039ba09a1fa2ac522e7836
|
|
BLAKE2b-256 checksum How to use checksums |
747f27e99b5ab1853cdc24e515ffc21294b60e8be47df87b8cc19678d02843ee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.
Transparency log