diff options
Diffstat (limited to 'src_doit')
| -rw-r--r-- | src_doit/__init__.py | 56 | ||||
| -rw-r--r-- | src_doit/common.py | 19 | ||||
| -rw-r--r-- | src_doit/js.py | 117 | ||||
| -rw-r--r-- | src_doit/py.py | 99 |
4 files changed, 291 insertions, 0 deletions
diff --git a/src_doit/__init__.py b/src_doit/__init__.py new file mode 100644 index 0000000..e2999f2 --- /dev/null +++ b/src_doit/__init__.py @@ -0,0 +1,56 @@ +from pathlib import Path +import subprocess +import sys + +from . import common + +from .js import * # NOQA +from .py import * # NOQA +from . import js +from . import py + + +__all__ = ['task_clean_all', + 'task_build', + 'task_test', + *js.__all__, + *py.__all__] + + +build_dir = Path('build') +pytest_dir = Path('test_pytest') + + +def task_clean_all(): + """Clean all""" + return {'actions': [(common.rm_rf, [build_dir, + js.dst_dir, + py.json_schema_repo_path])]} + + +def task_build(): + """Build""" + + def build(): + subprocess.run([sys.executable, 'setup.py', '-q', 'bdist_wheel'], + cwd=str(build_dir), + check=True) + + return {'actions': [build], + 'task_dep': ['py_build']} + + +def task_test(): + """Test""" + + def run(args): + js.dst_dir.mkdir(parents=True, exist_ok=True) + subprocess.run([sys.executable, '-m', 'pytest', + '-s', '-p', 'no:cacheprovider', + *(args or [])], + cwd=str(pytest_dir), + check=True) + + return {'actions': [run], + 'pos_arg': 'args', + 'task_dep': ['py_json_schema_repo']} diff --git a/src_doit/common.py b/src_doit/common.py new file mode 100644 index 0000000..6697b6e --- /dev/null +++ b/src_doit/common.py @@ -0,0 +1,19 @@ +from pathlib import Path +import shutil + + +def rm_rf(*paths: Path): + for path in paths: + if not path.exists(): + continue + if path.is_dir(): + shutil.rmtree(str(path), ignore_errors=True) + else: + path.unlink() + + +def cp_r(src: Path, dest: Path): + if src.is_dir(): + shutil.copytree(str(src), str(dest), dirs_exist_ok=True) + else: + shutil.copy2(str(src), str(dest)) diff --git a/src_doit/js.py b/src_doit/js.py new file mode 100644 index 0000000..dea8d04 --- /dev/null +++ b/src_doit/js.py @@ -0,0 +1,117 @@ +from pathlib import Path +import subprocess +import tempfile + +from . import common + + +__all__ = ['task_js_build', + 'task_js_deps', + 'task_js_deps_clean'] + + +src_py_dir = Path('src_py') +src_js_dir = Path('src_js') +src_scss_dir = Path('src_scss') +node_modules_dir = Path('node_modules') +openapi_dir = Path('schemas_openapi') + +dst_dir = src_py_dir / 'restlog/ui' + + +def task_js_build(): + """JavaScript - build""" + + def build(args): + args = args or [] + entry = src_js_dir / 'main.js' + conf = _webpack_conf.format( + entry=entry.resolve(), + dst_dir=dst_dir.resolve(), + src_js_dir=src_js_dir.resolve(), + src_scss_dir=src_scss_dir.resolve(), + node_modules_dir=node_modules_dir.resolve()) + + common.rm_rf(dst_dir) + dst_dir.mkdir(parents=True, exist_ok=True) + + common.cp_r(openapi_dir / 'main.yaml', dst_dir / 'openapi.yaml') + (dst_dir / 'index.html').write_text(_index_html) + + with tempfile.TemporaryDirectory() as tmpdir: + tmpdir = Path(tmpdir) + config_path = tmpdir / 'webpack.config.js' + config_path.write_text(conf) + subprocess.run([str(node_modules_dir / '.bin/webpack'), + '--config', str(config_path), + *args], + check=True) + + return {'actions': [(common.rm_rf, [dst_dir]), + build], + 'pos_arg': 'args', + 'task_dep': ['js_deps']} + + +def task_js_deps(): + """JavaScript - install dependencies""" + return {'actions': ['yarn install --silent']} + + +def task_js_deps_clean(): + """JavaScript - remove dependencies""" + return {'actions': [(common.rm_rf, [node_modules_dir, + Path('yarn.lock')])]} + + +_index_html = r"""<!DOCTYPE html> +<html> +<head> + <meta charset="UTF-8"> + <title>restlog</title> + <script src="index.js"></script> +</head> +<body> +</body> +</html> +""" + + +_webpack_conf = r""" +module.exports = {{ + mode: 'none', + entry: '{entry}', + output: {{ + filename: 'index.js', + path: '{dst_dir}' + }}, + module: {{ + rules: [ + {{ + test: /\.scss$/, + use: [ + "style-loader", + "css-loader", + "resolve-url-loader", + {{ + loader: "sass-loader", + options: {{ sourceMap: true }} + }} + ] + }} + ] + }}, + resolve: {{ + modules: [ + '{src_js_dir}', + '{src_scss_dir}', + '{node_modules_dir}' + ] + }}, + watchOptions: {{ + ignored: /node_modules/ + }}, + devtool: 'source-map', + stats: 'errors-only' +}}; +""" diff --git a/src_doit/py.py b/src_doit/py.py new file mode 100644 index 0000000..f2876ae --- /dev/null +++ b/src_doit/py.py @@ -0,0 +1,99 @@ +from pathlib import Path + +import packaging.requirements + +from hat import json + +from . import common + + +__all__ = ['task_py_build', + 'task_py_json_schema_repo'] + + +build_dir = Path('build') +src_py_dir = Path('src_py') +schemas_json_dir = Path('schemas_json') +requirements_path = Path('requirements.pip.runtime.txt') + +json_schema_repo_path = src_py_dir / 'restlog/json_schema_repo.json' + + +def task_py_build(): + """Python - build""" + + def build(): + common.rm_rf(build_dir) + build_dir.mkdir(parents=True, exist_ok=True) + + common.cp_r(src_py_dir, build_dir) + common.rm_rf(*build_dir.rglob('__pycache__')) + + manifest_path = build_dir / 'MANIFEST.in' + paths = [path for path in build_dir.rglob('*') if not path.is_dir()] + with open(manifest_path, 'w', encoding='utf-8') as f: + for path in paths: + f.write(f"include {path.relative_to(manifest_path.parent)}\n") + + readme = Path('README.rst').read_text() + requirements = list(_get_requirements(requirements_path)) + setup_py = _setup_py.format(readme=repr(readme), + requirements=repr(requirements)) + (build_dir / 'setup.py').write_text(setup_py) + + return {'actions': [build], + 'task_dep': ['py_json_schema_repo', + 'js_build']} + + +def task_py_json_schema_repo(): + """Python - JSON schema repo""" + src_paths = list(schemas_json_dir.rglob('*.yaml')) + + def generate(): + repo = json.SchemaRepository(*src_paths) + data = repo.to_json() + json.encode_file(data, json_schema_repo_path, indent=None) + + return {'actions': [generate], + 'file_dep': src_paths, + 'targets': [json_schema_repo_path]} + + +def _get_requirements(path): + # TODO: implement full format + # https://pip.pypa.io/en/stable/cli/pip_install/ + for i in path.read_text().split('\n'): + i = i.strip() + if not i or i.startswith('#'): + continue + requirement = packaging.requirements.Requirement(i) + yield str(requirement) + + +_setup_py = r""" +from setuptools import setup + +readme = {readme} +requirements = {requirements} + +setup( + name='restlog', + version='0.0.1', + description='JSON log-structured data storage with REST API', + long_description=readme, + long_description_content_type='text/x-rst', + url='https://github.com/bnozokopic/restlog', + license='GPLv3', + classifiers=[ + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)'], + packages=['restlog'], + include_package_data=True, + install_requires=requirements, + python_requires='>=3.8', + zip_safe=False, + entry_points={{ + 'console_scripts': ['restlog = restlog.main:main'] + }}) +""" # NOQA |
