-
Notifications
You must be signed in to change notification settings - Fork 25
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
Low hanging fruit and the jump to R v4 #159
Conversation
Adds support for #110 |
Hey @ijlyttle this branch covers a lot of open issues and brings us up to speed for R 4.0. I think it's time to do a CRAN release and I would like to submit it by the end of July. Not all of this code has to go into the release, but most of the changes are on new functions, so there is low risk including them. Ideally I'd say we merge this and #155, then cut it. What do you think? |
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.
Hi again Nate - I know I'm very late again in responding.
I like where you're going with this, I just want to make sure we get an idea of a function-naming convention before creating new functions.
I think, as well, this could use a version-bump and additions to the pkgdown function index.
R/boxr_file_versions.R
Outdated
#' along with a helpful message. | ||
#' | ||
#' The returned `data.frame` contains a variable, `file_version_id`, | ||
#' which you can use with [box_dl()]. | ||
#' * `box_current_version()` returns a `integer`, starting from 1, which can be passed |
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.
how about box_get_current_version()
? at some point also to rename (and soft-deprecate) box_previous_versions()
to box_file_get_info()
(I'd have to take a look at what gets returned)?
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 dropped this to box_version(file_id)
in my responses. It feels succinct and fits with box_previous_versions()
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.
working through all this - this afternoon. I fiddled with the documentation a little bit, just to get my mind right - but made no operational changes other than an as.integer()
and to use glue()
in the API call.
How about:
box_version_info()
as new name for (to-be-deprecated)box_previous_versions()
.box_version_number()
forbox_version()
.
I like putting version
in the second slot of each name for autocomplete reasons.
That being proposed, how about a quiet
argument (default to FALSE
) for box_version()
?
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.
Sure, that sounds good on names. No rush to deprecate box_previous_versions()
(at least as an alias) because it's been around since the beginning
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.
Tidyverse-style soft-deprecate, then, i.e. "superseded". Sounds good to me!
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.
Hey, thinking about the naming again, how does box_version_history()
sound instead? My thinking is version_info
is a bit ambiguous and doesn't say anything directly about the current version, version_history
feels more like what the func does only report info about past versions.
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.
Sounds good! I wonder if this is a good opportunity to supersede, rather than to deprecate.
Let me see if I can take a whack at it - here's an example of the idea: https://github.com/tidyverse/dplyr/blob/master/R/sample.R
I'm going to start moving these edits to a new PR, but will leave this one open until that is complete. |
I was able to use If you want to use this PR, great - if you want to move to a new PR, great. |
5f916d0
to
f165787
Compare
Hey @ijlyttle I think I responded to your edits on this PR. There are a few that are still open for discussion and I tried to leave a specific comment above. All of these revolve around naming functions, our new favorite boxr past-time LOL |
Hi @nathancday - I made a few fiddly changes, and have hit the ball back on our game of API tennis... have I missed responding to anything? I think we're getting closer. Happy to chat whenever! |
Thanks for review no2, I don't think you miss anything. I totally agree with your suggested API tweaks, I'll push those changes up tonight. |
Codecov Report
@@ Coverage Diff @@
## master #159 +/- ##
==========================================
+ Coverage 55.88% 58.99% +3.10%
==========================================
Files 24 25 +1
Lines 1555 1724 +169
==========================================
+ Hits 869 1017 +148
- Misses 686 707 +21
Continue to review full report at Codecov.
|
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.
Hi Nate, just a couple of fiddly things. I am looking at the superseding mechanism, so I think we can stay out of each others' way...
I ended up following a much-easier path: I reworked the documentation to separate |
b4367f8
to
08a5a5b
Compare
I'm not sure I like classing things anymore, after seeing how you'd have to use Here I've layered our box_r class on top of the |
83b823f
to
3782255
Compare
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.
To answer your question on the usefulness of returning an amorphous list-object of questionable utility, I think we should do so for two reasons:
- it fits in with how the other functions work.
- if someone wants a peek at what the API returned, perhaps to debug, it's the only way we can provide that.
boxr was set up somewhat along the lines of what httr suggests.
Clearly, this comes at a cost. But it also provides some flexibility in what someone can use - for a given box object (say a comment or list of comments), we can provide a way to extract:
- a data frame
- a tibble, if you like
- an opinionated optimal version of the return object, using something like
box_wrangle()
(in the future).
I know I have been burned by other boxr functions when I would print them, then expect a data frame. For this reason, I added the --- printing as data frame ---
to the print method for collabs.
I see a lot of the pattern where Box either returns a single object (box_create_comment()
) or a collection of objects in the entries
element (box_get_comment()
) - so we can provide a single-row data frame or a multi-row data frame. The pattern extends to collaborations and to versions, and I'm sure to other stuff.
This is where I thought a set of internal helpers could be reused: stack_row_df|tbl()
and stack_rows_df|tbl()
. By having these as internal functions, we can modify and test easily when new edge-cases appear.
The print helper print_dispatch()
automatically tells you if {tibble} is loaded or not - if a person wanted to always print as.data.frame
, we could set an option for that (I'll make a PR).
I think there are better names out there for these internal functions, but being internal functions, we can rename them whenever it suits.
What do you think?
R/boxr_comment.R
Outdated
x <- httr::content(req) | ||
|
||
# class it up | ||
x[["file_id"]] <- file_id |
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 think that our return object should be the parsed response from the API call, and that we should not be adding anything the object itself. We could add this to the object as an attribute.
R/boxr_comment.R
Outdated
x <- httr::content(req) | ||
|
||
# class it up | ||
class(x) <- c("boxr_comment_create", class(x)) |
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.
This class could be called boxr_comment
, to mirror the Box docs.
For this endpoint, the Box API returns a comment object; when we get a list comments, its
entries
member is an array of comment objects.
We see this pattern elsewhere; it's the motivation behind the stack_row_df|tbl()
and stack_rows_df|tbl()
helpers.
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.
Similarly as box_comment_get()
, we could add the file_id
as an attribute of the object.
R/boxr_comment.R
Outdated
|
||
# class it up | ||
x[["file_id"]] <- file_id | ||
class(x) <- c("boxr_comment_get", class(x)) |
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 think this class could be named boxr_comment_list
.
R/boxr_s3_classes.R
Outdated
|
||
# * Create ---------------------------------------------------------------- | ||
|
||
# no method for as.data.frame() needed, list.as.data.frame() works fine. |
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.
If there appears a NULL in a response, this throws a wrench into the stacking process - I work around this in stack_row_df()
- which is why I think it could be a useful helper here (and in general).
R/boxr_s3_classes.R
Outdated
#' @export | ||
#' | ||
print.boxr_comment_create <- function(x, ...) { | ||
x <- as.data.frame(x) |
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 think print_dispatch()
could be useful here. It could be preceded by the glue::glue()
call.
R/boxr_s3_classes.R
Outdated
#' @export | ||
#' | ||
as.data.frame.boxr_comment_get <- function(x, ...) { | ||
# stacking the comment records into a frame, one row per comment record |
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.
stack_rows_df()
should work here. If the file_id
were an attribute of x
, it could be added here to the data frame.
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.
As well, I think it would be good to have an as_tibble()
method.
R/boxr_s3_classes.R
Outdated
#' @export | ||
#' | ||
print.boxr_comment_get <- function(x, ...) { | ||
x <- as.data.frame(x) |
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 think print_dispatch()
could work here, too.
tests/testthat/test_14_comments.R
Outdated
"Comment" | ||
) | ||
expect_s3_class(resp, "boxr_comment_create") | ||
expect_s3_class(resp, "list") |
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 forgot to mention this earlier: in the new testthat this will have to be expect_type(resp, "list")
, which works now - I'm sure there will be other stuff that comes up when we switch over (not now!), but it could be useful to get ahead of this one.
I agree about preserving the original API response as much as possible, I just think that response is more useful in a data frame format (and most users probably end up there eventually) I just responded to changes and would really like to get this PR to done. Let me know if you are okay to merge and move on to other tasks. |
Sorry for delay - last week was busy at work. I agree that I agree Now that I think I have a better idea of the (admittedly less-than-ideal) compromise, I can make an effort to document it better, as it was not immediately evident to me. I should have some time this week to go through this and make any adjustments, so we can move on to other tasks. |
No worries, Box doesn't pay the bills. We can leave the behavior as is for FWIW I was imaging the return object reckoning (everyone gets a data.frame/tibble by default?) in v4.0. |
I agree we will have the object reckoning leading to v4 - I am in favor of the data.frame/tibble return (although we will have to sort out which one, and nesting, etc.) For me the trick will be to migrate from current to v4 without breaking anything. testthat's edition approach seems interesting, but I think even the Tidyverse team are still figuring out if/how to extend that approach. Getting to work now to map out the current situation, and to see how it might relate to some of our other recently-opened issues. |
…atch argument order
…f the API response: - the rest deals with only pagination - by returning only entries, we can support pagination - this is what box_ls() does
… amend tests - uses `version_id` rather than `file_version_id`
This is a placeholder for the narrative that I will write Monday. |
Here's what I think I know about the changes:
I am happy with where this is now - if there's anything I should change or we should discuss, please let me know. Otherwise, I would be pleased that one of us "squash-and-merge". 🙌 |
This is PR in progress with remedies for small open issues for new functionality:
box_current_version()
from issue Feature: knitr cache dependency on box file versions #142, hits the Version API similar tobox_previous_versions()
but just returns an integer >=1box_saveRDS()/
box_readRDS()` from feature: box_saveRDS()/box_readRDS() #110 is happening