-
Notifications
You must be signed in to change notification settings - Fork 22
Prevent strwidth() and par() calls from leaking graphics devices
#285
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
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR addresses issue #227 by preventing unintended Rplots.pdf file generation when graphics::strwidth() and graphics::par() are called without an active graphics device. The solution introduces a helper function that manages graphics device lifecycle by opening a null-output device only when needed and ensuring it's closed on exit.
Key changes:
- Introduces a
with_graphics_device()helper that wraps graphics function calls to prevent device leaks - Refactors all
graphics::strwidth()andgraphics::par()calls in R code and tests to use the new helper - Removes
Rplots.pdffrom.gitignoresince it should no longer be generated
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| R/safe_graphics.R | New file implementing device lifecycle management helpers: with_graphics_device(), open_null_device(), close_device(), and file_null() |
| R/rtf_strwidth.R | Updated to wrap graphics::par() and graphics::strwidth() calls with with_graphics_device() |
| tests/testthat/test-independent-testing-rtf_strwidth.R | Updated test code to wrap graphics::strwidth() calls with with_graphics_device() |
| tests/testthat/test-independent-testing-rtf_nrow.R | Updated test code to wrap graphics::strwidth() calls with with_graphics_device() |
| .gitignore | Removed Rplots.pdf entry (no longer needed) and sync_bitbucket.R (appears unrelated) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Cool, thanks for fixing the issue! |
yihui
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need more time to understand the rtf_strwidth() function and will review the PR tomorrow.
|
Just to make sure I understand pdf(NULL)
on.exit(dev.off())in |
Unfortunately, a quick test shows that I was wrong: > png()
> strwidth('hello world', 'inches', family = 'Times')
[1] 0.7637533
> dev.off()
> pdf()
> strwidth('hello world', 'inches', family = 'Times')
[1] 0.7621667
> dev.off()That means |
|
BTW, although I don't think any of you would consider switching to another testing framework, I'd like to mention that I also ran into this problem several years ago and provided an option in {testit} to automatically clean up new files generated from tests (including this |
|
Yes, it seems clear that the original intention for And yes, the current output is dependent on the graphical device context and thus unpredictable. The goal of this PR is to eliminate the annoying Theoretically, calculating this should NOT require a graphical device. The parameters that truly matter are the font, font size, and DPI. See a proper solution in rtflite (Python) calling Pillow's Here is a table comparing these possible solutions:
|
Fixes #227
This is new try (after PR #228) to fix the issue reported in #227 where calls to
graphics::strwidth()andgraphics::par()unintentionally generateRplots.pdffiles in some environments due to opening a new default graphics device that is never closed.The discussion in that PR was very helpful in getting this "more proper" solution.
with_graphics_device()helper to rungraphics::strwidth()/graphics::par()without implicitly leaving the default device open by opening a null-output device only when needed and closing it on exit.R/andtests/to use the helper.Performance comparison:
Note that changing this might affect some
strwidth()calculation results slightly.