mirror of
https://github.com/daylinmorgan/swydd.git
synced 2024-11-23 07:20:43 -06:00
mvp
This commit is contained in:
parent
3b9905752c
commit
78e309bba6
8 changed files with 765 additions and 0 deletions
162
.gitignore
vendored
Normal file
162
.gitignore
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
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
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
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-project.org/#use-with-ide
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
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/
|
9
.pre-commit-config.yaml
Normal file
9
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,9 @@
|
|||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.1.10
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
- id: ruff
|
||||
args: [ --fix ]
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Daylin Morgan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
54
README.md
Normal file
54
README.md
Normal file
|
@ -0,0 +1,54 @@
|
|||
[![EffVer][effver-shield]][effver-url]
|
||||
[![Issues][issues-shield]][issues-url]
|
||||
[![MIT License][license-shield]][license-url]
|
||||
[![Ruff][ruff-shield]][ruff-url]
|
||||
[![pre-commit][pre-commit-shield]][pre-commit-url]
|
||||
|
||||
<div align="center">
|
||||
<h1>sywdd</h1>
|
||||
<p>sywdd will yield desired deliverables </p>
|
||||
</div>
|
||||
|
||||
|
||||
## Automagic Snippet
|
||||
|
||||
```python
|
||||
# https://github.com/daylinmorgan/swydd?tab=readme-ov-file#automagic-snippet
|
||||
# fmt: off
|
||||
if not (src := __import__("pathlib").Path(__file__).parent / "swydd/__init__.py").is_file(): # noqa
|
||||
try: __import__("swydd") # noqa
|
||||
except ImportError:
|
||||
import sys; from urllib.request import urlopen; from urllib.error import URLError # noqa
|
||||
try: r = urlopen("https://raw.githubusercontent.com/daylinmorgan/swydd/main/src/swydd/__init__.py") # noqa
|
||||
except URLError as e: sys.exit(f"{e}\n") # noqa
|
||||
src.parent.mkdir(exists_ok=True); src.write_text(r.read().decode("utf-8")); # noqa
|
||||
# fmt: on
|
||||
```
|
||||
|
||||
## Alternatives
|
||||
|
||||
- make
|
||||
- just
|
||||
- task
|
||||
- nox
|
||||
- pypyr
|
||||
- pydoit
|
||||
|
||||
<!-- [![Stargazers][stars-shield]][stars-url] -->
|
||||
<!-- [![PYPI][pypi-shield]][pypi-url] -->
|
||||
|
||||
<!-- badges -->
|
||||
[pre-commit-shield]: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white
|
||||
[pre-commit-url]: https://pre-commit.com
|
||||
[ruff-shield]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
|
||||
[ruff-url]: https://github.com/astral-sh/ruff
|
||||
[pypi-shield]: https://img.shields.io/pypi/v/swydd
|
||||
[pypi-url]: https://pypi.org/project/sywdd
|
||||
<!-- [stars-shield]: https://img.shields.io/github/stars/daylinmorgan/viv.svg -->
|
||||
<!-- [stars-url]: https://github.com/daylinmorgan/viv/stargazers -->
|
||||
[issues-shield]: https://img.shields.io/github/issues/daylinmorgan/swydd.svg
|
||||
[issues-url]: https://github.com/daylinmorgan/swydd/issues
|
||||
[license-shield]: https://img.shields.io/github/license/daylinmorgan/sywdd.svg
|
||||
[license-url]: https://github.com/daylinmorgan/swydd/blob/main/LICENSE
|
||||
[effver-shield]: https://img.shields.io/badge/version_scheme-EffVer-0097a7
|
||||
[effver-url]: https://jacobtomlinson.dev/effver
|
232
pdm.lock
Normal file
232
pdm.lock
Normal file
|
@ -0,0 +1,232 @@
|
|||
# This file is @generated by PDM.
|
||||
# It is not intended for manual editing.
|
||||
|
||||
[metadata]
|
||||
groups = ["default", "dev"]
|
||||
strategy = ["cross_platform", "inherit_metadata"]
|
||||
lock_version = "4.4.1"
|
||||
content_hash = "sha256:694f5832fd8758c1540ec211819f96a17c0a17cb7eb1904a046b496850a76490"
|
||||
|
||||
[[package]]
|
||||
name = "cfgv"
|
||||
version = "3.4.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Validate configuration and produce human readable error messages."
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
||||
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.3.8"
|
||||
summary = "Distribution utilities"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
|
||||
{file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.13.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A platform independent file lock."
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
|
||||
{file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.5.35"
|
||||
requires_python = ">=3.8"
|
||||
summary = "File identification library for Python"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "identify-2.5.35-py2.py3-none-any.whl", hash = "sha256:c4de0081837b211594f8e877a6b4fad7ca32bbfc1a9307fdd61c28bfe923f13e"},
|
||||
{file = "identify-2.5.35.tar.gz", hash = "sha256:10a7ca245cfcd756a554a7288159f72ff105ad233c7c4b9c6f0f4d108f5f6791"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
version = "1.8.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Optional static typing for Python"
|
||||
groups = ["dev"]
|
||||
dependencies = [
|
||||
"mypy-extensions>=1.0.0",
|
||||
"tomli>=1.1.0; python_version < \"3.11\"",
|
||||
"typing-extensions>=4.1.0",
|
||||
]
|
||||
files = [
|
||||
{file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"},
|
||||
{file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"},
|
||||
{file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"},
|
||||
{file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"},
|
||||
{file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"},
|
||||
{file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"},
|
||||
{file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"},
|
||||
{file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"},
|
||||
{file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"},
|
||||
{file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"},
|
||||
{file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"},
|
||||
{file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"},
|
||||
{file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"},
|
||||
{file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"},
|
||||
{file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"},
|
||||
{file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"},
|
||||
{file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"},
|
||||
{file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"},
|
||||
{file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"},
|
||||
{file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"},
|
||||
{file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"},
|
||||
{file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "1.0.0"
|
||||
requires_python = ">=3.5"
|
||||
summary = "Type system extensions for programs checked with the mypy type checker."
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
|
||||
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.8.0"
|
||||
requires_python = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
||||
summary = "Node.js virtual environment builder"
|
||||
groups = ["dev"]
|
||||
dependencies = [
|
||||
"setuptools",
|
||||
]
|
||||
files = [
|
||||
{file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
|
||||
{file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "4.2.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"},
|
||||
{file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pre-commit"
|
||||
version = "3.6.2"
|
||||
requires_python = ">=3.9"
|
||||
summary = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||
groups = ["dev"]
|
||||
dependencies = [
|
||||
"cfgv>=2.0.0",
|
||||
"identify>=1.0.0",
|
||||
"nodeenv>=0.11.1",
|
||||
"pyyaml>=5.1",
|
||||
"virtualenv>=20.10.0",
|
||||
]
|
||||
files = [
|
||||
{file = "pre_commit-3.6.2-py2.py3-none-any.whl", hash = "sha256:ba637c2d7a670c10daedc059f5c49b5bd0aadbccfcd7ec15592cf9665117532c"},
|
||||
{file = "pre_commit-3.6.2.tar.gz", hash = "sha256:c3ef34f463045c88658c5b99f38c1e297abdcc0ff13f98d3370055fbbfabc67e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.1"
|
||||
requires_python = ">=3.6"
|
||||
summary = "YAML parser and emitter for Python"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "69.1.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"},
|
||||
{file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A lil' TOML parser"
|
||||
groups = ["dev"]
|
||||
marker = "python_version < \"3.11\""
|
||||
files = [
|
||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.10.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
|
||||
{file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.25.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Virtual Python Environment builder"
|
||||
groups = ["dev"]
|
||||
dependencies = [
|
||||
"distlib<1,>=0.3.7",
|
||||
"filelock<4,>=3.12.2",
|
||||
"platformdirs<5,>=3.9.1",
|
||||
]
|
||||
files = [
|
||||
{file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"},
|
||||
{file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"},
|
||||
]
|
34
pyproject.toml
Normal file
34
pyproject.toml
Normal file
|
@ -0,0 +1,34 @@
|
|||
[project]
|
||||
name = "swydd"
|
||||
version = "0.1.0"
|
||||
description = "Default template for PDM package"
|
||||
authors = [
|
||||
{name = "Daylin Morgan", email = "daylinmorgan@gmail.com"},
|
||||
]
|
||||
dependencies = []
|
||||
requires-python = ">=3.9"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
||||
|
||||
|
||||
[tool.pdm]
|
||||
distribution = true
|
||||
|
||||
[tool.pdm.dev-dependencies]
|
||||
dev = [
|
||||
"pre-commit>=3.6.2",
|
||||
"mypy>=1.8.0",
|
||||
]
|
||||
|
||||
[tool.ruff]
|
||||
select = ["E","F","I"]
|
||||
ignore = ["E402"]
|
||||
|
||||
[tool.mypy]
|
||||
check_untyped_defs = true
|
||||
disallow_untyped_defs = true
|
||||
warn_unused_configs = true
|
238
src/swydd/__init__.py
Normal file
238
src/swydd/__init__.py
Normal file
|
@ -0,0 +1,238 @@
|
|||
import argparse
|
||||
import inspect
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
from argparse import (
|
||||
Action,
|
||||
ArgumentParser,
|
||||
RawDescriptionHelpFormatter,
|
||||
_SubParsersAction,
|
||||
)
|
||||
from inspect import Parameter
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple
|
||||
|
||||
__version__ = "0.1.0"
|
||||
|
||||
|
||||
class Context:
|
||||
def __init__(self) -> None:
|
||||
self.show_targets = True
|
||||
self.dag = False
|
||||
self.dry = False
|
||||
self.tasks: Dict[str, Any] = {}
|
||||
self.targets: Dict[str, Any] = {}
|
||||
self.data: Any = None
|
||||
self.flags: Dict[str, Any] = {}
|
||||
self._flag_defs: List[Tuple[Tuple[str, ...], Any]] = []
|
||||
self.verbose = False
|
||||
|
||||
def add_task(
|
||||
self, func: Callable[..., Any], help: Optional[Dict[str, str]] = None
|
||||
) -> None:
|
||||
name = func.__name__
|
||||
if name == "inner":
|
||||
return
|
||||
if name in self.tasks:
|
||||
raise ValueError(f"{name} task is repeated.")
|
||||
else:
|
||||
self.tasks[name] = dict(
|
||||
func=func, signature=inspect.signature(func), help=help
|
||||
)
|
||||
|
||||
def add_flag(self, *args: str, **kwargs: Any) -> None:
|
||||
name = max(args, key=len).split("-")[-1]
|
||||
self.flags[name] = None
|
||||
self._flag_defs.append((args, kwargs))
|
||||
|
||||
|
||||
ctx = Context()
|
||||
|
||||
|
||||
class Exec:
|
||||
def __init__(self, cmd: str, shell: bool = False) -> None:
|
||||
self.shell = shell
|
||||
self.cmd = cmd
|
||||
|
||||
def execute(self) -> int:
|
||||
if ctx.verbose:
|
||||
sys.stdout.write(f"exec: {self.cmd}\n")
|
||||
if self.shell:
|
||||
return subprocess.run(self.cmd, shell=True).returncode
|
||||
else:
|
||||
return subprocess.run(shlex.split(self.cmd)).returncode
|
||||
|
||||
|
||||
def sh(cmd: str, shell: bool = False) -> int:
|
||||
return Exec(cmd, shell=shell).execute()
|
||||
|
||||
|
||||
class SubcommandHelpFormatter(RawDescriptionHelpFormatter):
|
||||
"""custom help formatter to remove bracketed list of subparsers"""
|
||||
|
||||
def _format_action(self, action: Action) -> str:
|
||||
# TODO: actually modify the real "format_action for better control"
|
||||
parts = super(RawDescriptionHelpFormatter, self)._format_action(action)
|
||||
if action.nargs == argparse.PARSER:
|
||||
lines = parts.split("\n")[1:]
|
||||
tasks, targets = [], []
|
||||
for line in lines:
|
||||
if len(line) > 0 and line.strip().split()[0] in ctx.targets:
|
||||
targets.append(line)
|
||||
else:
|
||||
tasks.append(line)
|
||||
parts = "\n".join(tasks)
|
||||
if len(targets) > 0 and ctx.show_targets:
|
||||
parts += "\n".join(("\ntargets:", *targets))
|
||||
|
||||
return parts
|
||||
|
||||
|
||||
ctx = Context()
|
||||
|
||||
|
||||
def task(func: Callable[..., Any]) -> Callable[..., None]:
|
||||
ctx.add_task(func)
|
||||
|
||||
def wrap(*args: Any, **kwargs: Any) -> None:
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrap
|
||||
|
||||
|
||||
def targets(
|
||||
*args: str,
|
||||
) -> Callable[[Callable[..., Any]], Callable[..., Callable[..., None]]]:
|
||||
def wrapper(func: Callable[..., Any]) -> Callable[..., Callable[..., None]]:
|
||||
for arg in args:
|
||||
ctx.targets[arg] = func
|
||||
|
||||
def inner(*args: Any, **kwargs: Any) -> Callable[..., None]:
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return inner
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def help(
|
||||
**help_kwargs: str,
|
||||
) -> Callable[[Callable[..., Any]], Callable[..., Callable[..., None]]]:
|
||||
def wrapper(func: Callable[..., Any]) -> Callable[..., Callable[..., None]]:
|
||||
ctx.add_task(func, help=help_kwargs)
|
||||
|
||||
def inner(*args: Any, **kwargs: Any) -> Callable[..., None]:
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return inner
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def manage(version: bool = False) -> None:
|
||||
"""manage self"""
|
||||
print("self management ey")
|
||||
if version:
|
||||
print("current version", __version__)
|
||||
|
||||
|
||||
def generate_subparser(
|
||||
shared: ArgumentParser,
|
||||
subparsers: _SubParsersAction,
|
||||
name: str,
|
||||
info: Dict[str, Any],
|
||||
) -> ArgumentParser:
|
||||
func = info["func"]
|
||||
signature = info["signature"]
|
||||
help = info.get("help")
|
||||
doc = func.__doc__.splitlines()[0] if func.__doc__ else ""
|
||||
subparser = subparsers.add_parser(
|
||||
name, help=doc, description=func.__doc__, parents=[shared]
|
||||
)
|
||||
for name, param in signature.parameters.items():
|
||||
args = (f"--{name}",)
|
||||
kwargs = {"help": help.get(name, "")} if help else {}
|
||||
|
||||
if param.annotation == bool:
|
||||
kwargs.update({"default": False, "action": "store_true"})
|
||||
elif param.annotation != Parameter.empty:
|
||||
kwargs.update({"type": param.annotation})
|
||||
kwargs.update(
|
||||
{"required": True}
|
||||
if param.default == Parameter.empty
|
||||
else {"default": param.default}
|
||||
)
|
||||
|
||||
subparser.add_argument(*args, **kwargs)
|
||||
subparser.set_defaults(func=func)
|
||||
return subparser
|
||||
|
||||
|
||||
def add_targets(
|
||||
parent: ArgumentParser, subparsers: _SubParsersAction, ctx: Context
|
||||
) -> None:
|
||||
for target, target_func in ctx.targets.items():
|
||||
subp = generate_subparser(
|
||||
parent,
|
||||
subparsers,
|
||||
target,
|
||||
dict(func=target_func, signature=inspect.signature(target_func)),
|
||||
)
|
||||
subp.add_argument("--dag", help="show target dag", action="store_true")
|
||||
|
||||
|
||||
def cli() -> None:
|
||||
parser = ArgumentParser(formatter_class=SubcommandHelpFormatter)
|
||||
shared = ArgumentParser(add_help=False)
|
||||
|
||||
for flag_args, flag_kwargs in ctx._flag_defs:
|
||||
shared.add_argument(*flag_args, **flag_kwargs)
|
||||
|
||||
shared.add_argument("--verbose", help="use verbose output", action="store_true")
|
||||
shared.add_argument(
|
||||
"-n", "--dry-run", help="don't execute tasks", action="store_true"
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(
|
||||
title="tasks",
|
||||
required=True,
|
||||
)
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "self":
|
||||
generate_subparser(
|
||||
shared,
|
||||
subparsers,
|
||||
"self",
|
||||
dict(func=manage, signature=inspect.signature(manage)),
|
||||
)
|
||||
|
||||
add_targets(shared, subparsers, ctx)
|
||||
|
||||
for name, info in ctx.tasks.items():
|
||||
generate_subparser(shared, subparsers, name, info)
|
||||
|
||||
args = vars(parser.parse_args())
|
||||
ctx.verbose = args.pop("verbose", False)
|
||||
ctx.dry = args.pop("dry_run", False)
|
||||
ctx.dag = args.pop("dag", False)
|
||||
for name in ctx.flags:
|
||||
ctx.flags[name] = args.pop(name)
|
||||
|
||||
if f := args.pop("func", None):
|
||||
if ctx.dry:
|
||||
print("dry run >>>")
|
||||
print(" args:", args)
|
||||
print(
|
||||
"\n".join(
|
||||
f" {line}"
|
||||
for line in inspect.getsource(f).splitlines()
|
||||
if not line.startswith("@")
|
||||
)
|
||||
)
|
||||
else:
|
||||
f(**args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.stderr.write("this module should not be invoked directly\n")
|
||||
sys.exit(1)
|
15
tasks.py
Executable file
15
tasks.py
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import swydd as s
|
||||
|
||||
|
||||
@s.task
|
||||
@s.help(types="also run mypy")
|
||||
def check(types: bool = False):
|
||||
"""run pre-commit (and mypy)"""
|
||||
s.sh("pre-commit run --all")
|
||||
if types:
|
||||
s.sh("mypy src/")
|
||||
|
||||
|
||||
s.cli()
|
Loading…
Reference in a new issue