Last active
July 6, 2024 22:29
-
-
Save Velocet/51245270c2197023eaa9752c58fddc81 to your computer and use it in GitHub Desktop.
Snippets & Templates (python/PwSh/bash)
This file contains 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
#!/usr/bin/env bash | |
# Best practices Bash script template with useful functions | |
# github.com/ralish/bash-script-template/blob/main/template.sh | |
#region INIT | |
if [[ ${DEBUG-} =~ ^1|yes|true$ ]]; then set -o xtrace; fi # Trace script execution if DEBUG | |
if ! (return 0 2> /dev/null); then | |
set -o errexit # Exit on Errors | |
set -o nounset # Disallow Unset Variables | |
set -o pipefail # Use last non-zero exit code in a pipeline | |
fi # Alternative Shell behaviours if not sourced | |
set -o errtrace # Ensure the error trap handler is inherited | |
function script_trap_err() { # Handler for unexpected errors | |
local exit_code=1 | |
trap - ERR # Disable trap handler to prevent recursion | |
set +o errexit # Consider further errors non-fatal | |
set +o pipefail # to ensure script completion | |
if [[ ${1-} =~ ^[0-9]+$ ]]; then exit_code="$1"; fi # Check exit code | |
if [[ -n ${cron-} ]]; then # Print dbg data if in Cron mode | |
if [[ -n ${script_output-} ]]; then exec 1>&3 2>&4; fi | |
printf '%b\n' "$ta_none" # Print basic dbg info | |
printf '***** Abnormal termination of script *****\n' | |
printf 'Script Path: %s\n' "$script_path" | |
printf 'Script Parameters: %s\n' "$script_params" | |
printf 'Script Exit Code: %s\n' "$exit_code" | |
if [[ -n ${script_output-} ]]; then printf 'Script Output:\n\n%s' "$(cat "$script_output")" | |
else printf 'Script Output: None (failed before log init)\n'; fi | |
fi # Print script log | |
exit "$exit_code" # Exit with failure status | |
} # script_trap_err | |
function script_trap_exit() { # Handler for exiting the script | |
cd "$orig_cwd" | |
if [[ -n ${cron-} && -f ${script_output-} ]]; then rm "$script_output"; fi # Remove Cron mode script log | |
if [[ -d ${script_lock-} ]]; then rmdir "$script_lock"; fi # Remove script execution lock | |
printf '%b' "$ta_none" # Restore colours | |
} # script_trap_exit | |
# "Minimal" safe bash script | |
# https://gist.github.com/m-radzikowski/53e0b39e9a59a1518990e76c2bff8038 | |
set -Eeuo pipefail | |
trap cleanup SIGINT SIGTERM ERR EXIT | |
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P) | |
usage() { | |
cat <<EOF | |
Usage: $(basename "${BASH_SOURCE[0]}") [-h] [-v] [-f] -p param_value arg1 [arg2...] | |
Script_Description. | |
Options: | |
-h, --help Print this help and exit | |
-v, --verbose Print script debug info | |
-f, --flag Some flag description | |
-p, --param Some param description | |
EOF | |
exit | |
} | |
cleanup() { trap - SIGINT SIGTERM ERR EXIT ;; } # script cleanup here | |
setup_colors() { | |
if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then | |
NOFORMAT='\033[0m' RED='\033[0;31m' GREEN='\033[0;32m' ORANGE='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' YELLOW='\033[1;33m' | |
else NOFORMAT='' RED='' GREEN='' ORANGE='' BLUE='' PURPLE='' CYAN='' YELLOW=''; fi | |
} | |
msg() { echo >&2 -e "${1-}"; } | |
die() { | |
local msg=$1; local code=${2-1} # default exit status 1 | |
msg "$msg"; exit "$code" | |
} | |
parse_params() { | |
flag=0; param=''; # default values of variables set from params | |
while :; do | |
case "${1-}" in | |
-h | --help) usage ;; | |
-v | --verbose) set -x ;; | |
--no-color) NO_COLOR=1 ;; | |
-f | --flag) flag=1 ;; # example flag | |
-p | --param) # example named parameter | |
param="${2-}" | |
shift | |
;; | |
-?*) die "Unknown option: $1" ;; | |
*) break ;; | |
esac | |
shift | |
done | |
args=("$@") | |
[[ -z "${param-}" ]] && die "Missing required parameter: param" | |
[[ ${#args[@]} -eq 0 ]] && die "Missing script arguments" | |
return 0 | |
} | |
parse_params "$@"; setup_colors | |
# script logic here | |
msg "${RED}Read parameters:${NOFORMAT}" | |
msg "- flag: ${flag}" | |
msg "- param: ${param}" | |
msg "- arguments: ${args[*]-}" |
This file contains 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
# Upgrade all outdated pip packages as a one-liner | |
pip list --outdated | tail -n +3 | cut -d' ' -f1 | xargs -n1 pip install --upgrade | |
# ... or when using pip.conf | |
export PIP_CONFIG_FILE=".vscode/pip.conf" | |
pip list --outdated | tail -n +3 | cut -d' ' -f1 | xargs -n1 pip install |
This file contains 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
#!/usr/bin/env python -m pip | |
# | |
# https://pip.pypa.io/en/stable/topics/configuration/ | |
# | |
# Environment Variable: PIP_CONFIG_FILE | |
# Usage: export PIP_CONFIG_FILE=".vscode/pip.conf" | |
# | |
[install] | |
# Upgrade packages to the newest version | |
upgrade = true | |
# Fail After: 1 second | |
timeout = 5 | |
# Fail After: 1 Error | |
retries = 1 | |
# Don't output anything except errors | |
quiet = 3 | |
# Don't ask for user input | |
no-input = true | |
# Don't output colors to avoid parsing errors | |
no-color = true | |
# Don't check python version | |
no-python-version-warning = true | |
# Don't check pip version | |
disable-pip-version-check = true |
This file contains 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
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# -*-python-*- vim:ft=py: | |
# /// script | |
# /// | |
#region init | |
# Disable black formatter | |
# fmt: off | |
# Disable pylint error message for line-too-long | |
# pylint: disable=line-too-long | |
""" One-line Short Description. | |
A longer description that spans multiple lines: Explain the purpose. | |
This DocString is shown on import: Write reasonably useful and informative! | |
more text... | |
Args: | |
var_name(var_type): description. Default: 'var_name value' | |
... | |
Returns: | |
A python object containing something. | |
""" | |
__version__ = "0.6.9" | |
__date__ = "2024-06-09" | |
__status__ = "Development" | |
__license__ = "MIT" | |
__credits__ = "© iown-homecontrol" | |
__copyright__ = "© iown-homecontrol" | |
__author__ = "Velocet" | |
__maintainer__ = "Velocet" | |
__email__ = "[email protected]" | |
import argparse # Argument Parser | |
import pathlib # file and path handling | |
import sys # Python Version and standard system functionality (stdin/stdout) | |
# import pprint # Pretty printer for data | |
# pprint = pprint.PrettyPrinter(width=256).pprint # Pretty printer configuration | |
# print = pprint # redefine pprint as print | |
is_even = lambda number: number % 2 == 0 | |
print(f"{__debug__ = }") | |
if __debug__: | |
def assert_python3(): | |
""" Assert Python >= 3.11 is used. """ | |
assert(sys.version_info.major == 3) | |
assert(sys.version_info.minor >= 11) | |
else: | |
if sys.version_info.minor < 11: raise Exception("Python >= 3.11 is required!") | |
""" Global Variables """ | |
verbose:bool = False # Verbose Output | |
#endregion init | |
def main(args: Any) -> None: | |
""" Main Entry Point """ | |
# def main(*args: Any, **kwargs: Any) -> None: | |
# kwargs["arg_name"] = arg_value | |
# super().main(*args, **kwargs) | |
global verbose | |
if (args.verbose): verbose = True | |
# verbose = (False, True)[args.verbose] # type: ignore | |
if not args and not sys.argv[1:]: | |
# exit if no arguments are given | |
print('[ERROR] No args/argv given!') | |
sys.exit(1) | |
# | |
# if args or sys.argv[1:]: | |
# if args.verbose: | |
# print('[args] Found!') | |
# if sys.argv[1:]: | |
# args = sys.argv[1:] # strip file name | |
# else: | |
# verbose:bool = (False, True)[args.verbose] # type: ignore | |
# | |
# argc = vars(args) # convert to dict. access via argc['arg_name'] | |
# Create list with 8 elements, all containing 0. | |
# data:list = [0] * 8 # Always initialize your variables with a value! | |
# do_something(data) | |
# def do_something(data:list = None) -> None: | |
# """ It does something! """ | |
# print("Do something with this: ", data) | |
# # simple print error function | |
# # TODO create verbose function | |
# def prettyprinterror(*args, **kwargs): | |
# | |
# # Version 1: print to stderr using print() | |
# print(*args, file=sys.stderr, **kwargs) | |
# | |
# # Version 2: print to stderr using sys.stderr.write() | |
# sys.stderr.write('Error Message!\n') | |
# | |
# # Version 3: print to stderr using logging | |
# # https://docs.python.org/3/library/logging.html | |
# import logging | |
# logging.basicConfig(format='%(message)s') | |
# log = logging.getLogger(__name__) | |
# log.warning('Error Message!') | |
if __name__ == "__main__": | |
""" Executed when run from CLI or the module is not initialized from an import statement """ | |
#region Arguments | |
# | |
# Parser Configuration | |
parser = argparse.ArgumentParser( | |
# Program Name (default: os.path.basename(sys.argv[0])) | |
prog="Program-Name", | |
# Usage description (default: generated from args) | |
usage="%(prog)s --input [FILE] --output [FILE(optional)]", | |
# Text before argument help (default: None) | |
description="%(prog)s description text before argument help.", | |
# Text after the argument help (default: None) | |
epilog="Alex: It's funny how the colors of the real world only seem really real when you viddy them on the screen...", | |
) | |
# | |
# Parser Definition | |
# | |
# NOTE: If FileType is used and a subsequent argument fails the file is not closed! | |
# Better wait after the parser has run and then use the with-statement to manage the files. | |
# dest: Specify the attribute name used in the result namespace | |
# metavar: Alternate display name for the argument as shown in help | |
# type: Automatically convert an argument to the given type | |
# | |
# test if input exists: "type=pathlib.Path.is_file()" | |
parser.add_argument("-i", "--input", metavar="FILE", dest="infile", type=str, required=True, help="Input File Description") | |
parser.add_argument("-o", "--output", metavar="FILE", dest="outfile", type=str, required=False, help="Output File Description") | |
# test if dir exists: "pathlib.Path.is_dir()" | |
parser.add_argument("-p", "--path", metavar="PATH", dest="outdir", type=str, required=False, default="./output", help="Output Directory (default: %(default)s)") | |
# Optional: Verbosity | |
parser.add_argument("-V", "--verbose", action="store_true", dest="verbose", default=False, help="Verbose Output") | |
# Optional: Version output | |
parser.add_argument("-v","--version", action="version", version="%(prog)s v{version}".format(version=__version__)) | |
# Parse Arguments | |
args = parser.parse_args() | |
# args = parser.parse_args(['--arg1', 'arg1_value', '--arg2']) # Test arguments with predefined values | |
#endregion Arguments | |
# terminate with defined status and message | |
# if (args.argument): | |
# parser.exit(status=0, message="Write Message and exit") | |
# if (args.some_argument): | |
# print(some_argument) | |
if (not pathlib.Path(args.infile).is_file()): | |
parser.error("--input must be a file!") # print message and exit with status = 2 | |
# Use this if you have multiple input values | |
# input_items = itertools.chain.from_iterable(map(glob.iglob, args.input)) | |
# input_files = filter(os.path.isfile, input_items) | |
main(args) # https://docs.python.org/3/library/__main__.html | |
# Re-Activate black | |
# fmt: on |
This file contains 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
function Update-PythonPipPackages { | |
<# | |
.SYNOPSIS | |
Update all outdated pip Packages | |
.DESCRIPTION | |
Upgrade every outdated pip package and take care of error handling. | |
Includes Verbose Output. Turn on with the -verbose switch. | |
.ONELINER: (pip list --outdated) | Select -Skip 2 | % {pip install --upgrade $($_.split(' ')[0])} | |
.LINK | |
https://pip.pypa.io/en/stable/user_guide/#command-completion | |
python -m pip completion --powershell | Out-File -Encoding default -Append $PROFILE | |
.NOTES | |
Author: Velocet | |
Website: https://github.com/velocet | |
#> | |
[CmdletBinding()] | |
BEGIN { | |
#region PipEnviromentVars | |
# https://pip.pypa.io/en/stable/topics/configuration/#environment-variables | |
Write-Verbose -Message '[PIP] Set pip Environment Variables.' | |
$env:PIP_CONFIG_FILE = 'pip.conf' | |
$env:PIP_DISABLE_PIP_VERSION_CHECK = $true # Don't check pip version | |
$env:PIP_NO_PYTHON_VERSION_WARNING = $true # Don't check python version | |
$env:PIP_NO_INPUT = $true # Don't ask for user input | |
$env:PIP_NO_COLOR = $true # Don't output colors to avoid parsing errors | |
$env:PIP_QUIET = 3 # Don't output anything except errors | |
$env:PIP_RETRIES = 1 # Fail after 1 error | |
$env:PIP_TIMEOUT = 1 # Fail after 1 second | |
Write-Verbose -Message "[PIP] Use py on Windows as it takes care of versions, etc." | |
$PyRun = $IsWindows ? 'py' : 'python' | |
$PipRun = $("$PyRun -m pip") | |
#endregion PipEnviromentVars | |
#region PipEnsurePip | |
Write-Verbose -Message "[PIP] Check version to ensure correct install." | |
Invoke-Expression -Command $("$PyRun --version") # Display python version | |
Invoke-Expression -Command $("$PipRun --version") # Display pip version | |
if ($LastExitCode) { # Check if pip version failed... | |
# https://docs.python.org/3/library/ensurepip.html | |
Write-Verbose -Message "[PIP] Bootstrap pip." | |
Invoke-Expression -Command $("$PyRun -m ensurepip --upgrade --default-pip") | |
} | |
Write-Verbose -Message "[PIP] Upgrade: pip, setuptools, wheel." | |
Invoke-Expression -Command $("$PipRun install --upgrade pip setuptools wheel") | |
#endregion PipEnsurePip | |
} PROCESS { | |
Write-Verbose -Message "[PIP] Outdated: Get..." | |
[Collections.ArrayList]$Packages = Invoke-Expression -Command $("$PipRun list --outdated") | |
if ($LastExitCode) { Write-Error -Message "[PIP] Outdated: Error!";exit 1 } | |
else { | |
$Packages = $Packages[2..$Packages.GetUpperBound(0)] # Remove Header | |
if ($Packages.Count) { | |
Write-Verbose -Message "[PIP] Outdated: ($Packages.Count)" | |
foreach ($Package in $Packages) { | |
$Package = $Package.split(' ')[0] | |
Invoke-Expression -Command $("$PipRun install --upgrade $Package") | |
if ($LastExitCode) { Write-Error -Message "[PIP] Failed: $Package" } | |
else { Write-Verbose -Message "[PIP] Upgrade: $Package" } | |
} | |
} else { Write-Verbose -Message "[PIP] Upgrade: None." } | |
} | |
} END { | |
Write-Verbose -Message "[PIP] Unset Environment Variables..." | |
$env:PIP_CONFIG_FILE = '' | |
$env:PIP_DISABLE_PIP_VERSION_CHECK = '' | |
$env:PIP_NO_PYTHON_VERSION_WARNING = '' | |
$env:PIP_NO_INPUT = '' | |
$env:PIP_NO_COLOR = '' | |
$env:PIP_QUIET = '' | |
$env:PIP_RETRIES = '' | |
$env:PIP_TIMEOUT = '' | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment