summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2024-11-04 11:17:57 +0100
committerPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2024-11-28 12:19:43 +0100
commit8b44905d1784c95bd80331aa91cc9fbe2b6ee04a (patch)
tree27d9200b71d11742315a923cc972a867572dd3bf
parent9dc61e9faca5e8b05a1a2a2eed83a5468aeb6202 (diff)
downloadjustbuild-8b44905d1784c95bd80331aa91cc9fbe2b6ee04a.tar.gz
bin scripts: Use the NoReturn type hint
The NoReturn type hint should be used to ensure the return type of methods calling no-return methods are not falsely enforced to an Optional return type. Add the NoReturn type hint as needed and clear up existing Optional returns together with any corresponding casts affected by the above. While there, also fix formatting.
-rwxr-xr-xbin/bootstrap-traverser.py14
-rwxr-xr-xbin/just-deduplicate-repos.py79
-rwxr-xr-xbin/just-import-git.py36
-rwxr-xr-xbin/just-mr.py13
-rwxr-xr-xbin/parallel-bootstrap-traverser.py8
5 files changed, 83 insertions, 67 deletions
diff --git a/bin/bootstrap-traverser.py b/bin/bootstrap-traverser.py
index 9b82b338..1598c842 100755
--- a/bin/bootstrap-traverser.py
+++ b/bin/bootstrap-traverser.py
@@ -19,7 +19,7 @@ import os
import shutil
import subprocess
import sys
-from typing import Any, Dict, List, Optional, cast
+from typing import Any, Dict, List, NoReturn, cast
from argparse import ArgumentParser
@@ -32,7 +32,7 @@ def log(*args: str, **kwargs: Any) -> None:
print(*args, file=sys.stderr, **kwargs)
-def fail(s: str) -> None:
+def fail(s: str) -> NoReturn:
log(s)
sys.exit(1)
@@ -66,7 +66,7 @@ def link(src: str, dest: str) -> None:
os.symlink(src, dest)
-def build_local(desc: Json, *, root: str, config: Json) -> Optional[str]:
+def build_local(desc: Json, *, root: str, config: Json) -> str:
repo_name = desc["data"]["repository"]
repo: List[str] = config["repositories"][repo_name]["workspace_root"]
rel_path = desc["data"]["path"]
@@ -83,7 +83,7 @@ def build_tree(desc: Json, *, config: Json, root: str, graph: Json) -> str:
tree_dir_tmp = tree_dir + ".tmp"
tree_desc = graph["trees"][tree_id]
for location, desc in tree_desc.items():
- link(cast(str, build(desc, config=config, root=root, graph=graph)),
+ link(build(desc, config=config, root=root, graph=graph),
os.path.join(tree_dir_tmp, location))
# correctly handle the empty tree
os.makedirs(tree_dir_tmp, exist_ok=True)
@@ -98,7 +98,7 @@ def run_action(action_id: str, *, config: Json, root: str, graph: Json) -> str:
os.makedirs(action_dir)
action_desc = graph["actions"][action_id]
for location, desc in action_desc.get("input", {}).items():
- link(cast(str, build(desc, config=config, root=root, graph=graph)),
+ link(build(desc, config=config, root=root, graph=graph),
os.path.join(action_dir, location))
cmd = action_desc["command"]
env = action_desc.get("env")
@@ -121,7 +121,7 @@ def build_action(desc: Json, *, config: Json, root: str, graph: Json) -> str:
return os.path.join(action_dir, desc["data"]["path"])
-def build(desc: Json, *, config: Json, root: str, graph: Json) -> Optional[str]:
+def build(desc: Json, *, config: Json, root: str, graph: Json) -> str:
if desc["type"] == "TREE":
return build_tree(desc, config=config, root=root, graph=graph)
if desc["type"] == "ACTION":
@@ -139,7 +139,7 @@ def traverse(*, graph: Json, to_build: Json, out: str, root: str,
os.makedirs(root, exist_ok=True)
create_blobs(graph["blobs"], root=root)
for location, artifact in to_build.items():
- link(cast(str, build(artifact, config=config, root=root, graph=graph)),
+ link(build(artifact, config=config, root=root, graph=graph),
os.path.join(out, location))
diff --git a/bin/just-deduplicate-repos.py b/bin/just-deduplicate-repos.py
index ca4780b0..df64df8e 100755
--- a/bin/just-deduplicate-repos.py
+++ b/bin/just-deduplicate-repos.py
@@ -16,15 +16,17 @@
import json
import sys
-from typing import Any, Dict, List, Optional, Union, cast
+from typing import Any, Dict, List, NoReturn, Optional, Tuple, Union, cast
# generic JSON type
Json = Any
+
def log(*args: str, **kwargs: Any) -> None:
print(*args, file=sys.stderr, **kwargs)
-def fail(s: str, exit_code: int = 1):
+
+def fail(s: str, exit_code: int = 1) -> NoReturn:
log(f"Error: {s}")
sys.exit(exit_code)
@@ -45,29 +47,39 @@ def roots_equal(a: Json, b: Json) -> bool:
# for full equality
return a == b
-def get_root(repos: Json, name: str, *, root_name: str="repository",
- default_root : Optional[Json]=None) -> Json:
+
+def get_root(repos: Json,
+ name: str,
+ *,
+ root_name: str = "repository",
+ default_root: Optional[Json] = None) -> Json:
root = repos[name].get(root_name)
if root is None:
if default_root is not None:
return default_root
else:
- fail("Did not find mandatory root %s" % (name,))
+ fail("Did not find mandatory root %s" % (name, ))
if isinstance(root, str):
return get_root(repos, root)
return root
+
def local_repos_equal(repos: Json, name_a: str, name_b: str) -> bool:
if name_a == name_b:
return True
root_a = None
root_b = None
- for root_name in ["repository",
- "target_root", "rule_root", "expression_root"]:
- root_a = get_root(repos, name_a, root_name=root_name,
- default_root = root_a)
- root_b = get_root(repos, name_b, root_name=root_name,
- default_root = root_b)
+ for root_name in [
+ "repository", "target_root", "rule_root", "expression_root"
+ ]:
+ root_a = get_root(repos,
+ name_a,
+ root_name=root_name,
+ default_root=root_a)
+ root_b = get_root(repos,
+ name_b,
+ root_name=root_name,
+ default_root=root_b)
if not roots_equal(root_a, root_b):
return False
for file_name, default_name in [("target_file_name", "TARGETS"),
@@ -83,38 +95,38 @@ def local_repos_equal(repos: Json, name_a: str, name_b: str) -> bool:
return False
return True
+
def bisimilar_repos(repos: Json) -> List[List[str]]:
"""Compute the maximal bisimulation between the repositories
and return the bisimilarity classes."""
- bisim = {}
+ bisim: Dict[Tuple[str, str], Json] = {}
def is_different(name_a: str, name_b: str) -> bool:
return bisim.get((name_a, name_b), {}).get("different", False)
def mark_as_different(name_a: str, name_b: str):
nonlocal bisim
- entry = bisim.get((name_a, name_b),{})
+ entry = bisim.get((name_a, name_b), {})
if entry.get("different"):
return
bisim[(name_a, name_b)] = dict(entry, **{"different": True})
- also_different = entry.get("different_if", [])
+ also_different: List[Tuple[str, str]] = entry.get("different_if", [])
for a, b in also_different:
mark_as_different(a, b)
def register_dependency(name_a: str, name_b: str, dep_a: str, dep_b: str):
pos = (name_a, name_b) if name_a < name_b else (name_b, name_a)
entry = bisim.get(pos, {})
- deps = entry.get("different_if", [])
+ deps: List[Tuple[str, str]] = entry.get("different_if", [])
deps.append((dep_a, dep_b))
bisim[pos] = dict(entry, **{"different_if": deps})
-
names = sorted(repos.keys())
for j in range(len(names)):
b = names[j]
for i in range(j):
a = names[i]
- if is_different(a,b):
+ if is_different(a, b):
continue
if not local_repos_equal(repos, names[i], names[j]):
mark_as_different(names[i], names[j])
@@ -126,12 +138,12 @@ def bisimilar_repos(repos: Json) -> List[List[str]]:
next_b = links_b[link]
if next_a != next_b:
if is_different(next_a, next_b):
- mark_as_different(a,b)
+ mark_as_different(a, b)
continue
else:
register_dependency(next_a, next_b, a, b)
- classes = []
- done = {}
+ classes: List[List[str]] = []
+ done: Dict[str, bool] = {}
for j in reversed(range(len(names))):
name_j = names[j]
if done.get(name_j):
@@ -139,12 +151,13 @@ def bisimilar_repos(repos: Json) -> List[List[str]]:
c = [name_j]
for i in range(j):
name_i = names[i]
- if not bisim.get((name_i, name_j),{}).get("different"):
+ if not bisim.get((name_i, name_j), {}).get("different"):
c.append(name_i)
done[name_i] = True
classes.append(c)
return classes
+
def dedup(repos: Json, user_keep: List[str]) -> Json:
keep = set(user_keep)
@@ -157,9 +170,10 @@ def dedup(repos: Json, user_keep: List[str]) -> Json:
candidates = c
# Keep a repository with a proper root, if any of those has a root.
# In this way, we're not losing actual roots.
- with_root = [ n for n in candidates
- if isinstance(repos["repositories"][n]["repository"],
- dict)]
+ with_root = [
+ n for n in candidates
+ if isinstance(repos["repositories"][n]["repository"], dict)
+ ]
if with_root:
candidates = with_root
@@ -168,8 +182,7 @@ def dedup(repos: Json, user_keep: List[str]) -> Json:
if keep_entries:
candidates = list(keep_entries)
- return sorted(candidates,
- key=lambda s: (s.count("/"), len(s), s))[0]
+ return sorted(candidates, key=lambda s: (s.count("/"), len(s), s))[0]
def merge_pragma(rep: str, merged: List[str]) -> Json:
desc = cast(Union[str, Dict[str, Json]],
@@ -179,7 +192,7 @@ def dedup(repos: Json, user_keep: List[str]) -> Json:
pragma = desc.get("pragma", {})
# Clear pragma absent unless all merged repos that are not references
# have the pragma
- absent = pragma.get("absent", False)
+ absent: bool = pragma.get("absent", False)
for c in merged:
alt_desc = cast(Union[str, Dict[str, Json]],
repos["repositories"][c]["repository"])
@@ -207,8 +220,8 @@ def dedup(repos: Json, user_keep: List[str]) -> Json:
return desc
bisim = bisimilar_repos(repos["repositories"])
- renaming = {}
- updated_repos = {}
+ renaming: Dict[str, str] = {}
+ updated_repos: Json = {}
for c in bisim:
if len(c) == 1:
continue
@@ -226,12 +239,11 @@ def dedup(repos: Json, user_keep: List[str]) -> Json:
# actual root; can still be merged into a different once, but only
# one with a proper root as well.
return renaming.get(name, name)
- elif isinstance(root, str):
+ if isinstance(root, str):
return final_root_reference(root)
- else:
- fail("Invalid root found for %r: %r" % (name, root))
+ fail("Invalid root found for %r: %r" % (name, root))
- new_repos = {}
+ new_repos: Json = {}
for name in repos["repositories"].keys():
if name not in renaming:
desc = repos["repositories"][name]
@@ -255,6 +267,7 @@ def dedup(repos: Json, user_keep: List[str]) -> Json:
new_repos[name] = desc
return dict(repos, **{"repositories": new_repos})
+
if __name__ == "__main__":
orig = json.load(sys.stdin)
final = dedup(orig, sys.argv[1:])
diff --git a/bin/just-import-git.py b/bin/just-import-git.py
index 7416bb7b..eb3b690f 100755
--- a/bin/just-import-git.py
+++ b/bin/just-import-git.py
@@ -23,7 +23,7 @@ import tempfile
from argparse import ArgumentParser, Namespace
from pathlib import Path
-from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, cast
+from typing import Any, Dict, Iterable, List, NoReturn, Optional, Set, Tuple, cast
# generic JSON type that avoids getter issues; proper use is being enforced by
# return types of methods and typing vars holding return values of json getters
@@ -34,7 +34,7 @@ def log(*args: str, **kwargs: Any) -> None:
print(*args, file=sys.stderr, **kwargs)
-def fail(s: str, exit_code: int = 1):
+def fail(s: str, exit_code: int = 1) -> NoReturn:
log(f"Error: {s}")
sys.exit(exit_code)
@@ -114,7 +114,7 @@ def get_repository_config_file(root: Optional[str] = None) -> Optional[str]:
return path
-def get_base_config(repository_config: Optional[str]) -> Optional[Json]:
+def get_base_config(repository_config: Optional[str]) -> Json:
if repository_config == "-":
return json.load(sys.stdin)
if not repository_config:
@@ -125,9 +125,13 @@ def get_base_config(repository_config: Optional[str]) -> Optional[Json]:
fail('Could not get base config')
-def clone(url: str, branch: str, *,
- mirrors: List[str], inherit_env: List[str],
- ) -> Tuple[str, Dict[str, Any], str]:
+def clone(
+ url: str,
+ branch: str,
+ *,
+ mirrors: List[str],
+ inherit_env: List[str],
+) -> Tuple[str, Dict[str, Any], str]:
# clone the given git repository, checkout the specified
# branch, and return the checkout location
workdir: str = tempfile.mkdtemp()
@@ -157,7 +161,7 @@ def get_repo_to_import(config: Json) -> str:
return cast(str, config.get("main"))
repos = config.get("repositories", {}).keys()
if repos:
- return sorted(repos)[0]
+ return cast(str, sorted(repos)[0])
fail("Config does not contain any repositories; unsure what to import")
@@ -226,8 +230,8 @@ def name_imports(to_import: List[str],
return assign
-def rewrite_repo(repo_spec: Json, *, remote: Dict[str, Any],
- assign: Json, absent: bool) -> Json:
+def rewrite_repo(repo_spec: Json, *, remote: Dict[str, Any], assign: Json,
+ absent: bool) -> Json:
new_spec: Json = {}
repo = repo_spec.get("repository", {})
if isinstance(repo, str):
@@ -261,12 +265,13 @@ def rewrite_repo(repo_spec: Json, *, remote: Dict[str, Any],
def handle_import(args: Namespace) -> Json:
- base_config: Json = cast(Json, get_base_config(args.repository_config))
+ base_config: Json = get_base_config(args.repository_config)
base_repos: Json = base_config.get("repositories", {})
srcdir, remote, to_cleanup = clone(
- args.URL, args.branch,
- mirrors = args.mirrors,
- inherit_env = args.inherit_env,
+ args.URL,
+ args.branch,
+ mirrors=args.mirrors,
+ inherit_env=args.inherit_env,
)
if args.foreign_repository_config:
foreign_config_file = args.foreign_repository_config
@@ -293,7 +298,7 @@ def handle_import(args: Namespace) -> Json:
fail('Could not get repository config file')
foreign_repos: Json = foreign_config.get("repositories", {})
if args.foreign_repository_name:
- foreign_name = args.foreign_repository_name
+ foreign_name = cast(str, args.foreign_repository_name)
else:
foreign_name = get_repo_to_import(foreign_config)
import_map: Json = {}
@@ -357,8 +362,7 @@ def main():
parser.add_argument(
"--absent",
action="store_true",
- help="Import repository and all its dependencies as absent."
- )
+ help="Import repository and all its dependencies as absent.")
parser.add_argument(
"--as",
dest="import_as",
diff --git a/bin/just-mr.py b/bin/just-mr.py
index 21413546..4b79c295 100755
--- a/bin/just-mr.py
+++ b/bin/just-mr.py
@@ -22,7 +22,7 @@ import sys
import tempfile
import time
import zlib
-from typing import Any, Dict, List, Optional, Set, Tuple, Union, cast
+from typing import Any, Dict, List, NoReturn, Optional, Set, Tuple, Union, cast
from argparse import ArgumentParser
from pathlib import Path
@@ -140,7 +140,7 @@ def log(*args: str, **kwargs: Any) -> None:
print(*args, file=sys.stderr, **kwargs)
-def fail(s: str, exit_code: int = 65) -> None:
+def fail(s: str, exit_code: int = 65) -> NoReturn:
log(f"Error: {s}")
sys.exit(exit_code)
@@ -701,7 +701,7 @@ def distdir_tree_id_file(content: str) -> str:
content)
-def distdir_checkout(desc: Json, repos: Json):
+def distdir_checkout(desc: Json, repos: Json) -> List[str]:
""" Logic for processing the distdir repo type.
"""
content: Dict[str, str] = {}
@@ -783,7 +783,7 @@ def distdir_checkout(desc: Json, repos: Json):
]
-def checkout(desc: Json, *, name: str, repos: Json) -> Optional[List[str]]:
+def checkout(desc: Json, *, name: str, repos: Json) -> List[str]:
repo_desc = resolve_repo(desc, repos=repos)
repo_type = repo_desc.get("type")
if repo_type == "git":
@@ -965,8 +965,7 @@ def fetch(*,
return os.path.commonpath([path, base]) == base
# warn if fetch_dir is in invocation workspace
- if g_WORKSPACE_ROOT and is_subpath(cast(str, fetch_dir),
- g_WORKSPACE_ROOT):
+ if g_WORKSPACE_ROOT and is_subpath(fetch_dir, g_WORKSPACE_ROOT):
repo = repos.get(main, {}).get("repository", {})
repo_path = repo.get("path", None)
if repo_path is not None and repo.get("type", None) == "file":
@@ -993,7 +992,7 @@ Warning: Writing distribution files to workspace location '{fetch_dir}',
print("%r --> %r (content: %s)" % (repo, distfile, content))
archive_fetch(repo_desc, content)
shutil.copyfile(cas_path(content),
- os.path.join(cast(str, fetch_dir), distfile))
+ os.path.join(fetch_dir, distfile))
sys.exit(0)
diff --git a/bin/parallel-bootstrap-traverser.py b/bin/parallel-bootstrap-traverser.py
index ee5bb194..f27525d7 100755
--- a/bin/parallel-bootstrap-traverser.py
+++ b/bin/parallel-bootstrap-traverser.py
@@ -23,7 +23,7 @@ import sys
import threading
from enum import Enum
from argparse import ArgumentParser
-from typing import Any, Callable, Dict, List, Optional, Tuple, cast
+from typing import Any, Callable, Dict, List, NoReturn, Optional, Tuple, cast
# generic JSON type that avoids getter issues; proper use is being enforced by
# return types of methods and typing vars holding return values of json getters
@@ -195,11 +195,11 @@ class AtomicListMap:
g_CALLBACKS_PER_ID = AtomicListMap()
-def log(*args: str, **kwargs: Any):
+def log(*args: str, **kwargs: Any) -> None:
print(*args, file=sys.stderr, **kwargs)
-def fail(s: str):
+def fail(s: str) -> NoReturn:
log(s)
sys.exit(1)
@@ -236,7 +236,7 @@ def link(src: str, dest: str) -> None:
os.symlink(src, dest)
-def build_local(desc: Json, *, root: str, config: Json) -> Optional[str]:
+def build_local(desc: Json, *, root: str, config: Json) -> str:
repo_name: str = desc["data"]["repository"]
repo: List[str] = config["repositories"][repo_name]["workspace_root"]
rel_path: str = desc["data"]["path"]