pallets / click

Python composable command line interface toolkit
https://click.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
15.3k stars 1.39k forks source link

Extra quotation mark appended to string arguments with escaped or quoted spaces and a trailing backslash #2486

Closed alexander-novo closed 1 year ago

alexander-novo commented 1 year ago

Environment:

Example code (found in NVlabs/stylegan3 and trimmed):

@click.command()
@click.pass_context
@click.option('--source', help='Directory or archive name for input dataset',
              required=True, metavar='PATH', type=click.Path(
                  exists=True, file_okay=False, dir_okay=True, readable=True,
                  writable=False))
def convert_dataset(
    ctx: click.Context,
    source: str
):
    print(f'source: {source}')

This happens even if the above type is left as default (string). When a path without a space is given as source, the program works as expected:

❯ python .\dataset_tool.py --source '..\Thesis\PlantVillage-Dataset\raw\segmented\Tomato___Septoria_leaf_spot\'
source: ..\Thesis\PlantVillage-Dataset\raw\segmented\Tomato___Septoria_leaf_spot\

But if a path with a space is given (either by escaping or quoting, as done above with the non-space directory), the source argument has an erroneous quotation mark at the end:

❯ python .\dataset_tool.py --source ..\Thesis\PlantVillage-Dataset\raw\segmented\Tomato___Spider_mites` Two-spotted_spider_mite\
Usage: dataset_tool.py [OPTIONS]
Try 'dataset_tool.py --help' for help.

Error: Invalid value for '--source': Directory '..\\Thesis\\PlantVillage-Dataset\\raw\\segmented\\Tomato___Spider_mites Two-spotted_spider_mite"' does not exist.
❯ python .\dataset_tool.py --source '..\Thesis\PlantVillage-Dataset\raw\segmented\Tomato___Spider_mites Two-spotted_spider_mite\'
Usage: dataset_tool.py [OPTIONS]
Try 'dataset_tool.py --help' for help.

Error: Invalid value for '--source': Directory '..\\Thesis\\PlantVillage-Dataset\\raw\\segmented\\Tomato___Spider_mites Two-spotted_spider_mite"' does not exist.

As mentioned above, changing the type of the option gives a similar issue, but won't error the program and quit:

❯ python .\dataset_tool.py --source '..\Thesis\PlantVillage-Dataset\raw\segmented\Tomato___Spider_mites Two-spotted_spider_mite\'
source: ..\Thesis\PlantVillage-Dataset\raw\segmented\Tomato___Spider_mites Two-spotted_spider_mite"

Actually, after re-analyzing the example results I gave here, I realised that not only does it append a quotation mark, it also removes the trailing backslash (note how in the first working example, the trailing backslash is still present). After re-trying the results with removing the trailing backslash from the input argument, the problem no longer occurred:

❯ python .\dataset_tool.py --source '..\Thesis\PlantVillage-Dataset\raw\segmented\Tomato___Spider_mites Two-spotted_spider_mite'
source: ..\Thesis\PlantVillage-Dataset\raw\segmented\Tomato___Spider_mites Two-spotted_spider_mite

So an additional stipulation is that the argument must have a trailing backslash I suppose?

davidism commented 1 year ago

Click doesn't do anything that would affect the value as you've shown. What does sys.argv contain? This is likely some weird shell quoting behavior in PowerShell.

alexander-novo commented 1 year ago

Oh you're right, I just checked and that is being added. How bizarre. Sorry for the erroneous report.

EDIT: I did some investigating and this was a powershell bug fixed a long time ago, but in a much later version than what is currently distributed with Windows.