clearml-server/server/apierrors/autogen/generator.py

86 lines
2.7 KiB
Python
Raw Normal View History

2019-06-10 21:24:35 +00:00
import re
import json
import jinja2
import hashlib
from pathlib import Path
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(str(Path(__file__).parent)),
autoescape=jinja2.select_autoescape(disabled_extensions=('py',), default_for_string=False),
trim_blocks=True,
lstrip_blocks=True)
def env_filter(name=None):
return lambda func: env.filters.setdefault(name or func.__name__, func)
@env_filter()
def cls_name(name):
delims = list(map(re.escape, (' ', '_')))
parts = re.split('|'.join(delims), name)
return ''.join(x.capitalize() for x in parts)
class Generator(object):
_base_class_name = 'BaseError'
_base_class_module = 'apierrors.base'
def __init__(self, path, format_pep8=True, use_md5=True):
self._use_md5 = use_md5
self._format_pep8 = format_pep8
self._path = Path(path)
self._path.mkdir(parents=True, exist_ok=True)
def _make_init_file(self, path):
(self._path / path / '__init__.py').write_bytes('')
def _do_render(self, file, template, context):
with file.open('w') as f:
result = template.render(
base_class_name=self._base_class_name,
base_class_module=self._base_class_module,
**context)
if self._format_pep8:
result = autopep8.fix_code(result, options={'aggressive': 1, 'verbose': 0, 'max_line_length': 120})
f.write(result)
def _make_section(self, name, code, subcodes):
self._do_render(
file=(self._path / name).with_suffix('.py'),
template=env.get_template('templates/section.jinja2'),
context=dict(code=code, subcodes=list(subcodes.items()),))
def _make_init(self, sections):
self._do_render(
file=(self._path / '__init__.py'),
template=env.get_template('templates/init.jinja2'),
context=dict(sections=sections,))
def _key_to_str(self, data):
if isinstance(data, dict):
return {str(k): self._key_to_str(v) for k, v in data.items()}
return data
def _calc_digest(self, data):
data = json.dumps(self._key_to_str(data), sort_keys=True)
return hashlib.md5(data.encode('utf8')).hexdigest()
def make_errors(self, errors):
digest = None
digest_file = self._path / 'digest.md5'
if self._use_md5:
digest = self._calc_digest(errors)
if digest_file.is_file():
if digest_file.read_text() == digest:
return
self._make_init(errors)
for (code, section_name), subcodes in errors.items():
self._make_section(section_name, code, subcodes)
if self._use_md5:
digest_file.write_text(digest)