ValiDecor


NameValiDecor JSON
Version 1.0.3 PyPI version JSON
download
home_pageNone
SummaryDecorated, Annotated, Validated
upload_time2024-07-11 15:49:06
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseMIT License Copyright (c) 2024 giladrv 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.
keywords validation decorator lambda
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # ValiDecor

ValiDecor is a Python library designed to facilitate robust input validation using its core decorator `validecor`. It leverages Python's type annotation system to provide a seamless and intuitive interface for enforcing input constraints directly in function signatures using the special annotation type `typing.Annotated`.

ValiDecor was designed with special attention for its potential use on AWS Lambda functions. AWS Lambda handlers expect a fixed signature, i.e. `handler(event, context)`. This signature is uninformative and hinders code development. Refer to the [Advanced Usage](#advanced) section for more details.

## Installation

Install ValiDecor via pip:

    pip install ValiDecor

## Usage

### Basic Usage

To use ValiDecor, annotate function arguments with the desired validators wrapped inside `typing.Annotated`, and apply the `@validecor()` decorator to the function. Here is a basic example:

    from typing import Annotated
    from validecor import validecor
    from validecor.validators import IsType

    @validecor()
    def hello(msg: Annotated[str, IsType(str)]):
        print('Message:', msg)

### Advanced Usage (AWS Lambda)<a name="advanced"></a>

The `validecor` decorator accepts several parameters to customized its usage. One can define the function signature expected by the caller, and automatically map the input to actually relevant arguments needed by the function. This is best explained with an example:

    from typing import Annotated
    from validecor import Attr, Map, validecor

    # we define the source function signature
    def handler(event, context):
        pass
    
    # extend the Map class for better readability later
    class MapS3(Map):
        def __init__(self, *nodes: int | str | Callable[..., Any]):
            super().__init__('event', 'Records', 0, 's3', *nodes)

    # some function to be applied during the mapping
    def to_mb(size_in_bytes: float):
        return size_in_bytes / 1024 / 1024

    @validecor(handler)
    def s3_trigger(
        bucket: Annotated[str, MapS3('bucket', 'name')],
        key: Annotated[str, MapS3('object', 'key')],
        size: Annotated[float, MapS3('object', 'size', to_mb)],
        mem: Annotated[int, Map('context', Attr('memory_limit_in_mb'))]):
        ...

This way we only get the arguments relevant for the function operation, with helpful type hints, and don't need to bother with extracting them from the original `event` or `context` inputs within the function body.

Maps will be cached internally so as not to reapeat potentially expensive operations.

### Callback Hooks

The `validecor` decorator supports the following hooks:

#### Initialization And Logging

    pre_hook: Callable[[*source_args, **source_kwargs], Any] = default_log_hook
    
This hook is called with the same arguments as the original function. Can be used for logging or halting the rest of the function execution by returning any `not None` value, which is then returned to the original caller. By default no action is performed.

#### Validation Handling

    val_hook: Callable[[Exception, Validator | ExtendedValidator], Any] = default_val_hook

This hook is called upon validation errors (or Map failures). Use this to return a custom error message to the user. By default the exception is re-raised unchanged.

#### Function Errors

    err_hook: Callable[[Exception, *target_args, **target_kwargs], Any] = default_err_hook

This hook is called when an exception is raised within the function body. The return value of the hook is the final value returned to the original caller. By default the exception is re-raised unchanged.

#### Post-Processing

    map_hook: Callable[[Any], Any] = default_map_hook

This hook is called with the results of the function to enable any post-processing. The return value of the hook is the final value returned to the original caller. By default passes along the same value returned by the function.

### Custom Validators

You can create custom validators in two ways: using the `validators.Custom` class which accepts any `Callable`, or by extending the `Validator` or `ExtendedValidator` classes from `validecor.core`. Here's how to create a custom validator that ensures a number is positive:

    from validecor.core import Validator

    class IsPositive(Validator):
        def __call__(self, arg):
            try:
                if arg <= 0:
                    raise ValueError(f"Invalid value: {arg}")
            except ValueError:
                raise
            except Exception as e:
                raise ValueError(f'Uncomparable value: {arg}', e)
        def __desc__(self):
            return "Argument must be a positive number."

    @validecor()
    def increment(number: Annotated[int, IsPositive()]):
        return number + 1

Typically we would want the description to be general for the validation class, and the error message to contain some clue as to why the validation failed, e.g. by noting the argument value or type.

## Contributing

Contributions to ValiDecor are welcome! Fork the repository, make your changes, and submit a pull request to contribute.

## License

ValiDecor is released under the MIT License. See the LICENSE file for more details.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "ValiDecor",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "validation, decorator, lambda",
    "author": null,
    "author_email": "giladooshlon <giladrv@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/34/22/ee3a3bb9430faa974f103c4e33c9a6aa8df87e705df949a921cc87b7dd9f/validecor-1.0.3.tar.gz",
    "platform": null,
    "description": "# ValiDecor\n\nValiDecor is a Python library designed to facilitate robust input validation using its core decorator `validecor`. It leverages Python's type annotation system to provide a seamless and intuitive interface for enforcing input constraints directly in function signatures using the special annotation type `typing.Annotated`.\n\nValiDecor was designed with special attention for its potential use on AWS Lambda functions. AWS Lambda handlers expect a fixed signature, i.e. `handler(event, context)`. This signature is uninformative and hinders code development. Refer to the [Advanced Usage](#advanced) section for more details.\n\n## Installation\n\nInstall ValiDecor via pip:\n\n    pip install ValiDecor\n\n## Usage\n\n### Basic Usage\n\nTo use ValiDecor, annotate function arguments with the desired validators wrapped inside `typing.Annotated`, and apply the `@validecor()` decorator to the function. Here is a basic example:\n\n    from typing import Annotated\n    from validecor import validecor\n    from validecor.validators import IsType\n\n    @validecor()\n    def hello(msg: Annotated[str, IsType(str)]):\n        print('Message:', msg)\n\n### Advanced Usage (AWS Lambda)<a name=\"advanced\"></a>\n\nThe `validecor` decorator accepts several parameters to customized its usage. One can define the function signature expected by the caller, and automatically map the input to actually relevant arguments needed by the function. This is best explained with an example:\n\n    from typing import Annotated\n    from validecor import Attr, Map, validecor\n\n    # we define the source function signature\n    def handler(event, context):\n        pass\n    \n    # extend the Map class for better readability later\n    class MapS3(Map):\n        def __init__(self, *nodes: int | str | Callable[..., Any]):\n            super().__init__('event', 'Records', 0, 's3', *nodes)\n\n    # some function to be applied during the mapping\n    def to_mb(size_in_bytes: float):\n        return size_in_bytes / 1024 / 1024\n\n    @validecor(handler)\n    def s3_trigger(\n        bucket: Annotated[str, MapS3('bucket', 'name')],\n        key: Annotated[str, MapS3('object', 'key')],\n        size: Annotated[float, MapS3('object', 'size', to_mb)],\n        mem: Annotated[int, Map('context', Attr('memory_limit_in_mb'))]):\n        ...\n\nThis way we only get the arguments relevant for the function operation, with helpful type hints, and don't need to bother with extracting them from the original `event` or `context` inputs within the function body.\n\nMaps will be cached internally so as not to reapeat potentially expensive operations.\n\n### Callback Hooks\n\nThe `validecor` decorator supports the following hooks:\n\n#### Initialization And Logging\n\n    pre_hook: Callable[[*source_args, **source_kwargs], Any] = default_log_hook\n    \nThis hook is called with the same arguments as the original function. Can be used for logging or halting the rest of the function execution by returning any `not None` value, which is then returned to the original caller. By default no action is performed.\n\n#### Validation Handling\n\n    val_hook: Callable[[Exception, Validator | ExtendedValidator], Any] = default_val_hook\n\nThis hook is called upon validation errors (or Map failures). Use this to return a custom error message to the user. By default the exception is re-raised unchanged.\n\n#### Function Errors\n\n    err_hook: Callable[[Exception, *target_args, **target_kwargs], Any] = default_err_hook\n\nThis hook is called when an exception is raised within the function body. The return value of the hook is the final value returned to the original caller. By default the exception is re-raised unchanged.\n\n#### Post-Processing\n\n    map_hook: Callable[[Any], Any] = default_map_hook\n\nThis hook is called with the results of the function to enable any post-processing. The return value of the hook is the final value returned to the original caller. By default passes along the same value returned by the function.\n\n### Custom Validators\n\nYou can create custom validators in two ways: using the `validators.Custom` class which accepts any `Callable`, or by extending the `Validator` or `ExtendedValidator` classes from `validecor.core`. Here's how to create a custom validator that ensures a number is positive:\n\n    from validecor.core import Validator\n\n    class IsPositive(Validator):\n        def __call__(self, arg):\n            try:\n                if arg <= 0:\n                    raise ValueError(f\"Invalid value: {arg}\")\n            except ValueError:\n                raise\n            except Exception as e:\n                raise ValueError(f'Uncomparable value: {arg}', e)\n        def __desc__(self):\n            return \"Argument must be a positive number.\"\n\n    @validecor()\n    def increment(number: Annotated[int, IsPositive()]):\n        return number + 1\n\nTypically we would want the description to be general for the validation class, and the error message to contain some clue as to why the validation failed, e.g. by noting the argument value or type.\n\n## Contributing\n\nContributions to ValiDecor are welcome! Fork the repository, make your changes, and submit a pull request to contribute.\n\n## License\n\nValiDecor is released under the MIT License. See the LICENSE file for more details.\n",
    "bugtrack_url": null,
    "license": "MIT License  Copyright (c) 2024 giladrv  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. ",
    "summary": "Decorated, Annotated, Validated",
    "version": "1.0.3",
    "project_urls": {
        "Homepage": "https://github.com/giladrv/validecor"
    },
    "split_keywords": [
        "validation",
        " decorator",
        " lambda"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bbf3db489ed31879df5997713a904ad50b23a792248a1e9d8f0f5f7a77946695",
                "md5": "42625b358f71dfa37c13ffebdf54b000",
                "sha256": "12dcf0780fc60d3a037255ccff4b7a6088edbc910e2c39654996389d375cee7e"
            },
            "downloads": -1,
            "filename": "ValiDecor-1.0.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "42625b358f71dfa37c13ffebdf54b000",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 12305,
            "upload_time": "2024-07-11T15:49:05",
            "upload_time_iso_8601": "2024-07-11T15:49:05.083375Z",
            "url": "https://files.pythonhosted.org/packages/bb/f3/db489ed31879df5997713a904ad50b23a792248a1e9d8f0f5f7a77946695/ValiDecor-1.0.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3422ee3a3bb9430faa974f103c4e33c9a6aa8df87e705df949a921cc87b7dd9f",
                "md5": "ae2a3e049360633fb8cbdb9cfe15b29d",
                "sha256": "151d1040070896e367c3b34ed34b7cd8536f67321e1e71553c5bca7ee188aa00"
            },
            "downloads": -1,
            "filename": "validecor-1.0.3.tar.gz",
            "has_sig": false,
            "md5_digest": "ae2a3e049360633fb8cbdb9cfe15b29d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 10930,
            "upload_time": "2024-07-11T15:49:06",
            "upload_time_iso_8601": "2024-07-11T15:49:06.950476Z",
            "url": "https://files.pythonhosted.org/packages/34/22/ee3a3bb9430faa974f103c4e33c9a6aa8df87e705df949a921cc87b7dd9f/validecor-1.0.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-07-11 15:49:06",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "giladrv",
    "github_project": "validecor",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "validecor"
}
        
Elapsed time: 0.64575s