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
...@@ -29,7 +29,7 @@ class BuilderBase(object): ...@@ -29,7 +29,7 @@ class BuilderBase(object):
inst_dir, inst_dir,
env=None, env=None,
final_install_prefix=None, final_install_prefix=None,
): ) -> None:
self.env = Env() self.env = Env()
if env: if env:
self.env.update(env) self.env.update(env)
...@@ -57,7 +57,14 @@ class BuilderBase(object): ...@@ -57,7 +57,14 @@ class BuilderBase(object):
return [vcvarsall, "amd64", "&&"] return [vcvarsall, "amd64", "&&"]
return [] return []
def _run_cmd(self, cmd, cwd=None, env=None, use_cmd_prefix=True, allow_fail=False): def _run_cmd(
self,
cmd,
cwd=None,
env=None,
use_cmd_prefix: bool = True,
allow_fail: bool = False,
):
if env: if env:
e = self.env.copy() e = self.env.copy()
e.update(env) e.update(env)
...@@ -79,7 +86,7 @@ class BuilderBase(object): ...@@ -79,7 +86,7 @@ class BuilderBase(object):
allow_fail=allow_fail, allow_fail=allow_fail,
) )
def build(self, install_dirs, reconfigure): def build(self, install_dirs, reconfigure: bool) -> None:
print("Building %s..." % self.manifest.name) print("Building %s..." % self.manifest.name)
if self.build_dir is not None: if self.build_dir is not None:
...@@ -97,6 +104,7 @@ class BuilderBase(object): ...@@ -97,6 +104,7 @@ class BuilderBase(object):
script_path = self.get_dev_run_script_path() script_path = self.get_dev_run_script_path()
dep_munger = create_dyn_dep_munger(self.build_opts, install_dirs) dep_munger = create_dyn_dep_munger(self.build_opts, install_dirs)
dep_dirs = self.get_dev_run_extra_path_dirs(install_dirs, dep_munger) dep_dirs = self.get_dev_run_extra_path_dirs(install_dirs, dep_munger)
# pyre-fixme[16]: Optional type has no attribute `emit_dev_run_script`.
dep_munger.emit_dev_run_script(script_path, dep_dirs) dep_munger.emit_dev_run_script(script_path, dep_dirs)
@property @property
...@@ -122,12 +130,12 @@ class BuilderBase(object): ...@@ -122,12 +130,12 @@ class BuilderBase(object):
def run_tests( def run_tests(
self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot
): ) -> None:
"""Execute any tests that we know how to run. If they fail, """Execute any tests that we know how to run. If they fail,
raise an exception.""" raise an exception."""
pass pass
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
"""Perform the build. """Perform the build.
install_dirs contains the list of installation directories for install_dirs contains the list of installation directories for
the dependencies of this project. the dependencies of this project.
...@@ -166,7 +174,7 @@ class MakeBuilder(BuilderBase): ...@@ -166,7 +174,7 @@ class MakeBuilder(BuilderBase):
build_args, build_args,
install_args, install_args,
test_args, test_args,
): ) -> None:
super(MakeBuilder, self).__init__( super(MakeBuilder, self).__init__(
build_opts, ctx, manifest, src_dir, build_dir, inst_dir build_opts, ctx, manifest, src_dir, build_dir, inst_dir
) )
...@@ -181,7 +189,7 @@ class MakeBuilder(BuilderBase): ...@@ -181,7 +189,7 @@ class MakeBuilder(BuilderBase):
def _get_prefix(self): def _get_prefix(self):
return ["PREFIX=" + self.inst_dir, "prefix=" + self.inst_dir] return ["PREFIX=" + self.inst_dir, "prefix=" + self.inst_dir]
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
env = self._compute_env(install_dirs) env = self._compute_env(install_dirs)
...@@ -208,7 +216,7 @@ class MakeBuilder(BuilderBase): ...@@ -208,7 +216,7 @@ class MakeBuilder(BuilderBase):
def run_tests( def run_tests(
self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot
): ) -> None:
if not self.test_args: if not self.test_args:
return return
...@@ -219,7 +227,7 @@ class MakeBuilder(BuilderBase): ...@@ -219,7 +227,7 @@ class MakeBuilder(BuilderBase):
class CMakeBootStrapBuilder(MakeBuilder): class CMakeBootStrapBuilder(MakeBuilder):
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
self._run_cmd( self._run_cmd(
[ [
"./bootstrap", "./bootstrap",
...@@ -241,7 +249,7 @@ class AutoconfBuilder(BuilderBase): ...@@ -241,7 +249,7 @@ class AutoconfBuilder(BuilderBase):
inst_dir, inst_dir,
args, args,
conf_env_args, conf_env_args,
): ) -> None:
super(AutoconfBuilder, self).__init__( super(AutoconfBuilder, self).__init__(
build_opts, ctx, manifest, src_dir, build_dir, inst_dir build_opts, ctx, manifest, src_dir, build_dir, inst_dir
) )
...@@ -252,7 +260,7 @@ class AutoconfBuilder(BuilderBase): ...@@ -252,7 +260,7 @@ class AutoconfBuilder(BuilderBase):
def _make_binary(self): def _make_binary(self):
return self.manifest.get("build", "make_binary", "make", ctx=self.ctx) return self.manifest.get("build", "make_binary", "make", ctx=self.ctx)
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
configure_path = os.path.join(self.src_dir, "configure") configure_path = os.path.join(self.src_dir, "configure")
autogen_path = os.path.join(self.src_dir, "autogen.sh") autogen_path = os.path.join(self.src_dir, "autogen.sh")
...@@ -295,12 +303,12 @@ class Iproute2Builder(BuilderBase): ...@@ -295,12 +303,12 @@ class Iproute2Builder(BuilderBase):
# Thus, explicitly copy sources from src_dir to build_dir, bulid, # Thus, explicitly copy sources from src_dir to build_dir, bulid,
# and then install to inst_dir using DESTDIR # and then install to inst_dir using DESTDIR
# lastly, also copy include from build_dir to inst_dir # lastly, also copy include from build_dir to inst_dir
def __init__(self, build_opts, ctx, manifest, src_dir, build_dir, inst_dir): def __init__(self, build_opts, ctx, manifest, src_dir, build_dir, inst_dir) -> None:
super(Iproute2Builder, self).__init__( super(Iproute2Builder, self).__init__(
build_opts, ctx, manifest, src_dir, build_dir, inst_dir build_opts, ctx, manifest, src_dir, build_dir, inst_dir
) )
def _patch(self): def _patch(self) -> None:
# FBOSS build currently depends on an old version of iproute2 (commit # FBOSS build currently depends on an old version of iproute2 (commit
# 7ca63aef7d1b0c808da0040c6b366ef7a61f38c1). This is missing a commit # 7ca63aef7d1b0c808da0040c6b366ef7a61f38c1). This is missing a commit
# (ae717baf15fb4d30749ada3948d9445892bac239) needed to build iproute2 # (ae717baf15fb4d30749ada3948d9445892bac239) needed to build iproute2
...@@ -313,7 +321,7 @@ class Iproute2Builder(BuilderBase): ...@@ -313,7 +321,7 @@ class Iproute2Builder(BuilderBase):
f.write("#include <stdint.h>\n") f.write("#include <stdint.h>\n")
f.write(data) f.write(data)
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
configure_path = os.path.join(self.src_dir, "configure") configure_path = os.path.join(self.src_dir, "configure")
env = self.env.copy() env = self.env.copy()
...@@ -334,7 +342,7 @@ class Iproute2Builder(BuilderBase): ...@@ -334,7 +342,7 @@ class Iproute2Builder(BuilderBase):
class BistroBuilder(BuilderBase): class BistroBuilder(BuilderBase):
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
p = os.path.join(self.src_dir, "bistro", "bistro") p = os.path.join(self.src_dir, "bistro", "bistro")
env = self._compute_env(install_dirs) env = self._compute_env(install_dirs)
env["PATH"] = env["PATH"] + ":" + os.path.join(p, "bin") env["PATH"] = env["PATH"] + ":" + os.path.join(p, "bin")
...@@ -361,7 +369,7 @@ class BistroBuilder(BuilderBase): ...@@ -361,7 +369,7 @@ class BistroBuilder(BuilderBase):
def run_tests( def run_tests(
self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot
): ) -> None:
env = self._compute_env(install_dirs) env = self._compute_env(install_dirs)
build_dir = os.path.join(self.src_dir, "bistro", "bistro", "cmake", "Release") build_dir = os.path.join(self.src_dir, "bistro", "bistro", "cmake", "Release")
NUM_RETRIES = 5 NUM_RETRIES = 5
...@@ -508,7 +516,7 @@ if __name__ == "__main__": ...@@ -508,7 +516,7 @@ if __name__ == "__main__":
loader=None, loader=None,
final_install_prefix=None, final_install_prefix=None,
extra_cmake_defines=None, extra_cmake_defines=None,
): ) -> None:
super(CMakeBuilder, self).__init__( super(CMakeBuilder, self).__init__(
build_opts, build_opts,
ctx, ctx,
...@@ -533,7 +541,7 @@ if __name__ == "__main__": ...@@ -533,7 +541,7 @@ if __name__ == "__main__":
if build_opts.shared_libs: if build_opts.shared_libs:
self.defines["BUILD_SHARED_LIBS"] = "ON" self.defines["BUILD_SHARED_LIBS"] = "ON"
def _invalidate_cache(self): def _invalidate_cache(self) -> None:
for name in [ for name in [
"CMakeCache.txt", "CMakeCache.txt",
"CMakeFiles/CMakeError.log", "CMakeFiles/CMakeError.log",
...@@ -545,14 +553,14 @@ if __name__ == "__main__": ...@@ -545,14 +553,14 @@ if __name__ == "__main__":
elif os.path.exists(name): elif os.path.exists(name):
os.unlink(name) os.unlink(name)
def _needs_reconfigure(self): def _needs_reconfigure(self) -> bool:
for name in ["CMakeCache.txt", "build.ninja"]: for name in ["CMakeCache.txt", "build.ninja"]:
name = os.path.join(self.build_dir, name) name = os.path.join(self.build_dir, name)
if not os.path.exists(name): if not os.path.exists(name):
return True return True
return False return False
def _write_build_script(self, **kwargs): def _write_build_script(self, **kwargs) -> None:
env_lines = [" {!r}: {!r},".format(k, v) for k, v in kwargs["env"].items()] env_lines = [" {!r}: {!r},".format(k, v) for k, v in kwargs["env"].items()]
kwargs["env_str"] = "\n".join(["{"] + env_lines + ["}"]) kwargs["env_str"] = "\n".join(["{"] + env_lines + ["}"])
...@@ -668,7 +676,7 @@ if __name__ == "__main__": ...@@ -668,7 +676,7 @@ if __name__ == "__main__":
return define_args return define_args
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
reconfigure = reconfigure or self._needs_reconfigure() reconfigure = reconfigure or self._needs_reconfigure()
env = self._compute_env(install_dirs) env = self._compute_env(install_dirs)
...@@ -713,8 +721,8 @@ if __name__ == "__main__": ...@@ -713,8 +721,8 @@ if __name__ == "__main__":
) )
def run_tests( def run_tests(
self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot self, install_dirs, schedule_type, owner, test_filter, retry: int, no_testpilot
): ) -> None:
env = self._compute_env(install_dirs) env = self._compute_env(install_dirs)
ctest = path_search(env, "ctest") ctest = path_search(env, "ctest")
cmake = path_search(env, "cmake") cmake = path_search(env, "cmake")
...@@ -917,19 +925,21 @@ if __name__ == "__main__": ...@@ -917,19 +925,21 @@ if __name__ == "__main__":
# Only add this option in the second run. # Only add this option in the second run.
args += ["--rerun-failed"] args += ["--rerun-failed"]
count += 1 count += 1
# pyre-fixme[61]: `retcode` is undefined, or not always defined.
if retcode != 0: if retcode != 0:
# Allow except clause in getdeps.main to catch and exit gracefully # Allow except clause in getdeps.main to catch and exit gracefully
# This allows non-testpilot runs to fail through the same logic as failed testpilot runs, which may become handy in case if post test processing is needed in the future # This allows non-testpilot runs to fail through the same logic as failed testpilot runs, which may become handy in case if post test processing is needed in the future
# pyre-fixme[61]: `retcode` is undefined, or not always defined.
raise subprocess.CalledProcessError(retcode, args) raise subprocess.CalledProcessError(retcode, args)
class NinjaBootstrap(BuilderBase): class NinjaBootstrap(BuilderBase):
def __init__(self, build_opts, ctx, manifest, build_dir, src_dir, inst_dir): def __init__(self, build_opts, ctx, manifest, build_dir, src_dir, inst_dir) -> None:
super(NinjaBootstrap, self).__init__( super(NinjaBootstrap, self).__init__(
build_opts, ctx, manifest, src_dir, build_dir, inst_dir build_opts, ctx, manifest, src_dir, build_dir, inst_dir
) )
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
self._run_cmd([sys.executable, "configure.py", "--bootstrap"], cwd=self.src_dir) self._run_cmd([sys.executable, "configure.py", "--bootstrap"], cwd=self.src_dir)
src_ninja = os.path.join(self.src_dir, "ninja") src_ninja = os.path.join(self.src_dir, "ninja")
dest_ninja = os.path.join(self.inst_dir, "bin/ninja") dest_ninja = os.path.join(self.inst_dir, "bin/ninja")
...@@ -941,12 +951,12 @@ class NinjaBootstrap(BuilderBase): ...@@ -941,12 +951,12 @@ class NinjaBootstrap(BuilderBase):
class OpenSSLBuilder(BuilderBase): class OpenSSLBuilder(BuilderBase):
def __init__(self, build_opts, ctx, manifest, build_dir, src_dir, inst_dir): def __init__(self, build_opts, ctx, manifest, build_dir, src_dir, inst_dir) -> None:
super(OpenSSLBuilder, self).__init__( super(OpenSSLBuilder, self).__init__(
build_opts, ctx, manifest, src_dir, build_dir, inst_dir build_opts, ctx, manifest, src_dir, build_dir, inst_dir
) )
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
configure = os.path.join(self.src_dir, "Configure") configure = os.path.join(self.src_dir, "Configure")
# prefer to resolve the perl that we installed from # prefer to resolve the perl that we installed from
...@@ -1001,7 +1011,7 @@ class OpenSSLBuilder(BuilderBase): ...@@ -1001,7 +1011,7 @@ class OpenSSLBuilder(BuilderBase):
class Boost(BuilderBase): class Boost(BuilderBase):
def __init__( def __init__(
self, build_opts, ctx, manifest, src_dir, build_dir, inst_dir, b2_args self, build_opts, ctx, manifest, src_dir, build_dir, inst_dir, b2_args
): ) -> None:
children = os.listdir(src_dir) children = os.listdir(src_dir)
assert len(children) == 1, "expected a single directory entry: %r" % (children,) assert len(children) == 1, "expected a single directory entry: %r" % (children,)
boost_src = children[0] boost_src = children[0]
...@@ -1012,7 +1022,7 @@ class Boost(BuilderBase): ...@@ -1012,7 +1022,7 @@ class Boost(BuilderBase):
) )
self.b2_args = b2_args self.b2_args = b2_args
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
env = self._compute_env(install_dirs) env = self._compute_env(install_dirs)
linkage = ["static"] linkage = ["static"]
if self.build_opts.is_windows() or self.build_opts.shared_libs: if self.build_opts.is_windows() or self.build_opts.shared_libs:
...@@ -1068,12 +1078,12 @@ class Boost(BuilderBase): ...@@ -1068,12 +1078,12 @@ class Boost(BuilderBase):
class NopBuilder(BuilderBase): class NopBuilder(BuilderBase):
def __init__(self, build_opts, ctx, manifest, src_dir, inst_dir): def __init__(self, build_opts, ctx, manifest, src_dir, inst_dir) -> None:
super(NopBuilder, self).__init__( super(NopBuilder, self).__init__(
build_opts, ctx, manifest, src_dir, None, inst_dir build_opts, ctx, manifest, src_dir, None, inst_dir
) )
def build(self, install_dirs, reconfigure): def build(self, install_dirs, reconfigure) -> None:
print("Installing %s -> %s" % (self.src_dir, self.inst_dir)) print("Installing %s -> %s" % (self.src_dir, self.inst_dir))
parent = os.path.dirname(self.inst_dir) parent = os.path.dirname(self.inst_dir)
if not os.path.exists(parent): if not os.path.exists(parent):
...@@ -1116,12 +1126,12 @@ class OpenNSABuilder(NopBuilder): ...@@ -1116,12 +1126,12 @@ class OpenNSABuilder(NopBuilder):
# In future, if more builders require git-lfs, we would consider installing # In future, if more builders require git-lfs, we would consider installing
# git-lfs as part of the sandcastle infra as against repeating similar # git-lfs as part of the sandcastle infra as against repeating similar
# logic for each builder that requires git-lfs. # logic for each builder that requires git-lfs.
def __init__(self, build_opts, ctx, manifest, src_dir, inst_dir): def __init__(self, build_opts, ctx, manifest, src_dir, inst_dir) -> None:
super(OpenNSABuilder, self).__init__( super(OpenNSABuilder, self).__init__(
build_opts, ctx, manifest, src_dir, inst_dir build_opts, ctx, manifest, src_dir, inst_dir
) )
def build(self, install_dirs, reconfigure): def build(self, install_dirs, reconfigure) -> None:
env = self._compute_env(install_dirs) env = self._compute_env(install_dirs)
self._run_cmd(["git", "lfs", "install", "--local"], cwd=self.src_dir, env=env) self._run_cmd(["git", "lfs", "install", "--local"], cwd=self.src_dir, env=env)
self._run_cmd(["git", "lfs", "pull"], cwd=self.src_dir, env=env) self._run_cmd(["git", "lfs", "pull"], cwd=self.src_dir, env=env)
...@@ -1130,12 +1140,12 @@ class OpenNSABuilder(NopBuilder): ...@@ -1130,12 +1140,12 @@ class OpenNSABuilder(NopBuilder):
class SqliteBuilder(BuilderBase): class SqliteBuilder(BuilderBase):
def __init__(self, build_opts, ctx, manifest, src_dir, build_dir, inst_dir): def __init__(self, build_opts, ctx, manifest, src_dir, build_dir, inst_dir) -> None:
super(SqliteBuilder, self).__init__( super(SqliteBuilder, self).__init__(
build_opts, ctx, manifest, src_dir, build_dir, inst_dir build_opts, ctx, manifest, src_dir, build_dir, inst_dir
) )
def _build(self, install_dirs, reconfigure): def _build(self, install_dirs, reconfigure) -> None:
for f in ["sqlite3.c", "sqlite3.h", "sqlite3ext.h"]: for f in ["sqlite3.c", "sqlite3.h", "sqlite3ext.h"]:
src = os.path.join(self.src_dir, f) src = os.path.join(self.src_dir, f)
dest = os.path.join(self.build_dir, f) dest = os.path.join(self.build_dir, f)
......
...@@ -44,14 +44,14 @@ class BuildOptions(object): ...@@ -44,14 +44,14 @@ class BuildOptions(object):
scratch_dir, scratch_dir,
host_type, host_type,
install_dir=None, install_dir=None,
num_jobs=0, num_jobs: int = 0,
use_shipit=False, use_shipit: bool = False,
vcvars_path=None, vcvars_path=None,
allow_system_packages=False, allow_system_packages: bool = False,
lfs_path=None, lfs_path=None,
shared_libs=False, shared_libs: bool = False,
facebook_internal=None, facebook_internal=None,
): ) -> None:
"""fbcode_builder_dir - the path to either the in-fbsource fbcode_builder dir, """fbcode_builder_dir - the path to either the in-fbsource fbcode_builder dir,
or for shipit-transformed repos, the build dir that or for shipit-transformed repos, the build dir that
has been mapped into that dir. has been mapped into that dir.
...@@ -176,7 +176,7 @@ class BuildOptions(object): ...@@ -176,7 +176,7 @@ class BuildOptions(object):
def is_freebsd(self): def is_freebsd(self):
return self.host_type.is_freebsd() 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.""" """Given an estimated job_weight in MiB, compute a reasonable concurrency limit."""
if self.specified_num_jobs: if self.specified_num_jobs:
return self.specified_num_jobs return self.specified_num_jobs
...@@ -324,8 +324,8 @@ class BuildOptions(object): ...@@ -324,8 +324,8 @@ class BuildOptions(object):
return False return False
def add_prefix_to_env( def add_prefix_to_env(
self, d, env, append=True, add_library_path=False self, d, env, append: bool = True, add_library_path: bool = False
): # noqa: C901 ) -> bool: # noqa: C901
bindir = os.path.join(d, "bin") bindir = os.path.join(d, "bin")
found = False found = False
pkgconfig = os.path.join(d, "lib", "pkgconfig") pkgconfig = os.path.join(d, "lib", "pkgconfig")
...@@ -472,7 +472,7 @@ def find_unused_drive_letter(): ...@@ -472,7 +472,7 @@ def find_unused_drive_letter():
return available[-1] return available[-1]
def create_subst_path(path): def create_subst_path(path) -> str:
for _attempt in range(0, 24): for _attempt in range(0, 24):
drive = find_existing_win32_subst_for_path( drive = find_existing_win32_subst_for_path(
path, subst_mapping=list_win32_subst_letters() path, subst_mapping=list_win32_subst_letters()
...@@ -512,7 +512,7 @@ def _check_host_type(args, host_type): ...@@ -512,7 +512,7 @@ def _check_host_type(args, host_type):
return 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""" """Create a BuildOptions object based on the arguments"""
fbcode_builder_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) fbcode_builder_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
......
...@@ -10,7 +10,7 @@ class ArtifactCache(object): ...@@ -10,7 +10,7 @@ class ArtifactCache(object):
The primary use case is for storing the build products on CI The primary use case is for storing the build products on CI
systems to accelerate the build""" 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 """If `name` exists in the cache, download it and place it
in the specified `dest_file_name` location on the filesystem. in the specified `dest_file_name` location on the filesystem.
If a transient issue was encountered a TransientFailure shall If a transient issue was encountered a TransientFailure shall
...@@ -21,7 +21,7 @@ class ArtifactCache(object): ...@@ -21,7 +21,7 @@ class ArtifactCache(object):
All other conditions shall raise an appropriate exception.""" All other conditions shall raise an appropriate exception."""
return False 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 """Causes `name` to be populated in the cache by uploading
the contents of `source_file_name` to the storage system. the contents of `source_file_name` to the storage system.
If a transient issue was encountered a TransientFailure shall If a transient issue was encountered a TransientFailure shall
...@@ -31,7 +31,7 @@ class ArtifactCache(object): ...@@ -31,7 +31,7 @@ class ArtifactCache(object):
pass pass
def create_cache(): def create_cache() -> None:
"""This function is monkey patchable to provide an actual """This function is monkey patchable to provide an actual
implementation""" implementation"""
return None return None
...@@ -23,7 +23,7 @@ class CargoBuilder(BuilderBase): ...@@ -23,7 +23,7 @@ class CargoBuilder(BuilderBase):
workspace_dir, workspace_dir,
manifests_to_build, manifests_to_build,
loader, loader,
): ) -> None:
super(CargoBuilder, self).__init__( super(CargoBuilder, self).__init__(
build_opts, ctx, manifest, src_dir, build_dir, inst_dir build_opts, ctx, manifest, src_dir, build_dir, inst_dir
) )
...@@ -32,7 +32,7 @@ class CargoBuilder(BuilderBase): ...@@ -32,7 +32,7 @@ class CargoBuilder(BuilderBase):
self.manifests_to_build = manifests_to_build and manifests_to_build.split(",") self.manifests_to_build = manifests_to_build and manifests_to_build.split(",")
self.loader = loader 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 [] args = args or []
env = self._compute_env(install_dirs) env = self._compute_env(install_dirs)
# Enable using nightly features with stable compiler # Enable using nightly features with stable compiler
...@@ -55,12 +55,12 @@ class CargoBuilder(BuilderBase): ...@@ -55,12 +55,12 @@ class CargoBuilder(BuilderBase):
def manifest_dir(self, manifest): def manifest_dir(self, manifest):
return os.path.join(self.build_source_dir(), 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): if os.path.isdir(dst):
shutil.rmtree(dst) shutil.rmtree(dst)
shutil.copytree(src, 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() build_source_dir = self.build_source_dir()
self.recreate_dir(self.src_dir, build_source_dir) self.recreate_dir(self.src_dir, build_source_dir)
...@@ -121,7 +121,7 @@ incremental = false ...@@ -121,7 +121,7 @@ incremental = false
def run_tests( def run_tests(
self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot self, install_dirs, schedule_type, owner, test_filter, retry, no_testpilot
): ) -> None:
if test_filter: if test_filter:
args = ["--", test_filter] args = ["--", test_filter]
else: else:
...@@ -138,7 +138,7 @@ incremental = false ...@@ -138,7 +138,7 @@ incremental = false
if self.build_doc: if self.build_doc:
self.run_cargo(install_dirs, "doc", ["--no-deps"] + margs) 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 This method makes some assumptions about the state of the project and
its cargo dependendies: its cargo dependendies:
...@@ -184,7 +184,7 @@ incremental = false ...@@ -184,7 +184,7 @@ incremental = false
f.write("\n") f.write("\n")
f.write(config) f.write(config)
def _resolve_config(self): def _resolve_config(self) -> str:
""" """
Returns a configuration to be put inside root Cargo.toml file which Returns a configuration to be put inside root Cargo.toml file which
patches the dependencies git code with local getdeps versions. patches the dependencies git code with local getdeps versions.
......
...@@ -45,7 +45,7 @@ def find_eden_root(dirpath): ...@@ -45,7 +45,7 @@ def find_eden_root(dirpath):
return None 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 """After an amend/rebase, Eden may need to fetch a large number
of trees from the servers. The simplistic single threaded walk of trees from the servers. The simplistic single threaded walk
performed by copytree makes this more expensive than is desirable performed by copytree makes this more expensive than is desirable
...@@ -65,7 +65,8 @@ def prefetch_dir_if_eden(dirpath): ...@@ -65,7 +65,8 @@ def prefetch_dir_if_eden(dirpath):
PREFETCHED_DIRS.add(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 """Recursively copy the src_dir to the dest_dir, filtering
out entries using the ignore lambda. The behavior of the out entries using the ignore lambda. The behavior of the
ignore lambda must match that described by `shutil.copytree`. ignore lambda must match that described by `shutil.copytree`.
...@@ -75,4 +76,7 @@ def copytree(src_dir, dest_dir, ignore=None): ...@@ -75,4 +76,7 @@ def copytree(src_dir, dest_dir, ignore=None):
uses watchman to mirror src_dir into dest_dir. uses watchman to mirror src_dir into dest_dir.
""" """
prefetch_dir_if_eden(src_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) return shutil.copytree(src_dir, dest_dir, ignore=ignore)
...@@ -20,13 +20,13 @@ from .envfuncs import path_search ...@@ -20,13 +20,13 @@ from .envfuncs import path_search
OBJECT_SUBDIRS = ("bin", "lib", "lib64") OBJECT_SUBDIRS = ("bin", "lib", "lib64")
def copyfile(src, dest): def copyfile(src, dest) -> None:
shutil.copyfile(src, dest) shutil.copyfile(src, dest)
shutil.copymode(src, dest) shutil.copymode(src, dest)
class DepBase(object): class DepBase(object):
def __init__(self, buildopts, install_dirs, strip): def __init__(self, buildopts, install_dirs, strip) -> None:
self.buildopts = buildopts self.buildopts = buildopts
self.env = buildopts.compute_env_for_install_dirs(install_dirs) self.env = buildopts.compute_env_for_install_dirs(install_dirs)
self.install_dirs = install_dirs self.install_dirs = install_dirs
...@@ -36,7 +36,7 @@ class DepBase(object): ...@@ -36,7 +36,7 @@ class DepBase(object):
def list_dynamic_deps(self, objfile): def list_dynamic_deps(self, objfile):
raise RuntimeError("list_dynamic_deps not implemented") raise RuntimeError("list_dynamic_deps not implemented")
def interesting_dep(self, d): def interesting_dep(self, d) -> bool:
return True return True
# final_install_prefix must be the equivalent path to `destdir` on the # final_install_prefix must be the equivalent path to `destdir` on the
...@@ -44,11 +44,12 @@ class DepBase(object): ...@@ -44,11 +44,12 @@ class DepBase(object):
# is intended to map to `/usr/local` in the install image, then # is intended to map to `/usr/local` in the install image, then
# final_install_prefix='/usr/local'. # final_install_prefix='/usr/local'.
# If left unspecified, destdir will be used. # 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(): if self.buildopts.is_windows():
lib_dir = "bin" lib_dir = "bin"
else: else:
lib_dir = "lib" lib_dir = "lib"
# pyre-fixme[16]: `DepBase` has no attribute `munged_lib_dir`.
self.munged_lib_dir = os.path.join(destdir, 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) final_lib_dir = os.path.join(final_install_prefix or destdir, lib_dir)
...@@ -92,7 +93,7 @@ class DepBase(object): ...@@ -92,7 +93,7 @@ class DepBase(object):
return dep_paths 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) print("Munging %s" % objfile)
for d in self.list_dynamic_deps(objfile): for d in self.list_dynamic_deps(objfile):
if not self.interesting_dep(d): if not self.interesting_dep(d):
...@@ -103,6 +104,7 @@ class DepBase(object): ...@@ -103,6 +104,7 @@ class DepBase(object):
dep = self.resolve_loader_path(d) dep = self.resolve_loader_path(d)
print("dep: %s -> %s" % (d, dep)) print("dep: %s -> %s" % (d, dep))
if 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)) dest_dep = os.path.join(self.munged_lib_dir, os.path.basename(dep))
if dep not in self.processed_deps: if dep not in self.processed_deps:
self.processed_deps.add(dep) self.processed_deps.add(dep)
...@@ -128,7 +130,7 @@ class DepBase(object): ...@@ -128,7 +130,7 @@ class DepBase(object):
return candidate return candidate
return None 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): for entry in os.listdir(dir):
entry_path = os.path.join(dir, entry) entry_path = os.path.join(dir, entry)
st = os.lstat(entry_path) st = os.lstat(entry_path)
...@@ -143,21 +145,21 @@ class DepBase(object): ...@@ -143,21 +145,21 @@ class DepBase(object):
): ):
yield result yield result
def is_objfile(self, objfile): def is_objfile(self, objfile) -> bool:
return True return True
def strip_debug_info(self, objfile): def strip_debug_info(self, objfile) -> None:
"""override this to define how to remove debug information """override this to define how to remove debug information
from an object file""" from an object file"""
pass pass
class WinDeps(DepBase): 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) super(WinDeps, self).__init__(buildopts, install_dirs, strip)
self.dumpbin = self.find_dumpbin() self.dumpbin = self.find_dumpbin()
def find_dumpbin(self): def find_dumpbin(self) -> str:
# Looking for dumpbin in the following hardcoded paths. # Looking for dumpbin in the following hardcoded paths.
# The registry option to find the install dir doesn't work anymore. # The registry option to find the install dir doesn't work anymore.
globs = [ globs = [
...@@ -196,7 +198,7 @@ class WinDeps(DepBase): ...@@ -196,7 +198,7 @@ class WinDeps(DepBase):
return deps 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 # We can't rewrite on windows, but we will
# place the deps alongside the exe so that # place the deps alongside the exe so that
# they end up in the search path # they end up in the search path
...@@ -217,21 +219,21 @@ class WinDeps(DepBase): ...@@ -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: if "api-ms-win-crt" in d:
return False return False
if d in self.SYSTEM_DLLS: if d in self.SYSTEM_DLLS:
return False return False
return True return True
def is_objfile(self, objfile): def is_objfile(self, objfile) -> bool:
if not os.path.isfile(objfile): if not os.path.isfile(objfile):
return False return False
if objfile.lower().endswith(".exe"): if objfile.lower().endswith(".exe"):
return True return True
return False 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 """Emit a script that can be used to run build artifacts directly from the
build directory, without installing them. build directory, without installing them.
...@@ -297,7 +299,7 @@ class WinDeps(DepBase): ...@@ -297,7 +299,7 @@ class WinDeps(DepBase):
return dep_dirs 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_entries = ["$env:PATH"] + path_dirs
path_str = ";".join(path_entries) path_str = ";".join(path_entries)
return """\ return """\
...@@ -316,7 +318,7 @@ try {{ ...@@ -316,7 +318,7 @@ try {{
class ElfDeps(DepBase): 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) super(ElfDeps, self).__init__(buildopts, install_dirs, strip)
# We need patchelf to rewrite deps, so ensure that it is built... # We need patchelf to rewrite deps, so ensure that it is built...
...@@ -342,15 +344,17 @@ class ElfDeps(DepBase): ...@@ -342,15 +344,17 @@ class ElfDeps(DepBase):
lines = out.split("\n") lines = out.split("\n")
return lines 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_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( subprocess.check_call(
[self.patchelf, "--replace-needed", depname, final_dep, objfile] [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): if not os.path.isfile(objfile):
return False return False
with open(objfile, "rb") as f: with open(objfile, "rb") as f:
...@@ -358,7 +362,7 @@ class ElfDeps(DepBase): ...@@ -358,7 +362,7 @@ class ElfDeps(DepBase):
magic = f.read(4) magic = f.read(4)
return magic == b"\x7fELF" return magic == b"\x7fELF"
def strip_debug_info(self, objfile): def strip_debug_info(self, objfile) -> None:
subprocess.check_call(["strip", objfile]) subprocess.check_call(["strip", objfile])
...@@ -367,7 +371,7 @@ MACH_MAGIC = 0xFEEDFACF ...@@ -367,7 +371,7 @@ MACH_MAGIC = 0xFEEDFACF
class MachDeps(DepBase): class MachDeps(DepBase):
def interesting_dep(self, d): def interesting_dep(self, d) -> bool:
if d.startswith("/usr/lib/") or d.startswith("/System/"): if d.startswith("/usr/lib/") or d.startswith("/System/"):
return False return False
return True return True
...@@ -403,7 +407,7 @@ class MachDeps(DepBase): ...@@ -403,7 +407,7 @@ class MachDeps(DepBase):
deps.append(os.path.normcase(m.group(1))) deps.append(os.path.normcase(m.group(1)))
return deps 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"): if objfile.endswith(".dylib"):
# Erase the original location from the id of the shared # Erase the original location from the id of the shared
# object. It doesn't appear to hurt to retain it, but # object. It doesn't appear to hurt to retain it, but
...@@ -412,7 +416,9 @@ class MachDeps(DepBase): ...@@ -412,7 +416,9 @@ class MachDeps(DepBase):
["install_name_tool", "-id", os.path.basename(objfile), objfile] ["install_name_tool", "-id", os.path.basename(objfile), objfile]
) )
final_dep = os.path.join( 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( subprocess.check_call(
...@@ -420,7 +426,9 @@ class MachDeps(DepBase): ...@@ -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(): if buildopts.is_linux():
return ElfDeps(buildopts, install_dirs, strip) return ElfDeps(buildopts, install_dirs, strip)
if buildopts.is_darwin(): if buildopts.is_darwin():
......
...@@ -9,18 +9,18 @@ import sys ...@@ -9,18 +9,18 @@ import sys
class Env(object): class Env(object):
def __init__(self, src=None): def __init__(self, src=None) -> None:
self._dict = {} self._dict = {}
if src is None: if src is None:
self.update(os.environ) self.update(os.environ)
else: else:
self.update(src) self.update(src)
def update(self, src): def update(self, src) -> None:
for k, v in src.items(): for k, v in src.items():
self.set(k, v) self.set(k, v)
def copy(self): def copy(self) -> "Env":
return Env(self._dict) return Env(self._dict)
def _key(self, key): def _key(self, key):
...@@ -64,7 +64,7 @@ class Env(object): ...@@ -64,7 +64,7 @@ class Env(object):
raise KeyError(key) raise KeyError(key)
return val return val
def unset(self, key): def unset(self, key) -> None:
if key is None: if key is None:
raise KeyError("attempting to unset env[None]") raise KeyError("attempting to unset env[None]")
...@@ -72,13 +72,13 @@ class Env(object): ...@@ -72,13 +72,13 @@ class Env(object):
if key: if key:
del self._dict[key] del self._dict[key]
def __delitem__(self, key): def __delitem__(self, key) -> None:
self.unset(key) self.unset(key)
def __repr__(self): def __repr__(self):
return repr(self._dict) return repr(self._dict)
def set(self, key, value): def set(self, key, value) -> None:
if key is None: if key is None:
raise KeyError("attempting to assign env[None] = %r" % value) raise KeyError("attempting to assign env[None] = %r" % value)
...@@ -99,13 +99,13 @@ class Env(object): ...@@ -99,13 +99,13 @@ class Env(object):
self.unset(key) self.unset(key)
self._dict[key] = value self._dict[key] = value
def __setitem__(self, key, value): def __setitem__(self, key, value) -> None:
self.set(key, value) self.set(key, value)
def __iter__(self): def __iter__(self):
return self._dict.__iter__() return self._dict.__iter__()
def __len__(self): def __len__(self) -> int:
return len(self._dict) return len(self._dict)
def keys(self): def keys(self):
...@@ -118,7 +118,9 @@ class Env(object): ...@@ -118,7 +118,9 @@ class Env(object):
return self._dict.items() 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 """Cause `item` to be added to the path style env var named
`name` held in the `env` dict. `append` specifies whether `name` held in the `env` dict. `append` specifies whether
the item is added to the end (the default) or should be 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): ...@@ -135,7 +137,7 @@ def add_path_entry(env, name, item, append=True, separator=os.pathsep):
env.set(name, separator.join(val)) 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 """Cause `flag` to be added to the CXXFLAGS-style env var named
`name` held in the `env` dict. `append` specifies whether the `name` held in the `env` dict. `append` specifies whether the
flag is added to the end (the default) or should be prepended if flag is added to the end (the default) or should be prepended if
...@@ -152,7 +154,7 @@ _path_search_cache = {} ...@@ -152,7 +154,7 @@ _path_search_cache = {}
_not_found = object() _not_found = object()
def tpx_path(): def tpx_path() -> str:
return "xplat/testinfra/tpx/ctp.tpx" return "xplat/testinfra/tpx/ctp.tpx"
......
...@@ -13,5 +13,5 @@ class TransientFailure(Exception): ...@@ -13,5 +13,5 @@ class TransientFailure(Exception):
class ManifestNotFound(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) super(Exception, self).__init__("Unable to find manifest '%s'" % manifest_name)
...@@ -37,40 +37,40 @@ def parse_expr(expr_text, valid_variables): ...@@ -37,40 +37,40 @@ def parse_expr(expr_text, valid_variables):
class ExprNode(object): class ExprNode(object):
def eval(self, ctx): def eval(self, ctx) -> bool:
return False return False
class TrueExpr(ExprNode): class TrueExpr(ExprNode):
def eval(self, ctx): def eval(self, ctx) -> bool:
return True return True
def __str__(self): def __str__(self) -> str:
return "true" return "true"
class NotExpr(ExprNode): class NotExpr(ExprNode):
def __init__(self, node): def __init__(self, node) -> None:
self._node = node self._node = node
def eval(self, ctx): def eval(self, ctx) -> bool:
return not self._node.eval(ctx) return not self._node.eval(ctx)
def __str__(self): def __str__(self) -> str:
return "not(%s)" % self._node return "not(%s)" % self._node
class AllExpr(ExprNode): class AllExpr(ExprNode):
def __init__(self, nodes): def __init__(self, nodes) -> None:
self._nodes = nodes self._nodes = nodes
def eval(self, ctx): def eval(self, ctx) -> bool:
for node in self._nodes: for node in self._nodes:
if not node.eval(ctx): if not node.eval(ctx):
return False return False
return True return True
def __str__(self): def __str__(self) -> str:
items = [] items = []
for node in self._nodes: for node in self._nodes:
items.append(str(node)) items.append(str(node))
...@@ -78,16 +78,16 @@ class AllExpr(ExprNode): ...@@ -78,16 +78,16 @@ class AllExpr(ExprNode):
class AnyExpr(ExprNode): class AnyExpr(ExprNode):
def __init__(self, nodes): def __init__(self, nodes) -> None:
self._nodes = nodes self._nodes = nodes
def eval(self, ctx): def eval(self, ctx) -> bool:
for node in self._nodes: for node in self._nodes:
if node.eval(ctx): if node.eval(ctx):
return True return True
return False return False
def __str__(self): def __str__(self) -> str:
items = [] items = []
for node in self._nodes: for node in self._nodes:
items.append(str(node)) items.append(str(node))
...@@ -95,19 +95,19 @@ class AnyExpr(ExprNode): ...@@ -95,19 +95,19 @@ class AnyExpr(ExprNode):
class EqualExpr(ExprNode): class EqualExpr(ExprNode):
def __init__(self, key, value): def __init__(self, key, value) -> None:
self._key = key self._key = key
self._value = value self._value = value
def eval(self, ctx): def eval(self, ctx):
return ctx.get(self._key) == self._value return ctx.get(self._key) == self._value
def __str__(self): def __str__(self) -> str:
return "%s=%s" % (self._key, self._value) return "%s=%s" % (self._key, self._value)
class Parser(object): class Parser(object):
def __init__(self, text, valid_variables): def __init__(self, text, valid_variables) -> None:
self.text = text self.text = text
self.lex = shlex.shlex(text) self.lex = shlex.shlex(text)
self.valid_variables = valid_variables self.valid_variables = valid_variables
...@@ -147,13 +147,13 @@ class Parser(object): ...@@ -147,13 +147,13 @@ class Parser(object):
"Unexpected token sequence '%s %s' in %s" % (name, op, self.text) "Unexpected token sequence '%s %s' in %s" % (name, op, self.text)
) )
def ident(self): def ident(self) -> str:
ident = self.lex.get_token() ident = self.lex.get_token()
if not re.match("[a-zA-Z]+", ident): if not re.match("[a-zA-Z]+", ident):
raise Exception("expected identifier found %s" % ident) raise Exception("expected identifier found %s" % ident)
return ident return ident
def parse_not(self): def parse_not(self) -> NotExpr:
node = self.top() node = self.top()
expr = NotExpr(node) expr = NotExpr(node)
tok = self.lex.get_token() tok = self.lex.get_token()
...@@ -161,7 +161,7 @@ class Parser(object): ...@@ -161,7 +161,7 @@ class Parser(object):
raise Exception("expected ')' found %s" % tok) raise Exception("expected ')' found %s" % tok)
return expr return expr
def parse_any(self): def parse_any(self) -> AnyExpr:
nodes = [] nodes = []
while True: while True:
nodes.append(self.top()) nodes.append(self.top())
...@@ -172,7 +172,7 @@ class Parser(object): ...@@ -172,7 +172,7 @@ class Parser(object):
raise Exception("expected ',' or ')' but found %s" % tok) raise Exception("expected ',' or ')' but found %s" % tok)
return AnyExpr(nodes) return AnyExpr(nodes)
def parse_all(self): def parse_all(self) -> AllExpr:
nodes = [] nodes = []
while True: while True:
nodes.append(self.top()) nodes.append(self.top())
......
...@@ -50,7 +50,7 @@ class ChangeStatus(object): ...@@ -50,7 +50,7 @@ class ChangeStatus(object):
and whether we might need to reconfigure the build system. and whether we might need to reconfigure the build system.
""" """
def __init__(self, all_changed=False): def __init__(self, all_changed: bool = False) -> None:
"""Construct a ChangeStatus object. The default is to create """Construct a ChangeStatus object. The default is to create
a status that indicates no changes, but passing all_changed=True a status that indicates no changes, but passing all_changed=True
will create one that indicates that everything changed""" will create one that indicates that everything changed"""
...@@ -61,7 +61,7 @@ class ChangeStatus(object): ...@@ -61,7 +61,7 @@ class ChangeStatus(object):
self.source_files = 0 self.source_files = 0
self.make_files = 0 self.make_files = 0
def record_change(self, file_name): def record_change(self, file_name) -> None:
"""Used by the shipit fetcher to record changes as it updates """Used by the shipit fetcher to record changes as it updates
files in the destination. If the file name might be one used files in the destination. If the file name might be one used
in the cmake build system that we use for 1st party code, then in the cmake build system that we use for 1st party code, then
...@@ -81,14 +81,14 @@ class ChangeStatus(object): ...@@ -81,14 +81,14 @@ class ChangeStatus(object):
elif "/fbcode_builder/" not in file_name: elif "/fbcode_builder/" not in file_name:
self.source_files += 1 self.source_files += 1
def sources_changed(self): def sources_changed(self) -> bool:
"""Returns true if any source files were changed during """Returns true if any source files were changed during
an update operation. This will typically be used to decide an update operation. This will typically be used to decide
that the build system to be run on the source dir in an that the build system to be run on the source dir in an
incremental mode""" incremental mode"""
return self.source_files > 0 return self.source_files > 0
def build_changed(self): def build_changed(self) -> bool:
"""Returns true if any build files were changed during """Returns true if any build files were changed during
an update operation. This will typically be used to decidfe an update operation. This will typically be used to decidfe
that the build system should be reconfigured and re-run that the build system should be reconfigured and re-run
...@@ -102,7 +102,7 @@ class Fetcher(object): ...@@ -102,7 +102,7 @@ class Fetcher(object):
extracted data resides and reports this to the consumer via extracted data resides and reports this to the consumer via
its `get_src_dir` method.""" its `get_src_dir` method."""
def update(self): def update(self) -> ChangeStatus:
"""Brings the src dir up to date, ideally minimizing """Brings the src dir up to date, ideally minimizing
changes so that a subsequent build doesn't over-build. changes so that a subsequent build doesn't over-build.
Returns a ChangeStatus object that helps the caller to Returns a ChangeStatus object that helps the caller to
...@@ -110,12 +110,12 @@ class Fetcher(object): ...@@ -110,12 +110,12 @@ class Fetcher(object):
the update.""" the update."""
return ChangeStatus() return ChangeStatus()
def clean(self): def clean(self) -> None:
"""Reverts any changes that might have been made to """Reverts any changes that might have been made to
the src dir""" the src dir"""
pass pass
def hash(self): def hash(self) -> None:
"""Returns a hash that identifies the version of the code in the """Returns a hash that identifies the version of the code in the
working copy. For a git repo this is commit hash for the working working copy. For a git repo this is commit hash for the working
copy. For other Fetchers this should relate to the version of copy. For other Fetchers this should relate to the version of
...@@ -128,7 +128,7 @@ class Fetcher(object): ...@@ -128,7 +128,7 @@ class Fetcher(object):
""" """
pass pass
def get_src_dir(self): def get_src_dir(self) -> None:
"""Returns the source directory that the project was """Returns the source directory that the project was
extracted into""" extracted into"""
pass pass
...@@ -141,13 +141,13 @@ class LocalDirFetcher(object): ...@@ -141,13 +141,13 @@ class LocalDirFetcher(object):
This fetcher cannot update or track changes. It always reports that the This fetcher cannot update or track changes. It always reports that the
project has changed, forcing it to always be built.""" project has changed, forcing it to always be built."""
def __init__(self, path): def __init__(self, path) -> None:
self.path = os.path.realpath(path) self.path = os.path.realpath(path)
def update(self): def update(self) -> ChangeStatus:
return ChangeStatus(all_changed=True) return ChangeStatus(all_changed=True)
def hash(self): def hash(self) -> str:
return "0" * 40 return "0" * 40
def get_src_dir(self): def get_src_dir(self):
...@@ -155,7 +155,7 @@ class LocalDirFetcher(object): ...@@ -155,7 +155,7 @@ class LocalDirFetcher(object):
class SystemPackageFetcher(object): class SystemPackageFetcher(object):
def __init__(self, build_options, packages): def __init__(self, build_options, packages) -> None:
self.manager = build_options.host_type.get_package_manager() self.manager = build_options.host_type.get_package_manager()
self.packages = packages.get(self.manager) self.packages = packages.get(self.manager)
self.host_type = build_options.host_type self.host_type = build_options.host_type
...@@ -190,29 +190,29 @@ class SystemPackageFetcher(object): ...@@ -190,29 +190,29 @@ class SystemPackageFetcher(object):
return bool(self.installed) return bool(self.installed)
def update(self): def update(self) -> ChangeStatus:
assert self.installed assert self.installed
return ChangeStatus(all_changed=False) return ChangeStatus(all_changed=False)
def hash(self): def hash(self) -> str:
if self.packages_are_installed(): if self.packages_are_installed():
return hashlib.sha256(self.installed).hexdigest() return hashlib.sha256(self.installed).hexdigest()
else: else:
return "0" * 40 return "0" * 40
def get_src_dir(self): def get_src_dir(self) -> None:
return None return None
class PreinstalledNopFetcher(SystemPackageFetcher): class PreinstalledNopFetcher(SystemPackageFetcher):
def __init__(self): def __init__(self) -> None:
self.installed = True self.installed = True
class GitFetcher(Fetcher): class GitFetcher(Fetcher):
DEFAULT_DEPTH = 1 DEFAULT_DEPTH = 1
def __init__(self, build_options, manifest, repo_url, rev, depth): def __init__(self, build_options, manifest, repo_url, rev, depth) -> None:
# Extract the host/path portions of the URL and generate a flattened # Extract the host/path portions of the URL and generate a flattened
# directory name. eg: # directory name. eg:
# github.com/facebook/folly.git -> github.com-facebook-folly.git # github.com/facebook/folly.git -> github.com-facebook-folly.git
...@@ -246,7 +246,7 @@ class GitFetcher(Fetcher): ...@@ -246,7 +246,7 @@ class GitFetcher(Fetcher):
self.manifest = manifest self.manifest = manifest
self.depth = depth if depth else GitFetcher.DEFAULT_DEPTH self.depth = depth if depth else GitFetcher.DEFAULT_DEPTH
def _update(self): def _update(self) -> ChangeStatus:
current_hash = ( current_hash = (
subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=self.repo_dir) subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=self.repo_dir)
.strip() .strip()
...@@ -281,7 +281,7 @@ class GitFetcher(Fetcher): ...@@ -281,7 +281,7 @@ class GitFetcher(Fetcher):
self._clone() self._clone()
return ChangeStatus(True) return ChangeStatus(True)
def _clone(self): def _clone(self) -> None:
print("Cloning %s..." % self.origin_repo) print("Cloning %s..." % self.origin_repo)
# The basename/dirname stuff allows us to dance around issues where # The basename/dirname stuff allows us to dance around issues where
# eg: this python process is native win32, but the git.exe is cygwin # eg: this python process is native win32, but the git.exe is cygwin
...@@ -300,7 +300,7 @@ class GitFetcher(Fetcher): ...@@ -300,7 +300,7 @@ class GitFetcher(Fetcher):
) )
self._update() self._update()
def clean(self): def clean(self) -> None:
if os.path.exists(self.repo_dir): if os.path.exists(self.repo_dir):
run_cmd(["git", "clean", "-fxd"], cwd=self.repo_dir) run_cmd(["git", "clean", "-fxd"], cwd=self.repo_dir)
...@@ -343,7 +343,7 @@ def does_file_need_update(src_name, src_st, dest_name): ...@@ -343,7 +343,7 @@ def does_file_need_update(src_name, src_st, dest_name):
return False return False
def copy_if_different(src_name, dest_name): def copy_if_different(src_name, dest_name) -> bool:
"""Copy src_name -> dest_name, but only touch dest_name """Copy src_name -> dest_name, but only touch dest_name
if src_name is different from dest_name, making this a if src_name is different from dest_name, making this a
more build system friendly way to copy.""" more build system friendly way to copy."""
...@@ -380,22 +380,22 @@ def list_files_under_dir_newer_than_timestamp(dir_to_scan, ts): ...@@ -380,22 +380,22 @@ def list_files_under_dir_newer_than_timestamp(dir_to_scan, ts):
class ShipitPathMap(object): class ShipitPathMap(object):
def __init__(self): def __init__(self) -> None:
self.roots = [] self.roots = []
self.mapping = [] self.mapping = []
self.exclusion = [] self.exclusion = []
def add_mapping(self, fbsource_dir, target_dir): def add_mapping(self, fbsource_dir, target_dir) -> None:
"""Add a posix path or pattern. We cannot normpath the input """Add a posix path or pattern. We cannot normpath the input
here because that would change the paths from posix to windows here because that would change the paths from posix to windows
form and break the logic throughout this class.""" form and break the logic throughout this class."""
self.roots.append(fbsource_dir) self.roots.append(fbsource_dir)
self.mapping.append((fbsource_dir, target_dir)) self.mapping.append((fbsource_dir, target_dir))
def add_exclusion(self, pattern): def add_exclusion(self, pattern) -> None:
self.exclusion.append(re.compile(pattern)) self.exclusion.append(re.compile(pattern))
def _minimize_roots(self): def _minimize_roots(self) -> None:
"""compute the de-duplicated set of roots within fbsource. """compute the de-duplicated set of roots within fbsource.
We take the shortest common directory prefix to make this We take the shortest common directory prefix to make this
determination""" determination"""
...@@ -413,7 +413,7 @@ class ShipitPathMap(object): ...@@ -413,7 +413,7 @@ class ShipitPathMap(object):
self.roots = minimized self.roots = minimized
def _sort_mapping(self): def _sort_mapping(self) -> None:
self.mapping.sort(reverse=True, key=lambda x: len(x[0])) self.mapping.sort(reverse=True, key=lambda x: len(x[0]))
def _map_name(self, norm_name, dest_root): def _map_name(self, norm_name, dest_root):
...@@ -442,7 +442,7 @@ class ShipitPathMap(object): ...@@ -442,7 +442,7 @@ class ShipitPathMap(object):
raise Exception("%s did not match any rules" % norm_name) raise Exception("%s did not match any rules" % norm_name)
def mirror(self, fbsource_root, dest_root): def mirror(self, fbsource_root, dest_root) -> ChangeStatus:
self._minimize_roots() self._minimize_roots()
self._sort_mapping() self._sort_mapping()
...@@ -516,7 +516,7 @@ class FbsourceRepoData(NamedTuple): ...@@ -516,7 +516,7 @@ class FbsourceRepoData(NamedTuple):
FBSOURCE_REPO_DATA: Dict[str, FbsourceRepoData] = {} FBSOURCE_REPO_DATA: Dict[str, FbsourceRepoData] = {}
def get_fbsource_repo_data(build_options): def get_fbsource_repo_data(build_options) -> FbsourceRepoData:
"""Returns the commit metadata for the fbsource repo. """Returns the commit metadata for the fbsource repo.
Since we may have multiple first party projects to Since we may have multiple first party projects to
hash, and because we don't mutate the repo, we cache hash, and because we don't mutate the repo, we cache
...@@ -546,13 +546,13 @@ def get_fbsource_repo_data(build_options): ...@@ -546,13 +546,13 @@ def get_fbsource_repo_data(build_options):
class SimpleShipitTransformerFetcher(Fetcher): class SimpleShipitTransformerFetcher(Fetcher):
def __init__(self, build_options, manifest, ctx): def __init__(self, build_options, manifest, ctx) -> None:
self.build_options = build_options self.build_options = build_options
self.manifest = manifest self.manifest = manifest
self.repo_dir = os.path.join(build_options.scratch_dir, "shipit", manifest.name) self.repo_dir = os.path.join(build_options.scratch_dir, "shipit", manifest.name)
self.ctx = ctx self.ctx = ctx
def clean(self): def clean(self) -> None:
if os.path.exists(self.repo_dir): if os.path.exists(self.repo_dir):
shutil.rmtree(self.repo_dir) shutil.rmtree(self.repo_dir)
...@@ -571,7 +571,8 @@ class SimpleShipitTransformerFetcher(Fetcher): ...@@ -571,7 +571,8 @@ class SimpleShipitTransformerFetcher(Fetcher):
return mapping.mirror(self.build_options.fbsource_dir, self.repo_dir) return mapping.mirror(self.build_options.fbsource_dir, self.repo_dir)
def hash(self): # pyre-fixme[15]: `hash` overrides method defined in `Fetcher` inconsistently.
def hash(self) -> str:
# We return a fixed non-hash string for in-fbsource builds. # We return a fixed non-hash string for in-fbsource builds.
# We're relying on the `update` logic to correctly invalidate # We're relying on the `update` logic to correctly invalidate
# the build in the case that files have changed. # the build in the case that files have changed.
...@@ -584,18 +585,18 @@ class SimpleShipitTransformerFetcher(Fetcher): ...@@ -584,18 +585,18 @@ class SimpleShipitTransformerFetcher(Fetcher):
class ShipitTransformerFetcher(Fetcher): class ShipitTransformerFetcher(Fetcher):
SHIPIT = "/var/www/scripts/opensource/shipit/run_shipit.php" SHIPIT = "/var/www/scripts/opensource/shipit/run_shipit.php"
def __init__(self, build_options, project_name): def __init__(self, build_options, project_name) -> None:
self.build_options = build_options self.build_options = build_options
self.project_name = project_name self.project_name = project_name
self.repo_dir = os.path.join(build_options.scratch_dir, "shipit", project_name) self.repo_dir = os.path.join(build_options.scratch_dir, "shipit", project_name)
def update(self): def update(self) -> ChangeStatus:
if os.path.exists(self.repo_dir): if os.path.exists(self.repo_dir):
return ChangeStatus() return ChangeStatus()
self.run_shipit() self.run_shipit()
return ChangeStatus(True) return ChangeStatus(True)
def clean(self): def clean(self) -> None:
if os.path.exists(self.repo_dir): if os.path.exists(self.repo_dir):
shutil.rmtree(self.repo_dir) shutil.rmtree(self.repo_dir)
...@@ -603,7 +604,7 @@ class ShipitTransformerFetcher(Fetcher): ...@@ -603,7 +604,7 @@ class ShipitTransformerFetcher(Fetcher):
def available(cls): def available(cls):
return os.path.exists(cls.SHIPIT) return os.path.exists(cls.SHIPIT)
def run_shipit(self): def run_shipit(self) -> None:
tmp_path = self.repo_dir + ".new" tmp_path = self.repo_dir + ".new"
try: try:
if os.path.exists(tmp_path): if os.path.exists(tmp_path):
...@@ -640,7 +641,8 @@ class ShipitTransformerFetcher(Fetcher): ...@@ -640,7 +641,8 @@ class ShipitTransformerFetcher(Fetcher):
self.clean() self.clean()
raise raise
def hash(self): # pyre-fixme[15]: `hash` overrides method defined in `Fetcher` inconsistently.
def hash(self) -> str:
# We return a fixed non-hash string for in-fbsource builds. # We return a fixed non-hash string for in-fbsource builds.
return "fbsource" return "fbsource"
...@@ -648,7 +650,7 @@ class ShipitTransformerFetcher(Fetcher): ...@@ -648,7 +650,7 @@ class ShipitTransformerFetcher(Fetcher):
return self.repo_dir return self.repo_dir
def download_url_to_file_with_progress(url, file_name): def download_url_to_file_with_progress(url: str, file_name) -> None:
print("Download %s -> %s ..." % (url, file_name)) print("Download %s -> %s ..." % (url, file_name))
class Progress(object): class Progress(object):
...@@ -686,7 +688,7 @@ def download_url_to_file_with_progress(url, file_name): ...@@ -686,7 +688,7 @@ def download_url_to_file_with_progress(url, file_name):
class ArchiveFetcher(Fetcher): class ArchiveFetcher(Fetcher):
def __init__(self, build_options, manifest, url, sha256): def __init__(self, build_options, manifest, url, sha256) -> None:
self.manifest = manifest self.manifest = manifest
self.url = url self.url = url
self.sha256 = sha256 self.sha256 = sha256
...@@ -698,7 +700,7 @@ class ArchiveFetcher(Fetcher): ...@@ -698,7 +700,7 @@ class ArchiveFetcher(Fetcher):
self.src_dir = os.path.join(build_options.scratch_dir, "extracted", basename) self.src_dir = os.path.join(build_options.scratch_dir, "extracted", basename)
self.hash_file = self.src_dir + ".hash" self.hash_file = self.src_dir + ".hash"
def _verify_hash(self): def _verify_hash(self) -> None:
h = hashlib.sha256() h = hashlib.sha256()
with open(self.file_name, "rb") as f: with open(self.file_name, "rb") as f:
while True: while True:
...@@ -720,16 +722,16 @@ class ArchiveFetcher(Fetcher): ...@@ -720,16 +722,16 @@ class ArchiveFetcher(Fetcher):
os.makedirs(download_dir) os.makedirs(download_dir)
return download_dir return download_dir
def _download(self): def _download(self) -> None:
self._download_dir() self._download_dir()
download_url_to_file_with_progress(self.url, self.file_name) download_url_to_file_with_progress(self.url, self.file_name)
self._verify_hash() self._verify_hash()
def clean(self): def clean(self) -> None:
if os.path.exists(self.src_dir): if os.path.exists(self.src_dir):
shutil.rmtree(self.src_dir) shutil.rmtree(self.src_dir)
def update(self): def update(self) -> ChangeStatus:
try: try:
with open(self.hash_file, "r") as f: with open(self.hash_file, "r") as f:
saved_hash = f.read().strip() saved_hash = f.read().strip()
......
...@@ -56,7 +56,7 @@ class Loader(object): ...@@ -56,7 +56,7 @@ class Loader(object):
class ResourceLoader(Loader): class ResourceLoader(Loader):
def __init__(self, namespace, manifests_dir): def __init__(self, namespace, manifests_dir) -> None:
self.namespace = namespace self.namespace = namespace
self.manifests_dir = manifests_dir self.manifests_dir = manifests_dir
...@@ -82,7 +82,7 @@ class ResourceLoader(Loader): ...@@ -82,7 +82,7 @@ class ResourceLoader(Loader):
raise ManifestNotFound(project_name) raise ManifestNotFound(project_name)
def _load_manifest(self, path): def _load_manifest(self, path: str):
import pkg_resources import pkg_resources
contents = pkg_resources.resource_string(self.namespace, path).decode("utf8") contents = pkg_resources.resource_string(self.namespace, path).decode("utf8")
...@@ -96,7 +96,7 @@ class ResourceLoader(Loader): ...@@ -96,7 +96,7 @@ class ResourceLoader(Loader):
LOADER = Loader() LOADER = Loader()
def patch_loader(namespace, manifests_dir="manifests"): def patch_loader(namespace, manifests_dir: str = "manifests") -> None:
global LOADER global LOADER
LOADER = ResourceLoader(namespace, manifests_dir) LOADER = ResourceLoader(namespace, manifests_dir)
...@@ -119,7 +119,7 @@ class ManifestLoader(object): ...@@ -119,7 +119,7 @@ class ManifestLoader(object):
relationships and project hash values for this build configuration. 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._loader = LOADER
self.build_opts = build_opts self.build_opts = build_opts
if ctx_gen is None: if ctx_gen is None:
...@@ -231,16 +231,16 @@ class ManifestLoader(object): ...@@ -231,16 +231,16 @@ class ManifestLoader(object):
return dep_order 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) 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 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 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 self._install_prefix_overrides[project_name] = path
def create_fetcher(self, manifest): def create_fetcher(self, manifest):
...@@ -258,7 +258,7 @@ class ManifestLoader(object): ...@@ -258,7 +258,7 @@ class ManifestLoader(object):
self._project_hashes[manifest.name] = h self._project_hashes[manifest.name] = h
return 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. """This recursive function computes a hash for a given manifest.
The hash takes into account some environmental factors on the The hash takes into account some environmental factors on the
host machine and includes the hashes of its dependencies. host machine and includes the hashes of its dependencies.
......
...@@ -9,7 +9,7 @@ import shlex ...@@ -9,7 +9,7 @@ import shlex
import sys import sys
def is_windows(): def is_windows() -> bool:
"""Returns true if the system we are currently running on """Returns true if the system we are currently running on
is a Windows system""" is a Windows system"""
return sys.platform.startswith("win") return sys.platform.startswith("win")
...@@ -52,7 +52,7 @@ def get_linux_type(): ...@@ -52,7 +52,7 @@ def get_linux_type():
# but getdeps can't take third-party dependencies. # 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 # TODO: Ideally, this function would inspect the current cgroup for any
# limits, rather than solely relying on system RAM. # limits, rather than solely relying on system RAM.
with open("/proc/meminfo") as f: with open("/proc/meminfo") as f:
...@@ -175,7 +175,7 @@ def get_available_ram() -> int: ...@@ -175,7 +175,7 @@ def get_available_ram() -> int:
class HostType(object): 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: if ostype is None:
distro = None distro = None
distrovers = None distrovers = None
...@@ -185,6 +185,7 @@ class HostType(object): ...@@ -185,6 +185,7 @@ class HostType(object):
ostype = "darwin" ostype = "darwin"
elif is_windows(): elif is_windows():
ostype = "windows" ostype = "windows"
# pyre-fixme[16]: Module `sys` has no attribute `getwindowsversion`.
distrovers = str(sys.getwindowsversion().major) distrovers = str(sys.getwindowsversion().major)
elif sys.platform.startswith("freebsd"): elif sys.platform.startswith("freebsd"):
ostype = "freebsd" ostype = "freebsd"
...@@ -218,7 +219,7 @@ class HostType(object): ...@@ -218,7 +219,7 @@ class HostType(object):
def is_freebsd(self): def is_freebsd(self):
return self.ostype == "freebsd" return self.ostype == "freebsd"
def as_tuple_string(self): def as_tuple_string(self) -> str:
return "%s-%s-%s" % ( return "%s-%s-%s" % (
self.ostype, self.ostype,
self.distro or "none", self.distro or "none",
...@@ -237,7 +238,7 @@ class HostType(object): ...@@ -237,7 +238,7 @@ class HostType(object):
return None return None
@staticmethod @staticmethod
def from_tuple_string(s): def from_tuple_string(s) -> "HostType":
ostype, distro, distrovers = s.split("-") ostype, distro, distrovers = s.split("-")
return HostType(ostype=ostype, distro=distro, distrovers=distrovers) return HostType(ostype=ostype, distro=distro, distrovers=distrovers)
......
...@@ -212,7 +212,7 @@ class PythonWheelBuilder(BuilderBase): ...@@ -212,7 +212,7 @@ class PythonWheelBuilder(BuilderBase):
f.write(CMAKE_FOOTER.format(**self.template_format_dict)) 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" config_path_name = self.manifest.name + "-config.cmake.in"
output_path = os.path.join(self.build_dir, config_path_name) output_path = os.path.join(self.build_dir, config_path_name)
......
...@@ -22,7 +22,7 @@ class RunCommandError(Exception): ...@@ -22,7 +22,7 @@ class RunCommandError(Exception):
pass pass
def _print_env_diff(env, log_fn): def _print_env_diff(env, log_fn) -> None:
current_keys = set(os.environ.keys()) current_keys = set(os.environ.keys())
wanted_env = set(env.keys()) wanted_env = set(env.keys())
...@@ -44,7 +44,7 @@ def _print_env_diff(env, log_fn): ...@@ -44,7 +44,7 @@ def _print_env_diff(env, log_fn):
log_fn("+ %s=%s \\\n" % (k, shellquote(env[k]))) 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): def log_to_stdout(msg):
sys.stdout.buffer.write(msg.encode(errors="surrogateescape")) 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): ...@@ -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") log_fn("---\n")
try: try:
cmd_str = " \\\n+ ".join(shellquote(arg) for arg in cmd) cmd_str = " \\\n+ ".join(shellquote(arg) for arg in cmd)
......
...@@ -8,11 +8,11 @@ class SubCmd(object): ...@@ -8,11 +8,11 @@ class SubCmd(object):
NAME = None NAME = None
HELP = None HELP = None
def run(self, args): def run(self, args) -> int:
"""perform the command""" """perform the command"""
return 0 return 0
def setup_parser(self, parser): def setup_parser(self, parser) -> None:
# Subclasses should override setup_parser() if they have any # Subclasses should override setup_parser() if they have any
# command line options or arguments. # command line options or arguments.
pass pass
...@@ -21,7 +21,7 @@ class SubCmd(object): ...@@ -21,7 +21,7 @@ class SubCmd(object):
CmdTable = [] 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""" """Register parsers for the defined commands with the provided parser"""
for cls in cmd_table: for cls in cmd_table:
command = cls() command = cls()
......
...@@ -10,37 +10,37 @@ from ..expr import parse_expr ...@@ -10,37 +10,37 @@ from ..expr import parse_expr
class ExprTest(unittest.TestCase): class ExprTest(unittest.TestCase):
def test_equal(self): def test_equal(self) -> None:
valid_variables = {"foo", "some_var", "another_var"} valid_variables = {"foo", "some_var", "another_var"}
e = parse_expr("foo=bar", valid_variables) e = parse_expr("foo=bar", valid_variables)
self.assertTrue(e.eval({"foo": "bar"})) self.assertTrue(e.eval({"foo": "bar"}))
self.assertFalse(e.eval({"foo": "not-bar"})) self.assertFalse(e.eval({"foo": "not-bar"}))
self.assertFalse(e.eval({"not-foo": "bar"})) self.assertFalse(e.eval({"not-foo": "bar"}))
def test_not_equal(self): def test_not_equal(self) -> None:
valid_variables = {"foo"} valid_variables = {"foo"}
e = parse_expr("not(foo=bar)", valid_variables) e = parse_expr("not(foo=bar)", valid_variables)
self.assertFalse(e.eval({"foo": "bar"})) self.assertFalse(e.eval({"foo": "bar"}))
self.assertTrue(e.eval({"foo": "not-bar"})) self.assertTrue(e.eval({"foo": "not-bar"}))
def test_bad_not(self): def test_bad_not(self) -> None:
valid_variables = {"foo"} valid_variables = {"foo"}
with self.assertRaises(Exception): with self.assertRaises(Exception):
parse_expr("foo=not(bar)", valid_variables) parse_expr("foo=not(bar)", valid_variables)
def test_bad_variable(self): def test_bad_variable(self) -> None:
valid_variables = {"bar"} valid_variables = {"bar"}
with self.assertRaises(Exception): with self.assertRaises(Exception):
parse_expr("foo=bar", valid_variables) parse_expr("foo=bar", valid_variables)
def test_all(self): def test_all(self) -> None:
valid_variables = {"foo", "baz"} valid_variables = {"foo", "baz"}
e = parse_expr("all(foo = bar, baz = qux)", valid_variables) e = parse_expr("all(foo = bar, baz = qux)", valid_variables)
self.assertTrue(e.eval({"foo": "bar", "baz": "qux"})) self.assertTrue(e.eval({"foo": "bar", "baz": "qux"}))
self.assertFalse(e.eval({"foo": "bar", "baz": "nope"})) self.assertFalse(e.eval({"foo": "bar", "baz": "nope"}))
self.assertFalse(e.eval({"foo": "nope", "baz": "nope"})) self.assertFalse(e.eval({"foo": "nope", "baz": "nope"}))
def test_any(self): def test_any(self) -> None:
valid_variables = {"foo", "baz"} valid_variables = {"foo", "baz"}
e = parse_expr("any(foo = bar, baz = qux)", valid_variables) e = parse_expr("any(foo = bar, baz = qux)", valid_variables)
self.assertTrue(e.eval({"foo": "bar", "baz": "qux"})) self.assertTrue(e.eval({"foo": "bar", "baz": "qux"}))
......
...@@ -12,13 +12,13 @@ from ..manifest import ManifestParser ...@@ -12,13 +12,13 @@ from ..manifest import ManifestParser
class ManifestTest(unittest.TestCase): class ManifestTest(unittest.TestCase):
def test_missing_section(self): def test_missing_section(self) -> None:
with self.assertRaisesRegex( with self.assertRaisesRegex(
Exception, "manifest file test is missing required section manifest" Exception, "manifest file test is missing required section manifest"
): ):
ManifestParser("test", "") ManifestParser("test", "")
def test_missing_name(self): def test_missing_name(self) -> None:
with self.assertRaisesRegex( with self.assertRaisesRegex(
Exception, Exception,
"manifest file test section 'manifest' is missing required field 'name'", "manifest file test section 'manifest' is missing required field 'name'",
...@@ -30,7 +30,7 @@ class ManifestTest(unittest.TestCase): ...@@ -30,7 +30,7 @@ class ManifestTest(unittest.TestCase):
""", """,
) )
def test_minimal(self): def test_minimal(self) -> None:
p = ManifestParser( p = ManifestParser(
"test", "test",
""" """
...@@ -41,7 +41,7 @@ name = test ...@@ -41,7 +41,7 @@ name = test
self.assertEqual(p.name, "test") self.assertEqual(p.name, "test")
self.assertEqual(p.fbsource_path, None) self.assertEqual(p.fbsource_path, None)
def test_minimal_with_fbsource_path(self): def test_minimal_with_fbsource_path(self) -> None:
p = ManifestParser( p = ManifestParser(
"test", "test",
""" """
...@@ -53,7 +53,7 @@ fbsource_path = fbcode/wat ...@@ -53,7 +53,7 @@ fbsource_path = fbcode/wat
self.assertEqual(p.name, "test") self.assertEqual(p.name, "test")
self.assertEqual(p.fbsource_path, "fbcode/wat") self.assertEqual(p.fbsource_path, "fbcode/wat")
def test_unknown_field(self): def test_unknown_field(self) -> None:
with self.assertRaisesRegex( with self.assertRaisesRegex(
Exception, Exception,
( (
...@@ -70,7 +70,7 @@ invalid.field = woot ...@@ -70,7 +70,7 @@ invalid.field = woot
""", """,
) )
def test_invalid_section_name(self): def test_invalid_section_name(self) -> None:
with self.assertRaisesRegex( with self.assertRaisesRegex(
Exception, "manifest file test contains unknown section 'invalid.section'" Exception, "manifest file test contains unknown section 'invalid.section'"
): ):
...@@ -85,7 +85,7 @@ foo = bar ...@@ -85,7 +85,7 @@ foo = bar
""", """,
) )
def test_value_in_dependencies_section(self): def test_value_in_dependencies_section(self) -> None:
with self.assertRaisesRegex( with self.assertRaisesRegex(
Exception, Exception,
( (
...@@ -105,7 +105,7 @@ foo = bar ...@@ -105,7 +105,7 @@ foo = bar
""", """,
) )
def test_invalid_conditional_section_name(self): def test_invalid_conditional_section_name(self) -> None:
with self.assertRaisesRegex( with self.assertRaisesRegex(
Exception, Exception,
( (
...@@ -124,7 +124,7 @@ name = test ...@@ -124,7 +124,7 @@ name = test
""", """,
) )
def test_section_as_args(self): def test_section_as_args(self) -> None:
p = ManifestParser( p = ManifestParser(
"test", "test",
""" """
...@@ -164,7 +164,7 @@ name = test ...@@ -164,7 +164,7 @@ name = test
p2.get_section_as_args("autoconf.args"), ["--prefix=/foo", "--with-woot"] 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( p = ManifestParser(
"test", "test",
""" """
...@@ -202,12 +202,12 @@ foo = bar ...@@ -202,12 +202,12 @@ foo = bar
msg="sections cascade in the order they appear in the manifest", 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__) patch_loader(__name__)
manifests = load_all_manifests(None) manifests = load_all_manifests(None)
self.assertNotEqual(0, len(manifests), msg="parsed some number of manifests") 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( with self.assertRaisesRegex(
Exception, Exception,
"filename of the manifest 'foo' does not match the manifest name 'bar'", "filename of the manifest 'foo' does not match the manifest name 'bar'",
...@@ -220,7 +220,7 @@ name = bar ...@@ -220,7 +220,7 @@ name = bar
""", """,
) )
def test_duplicate_manifest(self): def test_duplicate_manifest(self) -> None:
patch_loader(__name__, "fixtures/duplicate") patch_loader(__name__, "fixtures/duplicate")
with self.assertRaisesRegex(Exception, "found duplicate manifest 'foo'"): with self.assertRaisesRegex(Exception, "found duplicate manifest 'foo'"):
......
...@@ -10,7 +10,7 @@ from ..platform import HostType ...@@ -10,7 +10,7 @@ from ..platform import HostType
class PlatformTest(unittest.TestCase): class PlatformTest(unittest.TestCase):
def test_create(self): def test_create(self) -> None:
p = HostType() p = HostType()
self.assertNotEqual(p.ostype, None, msg="probed and returned something") self.assertNotEqual(p.ostype, None, msg="probed and returned something")
...@@ -18,11 +18,11 @@ class PlatformTest(unittest.TestCase): ...@@ -18,11 +18,11 @@ class PlatformTest(unittest.TestCase):
round_trip = HostType.from_tuple_string(tuple_string) round_trip = HostType.from_tuple_string(tuple_string)
self.assertEqual(round_trip, p) self.assertEqual(round_trip, p)
def test_rendering_of_none(self): def test_rendering_of_none(self) -> None:
p = HostType(ostype="foo") p = HostType(ostype="foo")
self.assertEqual(p.as_tuple_string(), "foo-none-none") self.assertEqual(p.as_tuple_string(), "foo-none-none")
def test_is_methods(self): def test_is_methods(self) -> None:
p = HostType(ostype="windows") p = HostType(ostype="windows")
self.assertTrue(p.is_windows()) self.assertTrue(p.is_windows())
self.assertFalse(p.is_darwin()) self.assertFalse(p.is_darwin())
......
...@@ -10,7 +10,7 @@ from ..buildopts import find_existing_win32_subst_for_path ...@@ -10,7 +10,7 @@ from ..buildopts import find_existing_win32_subst_for_path
class Win32SubstTest(unittest.TestCase): class Win32SubstTest(unittest.TestCase):
def test_no_existing_subst(self): def test_no_existing_subst(self) -> None:
self.assertIsNone( self.assertIsNone(
find_existing_win32_subst_for_path( find_existing_win32_subst_for_path(
r"C:\users\alice\appdata\local\temp\fbcode_builder_getdeps", r"C:\users\alice\appdata\local\temp\fbcode_builder_getdeps",
...@@ -24,7 +24,7 @@ class Win32SubstTest(unittest.TestCase): ...@@ -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( self.assertEqual(
find_existing_win32_subst_for_path( find_existing_win32_subst_for_path(
r"C:\temp\fbcode_builder_getdeps", r"C:\temp\fbcode_builder_getdeps",
...@@ -40,7 +40,7 @@ class Win32SubstTest(unittest.TestCase): ...@@ -40,7 +40,7 @@ class Win32SubstTest(unittest.TestCase):
"X:\\", "X:\\",
) )
def test_multiple_exact_matches_returns_arbitrary_drive_path(self): def test_multiple_exact_matches_returns_arbitrary_drive_path(self) -> None:
self.assertIn( self.assertIn(
find_existing_win32_subst_for_path( find_existing_win32_subst_for_path(
r"C:\temp\fbcode_builder_getdeps", r"C:\temp\fbcode_builder_getdeps",
...@@ -53,7 +53,7 @@ class Win32SubstTest(unittest.TestCase): ...@@ -53,7 +53,7 @@ class Win32SubstTest(unittest.TestCase):
("X:\\", "Y:\\", "Z:\\"), ("X:\\", "Y:\\", "Z:\\"),
) )
def test_drive_letter_is_case_insensitive(self): def test_drive_letter_is_case_insensitive(self) -> None:
self.assertEqual( self.assertEqual(
find_existing_win32_subst_for_path( find_existing_win32_subst_for_path(
r"C:\temp\fbcode_builder_getdeps", r"C:\temp\fbcode_builder_getdeps",
...@@ -62,7 +62,7 @@ class Win32SubstTest(unittest.TestCase): ...@@ -62,7 +62,7 @@ class Win32SubstTest(unittest.TestCase):
"X:\\", "X:\\",
) )
def test_path_components_are_case_insensitive(self): def test_path_components_are_case_insensitive(self) -> None:
self.assertEqual( self.assertEqual(
find_existing_win32_subst_for_path( find_existing_win32_subst_for_path(
r"C:\TEMP\FBCODE_builder_getdeps", r"C:\TEMP\FBCODE_builder_getdeps",
......
...@@ -43,10 +43,10 @@ class ShellQuoted(namedtuple("ShellQuoted", ("do_not_use_raw_str",))): ...@@ -43,10 +43,10 @@ class ShellQuoted(namedtuple("ShellQuoted", ("do_not_use_raw_str",))):
"or ShellQuoted.format() instead".format(repr(self)) "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)) 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 Use instead of str.format() when the arguments are either
...@@ -65,7 +65,7 @@ class ShellQuoted(namedtuple("ShellQuoted", ("do_not_use_raw_str",))): ...@@ -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" "Quotes a string if it is not already quoted"
return ( return (
s s
...@@ -74,19 +74,19 @@ def shell_quote(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" "Not a member of ShellQuoted so we get a useful error for raw strings"
if isinstance(s, ShellQuoted): if isinstance(s, ShellQuoted):
return s.do_not_use_raw_str return s.do_not_use_raw_str
raise RuntimeError("{0} should have been ShellQuoted".format(s)) 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" "Joins an iterable of ShellQuoted with a delimiter between each two"
return ShellQuoted(delim.join(raw_shell(s) for s in it)) 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" "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])) 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