A lightweight Python CLI that streamlines common .NET project workflows: build, clean, test with coverage, bump versions, create git tags and scaffold projects.
The CLI exposes a single dispatcher command python-dotnet-tools and direct convenience commands for each action:
python-dotnet-buildpython-dotnet-cleanpython-dotnet-testpython-dotnet-bumppython-dotnet-tagpython-dotnet-init-libpython-dotnet-init-minpython-dotnet-init-proj
- Build .NET solutions (restore optional, configuration selection)
- Clean
bin/andobj/folders across a tree - Run tests and generate HTML coverage reports (via
reportgenerator) - Bump a project version in
.csproj(semantic versioning helpers) - Create and optionally push annotated git tags from
.csprojversion - Scaffold .NET repository layouts and projects (init-lib, init-min, init-proj)
python-dotnet-tools/
├─ LICENSE
├─ pyproject.toml
├─ README.md
├─ src/
│ ├─ __init__.py
│ ├─ cli.py # main dispatcher for python-dotnet-tools
│ ├─ commands/
│ │ ├─ __init__.py
│ │ ├─ build.py # build solution(s)
│ │ ├─ clean.py # remove bin/ and obj/
│ │ ├─ test.py # run tests + coverage
│ │ ├─ bump.py # bump <Version> in .csproj
│ │ ├─ tag.py # create git tag from version
│ │ ├─ init_lib.py # scaffold NuGet-ready library repo
│ │ ├─ init_min.py # scaffold minimal library repo
│ │ ├─ init_proj.py # scaffold single project folder
│ │ └─ _data/
│ │ ├─ __init__.py
│ │ ├─ parameters/
│ │ │ └─ init-parameters.json
│ │ └─ templates/
│ │ ├─ LICENSE.MIT.template
│ │ ├─ project.minimal.csproj.template
│ │ ├─ project.nuget.csproj.template
│ │ ├─ project.Tests.csproj.template
│ │ └─ solution.sln.template
│ └─ python_dotnet_tools.egg-info/
│ ├─ dependency_links.txt
│ ├─ entry_points.txt
│ ├─ PKG-INFO
│ ├─ SOURCES.txt
│ └─ top_level.txt
└─ tests/
├─ conftest.py
├─ mock/
├─ test_suite_bash_lib.py
├─ test_suite_bash_min.py
├─ test_suite_cmd_lib.py
└─ test_suite_cmd_min.py- Python 3.11+ (see
requires-pythoninpyproject.toml) - .NET SDK installed and available on PATH (
dotnetcommand)- Windows:
winget install Microsoft.DotNet.SDK.10or download from https://dotnet.microsoft.com/download - Linux: install via your distro (e.g., Ubuntu
sudo apt-get install dotnet-sdk-10.0, Fedorasudo dnf install dotnet-sdk-10.0) or follow official instructions
- Windows:
- Git installed (for tagging and pushing)
- reportgenerator installed (for coverage HTML reports)
- Dotnet CLI (cross-platform):
dotnet tool install -g dotnet-reportgenerator-globaltool - Windows:
winget install danielpalme.reportgeneratororscoop install reportgeneratororchoco install reportgenerator - Linux: via package manager if available, or download binaries from GitHub repository
- Dotnet CLI (cross-platform):
You can install the Python package from source using pip. From the repository root:
- Editable (recommended for development):
pip install -e .- Regular install (build and install):
pip install .After installation, console scripts will be available on your PATH:
python-dotnet-toolspython-dotnet-build,python-dotnet-clean,python-dotnet-test,python-dotnet-bump,python-dotnet-tag
Ensure prerequisites are on PATH:
dotnet(from .NET SDK)reportgenerator(either the standalone binary or the dotnet global tool; if installed as a dotnet tool, it’s available asreportgeneratoronce your dotnet tools path is on PATH)
Alternatively, you can run the dispatcher module directly during development:
python -m src.cli --helpYou can use either the single dispatcher or the dedicated commands. All commands support --help.
Notes:
- You can call any command via the dispatcher too. For example, instead of
python-dotnet-build, you can runpython-dotnet-tools build(and similarly:python-dotnet-tools clean,python-dotnet-tools test, etc.).
python-dotnet-tools --help
python-dotnet-tools <build|clean|test|bump|tag|init-lib|init-min|init-proj> [args]Builds a solution found under the target directory.
- Default target path (no arg):
./srcunder current working directory - If multiple
.slnfiles are present, you must specify one with--solution
Examples:
python-dotnet-build # restore + build Debug and Release under ./src
python-dotnet-build . # build current directory’s ./src
python-dotnet-build D:\path\to\repo\src # build a specific src directory
python-dotnet-build --no-restore # skip restore
python-dotnet-build --solution MyApp.sln # specify solution
python-dotnet-build --configuration Release # build only ReleaseFlags:
--no-restoreSkipdotnet restore--solution <name.sln>Pick a specific solution when multiple exist--configuration <Debug|Release>Build a specific configuration; default builds both
Removes all bin/ and obj/ directories under the target path.
Examples:
python-dotnet-clean # cleans ./src under current working directory
python-dotnet-clean . # cleans the current directory (expects ./src)
python-dotnet-clean D:\code\proj # cleans the provided directoryDiscovers test projects and runs dotnet test with coverage; generates HTML report via reportgenerator.
- With a path arg: results and coverage are created under that path
- Without a path arg: looks for
./testsand writes coverage to./docs/coverage-report
Examples:
python-dotnet-test # search ./tests, write results to ./tests/TestResults, HTML to ./docs/coverage-report
python-dotnet-test D:\code\proj\tests # search under given path, write TestResults/ and coverage-report/ thereOutputs:
- Test results:
TestResults/ - Coverage report:
coverage-report/(ordocs/coverage-report/when no path provided)
Bumps a version in a target .csproj by replacing or inserting a <Version> tag.
- Version sources: explicit
MAJOR.MINOR.PATCHor helpers--major|--minor|--patch - Target selection: explicit
.csprojfile or directory (non-recursive) with a single.csproj; otherwise auto-discovered under./src
Examples:
python-dotnet-bump 1.2.3 # set version to 1.2.3 (auto-discover csproj under ./src)
python-dotnet-bump --minor ./src/MyApp # bump minor in a single .csproj under provided directory
python-dotnet-bump --patch D:\code\MyApp.csproj # bump patch in an explicit csprojRules:
--major|--minor|--patchrequire an existing<Version>tag- Explicit version must match
MAJOR.MINOR.PATCH - Creates a timestamped backup and removes it after successful verification
Creates an annotated git tag from the version read in a .csproj.
- Default base path:
./src - If multiple
.csprojfiles are found, provide a more specific path - Optional push to remote with
--pushand--remote
Examples:
python-dotnet-tag # tag from version read under ./src (e.g., v1.2.3)
python-dotnet-tag D:\code\proj # tag from version read under given path
python-dotnet-tag --push # push to origin
python-dotnet-tag --push --remote upstream # push to custom remoteNotes:
- If tag already exists, the command aborts
Generate repository scaffolds and project files using embedded templates.
Examples:
# NuGet-ready repo: src/tests, LICENSE, .editorconfig, .gitignore, solution, project (in src), tests project
python-dotnet-init-lib --root MyLib --solution MyLib --project MyLib.Core --author "Jane Doe" --company "Jane Doe" --description "My sample library" --version 0.1.0 --packageId MyLib.Core --repositoryUrl https://github.com/user/MyLib
# Minimal repo: src/tests, LICENSE, no NuGet metadata, project under src/<Project>/
python-dotnet-init-min --root MyLib --solution MyLib --project MyLib --author "Jane Doe" --description "My library"
# Single project folder with a csproj
python-dotnet-init-proj --name Utils # minimal (default)
python-dotnet-init-proj --name Package --nuget # NuGet template with blank metadataYou can also pass a JSON file (mutually exclusive with flags) to init-lib/init-min with the same fields of the default json paramenters (see commands/_data/parameters/init-parameters.json).
Set up a virtual environment and install the package in editable mode.
Windows PowerShell:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e .Run commands locally:
python -m src.cli --help
python-dotnet-tools build --helpPytest-based tests live under tests/. The end-to-end suites run real external tools (dotnet, reportgenerator, git) and validate actual side effects (build outputs, cleaned folders, coverage artifacts, version bumps, and git tags).
test_suite_cmd_lib.py: End-to-end via dispatchercli.mainusinginit-lib. Scaffolds a full repo under a unique mock path, then exercisesbuild,clean,test(with coverage viareportgenerator),bump(version updates in.csproj),tag(annotated git tag from version), andinit-proj(adds an extra minimal project). Validates created files, directories, coverage HTML, and git tag presence.test_suite_bash_lib.py: End-to-end using direct command entrypoints (commands.*.main) withinit-lib. Creates a unique mock repo, then directly callsbuild,clean,testwith coverage,bump,tag, andinit-proj. Asserts scaffold correctness, test/coverage outputs, version changes, and tag creation.test_suite_cmd_min.py: End-to-end via dispatcher usinginit-minto scaffold a minimal repo. Adds a small xUnit tests project (withcoverlet.collector) to enable coverage, then runsbuild,clean,testwith coverage,bump(explicit version on minimal csproj),tag, andinit-proj.test_suite_bash_min.py: End-to-end using direct entrypoints withinit-min. Similarly adds a tests project, then runsbuild,clean,test,bump(explicit version),tag, andinit-proj, validating artifacts throughout.
Run tests:
python -m pip install -e .
python -m pip install pytest
pytest -qThis project is licensed under the MIT License. A copy of the license is available at LICENSE in the repository.