1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
#
# Copyright (c), 2016-2024, SISSA (International School for Advanced Studies).
# All rights reserved.
# This file is distributed under the terms of the MIT License.
# See the file 'LICENSE' in the root directory of the present
# distribution, or http://opensource.org/licenses/MIT.
#
# @author Davide Brunato <brunato@sissa.it>
#
import warnings
from functools import wraps
from collections.abc import Callable, Iterator
from typing import cast, Any, TypeVar
from xmlschema.exceptions import XMLSchemaException, XMLSchemaValueError, \
XMLSchemaTypeError, XMLSchemaAttributeError, XMLSchemaKeyError, \
XMLSchemaRuntimeError
def is_subclass(t: type[Any], cls: type[Any]) -> bool:
"""A safe subclass checker."""
return isinstance(t, type) and issubclass(t, cls)
def iter_class_slots(obj: Any) -> Iterator[str]:
"""Iterates slots defined for a class and its bases."""
for cls in obj.__class__.__mro__:
if hasattr(cls, '__slots__'):
yield from cls.__slots__
FT = TypeVar('FT', bound=Callable[..., Any])
RT = TypeVar('RT')
def catchable_xmlschema_error(func: FT) -> FT:
"""Force a function to raise only an XMLSchemaException or a subclass of it."""
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
try:
return func(*args, **kwargs)
except XMLSchemaException:
raise
except ValueError as err:
raise XMLSchemaValueError(err)
except TypeError as err:
raise XMLSchemaTypeError(err)
except AttributeError as err:
raise XMLSchemaAttributeError(err)
except KeyError as err:
raise XMLSchemaKeyError(err)
except RuntimeError as err:
raise XMLSchemaRuntimeError(err)
return cast(FT, wrapper)
def deprecated(version: str, stacklevel: int = 1, alt: str = '') \
-> Callable[[Callable[..., RT]], Callable[..., RT]]:
def decorator(func: Callable[..., RT]) -> Callable[..., RT]:
msg = f"{func.__qualname__!r} will be removed in v{version}."
if alt:
msg = f"{msg[:-1]}, {alt}."
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> RT:
warnings.warn(msg, DeprecationWarning, stacklevel=stacklevel + 1)
return func(*args, **kwargs)
return wrapper
return decorator
def will_change(version: str, stacklevel: int = 1, alt: str = '') \
-> Callable[[Callable[..., RT]], Callable[..., RT]]:
def decorator(func: Callable[..., RT]) -> Callable[..., RT]:
msg = f"{func.__qualname__!r} will change from v{version}."
if alt:
msg = f"{msg[:-1]}, {alt}."
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> RT:
warnings.warn(msg, FutureWarning, stacklevel=stacklevel + 1)
return func(*args, **kwargs)
return wrapper
return decorator
|