Skip to content

Instantly share code, notes, and snippets.

@MansourM61
Last active January 17, 2026 19:21
Show Gist options
  • Select an option

  • Save MansourM61/2f6aa3f0ee07431595ef31ec3585a1e5 to your computer and use it in GitHub Desktop.

Select an option

Save MansourM61/2f6aa3f0ee07431595ef31ec3585a1e5 to your computer and use it in GitHub Desktop.

Python Project Setup

Install UV

UNIX OS

To install:

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows OS

To install:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

env Activation

The Python environment will be automatically activated. However, in case needed:

# on Windows
.venv\Scripts\activate

# on UNIX
source .venv/bin/activate

VSCode Settings

  1. Add .vscode/extensions.json with the following contents:

    {
      "recommendations": [
        "njpwerner.autodocstring",
        "ms-python.autopep8",
        "ms-python.black-formatter",
        "ms-python.flake8",
        "ms-python.isort",
        "ms-python.vscode-pylance",
        "ms-python.python",
        "ms-python.debugpy",
        "ms-python.vscode-python-envs",
        "LeoJhonSong.python-extension-pack",
        "KevinRose.vsc-python-indent",
        "mgesbert.python-path",
        "charliermarsh.ruff",
        "esbenp.prettier-vscode",
        "ms-vscode.test-adapter-converter",
        "hbenl.vscode-test-explorer"
      ]
    }
  2. Add .vscode/settings.json with the following contents:

        "[python]": {
            "editor.defaultFormatter": "ms-python.autopep8"
        },
        "python.analysis.typeCheckingMode": "standard"

Project Setup

  1. Create the root directory.

  2. In the root directory, run:

    uv init
  3. To add a new package:

    uv add <package_name>
  4. To remove a package:

    uv remove <package_name>
  5. Install the following dependencies:

    uv add mkdocs mike mkdocs-gen-files mkdocs-graphviz mkdocs-literate-nav mkdocs-material mkdocs-section-index mkdocs-swagger-ui-tag mkdocstrings mkdocstrings-python mypy
  6. Install make. On UNIX it is already installed. For windows, use this link.

  7. Create Makefile in the project root directory:

    sync:
        uv sync
    
    upgrade:
        uv sync --upgrade
    
    check:
        mypy src
    
    verify:
        uvx ty check
    
    devel:
        uv run run.py
    
    prod:
        uv run src/main_prod.py
    
    gen-docs:
        mkdocs build -f mkdocs.yml
    
    run-docs:
        mkdocs serve -f mkdocs.yml -a localhost:8001
    
    test-all:
        uv run -m unittest discover

Code Structure

Create a hierarchy similar to the following:

Root
│
...
├───src
│   ├───lib
│   │   ├───__init__.py
│   │   ...
│   ...
│   │
│   ├───__init__.py
│   ├───__main__.py
│   ├───main_dev.py
│   └───main_prod.py
└───run.py

The contents of each file is based on the following templates:

./run.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Application runner

This file is only intended for debugging purposes.
The module in `src` folder cannot be directly executed in debug mode.
Therefore, this script is created to fix that. Particularly in VSCode IDE,
this file can be used as the start point for debugging.
"""
from src import main_dev


main_dev.Main()

src/__init__.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Main entry"""

# add contents as needed

The same template for src/__init__.py will be used when a subfolder within src folder is created and populated with Python codes. This way the Python codes are treated as packages and can be imported into the file using:

import src.lib.module_file.method_name

# ...

a = src.lib.module_file.method_name()

or

from src.lib.module_file import method_name

# ...

a = method_name()

or

from src.lib import module_file

# ...
a = module_file.method_name()

src/__main__.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Main entrance to the module

The sole purpose of this module is to call the 'Main' function and run
the module.
"""
from src import main_dev


if __name__ == "__main__":
    main_dev.Main()

src/main_dev.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Main entry point (development mode).


This module is the entry point to run the code in development mode.


Example:
    To run the code from this module, simply run the following line in the
    command line from the project root directory::


        $ python -m src.main_dev


    Project root directory is where you can see **src** as a subdirectory.
"""
# ...

def Main():
    # code for development mode
    # ...


if __name__ == "__main__":
    Main()

src/main_prod.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Main entry point (production mode).


This module is the entry point to run the code in production mode.
"""
# ...


def Main():
    print("I am in the production mode")


if __name__ == "__main__":
    Main()

For any new file to be added within the src folder, use the following template.

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""Docstring documentation"""

def my_func(
    par1: par1_type,
) -> return_type:
    """Summary of the function

    Args:
        par1 (par1_type): parameter 1 description

    Returns:
        return_type: return type description
    """

# Add these lines at the end to ensure the files are not independently executed
if __name__ == '__main__':
    print("This module is supposed to be called by other modules!")

Test Code

  1. Create a tests folder.

  2. Add tests/__init__.py file using the template.

  3. Create the test file with the name starting with test_.

    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    # test_myfunc.py
    """Test generated data model"""
    
    
    import unittest
    import src.lib.test_module as tu
    
    
    class TestDataModel(unittest.TestCase):
    
        def setUp(self):
            # perform any required preparation
            print("Test setup")
            pass
    
        def tearDown(self):
            # perform any required cleanup
            print("Test cleanup")
            pass
    
        def test_DataTable_class_is_valid(self):
            self.assertIsNone(tu.my_func())
    
    
    if __name__ == '__main__':
        unittest.main()
  4. To run the test file:

    uv run -m unittest tests\test_myfunc.py
  5. To run all tests:

    make test-all

Documentation

  1. Create mkdocs.yml in the project root folder:

    site_name: PROJECT NAME
    site_description: DESCRIPTION OF WHAT THE PROJECT DOES
    site_author: Mojtaba Mansour Abadi
    repo_url: https://github.com/squidfunk/mkdocs-material
    repo_name: squidfunk/mkdocs-material
    
    nav:
    - Getting Started: Index.md
    - Customisation: ReadMe.md
    - Code Reference: reference/Summary.md
    - Swagger Documentation: swagger-doc.md
    
    copyright: |
    Copyright &copy; 2025 Mojtaba Mansour Abadi
    
    extra:
    social:
        - icon: fontawesome/brands/github
        link: https://github.com/MansourM61
        - icon: fontawesome/brands/linkedin
        link: https://www.linkedin.com/in/mojtaba-mansour-abadi-4311b451/
    generator: true
    
    # ######################################
    # MkDocs configurations
    theme:
    logo: img/favicon.png
    favicon: img/favicon.ico
    name: material
    color_mode: auto
    user_color_mode_toggle: true
    locale: en
    language: en
    features:
        - navigation.instant
        - navigation.instant.prefetch
        - navigation.instant.preview
        - navigation.tabs
        - navigation.tabs.sticky
        - navigation.sections
        - navigation.expand
        - navigation.path
        - navigation.indexes
        - navigation.top
        - search.suggest
        - search.highlight
        - search.share
        - header.autohide
        - navigation.footer
        - content.tabs.link
        - content.code.annotation
        - content.code.copy
        # - toc.integrate
    icon:
        repo: fontawesome/brands/git-alt
    
    palette:
        # Palette toggle for automatic mode
        - media: "(prefers-color-scheme)"
        toggle:
            icon: material/brightness-auto
            name: Switch to light mode
    
        # Palette toggle for light mode
        - media: "(prefers-color-scheme: light)"
        scheme: default
        toggle:
            icon: material/brightness-7
            name: Switch to dark mode
    
        # Palette toggle for dark mode
        - media: "(prefers-color-scheme: dark)"
        scheme: slate
        toggle:
            icon: material/brightness-4
            name: Switch to system preference
    
    plugins:
    - offline
    - tags
    - search
    - section-index
    - swagger-ui-tag
    
    - gen-files:
        scripts:
            - tools/gen_ref_pages.py
    
    - literate-nav:
        nav_file: SUMMARY.md
    
    - mkdocstrings:
        default_handler: python
        handlers:
            python:
            paths: [src]
            options:
                docstring_style: google
            # inventories:
            #   - https://docs.python.org/3/objects.inv
    
    - termynal:
        prompt_literal_start:
            - "$"
            - ">"
    
    markdown_extensions:
    - admonition # Admonitions
    - attr_list # Annotations, Grids, Buttons
    - md_in_html
    - tables # Data tables
    - footnotes # Footnotes
    - abbr # Abbreviations
    - def_list # Lists
    - toc:
        permalink: true
    
    - pymdownx.details # Admonitions
    - pymdownx.superfences: # Annotations, Diagrams
        custom_fences:
            - name: mermaid
            class: mermaid
            format: !!python/name:pymdownx.superfences.fence_code_format
    - pymdownx.inlinehilite # Code blocks
    - pymdownx.snippets # Tooltips
    - pymdownx.highlight:
        anchor_linenums: true
        line_spans: __span
        pygments_lang_class: true
    - pymdownx.tabbed: # Content tabs
        alternate_style: true
    - pymdownx.critic # Formatting
    - pymdownx.caret
    - pymdownx.keys
    - pymdownx.mark
    - pymdownx.tilde
    - pymdownx.arithmatex: # Math
        generic: true
    - pymdownx.betterem:
        smart_enable: all
    - pymdownx.emoji: # Icons, Emojis
        emoji_index: !!python/name:material.extensions.emoji.twemoji
        emoji_generator: !!python/name:material.extensions.emoji.to_svg
    - pymdownx.tasklist: # Lists
        custom_checkbox: true
    - pymdownx.smartsymbols
    - pymdownx.blocks.caption # Images
    - mkdocs_graphviz # Graphviz
    
    extra_javascript: # Math, Graphviz
    - javascripts/mathjax.js
    - https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js
    - https://cdn.jsdelivr.net/gh/rod2ik/cdn@main/mkdocs/javascripts/mkdocs-graphviz.js
    
    extra_css:
    - https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.43.0/swagger-ui.css
  2. Create doc folder with the following markdown files:

    1. Index.md: getting started file
    2. ReadMe.md: customisation file
  3. Create doc/swagger-doc.md file:

    <swagger-ui src="openapi.json"/>
    
    Swagger documentation is generated using [MkDocs Swagger UI Tag plugin](https://github.com/blueswen/mkdocs-swagger-ui-tag).

    You also need to copy the generate OpenAPI json file to doc/openapi.json

  4. Add the icon file doc/img/favicon.ico and tje logo file doc/img/favicon.png.

  5. To generate the documentation:

    make gen-docs
  6. To start the documentation server on port 8001:

    make run-docs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment