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 Int

Dictionaries & 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   # โœ… Passes

Collections & 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:

FeatureArgCheck.jl (@argcheck)VerifyMacros.jl (@verify...)
PhilosophyConcise preconditionsDescriptive, specific failure context
Error TypeArgumentError (mostly)TypeError, KeyError, DimensionMismatch, etc.
MessageGeneric or manual stringAuto-generated, descriptive, and styled (colored)
Usage@argcheck x > 0@verifytype x Int or @verifykey d :id
Best ForFunction preconditionsData 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

As the following comparison demonstrates, `VerifyMacros`,
  • 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, ArgCheck
julia> 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, VerifyMacros
julia> 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

As the following example demonstrates, `VerifyMacros` further
  • deals with multiple conditions naturally
  • identifies which condition fails
julia> using ArgCheck
julia> 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 VerifyMacros
julia> D = Dict( :a=>1, 2 =>:b, :c => :3 );
julia> @verifykeys D :a :b :cERROR: KeyError: D lacks key b #= REPL[3]:1 =#
julia> using VerifyMacros
julia> 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

This also applies to the same type of condition on multiple objects
  • with ArgCheck an alternative would be to have as many lines of code as you have conditions to check
julia> using ArgCheck
julia> x = 1.0; y = 3;
julia> @argcheck x isa Float64 || y isa AbstractString
julia> using VerifyMacros
julia> 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

And you can combine multiple checks
  • with the caveat that you need to use the catchall @verifytrues
julia> using ArgCheck
julia> 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 VerifyMacros
julia> 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

MacroDescription
@verifyMeta macro (see above)
@verifytypeCheck type of value (isa)
@verifykeyCheck key in dictionary (haskey)
@verifypropertyCheck property of object (hasproperty)
@verifyfieldCheck field of type (hasfield)
@verifyinCheck membership (in)
@verifysupertypeCheck subtype relation (<:)
@verifyaxesCheck array axes
@verifysizeCheck array size
@verifylengthCheck collection length
@verifyequalCheck equality (==)
@verifyisfileCheck file existence
@verifyisdirCheck directory existence
@verifytrueGeneric assertion

All macros have plural versions (e.g., @verifytypes) for batch checking.

Reference

VerifyMacros.@define_verification โ€” Macro
@define_verification(Singular, Plural, FunctionName, NArgs)

Generates the verification macros:

  1. @Singular: The main macro (e.g., @verifytype).
  2. @_Singular_internal: Internal macro for batch processing.
  3. @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) for NArgs = 2
  • func(val, name, location) for NArgs = 1
source
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

source
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.

source
VerifyMacros.@verifyequal โ€” Macro
@verifyequal(val, expected, [name])

Check that val is equal to expected (using ==). Throws a styled ArgumentError if the check fails.

source
VerifyMacros.@verifyequals โ€” Macro
@verifyequals((val, expected), ...)

Batch verification for equality. Usage: @verifyequals((val1, exp1), (val2, exp2))

source
VerifyMacros.@verifyfield โ€” Macro
@verifyfield(val, field, [name])

Check that val has field field (using hasfield). Throws a styled KeyError if the check fails.

source
VerifyMacros.@verifyfields โ€” Macro
@verifyfields((val, field), ...)

Batch verification for fields. Usage: @verifyfields((val1, field1), (val2, field2))

source
VerifyMacros.@verifyin โ€” Macro
@verifyin(val, collection, [name])

Check that val is in collection (using val โˆˆ collection). Throws a styled ArgumentError if the check fails.

source
VerifyMacros.@verifyins โ€” Macro
@verifyins((val, collection), ...)

Batch verification for membership. Usage: @verifyins((val1, col1), (val2, col2))

source
VerifyMacros.@verifyisdir โ€” Macro
@verifyisdir(path, [name])

Check that path is an existing directory (using isdir). Throws a styled SystemError if the check fails.

source
VerifyMacros.@verifyisdirs โ€” Macro
@verifyisdirs(path, ...)

Batch verification for directories. Usage: @verifyisdirs(path1, path2) or @verifyisdirs((path1, name1), ...)

source
VerifyMacros.@verifyisfile โ€” Macro
@verifyisfile(path, [name])

Check that path is an existing file (using isfile). Throws a styled SystemError if the check fails.

source
VerifyMacros.@verifyisfiles โ€” Macro
@verifyisfiles(path, ...)

Batch verification for files. Usage: @verifyisfiles(path1, path2) or @verifyisfiles((path1, name1), ...)

source
VerifyMacros.@verifykey โ€” Macro
@verifykey(dict, key, [name])

Check that dict has key key (using haskey). Throws a styled KeyError if the check fails.

source
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.

source
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.

source
VerifyMacros.@verifyproperty โ€” Macro
@verifyproperty(val, prop, [name])

Check that val has property prop (using hasproperty). Throws a styled KeyError if the check fails.

source
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.

source
VerifyMacros.@verifytrues โ€” Macro
@verifytrues(cond, ...)

Batch verification for boolean conditions. Usage: @verifytrues(cond1, cond2) or @verifytrues((cond1, name1), ...)

source
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.

source