mirror of
https://github.com/maubot/maubot
synced 2025-08-30 15:40:38 +00:00
Rename clickquiry to cliq and remove util package
This commit is contained in:
parent
1bc51d2de5
commit
54e117c9e7
7 changed files with 21 additions and 19 deletions
2
maubot/cli/cliq/__init__.py
Normal file
2
maubot/cli/cliq/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .cliq import command, option
|
||||
from .validators import SPDXValidator, VersionValidator, PathValidator
|
91
maubot/cli/cliq/cliq.py
Normal file
91
maubot/cli/cliq/cliq.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
# maubot - A plugin-based Matrix bot system.
|
||||
# Copyright (C) 2018 Tulir Asokan
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from typing import Any, Callable, Union, Optional
|
||||
import functools
|
||||
|
||||
from prompt_toolkit.validation import Validator
|
||||
from PyInquirer import prompt
|
||||
import click
|
||||
|
||||
from ..base import app
|
||||
from .validators import Required, ClickValidator
|
||||
|
||||
|
||||
def command(help: str) -> Callable[[Callable], Callable]:
|
||||
def decorator(func) -> Callable:
|
||||
questions = func.__inquirer_questions__.copy()
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
for key, value in kwargs.items():
|
||||
if value is not None and (questions[key]["type"] != "confirm" or value != "null"):
|
||||
questions.pop(key, None)
|
||||
question_list = list(questions.values())
|
||||
question_list.reverse()
|
||||
resp = prompt(question_list, keyboard_interrupt_msg="Aborted!")
|
||||
if not resp and question_list:
|
||||
return
|
||||
kwargs = {**kwargs, **resp}
|
||||
func(*args, **kwargs)
|
||||
|
||||
return app.command(help=help)(wrapper)
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def yesno(val: str) -> Optional[bool]:
|
||||
if not val:
|
||||
return None
|
||||
elif val.lower() in ("true", "t", "yes", "y"):
|
||||
return True
|
||||
elif val.lower() in ("false", "f", "no", "n"):
|
||||
return False
|
||||
|
||||
|
||||
yesno.__name__ = "yes/no"
|
||||
|
||||
|
||||
def option(short: str, long: str, message: str = None, help: str = None,
|
||||
click_type: Union[str, Callable[[str], Any]] = None, inq_type: str = None,
|
||||
validator: Validator = None, required: bool = False, default: str = None,
|
||||
is_flag: bool = False) -> Callable[[Callable], Callable]:
|
||||
if not message:
|
||||
message = long[2].upper() + long[3:]
|
||||
click_type = validator.click_type if isinstance(validator, ClickValidator) else click_type
|
||||
if is_flag:
|
||||
click_type = yesno
|
||||
|
||||
def decorator(func) -> Callable:
|
||||
click.option(short, long, help=help, type=click_type)(func)
|
||||
if not hasattr(func, "__inquirer_questions__"):
|
||||
func.__inquirer_questions__ = {}
|
||||
q = {
|
||||
"type": (inq_type if isinstance(inq_type, str)
|
||||
else ("input" if not is_flag
|
||||
else "confirm")),
|
||||
"name": long[2:],
|
||||
"message": message,
|
||||
}
|
||||
if default is not None:
|
||||
q["default"] = default
|
||||
if required:
|
||||
q["validator"] = Required(validator)
|
||||
elif validator:
|
||||
q["validator"] = validator
|
||||
func.__inquirer_questions__[long[2:]] = q
|
||||
return func
|
||||
|
||||
return decorator
|
96
maubot/cli/cliq/validators.py
Normal file
96
maubot/cli/cliq/validators.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
# maubot - A plugin-based Matrix bot system.
|
||||
# Copyright (C) 2018 Tulir Asokan
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from typing import Callable
|
||||
import pkg_resources
|
||||
import json
|
||||
import os
|
||||
|
||||
from packaging.version import Version, InvalidVersion
|
||||
from prompt_toolkit.validation import Validator, ValidationError
|
||||
from prompt_toolkit.document import Document
|
||||
import click
|
||||
|
||||
|
||||
class Required(Validator):
|
||||
proxy: Validator
|
||||
|
||||
def __init__(self, proxy: Validator = None) -> None:
|
||||
self.proxy = proxy
|
||||
|
||||
def validate(self, document: Document) -> None:
|
||||
if len(document.text) == 0:
|
||||
raise ValidationError(message="This field is required")
|
||||
if self.proxy:
|
||||
return self.proxy.validate(document)
|
||||
|
||||
|
||||
class ClickValidator(Validator):
|
||||
click_type: Callable[[str], str] = None
|
||||
|
||||
@classmethod
|
||||
def validate(cls, document: Document) -> None:
|
||||
try:
|
||||
cls.click_type(document.text)
|
||||
except click.BadParameter as e:
|
||||
raise ValidationError(message=e.message, cursor_position=len(document.text))
|
||||
|
||||
|
||||
def path(val: str) -> str:
|
||||
val = os.path.abspath(val)
|
||||
if os.path.exists(val):
|
||||
return val
|
||||
directory = os.path.dirname(val)
|
||||
if not os.path.isdir(directory):
|
||||
if os.path.exists(directory):
|
||||
raise click.BadParameter(f"{directory} is not a directory")
|
||||
raise click.BadParameter(f"{directory} does not exist")
|
||||
return val
|
||||
|
||||
|
||||
class PathValidator(ClickValidator):
|
||||
click_type = path
|
||||
|
||||
|
||||
def version(val: str) -> Version:
|
||||
try:
|
||||
return Version(val)
|
||||
except InvalidVersion as e:
|
||||
raise click.BadParameter(f"{val} is not a valid PEP-440 version") from e
|
||||
|
||||
|
||||
class VersionValidator(ClickValidator):
|
||||
click_type = version
|
||||
|
||||
|
||||
spdx_list = None
|
||||
|
||||
|
||||
def load_spdx():
|
||||
global spdx_list
|
||||
spdx_data = pkg_resources.resource_stream("maubot.cli", "res/spdx-simple.json")
|
||||
spdx_list = json.load(spdx_data)
|
||||
|
||||
|
||||
def spdx(val: str) -> str:
|
||||
if not spdx_list:
|
||||
load_spdx()
|
||||
if val not in spdx_list:
|
||||
raise click.BadParameter(f"{val} is not a valid SPDX license identifier")
|
||||
return val
|
||||
|
||||
|
||||
class SPDXValidator(ClickValidator):
|
||||
click_type = spdx
|
Loading…
Add table
Add a link
Reference in a new issue