โข Planning to develop your first Python third-party package?
โข Troubled bysetuptools
'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.
๐๐ซ๐๐๐ญ๐ข๐๐๐ฅ, ๐๐ง๐ ๐ซ๐๐๐๐ฒ ๐ญ๐จ ๐ ๐จ ๐ฌ๐ญ๐ซ๐๐ข๐ ๐ก๐ญ ๐จ๐ฎ๐ญ ๐จ๐ ๐ญ๐ก๐ ๐๐จ๐ฑ
๐ก Tips
โข We usesetup.cfg
to manage all metadata, and just keep a minimalsetup.py
to ensure editable installation supported.
We provide:
-
A fully configured package-setup file, i.e.,
setup.cfg
orpyproject.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.
- It covers most common config items, allows dynamic access to
-
A complete and concise usage guidance, i.e. the
๐จ Usage
section below. -
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 toPyPI
andTestPyPI
and create a release in your github project according to tag name andCHANGELOG.md
. See theCI/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.
Important
-
In demo below, we assume that your github ID is
me
and project name ismy-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. Whilepyproject.toml
is an officially recommended alternative, I find it more complicated, so I prefersetup.cfg
. But if you really want to usepyproject.toml
, please replace thesetup.cfg
withpyproject.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="[email protected]" }, ] maintainers = [ { name="your-name", email="[email protected]" }, ] 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
-
-
๐ ๐๐ซ๐๐๐ญ๐ ๐ฒ๐จ๐ฎ๐ซ ๐ซ๐๐ฉ๐จ
Press the
Use this template
button next tostar
button at the top of this page,
so as to use this repo as a template to create your repo. -
๐ฅ ๐๐ฅ๐จ๐ง๐ ๐ฒ๐จ๐ฎ๐ซ ๐ซ๐๐ฉ๐จ ๐ญ๐จ ๐ฅ๐จ๐๐๐ฅ ๐ฆ๐๐๐ก๐ข๐ง๐
Find the newly created repo on your GitHub
repositories
page.
Pull it to your machine withgit 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
-
โ๏ธ ๐๐๐ง๐๐ฆ๐ ๐ฉ๐ซ๐จ๐ฃ๐๐๐ญ ๐๐จ๐ฅ๐๐๐ซ
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
-
๐ ๐๐จ๐๐ข๐๐ฒ ๐ญ๐ก๐ ๐๐จ๐ฅ๐ฅ๐จ๐ฐ๐ข๐ง๐ ๐๐ข๐ฅ๐๐ฌ
โ ๐๐๐๐๐.๐๐๐ / ๐๐ข๐๐๐๐๐๐๐.๐๐๐๐ (๐๐๐๐ ๐๐๐๐๐๐๐๐๐)
๐ก Tips
โข If your
README
is inrst
format, you need to replace"text/markdown"
with"text/x-rst"
inlong_description_content_type
(setup.cfg
) orreadme
(pyproject.toml
).โข If you want to create a CLI command for your package, enable
[options.entry_points]
option insetup.cfg
or[project.gui-scripts]
inpyproject.toml
. See more here.โข If you want more configuration, refer to keywords of
setup.cfg
or keywords ofpyproject.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 replaceyour-package
withmy-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.0
โ0.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 documentline 3
:target-version = "py37"
โ"py310"
, replace with your target pythonline 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  ## ๐ 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 theCI/CD via Github Action ๐ค
section below, or refer to Github Actions document<package-name>
โmy-project
-
๐จโ๐ป ๐๐๐ฏ๐๐ฅ๐จ๐ฉ ๐ฒ๐จ๐ฎ๐ซ ๐ฉ๐ซ๐จ๐ฃ๐๐๐ญ
๐ก Tips
โข Cross-module imports can be made via.module-name
ormy-project.module-name
in each module file.โข You can test your code using
python -m my-project.<module-name>
with working directory inMYPROJECT
.โข To develop a command-line tool, add
__main__.py
inmy-project
folder. It defines logit when typingmy-project
in terminal. See more hereFill your logit into
my-project
folder. -
๐ณ ๐๐ฎ๐ข๐ฅ๐ ๐๐ข๐ฌ๐ญ๐ซ๐ข๐๐ฎ๐ญ๐ข๐จ๐ง ๐ฉ๐๐๐ค๐๐ ๐๐ฌ
This step will generate
.tar.gz
source distribution file and.whl
built distribution in a new folder calleddist
.# 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 .
-
๐ ๐๐๐ฅ๐ข๐๐๐ญ๐ ๐ฉ๐๐๐ค๐๐ ๐
โ . ๐ต๐บ๐ ๐๐ฝ๐บ๐๐พ ๐ฝ๐๐๐๐๐๐ป๐๐๐๐๐ ๐๐พ๐๐บ๐ฝ๐บ๐๐บ
# 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.
-
๐ข ๐๐ฎ๐๐ฅ๐ข๐ฌ๐ก ๐ฉ๐๐๐ค๐๐ ๐
โข This step will upload your package to
PyPI
orTestPyPI
.
โข So firstly, you need to register an account withPyPI
orTestPyPI
.
โข Also, don't forget to generate a token for uploading your package. See more here.๐ ๐ฒ๐๐๐๐พ๐๐๐๐๐
You likely have many commits toPyPI
orTestPyPI
to familiarize yourself with the publishing operation. In this case, you can maintain a forgedPyPI
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
andkeyring
to automatically access your token whenever needed. Follow the step in theconfigure .pypirc and keyring ๐
section below.
-
๐ฅณ ๐๐ผ๐ป๐ด๐ฟ๐ฎ๐๐๐น๐ฎ๐๐ถ๐ผ๐ป๐!
โข You have successfully published your package toPyPI
.
โข Now everyone can install it viapip 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 theCI/CD via Github Action ๐ค
section below.
โ ๐๐ข๐๐-๐๐๐๐๐๐ ๐ฅ๏ธ
โข 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 ofpip install
is not always reliable: especially when your package depends on some packages that are only available onPyPI
but not onTestPyPI
.For example, if your package
mp-project
depends onruff
, thenpip install mp-project -i https://test.pypi.org/simple
will fail withResolutionImpossible
orPackage not found
in the process of finding and downloadingruff
, causeruff
is only available onPyPI
.
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)"
.
โ ก ๐ผ๐๐๐ฟ๐๐๐๐๐พ .๐๐ข๐๐๐๐ ๐บ๐๐ฝ ๐๐๐ข๐๐๐๐ ๐
-
Configure
keyring
firstpip 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__
-
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
-
At this point, there is no need to verify your token manually when you upload packages via
twine upload
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:
-
.github/CONTRIBUTING.md
: guide other to make contribution to your project. To change it, refer to link. -
.github/ISSUE_TEMPLATE
: standardize the format ofissue
reporting. Composed ofbug_report.yml
: template for reporting bugs.feature_request.yml
: template for requesting new features.config.yml
: A selector for templates that restricts issue initiation without templates.
๐ก Tips
โข Open theIssue page
in this repo,to see what the template looks like.
โข If you are to change it, refer to link1, link2 and link3. -
.github/PULL_REQUEST_TEMPLATE.md
: standardize the format ofPull 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
ispypi
in PyPI platform, cause we specify it in jobPublish-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 formv*.*.*
, events below will happen:- Build distribution packages, i.e.,
.tar.gz
and.whl
files - Verify meta information of the distribution packages
- Release distribution packages to
PyPI
andTestPyPI
, respectively - Generate release according to tag name and
CHANGELOG.md
- Upload the distribution package to the generated release.
- Build distribution packages, i.e.,
-
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
โข doSettings -> Actions -> General -> Disable actions
in project setting.
- 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
- Ruff document
- Isort document
- Setuptools User Guide
- Official Python Packaging User Guide
- Publishing package using GitHub Actions
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.