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): ...@@ -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())
......
This diff is collapsed.
...@@ -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