184 lines
5.4 KiB
Markdown
184 lines
5.4 KiB
Markdown
|
# 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:
|
||
|
|
||
|
```python
|
||
|
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:
|
||
|
|
||
|
```python
|
||
|
VowelOption('vowel', 'Vowel', 'aae')
|
||
|
```
|
||
|
|
||
|
```python
|
||
|
try:
|
||
|
VowelOption('vowel', 'Vowel', 'oooups')
|
||
|
except ValueError as err:
|
||
|
print(err)
|
||
|
```
|
||
|
|
||
|
returns:
|
||
|
|
||
|
```python
|
||
|
"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:
|
||
|
|
||
|
```python
|
||
|
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:
|
||
|
|
||
|
```python
|
||
|
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?
|
||
|
```
|
||
|
|
||
|
2. the character "e" is in the value and warnings_only is set to True:
|
||
|
|
||
|
```python
|
||
|
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?
|
||
|
```
|
||
|
|
||
|
3. the value is too short
|
||
|
|
||
|
```python
|
||
|
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
|
||
|
```
|
||
|
|
||
|
4. the value is too short and warnings_only is set to True:
|
||
|
|
||
|
```python
|
||
|
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
|
||
|
```
|
||
|
|
||
|
5. set minimum length to 50 characters, the value is valid:
|
||
|
|
||
|
```python
|
||
|
LipogramOption('lipo',
|
||
|
'Lipogram',
|
||
|
'I just want to add a quality string that has no bad symbols',
|
||
|
min_len=50)
|
||
|
```
|