Add async pieces.

This commit is contained in:
hackish 2023-07-31 15:57:05 -07:00
parent 79e06ea46f
commit 32f9588e26
11 changed files with 241 additions and 37 deletions

View file

@ -0,0 +1,46 @@
import argparse
import asyncio
import sys
import uvloop
__version__ = "0.0.1"
async def main(args: argparse.Namespace) -> None:
"""
Main function of the program (stub).
This function serves as ${REPO_NAME_SNAKE}'s critical path for primary logic.
It receives an `argparse.Namespace` object as input from invoke_maiun, which includes
the command-line arguments that were defined and parsed in the `run` function.
Args:
args (argparse.Namespace): The command-line arguments object.
Returns:
None
"""
pass
def invoke_main(args: argparse.Namespace) -> None:
"""
Function to invoke the main function using asyncio and uvloop (stub).
This function serves as a bridge to run the async main function in
a uvloop event loop. It handles the differences in asyncio API across
different Python versions.
Args:
args (argparse.Namespace): The command-line arguments object.
Returns:
None
"""
if sys.version_info >= (3, 11):
with asyncio.Runner(loop_factory=uvloop.new_event_loop) as runner:
runner.run(main(args))
else:
uvloop.install()
asyncio.run(main(args))

44
${REPO_NAME_SNAKE}/cli.py Normal file
View file

@ -0,0 +1,44 @@
from argparse import ArgumentParser
from pathlib import Path
from . import __version__
from .logger import logger
from .validation import validate_file_folder
def run() -> None:
"""
Command-line interface for ${REPO_NAME_SNAKE}.
This function defines and handles command-line arguments for the program.
The available options are:
--version: Show the version of the program and exit.
--verbose: Enable verbose logging. This will produce detailed output messages.
--output/-o: Specify the output file. This must be a valid file path.
paths: Specify any number of existing files or directories to be processed.
These paths must point to existing files or directories.
Upon parsing the command-line arguments, the function configures the logger
and invokes the `main` function with the parsed arguments.
Returns:
None
"""
# your code here
parser = ArgumentParser(description="${REPO_DESCRIPTION}")
parser.add_argument("--version", action="version", version=__version__)
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
parser.add_argument("--output", "-o", type=Path, help="Specify output file")
parser.add_argument(
"paths",
nargs="+",
type=validate_file_folder,
help="Specify any number of existing files or directories to be processed.",
)
args = parser.parse_args()
if args.verbose:
logger.debug("Verbose logging enabled")
run(args)

View file

@ -0,0 +1,4 @@
import logging
logging.basicConfig(format="%(asctime)s - %(message)s", datefmt="%d-%b-%y %H:%M:%S")
logger = logging.getLogger(__name__)

View file

@ -0,0 +1,12 @@
from pathlib import Path
from aiopath import AsyncPath
def validate_file_folder(value: str) -> Path:
file_folder_path = Path(value)
if not file_folder_path.exists():
raise FileNotFoundError(f"No such file or folder: {value}")
if not file_folder_path.is_file() and not file_folder_path.is_dir():
raise TypeError(f"Not a file or directory: {value}")
return AsyncPath(value)

3
.flake8 Normal file
View file

@ -0,0 +1,3 @@
[flake8]
max-line-length = 160
exclude = docs/*, build/*, .git, __pycache__, build

40
.gitignore vendored
View file

@ -28,8 +28,6 @@ share/python-wheels/
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
@ -83,34 +81,10 @@ target/
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
# PDM
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
# PEP 582
__pypackages__/
# Celery stuff
@ -154,11 +128,7 @@ dmypy.json
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/
# ---> macOS
# General
@ -167,7 +137,8 @@ cython_debug/
.LSOverride
# Icon must end with two \r
Icon
Icon
# Thumbnails
._*
@ -228,4 +199,3 @@ $RECYCLE.BIN/
# .nfs files are created when an open file is removed but is still being accessed
.nfs*

35
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,35 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/asottile/reorder_python_imports
rev: v3.9.0
hooks:
- id: reorder-python-imports
args: [--application-directories, '.:${REPO_NAME_SNAKE}', --py39-plus]
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
language_version: python3.11
- repo: https://github.com/PyCQA/bandit
rev: 1.7.5
hooks:
- id: bandit
args: ["-c", "pyproject.toml"]
additional_dependencies: ["bandit[toml]"]
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
- repo: local
hooks:
- id: version
name: Update version
entry: ./pre-commit.sh
language: script
files: 'pyproject.toml'

View file

@ -1,3 +1,33 @@
# python-module
<div align="center">
# ${REPO_NAME_SNAKE}
Template for a new Python project.
**${REPO_NAME_SNAKE}** is a...
Python project!<br/>
[Installation](#installation) •
[Examples](#examples) •
[Contributing](#contributing) •
[License](#license)
</div>
## Installation
Install and run ${REPO_NAME_SNAKE} using the below commands or their equivalents for your environment.
```bash
pip3 install -U ${REPO_HTTPS_URL}
${REPO_NAME_SNAKE}
```
## Examples
TBD
## Contributing
If you would like to contribute to this project, feel free to submit a pull request or open an issue on GitHub.
## License
This project is licensed under the current AGPL 3.0+ License. See the `LICENSE` file for details.

21
pre-commit.sh Executable file
View file

@ -0,0 +1,21 @@
#!/bin/bash
PROJECT_ROOT=$(git rev-parse --show-toplevel)
VERSION=$(grep 'version =' $PROJECT_ROOT/pyproject.toml | head -1 | cut -d '"' -f 2)
INIT_FILE="$PROJECT_ROOT/${REPO_NAME_SNAKE}/${REPO_NAME_SNAKE}/__init__.py"
PYPROJECT_FILE="$PROJECT_ROOT/pyproject.toml"
# Modify the CLI line to remove quotes in pyproject.toml
sed -i.bak "s/\"${REPO_NAME_SNAKE}\" = \"${REPO_NAME_SNAKE}\.cli:run\"/${REPO_NAME_SNAKE} = \"${REPO_NAME_SNAKE}\.cli:run\"/" $PYPROJECT_FILE && \
rm "$PYPROJECT_FILE.bak"
# Check if __init__.py file exists for template purposes
# This can be removed now that the template is cloned
if [ ! -f "$INIT_FILE" ]; then
echo "__init__.py does not exist yet, exiting."
exit 0
fi
# Portable workaround for macOS/Linux sed differences
sed -i.bak "s/__version__ = .*/__version__ = \"$VERSION\"/" $INIT_FILE && \
rm "$INIT_FILE.bak"

34
pyproject.toml Normal file
View file

@ -0,0 +1,34 @@
[build-system]
requires = ["setuptools>=68.0"]
build-backend = "setuptools.build_meta"
[project]
name = "${REPO_NAME_SNAKE}"
version = "0.0.1"
authors = [{ name = "${REPO_OWNER_SNAKE}", email = "git@nixon.mozmail.com" }]
description = "${REPO_DESCRIPTION}"
readme = "README.md"
requires-python = ">=3.9"
license = { text = "MIT" }
dependencies = [
"loguru>=0.7.0",
"uvloop>=0.17.0",
"aiopath>=0.6.11",
"asyncstdlib>=3.10.8",
]
[project.scripts]
"${REPO_NAME_SNAKE}" = "${REPO_NAME_SNAKE}.cli:run"
[project.urls]
homepage = "${REPO_LINK}"
repository = "${REPO_LINK}"
[tool.setuptools]
py-modules = ["${REPO_NAME_SNAKE}"]
[tool.bandit]
exclude_dirs = ["/docs", "/build"]
[tool.black]
line-length = 120

5
template Normal file
View file

@ -0,0 +1,5 @@
**.py
.pre-commit-config.yaml
README.md
pyproject.toml
pre-commit.sh