Source code for otoole.validate
"""Ensures that technology and fuel names match the convention
For example, to validate the following list of names, you would use the
config shown below::
theseUNIQUE_ENTRY1
are__UNIQUE_ENTRY2
all__UNIQUE_ENTRY1
validUNIQUE_ENTRY2
entryUNIQUE_ENTRY1
in__UNIQUE_ENTRY2
a____UNIQUE_ENTRY1
list_UNIQUE_ENTRY2
Create a yaml validation config with the following format::
codes:
some_valid_codes:
UNIQUE_ENTRY1: Description of unique entry 1
UNIQUE_ENTRY2: Description of unique entry 2
schema:
schema_name:
- name: first_entry_in_schema
valid: ['these', 'are__', 'all__', 'valid', 'entry', 'in__', 'a____', 'list_']
position: (1, 5) # a tuple representing the start and end position
- name: second_entry_in_schema
valid: some_valid_codes # references an entry in the codes section of the config
position: (6, 19) # a tuple representing the start and end position
"""
import logging
import re
from typing import Dict, List
from otoole import read_packaged_file
logger = logging.getLogger(__name__)
[docs]def read_validation_config():
return read_packaged_file('validate.yaml', 'otoole')
[docs]def create_schema(config: Dict = None):
"""Populate the dict of schema with codes from the validation config
Arguments
---------
config : dict, default=None
A configuration dictionary containing ``codes`` and ``schema`` keys
"""
if config is None:
config = read_validation_config()
for _, schema in config['schema'].items():
for name in schema:
if isinstance(name['valid'], str):
name['valid'] = list(config['codes'][name['valid']].keys())
return config['schema']
[docs]def compose_expression(schema: List) -> str:
"""Generates a regular expression from a schema
Returns
-------
str
"""
expression = "^"
for x in schema:
valid_entries = "|".join(x['valid'])
expression += "({})".format(valid_entries)
return expression
[docs]def validate(expression: str, name: str) -> bool:
"""Determine if ``name`` matches the ``expression``
Arguments
---------
expression : str
name : str
Returns
-------
bool
"""
valid = False
pattern = re.compile(expression)
if pattern.fullmatch(name):
msg = "{} is valid"
valid = True
else:
msg = "{} is invalid"
valid = False
logger.debug(msg.format(name))
return valid
[docs]def validate_fuel_name(name: str) -> bool:
"""Validate a fuel name
Arguments
---------
name : str
country_codes : list
fuel_codes : list
Returns
-------
True if ``name`` is valid according to ``country_codes`` and ``fuel_codes``
otherwise False
"""
schema = create_schema()
expression = compose_expression(schema['fuel_name'])
valid = validate(expression, name)
return valid