From 5e13bcdd08de4c9c75776ed8f5ea3c3a557bfbfe Mon Sep 17 00:00:00 2001 From: CodeWriter21 Date: Mon, 13 May 2024 16:16:56 +0330 Subject: [PATCH] New exception classes to use with `argumentify`! --- CHANGELOG.md | 6 ++ EXAMPLES.md | 53 ++++++++++++++++ README.md | 7 +- pyproject.toml | 34 +++++----- screen-shots/example-6.4.png | Bin 0 -> 17856 bytes src/log21/Argumentify.py | 120 ++++++++++++++++++++++++++++++----- src/log21/__init__.py | 8 ++- 7 files changed, 190 insertions(+), 38 deletions(-) create mode 100644 screen-shots/example-6.4.png diff --git a/CHANGELOG.md b/CHANGELOG.md index d301e5c..1b5b8f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ Help this project by [Donation](DONATE.md) Changes ------- +### 2.10.0 + ++ Added some exception classes to raise in the "argumentified" functions to show + *parser error* to the user: `ArgumentError`, `IncompatibleArguments`, + `RequiredArgument`, `TooFewArguments` + ### 2.9.2 + Added `Sequence[T]` as a supported type to the ColorizingArgumentParser. diff --git a/EXAMPLES.md b/EXAMPLES.md index a7ac261..45c88fa 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -376,3 +376,56 @@ if __name__ == "__main__": ![multi-entry](https://github.com/MPCodeWriter21/log21/raw/master/screen-shots/example-6.3.png) +Example with parser errors: + +```python +# Common Section +import log21 + + +class ReversedText: + def __init__(self, text: str): + self._text = text[::-1] + + def __str__(self): + return self._text + + def __repr__(self): + return f"<{self.__class__.__name__}(text='{self._text}') at {hex(id(self))}>" + + +# New way +def main(positional_arg: int, /, optional_arg: ReversedText, arg_with_default: int = 21, + additional_arg=None, verbose: bool = False, quiet: bool = False): + """Some description + + :param positional_arg: This argument is positional! + :param optional_arg: Whatever you pass here will be REVERSED! + :param arg_with_default: The default value is 21 + :param additional_arg: This one is extra. + :param verbose: Increase verbosity + :param quiet: Make the script quiet + """ + if verbose and quiet: + raise log21.IncompatibleArguments( + '--verbose', + '--quiet', + message="You can not make the script quiet and except it to be more verbose!" + ) + if verbose: + log21.basic_config(level='DEBUG') + if quiet: + log21.basic_config(level='WARN') + + log21.info(f"{positional_arg = }") + log21.info(f"{optional_arg = !s}") + log21.warn("THIS IS IMPORTANT!!!") + log21.debug(f"{arg_with_default = }") + log21.debug(f"{additional_arg = !s}") + + +if __name__ == '__main__': + log21.argumentify(main) +``` + +![parser-error](https://github.com/MPCodeWriter21/log21/raw/master/screen-shots/example-6.4.png) diff --git a/README.md b/README.md index 5c2ca5a..b086a16 100644 --- a/README.md +++ b/README.md @@ -61,10 +61,11 @@ pip install git+https://github.com/MPCodeWriter21/log21 Changes ------- -### 2.9.2 +### 2.10.0 -+ Added `Sequence[T]` as a supported type to the ColorizingArgumentParser. -+ Bug fixes. ++ Added some exception classes to raise in the "argumentified" functions to show + *parser error* to the user: `ArgumentError`, `IncompatibleArguments`, + `RequiredArgument`, `TooFewArguments` [Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md) diff --git a/pyproject.toml b/pyproject.toml index a0ca303..572ee32 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "log21" authors = [ - {name = "CodeWriter21(Mehrad Pooryoussof)", email = "CodeWriter21@gmail.com"} + {name = "CodeWriter21(Mehrad Pooryoussof)", email = "CodeWriter21@gmail.com"} ] description = "A simple logging package that helps you log colorized messages in Windows console." readme = {file = "README.md", content-type = "text/markdown"} @@ -13,20 +13,20 @@ requires-python = ">=3.8" keywords = ['python', 'log', 'colorize', 'color', 'logging', 'Python3', 'CodeWriter21'] license = {text = "Apache License 2.0"} classifiers = [ - "Intended Audience :: Developers", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Operating System :: Unix", - "Operating System :: Microsoft :: Windows", - "Operating System :: MacOS :: MacOS X" + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Operating System :: Unix", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS :: MacOS X" ] dependencies = [ - "webcolors", - "docstring-parser" + "webcolors", + "docstring-parser" ] -version = "2.9.2" +version = "2.10.0" [tool.setuptools.packages.find] where = ["src"] @@ -43,11 +43,11 @@ dev = ["yapf", "isort", "docformatter", "pylint", "json5", "pytest"] max-line-length = 88 disable = [ - "too-few-public-methods", - "too-many-arguments", - "protected-access", - "too-many-locals", - "fixme", + "too-few-public-methods", + "too-many-arguments", + "protected-access", + "too-many-locals", + "fixme", ] [tool.pylint.design] diff --git a/screen-shots/example-6.4.png b/screen-shots/example-6.4.png new file mode 100644 index 0000000000000000000000000000000000000000..e0c3c05c95e3ce0e9f1abf336a6860fbdbceeb88 GIT binary patch literal 17856 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 1: + message = "There is a problem with the arguments: " + ', '.join( + f"`{arg}`" for arg in args + ) + else: + message = "The argument `" + args[0] + "` is invalid." + self.message = message + self.arguments = args + + +class IncompatibleArguments(ArgumentError): + """Raise when the user has used arguments that are incompatible with each other.""" + + def __init__(self, *args, message: _Optional[str] = None): + """Initialize the exception. + + :param args: The arguments that are incompatible. + :param message: The error message to show. + """ + super().__init__(*args, message) + if message is None: + if args: + if len(args) > 1: + message = "You cannot use all these together: " + ', '.join( + f"`{arg}`" for arg in args + ) + else: + message = "The argument `" + args[0] + "` is not compatible." + self.message = message + + +class RequiredArgument(ArgumentError): + """Raise this when there is a required argument missing.""" + + def __init__(self, *args, message: _Optional[str] = None): + """Initialize the exception. + + :param args: The arguments that are required. + :param message: The error message to show. + """ + super().__init__(*args, message) + if message is None: + if args: + if len(args) > 1: + message = "These arguments are required: " + ', '.join( + f"`{arg}`" for arg in args + ) + else: + message = "The argument `" + args[0] + "` is required." + self.message = message + + +class TooFewArguments(ArgumentError): + """Raise this when there were not enough arguments passed.""" + + def __init__(self, *args, message: _Optional[str] = None): + """Initialize the exception. + + :param args: The arguments that should be passed. + :param message: The error message to show. + """ + super().__init__(*args, message) + if message is None: + if args: + if len(args) > 1: + message = "You should use these arguments: " + ', '.join( + f"`{arg}`" for arg in args + ) + else: + message = "The argument `" + args[0] + "` should be used." + self.message = message + + def normalize_name_to_snake_case(name: str, sep_char: str = '_') -> str: """Returns the normalized name a class. @@ -278,8 +363,7 @@ def _add_arguments( def _argumentify_one(func: Callable): - """This function argumentifies one function as the entry point of the - script. + """This function argumentifies one function as the entry point of the script. :param function: The function to argumentify. """ @@ -312,15 +396,18 @@ def _argumentify_one(func: Callable): args.extend(getattr(cli_args, argument.name) or []) else: kwargs[argument.name] = getattr(cli_args, argument.name) - result = func(*args, **kwargs) - # Check if the result is a coroutine - if isinstance(result, (_Coroutine, _Awaitable)): - _asyncio.run(result) + try: + result = func(*args, **kwargs) + # Check if the result is a coroutine + if isinstance(result, (_Coroutine, _Awaitable)): + _asyncio.run(result) + except ArgumentError as error: + parser.error(error.message) def _argumentify(functions: _Dict[str, Callable]): - """This function argumentifies one or more functions as the entry point of - the script. + """This function argumentifies one or more functions as the entry point of the + script. :param functions: A dictionary of functions to argumentify. :raises RuntimeError: @@ -361,15 +448,18 @@ def _argumentify(functions: _Dict[str, Callable]): args.extend(getattr(cli_args, argument.name) or []) else: kwargs[argument.name] = getattr(cli_args, argument.name) - result = function(*args, **kwargs) - # Check if the result is a coroutine - if isinstance(result, (_Coroutine, _Awaitable)): - _asyncio.run(result) + try: + result = function(*args, **kwargs) + # Check if the result is a coroutine + if isinstance(result, (_Coroutine, _Awaitable)): + _asyncio.run(result) + except ArgumentError as error: + parser.error(error.message) def argumentify(entry_point: _Union[Callable, _List[Callable], _Dict[str, Callable]]): - """This function argumentifies one or more functions as the entry point of - the script. + """This function argumentifies one or more functions as the entry point of the + script. 1 #!/usr/bin/env python 2 # argumentified.py diff --git a/src/log21/__init__.py b/src/log21/__init__.py index 6c4a446..52438fd 100644 --- a/src/log21/__init__.py +++ b/src/log21/__init__.py @@ -16,14 +16,15 @@ from .Argparse import ColorizingArgumentParser from .TreePrint import TreePrint, tree_format from .Formatters import ColorizingFormatter, DecolorizingFormatter, _Formatter -from .Argumentify import argumentify +from .Argumentify import (ArgumentError, TooFewArguments, RequiredArgument, + IncompatibleArguments, argumentify) from .FileHandler import FileHandler, DecolorizingFileHandler from .ProgressBar import ProgressBar from .LoggingWindow import LoggingWindow, LoggingWindowHandler from .StreamHandler import StreamHandler, ColorizingStreamHandler __author__ = 'CodeWriter21 (Mehrad Pooryoussof)' -__version__ = '2.9.2' +__version__ = '2.10.0' __github__ = 'Https://GitHub.com/MPCodeWriter21/log21' __all__ = [ 'ColorizingStreamHandler', 'DecolorizingFileHandler', 'ColorizingFormatter', @@ -35,7 +36,8 @@ 'debug', 'info', 'warning', 'warn', 'error', 'critical', 'fatal', 'exception', 'log', 'basic_config', 'basicConfig', 'ProgressBar', 'progress_bar', 'LoggingWindow', 'LoggingWindowHandler', 'get_logging_window', 'CrashReporter', - 'console_reporter', 'file_reporter', 'argumentify' + 'console_reporter', 'file_reporter', 'argumentify', 'ArgumentError', + 'IncompatibleArguments', 'RequiredArgument', 'TooFewArguments' ] _manager = Manager()