├── .devcontainer └── devcontainer.json ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── labeler.yml ├── pull_request_template.md └── workflows │ ├── labeler.yml │ ├── main.yml │ ├── mkdocs_ci.yml │ ├── publish-to-test-pypi.yml │ ├── stale.yml │ └── welcome.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── client.py ├── docs ├── CNAME └── index.md ├── mkdocs.yml ├── pyproject.toml ├── src └── python_project_template │ ├── __init__.py │ ├── awesome.py │ └── server.py ├── tests └── test_awesome.py └── uv.lock /.devcontainer /devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "customizations": { 3 | "codespaces": { 4 | }, 5 | "vscode": { 6 | "extensions": [ 7 | "ms-python.python", 8 | "ms-python.pylint", 9 | "ms-toolsai.jupyter", 10 | "github.copilot", 11 | "ms-vscode.makefile-tools", 12 | "ms-azuretools.vscode-docker", 13 | "twixes.pypi-assistant", 14 | "EditorConfig.EditorConfig" 15 | ] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # More details are here: https://help.github.com/articles/about-codeowners/ 5 | 6 | # The '*' pattern is global owners. 7 | 8 | # Order is important. The last matching pattern has the most precedence. 9 | # The folders are ordered as follows: 10 | 11 | # In each subsection folders are ordered first by depth, then alphabetically. 12 | # This should make it easy to add new rules without breaking existing ones. 13 | 14 | # Global rule: 15 | 16 | * @aniketmaurya 17 | 18 | # tests 19 | 20 | /tests/** @aniketmaurya 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | #### Bug description 12 | 13 | 14 | #### Expected result 15 | 16 | 17 | #### Actual result 18 | 19 | 20 | #### Steps to reproduce 21 | 22 | 23 | 1. 24 | 2. 25 | 3. 26 | #### Context 27 | 28 | 29 | 30 | #### Your Environment 31 | 32 | 33 | * Version used: 34 | * Operating System and version: 35 | * Link to your fork: 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | #### Is your feature request related to a problem? Please describe. 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | #### Describe the solution you'd like 14 | A clear and concise description of what you want to happen. 15 | 16 | #### Describe alternatives you've considered 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | #### Additional context 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # Add 'docs' to any changes within 'docs' folder or any subfolders 2 | documentation: 3 | - docs/**/* 4 | 5 | example: 6 | - examples/**/* 7 | 8 | test: 9 | - tests/**/* 10 | 11 | CI: 12 | - .github/**/* 13 | - "*.yaml" 14 | - "*.yml" 15 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | #### Changes 2 | 3 | 4 | 5 | 6 | Fixes # (issue) 7 | 8 | 9 | #### Type of change 10 | 11 | - [ ] 📚 Documentation Update 12 | - [ ] 🧪 Tests Cases 13 | - [ ] 🐞 Bug fix (non-breaking change which fixes an issue) 14 | - [ ] 🔬 New feature (non-breaking change which adds functionality) 15 | - [ ] 🚨 Breaking change (fix or feature that would cause existing functionality to not work as expected) 16 | - [ ] 📝 This change requires a documentation update 17 | 18 | 19 | #### Checklist 20 | 21 | - [ ] My code follows the style guidelines of this project 22 | - [ ] I have performed a self-review of my own code 23 | - [ ] I have commented my code, particularly in hard-to-understand areas 24 | - [ ] I have made corresponding changes to the documentation 25 | - [ ] My changes generate no new warnings 26 | - [ ] Did you update CHANGELOG in case of a major change? 27 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Labeler" 2 | on: 3 | - pull_request_target 4 | 5 | jobs: 6 | triage: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/labeler@v3 10 | with: 11 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 12 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: pytest 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | 8 | 9 | jobs: 10 | pytest: 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [ ubuntu-latest, macos-latest ] 15 | python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 16 | include: 17 | - os: ubuntu-latest 18 | path: ~/.cache/pip 19 | - os: macos-latest 20 | path: ~/Library/Caches/pip 21 | env: 22 | OS: ${{ matrix.os }} 23 | PYTHON: ${{ matrix.python-version }} 24 | 25 | 26 | steps: 27 | - uses: actions/checkout@v2 28 | with: 29 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 30 | 31 | - name: Set up Python ${{ matrix.python-version }} 32 | uses: actions/setup-python@v2 33 | with: 34 | python-version: ${{ matrix.python-version }} 35 | 36 | - name: Cache pip 37 | uses: actions/cache@v2 38 | with: 39 | path: ${{ matrix.path }} 40 | key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 41 | restore-keys: | 42 | ${{ runner.os }}-pip- 43 | ${{ runner.os }}- 44 | 45 | - name: Install 46 | run: | 47 | python --version 48 | pip --version 49 | python -m pip install --upgrade pip 50 | pip install coverage pytest pytest-cov 51 | pip install ".[dev]" 52 | pip list 53 | shell: bash 54 | 55 | - name: Run Test with Coverage 56 | run: | 57 | coverage erase 58 | coverage run -m pytest 59 | 60 | - name: Generate Coverage Report 61 | run: | 62 | coverage report -m -i 63 | coverage xml -i 64 | 65 | - name: Upload Coverage to Codecov 66 | if: runner.os != 'macOS' 67 | uses: codecov/codecov-action@v1 68 | with: 69 | token: ${{ secrets.CODECOV_TOKEN }} 70 | file: ./coverage.xml 71 | flags: unittests 72 | env_vars: OS,PYTHON 73 | name: codecov-umbrella 74 | fail_ci_if_error: false 75 | -------------------------------------------------------------------------------- /.github/workflows/mkdocs_ci.yml: -------------------------------------------------------------------------------- 1 | name: MkDocs 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions/setup-python@v2 12 | with: 13 | python-version: "3.12" 14 | - run: pip install mkdocs mkdocs-material 15 | - run: make build-docs && mkdocs gh-deploy --force 16 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-test-pypi.yml: -------------------------------------------------------------------------------- 1 | name: Publish Python 🐍 distributions 📦 to PyPI 2 | 3 | on: push 4 | 5 | jobs: 6 | build-n-publish: 7 | name: Build and publish Python 🐍 distributions 📦 to PyPI 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@master 12 | - name: Set up Python 3.9 13 | uses: actions/setup-python@v1 14 | with: 15 | python-version: 3.9 16 | 17 | - name: Install pypa/build 18 | run: >- 19 | python -m 20 | pip install 21 | build 22 | --user 23 | - name: Build a binary wheel and a source tarball 24 | run: >- 25 | make clean && make build 26 | 27 | - name: Publish distribution 📦 to PyPI 28 | if: startsWith(github.ref, 'refs/tags') 29 | uses: pypa/gh-action-pypi-publish@master 30 | with: 31 | password: ${{ secrets.PYPI_API_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: "30 1 * * *" 6 | 7 | jobs: 8 | stale: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/stale@v3 14 | with: 15 | repo-token: ${{ secrets.GITHUB_TOKEN }} 16 | stale-issue-message: 'Stale issue message' 17 | stale-pr-message: 'Stale pull request message' 18 | stale-issue-label: 'no-issue-activity' 19 | stale-pr-label: 'no-pr-activity' 20 | -------------------------------------------------------------------------------- /.github/workflows/welcome.yml: -------------------------------------------------------------------------------- 1 | name: Greet New Contributors 2 | 3 | on: [pull_request_target, issues] 4 | 5 | jobs: 6 | greeting: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/first-interaction@v1 10 | with: 11 | repo-token: ${{ secrets.GITHUB_TOKEN }} 12 | issue-message: "👋 @${{github.actor}}! Thank you for opening your first issue in this repo. We are so happy that you have decided to contribute and value your contribution. Please read these materials before proceeding: [Contributing Guide](https://github.com/gradsflow/gradsflow/blob/master/CONTRIBUTING.md) and [Code of Conduct](https://github.com/gradsflow/gradsflow/blob/master/CODE_OF_CONDUCT.md)." 13 | pr-message: "👋 @${{github.actor}}! Thank you for opening your first pull request in this repo. We are so happy that you have decided to contribute and value your contribution. Please read these materials before proceeding: [Contributing Guide](https://github.com/gradsflow/gradsflow/blob/master/CONTRIBUTING.md) and [Code of Conduct](https://github.com/gradsflow/gradsflow/blob/master/CODE_OF_CONDUCT.md)." 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | .idea/ 132 | .vscode/ 133 | lightning_logs/ 134 | *.zip 135 | *.jpg 136 | *.jpeg 137 | *.png 138 | *.gif 139 | 140 | /data 141 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python3 3 | 4 | ci: 5 | autofix_prs: true 6 | autoupdate_commit_msg: "[pre-commit.ci] pre-commit suggestions" 7 | autoupdate_schedule: "monthly" 8 | # submodules: true 9 | 10 | repos: 11 | - repo: https://github.com/pre-commit/pre-commit-hooks 12 | rev: v5.0.0 13 | hooks: 14 | - id: end-of-file-fixer 15 | - id: trailing-whitespace 16 | exclude: '.*\.md$' 17 | - id: check-case-conflict 18 | - id: check-yaml 19 | - id: check-toml 20 | - id: check-json 21 | - id: check-added-large-files 22 | - id: check-docstring-first 23 | - id: detect-private-key 24 | 25 | - repo: https://github.com/codespell-project/codespell 26 | rev: v2.3.0 27 | hooks: 28 | - id: codespell 29 | additional_dependencies: [tomli] 30 | #args: ["--write-changes"] 31 | 32 | - repo: https://github.com/pre-commit/mirrors-prettier 33 | rev: v3.1.0 34 | hooks: 35 | - id: prettier 36 | files: \.(json|yml|yaml|toml) 37 | # https://prettier.io/docs/en/options.html#print-width 38 | args: ["--print-width=120"] 39 | 40 | - repo: https://github.com/astral-sh/ruff-pre-commit 41 | rev: v0.8.1 42 | hooks: 43 | - id: ruff-format 44 | args: ["--preview"] 45 | - id: ruff 46 | args: ["--fix"] 47 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | mkdocs: 9 | configuration: mkdocs.yml 10 | 11 | # Optionally set the version of Python and requirements required to build your docs 12 | python: 13 | version: 3.8 14 | install: 15 | - requirements: docs/requirements.txt 16 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | hello@domain.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guidelines 2 | 3 | 👍🎉 First off, thanks for taking the time to contribute! 🎉👍 4 | 5 | The following is a set of guidelines for contributing to Python-Project-Template and its packages, which are hosted in the Python-Project-Template Organization on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. 6 | 7 | We welcome any kind of contribution to our software, from simple comment or question to a full fledged [pull request](https://help.github.com/articles/about-pull-requests/). Please read and follow our [Code of Conduct](CODE_OF_CONDUCT.md). 8 | 9 | A contribution can be one of the following cases: 10 | 11 | 1. you have a question; 12 | 1. you think you may have found a bug (including unexpected behavior); 13 | 1. you want to make some kind of change to the code base (e.g. to fix a bug, to add a new feature, to update documentation); 14 | 1. you want to make a new release of the code base. 15 | 16 | The sections below outline the steps in each case. 17 | 18 | ## You have a question 19 | 20 | 1. use the search functionality [here](https://github.com/aniketmaurya/python-project-template/issues) to see if someone already filed the same issue; 21 | 2. if your issue search did not yield any relevant results, make a new issue; 22 | 3. apply the "Question" label; apply other labels when relevant. 23 | 4. You can join our Slack group as well. 24 | 25 | ## You think you may have found a bug 26 | 27 | 1. use the search functionality [here](https://github.com/aniketmaurya/python-project-template/issues) to see if someone already filed the same issue; 28 | 1. if your issue search did not yield any relevant results, make a new issue, making sure to provide enough information to the rest of the community to understand the cause and context of the problem. Depending on the issue, you may want to include: 29 | - the [SHA hashcode](https://help.github.com/articles/autolinked-references-and-urls/#commit-shas) of the commit that is causing your problem; 30 | - some identifying information (name and version number) for dependencies you're using; 31 | - information about the operating system; 32 | 1. apply relevant labels to the newly created issue. 33 | 34 | ## You want to make some kind of change to the code base 35 | 36 | 1. (**important**) announce your plan to the rest of the community *before you start working*. This announcement should be in the form of a (new) issue; 37 | 1. (**important**) wait until some kind of consensus is reached about your idea being a good idea; 38 | 1. if needed, fork the repository to your own Github profile and create your own feature branch off of the latest master commit. While working on your feature branch, make sure to stay up to date with the master branch by pulling in changes, possibly from the 'upstream' repository (follow the instructions [here](https://help.github.com/articles/configuring-a-remote-for-a-fork/) and [here](https://help.github.com/articles/syncing-a-fork/)); 39 | 1. make sure the existing tests still work by running ``pytest``; 40 | 1. add your own tests (if necessary); 41 | 1. update or expand the documentation; 42 | 1. update the `docs/CHANGELOG.md` file with change; 43 | 1. push your feature branch to (your fork of) the https://github.com/aniketmaurya/python-project-template repository on GitHub; 44 | 1. create the pull request, e.g. following the instructions [here](https://help.github.com/articles/creating-a-pull-request/). 45 | 46 | In case you feel like you've made a valuable contribution, but you don't know how to write or run tests for it, or how to generate the documentation: don't let this discourage you from making the pull request; we can help you! Just go ahead and submit the pull request, but keep in mind that you might be asked to append additional commits to your pull request. 47 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PYTHON_VERSION=3.12 2 | FROM python:$PYTHON_VERSION-slim 3 | 4 | ####### Add your own installation commands here ####### 5 | # RUN pip install some-package 6 | # RUN wget https://path/to/some/data/or/weights 7 | # RUN apt-get update && apt-get install -y 8 | 9 | WORKDIR /app 10 | COPY . /app 11 | 12 | # Install litserve and requirements 13 | RUN pip install --no-cache-dir litserve==0.2.5 14 | EXPOSE 8000 15 | CMD ["python", "/app/src/python_project_template/server.py"] 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2025 Aniket Maurya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # Manifest syntax https://docs.python.org/2/distutils/sourcedist.html 2 | graft wheelhouse 3 | 4 | recursive-exclude __pycache__ *.py[cod] *.orig 5 | 6 | # Include the README and CHANGELOG 7 | include *.md 8 | recursive-include src *.md 9 | 10 | # Include the license file 11 | include LICENSE 12 | 13 | # Exclude build configs 14 | exclude *.sh 15 | exclude *.toml 16 | exclude *.svg 17 | exclude *.yml 18 | exclude *.yaml 19 | 20 | # exclude tests from package 21 | recursive-exclude tests * 22 | recursive-exclude site * 23 | exclude tests 24 | 25 | # Exclude the documentation files 26 | recursive-exclude docs * 27 | exclude docs 28 | 29 | # Include the Requirements 30 | include requirements.txt 31 | recursive-include _requirements *.tx;t 32 | 33 | # Exclude Makefile 34 | exclude Makefile 35 | 36 | prune .git 37 | prune .github 38 | prune temp* 39 | prune test* 40 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build-docs: 2 | cp README.md docs/index.md 3 | 4 | docsserve: 5 | mkdocs serve 6 | 7 | test: 8 | pytest 9 | 10 | coverage: ## Run tests with coverage 11 | coverage erase 12 | coverage run -m pytest 13 | coverage report -m 14 | coverage xml 15 | 16 | clean: 17 | rm -rf dist 18 | find . -type f -name "*.DS_Store" -ls -delete 19 | find . | grep -E "(__pycache__|\.pyc|\.pyo)" | xargs rm -rf 20 | find . | grep -E ".pytest_cache" | xargs rm -rf 21 | find . | grep -E ".ipynb_checkpoints" | xargs rm -rf 22 | rm -f .coverage 23 | 24 | style: 25 | isort --profile black . 26 | ruff format . 27 | 28 | push: 29 | git push && git push --tags 30 | 31 | build: 32 | python -m build --wheel 33 | 34 | publish-test: 35 | $(style clean build) 36 | twine upload -r testpypi dist/* 37 | 38 | publish-prod: 39 | $(style clean build) 40 | twine upload dist/* 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

Python Project Template 🐍

3 | 4 |

A template to kick-start your open-source Python project.

5 |
6 | 7 |

8 | 9 | Tests 10 | 11 | 12 | codecov 13 | 14 | 15 | black 16 | 17 | 18 | license 19 | 20 |

21 | 22 |

23 | 24 | Open in GitHub Codespaces 25 | 26 |

27 | 28 | # Features 29 | 30 | - 🚀 Modern Python project structure 31 | - 📦 Pre-configured [pyproject.toml](pyproject.toml) 32 | - 🤖 ML server template with [LitServe](https://github.com/Lightning-AI/LitServe) 33 | - 🧪 Testing setup with [pytest](https://docs.pytest.org/en/latest/) 34 | - 👷 CI/CD with [GitHub Actions](https://github.com/aniketmaurya/python-project-template/blob/main/.github/workflows) 35 | - 📝 Auto-generated documentation 36 | - 🎯 Type hints and static type checking 37 | - 🔍 Code formatting with ruff and isort 38 | - 🐛 Linting with ruff 39 | 40 | # Project Structure 41 | 42 | ``` 43 | python-project-template/ 44 | ├── .github/ 45 | │ └── workflows/ # GitHub Actions workflows 46 | ├── docs/ # Documentation 47 | ├── src/ # Source code 48 | │ └── python_project_template/ 49 | ├── tests/ # Test files 50 | ├── .gitignore 51 | ├── LICENSE 52 | ├── README.md 53 | ├── pyproject.toml # Project metadata and dependencies 54 | └── setup.py # Package installation 55 | ``` 56 | 57 | # Installation 58 | 59 | ## From Source 60 | 61 | ```bash 62 | git clone https://github.com/aniketmaurya/python-project-template.git 63 | cd python-project-template 64 | pip install . 65 | ``` 66 | 67 | ## Development Installation 68 | 69 | ```bash 70 | git clone https://github.com/aniketmaurya/python-project-template.git 71 | cd python-project-template 72 | pip install -e ".[dev]" 73 | ``` 74 | 75 | ## Usage 76 | 77 | ```python 78 | from python_project_template import do_something_awesome 79 | 80 | print(do_something_awesome()) 81 | ``` 82 | 83 | # Development 84 | 85 | 1. Clone the repository 86 | 87 | ```bash 88 | git clone https://github.com/aniketmaurya/python-project-template.git 89 | cd python-project-template 90 | ``` 91 | 92 | 2. Create a virtual environment 93 | 94 | ```bash 95 | python -m venv venv 96 | source venv/bin/activate # On Windows, use `venv\Scripts\activate` 97 | ``` 98 | 99 | 3. Install development dependencies 100 | 101 | ```bash 102 | pip install -e ".[dev]" 103 | ``` 104 | 105 | ## Running Tests 106 | 107 | ```bash 108 | pytest tests/ 109 | ``` 110 | 111 | # Contributing 112 | 113 | Contributions are always welcome! Here's how you can help: 114 | 115 | 1. Fork the repository 116 | 2. Create a new branch (`git checkout -b feature/amazing-feature`) 117 | 3. Make your changes 118 | 4. Commit your changes (`git commit -m 'Add some amazing feature'`) 119 | 5. Push to the branch (`git push origin feature/amazing-feature`) 120 | 6. Open a Pull Request 121 | 122 | Please make sure to update tests as appropriate and follow the existing coding style. 123 | 124 | # License 125 | 126 | [MIT](https://choosealicense.com/licenses/mit/) - Feel free to use this template for your projects! 127 | -------------------------------------------------------------------------------- /client.py: -------------------------------------------------------------------------------- 1 | # Sample client to test the server 2 | import requests 3 | 4 | response = requests.post("http://127.0.0.1:8000/predict", json={"input": 4.0}) 5 | print(f"Status: {response.status_code}\nResponse:\n {response.text}") 6 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | python-template.aniketmaurya.github.io 2 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aniketmaurya/python-project-template/cd0af65c8d3624da60f93069b1a6413814661c7e/docs/index.md -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Python Project Template 2 | site_url: https://github.com/aniketmaurya/python-project-template 3 | theme: 4 | name: material 5 | palette: 6 | primary: amber 7 | accent: blue 8 | features: 9 | - content.action.edit 10 | - content.action.edit.link 11 | font: 12 | text: Roboto 13 | code: Roboto Mono 14 | nav: 15 | - Home: index.md 16 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "setuptools-scm"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "python-template-project" 7 | description = "Python template project" 8 | readme = "README.md" 9 | requires-python = ">=3.9" 10 | license = {file = "LICENSE"} 11 | dynamic = ["version"] 12 | dependencies = [ 13 | "litserve>=0.2.5", 14 | ] 15 | 16 | [tool.setuptools.packages.find] 17 | where = ["src"] 18 | include = ["python_project_template*"] 19 | 20 | [tool.setuptools.dynamic] 21 | version = {attr = "python_project_template.__version__"} 22 | 23 | [tool.ruff] 24 | line-length = 120 25 | target-version = "py39" 26 | lint.select = ["I"]# implementation for isort 27 | 28 | [dependency-groups] 29 | dev = [ 30 | "mkdocs-material>=9.5.49", 31 | "mkdocs>=1.6.1", 32 | "pytest>=8.3.4", 33 | "ruff>=0.8.4", 34 | "uv>=0.5.12", 35 | ] 36 | -------------------------------------------------------------------------------- /src/python_project_template/__init__.py: -------------------------------------------------------------------------------- 1 | """A Python Project""" 2 | 3 | __version__ = "0.0.1" 4 | -------------------------------------------------------------------------------- /src/python_project_template/awesome.py: -------------------------------------------------------------------------------- 1 | def do_something_awesome(): 2 | return "Congratulations for taking the first step to build your Python project 🎉" 3 | -------------------------------------------------------------------------------- /src/python_project_template/server.py: -------------------------------------------------------------------------------- 1 | import litserve as ls 2 | 3 | 4 | # (STEP 1) - DEFINE THE API (compound AI system) 5 | class SimpleLitAPI(ls.LitAPI): 6 | def setup(self, device): 7 | # setup is called once at startup. Build a compound AI system (1+ models), connect DBs, load data, etc... 8 | self.model = lambda x: x**2 9 | 10 | def decode_request(self, request): 11 | # Convert the request payload to model input. 12 | return request["input"] 13 | 14 | def predict(self, x): 15 | # Easily build compound systems. Run inference and return the output. 16 | output = self.model(x) 17 | return {"output": output} 18 | 19 | def encode_response(self, output): 20 | # Convert the model output to a response payload. 21 | return {"output": output} 22 | 23 | 24 | # (STEP 2) - START THE SERVER 25 | if __name__ == "__main__": 26 | # scale with advanced features (batching, GPUs, etc...) 27 | server = ls.LitServer(SimpleLitAPI(), accelerator="auto", max_batch_size=1) 28 | server.run(port=8000) 29 | -------------------------------------------------------------------------------- /tests/test_awesome.py: -------------------------------------------------------------------------------- 1 | from python_project_template.awesome import do_something_awesome 2 | 3 | 4 | def test_do_something_awesome(): 5 | assert isinstance(do_something_awesome(), str) 6 | assert do_something_awesome() == "Congratulations for taking the first step to build your Python project 🎉" 7 | --------------------------------------------------------------------------------