freelance-project-34-market.../python/cli.py
2025-05-20 14:00:09 +03:00

207 lines
4.8 KiB
Python

import sys
import shutil
import glob
import io
import copy
import subprocess
import pathlib
import logging
import enum
import argparse
import dataclasses
from typing import (
Optional,
# override,
)
from typing_extensions import (
override,
)
from online.fxreader.pr34.commands_typed.logging import setup as logging_setup
from online.fxreader.pr34.commands_typed import cli as _cli
from online.fxreader.pr34.commands_typed import cli_bootstrap
logging_setup()
logger = logging.getLogger(__name__)
class Command(enum.Enum):
mypy = 'mypy'
pyright = 'pyright'
ruff = 'ruff'
deploy_wheel = 'deploy:wheel'
tests = 'tests'
meson_setup = 'meson:setup'
@dataclasses.dataclass
class Settings(
_cli.DistSettings,
):
base_dir: pathlib.Path = pathlib.Path(__file__).parent.parent
build_dir: pathlib.Path = base_dir / 'tmp' / 'build'
wheel_dir: pathlib.Path = base_dir / 'deps' / 'dist'
env_path: pathlib.Path = cli_bootstrap.BootstrapSettings.get().env_path
python_path: pathlib.Path = pathlib.Path(sys.executable)
class CLI(_cli.CLI):
def __init__(self) -> None:
self.settings = Settings()
self._projects: dict[str, _cli.Project] = {
'online.fxreader.pr34': _cli.Project(
source_dir=self.settings.base_dir / 'python',
build_dir=self.settings.base_dir / 'tmp' / 'online' / 'fxreader' / 'pr34' / 'build',
dest_dir=self.settings.base_dir / 'tmp' / 'online' / 'fxreader' / 'pr34' / 'install',
meson_path=self.settings.base_dir / 'python' / 'meson.build',
)
}
self._dependencies: dict[str, _cli.Dependency] = dict()
@override
@property
def dist_settings(self) -> _cli.DistSettings:
return self.settings
@override
@property
def projects(self) -> dict[str, _cli.Project]:
return self._projects
def mypy(
self,
argv: list[str],
) -> None:
import online.fxreader.pr34.commands_typed.mypy as _mypy
project = self._projects['online.fxreader.pr34']
_mypy.run(
argv,
settings=_mypy.MypySettings(
paths=[
# Settings.settings().project_root / 'dotfiles/.local/bin/commands',
# project.source_dir / 'm.py',
project.source_dir / '_m.py',
project.source_dir / 'online',
project.source_dir / 'cli.py',
project.source_dir / 'm.py',
# Settings.settings().project_root / 'deps/com.github.aiortc.aiortc/src',
# Settings.settings().project_root / 'm.py',
],
max_errors={
'online/fxreader/pr34/commands_typed': 0,
# 'online/fxreader/pr34/commands': 0,
'cli.py': 0,
'm.py': 0,
'../deps/com.github.aiortc.aiortc/src/online_fxreader': 0,
'../deps/com.github.aiortc.aiortc/src/aiortc/contrib/signaling': 0,
},
),
)
@override
@property
def dependencies(self) -> dict[str, _cli.Dependency]:
return self._dependencies
def run(self, argv: Optional[list[str]] = None) -> None:
if argv is None:
argv = copy.deepcopy(sys.argv)
parser = argparse.ArgumentParser()
parser.add_argument('command', choices=[o.value for o in Command])
parser.add_argument('-p', '--project', choices=[o for o in self.projects])
parser.add_argument(
'-o',
'--output_dir',
default=None,
help='wheel output dir for deploy:wheel',
)
parser.add_argument(
'-f',
'--force',
default=False,
action='store_true',
help='remove install dir, before installing, default = false',
)
options, args = parser.parse_known_args(argv[1:])
default_project: Optional[str] = None
for k, v in self.projects.items():
if cli_bootstrap.paths_equal(
v.source_dir.resolve(),
# pathlib.Path(__file__).parent.resolve(),
pathlib.Path.cwd(),
):
default_project = k
if options.project is None:
if not default_project is None:
options.project = default_project
else:
logger.error(dict(msg='not provided project name'))
raise NotImplementedError
options.command = Command(options.command)
if options.command is Command.deploy_wheel:
assert not options.project is None
self.deploy_wheel(
project_name=options.project,
argv=args,
output_dir=options.output_dir,
# mypy=True,
ruff=True,
pyright=True,
)
elif options.command is Command.pyright:
self.pyright(
project_name=options.project,
argv=args,
)
elif options.command is Command.ruff:
self.ruff(
project_name=options.project,
argv=args,
)
elif options.command is Command.meson_setup:
assert not options.project is None
self.meson_setup(
project_name=options.project,
argv=args,
force=options.force,
)
elif options.command is Command.mypy:
self.mypy(
argv=args,
)
elif options.command is Command.tests:
for k, v in self.projects.items():
subprocess.check_call(
[
sys.executable,
'-m',
'unittest',
'online.fxreader.pr34.tests.test_crypto',
*args,
],
cwd=str(v.source_dir),
)
else:
raise NotImplementedError
if __name__ == '__main__':
CLI().run()