Skip to content

Commit

Permalink
Vectorized version of osm_read_changeset()
Browse files Browse the repository at this point in the history
  • Loading branch information
jmaspons committed Dec 22, 2023
1 parent ce87a35 commit 21e185f
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 22 deletions.
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export(osm_details_logged_user)
export(osm_diff_upload_changeset)
export(osm_download_changeset)
export(osm_feed_notes)
export(osm_get_changesets)
export(osm_get_data_gpx)
export(osm_get_gpx_metadata)
export(osm_get_objects)
Expand All @@ -46,7 +47,6 @@ export(osm_list_gpxs)
export(osm_permissions)
export(osm_query_changesets)
export(osm_read_bbox_notes)
export(osm_read_changeset)
export(osm_read_note)
export(osm_redaction_object)
export(osm_relations_object)
Expand Down
115 changes: 115 additions & 0 deletions R/osm_get_changesets.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Vectorized version of osm_read_changeset

#' Get changesets
#'
#' Returns the changesets with the given `changeset_id`.
#'
#' @param changeset_id A vector with ids of changesets to retrieve represented by a numeric or a character values.
#' @param include_discussion Indicates whether the result should contain the changeset discussion or not.
#' @param format Format of the output. Can be `R` (default), `xml`, or `json`.
#' @param tags_in_columns If `FALSE` (default), the tags of the changesets are saved in a single list column `tags`
#' containing a `data.frame` for each changeset with the keys and values. If `TRUE`, add a column for each key.
#' Ignored if `format != "R"`.
#'
#' @details
#' * The `uid` might not be available for changesets auto generated by the API v0.5 to API v0.6 transition
#' * The bounding box attributes will be missing for an empty changeset.
#' * The changeset bounding box is a rectangle that contains the bounding boxes of all objects changed in this
#' changeset. It is not necessarily the smallest possible rectangle that does so.
#' * This API call only returns information about the changeset itself but not the actual changes made to elements in
#' this changeset. To access this information use [osm_download_changeset()].
#'
#' @return
#' If `format = "R"`, returns a data frame with one OSM changeset per row.
#'
#' ## `format = "xml"`
#' Returns a [xml2::xml_document-class] with the following format:
#' ``` xml
#' <osm>
#' <changeset id="10" created_at="2008-11-08T19:07:39+01:00" open="true" user="fred" uid="123" min_lon="7.0191821" min_lat="49.2785426" max_lon="7.0197485" max_lat="49.2793101" comments_count="3" changes_count="10">
#' <tag k="created_by" v="JOSM 1.61"/>
#' <tag k="comment" v="Just adding some streetnames"/>
#' ...
#' <discussion>
#' <comment date="2015-01-01T18:56:48Z" uid="1841" user="metaodi">
#' <text>Did you verify those street names?</text>
#' </comment>
#' <comment date="2015-01-01T18:58:03Z" uid="123" user="fred">
#' <text>sure!</text>
#' </comment>
#' ...
#' </discussion>
#' </changeset>
#' <changeset>
#' ...
#' </changeset>
#' </osm>
#' ```
#'
#' ## `format = "json"`
#' Returns a list with the following json structure:
#' ``` json
#' {
#' "version": "0.6",
#' "elements": [
#' {"type": "changeset",
#' "id": 10,
#' "created_at": "2005-05-01T16:09:37Z",
#' "closed_at": "2005-05-01T17:16:44Z",
#' "open": False,
#' "user": "Petter Reinholdtsen",
#' "uid": 24,
#' "minlat": 59.9513092,
#' "minlon": 10.7719727,
#' "maxlat": 59.9561501,
#' "maxlon": 10.7994537,
#' "comments_count": 1,
#' "changes_count": 10,
#' "discussion": [{"date": "2022-03-22T20:58:30Z", "uid": 15079200, "user": "Ethan White of Cheriton", "text": "wow no one have said anything here 3/22/2022\n"}]
#' }, ...]
#' }
#' ```
#'
#' @family get changesets' functions
#' @export
#'
#' @examples
#' \dontrun{
#' chaset <- osm_get_changesets(changeset_id = 137595351, include_discussion = TRUE)
#' chaset
#' chaset$discussion
#' }
osm_get_changesets <- function(changeset_id, include_discussion = FALSE,
format = c("R", "xml", "json"), tags_in_columns = FALSE) {
format <- match.arg(format)

if (length(changeset_id) == 1) {
out <- osm_read_changeset(
changeset_id = changeset_id, include_discussion = include_discussion,
format = format, tags_in_columns = tags_in_columns
)
} else {
outL <- lapply(changeset_id, function(id) {
osm_read_changeset(changeset_id = id, include_discussion = include_discussion, format = format)
})

if (format == "R") {
out <- do.call(rbind, outL)
if (tags_in_columns) {
out <- tags_list2wide(out)
}
} else if (format == "xml") {
out <- xml2::xml_new_root(outL[[1]])
for (i in seq_len(length(outL) - 1)) {
xml2::xml_add_child(out, xml2::xml_child(outL[[i + 1]]))
}
} else if (format == "json") {
out <- outL[[1]]
if (length(outL) > 1) {
out$elements <- do.call(c, c(list(out$elements), lapply(outL[-1], function(x) x$elements)))
}
}
}

return(out)
}
6 changes: 3 additions & 3 deletions R/osmapi_changesets.R
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ osm_create_changeset <- function(comment, ...,
#' }
#' ```
#'
#' @family get changesets' functions
#' @export
# @family get changesets' functions
#' @noRd
#'
#' @examples
#' \dontrun{
Expand Down Expand Up @@ -444,7 +444,7 @@ osm_close_changeset <- function(changeset_id) {
#' @details
#' * The result of calling this may change as long as the changeset is open.
#' * The elements in the OsmChange are sorted by timestamp and version number.
#' * There is [osm_read_changeset()] to get only information about the changeset itself.
#' * There is [osm_get_changesets()] to get only information about the changeset itself.
#'
#' @return
#' If `format = "R"`, returns a data frame with one row for each edit action in the changeset. If `format = "xml`,
Expand Down
2 changes: 1 addition & 1 deletion R/tags_list-wide.r
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#'
#' @rdname tags_list-wide
#' @param x An `osmapi_objects` or `osmapi_changesets` objects as returned by, for example, [osm_get_objects()] or
#' [osm_read_changeset()].
#' [osm_get_changesets()].
#'
#' @details
#' Both formats have advantages. Tags in a list of data.frames is a more compact representation and there is no risk of
Expand Down
6 changes: 3 additions & 3 deletions man/osm_download_changeset.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 12 additions & 9 deletions man/osm_read_changeset.Rd → man/osm_get_changesets.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/osm_query_changesets.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/tags_list-wide.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions tests/testthat/test-changesets.R
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ test_that("edit changeset (create/update/diff upload) works", {
"New changeset with id = "
)

chaset <- osm_read_changeset(changeset_id = chset_id)
chaset <- osm_get_changesets(changeset_id = chset_id)

## Update: `PUT /api/0.6/changeset/#id` ----
upd_chaset <- osm_update_changeset(
Expand Down Expand Up @@ -94,8 +94,8 @@ test_that("edit changeset (create/update/diff upload) works", {

test_that("osm_read_changeset works", {
with_mock_dir("mock_read_changeset", {
chaset <- osm_read_changeset(changeset_id = 137595351)
chaset_discuss <- osm_read_changeset(changeset_id = 137595351, include_discussion = TRUE)
chaset <- osm_get_changesets(changeset_id = 137595351)
chaset_discuss <- osm_get_changesets(changeset_id = 137595351, include_discussion = TRUE)
})

expect_s3_class(chaset, c("osmapi_changesets", "data.frame"))
Expand Down

0 comments on commit 21e185f

Please sign in to comment.