dhcpsrv/CONTRIBUTING.md
engelgardt 540bad0ecb refactor: split into modules under src/dhcpsrv/
The previous monolithic dhcpsrv_app.py (~500 lines) is now 7 focused modules:

- src/dhcpsrv/__init__.py    : single source of truth for __version__
- src/dhcpsrv/__main__.py    : entry for python -m dhcpsrv
- src/dhcpsrv/app.py         : main orchestration, wires the rest
- src/dhcpsrv/platform_win.py: VT enable + UAC self-elevate
- src/dhcpsrv/update_check.py: GitHub /releases/latest poll
- src/dhcpsrv/network.py     : NIC enumeration, netsh, ping
- src/dhcpsrv/dhcp.py        : DhcpConfig, DhcpServer, packet parse/build, server loop
- src/dhcpsrv/ui.py          : rich-based full-screen TUI

Also added:
- dhcpsrv-launcher.py at repo root: absolute-import entry for PyInstaller
- pyproject.toml: deps + dynamic version
- CONTRIBUTING.md: layout, build, and release flow

CI workflow now builds from dhcpsrv-launcher.py.
No user-visible behaviour change.
2026-05-16 12:28:07 +03:00

3.3 KiB

Contributing

Project layout, build, and release flow. If you only want to use the tool — read README instead.

Repo layout

dhcpsrv/
├── .github/
│   ├── workflows/release.yml          ← CI: tag-driven build + GitHub Release
│   └── ISSUE_TEMPLATE/                ← bug / feature / security routing
├── src/dhcpsrv/                       ← package source (≤200 lines per module)
│   ├── __init__.py                    ← single source of truth for __version__
│   ├── __main__.py                    ← entry: python -m dhcpsrv
│   ├── app.py                         ← main flow, wires everything
│   ├── platform_win.py                ← VT enable + UAC self-elevate
│   ├── update_check.py                ← GitHub /releases/latest poll
│   ├── network.py                     ← list_adapters, netsh, ping (no shared state)
│   ├── dhcp.py                        ← DhcpConfig, DhcpServer, packet parse/build
│   └── ui.py                          ← rich-based full-screen TUI
├── pyproject.toml                     ← deps, packaging, dynamic version
├── CHANGELOG.md                       ← Keep a Changelog format, newest first
├── CONTRIBUTING.md                    ← this file
├── LICENSE / README.md / SECURITY.md
└── .gitignore

Run from source (no exe)

python -m pip install rich
python -m dhcpsrv

python -m dhcpsrv finds src/dhcpsrv/__main__.py because the package lives under src/. You'll need administrator privileges for UDP/67 and netsh — the tool self-elevates via UAC.

Editable install (development)

python -m pip install -e .
dhcpsrv

-e . makes the entry-point dhcpsrv available on PATH; edits in src/dhcpsrv/ take effect immediately.

Build the portable .exe

python -m pip install pyinstaller rich
python -m PyInstaller --onefile --uac-admin --console --name dhcpsrv --paths src dhcpsrv-launcher.py

dhcpsrv-launcher.py (at repo root) is the PyInstaller entry — it does an absolute import (from dhcpsrv.app import main) which is needed when PyInstaller runs the bundled script as a standalone module. The --paths src flag tells PyInstaller where to find the dhcpsrv package itself. Output: dist/dhcpsrv.exe.

Cut a release

  1. Update src/dhcpsrv/__init__.py — bump __version__ to X.Y.Z.
  2. Update CHANGELOG.md — move items from [Unreleased] into a new [X.Y.Z] section with today's date.
  3. Commit: git commit -am "vX.Y.Z: …".
  4. Tag: git tag vX.Y.Z.
  5. Push: git push && git push --tags.

That's it. GitHub Actions picks up the tag, builds the exe, writes the SHA-256, and creates the GitHub Release with the zip attached.

Where features go

Adding... Touch this module
A new DHCP option in the reply dhcp.pyDhcpServer.build_reply
A new adapter filter network.pySKIP_DESCRIPTION / SKIP_MEDIA / list_adapters
A new column in the clients table ui.pyUi._render_table
Something shown in the header ui.pyUi._render_header
A startup check or banner line app.pymain()
A change to UAC / VT logic platform_win.py
Tweaking the GitHub update-check UX update_check.py