click
click copied to clipboard
allow checking for path non-existance
right now, using click.Path() allows a user to set the following params:
exists=True
: aborts if path does not exists
dir_okay=False
: aborts if path (exists and) is a dir
file_okay=False
: aborts if path (exists and) is a file
(notice that for the each case, the opposite value will make the check to be simply skipped)
However, I believe that in many times, the programmer will want to write a program that verifies that a given path does not exists, (e.g. for purpose of creating it without overwriting anything)
for this case, I believe this set of parameters is better:
exists_okay=False
: aborts if path exists
not_exists_okay=False
: aborts if path does not exists
dir_okay=False
: aborts if path (exists and) is a dir
file_okay=False
: aborts if path (exists and) is a file
notice how before, users could think that exist=False
will force the path to be non-existing, while now each parameter behavior is clear from it's name.
from a quick look at the code, making this change seems to be trivial.
I'd like to take this up!
I've been thinking about this, and while I understand the use case, I think it's probably better to leave this to a custom parameter type or callback. You probably want to do something more complicated when a file exists, such as appending to it, or prompting to overwrite it (or failing), or making the path unique. On the other hand, exists=True
covers the much more common case where you want to read from a file and that file must actually exist.
That said, if we were to do it, I don't like the separate parameters, it can create combinations that don't make sense. Making exists=None
mean "don't care", and using False
and True
makes more sense to me.
Also it doesn't guard against paths which are neither a file nor a directory, such as pipes/sockets/char-devices/block-devices, so file_okay=False
will let a pipe pass, and might break the program if it open()
s and tries to .seek()
it for example.
Noting that I would like a way to require a path to not exist. However, this might be too significant an API change.
With all this different types (non-existent, file, directory, etc.), maybe it would be better to have it as a state
parameter.
It could be a set of acceptable states for the path. It could default to {Missing, File, Directory}
. Also, it could be cross-linked with the dir_okay
and file_okay
and exist_okay
flags.
Additionally, this could be extended to make special file checking (like symlink, hard-link, socket, fifo, etc. in linux).