Skip to content

Latest commit

 

History

History
744 lines (576 loc) · 34 KB

File metadata and controls

744 lines (576 loc) · 34 KB

📦 A Project Template for Self-developed Python Package

Package Version License Pypi Template

setuptools Ruff Isort

• Planning to develop your first Python third-party package?
• Troubled by setuptools's numerous, complex configurations?
• Unsure about what the structure of a project should be?
𝐓𝐡𝐞𝐧 𝐲𝐨𝐮'𝐯𝐞 𝐜𝐨𝐦𝐞 𝐭𝐨 𝐭𝐡𝐞 𝐫𝐢𝐠𝐡𝐭 𝐩𝐥𝐚𝐜𝐞!

This repo provides an 𝐨𝐮𝐭-𝐨𝐟-𝐭𝐡𝐞-𝐛𝐨𝐱 𝐩𝐫𝐨𝐣𝐞𝐜𝐭 𝐬𝐭𝐫𝐮𝐜𝐭𝐮𝐫𝐞 𝐭𝐞𝐦𝐩𝐥𝐚𝐭𝐞 that accelerates your third-party Python package development.

🎯 Features

𝐏𝐫𝐚𝐜𝐭𝐢𝐜𝐚𝐥, 𝐚𝐧𝐝 𝐫𝐞𝐚𝐝𝐲 𝐭𝐨 𝐠𝐨 𝐬𝐭𝐫𝐚𝐢𝐠𝐡𝐭 𝐨𝐮𝐭 𝐨𝐟 𝐭𝐡𝐞 𝐛𝐨𝐱

💡 Tips
• We use setup.cfg to manage all metadata, and just keep a minimal setup.py to ensure editable installation supported.

We provide:

  1. A fully configured package-setup file, i.e., setup.cfg or pyproject.toml.

    • It covers most common config items, allows dynamic access to version, README, and project dependencies when building.
    • It is well commented, so you don't need to look up documents to understand each item's meaning.
  2. A complete and concise usage guidance, i.e. the 🔨 Usage section below.

  3. CI/CD support: Once a push with a tag is made and the tag matches a template of the form v*.*.*, the CI/CD pipeline will be triggered to build the package, upload it to PyPI and TestPyPI and create a release in your github project according to tag name and CHANGELOG.md. See the CI/CD via Github Action 🤖 section below.

𝐄𝐟𝐟𝐢𝐜𝐢𝐞𝐧𝐭 𝐚𝐧𝐝 𝐩𝐫𝐨𝐟𝐞𝐬𝐬𝐢𝐨𝐧𝐚𝐥

We provide a useful, complete project structure, which
• not only complies with software engineering specifications,
• but also includes all file templates required for a project and continuous deployment(CD) workflows(see the CI/CD via Github Action 🤖 section below).

Here is the detailed structure of the project:

Python-package-template/
├── .github/                      # Store Github Action workflow files and templates of Issue, PR 
│   ├── CONTRIBUTING.md           # Instructions for contributing to project
│   ├── ISSUE_TEMPLATE            # Store Issue template files
│   │   ├── bug_report.yml        # Bug report template
│   │   ├── feature_request.yml   # Feature request template
│   │   └── config.yml            # Template choosing configuration
│   ├── PULL_REQUEST_TEMPLATE.md  # Template for PR description
│   └── workflows                 # Store Github Action workflow files    
│       └── publish_release.yml   # Workflow for publishing and releaseing Python package
|
├── tests/           # Store testing code
│   └── README.md    # Instructions of how to test your code
|
├── docs/            # Store document related files
│   └── README.md    # Instructions of how to build document for your project
|
├── examples/        # Store project demo code
│   └── demo.ipynb   # Demonstration of your project
|
├── package-name/    # Store project code
│   ├── core.py      # Core code
│   └── __init__.py  # Package initialization file, defining copyright, version,and other information
|
├── .gitignore       # File patterns which will be ignored by Git
├── LICENSE          # Project license
├── MANIFEST.in      # Describe the files included or not included in built package
├── CHANGELOG.md     # Project changelog
├── README.md        # Project description
├── requirements.txt # Project dependency
├── ruff.toml        # Define rules for code style, code inspection, and import management
├── packaging.sh     # Package building script
├── check_meta.sh    # Packaging metadata checking script
├── setup.cfg        # Packaging configuration
└── setup.py         # Packaging script
𝐒𝐭𝐚𝐧𝐝𝐚𝐫𝐝 𝐲𝐞𝐭 𝐡𝐢𝐠𝐡𝐥𝐲 𝐜𝐮𝐬𝐭𝐨𝐦𝐢𝐳𝐚𝐛𝐥𝐞
  • We standardize code sytle and quality with the wonderful Python linter and formatter: Ruff.
  • We standardize contributing pipeline with CONTRIBUTING.md to cut communication costs and boost development efficiency.
  • We offer ready-to-use templates for issue, pull requests(PR), and package publishing workflows, complete with modifications and usage instructions to help you customize them effectively.

🔨 Usage

Important

  • In demo below, we assume that your github ID is me and project name is my-project.
    ❗️❗️❗️ Remember to replace them with your own ID and project name when using ❗️❗️❗️

  • This template uses setup.cfg to manage all metadata by default. While pyproject.toml is an officially recommended alternative, I find it more complicated, so I prefer setup.cfg. But if you really want to use pyproject.toml, please replace the setup.cfg with pyproject.toml below. Of course, you can download it directly here.

    • 𝚙𝚢𝚙𝚛𝚘𝚓𝚎𝚌𝚝.𝚝𝚘𝚖𝚕
      # refer to https://packaging.python.org/en/latest/guides/writing-pyproject-toml
      # See https://docs.astral.sh/ruff/settings for configuring ruff
      
      [build-system]  # define build backend and dependencies needed to build your project
      requires = ["setuptools>=66.0", "cython", "wheel", "isort", "ruff"]           # dependencies needed to build your project
      build-backend = "setuptools.build_meta"                             # build backend
      
      [project] # define metadata of your project
      
      # ---------------- Dynamic info ----------------
      dynamic = ["version","dependencies"]                                # dynamic info will be filled in by the build backend
      
      # ---------------- Basic info ----------------
      name = "your-package"                                               # package name
      authors = [
        { name="your-name", email="your-email@mail.com" }, 
      ]
      maintainers = [
        { name="your-name", email="your-email@mail.com" }, 
      ]
      description = "Package test"                             # one-line description of your project
      readme = {file = "README.md", content-type = "text/markdown"}       # specify README file
      
      # ---------------- Dependency info ----------------
      requires-python = ">=3.7"                                           # Python version requirement
      
      # ---------------- Other ----------------
      keywords = ["A","B","c"]      # keywords of your project, will help to suggest your project when people search for these keywords.
      classifiers = [               # Trove classifiers, Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
        "Development Status :: 4 - Beta",
        "Intended Audience :: Developers",
        "Topic :: Software Development :: Build Tools",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
      ]
      
      # ---------------- Optional dependency ----------------
      [project.optional-dependencies] 
      docs = ["sphinx>=7.0.0"]
      
      test = [
        "pytest", 
        "pytest-sugar"]
      
      cli = [
        "rich",
        "click",
      ]
      
      # Install a command as part of your package
      [project.gui-scripts]                           # use [project.gui-scripts] to compatiable with differernt system   
      your-package = "your-package.cli:app"           # command = package:func
      
      
      # URLs associated with your project
      [project.urls]
      Homepage = "https://github.com/your-name/your-package"                    
      Repository = "https://github.com/your-name/your-package.git" 
      Issues = "https://github.com/your-name/your-package/issues" 
      Changelog = "https://github.com/your-name/your-package/blob/master/CHANGELOG.md"
      
      [tool.setuptools.dynamic]
      version = {attr = "your-package.__version__"}  # automatically obtain the value by `my_package.__version__`.
      dependencies = {file = ["requirements.txt", "requirement.txt", > "requirement"]}
      
      # -------------------------------- Tools Setting --------------------------------
      [tool.setuptools]
      license-files = ['LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*']  # specify License files
      
      [tool.setuptools.packages]
      find = {}  # Scan the project directory with the default parameters
      
      [tool.ruff]
      # Allow lines to be as long as 120.
      line-length = 120
      
      [tool.ruff.format]
      # Enable reformatting of code snippets in docstrings.
      docstring-code-format = true
      
      [tool.ruff.lint]
      # Skip unused variable rules
      ignore = [
          "ANN101",  # Missing type annotation for `self` in method
          "ANN102",  # Missing type annotation for `cls` in classmethod
          "ANN401",  # Dynamically typed expressions (typing.Any) are disallowed
          "C901",    # function is too complex (12 > 10)
          "COM812",  # Trailing comma missing
          "D",       # Docstring rules
          "EM101",   # Exception must not use a string literal, assign to variable first
          "EM102",   # Exception must not use an f-string literal, assign to variable first
          "ERA001",  # Found commented-out code
          "FBT001",  # Boolean positional arg in function definition
          "FBT002",  # Boolean default value in function definition
          "FBT003",  # Boolean positional value in function call
          "FIX002",  # Line contains TODO
          "ISC001",  # Isort
          "PLR0911", # Too many return statements (11 > 6)
          "PLR2004", # Magic value used in comparison, consider replacing 2 with a constant variable
          "PLR0912", # Too many branches
          "PLR0913", # Too many arguments to function call
          "PLR0915", # Too many statements
          "S101",    # Use of `assert` detected
          "S311",    # Standard pseudo-random generators are not suitable for cryptographic purposes
          "T201",    # print() found
          "T203",    # pprint() found
          "TD002",   # Missing author in TODO; try: `# TODO(<author_name>): ...`
          "TD003",   # Missing issue link on the line following this TODO
          "TD005",   # Missing issue description after `TODO`
          "TRY003",  # Avoid specifying long messages outside the exception class
          "PLW2901", # `for` loop variable `name` overwritten by assignment target
          "SLF001",  # Private member accessed: `_modules`
      ]
      
      [tool.ruff.lint.isort]
      length-sort = true                              # sort imports by their string length
      combine-as-imports = true                       # combines as imports on the same line
      known-first-party = ["your-package"]
      lines-after-imports = 1                         # Use a single line after each import block.
      single-line-exclusions = ["os", "json", "re"]   # modules to exclude from the single line rule
  1. 🚀 𝐂𝐫𝐞𝐚𝐭𝐞 𝐲𝐨𝐮𝐫 𝐫𝐞𝐩𝐨

    Press the Use this template button next to star button at the top of this page,
    so as to use this repo as a template to create your repo.

  2. 📥 𝐂𝐥𝐨𝐧𝐞 𝐲𝐨𝐮𝐫 𝐫𝐞𝐩𝐨 𝐭𝐨 𝐥𝐨𝐜𝐚𝐥 𝐦𝐚𝐜𝐡𝐢𝐧𝐞

    Find the newly created repo on your GitHub repositories page.
    Pull it to your machine with git clone.

    # replace 'me' with your github ID, 
    # 'my-project' with your project name, 
    # and `MYPROJECT` with your local project folder name
    git clone https://github.com/me/my-project MYPROJECT
  3. ✏️ 𝐑𝐞𝐧𝐚𝐦𝐞 𝐩𝐫𝐨𝐣𝐞𝐜𝐭 𝐟𝐨𝐥𝐝𝐞𝐫
    cd MYPROJECT
    
    # replace 'my-project' with your project name
    git mv package-name my-project
    𝘯𝘰𝘸 𝘺𝘰𝘶𝘳 𝘱𝘳𝘰𝘫𝘦𝘤𝘵 𝘴𝘵𝘳𝘶𝘤𝘵𝘶𝘳𝘦 𝘴𝘩𝘰𝘶𝘭𝘥 𝘣𝘦 𝘭𝘪𝘬𝘦 𝘵𝘩𝘪𝘴
    # Note: 
    # the directory structure below neglects the `.github` dir
    
    MYPROJECT/
    ├── tests/ 
    │   └── README.md     
    |      
    ├── docs/   
    │   └── README.md    
    |            
    ├── examples/  
    │   └── demo.ipynb    
    |         
    ├── my-project/    
    │   ├── core.py      
    │   └── __init__.py   
    |
    ├── .gitignore   
    ├── LICENSE          
    ├── MANIFEST.in     
    ├── CHANGELOG.md     
    ├── README.md        
    ├── requirements.txt 
    ├── ruff.toml       
    ├── packaging.sh     
    ├── check_meta.sh    
    ├── setup.cfg        
    └── setup.py         
    
  4. 📄 𝐌𝐨𝐝𝐢𝐟𝐲 𝐭𝐡𝐞 𝐟𝐨𝐥𝐥𝐨𝐰𝐢𝐧𝐠 𝐟𝐢𝐥𝐞𝐬
    ① 𝚜𝚎𝚝𝚞𝚙.𝚌𝚏𝚐 / 𝚙𝚢𝚙𝚛𝚘𝚓𝚎𝚌𝚝.𝚝𝚘𝚖𝚕 (𝚖𝚘𝚜𝚝 𝚒𝚖𝚙𝚘𝚛𝚝𝚊𝚗𝚝)

    💡 Tips

    • If your README is in rst format, you need to replace "text/markdown" with "text/x-rst" in long_description_content_type(setup.cfg) or readme(pyproject.toml).

    • If you want to create a CLI command for your package, enable [options.entry_points] option in setup.cfg or [project.gui-scripts] in pyproject.toml. See more here.

    • If you want more configuration, refer to keywords of setup.cfg or keywords of pyproject.toml

    Look for the following variables in setup.cfg and modify as per comments.

    Basic Requirement related Package structure related
    name python_requires packages
    version install_requires include_package_data
    author exclude
    author_email [options.extras_require]
    description
    long_description
    url
    keywords
    license
    classifiers

    If you are using pyproject.toml, you may need to replace your-package with my-package in the file we provided first, then check out and modify following variables.

    Basic Requirement related Package structure related
    name requires find
    version requires-python
    authors [project.optional-dependencies]
    maintainers
    description
    readme
    [project.urls]
    keywords
    classifiers
    ② 𝚖𝚢-𝚙𝚛𝚘𝚓𝚎𝚌𝚝/__𝚒𝚗𝚒𝚝__.𝚙𝚢
    • line 2: <your-name>me, replace with your github ID
    • replace <license-name> with your license name
    • replace <full_text-url-of-license-terms> with your license url, attain it from choosealicense.com
    • line 8: 0.1.00.0.1, replace with your project initial version
    ③ 𝚛𝚞𝚏𝚏.𝚝𝚘𝚖𝚕

    • Here show the common change of ruff.toml
    • With comments in the file, you can modify everything as needed.
    • If you want more configuration, refer to Ruff document

    • line 3: target-version = "py37""py310", replace with your target python
    • line 46: known-first-party = ["<your_package_name>"]["my-project"], replace with your project name
    ④ 𝚛𝚎𝚚𝚞𝚒𝚛𝚎𝚖𝚎𝚗𝚝𝚜.𝚝𝚡𝚝

    Here is an example, change it with the concrete dependencies that your project actually uses.

    setuptools
    isort
    ruff
    opencv-python
    tqdm
    
    ⑤ 𝚁𝙴𝙰𝙳𝙼𝙴.𝚖𝚍

    Here is an example, change it with your project description.

    # 🧐 my-project
    
    ![Static Badge](https://img.shields.io/badge/Version-v0.0.1-green)
    
    ## 👋 Introduction
    
    This is my first Python package called `my-project`.
    
    ## 📦 Getting Started
    
    Install the package with pip: `pip install my-project`
    
    ## 📄 License
    
    This project is licensed under the MIT License, 
    see the [LICENSE.md](LICENSE.md) for details
    
    ## 💖 Acknowledge
    
    Thanks for John for his help.
    ⑥ 𝙻𝚒𝚌𝚎𝚗𝚜𝚎

    Default license is MIT, you can change it to other.
    See https://choosealicense.com/licenses/

    line 3: Copyright (c) <YEAR> <COPYRIGHT HOLDER>
    ↓
    line 3: Copyright (c) 2024 me
    
    ⑦ .𝚐𝚒𝚝𝚑𝚞𝚋/𝚠𝚘𝚛𝚔𝚏𝚕𝚘𝚠𝚜/𝚙𝚞𝚋𝚕𝚒𝚜𝚑_𝚛𝚎𝚕𝚎𝚊𝚜𝚎.𝚢𝚖𝚕

    • Change this file to use Github Actions for package publication.
    • If you want to change the preset workflow, see the CI/CD via Github Action 🤖 section below, or refer to Github Actions document

    • <package-name>my-project
  5. 👨‍💻 𝐃𝐞𝐯𝐞𝐥𝐨𝐩 𝐲𝐨𝐮𝐫 𝐩𝐫𝐨𝐣𝐞𝐜𝐭

    💡 Tips
    • Cross-module imports can be made via .module-name or my-project.module-name in each module file.

    • You can test your code using python -m my-project.<module-name> with working directory in MYPROJECT.

    • To develop a command-line tool, add __main__.py in my-project folder. It defines logit when typing my-project in terminal. See more here

    Fill your logit into my-project folder.

  6. 🗳 𝐁𝐮𝐢𝐥𝐝 𝐝𝐢𝐬𝐭𝐫𝐢𝐛𝐮𝐭𝐢𝐨𝐧 𝐩𝐚𝐜𝐤𝐚𝐠𝐞𝐬

    This step will generate .tar.gz source distribution file and .whl built distribution in a new folder called dist .

    # pwd: .../MYPROJECT
    chmod +x packaging.sh
    
    # Assume you are using anaconda to manage your python environment
    ./packaging.sh
    
    # Otherwise, activate your environment and execute following command
    python -m build -v -n .
  7. 🔍 𝐕𝐚𝐥𝐢𝐝𝐚𝐭𝐞 𝐩𝐚𝐜𝐤𝐚𝐠𝐞

    ①. 𝖵𝖺𝗅𝗂𝖽𝖺𝗍𝖾 𝖽𝗂𝗌𝗍𝗋𝗂𝖻𝗎𝗍𝗂𝗈𝗇 𝗆𝖾𝗍𝖺𝖽𝖺𝗍𝖺

    # pwd: .../MYPROJECT
    pip install twine
    
    chmod +x check_meta.sh
    ./check_meta.sh

    ②. 𝖵𝖺𝗅𝗂𝖽𝖺𝗍𝖾 𝖬𝖠𝖭𝖨𝖥𝖤𝖲𝖳.𝗂𝗇 𝗂𝖿 𝗒𝗈𝗎 𝗁𝖺𝗏𝖾 𝗍𝗁𝗂𝗌 𝖿𝗂𝗅𝖾.

    # pwd: .../MYPROJECT
    pip install check-manifest
    
    # command below will automatically add missing file patterns to MANIFEST.in.
    check-manifest -u -v

    ③. (𝖮𝗉𝗍𝗂𝗈𝗇) 𝖵𝖺𝗅𝗂𝖽𝖺𝗍𝖾 𝗉𝖺𝖼𝗄𝖺𝗀𝖾 𝖿𝗎𝗇𝖼𝗍𝗂𝗈𝗇𝗌

    # pwd: .../MYPROJECT
    pip install dist/*.whl
    
    # then test your package to see whether it works well.
    # this is suggested if you have create a CLI tool for your package.
  8. 📢 𝐏𝐮𝐛𝐥𝐢𝐬𝐡 𝐩𝐚𝐜𝐤𝐚𝐠𝐞

    • This step will upload your package to PyPI or TestPyPI.
    • So firstly, you need to register an account with PyPI or TestPyPI.
    • Also, don't forget to generate a token for uploading your package. See more here.

    📋 𝖲𝗎𝗀𝗀𝖾𝗌𝗍𝗂𝗈𝗇
    You likely have many commits to PyPI or TestPyPI to familiarize yourself with the publishing operation. In this case, you can maintain a forged PyPI server locally, see the 🧰 Tools Recommended -> pypi-server section below.

    # pwd: .../MYPROJECT
    
    # (Option but strongly recommended) upload to testpypi firstly to see if anywhere wrong
    twine upload --repository testpypi dist/* 
    
    # upload to pypi
    # then everyone can install your package via `pip install my-project`
    twine upload --repository pypi dist/* 

    After executing command above, you will be asked to enter your account token.

    • Sure, you can paste your token in terminal to go through the process.

    • But if you are tired of doing this, you can use .pypirc and keyring to automatically access your token whenever needed. Follow the step in the configure .pypirc and keyring 🔐 section below.


🥳 𝗖𝗼𝗻𝗴𝗿𝗮𝘁𝘂𝗹𝗮𝘁𝗶𝗼𝗻𝘀!
• You have successfully published your package to PyPI.
• Now everyone can install it via pip install my-project
• To update your package to a new version, you have two choices:
① Manually update: repeat steps 5 to 8 above.
② CI/CD workflow(recommended): see the CI/CD via Github Action 🤖 section below.

🧰 Tools Recommended

Ⅰ 𝚙𝚢𝚙𝚒-𝚜𝚎𝚛𝚟𝚎𝚛 🖥️

What is it: A simple PyPI server for local use.
Highly recommended if you are testing your CI/CD workflow.

You likely have many commits to PyPI or TestPyPI to familiarize yourself with publishing process. Then there exists two problems:

TestPyPI / PyPI project size limit: many commits can exceed project size limit.

• Using TestPyPI as the index of pip install is not always reliable: especially when your package depends on some packages that are only available on PyPI but not on TestPyPI.

For example, if your package mp-project depends on ruff, then pip install mp-project -i https://test.pypi.org/simple will fail with ResolutionImpossible or Package not found in the process of finding and downloading ruff, cause ruff is only available on PyPI.

To solve these problems and fully imitate the bahvior of normal pip install using PyPI index. You can deploy a local PyPI server with pypi-server.

Here is a quick guide to get started, please check pypiserver's repo for more details.

pip install pypiserver 

mkdir Path/to/store/packages  # path to store distribution packages

pypi-server run \
-i 0.0.0.0 \
-p <port> \                  # specify a port to listen
<path-to-store>/.pypiserver_pkgs\
-a . -P . &                  # disable authentication for intranet use

cat >~/.pypirc<<EOF          # add local server to .pypirc
[distutils]
index-servers =
    pypi
    testpypi
    local

[pypi]
repository: https://upload.pypi.org/legacy/

[testpypi]
repository: https://test.pypi.org/legacy/

[local]
    repository: http://0.0.0.0:7418
    username: none          # random string, not important
    password: none          # random string, not important
EOF

OK, then we can use commands below to upload and install packages:

# pwd: .../package project dir

# upload package to local server
twine upload --repository local dist/*

# install package from local server
pip install <package> \
--trusted-host \
--extra-index-url http://0.0.0.0:<port>/simple/ 

❗️❗️❗️ If you want to close the server, using kill -9 "$(pgrep pypi-server)".

Ⅱ 𝖼𝗈𝗇𝖿𝗂𝗀𝗎𝗋𝖾 .𝚙𝚢𝚙𝚒𝚛𝚌 𝖺𝗇𝖽 𝚔𝚎𝚢𝚛𝚒𝚗𝚐 🔐
  1. Configure keyring first

    pip install keyring keyrings.alt
    
    # if you are on Linux, execute commands below additionally.
    cat >"$(keyring diagnose | grep "config path:" | cut -d' ' -f3)"<<EOF
    [backend]
    default-keyring=keyrings.alt.file.PlaintextKeyring
    EOF
    
    # encrypt your pypi token 
    ## pypi
    keyring set https://upload.pypi.org/legacy/ __token__
    
    ## enter your pypi token when prompted
    
    # verify that the encrypted token has been stored
    keyring get https://upload.pypi.org/legacy/ __token__ 
    
    # ------------------------ same for testpypi ------------------------
    
    ## testpypi
    keyring set https://test.pypi.org/legacy/ __token__
    
    ## enter your pypi token when prompted
    
    # verify that the encrypted token has been stored
    keyring get https://test.pypi.org/legacy/ __token__
  2. Configure .pypirc

    # refer to https://packaging.python.org/en/latest/specifications/pypirc/
    cat >~/.pypirc<<EOF
    [distutils]
    index-servers =
        pypi
        testpypi
    
    [pypi]
    repository = https://upload.pypi.org/legacy/
    
    [testpypi]
    repository = https://test.pypi.org/legacy/
    EOF
    
    chmod 600 ~/.pypirc
  3. At this point, there is no need to verify your token manually when you upload packages via twine upload

🗃 Project Management

This section emphasizes the effective management of your project on GitHub.

Ⅰ 𝐒𝐭𝐚𝐧𝐝𝐚𝐫𝐝𝐢𝐳𝐞𝐝 𝐜𝐨𝐧𝐭𝐫𝐢𝐛𝐮𝐭𝐢𝐨𝐧 𝐩𝐫𝐨𝐜𝐞𝐬𝐬 💼

Standardizing project participation cuts communication costs and boosts development efficiency. This mainly focus on the files below:

  1. .github/CONTRIBUTING.md : guide other to make contribution to your project. To change it, refer to link.

  2. .github/ISSUE_TEMPLATE : standardize the format of issue reporting. Composed of

    💡 Tips
    • Open the Issue page in this repo,to see what the template looks like.
    • If you are to change it, refer to link1, link2 and link3.

  3. .github/PULL_REQUEST_TEMPLATE.md : standardize the format of Pull Request. To change it, refer to link.

Ⅱ 𝐂𝐈/𝐂𝐃 𝐯𝐢𝐚 𝐆𝐢𝐭𝐡𝐮𝐛 𝐀𝐜𝐭𝐢𝐨𝐧 🤖

⚠️⚠️⚠️
• Due to the need of publishing to PyPI and TestPypi, trusted publishers of two platform needs to be configured first before use. Following tutorial 1 and tutorial 2 to make it.

NOTE: The Environment name item in configuration should be the same as what you specify in the workflow file.

For example, in the provided publish_release.yml, the Environment name is pypi in PyPI platform, cause we specify it in job Publish-PyPI.environment.name.

  • By creating a .yml file under the .github/workflows/ directory, CI/CD support for the project can be achieved.

  • In this template repo, the automation of steps 6 to 8 in 🔨 Usage section is implemented. Once a push with a tag is made and the tag matches a template of the form v*.*.*, events below will happen:

    1. Build distribution packages, i.e., .tar.gz and .whl files
    2. Verify meta information of the distribution packages
    3. Release distribution packages to PyPI and TestPyPI, respectively
    4. Generate release according to tag name and CHANGELOG.md
    5. Upload the distribution package to the generated release.
  • If you are to change the task flows, please see Github Actions document for more details.

❗️❗️❗️
If you want to disable the CI/CD feature, there are two options:
• delete the .github/workflows/ directory
• do Settings -> Actions -> General -> Disable actions in project setting.

📑 To Do

  • Add full pipeline of package development, from project preparation to maintaining.
  • Add CI/CD support, such as GitHub Actions
  • Add pyproject.toml support
  • Add linter

👀 See More

🧾 License

This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.