Commit 56079b9c authored by Pyre Bot Jr's avatar Pyre Bot Jr Committed by Facebook GitHub Bot

Add annotations to `opensource/fbcode_builder`

Reviewed By: shannonzhu

Differential Revision: D34224272

fbshipit-source-id: 52e19886ab3d4fb015a557244660dd4357a35c17
parent 126c1959
This diff is collapsed.
......@@ -44,14 +44,14 @@ class BuildOptions(object):
scratch_dir,
host_type,
install_dir=None,
num_jobs=0,
use_shipit=False,
num_jobs: int = 0,
use_shipit: bool = False,
vcvars_path=None,
allow_system_packages=False,
allow_system_packages: bool = False,
lfs_path=None,
shared_libs=False,
shared_libs: bool = False,
facebook_internal=None,
):
) -> None:
"""fbcode_builder_dir - the path to either the in-fbsource fbcode_builder dir,
or for shipit-transformed repos, the build dir that
has been mapped into that dir.
......@@ -176,7 +176,7 @@ class BuildOptions(object):
def is_freebsd(self):
return self.host_type.is_freebsd()
def get_num_jobs(self, job_weight):
def get_num_jobs(self, job_weight: int):
"""Given an estimated job_weight in MiB, compute a reasonable concurrency limit."""
if self.specified_num_jobs:
return self.specified_num_jobs
......@@ -324,8 +324,8 @@ class BuildOptions(object):
return False
def add_prefix_to_env(
self, d, env, append=True, add_library_path=False
): # noqa: C901
self, d, env, append: bool = True, add_library_path: bool = False
) -> bool: # noqa: C901
bindir = os.path.join(d, "bin")
found = False
pkgconfig = os.path.join(d, "lib", "pkgconfig")
......@@ -472,7 +472,7 @@ def find_unused_drive_letter():
return available[-1]
def create_subst_path(path):
def create_subst_path(path) -> str:
for _attempt in range(0, 24):
drive = find_existing_win32_subst_for_path(
path, subst_mapping=list_win32_subst_letters()
......@@ -512,7 +512,7 @@ def _check_host_type(args, host_type):
return host_type
def setup_build_options(args, host_type=None):
def setup_build_options(args, host_type=None) -> BuildOptions:
"""Create a BuildOptions object based on the arguments"""
fbcode_builder_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
......
......@@ -10,7 +10,7 @@ class ArtifactCache(object):
The primary use case is for storing the build products on CI
systems to accelerate the build"""
def download_to_file(self, name, dest_file_name):
def download_to_file(self, name, dest_file_name) -> bool:
"""If `name` exists in the cache, download it and place it
in the specified `dest_file_name` location on the filesystem.
If a transient issue was encountered a TransientFailure shall
......@@ -21,7 +21,7 @@ class ArtifactCache(object):
All other conditions shall raise an appropriate exception."""
return False
def upload_from_file(self, name, source_file_name):
def upload_from_file(self, name, source_file_name) -> None:
"""Causes `name` to be populated in the cache by uploading
the contents of `source_file_name` to the storage system.
If a transient issue was encountered a TransientFailure shall
......@@ -31,7 +31,7 @@ class ArtifactCache(object):
pass
def create_cache():
def create_cache() -> None:
"""This function is monkey patchable to provide an actual
implementation"""
return None
......@@ -23,7 +23,7 @@ class CargoBuilder(BuilderBase):
workspace_dir,
manifests_to_build,
loader,
):
) -> None:
super(CargoBuilder, self).__init__(
build_opts, ctx, manifest, src_dir, build_dir, inst_dir
)
......@@ -32,7 +32,7 @@ class CargoBuilder(BuilderBase):
self.manifests_to_build = manifests_to_build and manifests_to_build.split(",")
self.loader = loader
def run_cargo(self, install_dirs, operation, args=None):
def run_cargo(self, install_dirs, operation, args=None) -> None:
args = args or []
env = self._compute_env(install_dirs)
# Enable using nightly features with stable compiler
......@@ -55,12 +55,12 @@ class CargoBuilder(BuilderBase):
def manifest_dir(self, manifest):
return os.path.join(self.build_source_dir(), manifest)
def recreate_dir(self, src, dst):
def recreate_dir(self, src, dst) -> None:
if os.path.isdir(dst):
shutil.rmtree(dst)
shutil.copytree(src, dst)
def _build(self, install_dirs, reconfigure):
def _build(self, install_dirs, reconfigure) -> None:
build_source_dir = self.build_source_dir()
self.recreate_dir(self.src_dir, build_source_dir)
......@@ -121,7 +121,7 @@ incremental = false
def run_tests(
self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot
):
) -> None:
if test_filter:
args = ["--", test_filter]
else:
......@@ -138,7 +138,7 @@ incremental = false
if self.build_doc:
self.run_cargo(install_dirs, "doc", ["--no-deps"] + margs)
def _patchup_workspace(self):
def _patchup_workspace(self) -> None:
"""
This method makes some assumptions about the state of the project and
its cargo dependendies:
......@@ -184,7 +184,7 @@ incremental = false
f.write("\n")
f.write(config)
def _resolve_config(self):
def _resolve_config(self) -> str:
"""
Returns a configuration to be put inside root Cargo.toml file which
patches the dependencies git code with local getdeps versions.
......
......@@ -45,7 +45,7 @@ def find_eden_root(dirpath):
return None
def prefetch_dir_if_eden(dirpath):
def prefetch_dir_if_eden(dirpath) -> None:
"""After an amend/rebase, Eden may need to fetch a large number
of trees from the servers. The simplistic single threaded walk
performed by copytree makes this more expensive than is desirable
......@@ -65,7 +65,8 @@ def prefetch_dir_if_eden(dirpath):
PREFETCHED_DIRS.add(dirpath)
def copytree(src_dir, dest_dir, ignore=None):
# pyre-fixme[9]: ignore has type `bool`; used as `None`.
def copytree(src_dir, dest_dir, ignore: bool = None):
"""Recursively copy the src_dir to the dest_dir, filtering
out entries using the ignore lambda. The behavior of the
ignore lambda must match that described by `shutil.copytree`.
......@@ -75,4 +76,7 @@ def copytree(src_dir, dest_dir, ignore=None):
uses watchman to mirror src_dir into dest_dir.
"""
prefetch_dir_if_eden(src_dir)
# pyre-fixme[6]: For 3rd param expected
# `Union[typing.Callable[[Union[PathLike[str], str], List[str]], Iterable[str]],
# typing.Callable[[str, List[str]], Iterable[str]], None]` but got `bool`.
return shutil.copytree(src_dir, dest_dir, ignore=ignore)
......@@ -20,13 +20,13 @@ from .envfuncs import path_search
OBJECT_SUBDIRS = ("bin", "lib", "lib64")
def copyfile(src, dest):
def copyfile(src, dest) -> None:
shutil.copyfile(src, dest)
shutil.copymode(src, dest)
class DepBase(object):
def __init__(self, buildopts, install_dirs, strip):
def __init__(self, buildopts, install_dirs, strip) -> None:
self.buildopts = buildopts
self.env = buildopts.compute_env_for_install_dirs(install_dirs)
self.install_dirs = install_dirs
......@@ -36,7 +36,7 @@ class DepBase(object):
def list_dynamic_deps(self, objfile):
raise RuntimeError("list_dynamic_deps not implemented")
def interesting_dep(self, d):
def interesting_dep(self, d) -> bool:
return True
# final_install_prefix must be the equivalent path to `destdir` on the
......@@ -44,11 +44,12 @@ class DepBase(object):
# is intended to map to `/usr/local` in the install image, then
# final_install_prefix='/usr/local'.
# If left unspecified, destdir will be used.
def process_deps(self, destdir, final_install_prefix=None):
def process_deps(self, destdir, final_install_prefix=None) -> None:
if self.buildopts.is_windows():
lib_dir = "bin"
else:
lib_dir = "lib"
# pyre-fixme[16]: `DepBase` has no attribute `munged_lib_dir`.
self.munged_lib_dir = os.path.join(destdir, lib_dir)
final_lib_dir = os.path.join(final_install_prefix or destdir, lib_dir)
......@@ -92,7 +93,7 @@ class DepBase(object):
return dep_paths
def munge_in_place(self, objfile, final_lib_dir):
def munge_in_place(self, objfile, final_lib_dir) -> None:
print("Munging %s" % objfile)
for d in self.list_dynamic_deps(objfile):
if not self.interesting_dep(d):
......@@ -103,6 +104,7 @@ class DepBase(object):
dep = self.resolve_loader_path(d)
print("dep: %s -> %s" % (d, dep))
if dep:
# pyre-fixme[16]: `DepBase` has no attribute `munged_lib_dir`.
dest_dep = os.path.join(self.munged_lib_dir, os.path.basename(dep))
if dep not in self.processed_deps:
self.processed_deps.add(dep)
......@@ -128,7 +130,7 @@ class DepBase(object):
return candidate
return None
def list_objs_in_dir(self, dir, recurse=False, output_prefix=""):
def list_objs_in_dir(self, dir, recurse: bool = False, output_prefix: str = ""):
for entry in os.listdir(dir):
entry_path = os.path.join(dir, entry)
st = os.lstat(entry_path)
......@@ -143,21 +145,21 @@ class DepBase(object):
):
yield result
def is_objfile(self, objfile):
def is_objfile(self, objfile) -> bool:
return True
def strip_debug_info(self, objfile):
def strip_debug_info(self, objfile) -> None:
"""override this to define how to remove debug information
from an object file"""
pass
class WinDeps(DepBase):
def __init__(self, buildopts, install_dirs, strip):
def __init__(self, buildopts, install_dirs, strip) -> None:
super(WinDeps, self).__init__(buildopts, install_dirs, strip)
self.dumpbin = self.find_dumpbin()
def find_dumpbin(self):
def find_dumpbin(self) -> str:
# Looking for dumpbin in the following hardcoded paths.
# The registry option to find the install dir doesn't work anymore.
globs = [
......@@ -196,7 +198,7 @@ class WinDeps(DepBase):
return deps
def rewrite_dep(self, objfile, depname, old_dep, new_dep, final_lib_dir):
def rewrite_dep(self, objfile, depname, old_dep, new_dep, final_lib_dir) -> None:
# We can't rewrite on windows, but we will
# place the deps alongside the exe so that
# they end up in the search path
......@@ -217,21 +219,21 @@ class WinDeps(DepBase):
]
)
def interesting_dep(self, d):
def interesting_dep(self, d) -> bool:
if "api-ms-win-crt" in d:
return False
if d in self.SYSTEM_DLLS:
return False
return True
def is_objfile(self, objfile):
def is_objfile(self, objfile) -> bool:
if not os.path.isfile(objfile):
return False
if objfile.lower().endswith(".exe"):
return True
return False
def emit_dev_run_script(self, script_path, dep_dirs):
def emit_dev_run_script(self, script_path, dep_dirs) -> None:
"""Emit a script that can be used to run build artifacts directly from the
build directory, without installing them.
......@@ -297,7 +299,7 @@ class WinDeps(DepBase):
return dep_dirs
def _get_dev_run_script_contents(self, path_dirs):
def _get_dev_run_script_contents(self, path_dirs) -> str:
path_entries = ["$env:PATH"] + path_dirs
path_str = ";".join(path_entries)
return """\
......@@ -316,7 +318,7 @@ try {{
class ElfDeps(DepBase):
def __init__(self, buildopts, install_dirs, strip):
def __init__(self, buildopts, install_dirs, strip) -> None:
super(ElfDeps, self).__init__(buildopts, install_dirs, strip)
# We need patchelf to rewrite deps, so ensure that it is built...
......@@ -342,15 +344,17 @@ class ElfDeps(DepBase):
lines = out.split("\n")
return lines
def rewrite_dep(self, objfile, depname, old_dep, new_dep, final_lib_dir):
def rewrite_dep(self, objfile, depname, old_dep, new_dep, final_lib_dir) -> None:
final_dep = os.path.join(
final_lib_dir, os.path.relpath(new_dep, self.munged_lib_dir)
final_lib_dir,
# pyre-fixme[16]: `ElfDeps` has no attribute `munged_lib_dir`.
os.path.relpath(new_dep, self.munged_lib_dir),
)
subprocess.check_call(
[self.patchelf, "--replace-needed", depname, final_dep, objfile]
)
def is_objfile(self, objfile):
def is_objfile(self, objfile) -> bool:
if not os.path.isfile(objfile):
return False
with open(objfile, "rb") as f:
......@@ -358,7 +362,7 @@ class ElfDeps(DepBase):
magic = f.read(4)
return magic == b"\x7fELF"
def strip_debug_info(self, objfile):
def strip_debug_info(self, objfile) -> None:
subprocess.check_call(["strip", objfile])
......@@ -367,7 +371,7 @@ MACH_MAGIC = 0xFEEDFACF
class MachDeps(DepBase):
def interesting_dep(self, d):
def interesting_dep(self, d) -> bool:
if d.startswith("/usr/lib/") or d.startswith("/System/"):
return False
return True
......@@ -403,7 +407,7 @@ class MachDeps(DepBase):
deps.append(os.path.normcase(m.group(1)))
return deps
def rewrite_dep(self, objfile, depname, old_dep, new_dep, final_lib_dir):
def rewrite_dep(self, objfile, depname, old_dep, new_dep, final_lib_dir) -> None:
if objfile.endswith(".dylib"):
# Erase the original location from the id of the shared
# object. It doesn't appear to hurt to retain it, but
......@@ -412,7 +416,9 @@ class MachDeps(DepBase):
["install_name_tool", "-id", os.path.basename(objfile), objfile]
)
final_dep = os.path.join(
final_lib_dir, os.path.relpath(new_dep, self.munged_lib_dir)
final_lib_dir,
# pyre-fixme[16]: `MachDeps` has no attribute `munged_lib_dir`.
os.path.relpath(new_dep, self.munged_lib_dir),
)
subprocess.check_call(
......@@ -420,7 +426,9 @@ class MachDeps(DepBase):
)
def create_dyn_dep_munger(buildopts, install_dirs, strip=False) -> Optional[DepBase]:
def create_dyn_dep_munger(
buildopts, install_dirs, strip: bool = False
) -> Optional[DepBase]:
if buildopts.is_linux():
return ElfDeps(buildopts, install_dirs, strip)
if buildopts.is_darwin():
......
......@@ -9,18 +9,18 @@ import sys
class Env(object):
def __init__(self, src=None):
def __init__(self, src=None) -> None:
self._dict = {}
if src is None:
self.update(os.environ)
else:
self.update(src)
def update(self, src):
def update(self, src) -> None:
for k, v in src.items():
self.set(k, v)
def copy(self):
def copy(self) -> "Env":
return Env(self._dict)
def _key(self, key):
......@@ -64,7 +64,7 @@ class Env(object):
raise KeyError(key)
return val
def unset(self, key):
def unset(self, key) -> None:
if key is None:
raise KeyError("attempting to unset env[None]")
......@@ -72,13 +72,13 @@ class Env(object):
if key:
del self._dict[key]
def __delitem__(self, key):
def __delitem__(self, key) -> None:
self.unset(key)
def __repr__(self):
return repr(self._dict)
def set(self, key, value):
def set(self, key, value) -> None:
if key is None:
raise KeyError("attempting to assign env[None] = %r" % value)
......@@ -99,13 +99,13 @@ class Env(object):
self.unset(key)
self._dict[key] = value
def __setitem__(self, key, value):
def __setitem__(self, key, value) -> None:
self.set(key, value)
def __iter__(self):
return self._dict.__iter__()
def __len__(self):
def __len__(self) -> int:
return len(self._dict)
def keys(self):
......@@ -118,7 +118,9 @@ class Env(object):
return self._dict.items()
def add_path_entry(env, name, item, append=True, separator=os.pathsep):
def add_path_entry(
env, name, item, append: bool = True, separator: str = os.pathsep
) -> None:
"""Cause `item` to be added to the path style env var named
`name` held in the `env` dict. `append` specifies whether
the item is added to the end (the default) or should be
......@@ -135,7 +137,7 @@ def add_path_entry(env, name, item, append=True, separator=os.pathsep):
env.set(name, separator.join(val))
def add_flag(env, name, flag, append=True):
def add_flag(env, name, flag, append: bool = True) -> None:
"""Cause `flag` to be added to the CXXFLAGS-style env var named
`name` held in the `env` dict. `append` specifies whether the
flag is added to the end (the default) or should be prepended if
......@@ -152,7 +154,7 @@ _path_search_cache = {}
_not_found = object()
def tpx_path():
def tpx_path() -> str:
return "xplat/testinfra/tpx/ctp.tpx"
......
......@@ -13,5 +13,5 @@ class TransientFailure(Exception):
class ManifestNotFound(Exception):
def __init__(self, manifest_name):
def __init__(self, manifest_name) -> None:
super(Exception, self).__init__("Unable to find manifest '%s'" % manifest_name)
......@@ -37,40 +37,40 @@ def parse_expr(expr_text, valid_variables):
class ExprNode(object):
def eval(self, ctx):
def eval(self, ctx) -> bool:
return False
class TrueExpr(ExprNode):
def eval(self, ctx):
def eval(self, ctx) -> bool:
return True
def __str__(self):
def __str__(self) -> str:
return "true"
class NotExpr(ExprNode):
def __init__(self, node):
def __init__(self, node) -> None:
self._node = node
def eval(self, ctx):
def eval(self, ctx) -> bool:
return not self._node.eval(ctx)
def __str__(self):
def __str__(self) -> str:
return "not(%s)" % self._node
class AllExpr(ExprNode):
def __init__(self, nodes):
def __init__(self, nodes) -> None:
self._nodes = nodes
def eval(self, ctx):
def eval(self, ctx) -> bool:
for node in self._nodes:
if not node.eval(ctx):
return False
return True
def __str__(self):
def __str__(self) -> str:
items = []
for node in self._nodes:
items.append(str(node))
......@@ -78,16 +78,16 @@ class AllExpr(ExprNode):
class AnyExpr(ExprNode):
def __init__(self, nodes):
def __init__(self, nodes) -> None:
self._nodes = nodes
def eval(self, ctx):
def eval(self, ctx) -> bool:
for node in self._nodes:
if node.eval(ctx):
return True
return False
def __str__(self):
def __str__(self) -> str:
items = []
for node in self._nodes:
items.append(str(node))
......@@ -95,19 +95,19 @@ class AnyExpr(ExprNode):
class EqualExpr(ExprNode):
def __init__(self, key, value):
def __init__(self, key, value) -> None:
self._key = key
self._value = value
def eval(self, ctx):
return ctx.get(self._key) == self._value
def __str__(self):
def __str__(self) -> str:
return "%s=%s" % (self._key, self._value)
class Parser(object):
def __init__(self, text, valid_variables):
def __init__(self, text, valid_variables) -> None:
self.text = text
self.lex = shlex.shlex(text)
self.valid_variables = valid_variables
......@@ -147,13 +147,13 @@ class Parser(object):
"Unexpected token sequence '%s %s' in %s" % (name, op, self.text)
)
def ident(self):
def ident(self) -> str:
ident = self.lex.get_token()
if not re.match("[a-zA-Z]+", ident):
raise Exception("expected identifier found %s" % ident)
return ident
def parse_not(self):
def parse_not(self) -> NotExpr:
node = self.top()
expr = NotExpr(node)
tok = self.lex.get_token()
......@@ -161,7 +161,7 @@ class Parser(object):
raise Exception("expected ')' found %s" % tok)
return expr
def parse_any(self):
def parse_any(self) -> AnyExpr:
nodes = []
while True:
nodes.append(self.top())
......@@ -172,7 +172,7 @@ class Parser(object):
raise Exception("expected ',' or ')' but found %s" % tok)
return AnyExpr(nodes)
def parse_all(self):
def parse_all(self) -> AllExpr:
nodes = []
while True:
nodes.append(self.top())
......
This diff is collapsed.
......@@ -56,7 +56,7 @@ class Loader(object):
class ResourceLoader(Loader):
def __init__(self, namespace, manifests_dir):
def __init__(self, namespace, manifests_dir) -> None:
self.namespace = namespace
self.manifests_dir = manifests_dir
......@@ -82,7 +82,7 @@ class ResourceLoader(Loader):
raise ManifestNotFound(project_name)
def _load_manifest(self, path):
def _load_manifest(self, path: str):
import pkg_resources
contents = pkg_resources.resource_string(self.namespace, path).decode("utf8")
......@@ -96,7 +96,7 @@ class ResourceLoader(Loader):
LOADER = Loader()
def patch_loader(namespace, manifests_dir="manifests"):
def patch_loader(namespace, manifests_dir: str = "manifests") -> None:
global LOADER
LOADER = ResourceLoader(namespace, manifests_dir)
......@@ -119,7 +119,7 @@ class ManifestLoader(object):
relationships and project hash values for this build configuration.
"""
def __init__(self, build_opts, ctx_gen=None):
def __init__(self, build_opts, ctx_gen=None) -> None:
self._loader = LOADER
self.build_opts = build_opts
if ctx_gen is None:
......@@ -231,16 +231,16 @@ class ManifestLoader(object):
return dep_order
def set_project_src_dir(self, project_name, path):
def set_project_src_dir(self, project_name, path) -> None:
self._fetcher_overrides[project_name] = fetcher.LocalDirFetcher(path)
def set_project_build_dir(self, project_name, path):
def set_project_build_dir(self, project_name, path) -> None:
self._build_dir_overrides[project_name] = path
def set_project_install_dir(self, project_name, path):
def set_project_install_dir(self, project_name, path) -> None:
self._install_dir_overrides[project_name] = path
def set_project_install_prefix(self, project_name, path):
def set_project_install_prefix(self, project_name, path) -> None:
self._install_prefix_overrides[project_name] = path
def create_fetcher(self, manifest):
......@@ -258,7 +258,7 @@ class ManifestLoader(object):
self._project_hashes[manifest.name] = h
return h
def _compute_project_hash(self, manifest):
def _compute_project_hash(self, manifest) -> str:
"""This recursive function computes a hash for a given manifest.
The hash takes into account some environmental factors on the
host machine and includes the hashes of its dependencies.
......
......@@ -9,7 +9,7 @@ import shlex
import sys
def is_windows():
def is_windows() -> bool:
"""Returns true if the system we are currently running on
is a Windows system"""
return sys.platform.startswith("win")
......@@ -52,7 +52,7 @@ def get_linux_type():
# but getdeps can't take third-party dependencies.
def _get_available_ram_linux():
def _get_available_ram_linux() -> int:
# TODO: Ideally, this function would inspect the current cgroup for any
# limits, rather than solely relying on system RAM.
with open("/proc/meminfo") as f:
......@@ -175,7 +175,7 @@ def get_available_ram() -> int:
class HostType(object):
def __init__(self, ostype=None, distro=None, distrovers=None):
def __init__(self, ostype=None, distro=None, distrovers=None) -> None:
if ostype is None:
distro = None
distrovers = None
......@@ -185,6 +185,7 @@ class HostType(object):
ostype = "darwin"
elif is_windows():
ostype = "windows"
# pyre-fixme[16]: Module `sys` has no attribute `getwindowsversion`.
distrovers = str(sys.getwindowsversion().major)
elif sys.platform.startswith("freebsd"):
ostype = "freebsd"
......@@ -218,7 +219,7 @@ class HostType(object):
def is_freebsd(self):
return self.ostype == "freebsd"
def as_tuple_string(self):
def as_tuple_string(self) -> str:
return "%s-%s-%s" % (
self.ostype,
self.distro or "none",
......@@ -237,7 +238,7 @@ class HostType(object):
return None
@staticmethod
def from_tuple_string(s):
def from_tuple_string(s) -> "HostType":
ostype, distro, distrovers = s.split("-")
return HostType(ostype=ostype, distro=distro, distrovers=distrovers)
......
......@@ -212,7 +212,7 @@ class PythonWheelBuilder(BuilderBase):
f.write(CMAKE_FOOTER.format(**self.template_format_dict))
def _write_cmake_config_template(self):
def _write_cmake_config_template(self) -> None:
config_path_name = self.manifest.name + "-config.cmake.in"
output_path = os.path.join(self.build_dir, config_path_name)
......
......@@ -22,7 +22,7 @@ class RunCommandError(Exception):
pass
def _print_env_diff(env, log_fn):
def _print_env_diff(env, log_fn) -> None:
current_keys = set(os.environ.keys())
wanted_env = set(env.keys())
......@@ -44,7 +44,7 @@ def _print_env_diff(env, log_fn):
log_fn("+ %s=%s \\\n" % (k, shellquote(env[k])))
def run_cmd(cmd, env=None, cwd=None, allow_fail=False, log_file=None):
def run_cmd(cmd, env=None, cwd=None, allow_fail: bool = False, log_file=None):
def log_to_stdout(msg):
sys.stdout.buffer.write(msg.encode(errors="surrogateescape"))
......@@ -64,7 +64,7 @@ def run_cmd(cmd, env=None, cwd=None, allow_fail=False, log_file=None):
)
def _run_cmd(cmd, env, cwd, allow_fail, log_fn):
def _run_cmd(cmd, env, cwd, allow_fail, log_fn) -> int:
log_fn("---\n")
try:
cmd_str = " \\\n+ ".join(shellquote(arg) for arg in cmd)
......
......@@ -8,11 +8,11 @@ class SubCmd(object):
NAME = None
HELP = None
def run(self, args):
def run(self, args) -> int:
"""perform the command"""
return 0
def setup_parser(self, parser):
def setup_parser(self, parser) -> None:
# Subclasses should override setup_parser() if they have any
# command line options or arguments.
pass
......@@ -21,7 +21,7 @@ class SubCmd(object):
CmdTable = []
def add_subcommands(parser, common_args, cmd_table=CmdTable):
def add_subcommands(parser, common_args, cmd_table=CmdTable) -> None:
"""Register parsers for the defined commands with the provided parser"""
for cls in cmd_table:
command = cls()
......
......@@ -10,37 +10,37 @@ from ..expr import parse_expr
class ExprTest(unittest.TestCase):
def test_equal(self):
def test_equal(self) -> None:
valid_variables = {"foo", "some_var", "another_var"}
e = parse_expr("foo=bar", valid_variables)
self.assertTrue(e.eval({"foo": "bar"}))
self.assertFalse(e.eval({"foo": "not-bar"}))
self.assertFalse(e.eval({"not-foo": "bar"}))
def test_not_equal(self):
def test_not_equal(self) -> None:
valid_variables = {"foo"}
e = parse_expr("not(foo=bar)", valid_variables)
self.assertFalse(e.eval({"foo": "bar"}))
self.assertTrue(e.eval({"foo": "not-bar"}))
def test_bad_not(self):
def test_bad_not(self) -> None:
valid_variables = {"foo"}
with self.assertRaises(Exception):
parse_expr("foo=not(bar)", valid_variables)
def test_bad_variable(self):
def test_bad_variable(self) -> None:
valid_variables = {"bar"}
with self.assertRaises(Exception):
parse_expr("foo=bar", valid_variables)
def test_all(self):
def test_all(self) -> None:
valid_variables = {"foo", "baz"}
e = parse_expr("all(foo = bar, baz = qux)", valid_variables)
self.assertTrue(e.eval({"foo": "bar", "baz": "qux"}))
self.assertFalse(e.eval({"foo": "bar", "baz": "nope"}))
self.assertFalse(e.eval({"foo": "nope", "baz": "nope"}))
def test_any(self):
def test_any(self) -> None:
valid_variables = {"foo", "baz"}
e = parse_expr("any(foo = bar, baz = qux)", valid_variables)
self.assertTrue(e.eval({"foo": "bar", "baz": "qux"}))
......
......@@ -12,13 +12,13 @@ from ..manifest import ManifestParser
class ManifestTest(unittest.TestCase):
def test_missing_section(self):
def test_missing_section(self) -> None:
with self.assertRaisesRegex(
Exception, "manifest file test is missing required section manifest"
):
ManifestParser("test", "")
def test_missing_name(self):
def test_missing_name(self) -> None:
with self.assertRaisesRegex(
Exception,
"manifest file test section 'manifest' is missing required field 'name'",
......@@ -30,7 +30,7 @@ class ManifestTest(unittest.TestCase):
""",
)
def test_minimal(self):
def test_minimal(self) -> None:
p = ManifestParser(
"test",
"""
......@@ -41,7 +41,7 @@ name = test
self.assertEqual(p.name, "test")
self.assertEqual(p.fbsource_path, None)
def test_minimal_with_fbsource_path(self):
def test_minimal_with_fbsource_path(self) -> None:
p = ManifestParser(
"test",
"""
......@@ -53,7 +53,7 @@ fbsource_path = fbcode/wat
self.assertEqual(p.name, "test")
self.assertEqual(p.fbsource_path, "fbcode/wat")
def test_unknown_field(self):
def test_unknown_field(self) -> None:
with self.assertRaisesRegex(
Exception,
(
......@@ -70,7 +70,7 @@ invalid.field = woot
""",
)
def test_invalid_section_name(self):
def test_invalid_section_name(self) -> None:
with self.assertRaisesRegex(
Exception, "manifest file test contains unknown section 'invalid.section'"
):
......@@ -85,7 +85,7 @@ foo = bar
""",
)
def test_value_in_dependencies_section(self):
def test_value_in_dependencies_section(self) -> None:
with self.assertRaisesRegex(
Exception,
(
......@@ -105,7 +105,7 @@ foo = bar
""",
)
def test_invalid_conditional_section_name(self):
def test_invalid_conditional_section_name(self) -> None:
with self.assertRaisesRegex(
Exception,
(
......@@ -124,7 +124,7 @@ name = test
""",
)
def test_section_as_args(self):
def test_section_as_args(self) -> None:
p = ManifestParser(
"test",
"""
......@@ -164,7 +164,7 @@ name = test
p2.get_section_as_args("autoconf.args"), ["--prefix=/foo", "--with-woot"]
)
def test_section_as_dict(self):
def test_section_as_dict(self) -> None:
p = ManifestParser(
"test",
"""
......@@ -202,12 +202,12 @@ foo = bar
msg="sections cascade in the order they appear in the manifest",
)
def test_parse_common_manifests(self):
def test_parse_common_manifests(self) -> None:
patch_loader(__name__)
manifests = load_all_manifests(None)
self.assertNotEqual(0, len(manifests), msg="parsed some number of manifests")
def test_mismatch_name(self):
def test_mismatch_name(self) -> None:
with self.assertRaisesRegex(
Exception,
"filename of the manifest 'foo' does not match the manifest name 'bar'",
......@@ -220,7 +220,7 @@ name = bar
""",
)
def test_duplicate_manifest(self):
def test_duplicate_manifest(self) -> None:
patch_loader(__name__, "fixtures/duplicate")
with self.assertRaisesRegex(Exception, "found duplicate manifest 'foo'"):
......
......@@ -10,7 +10,7 @@ from ..platform import HostType
class PlatformTest(unittest.TestCase):
def test_create(self):
def test_create(self) -> None:
p = HostType()
self.assertNotEqual(p.ostype, None, msg="probed and returned something")
......@@ -18,11 +18,11 @@ class PlatformTest(unittest.TestCase):
round_trip = HostType.from_tuple_string(tuple_string)
self.assertEqual(round_trip, p)
def test_rendering_of_none(self):
def test_rendering_of_none(self) -> None:
p = HostType(ostype="foo")
self.assertEqual(p.as_tuple_string(), "foo-none-none")
def test_is_methods(self):
def test_is_methods(self) -> None:
p = HostType(ostype="windows")
self.assertTrue(p.is_windows())
self.assertFalse(p.is_darwin())
......
......@@ -10,7 +10,7 @@ from ..buildopts import find_existing_win32_subst_for_path
class Win32SubstTest(unittest.TestCase):
def test_no_existing_subst(self):
def test_no_existing_subst(self) -> None:
self.assertIsNone(
find_existing_win32_subst_for_path(
r"C:\users\alice\appdata\local\temp\fbcode_builder_getdeps",
......@@ -24,7 +24,7 @@ class Win32SubstTest(unittest.TestCase):
)
)
def test_exact_match_returns_drive_path(self):
def test_exact_match_returns_drive_path(self) -> None:
self.assertEqual(
find_existing_win32_subst_for_path(
r"C:\temp\fbcode_builder_getdeps",
......@@ -40,7 +40,7 @@ class Win32SubstTest(unittest.TestCase):
"X:\\",
)
def test_multiple_exact_matches_returns_arbitrary_drive_path(self):
def test_multiple_exact_matches_returns_arbitrary_drive_path(self) -> None:
self.assertIn(
find_existing_win32_subst_for_path(
r"C:\temp\fbcode_builder_getdeps",
......@@ -53,7 +53,7 @@ class Win32SubstTest(unittest.TestCase):
("X:\\", "Y:\\", "Z:\\"),
)
def test_drive_letter_is_case_insensitive(self):
def test_drive_letter_is_case_insensitive(self) -> None:
self.assertEqual(
find_existing_win32_subst_for_path(
r"C:\temp\fbcode_builder_getdeps",
......@@ -62,7 +62,7 @@ class Win32SubstTest(unittest.TestCase):
"X:\\",
)
def test_path_components_are_case_insensitive(self):
def test_path_components_are_case_insensitive(self) -> None:
self.assertEqual(
find_existing_win32_subst_for_path(
r"C:\TEMP\FBCODE_builder_getdeps",
......
......@@ -43,10 +43,10 @@ class ShellQuoted(namedtuple("ShellQuoted", ("do_not_use_raw_str",))):
"or ShellQuoted.format() instead".format(repr(self))
)
def __repr__(self):
def __repr__(self) -> str:
return "{0}({1})".format(self.__class__.__name__, repr(self.do_not_use_raw_str))
def format(self, **kwargs):
def format(self, **kwargs) -> "ShellQuoted":
"""
Use instead of str.format() when the arguments are either
......@@ -65,7 +65,7 @@ class ShellQuoted(namedtuple("ShellQuoted", ("do_not_use_raw_str",))):
)
def shell_quote(s):
def shell_quote(s) -> ShellQuoted:
"Quotes a string if it is not already quoted"
return (
s
......@@ -74,19 +74,19 @@ def shell_quote(s):
)
def raw_shell(s):
def raw_shell(s: ShellQuoted):
"Not a member of ShellQuoted so we get a useful error for raw strings"
if isinstance(s, ShellQuoted):
return s.do_not_use_raw_str
raise RuntimeError("{0} should have been ShellQuoted".format(s))
def shell_join(delim, it):
def shell_join(delim, it) -> ShellQuoted:
"Joins an iterable of ShellQuoted with a delimiter between each two"
return ShellQuoted(delim.join(raw_shell(s) for s in it))
def path_join(*args):
def path_join(*args) -> ShellQuoted:
"Joins ShellQuoted and raw pieces of paths to make a shell-quoted path"
return ShellQuoted(os.path.join(*[raw_shell(shell_quote(s)) for s in args]))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment