#!/usr/bin/env python3
# -*- coding: utf-8 -*-
###################
# This package implements tools for WebScripts Scripts
# Copyright (C) 2022, 2023 Maurice Lambert
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
###################
"""
This package implements tools for WebScripts Scripts.
"""
__version__ = "0.1.0"
__author__ = "Maurice Lambert"
__author_email__ = "mauricelambert434@gmail.com"
__maintainer__ = "Maurice Lambert"
__maintainer_email__ = "mauricelambert434@gmail.com"
__description__ = """
This package implements tools for WebScripts Scripts.
"""
license = "GPL-3.0 License"
__url__ = "https://github.com/mauricelambert/WebScriptsTools"
copyright = """
WebScriptsTools Copyright (C) 2022, 2023 Maurice Lambert
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
"""
__license__ = license
__copyright__ = copyright
__all__ = [
"get_webscripts_data_path",
"get_upload_module",
"get_upload_script",
"set_excepthook",
"get_log_file",
"module2to3",
"get_user",
"main",
]
from importlib.util import spec_from_file_location, module_from_spec
from types import ModuleType, MethodType, FunctionType
from os.path import join, splitext, basename
from contextlib import redirect_stdout
from collections.abc import Callable
from typing import Dict, Union, Any
from sys import exit, stderr, argv
from os import environ, makedirs
from types import TracebackType
from json import loads, dumps
from functools import wraps
from sys import excepthook # save default excepthook function
from typing import List
import sys
environ_get: Callable = environ.get
def get_upload_module() -> ModuleType:
"""
This function returns the WebScripts upload module.
"""
upload_path = join(
environ_get("WEBSCRIPTS_PATH"),
"scripts",
"uploads",
"modules",
"uploads_management.py",
)
spec = spec_from_file_location("uploads", upload_path)
upload = module_from_spec(spec)
spec.loader.exec_module(upload)
return upload
def get_webscripts_data_path() -> str:
"""
This function returns the path to the data directory.
"""
return environ["WEBSCRIPTS_DATA_PATH"]
def get_log_file() -> str:
"""
This function returns the log path
for WebScripts scripts.
"""
logpath = environ["WEBSCRIPTS_LOGS_PATH"].split("|", 1)[0]
script = loads(environ["SCRIPT_CONFIG"])
name = script.get("name")
category = environ_get("category", "nocategory")
directory = join(logpath, "scripts", category)
file = join(directory, f"{splitext(name)[0]}.log")
makedirs(directory, exist_ok=True)
return file
def get_log_files() -> str:
"""
This function returns the log files paths
used by WebScripts.
"""
return environ["WEBSCRIPTS_LOGS_FILES"].split("|")
def get_log_directories() -> List[str]:
"""
This function returns the log directories
used by WebScripts.
"""
return environ["WEBSCRIPTS_LOGS_PATH"].split("|")
def get_documentation_directories() -> List[str]:
"""
This function returns the documentation directories
used by WebScripts.
"""
return environ["WEBSCRIPTS_DOCUMENTATION_PATH"].split(":")
def get_webscripts_modules() -> List[str]:
"""
This function returns the modules files paths
used by WebScripts.
"""
return environ["WEBSCRIPTS_MODULES"].split(":")
def get_user() -> Dict[str, str]:
"""
This function returns the WebScripts user.
"""
return loads(environ_get("USER"))
def print_exception(
exception_class: type, exception: Exception, traceback: TracebackType
) -> None:
"""
This function prints exception and exit without prints sensible
informations about the system and the code (file path, code, ect...).
"""
try:
function = getattr(exception, "function_name", None)
text = repr(exception) + (
f" from:{function!r}" if function is not None else ""
)
with redirect_stdout(stderr):
cause: Exception = exception.__cause__
while cause:
function = getattr(cause, "function_name", None)
text = (
f"{cause!r}"
f"{f' from:{function!r}' if function is not None else ''}"
f"[{text}]"
)
cause = cause.__cause__
filename = basename(traceback.tb_frame.f_code.co_filename)
print(f"{filename!r}:{traceback.tb_lineno!r} -> {text}")
finally:
exit(getattr(exception, "exit_code", 127))
def set_excepthook() -> None:
"""
This function sets sys.excepthook to secure
sensible informations on python errors.
"""
sys.excepthook = print_exception
def get_upload_script() -> str:
"""
This function prints the upload script path.
"""
return join(
environ_get("WEBSCRIPTS_PATH"),
"scripts",
"uploads",
"upload_file.py",
)
def module2to3(callable_: Union[FunctionType, MethodType]) -> FunctionType:
"""
This decorator make compatibility between the module
functions of version 2 and version 3 of WebScripts.
"""
@wraps(callable_)
def function(*args, **kwargs) -> Any:
"""
This decorator make compatibility between the module
functions of version 2 and version 3 of WebScripts.
"""
environ, user, server, filename, command, inputs = args
return callable_(
environ,
user,
server.configuration,
filename,
command,
inputs,
**kwargs,
)
@wraps(callable_)
def method(*args, **kwargs) -> Any:
"""
This decorator make compatibility between the module
functions of version 2 and version 3 of WebScripts.
"""
self, environ, user, server, filename, command, inputs = args
return callable_(
self,
environ,
user,
server.configuration,
filename,
command,
inputs,
**kwargs,
)
arg_length = callable_.__code__.co_argcount
if arg_length == 7:
return function
elif arg_length == 8:
return method
def main() -> int:
"""
This function execute scripts
tools from the command line.
"""
functions = (
"get_log_file",
"get_log_files",
"get_upload_script",
"get_log_directories",
"get_webscripts_modules",
"get_webscripts_data_path",
"get_documentation_directories",
)
if len(argv) != 2 or argv[1] not in functions:
print(
f"USAGES: {argv[0]} \n"
"\tAvailable tools are:\n\t - " + "\n\t - ".join(functions)
)
return 1
data = globals()[argv[1]]()
if isinstance(data, list):
data = dumps(data)
print(data)
return 0
if __name__ == "__main__":
# print(copyright)
exit(main())