tiramisu/doc/own_option.md

5.4 KiB

Create it's own option

Generic regexp option: "RegexpOption"

Use "RegexpOption" to create custom option is very simple.

You just have to create an object that inherits from "RegexpOption" and that has the following class attributes:

  • __slots__: with new data members (the values should always be "tuple()")
  • _type = with a name
  • _display_name: with the display name (for example in error message)
  • _regexp: with a compiled regexp

Here an example to an option that only accept string with on lowercase ASCII vowel characters:

import re
from tiramisu import RegexpOption
class VowelOption(RegexpOption):
    __slots__ = tuple()
    _type = 'vowel'
    _display_name = "string with vowel"
    _regexp = re.compile(r"^[aeiouy]*$")

Let's try our object:

VowelOption('vowel', 'Vowel', 'aae')
try:
    VowelOption('vowel', 'Vowel', 'oooups')
except ValueError as err:
    print(err)

returns:

"oooups" is an invalid string with vowel for "Vowel"

Create a custom option

An option always inherits from "Option" object. This object has the following class attributes:

  • __slots__: a tuple with new data members (by default you should set "tuple()")
  • _type = with a name
  • _display_name: with the display name (for example in error message)

Here an example to an lipogram option:

from tiramisu import Option
from tiramisu.error import ValueWarning
import warnings

class LipogramOption(Option):
    __slots__ = tuple()
    _type = 'lipogram'
    _display_name = 'lipogram'
    #
    # First of all we want to add a custom parameter to ask the minimum length (min_len) of the value:
    def __init__(self,
                 *args,
                 min_len=100,
                 **kwargs):
        # store extra parameters
        extra = {'_min_len': min_len}
        super().__init__(*args,
                         extra=extra,
                         **kwargs)
    #
    # We have a first validation method.
    # In this method, we verify that the value is a string and that there is no "e" on it:
    # Even if user set warnings_only attribute, this method will raise.
    def validate(self,
                 value):
        # first, valid that the value is a string
        if not isinstance(value, str):
            raise ValueError('invalid string')
        # and verify that there is any 'e' in the sentense
        if 'e' in value:
            raise ValueError('Perec wrote a book without any "e", you could not do it in a simple sentence?')
    #
    # Finally we add a method to valid the value length.
    # If "warnings_only" is set to True, a warning will be emit:
    def second_level_validation(self,
                                value,
                                warnings_only):
        # retrive parameter in extra
        min_len = self.impl_get_extra('_min_len')
        # verify the sentense length
        if len(value) < min_len:
            # raise message, in this case, warning and error message are different
            if warnings_only:
                msg = f'it would be better to have at least {min_len} characters in the sentence'
            else:
                msg = f'you must have at least {min_len} characters in the sentence'
            raise ValueError(msg)

Let's test it:

  1. the character "e" is in the value:
try:
    LipogramOption('lipo',
                   'Lipogram',
                   'I just want to add a quality string that has no bad characters')
except ValueError as err:
    print(err)

returns:

"I just want to add a quality string that has no bad characters" is an invalid lipogram for "Lipogram", Perec wrote a book without any "e", you could not do it in a simple sentence?
  1. the character "e" is in the value and warnings_only is set to True:
try:
    LipogramOption('lipo',
                   'Lipogram',
                   'I just want to add a quality string that has no bad characters',
                   warnings_only=True)
except ValueError as err:
    print(err)
"I just want to add a quality string that has no bad characters" is an invalid lipogram for "Lipogram", Perec wrote a book without any "e", you could not do it in a simple sentence?
  1. the value is too short
try:
    LipogramOption('lipo',
                   'Lipogram',
                   'I just want to add a quality string that has no bad symbols')
except ValueError as err:
    print(err)

returns:

"I just want to add a quality string that has no bad symbols" is an invalid lipogram for "Lipogram", you must have at least 100 characters in the sentence
  1. the value is too short and warnings_only is set to True:
warnings.simplefilter('always', ValueWarning)
with warnings.catch_warnings(record=True) as warn:
   LipogramOption('lipo',
                  'Lipogram',
                  'I just want to add a quality string that has no bad symbols',
                  warnings_only=True)
   if warn:
       print(warn[0].message)

returns:

attention, "I just want to add a quality string that has no bad symbols" could be an invalid lipogram for "Lipogram", it would be better to have at least 100 characters in the sentence
  1. set minimum length to 50 characters, the value is valid:
LipogramOption('lipo',
               'Lipogram',
               'I just want to add a quality string that has no bad symbols',
               min_len=50)