jw.pkg.App.get_modules_from_project_txt(): Add Scope

Add the Enum "Scope" to denote the scope argument of
jw.pkg.App.get_modules_from_project_txt(), because it explains itself
better than an integer.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-01-26 13:13:12 +01:00
commit f6ed191d73
11 changed files with 36 additions and 24 deletions

View file

@ -5,6 +5,7 @@
import os, sys, argparse, pwd, re import os, sys, argparse, pwd, re
from functools import lru_cache from functools import lru_cache
from enum import Enum, auto
from .lib.App import App as Base from .lib.App import App as Base
from .lib.log import * from .lib.log import *
@ -46,6 +47,11 @@ class ResultCache(object):
#d = d[k] #d = d[k]
raise Exception("cache algorithm failed for function", func.__name__, "in depth", depth) raise Exception("cache algorithm failed for function", func.__name__, "in depth", depth)
class Scope(Enum):
Self = auto()
One = auto()
Subtree = auto()
# ----------------------------------------------------------------- class App # ----------------------------------------------------------------- class App
class App(Base): class App(Base):
@ -323,15 +329,11 @@ class App(Base):
r = r + " " + val r = r + " " + val
return self.remove_duplicates([x.strip() for x in r.split(",")]) return self.remove_duplicates([x.strip() for x in r.split(",")])
# scope 0: no children
# scope 1: children
# scope 2: recursive
def add_modules_from_project_txt_cached(self, buf, visited, spec, section, key, add_self, scope, names_only): def add_modules_from_project_txt_cached(self, buf, visited, spec, section, key, add_self, scope, names_only):
return self.__res_cache.run(self.add_modules_from_project_txt, [buf, visited, spec, section, key, add_self, scope, names_only]) return self.__res_cache.run(self.add_modules_from_project_txt, [buf, visited, spec, section, key, add_self, scope, names_only])
def add_modules_from_project_txt(self, buf: list[str], visited: set[str], spec: str, def add_modules_from_project_txt(self, buf: list[str], visited: set[str], spec: str,
section: str, key: str, add_self: bool, scope: int, names_only: bool): section: str, key: str, add_self: bool, scope: Scope, names_only: bool):
name = self.strip_module_from_spec(spec) name = self.strip_module_from_spec(spec)
if names_only: if names_only:
spec = name spec = name
@ -343,12 +345,12 @@ class App(Base):
return return
visited.add(spec) visited.add(spec)
deps = self.get_value(name, section, key) deps = self.get_value(name, section, key)
log(DEBUG, "name = ", name, "section = ", section, "key = ", key, "deps = ", deps, "scope = ", scope, "visited = ", visited) log(DEBUG, "name = ", name, "section = ", section, "key = ", key, "deps = ", deps, "scope = ", scope.name, "visited = ", visited)
if deps and scope > 0: if deps and scope != Scope.Self:
if scope == 1: if scope == Scope.One:
subscope = 0 subscope = Scope.Self
else: else:
subscope = 2 subscope = Scope.Subtree
deps = deps.split(',') deps = deps.split(',')
for dep in deps: for dep in deps:
dep = dep.strip() dep = dep.strip()
@ -381,7 +383,7 @@ class App(Base):
def get_libname(self, names): def get_libname(self, names):
vals = self.get_modules_from_project_txt(names, ['build'], 'libname', vals = self.get_modules_from_project_txt(names, ['build'], 'libname',
scope = 1, add_self=False, names_only=True) scope = Scope.One, add_self=False, names_only=True)
if not vals: if not vals:
return ' '.join(names) return ' '.join(names)
if 'none' in vals: if 'none' in vals:
@ -391,7 +393,7 @@ class App(Base):
def is_excluded_from_build(self, module): def is_excluded_from_build(self, module):
log(DEBUG, "checking if module " + module + " is excluded from build") log(DEBUG, "checking if module " + module + " is excluded from build")
exclude = self.get_modules_from_project_txt([ module ], ['build'], 'exclude', exclude = self.get_modules_from_project_txt([ module ], ['build'], 'exclude',
scope = 1, add_self=False, names_only=True) scope = Scope.One, add_self=False, names_only=True)
cascade = self.os_cascade() + [ 'all' ] cascade = self.os_cascade() + [ 'all' ]
for p1 in exclude: for p1 in exclude:
for p2 in cascade: for p2 in cascade:
@ -413,7 +415,7 @@ class App(Base):
if m in graph: if m in graph:
continue continue
deps = self.get_modules_from_project_txt([ m ], ['pkg.requires.jw'], section, deps = self.get_modules_from_project_txt([ m ], ['pkg.requires.jw'], section,
scope = 1, add_self=False, names_only=True) scope = Scope.One, add_self=False, names_only=True)
if not deps is None: if not deps is None:
graph[m] = deps graph[m] = deps
for d in deps: for d in deps:

View file

@ -6,6 +6,7 @@ from functools import lru_cache
from ...lib.log import * from ...lib.log import *
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
class CmdBuild(Cmd): # export class CmdBuild(Cmd): # export
@ -36,7 +37,7 @@ class CmdBuild(Cmd): # export
dep_cache[prereq_type]: dict[str, str] = {} dep_cache[prereq_type]: dict[str, str] = {}
ret = self.app.get_modules_from_project_txt([ cur ], ['pkg.requires.jw'], ret = self.app.get_modules_from_project_txt([ cur ], ['pkg.requires.jw'],
prereq_type, scope = 2, add_self=False, names_only=True) prereq_type, scope = Scope.Subtree, add_self=False, names_only=True)
log(DEBUG, 'prerequisites = ' + ' '.join(ret)) log(DEBUG, 'prerequisites = ' + ' '.join(ret))
if cur in ret: if cur in ret:
ret.remove(cur) ret.remove(cur)

View file

@ -3,6 +3,7 @@
from argparse import Namespace, ArgumentParser from argparse import Namespace, ArgumentParser
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
class CmdCflags(Cmd): # export class CmdCflags(Cmd): # export
@ -15,7 +16,7 @@ class CmdCflags(Cmd): # export
def _run(self, args: Namespace) -> None: def _run(self, args: Namespace) -> None:
deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], 'build', deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], 'build',
scope = 2, add_self=True, names_only=True) scope = Scope.Subtree, add_self=True, names_only=True)
out = [] out = []
for m in reversed(deps): for m in reversed(deps):
path = self.app.find_dir(m, ['/include']) path = self.app.find_dir(m, ['/include'])

View file

@ -3,6 +3,7 @@
from argparse import Namespace, ArgumentParser from argparse import Namespace, ArgumentParser
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
class CmdExepath(Cmd): # export class CmdExepath(Cmd): # export
@ -15,7 +16,7 @@ class CmdExepath(Cmd): # export
def _run(self, args: Namespace) -> None: def _run(self, args: Namespace) -> None:
deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], [ 'run', 'build', 'devel' ], deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], [ 'run', 'build', 'devel' ],
scope = 2, add_self=True, names_only=True) scope = Scope.Subtree, add_self=True, names_only=True)
out = [] out = []
for m in deps: for m in deps:
path = self.app.find_dir(m, ['/bin']) path = self.app.find_dir(m, ['/bin'])

View file

@ -3,6 +3,7 @@
from argparse import Namespace, ArgumentParser from argparse import Namespace, ArgumentParser
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
class CmdLdflags(Cmd): # export class CmdLdflags(Cmd): # export
@ -19,7 +20,7 @@ class CmdLdflags(Cmd): # export
# -L needs to contain more paths than libs linked with -l would require # -L needs to contain more paths than libs linked with -l would require
def __get_ldpathflags(self, names: list[str], exclude: list[str] = []) -> str: def __get_ldpathflags(self, names: list[str], exclude: list[str] = []) -> str:
deps = self.app.get_modules_from_project_txt(names, ['pkg.requires.jw'], 'build', deps = self.app.get_modules_from_project_txt(names, ['pkg.requires.jw'], 'build',
scope = 2, add_self=True, names_only=True) scope = Scope.Subtree, add_self=True, names_only=True)
ret = [] ret = []
for m in deps: for m in deps:
if m in exclude: if m in exclude:
@ -37,7 +38,7 @@ class CmdLdflags(Cmd): # export
def _run(self, args: Namespace) -> None: def _run(self, args: Namespace) -> None:
deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], 'build', deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], 'build',
scope = 1, add_self=args.add_self, names_only=True) scope = Scope.One, add_self=args.add_self, names_only=True)
out = [] out = []
for m in reversed(deps): for m in reversed(deps):
if m in args.exclude: if m in args.exclude:

View file

@ -3,6 +3,7 @@
from argparse import Namespace, ArgumentParser from argparse import Namespace, ArgumentParser
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
class CmdLdlibpath(Cmd): # export class CmdLdlibpath(Cmd): # export
@ -15,7 +16,7 @@ class CmdLdlibpath(Cmd): # export
def _run(self, args: Namespace) -> None: def _run(self, args: Namespace) -> None:
deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], [ 'run', 'build', 'devel' ], deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], [ 'run', 'build', 'devel' ],
scope = 2, add_self=True, names_only=True) scope = Scope.Subtree, add_self=True, names_only=True)
out = [] out = []
for m in deps: for m in deps:
path = self.app.find_dir(m, ['/lib']) path = self.app.find_dir(m, ['/lib'])

View file

@ -3,6 +3,7 @@
from argparse import Namespace, ArgumentParser from argparse import Namespace, ArgumentParser
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
class CmdPath(Cmd): # export class CmdPath(Cmd): # export
@ -15,7 +16,7 @@ class CmdPath(Cmd): # export
def _run(self, args: Namespace) -> None: def _run(self, args: Namespace) -> None:
deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], 'run', deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], 'run',
scope = 2, add_self=True, names_only=True) scope = Scope.Subtree, add_self=True, names_only=True)
out = [] out = []
for m in deps: for m in deps:
path = self.app.find_dir(m, '/bin') path = self.app.find_dir(m, '/bin')

View file

@ -3,6 +3,7 @@
from argparse import Namespace, ArgumentParser from argparse import Namespace, ArgumentParser
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
# TODO: seems at least partly redundant to CmdPkgRequires / print_pkg_relations # TODO: seems at least partly redundant to CmdPkgRequires / print_pkg_relations
class CmdPrereq(Cmd): # export class CmdPrereq(Cmd): # export
@ -17,5 +18,5 @@ class CmdPrereq(Cmd): # export
def _run(self, args: Namespace) -> None: def _run(self, args: Namespace) -> None:
deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'],
args.flavour, scope = 2, add_self=False, names_only=True) args.flavour, scope = Scope.Subtree, add_self=False, names_only=True)
print(' '.join(deps)) print(' '.join(deps))

View file

@ -3,6 +3,7 @@
from argparse import Namespace, ArgumentParser from argparse import Namespace, ArgumentParser
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
class CmdPythonpath(Cmd): # export class CmdPythonpath(Cmd): # export
@ -15,7 +16,7 @@ class CmdPythonpath(Cmd): # export
def _run(self, args: Namespace) -> None: def _run(self, args: Namespace) -> None:
deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], [ 'run', 'build' ], deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], [ 'run', 'build' ],
scope = 2, add_self=True, names_only=True) scope = Scope.Subtree, add_self=True, names_only=True)
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, ['src/python', 'tools/python'])

View file

@ -3,6 +3,7 @@
from argparse import Namespace, ArgumentParser from argparse import Namespace, ArgumentParser
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
class CmdPythonpathOrig(Cmd): # export class CmdPythonpathOrig(Cmd): # export
@ -15,7 +16,7 @@ class CmdPythonpathOrig(Cmd): # export
def _run(self, args: Namespace) -> None: def _run(self, args: Namespace) -> None:
deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], [ 'run', 'build' ], deps = self.app.get_modules_from_project_txt(args.module, ['pkg.requires.jw'], [ 'run', 'build' ],
scope = 2, add_self=True, names_only=True) scope = Scope.Subtree, add_self=True, names_only=True)
r = '' r = ''
for m in deps: for m in deps:
pd = self.app.find_dir(m, pretty=False) pd = self.app.find_dir(m, pretty=False)

View file

@ -4,6 +4,7 @@ from argparse import Namespace, ArgumentParser
from ...lib.log import * from ...lib.log import *
from ..Cmd import Cmd from ..Cmd import Cmd
from ...App import Scope
# TODO: seems at least partly redundant to CmdPkgRequires / print_pkg_relations # TODO: seems at least partly redundant to CmdPkgRequires / print_pkg_relations
class CmdRequiredOsPkg(Cmd): # export class CmdRequiredOsPkg(Cmd): # export
@ -26,7 +27,7 @@ class CmdRequiredOsPkg(Cmd): # export
flavours.append('run') flavours.append('run')
log(DEBUG, "flavours = " + args.flavours) log(DEBUG, "flavours = " + args.flavours)
deps = self.app.get_modules_from_project_txt(modules, ['pkg.requires.jw'], flavours, deps = self.app.get_modules_from_project_txt(modules, ['pkg.requires.jw'], flavours,
scope = 2, add_self=True, names_only=True) scope = Scope.Subtree, add_self=True, names_only=True)
if args.skip_excluded: if args.skip_excluded:
for d in deps: for d in deps:
if self.app.is_excluded_from_build(d) is not None: if self.app.is_excluded_from_build(d) is not None: