Improve CmdPythonpath / mypy_path generation #10

Merged
Jan Lindemann merged 4 commits from jan/feature/20260611-feature/20260611-better-mypy-path into master 2026-06-11 12:48:14 +02:00 AGit
4 changed files with 36 additions and 45 deletions

View file

@ -1,10 +1,10 @@
include $(JWBDIR)/make/ldlibpath.mk include $(JWBDIR)/make/projects.mk
TD_GENERATE_FILES += pyproject.toml TD_GENERATE_FILES += pyproject.toml
PY_CHECK_EXCLUDE ?= PY_CHECK_EXCLUDE ?=
MYPY_CONFIG_PATH = $(subst :,:$$MYPY_CONFIG_FILE_DIR/,:$(PYTHONPATH)) MYPY_CONFIG_PATH = $(shell $(JW_PKG_PY) --topdir-format relative projects pythonpath --prefix '$$MYPY_CONFIG_FILE_DIR/' $(PROJECT))
MYPY_PATH_DIRECTIVE = mypy_path = "$(MYPY_CONFIG_PATH)" MYPY_PATH_DIRECTIVE = mypy_path = "$(MYPY_CONFIG_PATH)"
ifndef PY_CHECK_ROOTS ifndef PY_CHECK_ROOTS

View file

@ -83,6 +83,8 @@ class App(Base):
match fmt: match fmt:
case 'unaltered': case 'unaltered':
return path return path
case 'relative':
return os.path.relpath(path)
case None | 'absolute': case None | 'absolute':
return os.path.abspath(path) return os.path.abspath(path)
case _: case _:
@ -135,6 +137,8 @@ class App(Base):
return os.path.abspath(pd) return os.path.abspath(pd)
if self.__topdir_fmt == 'unaltered': if self.__topdir_fmt == 'unaltered':
return pd return pd
if self.__topdir_fmt == 'relative':
return os.path.relpath(pd, self.__pretty_topdir)
if name == self.__top_name: if name == self.__top_name:
return self.__pretty_topdir return self.__pretty_topdir
raise NotImplementedError( raise NotImplementedError(
@ -151,7 +155,10 @@ class App(Base):
if os.path.isdir(path): if os.path.isdir(path):
ret = format_pd(name, pd, pretty) ret = format_pd(name, pd, pretty)
if sd and sd[0] != '/': if sd and sd[0] != '/':
ret += '/' if ret == '.':
ret = ''
else:
ret += '/'
ret += sd ret += sd
return ret return ret
for ret in search_absdirs: for ret in search_absdirs:
@ -345,7 +352,7 @@ class App(Base):
default = 'absolute', default = 'absolute',
help = ( help = (
'Output references to topdir as one of "make:<var-name>", ' 'Output references to topdir as one of "make:<var-name>", '
'"unaltered", "absolute". Absolute topdir by default' '"unaltered", "relative", "absolute". Absolute topdir by default'
), ),
) )
parser.add_argument( parser.add_argument(

View file

@ -1,8 +1,9 @@
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING
from ...App import Scope from ...App import Scope
from .Cmd import Cmd, Parent from .Cmd import Cmd, Parent
from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from argparse import ArgumentParser, Namespace from argparse import ArgumentParser, Namespace
@ -16,6 +17,25 @@ class CmdPythonpath(Cmd): # export
def add_arguments(self, parser: ArgumentParser) -> None: def add_arguments(self, parser: ArgumentParser) -> None:
super().add_arguments(parser) super().add_arguments(parser)
parser.add_argument(
'--subdir',
action = 'append',
help = (
'Directories to look for relative to the '
'respective project root directory'
),
default = ['src/python', 'tools/python'],
)
parser.add_argument(
'--delimiter',
default = ':',
help = 'Delimiter between paths',
)
parser.add_argument(
'--prefix',
help = 'Prefix to prepend before every path component',
dest = 'path_component_prefix',
)
parser.add_argument('module', help = 'Modules', nargs = '*') parser.add_argument('module', help = 'Modules', nargs = '*')
async def _run(self, args: Namespace) -> None: async def _run(self, args: Namespace) -> None:
@ -29,8 +49,10 @@ class CmdPythonpath(Cmd): # export
) )
out = [] out = []
for m in deps: for m in deps:
path = self.app.find_dir(m, ['src/python', 'tools/python']) path = self.app.find_dir(m, args.subdir)
if path is not None: if path is not None:
if args.path_component_prefix is not None:
path = f'{args.path_component_prefix}{path}'
out.append(path) out.append(path)
if out: if out:
print(':'.join(out)) print(args.delimiter.join(out))

View file

@ -1,38 +0,0 @@
from __future__ import annotations
import os
from ...App import Scope
from .Cmd import Cmd, Parent
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from argparse import ArgumentParser, Namespace
class CmdPythonpathOrig(Cmd): # export
def __init__(self, parent: Parent) -> None:
super().__init__(parent, 'pythonpath_orig', help = 'pythonpath')
def add_arguments(self, parser: ArgumentParser) -> None:
super().add_arguments(parser)
parser.add_argument('module', nargs = '*', help = 'Modules')
async def _run(self, args: Namespace) -> None:
deps = self.app.get_project_refs(
args.module,
['pkg.requires.jw'],
['run', 'build'],
scope = Scope.Subtree,
add_self = True,
names_only = True,
)
r = ''
for m in deps:
pd = self.app.find_dir(m, pretty = False)
if pd is None:
continue
for subdir in ['src/python', 'tools/python']:
cand = pd + '/' + subdir
if os.path.isdir(cand):
r = r + ':' + cand
print(r[1:])