diff --git a/.mypy.ini b/.mypy.ini index 575a29f..c5a24d6 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -1,5 +1,5 @@ [mypy] mypy_path = - python/stubs + mypy-stubs plugins = numpy.typing.mypy_plugin diff --git a/_m.py b/_m.py index a79a9df..e732d7d 100644 --- a/_m.py +++ b/_m.py @@ -8,15 +8,19 @@ import pathlib import sys import argparse #import optparse +import dataclasses import subprocess import os -from typing import (Optional, Any, TypeAlias, Literal, cast,) +from typing import ( + Optional, Any, TypeAlias, Literal, cast, BinaryIO, Generator, + ClassVar, +) logger = logging.getLogger() -def js(argv): +def js(argv: list[str]) -> int: return subprocess.check_call([ 'sudo', 'docker-compose', @@ -38,7 +42,7 @@ def js(argv): def env( argv: Optional[list[str]] = None, **kwargs: Any, -) -> Optional[subprocess.CompletedProcess]: +) -> Optional[subprocess.CompletedProcess[bytes]]: env_path = pathlib.Path(__file__).parent / 'tmp' / 'env3' if not env_path.exists(): @@ -123,7 +127,42 @@ def ruff(argv: list[str]) -> None: logger.info(json.dumps(errors, indent=4)) logger.info(json.dumps(h, indent=4)) +@dataclasses.dataclass +class MypyFormatEntry: + name : str + value : str + + def __eq__(self, other: object) -> bool: + if not isinstance(other, type(self)): + raise NotImplementedError + + return self.value == other.value + +class MypyFormat: + vscode : ClassVar[MypyFormatEntry] = MypyFormatEntry(name='vscode', value='vscode') + json : ClassVar[MypyFormatEntry] = MypyFormatEntry(name='json', value='json') + + + @classmethod + def from_value(cls, value: str) -> MypyFormatEntry: + for e in cls.entries(): + if value == e.value: + return e + + raise NotImplementedError + + @classmethod + def entries(cls) -> Generator[MypyFormatEntry, None, None,]: + for o in dir(cls): + e = getattr(cls, o) + if not isinstance(e, MypyFormatEntry): + continue + + yield e + def mypy(argv: list[str]) -> None: + + parser = argparse.ArgumentParser() parser.add_argument( '-i', @@ -132,8 +171,20 @@ def mypy(argv: list[str]) -> None: default=[], action='append', ) + parser.add_argument( + '-f', '--format', + dest='_format', + help='output format of errors', + default=MypyFormat.json.value, + choices=[ + o.value + for o in MypyFormat.entries() + ], + ) options, args = parser.parse_known_args(argv) + options.format = MypyFormat.from_value(options._format) + if len(options.paths) == 0: options.paths.extend([ 'dotfiles/.local/bin/commands', @@ -153,10 +204,17 @@ def mypy(argv: list[str]) -> None: assert not res is None - errors = [ - json.loads(o) - for o in res.stdout.decode('utf-8').splitlines() - ] + try: + errors = [ + json.loads(o) + for o in res.stdout.decode('utf-8').splitlines() + if not o.strip() == '' + ] + except: + logger.exception('') + logger.error(res.stdout.decode('utf-8')) + logger.error(res.stderr.decode('utf-8')) + sys.exit(res.returncode) g : dict[str, Any] = dict() for o in errors: @@ -169,8 +227,23 @@ def mypy(argv: list[str]) -> None: for k, v in g.items() } - logger.info(json.dumps(errors, indent=4)) - logger.info(json.dumps(h, indent=4)) + if options.format == MypyFormat.vscode: + for o in errors: + sys.stdout.write('[%s] %s:%d,%d %s - %s - %s\n' % ( + o['severity'], + o['file'], + o['line'], + o['column'], + o['message'], + o['hint'], + o['code'], + )) + sys.stdout.flush() + #logger.info(json.dumps(errors, indent=4)) + logger.info(json.dumps(h, indent=4)) + else: + logger.info(json.dumps(errors, indent=4)) + logger.info(json.dumps(h, indent=4)) def inside_env() -> bool: try: @@ -218,7 +291,7 @@ def run(argv: Optional[list[str]] = None) -> None: options, args = parser.parse_known_args(argv) - assert options.command in cast(list[str], Command_args) + assert options.command in Command_args #options.command = Commands(options._command) diff --git a/dotfiles/.local/bin/commands b/dotfiles/.local/bin/commands index d4c830c..f63f9e9 100755 --- a/dotfiles/.local/bin/commands +++ b/dotfiles/.local/bin/commands @@ -3675,6 +3675,55 @@ def media_keys(argv): msg=msg, ) +def install(argv: list[str]) -> None: + parser = argparse.ArgumentParser() + parser.add_argument( + '-r', + dest='recursive', + ) + parser.add_argument( + '-s', '--source', + help='source file/dir to install (copy with permissions preserving)', + dest='source', + type=pathlib.Path, + required=True, + ) + parser.add_argument( + '-t', '--target', + type=pathlib.Path, + help='target file/dir to install (copy with permissions preserving)', + dest='target', + required=True, + ) + parser.add_argument( + '-f', '--overwrite', + help='overwrite if target is present', + dest='overwrite', + action='store_true', + defualt=False, + ) + + options, args = parser.parse_known_args(argv) + + logger.info(dict(source=options.source, target=options.source)) + + if options.target.exists(): + if not options.overwrite: + raise NotImplementedError + + shutil.rmtree(str(options.target)) + + if option.source.is_dir() and not options.recursive: + raise NotImplementedError + + shutil.copy( + options.source, + options.target, + ) + + logger.info(dict(msg='done')) + + def commands_cli() -> None: logging.getLogger().setLevel(logging.INFO) logger.setLevel(logging.INFO) @@ -3710,6 +3759,8 @@ def commands_cli() -> None: debug=json.loads(sys.argv[5]), tabs=sys.argv[6:], ) + elif sys.argv[1] == 'install': + install(sys.argv[2:]) elif sys.argv[1] == 'resilient-ethernet': resilient_ethernet( ip_addr=sys.argv[2], diff --git a/python/stubs/Cython/Build/Inline.pyi b/mypy-stubs/Cython/Build/Inline.pyi similarity index 100% rename from python/stubs/Cython/Build/Inline.pyi rename to mypy-stubs/Cython/Build/Inline.pyi diff --git a/python/stubs/Cython/Build/__init__.pyi b/mypy-stubs/Cython/Build/__init__.pyi similarity index 100% rename from python/stubs/Cython/Build/__init__.pyi rename to mypy-stubs/Cython/Build/__init__.pyi diff --git a/python/stubs/Cython/__init__.pyi b/mypy-stubs/Cython/__init__.pyi similarity index 100% rename from python/stubs/Cython/__init__.pyi rename to mypy-stubs/Cython/__init__.pyi diff --git a/python/stubs/cython/__init__.pyi b/mypy-stubs/cython/__init__.pyi similarity index 51% rename from python/stubs/cython/__init__.pyi rename to mypy-stubs/cython/__init__.pyi index 6e200a2..40cfdde 100644 --- a/python/stubs/cython/__init__.pyi +++ b/mypy-stubs/cython/__init__.pyi @@ -1,7 +1,7 @@ -from typing import (Type, Any,) +from typing import (Type, Any, Self) class NoGIL: - def __enter__(self): ... + def __enter__(self) -> Self: ... def __exit__(self, exc_class: Type[Exception], exc: Exception, tb: Any) -> None: ... -nogil = NoGIL() +nogil : NoGIL = NoGIL() \ No newline at end of file diff --git a/python/stubs/distutils/__init__.pyi b/mypy-stubs/distutils/__init__.pyi similarity index 100% rename from python/stubs/distutils/__init__.pyi rename to mypy-stubs/distutils/__init__.pyi diff --git a/python/stubs/distutils/command/__init__.pyi b/mypy-stubs/distutils/command/__init__.pyi similarity index 100% rename from python/stubs/distutils/command/__init__.pyi rename to mypy-stubs/distutils/command/__init__.pyi diff --git a/python/stubs/mypyc/__init__.pyi b/mypy-stubs/mypyc/__init__.pyi similarity index 100% rename from python/stubs/mypyc/__init__.pyi rename to mypy-stubs/mypyc/__init__.pyi diff --git a/python/stubs/mypyc/build/__init__.pyi b/mypy-stubs/mypyc/build/__init__.pyi similarity index 100% rename from python/stubs/mypyc/build/__init__.pyi rename to mypy-stubs/mypyc/build/__init__.pyi diff --git a/python/stubs/tqdm/__init__.pyi b/mypy-stubs/tqdm/__init__.pyi similarity index 100% rename from python/stubs/tqdm/__init__.pyi rename to mypy-stubs/tqdm/__init__.pyi diff --git a/python/tasks/cython.py b/python/tasks/cython.py index fe61860..1ad6aa6 100644 --- a/python/tasks/cython.py +++ b/python/tasks/cython.py @@ -22,7 +22,8 @@ def test( #if True: started_at = datetime.datetime.now() print('started') - elapsed = lambda : (datetime.datetime.now() - started_at).total_seconds() + def elapsed() -> float: + return (datetime.datetime.now() - started_at).total_seconds() #a = 0 while elapsed() < T: #a += 1 @@ -227,7 +228,7 @@ def test2(long long [:] _a, int _id, double T=16) -> int: ''', Source) -def test_cython(N: int=4, T:int=16): +def test_cython(N: int=4, T:int=16) -> None: #a = [0] * N a = numpy.zeros((N,), dtype=numpy.int64) @@ -250,7 +251,7 @@ def test_cython(N: int=4, T:int=16): #cython_module['test2'](a, 0) -def test_mypyc(N: int=4, W:int=35): +def test_mypyc(N: int=4, W:int=35) -> None: cython2 = mypyc_build( (pathlib.Path(__file__).parent / 'cython2.py').relative_to( pathlib.Path.cwd()