schmeckels/validate.py
2020-10-30 23:06:56 +01:00

98 lines
3.4 KiB
Python

#! /usr/bin/env python3
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from helper import list_profiles, build_rules_filename, build_database_filename
from schwifty import IBAN
import sys
import click
import os
import yaml
import re
import colorful as cf
try:
from yaml import CLoader as Loader, CDumper as Dumper
except ImportError:
from yaml import Loader, Dumper
ALLOWED_KEYS = ["name", "tags", "iban", "description"]
TAGS_REGEXP = re.compile(r'[\w]+(?:,\s{0,1}[\w]+)*')
def verbose_print(text, verbose):
if verbose:
print(text)
@click.command(name="validate")
@click.option("--verbose", "-v", default=False, is_flag=True)
def command(verbose):
for profile in list_profiles():
print(f"Checking {profile}:")
db_path = build_database_filename(profile)
rules_path = build_rules_filename(profile)
# Rules
if os.path.exists(rules_path) and os.path.isfile(rules_path):
with open(rules_path) as fh:
data = yaml.load(fh, Loader=Loader)
if not data:
print(cf.green(" Ruleset is empty"))
else:
errors = 0
for rule in data:
# validate yaml keys:
for key in rule.keys():
if key not in ALLOWED_KEYS:
verbose_print(cf.red(f"Rule uses the invalid key '{key}': {rule}"),verbose)
errors+=1
if not rule.get("tags"):
verbose_print(cf.red(f"Rule has no tags: {rule}"),verbose)
errors+=1
if not TAGS_REGEXP.fullmatch(rule.get("tags")):
verbose_print(cf.red(f"Rule has an invalid list of tags: {rule}"),verbose)
errors+=1
# validate name regex
if rule.get("name"):
try:
re.compile(rule["name"])
except:
verbose_print(cf.red(f" Invalid name regex: '{rule.get('name')}'"),verbose)
errors+=1
# validate description regex
if rule.get("description"):
try:
re.compile(rule["description"])
except:
verbose_print(cf.red(f" Invalid description regex: '{rule.get('description')}'"),verbose)
errors+=1
# validate IBAN
if rule.get("iban"):
try:
IBAN(rule.get("iban"))
except:
verbose_print(cf.red(f" Invalid IBAN: '{rule.get('iban')}'"), verbose)
errors+=1
if errors == 0:
print(cf.green(f" All rules are valid"))
else:
print(cf.red(f" Found {errors} invalid rules"))
else:
print(cf.red(f" The rule file doesn't exists"))
sys.exit(1)
# Database
if os.path.exists(db_path) and os.path.isfile(db_path):
print(cf.green(f" Database exists"))
else:
print(cf.red(f" The database file doesn't exists"))
sys.exit(1)