295 lines
4.9 KiB
Python
295 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
|
# vim: set filetype=python
|
|
|
|
import logging
|
|
import json
|
|
import enum
|
|
import pathlib
|
|
import sys
|
|
import argparse
|
|
|
|
# import optparse
|
|
import dataclasses
|
|
import subprocess
|
|
import os
|
|
|
|
|
|
from typing import (
|
|
Optional,
|
|
Any,
|
|
TypeAlias,
|
|
Literal,
|
|
cast,
|
|
BinaryIO,
|
|
Generator,
|
|
ClassVar,
|
|
Self,
|
|
)
|
|
|
|
logger = logging.getLogger()
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Settings:
|
|
project_root: pathlib.Path = pathlib.Path.cwd()
|
|
|
|
env_path: pathlib.Path = project_root / 'tmp' / 'env3'
|
|
|
|
_settings: ClassVar[Optional['Settings']] = None
|
|
|
|
@classmethod
|
|
def settings(cls) -> Self:
|
|
if cls._settings is None:
|
|
cls._settings = cls()
|
|
|
|
return cls._settings
|
|
|
|
|
|
def js(argv: list[str]) -> int:
|
|
return subprocess.check_call(
|
|
[
|
|
'sudo',
|
|
'docker-compose',
|
|
'--project-directory',
|
|
Settings.settings().project_root,
|
|
'-f',
|
|
Settings.settings().project_root / 'docker' / 'js' / 'docker-compose.yml',
|
|
*argv,
|
|
]
|
|
)
|
|
|
|
|
|
def env(
|
|
argv: Optional[list[str]] = None,
|
|
mode: Literal['exec', 'subprocess'] = 'subprocess',
|
|
**kwargs: Any,
|
|
) -> Optional[subprocess.CompletedProcess[bytes]]:
|
|
env_path = Settings.settings().env_path
|
|
|
|
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:
|
|
python_path = str(env_path / 'bin' / 'python3')
|
|
|
|
if mode == 'exec':
|
|
os.execv(
|
|
python_path,
|
|
[
|
|
python_path,
|
|
*argv,
|
|
],
|
|
)
|
|
return None
|
|
elif mode == 'subprocess':
|
|
return subprocess.run(
|
|
[
|
|
python_path,
|
|
*argv,
|
|
],
|
|
**kwargs,
|
|
)
|
|
else:
|
|
raise NotImplementedError
|
|
|
|
return None
|
|
|
|
|
|
def ruff(argv: list[str]) -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
'-i',
|
|
dest='paths',
|
|
help='specify paths to check',
|
|
default=[],
|
|
action='append',
|
|
)
|
|
parser.add_argument(
|
|
'-e',
|
|
dest='exclude',
|
|
help='rules to ignore',
|
|
default=[],
|
|
action='append',
|
|
)
|
|
|
|
options, args = parser.parse_known_args(argv)
|
|
|
|
if len(options.paths) == 0:
|
|
options.paths.extend(
|
|
[
|
|
'.',
|
|
'dotfiles/.local/bin/commands',
|
|
]
|
|
)
|
|
|
|
if len(options.exclude) == 0:
|
|
options.exclude.extend(
|
|
[
|
|
'E731',
|
|
'E713',
|
|
'E714',
|
|
'E703',
|
|
]
|
|
)
|
|
|
|
res = env(
|
|
[
|
|
'-m',
|
|
'ruff',
|
|
'check',
|
|
*args,
|
|
'--output-format',
|
|
'json',
|
|
'--ignore',
|
|
','.join(options.exclude),
|
|
*options.paths,
|
|
],
|
|
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 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'
|
|
|
|
# def mypy(argv: list[str]) -> None:
|
|
# import online.fxreader.pr34.commands_typed.mypy as _mypy
|
|
|
|
# _mypy.run(
|
|
# argv,
|
|
# )
|
|
|
|
|
|
def host_deps(argv: list[str]) -> None:
|
|
if sys.platform in ['linux']:
|
|
subprocess.check_call(
|
|
r"""
|
|
exec yay -S $(cat requirements-archlinux.txt)
|
|
""",
|
|
shell=True,
|
|
)
|
|
else:
|
|
raise NotImplementedError
|
|
|
|
|
|
Command_args = [
|
|
'js',
|
|
'mypy',
|
|
'env',
|
|
'ruff',
|
|
'm2',
|
|
'host_deps',
|
|
]
|
|
|
|
Command: TypeAlias = Literal[
|
|
'js',
|
|
'mypy',
|
|
'env',
|
|
'ruff',
|
|
'm2',
|
|
'host_deps',
|
|
]
|
|
|
|
|
|
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[:]
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
'command',
|
|
#'_command',
|
|
choices=[o for o in Command_args],
|
|
# required=True,
|
|
)
|
|
|
|
options, args = parser.parse_known_args(argv[1:])
|
|
|
|
assert options.command in Command_args
|
|
|
|
if len(args) > 0 and args[0] == '--':
|
|
del args[0]
|
|
|
|
# options.command = Commands(options._command)
|
|
|
|
if options.command == 'js':
|
|
js(args)
|
|
elif options.command == 'host_deps':
|
|
host_deps(args)
|
|
elif options.command == 'env':
|
|
env(
|
|
args,
|
|
mode='exec',
|
|
)
|
|
# elif options.command == 'mypy':
|
|
# if not inside_env():
|
|
# env(
|
|
# [
|
|
# pathlib.Path(__file__).parent / 'm.py',
|
|
# *argv[1:],
|
|
# ],
|
|
# mode='exec'
|
|
# )
|
|
# else:
|
|
# 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()
|