Development (Basic)
1. Clone the repository
git clone https://github.com/MarkusThill/BitBully.git
cd BitBully
git submodule update --init --recursive # Initialize and update submodules
BitBully uses submodules, so make sure to always clone with them initialized. If you already cloned earlier without them, run:
2. Create and activate a virtual environment (recommended)
3. Install development dependencies
This installs BitBully in editable mode plus all development tooling (ruff, mypy, pytest, coverage, commitizen, pre-commit, etc.).
4. Install Git hooks (pre-commit)
This activates:
- pre-commit: formatting, linting, static checks before each commit
- commit-msg: Commitizen / conventional commit message validation
- pre-push: optional checks before pushing (e.g., running tests)
To run all hooks manually:
5. Running tests
6. Building wheels locally (optional)
Testing and CI
Running Tests
Run unit tests using pytest:
For more detailed output:
Run only tests matching a pattern:
# A boolean expression that selects tests:
# - containing the substring board
# - but not containing the substring slow
pytest tests/ -k "board and not slow"
Run a specific test case:
Stop after the first failure:
Run with coverage (requires pytest-cov):
GitHub Actions
This project uses GitHub Actions to build and test the library. The CI workflow includes:
- Building wheels for Linux and Windows using
cibuildwheel. - Building source distributions (
sdist). - Optionally uploading artifacts to PyPI.
The workflows are found under .github/workflows/.
Contributing
Contributions are welcome! Follow these steps:
- Fork the repository.
- Create a new branch for your changes:
- Install
devdependencies: - Install pre-commit hooks:
- Commit your changes:
- Push to your branch:
- Open a pull request.
Development
Usual Push Procedure
If possible, also try the build on a windows-native machine since there are some subtle differences in the build process:
pytest tests/ # ensure that tests run through
mv dist/ dist.old # if applicable
python -m build # local build should pass
cibuildwheel --output-dir dist # now build for the other specified platforms
twine check dist/* # Check package metadata in dist folder
twine check dist/* --strict # Check package metadata in dist folder (strict)
git add -u # or add whatever you want to commit
pre-commit run # make sure that this passes
git commit -m "fix|feat|docs|...: message" # commit using semantic versioning
cz bump --dry-run
cz bump
git push --atomic origin master vx.x.x # make sure that you set the correct version
# build will now be performed on GitHub Runners
In case you run into an error during cibuildwheel, like
CMake Error: The current CMakeCache.txt directory /project/build/temp.linux-x86_64-cpython-312/CMakeCache.txt is different than the directory /workspaces/BitBully/build/temp.linux-x86_64-cpython-312 where CMakeCache.txt was created. This may result in binaries being created in the wrong place. If you are not sure, reedit the CMakeCache.txt
CMake Error: The source "/project/CMakeLists.txt" does not match the source "/workspaces/BitBully/CMakeLists.txt" used to generate cache. Re-run cmake with a different source directory.
it might help to clean up old builds:
You can also build pre-release versions like this.
cz bump --prerelease alpha # Creates 1.2.3a0 if current is 1.2.3
cz bump --prerelease beta
cz bump --prerelease rc
cz bump --prerelease rc --increment minor # To bump the minor version and start a pre-release
In this case, after pushing to the repository, only a small build for Python3.11 is performed and the results wheels are pushed to Test-PyPI instead of the real PyPi.
Generating Python Type Stubs for Pybind11 Modules
To enable type checking with tools like mypy for Pybind11 compiled modules, you can generate a .pyi stub file using pybind11-stubgen. For example:
Notes
The generated .pyi file contains function and class signatures with type hints, which helps mypy and other type checkers.
Compiler
The code was compiled with: gcc 13.1.0
Configure gov-13 to match g++-13/gcc-13
The version of gcov has to match our compiler version, in order to be able to produce coverage reports:
sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-11 50 # for compiler version 11
sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-13 100 # for compiler version 13 (as we have here)
sudo update-alternatives --config gcov
Development (Debian-based Systems)
Install Python 3
Configure alternatives, if you have other versions of python installed:
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.11 2
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 2
sudo update-alternatives --config python
sudo update-alternatives --config python3
Install & Activate virtualenv
Install Dependencies
You can run pre-commit before a commit with:
Commitizen
Bump Version
Push commit and tag atomically
Commit types
| Commit Type | Title | Description | Emoji |
|---|---|---|---|
feat |
Features | A new feature | ✨ |
fix |
Bug Fixes | A bug Fix | 🐛 |
docs |
Documentation | Documentation only changes | 📚 |
style |
Styles | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) | 💎 |
refactor |
Code Refactoring | A code change that neither fixes a bug nor adds a feature | 📦 |
perf |
Performance Improvements | A code change that improves performance | 🚀 |
test |
Tests | Adding missing tests or correcting existing tests | 🚨 |
build |
Builds | Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) | 🛠 |
ci |
Continuous Integrations | Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) | ⚙️ |
chore |
Chores | Other changes that don't modify src or test files | ♻️ |
revert |
Reverts | Reverts a previous commit | 🗑 |
Publish to PyPI
-
Create a PyPi Test Account
-
Log in to Test PyPI or create a new account.
- Navigate to "Account Settings" → "API Tokens".
-
Generate a new API token if needed.
-
Create a PyPI Account:
-
Sign up on PyPI.
- Set up 2FA (Two-Factor Authentication) for enhanced security.
- Install Required Tools: Ensure you have build and twine installed for building and publishing:
- Update your
~/.pypirc File:
[ distutils ]
index-servers =
pypi
testpypi
[ testpypi ]
repository = https://test.pypi.org/legacy/
username = __token__
password = <your_api_token>
[ pypi ]
repository = https://upload.pypi.org/legacy/
username = __token__
password = <your_api_token>
Build the Package
Check the Readme
Build
Upload to Test PyPI
Upload to Test pypi first:
Test installation:
Publish to PyPI
Test installation from PyPI:
Compile Libs using CMake
Compile and run Google Tests
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release # run in project root
cmake --build build --target gtest_run --config Release
cd build # navigate into build directory
./gtests/gtest_run # run tests
Updates
Update pybind11 Submodule
git -C thirdParty/pybind11 rev-parse --abbrev-ref HEAD && git -C thirdParty/pybind11 describe --tags --always && git -C thirdParty/pybind11 remote -v
git -C thirdParty/pybind11 fetch --tags origin && git -C thirdParty/pybind11 tag --list "v3.*" | tail -n 200 # adapt to v4.* etc., depending on your needs
git -C thirdParty/pybind11 status --porcelain
git -C thirdParty/pybind11 fetch --tags origin
git -C thirdParty/pybind11 tag --list
git -C thirdParty/pybind11 checkout v3.0.1 # adapt to the version that you wish to checkout
git add thirdParty/pybind11
git commit -m "fix: update pybind11 submodule to vx.x.x" # adapt the version in the message
Update GoogleTests Submodule
git -C thirdParty/googletest rev-parse --abbrev-ref HEAD && git -C thirdParty/googletest describe --tags --always && git -C thirdParty/googletest remote -v
git -C thirdParty/googletest fetch --tags origin && git -C thirdParty/googletest tag --list | sort -V | tail -n 20
git -C thirdParty/googletest status --porcelain # check status
git -C thirdParty/googletest fetch --tags origin # fetch remote tags (if not done already)
git -C thirdParty/googletest checkout vx.x.x # select a tag you want to check out
git add thirdParty/googletest
git commit -m "fix: update googletest submodule to vx.x.x" # adapt the tag here
Update doxygen-awesome-css Submodule
git -C thirdParty/doxygen-awesome-css rev-parse --abbrev-ref HEAD && git -C thirdParty/doxygen-awesome-css describe --tags --always && git -C thirdParty/doxygen-awesome-css remote -v
git -C thirdParty/doxygen-awesome-css fetch --tags origin && git -C thirdParty/doxygen-awesome-css tag --list | sort -V | tail -n 20
git -C thirdParty/doxygen-awesome-css status --porcelain # 1. Check status
git -C thirdParty/doxygen-awesome-css fetch --tags origin # 2. Fetch remote tags (if not already done)
git -C thirdParty/doxygen-awesome-css checkout vx.x.x # 3. Checkout a tag (e.g., v2.4.1 for the latest)
git add thirdParty/doxygen-awesome-css # 4. Update superproject reference
git commit -m "fix: update doxygen-awesome-css submodule to vx.x.x"
git push origin HEAD # 5. Push
Cheatsheet: Most Useful Commands
Version Control (Git)
git status– Check repository status.git add -u– Stage all changes.git add <files>– Stage specific files.git commit -m "<message>"– Commit changes with a message.git commit --amend– Modify the last commit.git push --atomic origin master v<version>– Atomically pushes master branch and tagsgit push– Push changes to the remote repository.git tag -l,git tag --list– List tags.git tag -d <tag>– Delete a local tag.git push origin --delete <tag>– Delete a remote tag.git diff– Show differences between changes.git fetch– Fetch changes from the remote repository.git fetch upstream– Fetches changes from the upstream repositorygit rebase <branch>– Rebase the current branch.git merge <branch>– Merge a branch into the current branch.git merge upstream/main– Merge changes from upstream/main branchgit checkout <file>– Revert changes in a specific file
Git Submodule Commands
git submodule status– Show the status of submodules.git submodule add <repo-url> <path>– Add a new submodule.git submodule update --init --recursive– Initialize and update submodules.git submodule add -b <branch> <repo-url> <path>– Add a submodule tracking a specific branch.
Formatting and Linting
ruff format <file>– Format Python code using Ruff.ruff format .– Format all files using Ruffruff check --fix– Run Ruff checks and apply automatic fixesruff check --unsafe-fixes --fix– Run Ruff checks with unsafe fixesruff format notebooks/*– Format Jupyter notebook filesruff clean– Clean Ruff cache and temporary filesclang-format <file>– Format C++ code using Clang-Format.
CMake Commands
cmake --version– Check the version of CMake.cmake <options>– Generate build files based onCMakeLists.txt.
Testing and Debugging
gdb --version– Check the version of GDB (GNU Debugger).gdb <program>– Debug a program.
Python Environment Management
python3 --version– Check Python version.python3 -m venv <name>– Create a virtual environment.source <venv>/bin/activate– Activate a virtual environment.deactivate– Deactivate the virtual environment.
Dependency and Package Management
pip install <package>– Install a Python package.pip install -e .– Install the package in editable mode.pip uninstall <package>– Uninstall a Python package.pip freeze– List installed packages.gem install <gem>– Install a Ruby gem.bundle install– Install Ruby gem dependencies.pip install /path/to/<package.whl>– Install a locally built wheel.pip uninstall <package>– Uninstall a Python package.
Building and Publishing Python Packages
python -m build– Build a Python package.twine upload dist/*– Upload the package to PyPI.twine check dist/*– Check package metadata in dist foldertwine check dist/* --strict– Strictly check package metadata in dist folpython -m build --wheel– Build only the wheel package.python -m build --sdist– Build only the source distribution.python -m build --platform-tag– Add a specific platform tag to the build.
CIBuildWheel
cibuildwheel --output-dir <dir>– Build Python wheels for multiple platforms.cibuildwheel --output-dir <dir> --verbose– Build wheels with detailed output.cibuildwheel --output-dir <dir> --platform <platform>– Specify a platform for the build (e.g.,linux,macos, orwindows). However, usually, defined in thepyproject.toml.
Pre-Commit Commands
pre-commit install --hook-type <type>– Install specific pre-commit hooks (e.g.,commit-msg,pre-push).pre-commit migrate-config– Migrate.pre-commit-config.yamlto the latest format.pre-commit autoupdate– Update all pre-commit hooks to their latest versions.pre-commit run --all-files– Run hooks on all files.
Testing and CI/CD
pre-commit install– Install pre-commit hooks.pre-commit run– Run all pre-commit hooks.ctest– Run CMake-based tests.cibuildwheel --output-dir dist– Build Python wheels.
Commitizen (cz)
cz init– Initialize Commitizen configuration.cz bump– Automate version bump.cz bump --dry-run– Simulate version bump.
Doxygen
sudo apt install doxygen– Install Doxygen using APTapt show doxygen– displays detailed information about the doxygen packagedoxygen -g Doxyfile– generates a default configuration file named Doxyfile for Doxygendoxygen Doxyfile– Generate Doxgen Docs based on configuration inDoxyfilepython3 -m http.server 8000 --directory docs/html/– Serve documentation locally on port8000doxygen -w html header.html footer.html style.css– Generate template files for customizing Doxygen's output.doxygen --version- get version
Installation script (used in doxygen.yml):
export DOXY_VERSION=1.13.1
echo "Installing doxgen v$DOXY_VERSION"
sudo apt-get update && sudo apt-get install -y graphviz
mkdir doxygen-installer
wget "https://www.doxygen.nl/files/doxygen-${DOXY_VERSION}.linux.bin.tar.gz"
mv "doxygen-${DOXY_VERSION}.linux.bin.tar.gz" doxygen-installer
cd doxygen-installer
gunzip "doxygen-${DOXY_VERSION}.linux.bin.tar.gz"
tar xf "doxygen-${DOXY_VERSION}.linux.bin.tar"
cd "doxygen-${DOXY_VERSION}"
ls -laht
sudo make install
Configuration and Logs
nano ~/.bashrc– Edit the bash configuration file.cat <file>– View file contents.pip show <package>– Display package details.sudo apt install <package>– Install a package using APT.
mkdocs
pip install mkdocs-material mkdocstrings[python] pymdown-extensions- mkdocs extensionsmkdocs buildmkdocs serve
Node.js and NPM
nvm install <version>– Install a specific Node.js version.node -v– Check Node.js version.npm -v– Check NPM version.npm install --save-dev <package>– Install a development dependency.npx prettier . --check– Check code formatting with Prettier.npx prettier . --write– Format code with Prettier.
Docker
docker compose pull– Pull updated images for the services.docker compose up– Start Docker Compose services.docker compose up --help– Display help for Docker Compose.
Ruby and Rbenv
rbenv install <version>– Install a specific Ruby version.rbenv local <version>– Set a local Ruby version for a project.gem install bundle– Install the Bundler gem.bundle install– Install Ruby project dependencies.
Jekyll
bundle exec jekyll serve --incremental– Run a Jekyll server incrementally.bundle exec jekyll serve --lsi– Run Jekyll with LSI (Latent Semantic Indexing).bundle install– Install dependencies from the Gemfile.
Miscellaneous
ls– List directory contents.cd <path>– Change directory.history | grep <keyword>– Search command history.htop– Display interactive process viewer.tmux– Start a new tmux session.