aboutsummaryrefslogtreecommitdiff
path: root/src_py
diff options
context:
space:
mode:
Diffstat (limited to 'src_py')
-rw-r--r--src_py/opcut/doit/_common.py28
-rw-r--r--src_py/opcut/doit/jsopcut.py85
-rw-r--r--src_py/opcut/doit/main.py46
-rw-r--r--src_py/opcut/doit/pyopcut.py104
4 files changed, 263 insertions, 0 deletions
diff --git a/src_py/opcut/doit/_common.py b/src_py/opcut/doit/_common.py
new file mode 100644
index 0000000..8e33791
--- /dev/null
+++ b/src_py/opcut/doit/_common.py
@@ -0,0 +1,28 @@
+import os
+import shutil
+from pathlib import Path
+
+
+def mkdir_p(*paths):
+ for path in paths:
+ os.makedirs(str(Path(path)), exist_ok=True)
+
+
+def rm_rf(*paths):
+ for path in paths:
+ p = Path(path)
+ if not p.exists():
+ continue
+ if p.is_dir():
+ shutil.rmtree(str(p), ignore_errors=True)
+ else:
+ p.unlink()
+
+
+def cp_r(src, dest):
+ src = Path(src)
+ dest = Path(dest)
+ if src.is_dir():
+ shutil.copytree(str(src), str(dest))
+ else:
+ shutil.copy2(str(src), str(dest))
diff --git a/src_py/opcut/doit/jsopcut.py b/src_py/opcut/doit/jsopcut.py
new file mode 100644
index 0000000..fcfd8dc
--- /dev/null
+++ b/src_py/opcut/doit/jsopcut.py
@@ -0,0 +1,85 @@
+import json
+import yaml
+import subprocess
+from pathlib import Path
+
+from opcut.doit import _common
+
+
+__all__ = ['task_jsopcut_clean', 'task_jsopcut_install_deps',
+ 'task_jsopcut_remove_deps', 'task_jsopcut_gen',
+ 'task_jsopcut_gen_validator', 'task_jsopcut_build',
+ 'task_jsopcut_watch']
+
+
+def task_jsopcut_clean():
+ """JsOpcut - clean"""
+
+ return {'actions': [(_common.rm_rf, ['build/jsopcut',
+ 'src_js/opcut/validator.js'])]}
+
+
+def task_jsopcut_install_deps():
+ """JsOpcut - install dependencies"""
+
+ def patch():
+ subprocess.Popen(['patch', '-r', '/dev/null', '--forward', '-p0',
+ '-i', 'node_modules.patch'],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL).wait()
+
+ return {'actions': ['yarn install',
+ patch]}
+
+
+def task_jsopcut_remove_deps():
+ """JsOpcut - remove dependencies"""
+
+ return {'actions': [(_common.rm_rf, ['node_modules', 'yarn.lock'])]}
+
+
+def task_jsopcut_gen():
+ """JsOpcut - generate additional JavaScript modules"""
+
+ return {'actions': None,
+ 'task_dep': ['jsopcut_gen_validator']}
+
+
+def task_jsopcut_gen_validator():
+ """JsOpcut - generate json validator"""
+
+ schema_files = list(Path('schemas_json').glob('**/*.yaml'))
+ output_file = Path('src_js/opcut/validator.js')
+
+ def parse_schemas():
+ for schema_file in schema_files:
+ with open(schema_file, encoding='utf-8') as f:
+ yield yaml.safe_load(f)
+
+ def generate_output():
+ schemas_json = json.dumps(list(parse_schemas()), indent=4)
+ with open(output_file, 'w', encoding='utf-8') as f:
+ f.write(
+ 'import tv4 from "tv4";\n\n\n' +
+ schemas_json + '.forEach(i => tv4.addSchema(i.id, i));\n\n\n' +
+ 'export function validate(data, schemaId) {\n' +
+ ' return tv4.validate(data, tv4.getSchema(schemaId));\n' +
+ '}\n')
+
+ return {'actions': [generate_output],
+ 'file_dep': schema_files,
+ 'targets': [output_file]}
+
+
+def task_jsopcut_build():
+ """JsOpcut - build"""
+
+ return {'actions': ['yarn run build'],
+ 'task_dep': ['jsopcut_install_deps', 'jsopcut_gen']}
+
+
+def task_jsopcut_watch():
+ """JsOpcut - build on change"""
+
+ return {'actions': ['yarn run watch'],
+ 'task_dep': ['jsopcut_install_deps', 'jsopcut_gen']}
diff --git a/src_py/opcut/doit/main.py b/src_py/opcut/doit/main.py
new file mode 100644
index 0000000..92e4fc9
--- /dev/null
+++ b/src_py/opcut/doit/main.py
@@ -0,0 +1,46 @@
+
+from opcut.doit import _common
+
+import opcut.doit.pyopcut
+import opcut.doit.jsopcut
+from opcut.doit.pyopcut import * # NOQA
+from opcut.doit.jsopcut import * # NOQA
+
+
+__all__ = (['task_clean_all', 'task_gen_all', 'task_dist_build',
+ 'task_dist_clean'] +
+ opcut.doit.pyopcut.__all__ +
+ opcut.doit.jsopcut.__all__)
+
+
+def task_clean_all():
+ """Clean all"""
+
+ return {'actions': [(_common.rm_rf, ['build', 'dist'])],
+ 'task_dep': ['pyopcut_clean',
+ 'jsopcut_clean',
+ 'dist_clean']}
+
+
+def task_gen_all():
+ """Generate all"""
+
+ return {'actions': None,
+ 'task_dep': ['pyopcut_gen',
+ 'jsopcut_gen']}
+
+
+def task_dist_clean():
+ """Distribution - clean"""
+
+ return {'actions': [(_common.rm_rf, ['dist'])]}
+
+
+def task_dist_build():
+ """Distribution - build (DEFAULT)"""
+
+ return {'actions': [(_common.mkdir_p, ['dist'])],
+ 'task_dep': [
+ 'gen_all',
+ 'pyopcut_build',
+ 'jsopcut_build']}
diff --git a/src_py/opcut/doit/pyopcut.py b/src_py/opcut/doit/pyopcut.py
new file mode 100644
index 0000000..8582f95
--- /dev/null
+++ b/src_py/opcut/doit/pyopcut.py
@@ -0,0 +1,104 @@
+import py_compile
+import os
+import yaml
+from pathlib import Path
+
+from opcut.doit import _common
+
+
+__all__ = ['task_pyopcut_clean', 'task_pyopcut_build', 'task_pyopcut_gen',
+ 'task_pyopcut_gen_json_validator']
+
+
+def task_pyopcut_clean():
+ """PyOpcut - clean"""
+
+ return {'actions': [(_common.rm_rf, ['build/pyopcut',
+ 'src_py/opcut/json_validator.py'])]}
+
+
+def task_pyopcut_build():
+ """PyOpcut - build"""
+
+ generated_files = {Path('src_py/opcut/json_validator.py')}
+
+ def compile(src_path, dst_path):
+ _common.mkdir_p(dst_path.parent)
+ if src_path.suffix == '.py':
+ py_compile.compile(src_path, dst_path, doraise=True)
+ else:
+ _common.cp_r(src_path, dst_path)
+
+ def create_subtask(src_path):
+ dst_path = Path('build/pyopcut') / src_path.relative_to('src_py')
+ if dst_path.suffix == '.py':
+ dst_path = dst_path.with_suffix('.pyc')
+ return {'name': str(src_path),
+ 'actions': [(compile, [src_path, dst_path])],
+ 'file_dep': [src_path],
+ 'targets': [dst_path]}
+
+ for src_path in generated_files:
+ yield create_subtask(src_path)
+
+ for dirpath, dirnames, filenames in os.walk('src_py'):
+ if '__pycache__' in dirnames:
+ dirnames.remove('__pycache__')
+ for i in filenames:
+ src_path = Path(dirpath) / i
+ if src_path not in generated_files:
+ yield create_subtask(src_path)
+
+
+def task_pyopcut_gen():
+ """PyOpcut - generate additional python modules"""
+
+ return {'actions': None,
+ 'task_dep': ['pyopcut_gen_json_validator']}
+
+
+def task_pyopcut_gen_json_validator():
+ """PyOpcut - generate json validator"""
+
+ schema_files = list(Path('schemas_json').glob('**/*.yaml'))
+ output_file = Path('src_py/opcut/json_validator.py')
+
+ def parse_schemas():
+ schemas = {}
+ for schema_file in schema_files:
+ with open(schema_file, encoding='utf-8') as f:
+ data = yaml.safe_load(f)
+ if data['id'] in schemas:
+ raise Exception("duplicate schema id " + data['id'])
+ schemas[data['id']] = data
+ return schemas
+
+ def generate_output():
+ schemas = parse_schemas()
+ with open(output_file, 'w', encoding='utf-8') as f:
+ f.write(
+ '# pylint: skip-file\n'
+ 'import jsonschema\n\n\n'
+ '_schemas = {schemas} # NOQA\n\n\n'
+ 'def validate(data, schema_id):\n'
+ ' """ Validate data with JSON schema\n\n'
+ ' Args:\n'
+ ' data: validated data\n'
+ ' schema_id (str): JSON schema identificator\n\n'
+ ' Raises:\n'
+ ' Exception: validation fails\n\n'
+ ' """\n'
+ ' base_uri = schema_id.split("#")[0] + "#"\n'
+ ' resolver = jsonschema.RefResolver(\n'
+ ' base_uri=base_uri,\n'
+ ' referrer=_schemas[base_uri],\n'
+ ' store=_schemas,\n'
+ ' cache_remote=False)\n'
+ ' jsonschema.validate(\n'
+ ' instance=data,\n'
+ ' schema=resolver.resolve(schema_id)[1],\n'
+ ' resolver=resolver)\n'.format(schemas=schemas))
+
+ return {'actions': [generate_output],
+ 'file_dep': schema_files,
+ 'targets': [output_file]}