I am using click for the very first time to create a cli program using Python 3.12.2.
I created a simple click command that takes an option (the '-f' / '--file' option) as a filepath with type click.Path():
@click.command()
@click.option(
"-f",
"--file",
"input_file_path",
type=click.Path(path_type=Path, exists=True, resolve_path=True),
required=True,
)
@click.option("-e", "--executor", "executor", default="pbiservice")
def validate(input_file_path: Path, executor):
executor = EXECUTORS[executor]
processed_validations_spec = (
process_validations_spec_from_local_file_and_return_resulting_validations_spec(
input_file_path, executor
)
)
click.echo(processed_validations_spec)
When I am now trying to test this command using the CliRunner of click, I want to have an isolated temporary directory that get's destroyed after the test. This way I can create a test file, invoke the command pointing to that file path and then have it all cleaned up afterwards. So I created a test for the command using the runner.isolated_filesystem context manager. However, no matter what I try I am unable to access a file that I have previously written to the temporary directory using my created cli command inside runner.invoke(). Here is my test:
def test_validate(validations_spec):
runner = CliRunner()
with runner.isolated_filesystem() as td:
file_name = "validations_spec.json"
write_validations_spec_to_local_file(validations_spec, Path(file_name))
result = runner.invoke(
validate,
[f"-f {file_name}"],
)
processed_validations_spec = validations_spec.process(MirrorExecutor())
assert result.output == processed_validations_spec
This always fails with Error: Invalid value for '-f' / '--file': Path ' validations_spec.json' does not exist.
I have tried reading the file with the python builtin open
function and that works, so the file does indeed exist. It's just that the click command cannot find it and I don't know why.
What I expect and tried:
The click command invoked inside an isolated_filesystem should be able to access the filepath to a file created inside this isolated fileystem. However, it claims that the file does not exist.
open
functionYour problem is this bit of code here:
result = runner.invoke(
validate,
[f"-f {file_name}"],
)
That's the equivalent of running a command line like:
./myprogram "-f validation_spec.json"
In both cases, the space between -f
and validation_spec.json
is considered part of the filename. That's why your error message look like:
Error: Invalid value for '-f' / '--file': Path ' validations_spec.json' does not exist.
See that space in ' validation_spec.json'
?
The solution is to pass a list of arguments:
result = runner.invoke(
validate,
["-f", file_name],
)