mirror of
https://github.com/YunoHost/apps.git
synced 2024-09-03 20:06:07 +02:00
initial toolsv2 commit
This commit is contained in:
parent
ab17a76f4d
commit
4bf698d2a1
11 changed files with 647 additions and 0 deletions
1
toolsv2/.pdm-python
Normal file
1
toolsv2/.pdm-python
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/home/felix/tmp/yunohost/repo_apps/toolsv2/.venv/bin/python
|
269
toolsv2/pdm.lock
generated
Normal file
269
toolsv2/pdm.lock
generated
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
# 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:4bf91edcb3dce5d08880e052da5d784fcfa603c2c014ef9776475cc078c05c48"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "black"
|
||||||
|
version = "24.2.0"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "The uncompromising code formatter."
|
||||||
|
groups = ["dev"]
|
||||||
|
dependencies = [
|
||||||
|
"click>=8.0.0",
|
||||||
|
"mypy-extensions>=0.4.3",
|
||||||
|
"packaging>=22.0",
|
||||||
|
"pathspec>=0.9.0",
|
||||||
|
"platformdirs>=2",
|
||||||
|
"tomli>=1.1.0; python_version < \"3.11\"",
|
||||||
|
"typing-extensions>=4.0.1; python_version < \"3.11\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "black-24.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6981eae48b3b33399c8757036c7f5d48a535b962a7c2310d19361edeef64ce29"},
|
||||||
|
{file = "black-24.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d533d5e3259720fdbc1b37444491b024003e012c5173f7d06825a77508085430"},
|
||||||
|
{file = "black-24.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61a0391772490ddfb8a693c067df1ef5227257e72b0e4108482b8d41b5aee13f"},
|
||||||
|
{file = "black-24.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:992e451b04667116680cb88f63449267c13e1ad134f30087dec8527242e9862a"},
|
||||||
|
{file = "black-24.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:163baf4ef40e6897a2a9b83890e59141cc8c2a98f2dda5080dc15c00ee1e62cd"},
|
||||||
|
{file = "black-24.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e37c99f89929af50ffaf912454b3e3b47fd64109659026b678c091a4cd450fb2"},
|
||||||
|
{file = "black-24.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9de21bafcba9683853f6c96c2d515e364aee631b178eaa5145fc1c61a3cc92"},
|
||||||
|
{file = "black-24.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:9db528bccb9e8e20c08e716b3b09c6bdd64da0dd129b11e160bf082d4642ac23"},
|
||||||
|
{file = "black-24.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d84f29eb3ee44859052073b7636533ec995bd0f64e2fb43aeceefc70090e752b"},
|
||||||
|
{file = "black-24.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e08fb9a15c914b81dd734ddd7fb10513016e5ce7e6704bdd5e1251ceee51ac9"},
|
||||||
|
{file = "black-24.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:810d445ae6069ce64030c78ff6127cd9cd178a9ac3361435708b907d8a04c693"},
|
||||||
|
{file = "black-24.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ba15742a13de85e9b8f3239c8f807723991fbfae24bad92d34a2b12e81904982"},
|
||||||
|
{file = "black-24.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e53a8c630f71db01b28cd9602a1ada68c937cbf2c333e6ed041390d6968faf4"},
|
||||||
|
{file = "black-24.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93601c2deb321b4bad8f95df408e3fb3943d85012dddb6121336b8e24a0d1218"},
|
||||||
|
{file = "black-24.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0057f800de6acc4407fe75bb147b0c2b5cbb7c3ed110d3e5999cd01184d53b0"},
|
||||||
|
{file = "black-24.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:faf2ee02e6612577ba0181f4347bcbcf591eb122f7841ae5ba233d12c39dcb4d"},
|
||||||
|
{file = "black-24.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:057c3dc602eaa6fdc451069bd027a1b2635028b575a6c3acfd63193ced20d9c8"},
|
||||||
|
{file = "black-24.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08654d0797e65f2423f850fc8e16a0ce50925f9337fb4a4a176a7aa4026e63f8"},
|
||||||
|
{file = "black-24.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca610d29415ee1a30a3f30fab7a8f4144e9d34c89a235d81292a1edb2b55f540"},
|
||||||
|
{file = "black-24.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:4dd76e9468d5536abd40ffbc7a247f83b2324f0c050556d9c371c2b9a9a95e31"},
|
||||||
|
{file = "black-24.2.0-py3-none-any.whl", hash = "sha256:e8a6ae970537e67830776488bca52000eaa37fa63b9988e8c487458d9cd5ace6"},
|
||||||
|
{file = "black-24.2.0.tar.gz", hash = "sha256:bce4f25c27c3435e4dace4815bcb2008b87e167e3bf4ee47ccdc5ce906eb4894"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "click"
|
||||||
|
version = "8.1.7"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "Composable command line interface toolkit"
|
||||||
|
groups = ["dev"]
|
||||||
|
dependencies = [
|
||||||
|
"colorama; platform_system == \"Windows\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
||||||
|
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorama"
|
||||||
|
version = "0.4.6"
|
||||||
|
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
|
summary = "Cross-platform colored terminal text."
|
||||||
|
groups = ["dev"]
|
||||||
|
marker = "platform_system == \"Windows\""
|
||||||
|
files = [
|
||||||
|
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||||
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gitdb"
|
||||||
|
version = "4.0.11"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "Git Object Database"
|
||||||
|
groups = ["default"]
|
||||||
|
dependencies = [
|
||||||
|
"smmap<6,>=3.0.1",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"},
|
||||||
|
{file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gitpython"
|
||||||
|
version = "3.1.42"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "GitPython is a Python library used to interact with Git repositories"
|
||||||
|
groups = ["default"]
|
||||||
|
dependencies = [
|
||||||
|
"gitdb<5,>=4.0.1",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "GitPython-3.1.42-py3-none-any.whl", hash = "sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd"},
|
||||||
|
{file = "GitPython-3.1.42.tar.gz", hash = "sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy"
|
||||||
|
version = "1.9.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.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"},
|
||||||
|
{file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"},
|
||||||
|
{file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"},
|
||||||
|
{file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"},
|
||||||
|
{file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"},
|
||||||
|
{file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"},
|
||||||
|
{file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"},
|
||||||
|
{file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"},
|
||||||
|
{file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"},
|
||||||
|
{file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"},
|
||||||
|
{file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"},
|
||||||
|
{file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"},
|
||||||
|
{file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"},
|
||||||
|
{file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"},
|
||||||
|
{file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"},
|
||||||
|
{file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"},
|
||||||
|
{file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"},
|
||||||
|
{file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"},
|
||||||
|
{file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"},
|
||||||
|
{file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"},
|
||||||
|
{file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"},
|
||||||
|
{file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"},
|
||||||
|
{file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"},
|
||||||
|
{file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"},
|
||||||
|
{file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"},
|
||||||
|
{file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"},
|
||||||
|
{file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "packaging"
|
||||||
|
version = "24.0"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "Core utilities for Python packages"
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
|
||||||
|
{file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathspec"
|
||||||
|
version = "0.12.1"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Utility library for gitignore style pattern matching of file paths."
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
|
||||||
|
{file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "ruff"
|
||||||
|
version = "0.3.2"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "An extremely fast Python linter and code formatter, written in Rust."
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "ruff-0.3.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77f2612752e25f730da7421ca5e3147b213dca4f9a0f7e0b534e9562c5441f01"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9966b964b2dd1107797be9ca7195002b874424d1d5472097701ae8f43eadef5d"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b83d17ff166aa0659d1e1deaf9f2f14cbe387293a906de09bc4860717eb2e2da"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb875c6cc87b3703aeda85f01c9aebdce3d217aeaca3c2e52e38077383f7268a"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be75e468a6a86426430373d81c041b7605137a28f7014a72d2fc749e47f572aa"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:967978ac2d4506255e2f52afe70dda023fc602b283e97685c8447d036863a302"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1231eacd4510f73222940727ac927bc5d07667a86b0cbe822024dd00343e77e9"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c6d613b19e9a8021be2ee1d0e27710208d1603b56f47203d0abbde906929a9b"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8439338a6303585d27b66b4626cbde89bb3e50fa3cae86ce52c1db7449330a7"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:de8b480d8379620cbb5ea466a9e53bb467d2fb07c7eca54a4aa8576483c35d36"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b74c3de9103bd35df2bb05d8b2899bf2dbe4efda6474ea9681280648ec4d237d"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f380be9fc15a99765c9cf316b40b9da1f6ad2ab9639e551703e581a5e6da6745"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0ac06a3759c3ab9ef86bbeca665d31ad3aa9a4b1c17684aadb7e61c10baa0df4"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-win32.whl", hash = "sha256:9bd640a8f7dd07a0b6901fcebccedadeb1a705a50350fb86b4003b805c81385a"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-win_amd64.whl", hash = "sha256:0c1bdd9920cab5707c26c8b3bf33a064a4ca7842d91a99ec0634fec68f9f4037"},
|
||||||
|
{file = "ruff-0.3.2-py3-none-win_arm64.whl", hash = "sha256:5f65103b1d76e0d600cabd577b04179ff592064eaa451a70a81085930e907d0b"},
|
||||||
|
{file = "ruff-0.3.2.tar.gz", hash = "sha256:fa78ec9418eb1ca3db392811df3376b46471ae93792a81af2d1cbb0e5dcb5142"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smmap"
|
||||||
|
version = "5.0.1"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "A pure Python implementation of a sliding window memory map manager"
|
||||||
|
groups = ["default"]
|
||||||
|
files = [
|
||||||
|
{file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"},
|
||||||
|
{file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "tomlkit"
|
||||||
|
version = "0.12.4"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "Style preserving TOML library"
|
||||||
|
groups = ["default"]
|
||||||
|
files = [
|
||||||
|
{file = "tomlkit-0.12.4-py3-none-any.whl", hash = "sha256:5cd82d48a3dd89dee1f9d64420aa20ae65cfbd00668d6f094d7578a78efbb77b"},
|
||||||
|
{file = "tomlkit-0.12.4.tar.gz", hash = "sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "types-toml"
|
||||||
|
version = "0.10.8.20240310"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Typing stubs for toml"
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "types-toml-0.10.8.20240310.tar.gz", hash = "sha256:3d41501302972436a6b8b239c850b26689657e25281b48ff0ec06345b8830331"},
|
||||||
|
{file = "types_toml-0.10.8.20240310-py3-none-any.whl", hash = "sha256:627b47775d25fa29977d9c70dc0cbab3f314f32c8d8d0c012f2ef5de7aaec05d"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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"},
|
||||||
|
]
|
48
toolsv2/pyproject.toml
Normal file
48
toolsv2/pyproject.toml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
[project]
|
||||||
|
name = "tools"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Default template for PDM package"
|
||||||
|
authors = [
|
||||||
|
{name = "Salamandar", email = "felix@piedallu.me"},
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"gitpython>=3.1.42",
|
||||||
|
"tomlkit>=0.12.4",
|
||||||
|
]
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
readme = "README.md"
|
||||||
|
license = {text = "GPLv3"}
|
||||||
|
|
||||||
|
|
||||||
|
[tool.pdm]
|
||||||
|
distribution = false
|
||||||
|
|
||||||
|
[tool.pdm.dev-dependencies]
|
||||||
|
dev = [
|
||||||
|
"black>=24",
|
||||||
|
"ruff>=0.3",
|
||||||
|
"mypy>=1.9",
|
||||||
|
"types-toml>=0.10",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.black]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = [
|
||||||
|
"F", # pyflakes
|
||||||
|
"E", # pycodestyle
|
||||||
|
"W", # pycodestyle
|
||||||
|
"I", # isort
|
||||||
|
"N", # pep8-naming
|
||||||
|
"B", # flake8-ubgbear
|
||||||
|
"ANN", # flake8-annotations
|
||||||
|
"Q", # flake8-quotes
|
||||||
|
"PTH", # flake8-use-pathlib
|
||||||
|
"UP", # pyupgrade,
|
||||||
|
]
|
||||||
|
|
||||||
|
ignore = ["ANN101", "ANN102", "ANN401"]
|
0
toolsv2/tests/__init__.py
Normal file
0
toolsv2/tests/__init__.py
Normal file
0
toolsv2/tools/__init__.py
Normal file
0
toolsv2/tools/__init__.py
Normal file
0
toolsv2/tools/forge/__init__.py
Normal file
0
toolsv2/tools/forge/__init__.py
Normal file
47
toolsv2/tools/forge/github.py
Normal file
47
toolsv2/tools/forge/github.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from functools import cache
|
||||||
|
|
||||||
|
import github
|
||||||
|
|
||||||
|
from ..utils.paths import APPS_REPO_ROOT
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def github_login() -> str | None:
|
||||||
|
if (file := APPS_REPO_ROOT / ".github_login").exists():
|
||||||
|
return file.open(encoding="utf-8").read().strip()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def github_email() -> str | None:
|
||||||
|
if (file := APPS_REPO_ROOT / ".github_email").exists():
|
||||||
|
return file.open(encoding="utf-8").read().strip()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def github_token() -> str | None:
|
||||||
|
if (file := APPS_REPO_ROOT / ".github_token").exists():
|
||||||
|
return file.open(encoding="utf-8").read().strip()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def github_auth() -> github.Auth.Auth | None:
|
||||||
|
token = github_token()
|
||||||
|
if token is None:
|
||||||
|
logging.warning("Could not get Github token authentication.")
|
||||||
|
return None
|
||||||
|
return github.Auth.Token(token)
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def github_api() -> github.Github:
|
||||||
|
auth = github_auth()
|
||||||
|
if auth is None:
|
||||||
|
logging.warning("Returning unauthenticated Github API.")
|
||||||
|
return github.Github()
|
||||||
|
return github.Github(auth=auth)
|
178
toolsv2/tools/forge/rest_api.py
Normal file
178
toolsv2/tools/forge/rest_api.py
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import re
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class RefType(Enum):
|
||||||
|
tags = 1
|
||||||
|
commits = 2
|
||||||
|
|
||||||
|
|
||||||
|
class GithubAPI:
|
||||||
|
def __init__(self, upstream: str, auth: Optional[tuple[str, str]] = None) -> None:
|
||||||
|
self.upstream = upstream
|
||||||
|
self.upstream_repo = upstream.replace("https://github.com/", "").strip("/")
|
||||||
|
assert (
|
||||||
|
len(self.upstream_repo.split("/")) == 2
|
||||||
|
), f"'{upstream}' doesn't seem to be a github repository ?"
|
||||||
|
self.auth = auth
|
||||||
|
|
||||||
|
def internal_api(self, uri: str) -> Any:
|
||||||
|
url = f"https://api.github.com/{uri}"
|
||||||
|
r = requests.get(url, auth=self.auth)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.json()
|
||||||
|
|
||||||
|
def tags(self) -> list[dict[str, str]]:
|
||||||
|
"""Get a list of tags for project."""
|
||||||
|
return self.internal_api(f"repos/{self.upstream_repo}/tags")
|
||||||
|
|
||||||
|
def commits(self) -> list[dict[str, Any]]:
|
||||||
|
"""Get a list of commits for project."""
|
||||||
|
return self.internal_api(f"repos/{self.upstream_repo}/commits")
|
||||||
|
|
||||||
|
def releases(self) -> list[dict[str, Any]]:
|
||||||
|
"""Get a list of releases for project."""
|
||||||
|
return self.internal_api(f"repos/{self.upstream_repo}/releases")
|
||||||
|
|
||||||
|
def url_for_ref(self, ref: str, ref_type: RefType) -> str:
|
||||||
|
"""Get a URL for a ref."""
|
||||||
|
if ref_type == RefType.tags:
|
||||||
|
return f"{self.upstream}/archive/refs/tags/{ref}.tar.gz"
|
||||||
|
elif ref_type == RefType.commits:
|
||||||
|
return f"{self.upstream}/archive/{ref}.tar.gz"
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class GitlabAPI:
|
||||||
|
def __init__(self, upstream: str) -> None:
|
||||||
|
# Find gitlab api root...
|
||||||
|
self.forge_root = self.get_forge_root(upstream).rstrip("/")
|
||||||
|
self.project_path = upstream.replace(self.forge_root, "").lstrip("/")
|
||||||
|
self.project_id = self.find_project_id(self.project_path)
|
||||||
|
|
||||||
|
def get_forge_root(self, project_url: str) -> str:
|
||||||
|
"""A small heuristic based on the content of the html page..."""
|
||||||
|
r = requests.get(project_url)
|
||||||
|
r.raise_for_status()
|
||||||
|
match = re.search(r"const url = `(.*)/api/graphql`", r.text)
|
||||||
|
assert match is not None
|
||||||
|
return match.group(1)
|
||||||
|
|
||||||
|
def find_project_id(self, project: str) -> int:
|
||||||
|
try:
|
||||||
|
project = self.internal_api(f"projects/{project.replace('/', '%2F')}")
|
||||||
|
except requests.exceptions.HTTPError as err:
|
||||||
|
if err.response.status_code != 404:
|
||||||
|
raise
|
||||||
|
# Second chance for some buggy gitlab instances...
|
||||||
|
name = self.project_path.split("/")[-1]
|
||||||
|
projects = self.internal_api(f"projects?search={name}")
|
||||||
|
project = next(
|
||||||
|
filter(
|
||||||
|
lambda x: x.get("path_with_namespace") == self.project_path,
|
||||||
|
projects,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(project, dict)
|
||||||
|
project_id = project.get("id", None)
|
||||||
|
return project_id
|
||||||
|
|
||||||
|
def internal_api(self, uri: str) -> Any:
|
||||||
|
url = f"{self.forge_root}/api/v4/{uri}"
|
||||||
|
r = requests.get(url)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.json()
|
||||||
|
|
||||||
|
def tags(self) -> list[dict[str, str]]:
|
||||||
|
"""Get a list of tags for project."""
|
||||||
|
return self.internal_api(f"projects/{self.project_id}/repository/tags")
|
||||||
|
|
||||||
|
def commits(self) -> list[dict[str, Any]]:
|
||||||
|
"""Get a list of commits for project."""
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"sha": commit["id"],
|
||||||
|
"commit": {"author": {"date": commit["committed_date"]}},
|
||||||
|
}
|
||||||
|
for commit in self.internal_api(
|
||||||
|
f"projects/{self.project_id}/repository/commits"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
def releases(self) -> list[dict[str, Any]]:
|
||||||
|
"""Get a list of releases for project."""
|
||||||
|
releases = self.internal_api(f"projects/{self.project_id}/releases")
|
||||||
|
retval = []
|
||||||
|
for release in releases:
|
||||||
|
r = {
|
||||||
|
"tag_name": release["tag_name"],
|
||||||
|
"prerelease": False,
|
||||||
|
"draft": False,
|
||||||
|
"html_url": release["_links"]["self"],
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"name": asset["name"],
|
||||||
|
"browser_download_url": asset["direct_asset_url"],
|
||||||
|
}
|
||||||
|
for asset in release["assets"]["links"]
|
||||||
|
],
|
||||||
|
}
|
||||||
|
for source in release["assets"]["sources"]:
|
||||||
|
r["assets"].append(
|
||||||
|
{
|
||||||
|
"name": f"source.{source['format']}",
|
||||||
|
"browser_download_url": source["url"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
retval.append(r)
|
||||||
|
|
||||||
|
return retval
|
||||||
|
|
||||||
|
def url_for_ref(self, ref: str, ref_type: RefType) -> str:
|
||||||
|
name = self.project_path.split("/")[-1]
|
||||||
|
clean_ref = ref.replace("/", "-")
|
||||||
|
return f"{self.forge_root}/{self.project_path}/-/archive/{ref}/{name}-{clean_ref}.tar.bz2"
|
||||||
|
|
||||||
|
|
||||||
|
class GiteaForgejoAPI:
|
||||||
|
def __init__(self, upstream: str):
|
||||||
|
# Find gitea/forgejo api root...
|
||||||
|
self.forge_root = self.get_forge_root(upstream).rstrip("/")
|
||||||
|
self.project_path = upstream.replace(self.forge_root, "").lstrip("/")
|
||||||
|
|
||||||
|
def get_forge_root(self, project_url: str) -> str:
|
||||||
|
"""A small heuristic based on the content of the html page..."""
|
||||||
|
r = requests.get(project_url)
|
||||||
|
r.raise_for_status()
|
||||||
|
match = re.search(r"appUrl: '([^']*)',", r.text)
|
||||||
|
assert match is not None
|
||||||
|
return match.group(1).replace("\\", "")
|
||||||
|
|
||||||
|
def internal_api(self, uri: str):
|
||||||
|
url = f"{self.forge_root}/api/v1/{uri}"
|
||||||
|
r = requests.get(url)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.json()
|
||||||
|
|
||||||
|
def tags(self) -> list[dict[str, Any]]:
|
||||||
|
"""Get a list of tags for project."""
|
||||||
|
return self.internal_api(f"repos/{self.project_path}/tags")
|
||||||
|
|
||||||
|
def commits(self) -> list[dict[str, Any]]:
|
||||||
|
"""Get a list of commits for project."""
|
||||||
|
return self.internal_api(f"repos/{self.project_path}/commits")
|
||||||
|
|
||||||
|
def releases(self) -> list[dict[str, Any]]:
|
||||||
|
"""Get a list of releases for project."""
|
||||||
|
return self.internal_api(f"repos/{self.project_path}/releases")
|
||||||
|
|
||||||
|
def url_for_ref(self, ref: str, ref_type: RefType) -> str:
|
||||||
|
"""Get a URL for a ref."""
|
||||||
|
return f"{self.forge_root}/{self.project_path}/archive/{ref}.tar.gz"
|
39
toolsv2/tools/utils/logging_sender.py
Normal file
39
toolsv2/tools/utils/logging_sender.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
from shutil import which
|
||||||
|
import logging
|
||||||
|
import logging.handlers
|
||||||
|
|
||||||
|
|
||||||
|
def send_to_matrix(message: str) -> None:
|
||||||
|
if which("sendxmpppy") is None:
|
||||||
|
logging.warning("Could not send error via xmpp.")
|
||||||
|
return
|
||||||
|
subprocess.call(["sendxmpppy", message], stdout=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
|
||||||
|
class LogSenderHandler(logging.Handler):
|
||||||
|
def __init__(self):
|
||||||
|
logging.Handler.__init__(self)
|
||||||
|
self.is_logging = False
|
||||||
|
|
||||||
|
def emit(self, record):
|
||||||
|
msg = f"[Apps tools error] {record.msg}"
|
||||||
|
send_to_matrix(msg)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add(cls, level=logging.ERROR):
|
||||||
|
if not logging.getLogger().handlers:
|
||||||
|
logging.basicConfig()
|
||||||
|
|
||||||
|
# create handler
|
||||||
|
handler = cls()
|
||||||
|
handler.setLevel(level)
|
||||||
|
# add the handler
|
||||||
|
logging.getLogger().handlers.append(handler)
|
||||||
|
|
||||||
|
|
||||||
|
def enable():
|
||||||
|
"""Enables the LogSenderHandler"""
|
||||||
|
LogSenderHandler.add(logging.ERROR)
|
11
toolsv2/tools/utils/paths.py
Normal file
11
toolsv2/tools/utils/paths.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from git import Repo
|
||||||
|
|
||||||
|
APPS_REPO_ROOT = Path(Repo(__file__, search_parent_directories=True).working_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def apps_repo_root() -> Path:
|
||||||
|
return APPS_REPO_ROOT
|
54
toolsv2/tools/utils/utils.py
Normal file
54
toolsv2/tools/utils/utils.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import time
|
||||||
|
from functools import cache
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Union
|
||||||
|
|
||||||
|
import toml
|
||||||
|
|
||||||
|
from .paths import APPS_REPO_ROOT
|
||||||
|
|
||||||
|
|
||||||
|
def git_repo_age(path: Path) -> Union[bool, int]:
|
||||||
|
for file in [path / ".git" / "FETCH_HEAD", path / ".git" / "HEAD"]:
|
||||||
|
if file.exists():
|
||||||
|
return int(time.time() - file.stat().st_mtime)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_catalog(working_only: bool = False) -> dict[str, dict[str, Any]]:
|
||||||
|
"""Load the app catalog and filter out the non-working ones"""
|
||||||
|
catalog = toml.load((APPS_REPO_ROOT / "apps.toml").open("r", encoding="utf-8"))
|
||||||
|
if working_only:
|
||||||
|
catalog = {
|
||||||
|
app: infos
|
||||||
|
for app, infos in catalog.items()
|
||||||
|
if infos.get("state") != "notworking"
|
||||||
|
}
|
||||||
|
return catalog
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_categories() -> dict[str, Any]:
|
||||||
|
categories_path = APPS_REPO_ROOT / "categories.toml"
|
||||||
|
return toml.load(categories_path)
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_antifeatures() -> dict[str, Any]:
|
||||||
|
antifeatures_path = APPS_REPO_ROOT / "antifeatures.toml"
|
||||||
|
return toml.load(antifeatures_path)
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_wishlist() -> dict[str, dict[str, str]]:
|
||||||
|
wishlist_path = APPS_REPO_ROOT / "wishlist.toml"
|
||||||
|
return toml.load(wishlist_path)
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_graveyard() -> dict[str, dict[str, str]]:
|
||||||
|
wishlist_path = APPS_REPO_ROOT / "graveyard.toml"
|
||||||
|
return toml.load(wishlist_path)
|
Loading…
Add table
Reference in a new issue