""":mod:`wand.assertions` --- Input assertion helpers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This module checks user input before calling MagickWands C-API methods. .. versionadded:: 0.5.4 """ import numbers try: from collections.abc import Sequence except ImportError: from collections import Sequence from .compat import string_type def assert_bool(**kwargs): """Ensure all given values are boolean. :raises TypeError: if value is not ``True`` or ``False. .. versionadded:: 0.5.4 """ for label, subject in kwargs.items(): if not isinstance(subject, bool): fmt = "{0} must be a bool, not {1}" msg = fmt.format(label, repr(subject)) raise TypeError(msg) def assert_color(**kwargs): """Ensure all given values are instances of :class:`~wand.color.Color`. :raises TypeError: if value is not :class:`~wand.color.Color`. .. versionadded:: 0.5.4 """ for label, subject in kwargs.items(): if not isinstance(subject, Color): fmt = "Expecting an instance of wand.color.Color for {0}, not {1}" msg = fmt.format(label, repr(subject)) raise TypeError(msg) def assert_counting_number(**kwargs): """Ensure all given values are natural integer. :raises TypeError: if value is not an integer. :raises ValueError: if value is less than ``1``. .. versionadded:: 0.5.4 """ assert_integer(**kwargs) for label, subject in kwargs.items(): if subject < 1: fmt = "{0}={1} must be a natural number greater than 0" msg = fmt.format(label, subject) raise ValueError(msg) def assert_integer(**kwargs): """Ensure all given values are an integer. :raises TypeError: if value is not an integer. .. versionadded:: 0.5.4 """ for label, subject in kwargs.items(): if not isinstance(subject, numbers.Integral): fmt = "{0} must be an integer, not {1}" msg = fmt.format(label, repr(subject)) raise TypeError(msg) def assert_real(**kwargs): """Ensure all given values are real numbers. :raises TypeError: if value is not a real number. .. versionadded:: 0.5.4 """ for label, subject in kwargs.items(): if not isinstance(subject, numbers.Real): fmt = "{0} must be a real number, not {1}" msg = fmt.format(label, repr(subject)) raise TypeError(msg) def assert_unsigned_integer(**kwargs): """Ensure all given values are positive integer. :raises TypeError: if value is not an integer. :raises ValueError: if value is less than ``0``. .. versionadded:: 0.5.4 """ assert_integer(**kwargs) for label, subject in kwargs.items(): if subject < 0: fmt = "{0}={1} must be a positive integer" msg = fmt.format(label, subject) raise ValueError(msg) def assert_coordinate(**kwargs): """Ensure all given values are a sequence of 2 real numbers. :raises TypeError: if value is not a pair of doubles. .. versionadded:: 0.6.0 """ for label, subject in kwargs.items(): if not isinstance(subject, Sequence): fmt = "'{0}' must be a pair of real numbers, not {1}" msg = fmt.format(label, repr(subject)) raise TypeError(msg) elif len(subject) != 2: fmt = "'{0}' must be a exactly 2 real numbers, not {1}" msg = fmt.format(label, len(subject)) raise ValueError(msg) elif not isinstance(subject[0], numbers.Real): fmt = "first entry of '{0}' must be a real number, not {1}" msg = fmt.format(label, repr(subject[0])) raise TypeError(msg) elif not isinstance(subject[1], numbers.Real): fmt = "second entry of '{0}' must be a real number, not {1}" msg = fmt.format(label, repr(subject[1])) raise TypeError(msg) def assert_string(**kwargs): for label, subject in kwargs.items(): if not isinstance(subject, string_type): fmt = "{0} must be a string, not {1}" msg = fmt.format(label, repr(subject)) raise TypeError(msg) def in_list(options, label, **kwargs): for subject_label, subject in kwargs.items(): if subject not in options: fmt = "{0} must be defined in {1}, not {2}" msg = fmt.format(subject_label, label, repr(subject)) raise ValueError(msg) def string_in_list(options, label, **kwargs): assert_string(**kwargs) in_list(options, label, **kwargs) # Lazy load recursive import from .color import Color # noqa: E402