Contributing to getmac¶
Thanks for taking an interest in this awesome little project. We love to bring new members into the community, and can always use the help.
Resources¶
Features suggestions and bug reports: GitHub
Discussion and general questions/help: GitHub discussions or the Python Discord server
Code requirements¶
Your code must:
Have tests
Work with all supported Python versions
Work on all supported platforms
Pass linting (code quality checks)
Pass CI (GitHub Actions)
Adhere to the Code of Conduct
Adhere to the AI policy below
Branch names and commits must follow Conventional Commits notation, e.g. a branch should be
feat-my-feature, notpatch-1, and commits should befeat: myfeature description, notadd some cool thing check it out.
Most of these requirements are checked in CI (GitHub Actions), including Python versions and most supported platforms. Code is formatted with Ruff’s formatter. You can write whatever format you want, as long as you run the formatter before pushing, you’re good (pdm run format).
Please be respectful and follow the Code of Conduct. Memes, references, and jokes are OK. Be nice, we’re all human (well, most of us), and code is the great equalizer.
AI Policy¶
AI-assisted contributions are allowed, with the following requirements:
[ ] All commits must include Co-Authorship indicating the commit was authored in-part or wholly by AI
[ ] PR description must note that the contribution was authoried in-part or wholly by AI
[ ] You (the human) must personally review all library, CI, and documentation changes made by the AI before opening the PR. This is a small project, it’s not a big ask. Tests, scripts, etc are fine to do only a cursory review. If it’s obvious you have not done this, your PR will be closed as the slop it is, kthnxbai.
[ ] It’s OK to draft CHANGELOG and documentation with the AI, but please write it in your own words. AI-verbiage will be told once to be made human, second offence => PR closed.
This policy only applies to agent-powered AI contributions. It doesn’t apply if you’re just using AI tab-completion in an editor or a chatbot to answer questions or generate code snippets (unless the chatbot generates ALL your code, then it applies).
It’s a (hopefully) straightforward and easy to follow policy. Therefore, if you don’t follow this policy, you risk your PR being closed, and possibly being banned from the repo (and risk your GitHub account being suspended). I’ve had annoying bots on other repos, don’t be that guy.
Checklist before submitting a pull request¶
[ ] Code is formatted using
ruff(pdm run format)[ ] All tests run and pass locally
[ ] Tests:
pdm run test[ ] Benchmarks:
pdm run benchmark[ ] Lint:
pdm run lint
[ ] Update the CHANGELOG (if applicable, for non-trivial changes)
[ ] Add your name to the contributors list in the README (please include what your contribution was after your name)
[ ] (AI Bots) The AI policy was followed
Checklist before a Pull Request will be merged¶
[ ] All tests pass in GitHub Actions
[ ] Code has been reviewed by at least one maintainer
[ ] Coverage has NOT decreased
Where to contribute¶
Good for beginners¶
Sample collection (see section below)
Platform testing (see section below)
Bug reports!
Documentation (including fixes for grammar and spelling)
Improving and adding tests for existing samples
Main areas of focus¶
Writing parsers for new commands (Example:
netsh int ipv6)Addressing missing functionality (Example: default interface detection for IPv6 on Windows)
Adding new features (Example: ability to find MAC by interface index integer)
Adding tests for internal methods and mocking where necessary
Platform testing¶
Help is dearly needed on testing and rooting out differences in various platforms and configurations. At a basic level, this involves just running the tests on any platforms you use. Open issues for any bugs or quirks you discover, or if you’re feeling adventurous, fix it yourself!
Any platform is fair game! The following are platforms of special interest:
MacOS/OSX (This requires owning a Mac, and is the area most sorely in need of testing)
Legacy Windows (7, 8, 8.1)
Windows Server (all versions)
Arch Linux
BSDs
Sample collection¶
Collection examples of output of various commands is an easy way to contribute in a meaningful way.
Samples go in tests/samples/, in a folder named after the platform and version (e.g. ubuntu_18.04, macos_10.12.6, windows_10).
The easiest way is to run scripts/collect_samples.py. It runs all the commands getmac uses on your platform (plus a few related ones), including the generic commands getmac falls back to on platforms it doesn’t fully support, and saves the output of each one to a .out file in tests/samples/<platform>_<version>/. It only needs Python 3.9+, getmac doesn’t need to be installed, so you can copy it to any machine and run it there. When run from a copy outside a getmac checkout, it saves to ./samples/<platform>_<version>/ in the current directory instead (or use --output-root); copy that folder into tests/samples/.
# List the samples that would be collected, without collecting or saving them
python scripts/collect_samples.py --dry-run
# Collect the samples
python scripts/collect_samples.py
Some notes:
--dry-rundoesn’t collect or save anything, but it may run a few read-only commands (e.g.ip route list 0/0orbusybox --list) to find the interfaces, the default gateway, and the commands BusyBox has.Existing samples aren’t overwritten, unless you use
--forceCommands that aren’t installed are skipped. Exit codes and errors are written to
collect_samples.login the same folder.If a command times out, its output isn’t saved, and it’s run again the next time. Use
--timeoutto wait longer.Some commands only work as root or Administrator (e.g.
arping).Run
python scripts/collect_samples.py --helpfor all the options, e.g.--nameto change the folder name,--interfaceand--ipto choose the interfaces and hosts to look up.
Check the samples before committing them! They have real MAC addresses, IP addresses, and hostnames from your machine. Replace anything you don’t want to be public, and use the same replacement everywhere so the samples stay consistent.
To add a sample by hand¶
Run the command
Copy/paste the output (or redirect output,
teeis helpful here) into a.outfile intests/samples/<platform>_<version>/. Name it after the command, e.g.arp -aisarp_-a.outandip route list 0/0isip_route_list_0slash0.out.That’s it!
Getting started¶
Create your own fork of the code through GitHub web interface (Here’s a Guide)
Clone the fork to your computer. This can be done using the GitHub desktop GUI ,
git clone <fork-url>, or the Git tools in your favorite editor or IDE.Create and checkout a new branch in the fork with either your username (e.g. “ghostofgoes”), or the name of the feature or issue you’re working on (e.g. “openbsd-support”). Again, this can be done using the GUI, your favorite editor, or
git checkout -b <branch> origin/<branch>.Install PDM (2.20+): https://pdm-project.org/en/latest/#installation
Create local environment:
pdm install -d
Ensure tests and linting works:
pdm run lint pdm run test
Write some code! Git commit messages should information about what changed, and if it’s relevant, the rationale (thinking) for the change.
Format your code:
pdm run format
Follow the checklist in the pull request template
Submit a pull request!
Bug reports¶
Filing a bug report:
Answer these questions:
[ ] What version of
getmacare you using? (getmac --version)[ ] What operating system and processor architecture are you using?
[ ] What version of Python are you using?
[ ] What did you do?
[ ] What did you expect to see?
[ ] What did you see instead?
Put any excessive output into a GitHub Gist and include a link in the issue.
Tag the issue with “Bug”
NOTE: If the issue is a potential security vulnerability, do NOT open an issue! Instead, email: ghostofgoes(at)gmail(dot)com
Features and ideas¶
Ideas for features or other things are welcomed. Open an issue on GitHub detailing the idea, and tag it appropriately (e.g. “Feature” for a new feature).
Resources¶
Regex resources (regular expressions)¶
https://pythex.org/
https://regex101.com/
Python’s guide to regex (this is actually really helpful)
https://ultrapico.com/Expresso.htm (I haven’t used this but it looks useful)
Commands¶
# Create development environment
pdm install -d
# List scripts, these can be run with "pdm run"
pdm run -l
# Run tests
pdm run test
# Run the fuzz tests with many more generated inputs (takes several minutes)
pdm run fuzz
# Lint checks
pdm run lint
# Run getmac CLI
pdm run getmac --help
pdm run getmac --version
The fuzz tests in tests/test_fuzz.py use Hypothesis to feed random and mutated command output to every method’s parser, and random arguments to get_mac_address(). They run a few examples with the regular tests (except on PyPy, where Hypothesis isn’t installed), and many more weekly in the “Fuzz” workflow. If you add or change a parser, run pdm run fuzz before opening a PR. When a fuzz test fails, Hypothesis prints the input that caused it. Add that input as an @example or a regular test along with the fix.
Documentation¶
The docs are built using Sphinx. They are located in the docs/ folder, and the configuration is in docs/conf.py.
To build docs locally (requires Python 3.12 or newer):
pdm run docs
Sphinx warnings fail the build (the same as in CI), so fix any warnings before submitting a pull request.
Docker¶
The Docker image is defined in packaging/Dockerfile. To build it locally (this needs Docker with BuildKit, which is the default since Docker Engine 23.0):
pdm run build-docker
# Try it out
docker run --rm getmac --version
docker run --rm getmac -n localhost
docker run --rm --network host getmac
--pull gets the latest version of the base image instead of using a locally cached copy. Set IMAGE to use a different image name, or a name with a tag to only use that tag. Any arguments are passed to docker build.
IMAGE=getmac-dev pdm run build-docker
IMAGE=getmac:dev pdm run build-docker --no-cache
Build arguments, set with --build-arg NAME=value:
BASE_IMAGE: the image to build on,docker.io/library/python:3.14-slim-trixieby default. Use this to try a different Python version, e.g.--build-arg BASE_IMAGE=docker.io/library/python:3.13-slim-trixie.VERSION,REVISION, andCREATED: the getmac version, git commit, and build time (RFC 3339), for theorg.opencontainers.image.version,revision, andcreatedlabels.
Docker in CI¶
The Docker workflow (.github/workflows/docker.yml) builds and tests the image on linux/amd64 and linux/arm64. It publishes the image to ghcr.io/ghostofgoes/getmac:
Pushes to
mainpublish theedgetag.Pushing a release tag (e.g.
1.0.0) publishes1.0.0,1.0,1, andlatest.Running the workflow manually on
mainor a release tag publishes the same tags again.Pull requests, other branches, and forks only build and test the image.
Published images have SBOM and provenance attestations, and a signed build provenance attestation from GitHub that can be checked with gh attestation verify oci://ghcr.io/ghostofgoes/getmac:<tag> --repo GhostofGoes/getmac.
For maintainers: packages published to a personal account are private at first, even when the repository is public. After the first publish, make the package public on GitHub: on the package’s page, click “Package settings”, then “Change visibility” (under “Danger Zone”), and select “Public”. This only needs to be done once, and it can’t be undone.
GitHub Actions¶
The actions used in the workflows in .github/workflows/ are pinned to a commit SHA, with the version tag they track in a comment, e.g. actions/checkout@<commit SHA> # v7. This protects CI from a tag being moved to a different, possibly malicious, commit.
To update the pinned actions, run:
# NOTE: requires Docker
pdm run update-actions
This uses pin-github-action. To move an action to a new major version, change the tag in its comment (e.g. # v7 to # v8), then run the command. To add a new action, write it with a tag as usual (e.g. uses: owner/action@v1), then run the command to pin it.