Author josh.r
Recipients David.Layton, Paolo.Elvati, Stefan.Pfeiffer, bethard, eric.araujo, josh.r, manveru, mitar, paul.j3
Date 2019-05-07.16:02:11
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1557244931.5.0.406714794.issue13824@roundup.psfhosted.org>
In-reply-to
Content
Mitar: argparse.FileType's __call__ (which is what "parses" the argument) returns whatever open (aka io.open) returns. Basically, post-parsing, there is nothing about the result of FileType that distinguishes it from a manually opened file (or when '-' is passed, from stdin/stdout). So it's already possible to do what you describe, simply by doing:

parser = argparse.ArgumentParser()
parser.add_argument('input', type=argparse.FileType())
arguments = parser.parse_args()

with arguments.input as f:
   assert arguments.input is f

That already "open[s] eagerly as now, but it would be closed at exit from context manager."

The original report did not like that you couldn't prevent clobbering of an existing file in write mode (no longer true, since you can pass a mode of 'x' just like you can with open), and did not like that the result of parsing was implicitly opened immediately without being controllable *immediately* via a context manager.

The only real solutions to that problem are either:

1. Making FileType (or a replacement) that is lazier in some way.
2. Making the argument namespace itself support context management

The proposal to check validity and return a curried call to open is problematic given the TOCTOU issues, but a curried version that performs little or no checks up front, but performs argparse style clean exits if the deferred open fails would be reasonable.

The alternative would be to integrate more heavily with the argument namespace, such that you could write code like:

with parser.parse_args() as arguments:

and in that scenario, the files would be opened immediately and stored on the namespace, but either only FileType, or any type result supporting context management, would be bulk __enter__-ed and bulk __exit__-ed upon exiting the with block.

As is, a user could do most of this with contextlib.ExitStack, but it's more to reimplement (and tricky to get right, and would still rely on argparse to clean up files 1 through n-1 if opening file n fails for whatever reason before parsing completes).
History
Date User Action Args
2019-05-07 16:02:11josh.rsetrecipients: + josh.r, bethard, eric.araujo, mitar, Paolo.Elvati, manveru, Stefan.Pfeiffer, paul.j3, David.Layton
2019-05-07 16:02:11josh.rsetmessageid: <1557244931.5.0.406714794.issue13824@roundup.psfhosted.org>
2019-05-07 16:02:11josh.rlinkissue13824 messages
2019-05-07 16:02:11josh.rcreate