jw.pkg: Massively tighten linter checks #53
92 changed files with 588 additions and 324 deletions
|
|
@ -1,6 +1,14 @@
|
|||
{
|
||||
"typeCheckingMode": "basic",
|
||||
"typeCheckingMode": "strict",
|
||||
"pythonPlatform": "Linux",
|
||||
"useLibraryCodeForTypes": true,
|
||||
"verboseOutput": false
|
||||
"verboseOutput": false,
|
||||
|
||||
"reportImplicitOverride": "error",
|
||||
"reportDeprecated": "error",
|
||||
"reportMatchNotExhaustive": "error",
|
||||
|
||||
"reportUnnecessaryTypeIgnoreComment": "error",
|
||||
"reportImplicitStringConcatenation": "error",
|
||||
"reportUninitializedInstanceVariable": "error"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,19 @@
|
|||
|
||||
{mypypath}
|
||||
|
||||
strict = true
|
||||
|
||||
warn_unreachable = true
|
||||
|
||||
enable_error_code = [
|
||||
"explicit-override",
|
||||
"ignore-without-code",
|
||||
"possibly-undefined",
|
||||
"truthy-bool",
|
||||
"truthy-iterable",
|
||||
"exhaustive-match",
|
||||
]
|
||||
|
||||
[tool.isort]
|
||||
|
||||
lines_between_sections = 1
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import sys
|
|||
|
||||
from enum import Enum, auto
|
||||
from functools import cache
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import Any, cast, override, TYPE_CHECKING
|
||||
|
||||
from .lib.App import App as Base
|
||||
from .lib.Distro import Distro
|
||||
|
|
@ -19,6 +19,7 @@ from .lib.ProjectConf import ProjectConf
|
|||
|
||||
if TYPE_CHECKING:
|
||||
import argparse
|
||||
from argparse import ArgumentParser
|
||||
|
||||
from typing import TypeAlias
|
||||
|
||||
|
|
@ -36,10 +37,10 @@ if TYPE_CHECKING:
|
|||
|
||||
class ResultCache(object):
|
||||
|
||||
def __init__(self):
|
||||
self.__cache = {}
|
||||
def __init__(self) -> None:
|
||||
self.__cache: dict[str, Any] = {}
|
||||
|
||||
def run(self, func, args):
|
||||
def run(self, func: Any, args: list[Any]) -> object:
|
||||
d = self.__cache
|
||||
depth = 0
|
||||
keys = [func.__name__] + args
|
||||
|
|
@ -85,7 +86,7 @@ class App(Base):
|
|||
return path
|
||||
case 'relative':
|
||||
return os.path.relpath(path)
|
||||
case None | 'absolute':
|
||||
case 'absolute':
|
||||
return os.path.abspath(path)
|
||||
case _:
|
||||
m = re.search(r'^make:(\S+)$', fmt)
|
||||
|
|
@ -136,21 +137,21 @@ class App(Base):
|
|||
if search_absdirs is None:
|
||||
search_absdirs = []
|
||||
|
||||
def __format_relpath(path: str):
|
||||
def __format_relpath(path: str) -> str:
|
||||
if path.startswith('./'):
|
||||
return path[2:]
|
||||
if path.endswith('/.'):
|
||||
return path[:-2]
|
||||
return path
|
||||
|
||||
def __relpath(target: str, base: str):
|
||||
def __relpath(target: str, base: str) -> str:
|
||||
return __format_relpath(os.path.relpath(target, base))
|
||||
|
||||
def __format_pd(name: str, pd: str, pretty: bool):
|
||||
def __format_pd(name: str, pd: str, pretty: bool) -> str | None:
|
||||
if not pretty:
|
||||
return pd
|
||||
if self.__topdir_fmt == 'absolute':
|
||||
return os.path.abspath(pd)
|
||||
return str(os.path.abspath(pd))
|
||||
if self.__topdir_fmt == 'unaltered':
|
||||
return pd
|
||||
if self.__topdir_fmt == 'relative':
|
||||
|
|
@ -174,6 +175,7 @@ class App(Base):
|
|||
path = pd + '/' + sd
|
||||
if os.path.isdir(path):
|
||||
ret = __format_pd(name, pd, pretty)
|
||||
assert ret is not None
|
||||
if sd and sd[0] != '/':
|
||||
if ret == '.':
|
||||
ret = ''
|
||||
|
|
@ -200,11 +202,22 @@ class App(Base):
|
|||
return None
|
||||
|
||||
def __get_project_refs_cached(
|
||||
self, buf, visited, spec, section, key, add_self, scope, names_only
|
||||
):
|
||||
return self.__res_cache.run(
|
||||
self.__get_project_refs,
|
||||
[buf, visited, spec, section, key, add_self, scope, names_only],
|
||||
self,
|
||||
buf: list[str],
|
||||
visited: set[str],
|
||||
spec: str,
|
||||
section: str,
|
||||
key: str,
|
||||
add_self: bool,
|
||||
scope: Scope,
|
||||
names_only: bool,
|
||||
) -> list[str]:
|
||||
return cast(
|
||||
'list[str]',
|
||||
self.__res_cache.run(
|
||||
self.__get_project_refs,
|
||||
[buf, visited, spec, section, key, add_self, scope, names_only],
|
||||
),
|
||||
)
|
||||
|
||||
def __get_project_refs(
|
||||
|
|
@ -283,7 +296,7 @@ class App(Base):
|
|||
for dep in deps:
|
||||
self.__read_dep_graph([dep], sections, graph)
|
||||
|
||||
def __flip_dep_graph(self, graph: Graph):
|
||||
def __flip_dep_graph(self, graph: Graph) -> Graph:
|
||||
ret: Graph = {}
|
||||
for project, deps in graph.items():
|
||||
for d in deps:
|
||||
|
|
@ -374,12 +387,14 @@ class App(Base):
|
|||
default_pkg_filter = pkg_filter,
|
||||
)
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb) -> None:
|
||||
@override
|
||||
async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None:
|
||||
if self.__exec_context is not None:
|
||||
await self.__exec_context.close()
|
||||
self.__exec_context = None
|
||||
|
||||
def _add_arguments(self, parser) -> None:
|
||||
@override
|
||||
def _add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super()._add_arguments(parser)
|
||||
parser.add_argument('-t', '--topdir', default = None, help = 'Project Path')
|
||||
parser.add_argument(
|
||||
|
|
@ -421,6 +436,7 @@ class App(Base):
|
|||
help = 'Default filter for all distribution package-related operations',
|
||||
)
|
||||
|
||||
@override
|
||||
async def _run(self, args: argparse.Namespace) -> None:
|
||||
self.___topdir = args.topdir
|
||||
self.___pretty_topdir = self.__format_topdir(self.___topdir, args.topdir_format)
|
||||
|
|
@ -482,7 +498,7 @@ class App(Base):
|
|||
return self.__exec_context
|
||||
|
||||
@property
|
||||
def top_name(self):
|
||||
def top_name(self) -> str | None:
|
||||
return self.__top_name
|
||||
|
||||
@property
|
||||
|
|
@ -534,7 +550,7 @@ class App(Base):
|
|||
def tmpl_dir(self, name: str) -> str | None:
|
||||
return self.find_dir(name, ['/tmpl'], ['/opt/' + name + '/share/tmpl'])
|
||||
|
||||
def strip_module_from_spec(self, mod):
|
||||
def strip_module_from_spec(self, mod: str) -> str:
|
||||
return re.sub(r'-dev$|-devel$|-run$', '', re.split('([=><]+)', mod)[0].strip())
|
||||
|
||||
@cache
|
||||
|
|
@ -569,7 +585,7 @@ class App(Base):
|
|||
return ret
|
||||
|
||||
@cache
|
||||
def get_version(self, project) -> str:
|
||||
def get_version(self, project: str) -> str:
|
||||
ret = self.get_value(project, 'version', '')
|
||||
if ret is None:
|
||||
raise Exception(f"Can't get version of project {project}")
|
||||
|
|
@ -598,9 +614,9 @@ class App(Base):
|
|||
projects: list[str],
|
||||
sections: list[str],
|
||||
keys: str | list[str],
|
||||
add_self: bool,
|
||||
scope: Scope,
|
||||
names_only = True,
|
||||
scope: Scope = Scope.One,
|
||||
add_self: bool = False,
|
||||
names_only: bool = False,
|
||||
) -> list[str]:
|
||||
if isinstance(keys, str):
|
||||
keys = [keys]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
from typing import override
|
||||
from .App import App
|
||||
from .lib.Cmd import Cmd as Base
|
||||
|
||||
class CmdBase(Base):
|
||||
|
||||
@override # pyright: ignore[reportArgumentType]
|
||||
@property
|
||||
def app(self) -> App:
|
||||
ret = super().app
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import override, TYPE_CHECKING
|
||||
|
||||
from ..App import App as Parent
|
||||
from ..CmdBase import CmdBase as Base
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from argparse import Namespace
|
||||
from typing import Iterable
|
||||
from ..lib.Distro import Distro
|
||||
|
||||
|
|
@ -20,7 +21,8 @@ class Cmd(Base): # export
|
|||
) -> None:
|
||||
super().__init__(parent, name, help, aliases = aliases)
|
||||
|
||||
async def _run(self, args):
|
||||
@override
|
||||
async def _run(self, args: 'Namespace') -> None:
|
||||
# Missing subcommand
|
||||
self.print_help(1)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from argparse import ArgumentParser
|
||||
from argparse import ArgumentParser, Namespace
|
||||
|
||||
class CmdPkg(Cmd): # export
|
||||
|
||||
|
|
@ -18,12 +18,14 @@ class CmdPkg(Cmd): # export
|
|||
)
|
||||
self.load_subcommands()
|
||||
|
||||
async def _run(self, args):
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
import sys
|
||||
|
||||
# Missing subcommand
|
||||
self.parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from argparse import ArgumentParser
|
||||
from argparse import ArgumentParser, Namespace
|
||||
|
||||
class CmdPlatform(Cmd): # export
|
||||
|
||||
|
|
@ -15,12 +15,14 @@ class CmdPlatform(Cmd): # export
|
|||
)
|
||||
self.load_subcommands()
|
||||
|
||||
async def _run(self, args):
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
import sys
|
||||
|
||||
# Missing subcommand
|
||||
self.parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from argparse import ArgumentParser
|
||||
from argparse import ArgumentParser, Namespace
|
||||
|
||||
class CmdPosix(Cmd): # export
|
||||
|
||||
|
|
@ -20,12 +20,14 @@ class CmdPosix(Cmd): # export
|
|||
)
|
||||
self.load_subcommands()
|
||||
|
||||
async def _run(self, args):
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
import sys
|
||||
|
||||
# Missing subcommand
|
||||
self.parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from argparse import ArgumentParser
|
||||
from argparse import ArgumentParser, Namespace
|
||||
|
||||
class CmdProjects(Cmd): # export
|
||||
|
||||
|
|
@ -17,12 +17,14 @@ class CmdProjects(Cmd): # export
|
|||
)
|
||||
self.load_subcommands()
|
||||
|
||||
async def _run(self, args):
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
import sys
|
||||
|
||||
# Missing subcommand
|
||||
self.parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from argparse import ArgumentParser
|
||||
from argparse import ArgumentParser, Namespace
|
||||
|
||||
class CmdSecrets(Cmd): # export
|
||||
|
||||
|
|
@ -13,12 +13,14 @@ class CmdSecrets(Cmd): # export
|
|||
super().__init__(parent, 'secrets', help = 'Manage package secrets')
|
||||
self.load_subcommands()
|
||||
|
||||
async def _run(self, args):
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
import sys
|
||||
|
||||
# Missing subcommand
|
||||
self.parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
|
|
@ -12,11 +12,13 @@ class CmdDelete(Cmd): # export
|
|||
def __init__(self, parent: Parent) -> None:
|
||||
super().__init__(parent, 'delete', help = 'Delete packages by name')
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
parser.add_argument(
|
||||
'names', nargs = '*', help = 'Names of packages to be deleted'
|
||||
)
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
return await self.distro.delete(args.names)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
|
|
@ -12,6 +12,7 @@ class CmdDup(Cmd): # export
|
|||
def __init__(self, parent: Parent) -> None:
|
||||
super().__init__(parent, 'dup', help = 'Upgrade distribution')
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
parser.add_argument(
|
||||
|
|
@ -21,5 +22,6 @@ class CmdDup(Cmd): # export
|
|||
help = "Only download packages from the repos, don't install them, yet",
|
||||
)
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
return await self.distro.dup(download_only = args.download_only)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import override, TYPE_CHECKING
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
|
|
@ -16,6 +16,7 @@ class CmdInstall(Cmd): # export
|
|||
help = "Install the distribution's notion of available packages",
|
||||
)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
parser.add_argument('names', nargs = '*', help = 'Packages to be installed')
|
||||
|
|
@ -32,6 +33,7 @@ class CmdInstall(Cmd): # export
|
|||
help = "Don't expand macros in <names>",
|
||||
)
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
names = (
|
||||
args.names if args.fixed_strings else self.distro.expand_macros(args.names)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .NamedPkgsCmd import NamedPkgsCmd
|
||||
|
||||
|
|
@ -14,9 +14,11 @@ class CmdLs(NamedPkgsCmd): # export
|
|||
def __init__(self, parent: Parent) -> None:
|
||||
super().__init__(parent, 'ls', help = 'List package contents')
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
for name in args.names:
|
||||
print('\n'.join(await self.distro.pkg_files(name)))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .NamedPkgsCmd import NamedPkgsCmd, Parent
|
||||
|
||||
|
|
@ -12,9 +12,11 @@ class CmdMeta(NamedPkgsCmd): # export
|
|||
def __init__(self, parent: Parent) -> None:
|
||||
super().__init__(parent, 'meta', help = 'List package metadata')
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
names = await self.distro.select(args.names)
|
||||
for name in names:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
|
|
@ -16,8 +16,10 @@ class CmdRebootRequired(Cmd): # export
|
|||
help = 'Check whether the machine needs rebooting'
|
||||
)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
await self.distro.reboot_required()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
|
|
@ -16,8 +16,10 @@ class CmdRefresh(Cmd): # export
|
|||
help = "Refresh the distribution's notion of available packages",
|
||||
)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
return await self.distro.ref()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from ...lib.PackageFilter import PackageFilterString
|
||||
from .Cmd import Cmd, Parent
|
||||
|
|
@ -13,10 +13,12 @@ class CmdSelect(Cmd): # export
|
|||
def __init__(self, parent: Parent) -> None:
|
||||
super().__init__(parent, 'select', help = 'Select packages by filter')
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
parser.add_argument('filter', help = 'Package filter string')
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
filter = PackageFilterString(args.filter) if args.filter else None
|
||||
for p in await self.distro.select(filter = filter):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from .Cmd import Cmd, Parent
|
||||
|
||||
|
|
@ -12,6 +12,7 @@ class NamedPkgsCmd(Cmd): # export
|
|||
def __init__(self, parent: Parent, name: str, help: str) -> None:
|
||||
super().__init__(parent, name, help)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
parser.add_argument('names', nargs = '*', help = 'Package names')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from ...lib.Distro import Distro
|
||||
from .Cmd import Cmd, Parent
|
||||
|
|
@ -15,6 +15,7 @@ class CmdInfo(Cmd): # export
|
|||
parent, 'info', help = 'Retrieve information about target platform'
|
||||
)
|
||||
|
||||
@override
|
||||
def add_arguments(self, parser: ArgumentParser) -> None:
|
||||
super().add_arguments(parser)
|
||||
parser.add_argument(
|
||||
|
|
@ -23,5 +24,6 @@ class CmdInfo(Cmd): # export
|
|||
help = f'Format string, expanding macros {", ".join(Distro.macros())}',
|
||||
)
|
||||
|
||||
@override
|
||||
async def _run(self, args: Namespace) -> None:
|
||||
print(self.app.distro.expand_macros(args.format))
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue