Last active
September 5, 2025 15:04
-
-
Save niftycode/fd1442c624798c5f2773db0b443827cc to your computer and use it in GitHub Desktop.
Shell script to create a Python project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash - | |
#=============================================================================== | |
# | |
# FILE: createPythonProject.sh | |
# | |
# USAGE: ./createPythonProject.sh | |
# | |
# DESCRIPTION: Create a new Python project | |
# | |
# VERSION: 2.2 | |
# REQUIREMENTS: --- | |
# BUGS: --- | |
# NOTES: This script creates a pyproject.toml. In addition, the configuration | |
# file logging.ini is created for the logging module. | |
# | |
# AUTHOR: @niftycode | |
# ORGANIZATION: | |
# CREATED: December 10th, 2021 | |
# REVISION: September 5th, 2025 | |
#=============================================================================== | |
set -o nounset # Treat unset variables as an error | |
echo "Enter a project name:" | |
read name | |
mkdir $name | |
cd $name | |
# Create the subfolders 'docs' and 'tests' | |
mkdir docs | |
mkdir tests | |
# Create __init__.py file in the 'tests' folder | |
cd tests | |
touch __init__.py | |
cd .. | |
# Create pyproject.toml file | |
cat > pyproject.toml << EOF | |
[build-system] | |
requires = ["setuptools>=70.0"] | |
build-backend = "setuptools.build_meta" | |
[project] | |
name = "$name" | |
version = "0.1.0" | |
description = "Project description" | |
readme = "README.md" | |
requires-python = ">=3.12" | |
license = { text = "MIT" } | |
authors = [ | |
{ name = "Your Name", email = "[email protected]" } | |
] | |
urls = {"Homepage" = "https://github.com/username/project_name"} | |
classifiers = [ | |
"License :: OSI Approved :: MIT License", | |
"Operating System :: OS Independent", | |
"Programming Language :: Python :: 3", | |
"Programming Language :: Python :: 3.12", | |
"Programming Language :: Python :: 3.13", | |
"Programming Language :: Python :: Implementation :: CPython" | |
] | |
dependencies = [] | |
[project.scripts] | |
$name = "src.main:main" | |
[tool.setuptools] | |
zip-safe = false | |
packages = { find = { exclude = ["tests"] } } | |
EOF | |
# Create requirements.txt file | |
cat > requirements.txt << EOF | |
setuptools | |
wheel | |
build | |
flake8 | |
black | |
mypy | |
pytest | |
pytest-cov | |
EOF | |
# Create .flake8 file | |
cat > .flake8 << EOF | |
[flake8] | |
extend-ignore = E203, W503 | |
max-line-length = 120 | |
exclude = | |
.git, | |
__pycache__, | |
docs/source/conf.py, | |
build, | |
dist | |
max-complexity = 10 | |
EOF | |
# Create logging.ini | |
cat > logging.ini << EOF | |
[loggers] | |
keys=root | |
[handlers] | |
keys=stream_handler | |
[formatters] | |
keys=formatter | |
[logger_root] | |
level=DEBUG | |
handlers=stream_handler | |
[handler_stream_handler] | |
class=StreamHandler | |
level=DEBUG | |
formatter=formatter | |
args=(sys.stderr,) | |
[formatter_formatter] | |
format=%(asctime)s %(name)-12s %(levelname)-8s %(message)s | |
EOF | |
# Create empty Changelog and Contributing files | |
touch Changelog.md | |
touch CONTRIBUTING.md | |
# Create Readme file | |
cat > README.md << EOF | |
# $name | |
EOF | |
# Create .gitignore file | |
cat > .gitignore << EOF | |
############################# | |
#### Configuration Files #### | |
############################# | |
.DS_Store | |
.vscode | |
.idea | |
.fleet | |
############################# | |
### Build Files & Folders ### | |
############################# | |
dist/ | |
build/ | |
wheels/ | |
*.egg-info/ | |
__pycache__/ | |
############################# | |
### venv & Code Coverage #### | |
############################# | |
.venv/ | |
.coverage | |
/htmlcov | |
############################# | |
############ uv ############# | |
############################# | |
.python-version | |
uv.lock | |
############################# | |
########### Misc ############ | |
############################# | |
.mypy_cache | |
.pytest_cache | |
EOF | |
# Create subfolder with the name of the project and | |
# create __init__.py and main.py file | |
echo | |
read -p "Should the project directory be named 'src'? (Y/n)" dir_name | |
dir_name=${dir_name:-Y} | |
if [ $dir_name = "Y" ] | |
then | |
mkdir src | |
echo "[+] src created" | |
cd src | |
else | |
mkdir $name | |
echo "[+] $name created" | |
cd $name | |
fi | |
touch __init__.py | |
month=$(date "+%B") | |
day=$(date "+%d") | |
year=$(date "+%Y") | |
# Create main.py file | |
cat > main.py << EOF | |
#!/usr/bin/env python3 | |
""" | |
Description goes here... | |
Version: 1.0 | |
Python 3.12+ | |
Date created: $month $day, $year | |
Date modified: - | |
""" | |
import logging | |
from logging.config import fileConfig | |
fileConfig("logging.ini") | |
logger = logging.getLogger() | |
def main() -> None: | |
pass | |
if __name__ == '__main__': | |
main() | |
EOF | |
cd .. | |
# Create mypy.ini file | |
echo | |
read -p "Do you need a mypy.ini file? (Y/n)" mypy | |
mypy=${mypy:-Y} | |
if [ $mypy = "Y" ] | |
then | |
touch mypy.ini | |
echo "[+] Created mypy.ini file!" | |
else | |
echo "[-] mypy.ini will not be created" | |
cd .. | |
fi | |
if test -f "mypy.ini"; then | |
echo "[mypy]" >> mypy.ini | |
echo "disable_error_code = import-untyped" >> mypy.ini | |
echo "ignore_missing_imports = True" >> mypy.ini | |
fi | |
# Create pytest.ini file | |
echo | |
read -p "Do you need a pytest.ini file? (Y/n)" pytest | |
pytest=${pytest:-Y} | |
if [ $pytest = "Y" ] | |
then | |
touch pytest.ini | |
echo "[+] Created pytest.ini file!" | |
else | |
echo "[-] pytest.ini will not be created" | |
fi | |
if test -f "pytest.ini"; then | |
echo "[pytest]" >> pytest.ini | |
echo "norecursedirs = .* src *.egg dist build" >> pytest.ini | |
echo "addopts = -rsxX -l --tb=short --strict-markers" >> pytest.ini | |
fi | |
# Create virtual environment | |
echo | |
read -p "Do you need a virtual environment? (Y/n)" venv | |
venv=${venv:-Y} | |
if [ $venv = "Y" ] | |
then | |
echo "[+] Creating a virtual environment..." | |
python3 -m venv .venv | |
echo | |
echo "Done!" | |
echo | |
echo "Start the virtual environment using 'source .venv/bin/activate'." | |
else | |
echo "[-] A virtual environment will not be created!" | |
fi | |
echo | |
echo "-----------------------" | |
echo "All done! Exit program." | |
echo "-----------------------" | |
echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment