omdev 0.0.0.dev28__tar.gz → 0.0.0.dev29__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of omdev might be problematic. Click here for more details.
- {omdev-0.0.0.dev28/omdev.egg-info → omdev-0.0.0.dev29}/PKG-INFO +2 -2
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/comp/contexts.py +1 -1
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/data/__init__.py +1 -1
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/data/cache.py +1 -1
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/data/defaults.py +3 -3
- omdev-0.0.0.dev29/omdev/precheck/base.py +37 -0
- omdev-0.0.0.dev29/omdev/precheck/git.py +34 -0
- omdev-0.0.0.dev29/omdev/precheck/lite.py +135 -0
- omdev-0.0.0.dev29/omdev/precheck/precheck.py +100 -0
- omdev-0.0.0.dev29/omdev/precheck/scripts.py +42 -0
- omdev-0.0.0.dev29/omdev/tools/piptools.py +26 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev.egg-info/SOURCES.txt +5 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/pyproject.toml +2 -2
- omdev-0.0.0.dev28/omdev/precheck/precheck.py +0 -316
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/LICENSE +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/README.rst +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/.manifests.json +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/amalg/amalg.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/bracepy.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/comp/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/comp/cache.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/comp/fns.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/comp/resolvers.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/comp/types.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/classdot.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/findimports.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/findmagic.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/git.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/providers.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/pyenv.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/standalone.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/system.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/manifests.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/revisions.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/scripts/execrss.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/scripts/pyproject.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/tokens.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/toml/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/toml/parser.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/toml/writer.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/tools/dockertools.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/tools/gittools.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/tools/importscan.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/tools/importtrace.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/tools/rst.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/versioning/__init__.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/versioning/specifiers.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/versioning/versions.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev/wheelfile.py +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev28 → omdev-0.0.0.dev29}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev29
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: ~=3.12
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
|
15
|
+
Requires-Dist: omlish==0.0.0.dev29
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
18
18
|
Requires-Dist: cffi~=1.17; extra == "all"
|
|
@@ -2,7 +2,7 @@ import os.path
|
|
|
2
2
|
|
|
3
3
|
from omlish import lang
|
|
4
4
|
|
|
5
|
-
from .cache import
|
|
5
|
+
from .cache import Cache
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
##
|
|
@@ -14,5 +14,5 @@ def default_dir() -> str:
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@lang.cached_function(lock=True)
|
|
17
|
-
def default() ->
|
|
18
|
-
return
|
|
17
|
+
def default() -> Cache:
|
|
18
|
+
return Cache(default_dir())
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import dataclasses as dc
|
|
3
|
+
import typing as ta
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
PrecheckConfigT = ta.TypeVar('PrecheckConfigT', bound='Precheck.Config')
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
13
|
+
class PrecheckContext:
|
|
14
|
+
src_roots: ta.Sequence[str]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Precheck(abc.ABC, ta.Generic[PrecheckConfigT]):
|
|
21
|
+
@dc.dataclass(frozen=True)
|
|
22
|
+
class Config:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
def __init__(self, context: PrecheckContext, config: PrecheckConfigT) -> None:
|
|
26
|
+
super().__init__()
|
|
27
|
+
self._context = context
|
|
28
|
+
self._config = config
|
|
29
|
+
|
|
30
|
+
@dc.dataclass(frozen=True)
|
|
31
|
+
class Violation:
|
|
32
|
+
pc: 'Precheck'
|
|
33
|
+
msg: str
|
|
34
|
+
|
|
35
|
+
@abc.abstractmethod
|
|
36
|
+
def run(self) -> ta.AsyncIterator[Violation]:
|
|
37
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import dataclasses as dc
|
|
3
|
+
import typing as ta
|
|
4
|
+
|
|
5
|
+
from .base import Precheck
|
|
6
|
+
from .base import PrecheckContext
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GitBlacklistPrecheck(Precheck['GitBlacklistPrecheck.Config']):
|
|
13
|
+
"""
|
|
14
|
+
TODO:
|
|
15
|
+
- globs
|
|
16
|
+
- regex
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@dc.dataclass(frozen=True)
|
|
20
|
+
class Config(Precheck.Config):
|
|
21
|
+
files: ta.Sequence[str] = (
|
|
22
|
+
'.env',
|
|
23
|
+
'secrets.yml',
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def __init__(self, context: PrecheckContext, config: Config = Config()) -> None:
|
|
27
|
+
super().__init__(context, config)
|
|
28
|
+
|
|
29
|
+
async def run(self) -> ta.AsyncGenerator[Precheck.Violation, None]:
|
|
30
|
+
for f in self._config.files:
|
|
31
|
+
proc = await asyncio.create_subprocess_exec('git', 'status', '-s', f)
|
|
32
|
+
await proc.communicate()
|
|
33
|
+
if proc.returncode:
|
|
34
|
+
yield Precheck.Violation(self, f)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import dataclasses as dc
|
|
3
|
+
import glob
|
|
4
|
+
import inspect
|
|
5
|
+
import logging
|
|
6
|
+
import os.path
|
|
7
|
+
import subprocess
|
|
8
|
+
import textwrap
|
|
9
|
+
import typing as ta
|
|
10
|
+
|
|
11
|
+
from omdev import findmagic
|
|
12
|
+
from omlish import cached
|
|
13
|
+
|
|
14
|
+
from .base import Precheck
|
|
15
|
+
from .base import PrecheckContext
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
log = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class LitePython8Precheck(Precheck['LitePython8Precheck.Config']):
|
|
25
|
+
@dc.dataclass(frozen=True)
|
|
26
|
+
class Config(Precheck.Config):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
def __init__(self, context: PrecheckContext, config: Config = Config()) -> None:
|
|
30
|
+
super().__init__(context, config)
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
def _load_file_module(fp: str) -> None:
|
|
36
|
+
import os.path # noqa
|
|
37
|
+
import types # noqa
|
|
38
|
+
|
|
39
|
+
fp = os.path.abspath(fp)
|
|
40
|
+
|
|
41
|
+
with open(fp) as f:
|
|
42
|
+
src = f.read()
|
|
43
|
+
|
|
44
|
+
mn = os.path.basename(fp).rpartition('.')[0]
|
|
45
|
+
|
|
46
|
+
mod = types.ModuleType(mn)
|
|
47
|
+
mod.__name__ = mn
|
|
48
|
+
mod.__file__ = fp
|
|
49
|
+
mod.__builtins__ = __builtins__ # type: ignore
|
|
50
|
+
mod.__spec__ = None
|
|
51
|
+
|
|
52
|
+
code = compile(src, fp, 'exec')
|
|
53
|
+
exec(code, mod.__dict__, mod.__dict__)
|
|
54
|
+
|
|
55
|
+
@cached.function
|
|
56
|
+
def _load_file_module_payload(self) -> str:
|
|
57
|
+
return '\n'.join([
|
|
58
|
+
'import sys',
|
|
59
|
+
'fp = sys.argv[-1]',
|
|
60
|
+
'',
|
|
61
|
+
textwrap.dedent('\n'.join(inspect.getsource(LitePython8Precheck._load_file_module).splitlines()[2:])),
|
|
62
|
+
])
|
|
63
|
+
|
|
64
|
+
#
|
|
65
|
+
|
|
66
|
+
async def _run_script(self, fp: str) -> list[Precheck.Violation]:
|
|
67
|
+
log.debug('%s: loading script %s', self.__class__.__name__, fp)
|
|
68
|
+
|
|
69
|
+
vs: list[Precheck.Violation] = []
|
|
70
|
+
|
|
71
|
+
proc = await asyncio.create_subprocess_exec(
|
|
72
|
+
'.venvs/8/bin/python',
|
|
73
|
+
'-c',
|
|
74
|
+
self._load_file_module_payload(),
|
|
75
|
+
fp,
|
|
76
|
+
stderr=subprocess.PIPE,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
_, stderr = await proc.communicate()
|
|
80
|
+
if proc.returncode != 0:
|
|
81
|
+
vs.append(Precheck.Violation(self, f'lite script {fp} failed to load in python8: {stderr.decode()}'))
|
|
82
|
+
|
|
83
|
+
return vs
|
|
84
|
+
|
|
85
|
+
async def _run_one_module(self, fp: str) -> list[Precheck.Violation]:
|
|
86
|
+
vs: list[Precheck.Violation] = []
|
|
87
|
+
|
|
88
|
+
mod = fp.rpartition('.')[0].replace(os.sep, '.')
|
|
89
|
+
|
|
90
|
+
log.debug('%s: loading module %s', self.__class__.__name__, mod)
|
|
91
|
+
|
|
92
|
+
proc = await asyncio.create_subprocess_exec(
|
|
93
|
+
'.venvs/8/bin/python',
|
|
94
|
+
'-c',
|
|
95
|
+
f'import {mod}',
|
|
96
|
+
stderr=subprocess.PIPE,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
_, stderr = await proc.communicate()
|
|
100
|
+
if proc.returncode != 0:
|
|
101
|
+
vs.append(Precheck.Violation(self, f'lite module {fp} failed to import in python8: {stderr.decode()}')) # noqa
|
|
102
|
+
|
|
103
|
+
return vs
|
|
104
|
+
|
|
105
|
+
async def _run_module(self, fp: str) -> list[Precheck.Violation]:
|
|
106
|
+
vs: list[Precheck.Violation] = []
|
|
107
|
+
|
|
108
|
+
if fp.endswith('__init__.py'):
|
|
109
|
+
pfps = glob.glob(os.path.join(os.path.dirname(fp), '**/*.py'), recursive=True)
|
|
110
|
+
else:
|
|
111
|
+
pfps = [fp]
|
|
112
|
+
|
|
113
|
+
for pfp in pfps:
|
|
114
|
+
vs.extend(await self._run_one_module(pfp))
|
|
115
|
+
|
|
116
|
+
return vs
|
|
117
|
+
|
|
118
|
+
async def run(self) -> ta.AsyncGenerator[Precheck.Violation, None]:
|
|
119
|
+
for fp in findmagic.find_magic(
|
|
120
|
+
self._context.src_roots,
|
|
121
|
+
['# @omlish-lite'],
|
|
122
|
+
['py'],
|
|
123
|
+
):
|
|
124
|
+
with open(fp) as f: # noqa # FIXME
|
|
125
|
+
src = f.read()
|
|
126
|
+
|
|
127
|
+
is_script = '# @omlish-script' in src.splitlines()
|
|
128
|
+
|
|
129
|
+
if is_script:
|
|
130
|
+
for v in await self._run_script(fp):
|
|
131
|
+
yield v
|
|
132
|
+
|
|
133
|
+
else:
|
|
134
|
+
for v in await self._run_module(fp):
|
|
135
|
+
yield v
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tiny pre-commit
|
|
3
|
+
|
|
4
|
+
TODO:
|
|
5
|
+
- global config
|
|
6
|
+
- global analyses - FilesWithShebang
|
|
7
|
+
- shebang files have no relative imports
|
|
8
|
+
- parallelize (asyncio)
|
|
9
|
+
- anyio? aiofiles? :| nonblock open().read()
|
|
10
|
+
- debug log
|
|
11
|
+
- omlish-lite - no non-lite deps, etc etc
|
|
12
|
+
- omlish-script - no deps, shebang, executable, can be 3.12
|
|
13
|
+
- big git files https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#check-added-large-files
|
|
14
|
+
- https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#check-case-conflict
|
|
15
|
+
- https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#check-symlinks
|
|
16
|
+
- https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#detect-aws-credentials
|
|
17
|
+
- https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#forbid-new-submodules
|
|
18
|
+
- don't check in .o's (omdev.ext import hook is dumb w build dir)
|
|
19
|
+
"""
|
|
20
|
+
import argparse
|
|
21
|
+
import asyncio
|
|
22
|
+
import logging
|
|
23
|
+
import os.path
|
|
24
|
+
import sys
|
|
25
|
+
import typing as ta
|
|
26
|
+
|
|
27
|
+
from omlish import logs
|
|
28
|
+
|
|
29
|
+
from .base import Precheck
|
|
30
|
+
from .base import PrecheckContext
|
|
31
|
+
from .git import GitBlacklistPrecheck
|
|
32
|
+
from .lite import LitePython8Precheck
|
|
33
|
+
from .scripts import ScriptDepsPrecheck
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
log = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _check_cmd(args) -> None:
|
|
43
|
+
if not os.path.isfile('pyproject.toml'):
|
|
44
|
+
raise RuntimeError('must run in project root')
|
|
45
|
+
|
|
46
|
+
ctx = PrecheckContext(
|
|
47
|
+
src_roots=args.roots,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
pcs: list[Precheck] = [
|
|
51
|
+
GitBlacklistPrecheck(ctx),
|
|
52
|
+
ScriptDepsPrecheck(ctx),
|
|
53
|
+
LitePython8Precheck(ctx),
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
async def run() -> list[Precheck.Violation]:
|
|
57
|
+
vs: list[Precheck.Violation] = []
|
|
58
|
+
|
|
59
|
+
for pc in pcs:
|
|
60
|
+
async for v in pc.run():
|
|
61
|
+
vs.append(v)
|
|
62
|
+
print(v)
|
|
63
|
+
|
|
64
|
+
return vs
|
|
65
|
+
|
|
66
|
+
vs = asyncio.run(run())
|
|
67
|
+
|
|
68
|
+
if vs:
|
|
69
|
+
print(f'{len(vs)} violations found')
|
|
70
|
+
sys.exit(1)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
##
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
77
|
+
parser = argparse.ArgumentParser()
|
|
78
|
+
|
|
79
|
+
subparsers = parser.add_subparsers()
|
|
80
|
+
|
|
81
|
+
parser_check = subparsers.add_parser('check')
|
|
82
|
+
parser_check.add_argument('roots', nargs='+')
|
|
83
|
+
parser_check.set_defaults(func=_check_cmd)
|
|
84
|
+
|
|
85
|
+
return parser
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _main(argv: ta.Sequence[str] | None = None) -> None:
|
|
89
|
+
logs.configure_standard_logging('INFO')
|
|
90
|
+
|
|
91
|
+
parser = _build_parser()
|
|
92
|
+
args = parser.parse_args(argv)
|
|
93
|
+
if not getattr(args, 'func', None):
|
|
94
|
+
parser.print_help()
|
|
95
|
+
else:
|
|
96
|
+
args.func(args)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
if __name__ == '__main__':
|
|
100
|
+
_main()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import dataclasses as dc
|
|
2
|
+
import os
|
|
3
|
+
import stat
|
|
4
|
+
import typing as ta
|
|
5
|
+
|
|
6
|
+
from omdev import findimports
|
|
7
|
+
from omdev import findmagic
|
|
8
|
+
|
|
9
|
+
from .base import Precheck
|
|
10
|
+
from .base import PrecheckContext
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ScriptDepsPrecheck(Precheck['ScriptDepsPrecheck.Config']):
|
|
17
|
+
@dc.dataclass(frozen=True)
|
|
18
|
+
class Config(Precheck.Config):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
def __init__(self, context: PrecheckContext, config: Config = Config()) -> None:
|
|
22
|
+
super().__init__(context, config)
|
|
23
|
+
|
|
24
|
+
async def run(self) -> ta.AsyncGenerator[Precheck.Violation, None]:
|
|
25
|
+
for fp in findmagic.find_magic(
|
|
26
|
+
self._context.src_roots,
|
|
27
|
+
['# @omlish-script'],
|
|
28
|
+
['py'],
|
|
29
|
+
):
|
|
30
|
+
if not (stat.S_IXUSR & os.stat(fp).st_mode):
|
|
31
|
+
yield Precheck.Violation(self, f'script {fp} is not executable')
|
|
32
|
+
|
|
33
|
+
with open(fp) as f: # noqa # FIXME
|
|
34
|
+
src = f.read()
|
|
35
|
+
|
|
36
|
+
if not src.startswith('#!/usr/bin/env python3\n'):
|
|
37
|
+
yield Precheck.Violation(self, f'script {fp} lacks correct shebang')
|
|
38
|
+
|
|
39
|
+
imps = findimports.find_imports(fp)
|
|
40
|
+
deps = findimports.get_import_deps(imps)
|
|
41
|
+
if deps:
|
|
42
|
+
yield Precheck.Violation(self, f'script {fp} has deps: {deps}')
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import urllib.request
|
|
3
|
+
import xml.etree.ElementTree as ET # noqa
|
|
4
|
+
|
|
5
|
+
from omlish import argparse as ap
|
|
6
|
+
from omlish import check
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
PYPI_URL = 'https://pypi.org/'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Cli(ap.Cli):
|
|
13
|
+
@ap.command(
|
|
14
|
+
ap.arg('package'),
|
|
15
|
+
)
|
|
16
|
+
def lookup_latest_version(self) -> None:
|
|
17
|
+
pkg_name = check.non_empty_str(self.args.package)
|
|
18
|
+
with urllib.request.urlopen(f'{PYPI_URL}rss/project/{pkg_name}/releases.xml') as resp: # noqa
|
|
19
|
+
rss = resp.read()
|
|
20
|
+
doc = ET.parse(io.BytesIO(rss)) # noqa
|
|
21
|
+
latest = check.not_none(doc.find('./channel/item/title')).text
|
|
22
|
+
print(latest)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == '__main__':
|
|
26
|
+
Cli()()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev29
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: ~=3.12
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
|
15
|
+
Requires-Dist: omlish==0.0.0.dev29
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
18
18
|
Requires-Dist: cffi~=1.17; extra == "all"
|
|
@@ -74,7 +74,11 @@ omdev/mypy/__init__.py
|
|
|
74
74
|
omdev/mypy/debug.py
|
|
75
75
|
omdev/precheck/__init__.py
|
|
76
76
|
omdev/precheck/__main__.py
|
|
77
|
+
omdev/precheck/base.py
|
|
78
|
+
omdev/precheck/git.py
|
|
79
|
+
omdev/precheck/lite.py
|
|
77
80
|
omdev/precheck/precheck.py
|
|
81
|
+
omdev/precheck/scripts.py
|
|
78
82
|
omdev/pyproject/__init__.py
|
|
79
83
|
omdev/pyproject/__main__.py
|
|
80
84
|
omdev/pyproject/cexts.py
|
|
@@ -95,6 +99,7 @@ omdev/tools/dockertools.py
|
|
|
95
99
|
omdev/tools/gittools.py
|
|
96
100
|
omdev/tools/importscan.py
|
|
97
101
|
omdev/tools/importtrace.py
|
|
102
|
+
omdev/tools/piptools.py
|
|
98
103
|
omdev/tools/rst.py
|
|
99
104
|
omdev/tools/sqlrepl.py
|
|
100
105
|
omdev/versioning/__init__.py
|
|
@@ -12,7 +12,7 @@ authors = [
|
|
|
12
12
|
urls = {source = 'https://github.com/wrmsr/omlish'}
|
|
13
13
|
license = {text = 'BSD-3-Clause'}
|
|
14
14
|
requires-python = '~=3.12'
|
|
15
|
-
version = '0.0.0.
|
|
15
|
+
version = '0.0.0.dev29'
|
|
16
16
|
classifiers = [
|
|
17
17
|
'License :: OSI Approved :: BSD License',
|
|
18
18
|
'Development Status :: 2 - Pre-Alpha',
|
|
@@ -22,7 +22,7 @@ classifiers = [
|
|
|
22
22
|
]
|
|
23
23
|
description = 'omdev'
|
|
24
24
|
dependencies = [
|
|
25
|
-
'omlish == 0.0.0.
|
|
25
|
+
'omlish == 0.0.0.dev29',
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
[project.optional-dependencies]
|
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tiny pre-commit
|
|
3
|
-
|
|
4
|
-
TODO:
|
|
5
|
-
- global config
|
|
6
|
-
- global analyses - FilesWithShebang
|
|
7
|
-
- shebang files have no relative imports
|
|
8
|
-
- parallelize (asyncio)
|
|
9
|
-
- anyio? aiofiles? :| nonblock open().read()
|
|
10
|
-
- debug log
|
|
11
|
-
- omlish-lite - no non-lite deps, etc etc
|
|
12
|
-
- omlish-script - no deps, shebang, executable, can be 3.12
|
|
13
|
-
- big git files https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#check-added-large-files
|
|
14
|
-
- https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#check-case-conflict
|
|
15
|
-
- https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#check-symlinks
|
|
16
|
-
- https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#detect-aws-credentials
|
|
17
|
-
- https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#forbid-new-submodules
|
|
18
|
-
- don't check in .o's (omdev.ext import hook is dumb w build dir)
|
|
19
|
-
"""
|
|
20
|
-
import abc
|
|
21
|
-
import argparse
|
|
22
|
-
import asyncio
|
|
23
|
-
import dataclasses as dc
|
|
24
|
-
import glob
|
|
25
|
-
import inspect
|
|
26
|
-
import logging
|
|
27
|
-
import os.path
|
|
28
|
-
import stat
|
|
29
|
-
import subprocess
|
|
30
|
-
import sys
|
|
31
|
-
import textwrap
|
|
32
|
-
import typing as ta
|
|
33
|
-
|
|
34
|
-
from omdev import findimports
|
|
35
|
-
from omdev import findmagic
|
|
36
|
-
from omlish import cached
|
|
37
|
-
from omlish import logs
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
T = ta.TypeVar('T')
|
|
41
|
-
PrecheckConfigT = ta.TypeVar('PrecheckConfigT', bound='Precheck.Config')
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
log = logging.getLogger(__name__)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
##
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
@dc.dataclass(frozen=True, kw_only=True)
|
|
51
|
-
class PrecheckContext:
|
|
52
|
-
src_roots: ta.Sequence[str]
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
##
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class Precheck(abc.ABC, ta.Generic[PrecheckConfigT]):
|
|
59
|
-
@dc.dataclass(frozen=True)
|
|
60
|
-
class Config:
|
|
61
|
-
pass
|
|
62
|
-
|
|
63
|
-
def __init__(self, context: PrecheckContext, config: PrecheckConfigT) -> None:
|
|
64
|
-
super().__init__()
|
|
65
|
-
self._context = context
|
|
66
|
-
self._config = config
|
|
67
|
-
|
|
68
|
-
@dc.dataclass(frozen=True)
|
|
69
|
-
class Violation:
|
|
70
|
-
pc: 'Precheck'
|
|
71
|
-
msg: str
|
|
72
|
-
|
|
73
|
-
@abc.abstractmethod
|
|
74
|
-
def run(self) -> ta.AsyncIterator[Violation]:
|
|
75
|
-
raise NotImplementedError
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
##
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class GitBlacklistPrecheck(Precheck['GitBlacklistPrecheck.Config']):
|
|
82
|
-
"""
|
|
83
|
-
TODO:
|
|
84
|
-
- globs
|
|
85
|
-
- regex
|
|
86
|
-
"""
|
|
87
|
-
|
|
88
|
-
@dc.dataclass(frozen=True)
|
|
89
|
-
class Config(Precheck.Config):
|
|
90
|
-
files: ta.Sequence[str] = (
|
|
91
|
-
'.env',
|
|
92
|
-
'secrets.yml',
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
def __init__(self, context: PrecheckContext, config: Config = Config()) -> None:
|
|
96
|
-
super().__init__(context, config)
|
|
97
|
-
|
|
98
|
-
async def run(self) -> ta.AsyncGenerator[Precheck.Violation, None]:
|
|
99
|
-
for f in self._config.files:
|
|
100
|
-
proc = await asyncio.create_subprocess_exec('git', 'status', '-s', f)
|
|
101
|
-
await proc.communicate()
|
|
102
|
-
if proc.returncode:
|
|
103
|
-
yield Precheck.Violation(self, f)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
##
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
class ScriptDepsPrecheck(Precheck['ScriptDepsPrecheck.Config']):
|
|
110
|
-
@dc.dataclass(frozen=True)
|
|
111
|
-
class Config(Precheck.Config):
|
|
112
|
-
pass
|
|
113
|
-
|
|
114
|
-
def __init__(self, context: PrecheckContext, config: Config = Config()) -> None:
|
|
115
|
-
super().__init__(context, config)
|
|
116
|
-
|
|
117
|
-
async def run(self) -> ta.AsyncGenerator[Precheck.Violation, None]:
|
|
118
|
-
for fp in findmagic.find_magic(
|
|
119
|
-
self._context.src_roots,
|
|
120
|
-
['# @omlish-script'],
|
|
121
|
-
['py'],
|
|
122
|
-
):
|
|
123
|
-
if not (stat.S_IXUSR & os.stat(fp).st_mode):
|
|
124
|
-
yield Precheck.Violation(self, f'script {fp} is not executable')
|
|
125
|
-
|
|
126
|
-
with open(fp) as f: # noqa # FIXME
|
|
127
|
-
src = f.read()
|
|
128
|
-
|
|
129
|
-
if not src.startswith('#!/usr/bin/env python3\n'):
|
|
130
|
-
yield Precheck.Violation(self, f'script {fp} lacks correct shebang')
|
|
131
|
-
|
|
132
|
-
imps = findimports.find_imports(fp)
|
|
133
|
-
deps = findimports.get_import_deps(imps)
|
|
134
|
-
if deps:
|
|
135
|
-
yield Precheck.Violation(self, f'script {fp} has deps: {deps}')
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
##
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
class LitePython8Precheck(Precheck['LitePython8Precheck.Config']):
|
|
142
|
-
@dc.dataclass(frozen=True)
|
|
143
|
-
class Config(Precheck.Config):
|
|
144
|
-
pass
|
|
145
|
-
|
|
146
|
-
def __init__(self, context: PrecheckContext, config: Config = Config()) -> None:
|
|
147
|
-
super().__init__(context, config)
|
|
148
|
-
|
|
149
|
-
#
|
|
150
|
-
|
|
151
|
-
@staticmethod
|
|
152
|
-
def _load_file_module(fp: str) -> None:
|
|
153
|
-
import os.path # noqa
|
|
154
|
-
import types # noqa
|
|
155
|
-
|
|
156
|
-
fp = os.path.abspath(fp)
|
|
157
|
-
|
|
158
|
-
with open(fp) as f:
|
|
159
|
-
src = f.read()
|
|
160
|
-
|
|
161
|
-
mn = os.path.basename(fp).rpartition('.')[0]
|
|
162
|
-
|
|
163
|
-
mod = types.ModuleType(mn)
|
|
164
|
-
mod.__name__ = mn
|
|
165
|
-
mod.__file__ = fp
|
|
166
|
-
mod.__builtins__ = __builtins__ # type: ignore
|
|
167
|
-
mod.__spec__ = None
|
|
168
|
-
|
|
169
|
-
code = compile(src, fp, 'exec')
|
|
170
|
-
exec(code, mod.__dict__, mod.__dict__)
|
|
171
|
-
|
|
172
|
-
@cached.function
|
|
173
|
-
def _load_file_module_payload(self) -> str:
|
|
174
|
-
return '\n'.join([
|
|
175
|
-
'import sys',
|
|
176
|
-
'fp = sys.argv[-1]',
|
|
177
|
-
'',
|
|
178
|
-
textwrap.dedent('\n'.join(inspect.getsource(LitePython8Precheck._load_file_module).splitlines()[2:])),
|
|
179
|
-
])
|
|
180
|
-
|
|
181
|
-
#
|
|
182
|
-
|
|
183
|
-
async def _run_script(self, fp: str) -> list[Precheck.Violation]:
|
|
184
|
-
log.debug('%s: loading script %s', self.__class__.__name__, fp)
|
|
185
|
-
|
|
186
|
-
vs: list[Precheck.Violation] = []
|
|
187
|
-
|
|
188
|
-
proc = await asyncio.create_subprocess_exec(
|
|
189
|
-
'.venvs/8/bin/python',
|
|
190
|
-
'-c',
|
|
191
|
-
self._load_file_module_payload(),
|
|
192
|
-
fp,
|
|
193
|
-
stderr=subprocess.PIPE,
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
_, stderr = await proc.communicate()
|
|
197
|
-
if proc.returncode != 0:
|
|
198
|
-
vs.append(Precheck.Violation(self, f'lite script {fp} failed to load in python8: {stderr.decode()}'))
|
|
199
|
-
|
|
200
|
-
return vs
|
|
201
|
-
|
|
202
|
-
async def _run_one_module(self, fp: str) -> list[Precheck.Violation]:
|
|
203
|
-
vs: list[Precheck.Violation] = []
|
|
204
|
-
|
|
205
|
-
mod = fp.rpartition('.')[0].replace(os.sep, '.')
|
|
206
|
-
|
|
207
|
-
log.debug('%s: loading module %s', self.__class__.__name__, mod)
|
|
208
|
-
|
|
209
|
-
proc = await asyncio.create_subprocess_exec(
|
|
210
|
-
'.venvs/8/bin/python',
|
|
211
|
-
'-c',
|
|
212
|
-
f'import {mod}',
|
|
213
|
-
stderr=subprocess.PIPE,
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
_, stderr = await proc.communicate()
|
|
217
|
-
if proc.returncode != 0:
|
|
218
|
-
vs.append(Precheck.Violation(self, f'lite module {fp} failed to import in python8: {stderr.decode()}')) # noqa
|
|
219
|
-
|
|
220
|
-
return vs
|
|
221
|
-
|
|
222
|
-
async def _run_module(self, fp: str) -> list[Precheck.Violation]:
|
|
223
|
-
vs: list[Precheck.Violation] = []
|
|
224
|
-
|
|
225
|
-
if fp.endswith('__init__.py'):
|
|
226
|
-
pfps = glob.glob(os.path.join(os.path.dirname(fp), '**/*.py'), recursive=True)
|
|
227
|
-
else:
|
|
228
|
-
pfps = [fp]
|
|
229
|
-
|
|
230
|
-
for pfp in pfps:
|
|
231
|
-
vs.extend(await self._run_one_module(pfp))
|
|
232
|
-
|
|
233
|
-
return vs
|
|
234
|
-
|
|
235
|
-
async def run(self) -> ta.AsyncGenerator[Precheck.Violation, None]:
|
|
236
|
-
for fp in findmagic.find_magic(
|
|
237
|
-
self._context.src_roots,
|
|
238
|
-
['# @omlish-lite'],
|
|
239
|
-
['py'],
|
|
240
|
-
):
|
|
241
|
-
with open(fp) as f: # noqa # FIXME
|
|
242
|
-
src = f.read()
|
|
243
|
-
|
|
244
|
-
is_script = '# @omlish-script' in src.splitlines()
|
|
245
|
-
|
|
246
|
-
if is_script:
|
|
247
|
-
for v in await self._run_script(fp):
|
|
248
|
-
yield v
|
|
249
|
-
|
|
250
|
-
else:
|
|
251
|
-
for v in await self._run_module(fp):
|
|
252
|
-
yield v
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
##
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
def _check_cmd(args) -> None:
|
|
259
|
-
if not os.path.isfile('pyproject.toml'):
|
|
260
|
-
raise RuntimeError('must run in project root')
|
|
261
|
-
|
|
262
|
-
ctx = PrecheckContext(
|
|
263
|
-
src_roots=args.roots,
|
|
264
|
-
)
|
|
265
|
-
|
|
266
|
-
pcs: list[Precheck] = [
|
|
267
|
-
GitBlacklistPrecheck(ctx),
|
|
268
|
-
ScriptDepsPrecheck(ctx),
|
|
269
|
-
LitePython8Precheck(ctx),
|
|
270
|
-
]
|
|
271
|
-
|
|
272
|
-
async def run() -> list[Precheck.Violation]:
|
|
273
|
-
vs: list[Precheck.Violation] = []
|
|
274
|
-
|
|
275
|
-
for pc in pcs:
|
|
276
|
-
async for v in pc.run():
|
|
277
|
-
vs.append(v)
|
|
278
|
-
print(v)
|
|
279
|
-
|
|
280
|
-
return vs
|
|
281
|
-
|
|
282
|
-
vs = asyncio.run(run())
|
|
283
|
-
|
|
284
|
-
if vs:
|
|
285
|
-
print(f'{len(vs)} violations found')
|
|
286
|
-
sys.exit(1)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
##
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
def _build_parser() -> argparse.ArgumentParser:
|
|
293
|
-
parser = argparse.ArgumentParser()
|
|
294
|
-
|
|
295
|
-
subparsers = parser.add_subparsers()
|
|
296
|
-
|
|
297
|
-
parser_check = subparsers.add_parser('check')
|
|
298
|
-
parser_check.add_argument('roots', nargs='+')
|
|
299
|
-
parser_check.set_defaults(func=_check_cmd)
|
|
300
|
-
|
|
301
|
-
return parser
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
def _main(argv: ta.Sequence[str] | None = None) -> None:
|
|
305
|
-
logs.configure_standard_logging('INFO')
|
|
306
|
-
|
|
307
|
-
parser = _build_parser()
|
|
308
|
-
args = parser.parse_args(argv)
|
|
309
|
-
if not getattr(args, 'func', None):
|
|
310
|
-
parser.print_help()
|
|
311
|
-
else:
|
|
312
|
-
args.func(args)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if __name__ == '__main__':
|
|
316
|
-
_main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|