#!/usr/bin/env python3 #vim: set filetype=python import logging import json import enum import pathlib import sys import argparse #import optparse import subprocess import os from typing import (Optional, Any, TypeAlias, Literal, cast,) logger = logging.getLogger() def js(argv): return subprocess.check_call([ 'sudo', 'docker-compose', '--project-directory', os.path.abspath( os.path.dirname(__file__), ), '-f', os.path.abspath( os.path.join( os.path.dirname(__file__), 'docker', 'js', 'docker-compose.yml', ) ), *argv, ]) def env( argv: Optional[list[str]] = None, **kwargs: Any, ) -> Optional[subprocess.CompletedProcess]: env_path = pathlib.Path(__file__).parent / 'tmp' / 'env3' if not env_path.exists(): subprocess.check_call([ sys.executable, '-m', 'venv', '--system-site-packages', str(env_path) ]) subprocess.check_call([ env_path / 'bin' / 'python3', '-m', 'pip', 'install', '-r', 'requirements.txt', ]) if not argv is None: return subprocess.run([ str(env_path / 'bin' / 'python3'), *argv, ], **kwargs) return None def ruff(args: list[str]) -> None: res = env([ '-m', 'ruff', 'check', *args, '--output-format', 'json', '--ignore', ','.join([ 'E731', 'E713', 'E714', 'E703', ]), '.', 'dotfiles/.local/bin/commands', ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) assert not res is None errors = json.loads(res.stdout.decode('utf-8')) g: dict[str, Any] = dict() for o in errors: if not o['filename'] in g: g[o['filename']] = [] g[o['filename']].append(o) h = { k : len(v) for k, v in g.items() } logger.info(json.dumps(errors, indent=4)) logger.info(json.dumps(h, indent=4)) def mypy(args: list[str]) -> None: res = env([ '-m', 'mypy', '--strict', '-O', 'json', *args, 'dotfiles/.local/bin/commands', 'python', 'm.py', ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) assert not res is None errors = [ json.loads(o) for o in res.stdout.decode('utf-8').splitlines() ] g : dict[str, Any] = dict() for o in errors: if not o['file'] in g: g[o['file']] = [] g[o['file']].append(o) h = { k : len(v) for k, v in g.items() } logger.info(json.dumps(errors, indent=4)) logger.info(json.dumps(h, indent=4)) def inside_env() -> bool: try: import numpy return True except Exception: return False #class Commands(enum.StrEnum): # js = 'js' # mypy = 'mypy' # env = 'env' # ruff = 'ruff' # m2 = 'm2' Command_args = ['js', 'mypy', 'env', 'ruff', 'm2'] Command : TypeAlias = Literal['js', 'mypy', 'env', 'ruff', 'm2'] def run(argv: Optional[list[str]] = None) -> None: logging.basicConfig( level=logging.INFO, format=( '%(levelname)s:%(name)s:%(message)s' ':%(process)d' ':%(asctime)s' ':%(pathname)s:%(funcName)s:%(lineno)s' ), ) if argv is None: argv = sys.argv[1:] parser = argparse.ArgumentParser() parser.add_argument( 'command', #'_command', choices=[ o for o in Command_args ], #required=True, ) options, args = parser.parse_known_args(argv) assert options.command in cast(list[str], Command_args) #options.command = Commands(options._command) if options.command == 'js': js(args) elif options.command == 'env': env(args) elif options.command == 'mypy': mypy(args) elif options.command == 'ruff': ruff(args) elif options.command == 'm2': if not inside_env(): env(['--', '_m.py', 'm2', *args]) return import python.tasks.cython python.tasks.cython.mypyc_build( pathlib.Path('_m.py') ) else: raise NotImplementedError if __name__ == '__main__': run(sys.argv[1:])