fix(make): compose runner and dry runner directly (#324)
The previous composition strategy was such that it was difficult to compose functions returning a value. This new composition strategy is better because it allows us to return values, which is definitely going to help us. Part of https://github.com/ooni/probe/issues/1466.
This commit is contained in:
parent
a9b3a3b3a5
commit
80ef3e4b1b
82
make
82
make
|
@ -290,8 +290,11 @@ class Engine(Protocol):
|
||||||
"""unsetenv clears an environment variable."""
|
"""unsetenv clears an environment variable."""
|
||||||
|
|
||||||
|
|
||||||
class CommandRealExecutor:
|
class CommandExecutor:
|
||||||
"""CommandRealExecutor executes commands."""
|
"""CommandExecutor executes commands."""
|
||||||
|
|
||||||
|
def __init__(self, dry_runner: Engine):
|
||||||
|
self._dry_runner = dry_runner
|
||||||
|
|
||||||
def backticks(
|
def backticks(
|
||||||
self,
|
self,
|
||||||
|
@ -300,12 +303,15 @@ class CommandRealExecutor:
|
||||||
output: List[bytes],
|
output: List[bytes],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""backticks implements Engine.backticks"""
|
"""backticks implements Engine.backticks"""
|
||||||
# Implemented in CommandDryRunner
|
self._dry_runner.backticks(output_variable, cmdline, output)
|
||||||
|
# Nothing else to do, because backticks is fully
|
||||||
|
# implemented by CommandDryRunner.
|
||||||
|
|
||||||
def cat_sed_redirect(
|
def cat_sed_redirect(
|
||||||
self, patterns: List[Tuple[str, str]], source: str, dest: str
|
self, patterns: List[Tuple[str, str]], source: str, dest: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""cat_sed_redirect implements Engine.cat_sed_redirect."""
|
"""cat_sed_redirect implements Engine.cat_sed_redirect."""
|
||||||
|
self._dry_runner.cat_sed_redirect(patterns, source, dest)
|
||||||
with open(source, "r") as sourcefp:
|
with open(source, "r") as sourcefp:
|
||||||
data = sourcefp.read()
|
data = sourcefp.read()
|
||||||
for p, v in patterns:
|
for p, v in patterns:
|
||||||
|
@ -315,13 +321,16 @@ class CommandRealExecutor:
|
||||||
|
|
||||||
def echo_to_file(self, content: str, filepath: str) -> None:
|
def echo_to_file(self, content: str, filepath: str) -> None:
|
||||||
"""echo_to_file implements Engine.echo_to_file"""
|
"""echo_to_file implements Engine.echo_to_file"""
|
||||||
|
self._dry_runner.echo_to_file(content, filepath)
|
||||||
with open(filepath, "w") as filep:
|
with open(filepath, "w") as filep:
|
||||||
filep.write(content)
|
filep.write(content)
|
||||||
filep.write("\n")
|
filep.write("\n")
|
||||||
|
|
||||||
def require(self, *executable: str) -> None:
|
def require(self, *executable: str) -> None:
|
||||||
"""require implements Engine.require."""
|
"""require implements Engine.require."""
|
||||||
# Implemented in CommandDryRunner
|
self._dry_runner.require(*executable)
|
||||||
|
# Nothing else to do, because executable is fully
|
||||||
|
# implemented by CommandDryRunner.
|
||||||
|
|
||||||
def run(
|
def run(
|
||||||
self,
|
self,
|
||||||
|
@ -331,6 +340,7 @@ class CommandRealExecutor:
|
||||||
inputbytes: Optional[bytes] = None,
|
inputbytes: Optional[bytes] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""run implements Engine.run."""
|
"""run implements Engine.run."""
|
||||||
|
self._dry_runner.run(cmdline, cwd, extra_env, inputbytes)
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
if extra_env:
|
if extra_env:
|
||||||
for key, value in extra_env.items():
|
for key, value in extra_env.items():
|
||||||
|
@ -339,10 +349,12 @@ class CommandRealExecutor:
|
||||||
|
|
||||||
def setenv(self, key: str, value: str) -> None:
|
def setenv(self, key: str, value: str) -> None:
|
||||||
"""setenv implements Engine.setenv."""
|
"""setenv implements Engine.setenv."""
|
||||||
|
self._dry_runner.setenv(key, value)
|
||||||
os.environ[key] = value
|
os.environ[key] = value
|
||||||
|
|
||||||
def unsetenv(self, key: str) -> None:
|
def unsetenv(self, key: str) -> None:
|
||||||
"""unsetenv implements Engine.unsetenv."""
|
"""unsetenv implements Engine.unsetenv."""
|
||||||
|
self._dry_runner.unsetenv(key)
|
||||||
del os.environ[key]
|
del os.environ[key]
|
||||||
|
|
||||||
|
|
||||||
|
@ -425,67 +437,13 @@ class CommandDryRunner:
|
||||||
log("./make: unset {}".format(key))
|
log("./make: unset {}".format(key))
|
||||||
|
|
||||||
|
|
||||||
class EngineComposer:
|
|
||||||
"""EngineComposer composes two engines."""
|
|
||||||
|
|
||||||
def __init__(self, first: Engine, second: Engine):
|
|
||||||
self._first = first
|
|
||||||
self._second = second
|
|
||||||
|
|
||||||
def backticks(
|
|
||||||
self,
|
|
||||||
output_variable: str,
|
|
||||||
cmdline: List[str],
|
|
||||||
output: List[bytes],
|
|
||||||
) -> None:
|
|
||||||
"""backticks implements Engine.backticks"""
|
|
||||||
self._first.backticks(output_variable, cmdline, output)
|
|
||||||
self._second.backticks(output_variable, cmdline, output)
|
|
||||||
|
|
||||||
def cat_sed_redirect(
|
|
||||||
self, patterns: List[Tuple[str, str]], source: str, dest: str
|
|
||||||
) -> None:
|
|
||||||
"""cat_sed_redirect implements Engine.cat_sed_redirect."""
|
|
||||||
self._first.cat_sed_redirect(patterns, source, dest)
|
|
||||||
self._second.cat_sed_redirect(patterns, source, dest)
|
|
||||||
|
|
||||||
def echo_to_file(self, content: str, filepath: str) -> None:
|
|
||||||
"""echo_to_file implements Engine.echo_to_file"""
|
|
||||||
self._first.echo_to_file(content, filepath)
|
|
||||||
self._second.echo_to_file(content, filepath)
|
|
||||||
|
|
||||||
def require(self, *executable: str) -> None:
|
|
||||||
"""require implements Engine.require."""
|
|
||||||
self._first.require(*executable)
|
|
||||||
self._second.require(*executable)
|
|
||||||
|
|
||||||
def run(
|
|
||||||
self,
|
|
||||||
cmdline: List[str],
|
|
||||||
cwd: Optional[str] = None,
|
|
||||||
extra_env: Optional[Dict[str, str]] = None,
|
|
||||||
inputbytes: Optional[bytes] = None,
|
|
||||||
) -> None:
|
|
||||||
"""run implements Engine.run."""
|
|
||||||
self._first.run(cmdline, cwd=cwd, extra_env=extra_env, inputbytes=inputbytes)
|
|
||||||
self._second.run(cmdline, cwd=cwd, extra_env=extra_env, inputbytes=inputbytes)
|
|
||||||
|
|
||||||
def setenv(self, key: str, value: str) -> None:
|
|
||||||
"""setenv implements Engine.setenv."""
|
|
||||||
self._first.setenv(key, value)
|
|
||||||
self._second.setenv(key, value)
|
|
||||||
|
|
||||||
def unsetenv(self, key: str) -> None:
|
|
||||||
"""unsetenv implements Engine.unsetenv."""
|
|
||||||
self._first.unsetenv(key)
|
|
||||||
self._second.unsetenv(key)
|
|
||||||
|
|
||||||
|
|
||||||
def new_engine(options: Options) -> Engine:
|
def new_engine(options: Options) -> Engine:
|
||||||
"""new_engine creates a new engine instance"""
|
"""new_engine creates a new engine instance"""
|
||||||
if options.dry_run():
|
out: Engine = CommandDryRunner()
|
||||||
return CommandDryRunner()
|
if not options.dry_run():
|
||||||
return EngineComposer(CommandDryRunner(), CommandRealExecutor())
|
out = CommandExecutor(out)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
class Target(Protocol):
|
class Target(Protocol):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user