VerifyMacros.jl
Documentation for VerifyMacros.jl.
VerifyMacros.jl is your toolkit for runtime verification with style. ๐
Stop writing boilerplate checks and manual error messages. Use VerifyMacros to assert conditions and get descriptive, color-coded error output that tells you exactly what went wrong.
๐ฆ Installation
using Pkg
Pkg.add("VerifyMacros")๐ Usage
๐ Single Verifications
Validate types, keys, dimensions, and more.
Types & Structure
using VerifyMacros
x = 1.0
@verifytype x Float64 # โ
Passes
@verifytype x Int # โ Throws: TypeError: x is of type Float64; was expecting a IntDictionaries & Properties
d = Dict(:a => 1)
@verifykey d :a # โ
Passes
@verifykey d :b # โ Throws: KeyError: d lacks key :b
struct Obj; p; end
o = Obj(1)
@verifyproperty o :p # โ
PassesCollections & Dimensions
A = [1, 2]
@verifyaxes A (1:2,) # โ
Passes
@verifyin 1 A # โ
Passes
@verifylength A 2 # โ
Passes๐ฆ Batch Verifications
Check everything at once. Clean and efficient.
# Check multiple types
@verifytypes (x, Float64) (1, Int)
# Check multiple keys
@verifykeys (d, :a) (d, :b)
# OR shorthand for one dict:
@verifykeys(d, :a, :b, :c)
# Check multiple files
@verifyisfiles ("config.json",) ("data.csv",)๐ ๏ธ The Meta-Macro: @verify
If you prefer a single entry point, use @verify. The first argument is a symbol (e.g., :type, :keys) which determines which check to run.
@verify :type x Float64 # expands to @verifytype x Float64
@verify :keys d :a :b # expands to @verifykeys d :a :b
@verify :true 1 < 2 # expands to @verifytrue 1 < 2๐ Comparison with ArgCheck.jl
bird's eye view
You might know ArgCheck.jl, which is excellent for concise argument checking. Here's how VerifyMacros.jl differs:
| Feature | ArgCheck.jl (@argcheck) | VerifyMacros.jl (@verify...) |
|---|---|---|
| Philosophy | Concise preconditions | Descriptive, specific failure context |
| Error Type | ArgumentError (mostly) | TypeError, KeyError, DimensionMismatch, etc. |
| Message | Generic or manual string | Auto-generated, descriptive, and styled (colored) |
| Usage | @argcheck x > 0 | @verifytype x Int or @verifykey d :id |
| Best For | Function preconditions | Data validation, debugging complex state, helpful errors |
Choose VerifyMacros.jl when you want your users (or future you) to know exactly why a check failed without digging into the stack trace.
examples
example 1
- provides a detailed error message without further user interaction
- colors are used to make it immediately apparent what the error is
- identifies where in the code the error is
julia> using Random, ArgCheckjulia> left = "WEEfgfweew11"; right = "fsdRweWERERGere";julia> D = Dict( j => left * randstring( 4 ) * right for j โ 1:40 );julia> needle = left * "abcd" * right"WEEfgfweew11abcdfsdRweWERERGere"julia> @argcheck haskey( D, needle )ERROR: ArgumentError: haskey(D, needle) must hold. Got D => Dict(5=>"WEEfgfweew11FuHvfsdRweWERERGere", 16=>"WEEfgfweew11ZdoifsdRweWERERGere", 20=>"WEEfgfweew11ClnVfsdRweWERERGere", 35=>"WEEfgfweew11NwPXfsdRweWERERGere", 12=>"WEEfgfweew117FumfsdRweWERERGere", 24=>"WEEfgfweew11CILnfsdRweWERERGere", 28=>"WEEfgfweew11G5NefsdRweWERERGere", 8=>"WEEfgfweew11aJgtfsdRweWERERGere", 17=>"WEEfgfweew11VKgqfsdRweWERERGere", 30=>"WEEfgfweew11JZTqfsdRweWERERGere"โฆ) needle => "WEEfgfweew11abcdfsdRweWERERGere"
julia> using Random, VerifyMacrosjulia> left = "WEEfgfweew11"; right = "fsdRweWERERGere";julia> D = Dict( j => left * randstring( 4 ) * right for j โ 1:40 );julia> needle = left * "abcd" * right"WEEfgfweew11abcdfsdRweWERERGere"julia> @verifykey D needleERROR: KeyError: D lacks key WEEfgfweew11abcdfsdRweWERERGere #= REPL[5]:1 =#
example 2
- deals with multiple conditions naturally
- identifies which condition fails
julia> using ArgCheckjulia> D = Dict( :a=>1, 2 =>:b, :c => :3 );julia> @argcheck haskey( D, :a ) && haskey( D, :b ) && haskey( D, :c )ERROR: ArgumentError: haskey(D, :a) && (haskey(D, :b) && haskey(D, :c)) must hold.
julia> using VerifyMacrosjulia> D = Dict( :a=>1, 2 =>:b, :c => :3 );julia> @verifykeys D :a :b :cERROR: KeyError: D lacks key b #= REPL[3]:1 =#
julia> using VerifyMacrosjulia> D = Dict( :a=>1, 2 =>:b, :c => :3 );julia> @verify :keys D :a :b :cERROR: KeyError: D lacks key b #= REPL[3]:1 =#
example 3
- with ArgCheck an alternative would be to have as many lines of code as you have conditions to check
julia> using ArgCheckjulia> x = 1.0; y = 3;julia> @argcheck x isa Float64 || y isa AbstractString
julia> using VerifyMacrosjulia> x = 1.0; y = 3;julia> @verifytypes ( x, Float64) ( y, AbstractString )ERROR: TypeError: y is of type Int64; was expecting a AbstractString #= REPL[3]:1 =#
example 4
julia> using ArgCheckjulia> D = Dict( :a=>1, 2 =>:b, :c => :3 );julia> @argcheck haskey( D, :a ) && D[:a] isa AbstractFloatERROR: ArgumentError: haskey(D, :a) && D[:a] isa AbstractFloat must hold.
julia> using VerifyMacrosjulia> D = Dict( :a=>1, 2 =>:b, :c => :3 );julia> @verifytrues haskey( D, :a ) D[:a] isa AbstractFloatERROR: AssertionError: D[:a] isa AbstractFloat is not true #= REPL[3]:1 =#
๐ ๏ธ Available Macros
| Macro | Description |
|---|---|
@verify | Meta macro (see above) |
@verifytype | Check type of value (isa) |
@verifykey | Check key in dictionary (haskey) |
@verifyproperty | Check property of object (hasproperty) |
@verifyfield | Check field of type (hasfield) |
@verifyin | Check membership (in) |
@verifysupertype | Check subtype relation (<:) |
@verifyaxes | Check array axes |
@verifysize | Check array size |
@verifylength | Check collection length |
@verifyequal | Check equality (==) |
@verifyisfile | Check file existence |
@verifyisdir | Check directory existence |
@verifytrue | Generic assertion |
All macros have plural versions (e.g., @verifytypes) for batch checking.
Reference
VerifyMacros.@define_verificationVerifyMacros.@verifyVerifyMacros.@verifyaxesVerifyMacros.@verifyaxesmVerifyMacros.@verifyequalVerifyMacros.@verifyequalsVerifyMacros.@verifyfieldVerifyMacros.@verifyfieldsVerifyMacros.@verifyinVerifyMacros.@verifyinsVerifyMacros.@verifyisdirVerifyMacros.@verifyisdirsVerifyMacros.@verifyisfileVerifyMacros.@verifyisfilesVerifyMacros.@verifykeyVerifyMacros.@verifykeysVerifyMacros.@verifylengthVerifyMacros.@verifylengthsVerifyMacros.@verifypropertiesVerifyMacros.@verifypropertyVerifyMacros.@verifysizeVerifyMacros.@verifysizesVerifyMacros.@verifysupertypeVerifyMacros.@verifysupertypesVerifyMacros.@verifytrueVerifyMacros.@verifytruesVerifyMacros.@verifytypeVerifyMacros.@verifytypes
VerifyMacros.@define_verification โ Macro
@define_verification(Singular, Plural, FunctionName, NArgs)Generates the verification macros:
@Singular: The main macro (e.g.,@verifytype).@_Singular_internal: Internal macro for batch processing.@Plural: Batch verification macro (e.g.,@verifytypes).
Arguments:
Singular: Name of the singular macro (symbol).Plural: Name of the plural macro (symbol).FunctionName: Name of the backend function to call (symbol).NArgs: Number of arguments to verify (1 or 2).
The backend function is expected to have the signature:
func(val, expected, name, location)forNArgs = 2func(val, name, location)forNArgs = 1
VerifyMacros.@verify โ Macro
@verify :action args...General purpose verification macro that delegates to specific @verify... macros. The first argument must be a symbol (e.g., :type, :keys) which is appended to "verify" to determine the target macro.
Example: @verify :type x Int expands to @verifytype x Int @verify :keys d :a :b expands to @verifykeys d :a :b
VerifyMacros.@verifyaxes โ Macro
@verifyaxes(val, ax, [name])Check that val has axes ax (using axes(val) == ax). Throws a styled DimensionMismatch if the check fails.
VerifyMacros.@verifyaxesm โ Macro
@verifyaxesm((val, ax), ...)Batch verification for axes. Usage: @verifyaxesm((val1, ax1), (val2, ax2))
VerifyMacros.@verifyequal โ Macro
@verifyequal(val, expected, [name])Check that val is equal to expected (using ==). Throws a styled ArgumentError if the check fails.
VerifyMacros.@verifyequals โ Macro
@verifyequals((val, expected), ...)Batch verification for equality. Usage: @verifyequals((val1, exp1), (val2, exp2))
VerifyMacros.@verifyfield โ Macro
@verifyfield(val, field, [name])Check that val has field field (using hasfield). Throws a styled KeyError if the check fails.
VerifyMacros.@verifyfields โ Macro
@verifyfields((val, field), ...)Batch verification for fields. Usage: @verifyfields((val1, field1), (val2, field2))
VerifyMacros.@verifyin โ Macro
@verifyin(val, collection, [name])Check that val is in collection (using val โ collection). Throws a styled ArgumentError if the check fails.
VerifyMacros.@verifyins โ Macro
@verifyins((val, collection), ...)Batch verification for membership. Usage: @verifyins((val1, col1), (val2, col2))
VerifyMacros.@verifyisdir โ Macro
@verifyisdir(path, [name])Check that path is an existing directory (using isdir). Throws a styled SystemError if the check fails.
VerifyMacros.@verifyisdirs โ Macro
@verifyisdirs(path, ...)Batch verification for directories. Usage: @verifyisdirs(path1, path2) or @verifyisdirs((path1, name1), ...)
VerifyMacros.@verifyisfile โ Macro
@verifyisfile(path, [name])Check that path is an existing file (using isfile). Throws a styled SystemError if the check fails.
VerifyMacros.@verifyisfiles โ Macro
@verifyisfiles(path, ...)Batch verification for files. Usage: @verifyisfiles(path1, path2) or @verifyisfiles((path1, name1), ...)
VerifyMacros.@verifykey โ Macro
@verifykey(dict, key, [name])Check that dict has key key (using haskey). Throws a styled KeyError if the check fails.
VerifyMacros.@verifykeys โ Macro
@verifykeys((dict1, key1), (dict2, key2), ...)
@verifykeys(dict, key1, key2, ...)Batch verify multiple key checks. Usage 1: Each argument is a tuple of (dict, key[, name]). Equivalent to multiple @verifykey calls. Usage 2: First argument is the dictionary, subsequent arguments are keys. Verify that dict contains all specified keys.
VerifyMacros.@verifylength โ Macro
@verifylength(val, len, [name])Check that val has length len (using length(val) == len). Throws a styled DimensionMismatch if the check fails.
VerifyMacros.@verifylengths โ Macro
@verifylengths((val, len), ...)Batch verification for lengths. Usage: @verifylengths((val1, len1), (val2, len2))
VerifyMacros.@verifyproperties โ Macro
@verifyproperties((val, prop), ...)Batch verification for properties. Usage: @verifyproperties((val1, prop1), (val2, prop2))
VerifyMacros.@verifyproperty โ Macro
@verifyproperty(val, prop, [name])Check that val has property prop (using hasproperty). Throws a styled KeyError if the check fails.
VerifyMacros.@verifysize โ Macro
@verifysize(val, size, [name])Check that val has size size (using size(val) == size). Throws a styled DimensionMismatch if the check fails.
VerifyMacros.@verifysizes โ Macro
@verifysizes((val, size), ...)Batch verification for sizes. Usage: @verifysizes((val1, size1), (val2, size2))
VerifyMacros.@verifysupertype โ Macro
@verifysupertype(T, Sup, [name])Check that T is a subtype of Sup (using <:). Throws a styled TypeError if the check fails.
VerifyMacros.@verifysupertypes โ Macro
@verifysupertypes((T, Sup), ...)Batch verification for supertypes. Usage: @verifysupertypes((T1, Sup1), (T2, Sup2))
VerifyMacros.@verifytrue โ Macro
@verifytrue(cond, [name])Check that cond is true. Throws a styled AssertionError if the check fails.
VerifyMacros.@verifytrues โ Macro
@verifytrues(cond, ...)Batch verification for boolean conditions. Usage: @verifytrues(cond1, cond2) or @verifytrues((cond1, name1), ...)
VerifyMacros.@verifytype โ Macro
@verifytype(val, T, [name])Check that val is of type T (using <:). If name is omitted, it defaults to the string representation of val. Throws a styled error if the check fails.
VerifyMacros.@verifytypes โ Macro
@verifytypes((val, T), ...)Batch verification for types. Usage: @verifytypes((val1, T1), (val2, T2))