Browse Source

Fix get_shallowest_files_sub: Return "" (not None) if file found in root. Modify it to replace _find_sub_with_known_files.

master
poikilos 7 months ago
parent
commit
d379767a1e
  1. 144
      pyenliven/mtpatches.py
  2. 2
      tests/test_mtpatches.py

144
pyenliven/mtpatches.py

@ -196,35 +196,58 @@ def diff_only_head(base, head, rel=None, more_1char_args=None, depth=0):
return diffs # folder, so return every sub's diff(s) ([] if None)
def get_shallowest_files_sub(root, log_level=0, filter=None):
def get_shallowest_files_sub(root, log_level=0, mask=None, name=None):
"""Get the shallowest folder relative to root that contains file(s).
Args:
root (str): The folder to check for files recursively.
rel (str, optional): Leave blank (set automatically during
recursion).
depth (int, optional): Leave as 0 (set automatically during
recursion).
filter (Union[str,list[str]], optional): Filename or list of
NOTE: "" or paths ending with "." will be converted to a
real path (following symlinks if any).
log_level (int, optional): 0 for only errors. 1 for info.
mask (Union[str,list[str]], optional): Filename or list of
filenames to find (None/0/""/False/"*"/[] will match any
file).
file). If a folder contains the files, the folder path
relative to root will be returned.
name (str, optional): What parent folder name to return, or None
for any with files (see mask). Defaults to None.
Returns:
Union(str, None): Get the relative dir that contains file(s).
str: Get the relative dir that contains file(s) ("" for root,
None if not found).
"""
if (root == "") or root.endswith("."):
root = os.path.realpath(root)
return _get_shallowest_files_sub(
root,
log_level=log_level,
filter=filter,
mask=mask,
name=name,
)
def _get_shallowest_files_sub(root, rel=None, depth=0, log_level=0,
filter=None):
if isinstance(filter, str):
if filter == "*":
filter = None
filter = [filter]
mask=None, name=None):
"""Get the shallowest folder relative to root that contains file(s).
See get_shallowest_files_sub for other arguments.
Args:
rel (str, optional): Leave blank (set automatically during
recursion).
depth (int, optional): Leave as 0 (set automatically during
recursion).
Raises:
ValueError: root is None
ValueError: _description_
Returns:
str: Get the relative dir that contains file(s) ("" for root,
None if not found).
"""
if isinstance(mask, str):
if mask == "*":
mask = None
mask = [mask]
if root is None:
raise ValueError("root is {}".format(root))
if rel and rel.startswith(os.path.sep):
@ -235,10 +258,17 @@ def _get_shallowest_files_sub(root, rel=None, depth=0, log_level=0,
)
parent = os.path.join(root, rel) if rel else root
_, parent_name = os.path.split(parent)
# ^ Ok even if rel is used, since split name results in ('', name)
for sub in os.listdir(parent):
if name and (parent_name != name):
# Match against the name if name is set by caller.
continue
sub_path = os.path.join(parent, sub)
if os.path.isfile(sub_path):
if (not filter) or (sub in filter):
if (not mask) or (sub in mask):
if rel is None:
rel = "" # found in root, so rel is ""
return rel
# ^ Check *all* subs first, in case dir is listed before file.
# The *parent* has file(s), so return parent
@ -262,10 +292,11 @@ def _get_shallowest_files_sub(root, rel=None, depth=0, log_level=0,
rel=sub_rel,
depth=depth+1,
log_level=log_level,
filter=filter,
mask=mask,
name=name,
)
if found_path:
if found_path is not None:
return found_path
continue
@ -273,72 +304,33 @@ def _get_shallowest_files_sub(root, rel=None, depth=0, log_level=0,
def find_mod(parent, name):
return _find_sub_with_known_files(
mask = ["init.lua", "mod.conf", "depends.txt", "description.txt"]
# return _find_sub_with_known_files(
# parent,
# name,
# mask=mask,
# )
return get_shallowest_files_sub(
parent,
name,
filter=["init.lua", "mod.conf", "depends.txt", "description.txt"],
mask=mask,
name=name,
)
def find_modpack(parent, name):
return _find_sub_with_known_files(
mask = ["modpack.txt", "modpack.conf"]
# return _find_sub_with_known_files(
# parent,
# name,
# mask=mask,
# )
return get_shallowest_files_sub(
parent,
name,
filter=["modpack.txt", "modpack.conf"],
mask=mask,
name=name,
)
def _find_sub_with_known_files(parent, name, root_slash=None, filter=None):
"""Get relative path to Minetest mod (or "" if parent is it).
Args:
parent (str): Folder to search for Minetest mod files.
name (str): Name of the mod to find. It can still be found if it
is the same name as the parent, so if parent is "mods",
then "3d_armor/3d_armor" would be the result rather than
"3d_armor".
root_slash (str, optional): Leave as None. Recursion sets it
automatically. Defaults to None.
filter (list[str]): Defaults to files found in a mod,
but can be changed to find a modpack or anything else.
Returns:
str: relative path to Minetest mod (or "" if parent is it),
or None if not Found.
"""
if not root_slash:
root_slash = parent + os.path.sep
_, parent_name = os.path.split(parent)
if parent_name == name:
for sub in os.listdir(parent):
sub_path = os.path.join(parent, sub)
if not os.path.isfile(sub_path):
continue
if sub in filter:
# Then parent is the mod. End the search
# and return *relative* path to mod
# (with root_slash removed, so
# "" if parent matches before recursion)
return parent[len(root_slash):]
# ^ must iterate files *before* recursion to avoid deeper false
# positive suchas backup folder inside of a mod that has a
# file in filter.
for sub in os.listdir(parent):
sub_path = os.path.join(parent, sub)
if os.path.isfile(sub_path):
continue
found = _find_sub_with_known_files(
sub_path,
name,
root_slash=root_slash,
filter=filter,
)
if found:
return found
return None
def main():
bases = (
"/opt/minebest/assemble/bucket_game",
@ -365,12 +357,12 @@ def main():
continue
mod_rel = get_shallowest_files_sub(
head_sub_path,
filter=["init.lua", "mod.conf", "depends.txt",
mask=["init.lua", "mod.conf", "depends.txt",
"description.txt"],
)
modpack_rel = get_shallowest_files_sub(
head_sub_path,
filter=["modpack.txt"],
mask=["modpack.txt"],
)
if mod_rel and not modpack_rel:
mod_parent = os.path.dirname(os.path.join(head_sub_path,

2
tests/test_mtpatches.py

@ -31,7 +31,7 @@ class TestMTPatches(unittest.TestCase):
os.path.join(TESTS_DATA_DIR, "base", "unused", "sub", "has_file"),
log_level=1,
)
self.assertEqual(sub, None)
self.assertEqual(sub, "")
# ^ should be "has_file" dir, since that contains
# "shallowest_in_base.txt"

Loading…
Cancel
Save