Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy open output files, and always close them #314

Merged
merged 3 commits into from
Jul 8, 2024

Conversation

kurtmckee
Copy link
Contributor

@kurtmckee kurtmckee commented Jun 29, 2024

This PR modifies the test suite to show all warnings, including ResourceWarning. By doing so, this revealed that the CLI code never closes output files opened by argparse during argument parsing.

Therefore, this PR additionally modifies the CLI code to open output files only when they will be written to, and ensures that they are always closed after writing.

@kurtmckee kurtmckee force-pushed the lazy-open-always-close-output-files branch from fee8ae3 to 94a0007 Compare July 1, 2024 14:39
@kurtmckee
Copy link
Contributor Author

kurtmckee commented Jul 1, 2024

Rebased on main

@kurtmckee kurtmckee force-pushed the lazy-open-always-close-output-files branch from 94a0007 to 11c7a5d Compare July 2, 2024 12:46
Copy link
Member

@miketheman miketheman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question inline, but otherwise looks fine.

I'm curious about the impact of leaving open files in a CLI tool - don't those descriptors disappear once the runtime exits?

Considering the primary use cases for this project is a library, how important is this change?

tox.ini Outdated Show resolved Hide resolved
@kurtmckee
Copy link
Contributor Author

kurtmckee commented Jul 2, 2024

Great questions.

  • I'm curious about the impact of leaving open files in a CLI tool - don't those descriptors disappear once the runtime exits?

    Yes, they will. However, I had two considerations when I observed this.

    The first is a recent experience at work with a tool that expected to be run as a CLI but that we needed to import, customize, and call the cli.main() function ourselves. That recent experience made me want to address this as a hygiene/best practice consideration.

    The second is a functional consideration: the output file is created even if there's an error.

    For example, if nh3 raises ValueError, that is caught, None is returned, and sys.exit(1) is subsequently called. An output file is created even though rendering failed.

    This PR changes that behavior so an output file is only created when rendered output is ready to be written, and ensures that resources are cleaned up afterward.

  • how important is this change?

    Not important. I think it's a low value -- but correct -- change.

  • Curious why you went with the outer call instead of using pytest -Wall ...?

    I didn't know that -Wall existed! 😀

    I have had past experience that configuring pytest's filterwarnings to raise errors on warnings wouldn't catch errors in very specific ways, like a DeprecationWarning that was triggered by Python 3.12 when importing an old version of dateutil; the solution I found at that time was to switch from pytest's filterwarnings to invoking Python directly, and that's the solution I reached for here.

    Want me to switch to pytest -Wall instead of python -Wall -m pytest?

@kurtmckee kurtmckee force-pushed the lazy-open-always-close-output-files branch from 11c7a5d to 0f58147 Compare July 2, 2024 22:21
@miketheman
Copy link
Member

... we needed to import, customize, and call the cli.main() function ourselves ...

Thanks for the context, and that makes sense.

The library was never fully intended as a CLI, so please be mindful of the cli namespace, as it is entire possible to change (as we ware changing it here). I'd be open to understanding the utility performed in the CLI that should be part of the general API, and thus decrease usage on cli.*

This PR changes that behavior so an output file is only created when rendered output is ready to be written, and ensures that resources are cleaned up afterward.

This makes most sense here.

Want me to switch to pytest -Wall instead of python -Wall -m pytest?

Yes please! If we have a specific reason to move it to the "outer" behavior you've described, then we can do that at a later time, but we should use the built-in if possible.

tox.ini Outdated Show resolved Hide resolved
@kurtmckee kurtmckee force-pushed the lazy-open-always-close-output-files branch from a6a2aaf to f14d946 Compare July 7, 2024 17:58
@kurtmckee
Copy link
Contributor Author

Oh no, my commit signatures appear to have been broken by using GitHub's web UI to rebase on main. Let me circle back to this when I'm back at my PC tomorrow.

Regarding the cli.main() discussion -- I wanted to be clear that this was not something involving this project, it was just an example from my recent experience that "people use stuff in unexpected ways". 😀

@kurtmckee kurtmckee force-pushed the lazy-open-always-close-output-files branch from f14d946 to 3c42ccf Compare July 8, 2024 11:22
@miketheman
Copy link
Member

Thanks! Merging now.

If you'd like to craft a CHANGES.rst entry for 44.0, we can get these released. Here's an example of a previous PR for releases: #303

@miketheman miketheman merged commit 09620a6 into pypa:main Jul 8, 2024
8 checks passed
@kurtmckee kurtmckee deleted the lazy-open-always-close-output-files branch July 8, 2024 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants