diff options
Diffstat (limited to 'man')
| -rw-r--r-- | man/cep_health.Rd | 34 | ||||
| -rw-r--r-- | man/cep_lookup.Rd | 46 | ||||
| -rw-r--r-- | man/cep_lookup_many.Rd | 51 | ||||
| -rw-r--r-- | man/cepis-package.Rd | 38 | ||||
| -rw-r--r-- | man/cepis_address.Rd | 34 | ||||
| -rw-r--r-- | man/cepis_client.Rd | 64 | ||||
| -rw-r--r-- | man/cepis_conditions.Rd | 42 | ||||
| -rw-r--r-- | man/cepis_geo.Rd | 36 | ||||
| -rw-r--r-- | man/cepis_health.Rd | 23 | ||||
| -rw-r--r-- | man/formatted_cep.Rd | 25 | ||||
| -rw-r--r-- | man/normalize_cep.Rd | 33 |
11 files changed, 426 insertions, 0 deletions
diff --git a/man/cep_health.Rd b/man/cep_health.Rd new file mode 100644 index 0000000..7fdfc1b --- /dev/null +++ b/man/cep_health.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/api.R +\name{cep_health} +\alias{cep_health} +\title{Ask the API how it is, and which database it is serving} +\usage{ +cep_health(client = default_client()) +} +\arguments{ +\item{client}{A \code{\link[=cepis_client]{cepis_client()}}. Defaults to a shared client built with +the default configuration.} +} +\value{ +A \link{cepis_health}. +} +\description{ +Useful for two things: checking that the API answers, and knowing which +version of the DNE database is live. The database changes every two weeks. +} +\section{Conditions}{ + +An API reporting itself degraded is not a failure here — that arrives in +\code{status}, and checking health is exactly when you want the diagnosis +rather than an error. Network failures still signal \code{cepis_network_error}. +} + +\examples{ +\donttest{ +health <- cep_health() +health$ok +health$dne +} + +} diff --git a/man/cep_lookup.Rd b/man/cep_lookup.Rd new file mode 100644 index 0000000..3c22a1e --- /dev/null +++ b/man/cep_lookup.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/api.R +\name{cep_lookup} +\alias{cep_lookup} +\title{Look up a single CEP} +\usage{ +cep_lookup(cep, client = default_client()) +} +\arguments{ +\item{cep}{A length-one character vector: \code{"01001-000"} or \code{"01001000"}.} + +\item{client}{A \code{\link[=cepis_client]{cepis_client()}}. Defaults to a shared client built with +the default configuration.} +} +\value{ +A \link{cepis_address}. +} +\description{ +Accepts the CEP masked or unmasked and returns everything the DNE database +has for it, including the coordinate when there is one. +} +\section{Conditions}{ + +\describe{ +\item{\code{cepis_invalid_cep}}{the CEP is not 8 digits. No request is made.} +\item{\code{cepis_not_found}}{well-formed, but not in the database.} +\item{\code{cepis_rate_limited}}{429 on every attempt.} +\item{\code{cepis_server_error}}{5xx on every attempt.} +\item{\code{cepis_network_error}}{the request never completed.} +\item{\code{cepis_invalid_response}}{a success status with an unreadable +body.} +} + +All of them inherit \code{cepis_error}; see \link{cepis_conditions}. +} + +\examples{ +\donttest{ +address <- cep_lookup("01001-000") +address$localidade +if (!is.null(address$geo) && address$geo$is_precise) { + c(address$geo$lat, address$geo$lon) +} +} + +} diff --git a/man/cep_lookup_many.Rd b/man/cep_lookup_many.Rd new file mode 100644 index 0000000..9362649 --- /dev/null +++ b/man/cep_lookup_many.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/api.R +\name{cep_lookup_many} +\alias{cep_lookup_many} +\title{Look up many CEPs in one request} +\usage{ +cep_lookup_many(ceps, client = default_client()) +} +\arguments{ +\item{ceps}{A character vector of CEPs, masked or unmasked.} + +\item{client}{A \code{\link[=cepis_client]{cepis_client()}}. Defaults to a shared client built with +the default configuration.} +} +\value{ +A list of \strong{the same length and in the same order} as \code{ceps}. +Each element is a \link{cepis_address}, or \code{NULL} where the CEP does not +exist or is malformed — it does not vanish from the list, and it does not +signal a condition. That is the right difference from \code{\link[=cep_lookup]{cep_lookup()}}: in +a batch of a thousand, one bad CEP must not cost the other nine hundred +and ninety-nine. Use \code{\link[=normalize_cep]{normalize_cep()}} beforehand if you need to know +\emph{which} input was malformed. + +A list rather than a \code{data.frame} because \code{NULL} is the only unambiguous +"no such CEP" in R: a row of \code{NA}s reads as an address with unknown +fields, which is a different statement, and an empty row cannot be told +apart from a CEP the database knows only by number. Rectangle it with +\code{do.call(rbind, lapply(result, function(a) as.data.frame(a[1:13])))} when +a \code{data.frame} is what you want. +} +\description{ +Resolves up to 500 CEPs per request, chunking longer inputs automatically. +Do not loop over \code{\link[=cep_lookup]{cep_lookup()}}: a loop of 500 calls pays 500 TLS +handshakes, the batch pays one. +} +\section{Batches carry no coordinate}{ + +The endpoint behind them is CSV, and the CSV has no \code{geo} column. Every +address returned here has \code{geo = NULL}, including for CEPs that do have +one. Need \code{geo}? Use \code{\link[=cep_lookup]{cep_lookup()}}, one at a time. +} + +\examples{ +\donttest{ +ceps <- c("01001000", "99999999", "20040020") +result <- cep_lookup_many(ceps) +vapply(result, function(a) if (is.null(a)) NA_character_ else a$localidade, + character(1)) +} + +} diff --git a/man/cepis-package.Rd b/man/cepis-package.Rd new file mode 100644 index 0000000..d182e04 --- /dev/null +++ b/man/cepis-package.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cepis-package.R +\docType{package} +\name{cepis-package} +\alias{cepis} +\alias{cepis-package} +\title{cepis: client for the public CEP API at cep.is} +\description{ +Resolves Brazilian postal codes against \url{https://cep.is}. Official +Correios data (DNE), refreshed every two weeks. + +\if{html}{\out{<div class="sourceCode r">}}\preformatted{address <- cep_lookup("01001-000") +address$logradouro # "Praca da Se" +address$localidade # "Sao Paulo" +}\if{html}{\out{</div>}} + +The API surface is English, but the \strong{data fields keep the API's own +Portuguese names} (\code{logradouro}, \code{bairro}, \code{localidade}, \code{uf}). What you +read in the JSON at \url{https://cep.is/01001000} is what you read on the +returned object, with no translation layer in between. + +Start at \code{\link[=cep_lookup]{cep_lookup()}} for one CEP, \code{\link[=cep_lookup_many]{cep_lookup_many()}} for many, +\code{\link[=cep_health]{cep_health()}} for the API's status and \code{\link[=cepis_client]{cepis_client()}} for anything +beyond the default configuration. Failures are classed conditions, +described in \link{cepis_conditions}. +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://cep.is} +} + +} +\author{ +\strong{Maintainer}: Murilo Ijanc \email{[email protected]} + +} +\keyword{internal} diff --git a/man/cepis_address.Rd b/man/cepis_address.Rd new file mode 100644 index 0000000..6fc0b89 --- /dev/null +++ b/man/cepis_address.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/models.R +\name{cepis_address} +\alias{cepis_address} +\title{A CEP and everything the database knows about it} +\description{ +The object returned by \code{\link[=cep_lookup]{cep_lookup()}} and by each element of +\code{\link[=cep_lookup_many]{cep_lookup_many()}}. It is a plain list of class \code{cepis_address}, so +\code{address$localidade} and \code{str(address)} work as usual. + +\strong{The data fields keep the API's Portuguese names.} Fields the database +does not have for a CEP come back as empty strings, never \code{NA} — that is +what the API returns, and changing it here would create a difference +between reading the JSON and reading this package. +} +\section{Fields}{ + +\describe{ +\item{\code{cep}}{the 8 digits, always unmasked. \code{\link[=formatted_cep]{formatted_cep()}} adds the +mask.} +\item{\code{logradouro}, \code{complemento}, \code{unidade}, \code{bairro}}{the street and +its qualifiers.} +\item{\code{localidade}, \code{uf}, \code{estado}, \code{regiao}}{municipality, state code, +state name, region.} +\item{\code{ibge}, \code{gia}, \code{ddd}, \code{siafi}}{the codes the database carries.} +\item{\code{geo}}{a \link{cepis_geo} object, or \code{NULL} when the database has no +coordinate for that CEP. \code{NULL} and not a row of \code{NA}s because the API +\strong{omits} the whole field in that case (about 43\% of CEPs) rather than +sending null.} +\item{\code{raw}}{the response exactly as it arrived, uninterpreted, so a +field the API grows before this package is updated is not lost.} +} +} + diff --git a/man/cepis_client.Rd b/man/cepis_client.Rd new file mode 100644 index 0000000..f8644e7 --- /dev/null +++ b/man/cepis_client.Rd @@ -0,0 +1,64 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/client.R +\name{cepis_client} +\alias{cepis_client} +\title{Build a client for the cep.is API} +\usage{ +cepis_client( + base_url = DEFAULT_BASE_URL, + timeout = 10, + max_attempts = 3L, + backoff_base = 0.5, + backoff_max = 8, + total_timeout = NULL, + user_agent = NULL +) +} +\arguments{ +\item{base_url}{Where the API lives. Point it at a local instance (the API +repo brings one up on \verb{http://localhost:8080} with \verb{just up}) or at a +test server. It is the only parameter that usually changes between +environments. Trailing slashes are stripped, so it cannot produce +doubled separators that some proxies normalise and others 404.} + +\item{timeout}{Seconds allowed for \strong{one attempt}, connection and +transfer together. It is not a cap on the whole call, since a call may +make several attempts; that cap is \code{total_timeout}.} + +\item{max_attempts}{How many attempts in total, counting the first. \code{1} +disables retrying. The default of \code{3} covers the common case (one +transient failure) without turning a real outage into a long wait.} + +\item{backoff_base}{Base of the exponential wait, in seconds. The actual +wait is drawn from \verb{[0, base * 2^(n - 1)]} — \emph{full jitter}. The +randomness is not decoration: without it, N clients that fail together +come back together and reproduce the spike that took the service down.} + +\item{backoff_max}{Cap on each individual wait, in seconds. It applies to +a server-sent \code{Retry-After} too, or a \code{Retry-After: 3600} from a +misconfigured proxy would park the session for an hour.} + +\item{total_timeout}{Cap on the whole call, attempts and waits included. +\code{NULL} leaves \code{max_attempts} as the only bound. Set it in code serving a +web request: without it the worst case is \code{max_attempts * timeout} plus +the sum of the backoffs.} + +\item{user_agent}{Overrides the \code{User-Agent}. The default identifies the +package and its version, which is what lets the server diagnose an old +client misbehaving.} +} +\value{ +An object of class \code{cepis_client}, to pass as the \code{client} +argument of \code{\link[=cep_lookup]{cep_lookup()}}, \code{\link[=cep_lookup_many]{cep_lookup_many()}} and \code{\link[=cep_health]{cep_health()}}. +} +\description{ +Holds the configuration and nothing else: no connection, no state between +calls. Build one and reuse it, or skip it entirely — \code{\link[=cep_lookup]{cep_lookup()}}, +\code{\link[=cep_lookup_many]{cep_lookup_many()}} and \code{\link[=cep_health]{cep_health()}} fall back to a shared default +client built with these defaults. +} +\examples{ +client <- cepis_client(base_url = "http://localhost:8080", timeout = 5) +client$max_attempts + +} diff --git a/man/cepis_conditions.Rd b/man/cepis_conditions.Rd new file mode 100644 index 0000000..4def4ff --- /dev/null +++ b/man/cepis_conditions.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/conditions.R +\name{cepis_conditions} +\alias{cepis_conditions} +\title{Conditions signalled by cepis} +\description{ +Every failure raised by this package is a classed condition inheriting +from \code{cepis_error}, so one handler catches all of them: + +\if{html}{\out{<div class="sourceCode r">}}\preformatted{tryCatch( + cep_lookup(cep_from_form), + cepis_not_found = function(e) NULL, + cepis_error = function(e) reschedule() +) +}\if{html}{\out{</div>}} + +Below \code{cepis_error} the split is by \strong{the decision you have to make}, not +by the HTTP status that caused it:\tabular{lll}{ + class \tab when \tab does retrying help? \cr + \code{cepis_invalid_cep} \tab not 8 digits \tab no \cr + \code{cepis_not_found} \tab well-formed, not in the database \tab no \cr + \code{cepis_rate_limited} \tab 429 \tab yes, later \cr + \code{cepis_server_error} \tab 5xx \tab yes, later \cr + \code{cepis_network_error} \tab DNS, connection, timeout, TLS \tab yes, later \cr + \code{cepis_invalid_response} \tab unintelligible response \tab probably not \cr +} + + +That split is why \code{cepis_not_found} is not "the HTTP 404 condition": it is +also signalled with no request made at all, when the CEP is malformed +before it ever leaves the machine. + +Each condition carries the fields a caller needs to act on it: +\code{cepis_rate_limited} has \code{retry_after} (seconds the server asked for, or +\code{NULL}), \code{cepis_server_error} has \code{status}, \code{cepis_network_error} has +\code{url}, and \code{cepis_invalid_cep} has \code{value}, the input as it arrived. + +\code{cepis_invalid_response} almost always means something between you and the +API is answering instead of it — a captive Wi-Fi portal, a corporate +proxy, an HTML error page. Useful as a diagnosis: the problem is not in +your code. +} diff --git a/man/cepis_geo.Rd b/man/cepis_geo.Rd new file mode 100644 index 0000000..3c92979 --- /dev/null +++ b/man/cepis_geo.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/models.R +\name{cepis_geo} +\alias{cepis_geo} +\title{The coordinate of a CEP, when the database has one} +\description{ +The \code{geo} field of a \link{cepis_address}, a plain list of class \code{cepis_geo}. +The point is the \strong{median} of the coordinates of that CEP's addresses, +not the mean: one badly geocoded address 40 km away shifts a mean and does +not move a median. +} +\section{Fields}{ + +\describe{ +\item{\code{lat}, \code{lon}}{decimal degrees, WGS 84.} +\item{\code{raio_m}}{the radius, in metres, containing 90\% of that CEP's +addresses.} +\item{\code{precisao}}{\code{"logradouro"} or \code{"localidade"} — see below.} +\item{\code{is_precise}}{\code{TRUE} when \code{precisao} is \code{"logradouro"}. Derived, +not sent by the API.} +} +} + +\section{Always check precisao before measuring distance}{ + +There are two kinds of point, and the difference between them is tens of +kilometres:\tabular{lll}{ + \code{precisao} \tab typical \code{raio_m} \tab what the point is \cr + \code{logradouro} \tab 110-140 m \tab the stretch of street: good for maps and for distance \cr + \code{localidade} \tab 7-40 km \tab the municipality centroid, because the CEP \emph{is} the whole city \cr +} + + +\code{raio_m} exists precisely so that error cannot pass unnoticed. +} + diff --git a/man/cepis_health.Rd b/man/cepis_health.Rd new file mode 100644 index 0000000..dc00d8b --- /dev/null +++ b/man/cepis_health.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/models.R +\name{cepis_health} +\alias{cepis_health} +\title{The answer of \code{GET /health}} +\description{ +A plain list of class \code{cepis_health}, returned by \code{\link[=cep_health]{cep_health()}}. Good for +two things: checking that the API answers, and knowing \strong{which version of +the database} is live. The DNE database changes every two weeks; \code{dne} +identifies it. +} +\section{Fields}{ + +\describe{ +\item{\code{status}}{\code{"ok"} when the API reports itself healthy.} +\item{\code{ok}}{\code{status == "ok"}. Derived, not sent by the API.} +\item{\code{dne}}{identifier of the fortnightly database.} +\item{\code{ceps}}{how many CEPs it holds.} +\item{\code{geo}}{how many of those carry a coordinate.} +\item{\code{base_gerada_em}}{when the base was generated, UTC.} +} +} + diff --git a/man/formatted_cep.Rd b/man/formatted_cep.Rd new file mode 100644 index 0000000..7f77b4e --- /dev/null +++ b/man/formatted_cep.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/models.R +\name{formatted_cep} +\alias{formatted_cep} +\title{Add the mask to a CEP} +\usage{ +formatted_cep(x) +} +\arguments{ +\item{x}{A \link{cepis_address} or a character vector of CEPs.} +} +\value{ +A character vector of masked CEPs. A value that is not 8 digits is +returned unchanged, because this is a formatting helper and not a +validator — \code{\link[=normalize_cep]{normalize_cep()}} is the validator. +} +\description{ +\code{"01001000"} becomes \code{"01001-000"}. The API always answers unmasked; +formatting is presentation, and it lives here so it does not become a +repeated \code{paste0()} in every project that uses this package. +} +\examples{ +formatted_cep("01001000") + +} diff --git a/man/normalize_cep.Rd b/man/normalize_cep.Rd new file mode 100644 index 0000000..6f9b462 --- /dev/null +++ b/man/normalize_cep.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/normalize.R +\name{normalize_cep} +\alias{normalize_cep} +\title{Return the 8 digits of a CEP, accepting the mask} +\usage{ +normalize_cep(value) +} +\arguments{ +\item{value}{A length-one character vector. Numbers are rejected on +purpose: \code{1001000} has already lost the leading zero that makes +\code{"01001000"} a CEP. Convert with \code{sprintf("\%08d", x)} first.} +} +\value{ +The 8 digits, as a length-one character vector. +} +\description{ +\code{"01001-000"}, \code{"01001000"}, \code{"01001.000"} and \code{" 01001-000 "} all become +\code{"01001000"}. + +This runs \strong{before} any request: a 7-digit CEP is the caller's bug, and +spending a round trip for the server to say so wastes both sides' time. +} +\section{Conditions}{ + +Signals \link[=cepis_conditions]{cepis_invalid_cep} unless exactly 8 digits +remain. +} + +\examples{ +normalize_cep("01001-000") + +} |