selkamand / assertions Goto Github PK
View Code? Open in Web Editor NEWAssertions with Beautiful and Customizable Error Messages
Home Page: https://selkamand.github.io/assertions/
License: Other
Assertions with Beautiful and Customizable Error Messages
Home Page: https://selkamand.github.io/assertions/
License: Other
I think when creating an assertion, it would be better to just use the original argument names from the function your wrapping.
This would unify the way users can access argument names using glue expressions in default_error_msg
arguments
is_string_advanced and is_number_advanced are exported, but they're pretty much useless to most users. ensure any advanced 'is' functions are not exported.
assert_function_expects_specific_arguments(func, names)
assert function expects arguments with specific names .
We need to be able to check if all elements of a vector are one of a valid set
look into is_subset
maybe create assert_subset
could also be named something like assert_all_are_in
Still refers to assert_create_advanced
Robust assertion packages should have extremely high unit-test coverage
Unfortunately, because assertion function from this package are created with a function assert_create
the unit tests aren't considered to cover the assertion creation statements
difference between assert_character and assert_character_vector is obscure
Add documentation indicating the difference and a matrix example passing in assert_character but failing in assert_character_vector
assert_greater_than can work on vectors or numbers. If using vector input, Produce an informative error messages that tell the user exactly which comparisons failed
assert_function_argument_count() - find a better name
see https://community.rstudio.com/t/count-number-of-arguments-in-function/156752/4 for a discussion on implementation
If a user calls assert_includes(x, required, msg = "please ensure 'x' includes these very important elements: {required}")
they probably assume evuation should have access to 'required'. By default this is not the case
For user msg overrides we should evaluate in their environment. For assertion creation functions, in which were defining a default error message, evaluation can remain as is.
we have arg_name to access deparse(substitute(x)) - called from within the assertion,
but how can we get the relevant 'name' of arg2 such that if a user calls assert_test(1:5, 10:12)
the error message says
'1:5 is our first argument, 10:12 is our second'
# Create an assertion-powering function
test_advanced <- function(x, arg2){
return("{arg_name} is our first argument. {name(arg2)} is our second.")
}
assert_test <- assert_create(
test_advanced
)
might need to make a new function
assert_create_advanced()
that only takes a function, and expects func to return TRUE if assertion passes, or a STRING if it should throw an error (where STRING = the error message)
Its just too useful to not include when building assertions that can take vector inputs, since the error message often needs to list all the elements that fail (or the count of how many failed if there are too many vector inputs)
new format: what argument does (type or default)
Current implementation is not OS-independent. The safest way to test if a file is readable is actually to just try and read a small part of it in a trycatch. Should remove and consider re-implementing later
set operation assertions
ensure that required / illegal elements are of the same type or throw error
Example
cli::test_that_cli("assert_list() works", configs = "plain", {
# Works for lists
expect_true(assert_list(list(1, 2, 3)))
expect_true(assert_list(list()))
# Aborts for non-list objects
expect_snapshot(assert_list(1), error = TRUE)
expect_snapshot(assert_list(1.5), error = TRUE)
expect_snapshot(assert_list('abc'), error = TRUE)
expect_snapshot(assert_list(c(1, 2, 3)), error= TRUE)
expect_snapshot(assert_list(mtcars), error= TRUE)
expect_snapshot(assert_list(factor(c(1, 2, 3))), error = TRUE)
# Error messages use variable name of passed arguments
y <- c(1, 2, 3)
expect_error(assert_list(y), "'y'", fixed = TRUE)
# Custom error messages work
expect_error(assert_list(1, msg = "Custom error message"), "Custom error message")
})
Currently we evaluate custom and predefined error messages as glue strings. This can include code written between curled braces. Now code that gets evaluated should only ever be written by package devs. The question is, can an end-user by supplying string arguments that contain code snippets somehow get it evaluated.
We should thoroughly test this for prebuilt, and custom built functions and see if we can get user - injected code available. If so we'll have to switch glue
to glue_safe
which evaluates variables but won't run code.
fix assert_file_extension and other file functions to take advantage ability of func to return strings defining error messages
What assertions should work on vectors vs scalars.
Its a tricky problem and worth doing more thought to devise a general rule and function naming structure that will work intuitively for end-users
Is assert_has_no_duplicates
and friends a little verbose?
I think assert_no_duplicates
would suffice
Similarly: assert_has_no_missing_values
would be better as assert_no_missing_values or even assert_no_missing
assert_matches_regex
and friends
Useful when implementing overwrite flags
a = 1
b = 2:1000
assert_subset(a, b) #slow
a %in% b #fast
In our examples there are lots of \dontrun{assert_number()} style code to get around the fact if examples are run they will throw errors
I need to dig up the cran additional checks checklist which had instructions on best ways to deal with this ... maybe I'll wrap assertions in try?
assertive and assertthat both solve this problem by using a helper/different function. For example in assertthat you see a lot of 'see_if' which does the same thing but doesnt throw an error. I could add a function like that ... but would prefer not to bloat the interface
assert_has_no_missing_values
extra single quote
''x' must have no missing values! Found
library(assertions)
# Fails when assert is called in a function
foo <- function(x){
bob <- 10
assert(length(bob) == 2, msg = "bob should be 2, not {bob}")
}
foo()
#> Error in "fun(..., .envir = .envir)": ! Could not evaluate cli `{}` expression: `bob`.
#> Caused by error in `eval(expr, envir = envir)`:
#> ! object 'bob' not found
# Works when assert not called in a function
bob <- 10
assert(length(bob) == 2, msg = "bob should be 2, not {bob}")
#> Error:
#> ! bob should be 2, not 10
Created on 2023-02-24 by the reprex package (v2.0.1)
Make assert_file_exists
and assert_directory_exists
scalar assertions
Create new assert_all_files_exist
and assert_all_directories_exist
functions
I know that its tempting to just name these assert_files_exist
and assert_directories_exist
but the all
is part of our general naming rules for vectorised functions, so will the API more consistent. See #15 for details
contain an invalid value
contains should always be plural
see #26 for context.
We should build
expect_
statements that test each assertion)Some potential options for badges here:
basically we just need to produce a json file somewhere in this repo that we could point to.
https://css-tricks.com/adding-custom-github-badges-to-your-repo/
Could use inherits to check if class/subclass
Could use is
to check direct subclass match
Test failed:
'C:\Users\RUNNER~1\AppData\Local\Temp\RtmpmItq67/working_dir\RtmpcBAB6t\file1dcd4d59fc' does not have permission: execute
I think this is because of the colon. Just need to add it to our regex as a valid path character
Also a -> an
based on whether class starts with vowel. many error messages need either this or a rewording
Number of issues resolved
Also consider name:
assert_number_whole
First release:
usethis::use_cran_comments()
Title:
and Description:
@return
and @examples
Authors@R:
includes a copyright holder (role 'cph')Prepare for release:
git pull
devtools::build_readme()
urlchecker::url_check()
devtools::check(remote = TRUE, manual = TRUE)
devtools::check_win_devel()
rhub::check_for_cran()
git push
Submit to CRAN:
usethis::use_version('minor')
devtools::submit_cran()
Wait for CRAN...
git push
usethis::use_github_release()
usethis::use_dev_version()
usethis::use_news_md()
git push
R universe build of the assertions package leads to a LaTeX Error due to the use of unicode character โฅ (U+2265)
assert_function_supports_variable_arguments(func)
assert function contains dotdotdot argument (...) that allows variable arguments to be passed#20 solution works so well for user-suppled msg's, lets try and add a similar solution for assert_create
default_error_msg AND func
-defined error messages should have access to the environment of func
The code below SHOULD ideally work, but it doesn't, because the cli_abort environment is NOT the function(mutation_types)
environment.
assert_all_mutations_are_valid_so <- assertions::assert_create(
func = function(mutation_types) {
unique_mutation_types <- unique(unlist(strsplit(mutation_types, split = "&")))
unknown_mutation_types <- unique_mutation_types[!unique_mutation_types %in% mutation_types_so()]
if(length(unique_mutation_types) > 0 ){
"Found {.strong {length(unknown_mutation_types)}} mutation type{?s} which {?was/were} NOT valid SO terms: [{.strong {unknown_mutation_types}}]"
}}
)
Lets forget about 'arg_name' and 'arg_value' and just let the user build error messages in the way that makes the most sense naturally
assert_file_exists
assert_file_extension
assert_is_directory
etc
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.