App.find_dir(): Allow return value None

Allow find_dir() to return None in case it couldn't find a directory, that's a legal outcome. Add a boolean parameter "throw" to support throwing an exception if the existence needs to be asserted.

It would probably be nicer for the type checkers to split this up into a throwing and non-throwing function. Postponed.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-06-01 19:55:43 +02:00
commit f687ded1a6
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61
3 changed files with 27 additions and 18 deletions

View file

@ -456,24 +456,27 @@ class App(Base):
search_subdirs: list[str] = [], search_subdirs: list[str] = [],
search_absdirs: list[str] = [], search_absdirs: list[str] = [],
pretty: bool = True, pretty: bool = True,
) -> str: throw: bool = False,
) -> str | None:
ret = self.__find_dir(name, search_subdirs, search_absdirs, pretty) ret = self.__find_dir(name, search_subdirs, search_absdirs, pretty)
if ret is None: if ret is not None:
msg = f'Failed to find directory for "{name}"' return ret
if not throw:
return None
msg = f'Failed to find directory for "{name}":'
log(ERR, msg) log(ERR, msg)
for search_name, search in [ for search_name, search in [
('subdirs', search_subdirs), ('subdirs', search_subdirs),
('absdirs', search_absdirs), ('absdirs', search_absdirs),
]: ]:
if search: if search:
log(ERR, f' Searched {search_name} in:') log(ERR, f'Searched {search_name}:')
for d in search: for d in search:
log(ERR, f' - {d}') log(ERR, f' - {d}')
raise FileNotFoundError(msg) raise FileNotFoundError(msg)
return ret
# TODO: add support for customizing this in project.conf # TODO: add support for customizing this in project.conf
def htdocs_dir(self, project: str) -> str: def htdocs_dir(self, project: str) -> str | None:
return self.find_dir( return self.find_dir(
project, project,
['/src/html/htdocs', '/tools/html/htdocs', '/htdocs'], ['/src/html/htdocs', '/tools/html/htdocs', '/htdocs'],
@ -481,7 +484,7 @@ class App(Base):
) )
# TODO: add support for customizing this in project.conf # TODO: add support for customizing this in project.conf
def tmpl_dir(self, name: str) -> str: def tmpl_dir(self, name: str) -> str | None:
return self.find_dir(name, ['/tmpl'], ['/opt/' + name + '/share/tmpl']) return self.find_dir(name, ['/tmpl'], ['/opt/' + name + '/share/tmpl'])
def strip_module_from_spec(self, mod): def strip_module_from_spec(self, mod):

View file

@ -57,9 +57,12 @@ class CmdGetAuthInfo(Cmd): # export
# --- Milk jw-pkg repo # --- Milk jw-pkg repo
jw_pkg_dir = self.app.find_dir('jw-pkg', pretty = False) jw_pkg_dir = self.app.find_dir('jw-pkg', pretty = False)
if jw_pkg_dir is None:
log(DEBUG, 'Can\'t find jw-pkg directory')
return None
if not os.path.isdir(jw_pkg_dir + '/.git'): if not os.path.isdir(jw_pkg_dir + '/.git'):
log(DEBUG, f'jw-pkg directory is not a Git repo: {jw_pkg_dir}') log(DEBUG, f'jw-pkg directory is not a Git repo: {jw_pkg_dir}')
return return None
git_result = await self.app.exec_context.run( git_result = await self.app.exec_context.run(
['git', '-C', jw_pkg_dir, 'remote', '-v'] ['git', '-C', jw_pkg_dir, 'remote', '-v']
) )

View file

@ -22,5 +22,8 @@ class CmdTmplDir(Cmd): # export
async def _run(self, args: Namespace) -> None: async def _run(self, args: Namespace) -> None:
r = [] r = []
for m in args.module: for m in args.module:
r.append(self.app.tmpl_dir(m)) d = self.app.tmpl_dir(m)
if d is None:
continue
r.append(d)
print(' '.join(r)) print(' '.join(r))