From 98d148be33d2dbb78c414d92e585e0a49cc50182 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Tue, 15 Oct 2024 18:48:05 +0000 Subject: [PATCH] build based on 1fca5d9 --- dev/.documenter-siteinfo.json | 2 +- dev/ambiguities/index.html | 2 +- dev/deps_compat/index.html | 2 +- dev/exports/index.html | 2 +- dev/index.html | 2 +- dev/objects.inv | Bin 1752 -> 1781 bytes dev/persistent_tasks/index.html | 2 +- dev/piracies/index.html | 2 +- dev/project_extras/index.html | 2 +- dev/release-notes/index.html | 2 +- dev/search_index.js | 2 +- dev/stale_deps/index.html | 2 +- dev/test_all/index.html | 2 +- dev/unbound_args/index.html | 2 +- 14 files changed, 13 insertions(+), 13 deletions(-) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 177f79ab..cb6c4ac 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.0","generation_timestamp":"2024-10-10T14:41:28","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.0","generation_timestamp":"2024-10-15T18:48:00","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/dev/ambiguities/index.html b/dev/ambiguities/index.html index 997f856..ea11e05 100644 --- a/dev/ambiguities/index.html +++ b/dev/ambiguities/index.html @@ -9,4 +9,4 @@ Possible fix, define f(::Int64, ::Int64)

This will throw an MethodError because both methods are equally specific. The solution is to add a third method:

f(x::Int, y::Int) = ? # `?` is dependent on the use case, most times it will be `1` or `2`

Test function

Aqua.test_ambiguitiesFunction
test_ambiguities(package::Union{Module, PkgId})
-test_ambiguities(packages::Vector{Union{Module, PkgId}})

Test that there is no method ambiguities in given package(s). It calls Test.detect_ambiguities in a separated clean process to avoid false-positives.

Keyword Arguments

  • broken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.
  • color::Union{Bool, Nothing} = nothing: Enable/disable colorful output if a Bool. nothing (default) means to inherit the setting in the current process.
  • exclude::AbstractVector = []: A vector of functions or types to be excluded from ambiguity testing. A function means to exclude all its methods. A type means to exclude all its methods of the callable (sometimes also called "functor") and the constructor. That is to say, MyModule.MyType means to ignore ambiguities between (::MyType)(x, y::Int) and (::MyType)(x::Int, y).
  • recursive::Bool = true: Passed to Test.detect_ambiguities. Note that the default here (true) is different from detect_ambiguities. This is for testing ambiguities in methods defined in all sub-modules.
  • Other keyword arguments such as imported and ambiguous_bottom are passed to Test.detect_ambiguities as-is.
source
+test_ambiguities(packages::Vector{Union{Module, PkgId}})

Test that there is no method ambiguities in given package(s). It calls Test.detect_ambiguities in a separated clean process to avoid false-positives.

Keyword Arguments

source diff --git a/dev/deps_compat/index.html b/dev/deps_compat/index.html index 46196a5..71bfdfc 100644 --- a/dev/deps_compat/index.html +++ b/dev/deps_compat/index.html @@ -1,2 +1,2 @@ -Compat entries · Aqua.jl

Compat entries

In your Project.toml you can (and should) use compat entries to specify with which versions of Julia and your dependencies your package is compatible with. This is important to ease the installation and upgrade of your package for users, and to keep everything working in the case of breaking changes in Julia or your dependencies.

For more details, see the Pkg docs.

Test function

Aqua.test_deps_compatFunction
Aqua.test_deps_compat(package)

Test that the Project.toml of package has a compat entry for each package listed under deps and for julia.

Arguments

  • packages: a top-level Module, a Base.PkgId, or a collection of them.

Keyword Arguments

Test choosers

  • check_julia = true: If true, additionally check for a compat entry for "julia".
  • check_extras = true: If true, additionally check "extras". A NamedTuple can be used to pass keyword arguments with test options (see below).
  • check_weakdeps = true: If true, additionally check "weakdeps". A NamedTuple can be used to pass keyword arguments with test options (see below).

Test options

If these keyword arguments are set directly, they only apply to the standard test for "deps". To apply them to "extras" and "weakdeps", pass them as a NamedTuple to the corresponding check_$x keyword argument.

  • broken::Bool = false: If true, it uses @test_broken instead of @test for "deps".
  • ignore::Vector{Symbol}: names of dependent packages to be ignored.
source
+Compat entries · Aqua.jl

Compat entries

In your Project.toml you can (and should) use compat entries to specify with which versions of Julia and your dependencies your package is compatible with. This is important to ease the installation and upgrade of your package for users, and to keep everything working in the case of breaking changes in Julia or your dependencies.

For more details, see the Pkg docs.

Test function

Aqua.test_deps_compatFunction
Aqua.test_deps_compat(package)

Test that the Project.toml of package has a compat entry for each package listed under deps and for julia.

Arguments

  • packages: a top-level Module, a Base.PkgId, or a collection of them.

Keyword Arguments

Test choosers

  • check_julia = true: If true, additionally check for a compat entry for "julia".
  • check_extras = true: If true, additionally check "extras". A NamedTuple can be used to pass keyword arguments with test options (see below).
  • check_weakdeps = true: If true, additionally check "weakdeps". A NamedTuple can be used to pass keyword arguments with test options (see below).

Test options

If these keyword arguments are set directly, they only apply to the standard test for "deps". To apply them to "extras" and "weakdeps", pass them as a NamedTuple to the corresponding check_$x keyword argument.

  • broken::Bool = false: If true, it uses @test_broken instead of @test for "deps".
  • ignore::Vector{Symbol}: names of dependent packages to be ignored.
source
diff --git a/dev/exports/index.html b/dev/exports/index.html index 7674637..a2b5040 100644 --- a/dev/exports/index.html +++ b/dev/exports/index.html @@ -1,2 +1,2 @@ -Undefined exports · Aqua.jl
+Undefined exports · Aqua.jl
diff --git a/dev/index.html b/dev/index.html index 79c3661..34d14e5 100644 --- a/dev/index.html +++ b/dev/index.html @@ -25,4 +25,4 @@ deps_compat=(ignore=[:SomeOtherPackage],), piracies=false, ) -end

Note, that for all tests with no explicit options provided, the default options are used.

For more details on the options, see the respective functions here.

Examples

The following is a small selection of packages that use Aqua.jl:

+end

Note, that for all tests with no explicit options provided, the default options are used.

For more details on the options, see the respective functions here.

Examples

The following is a small selection of packages that use Aqua.jl:

diff --git a/dev/objects.inv b/dev/objects.inv index 90e94b214738cb430bbaeeefcb4403a8edd560c4..7d075ca9e80f3a988c4b0bca3c25e25ece5ce4d1 100644 GIT binary patch delta 1682 zcmV;D25tG+4fPF>KLI(BKs z%_K@?$&;uw{`WnSdO6aL6IB9?L?ZPZPmk`7cgG~#@@Ge%F7<$>NVm5UZspv(+T{ z2)|ANxWOvGZLI`cHEO^mC<1?Lfx!|hQ!hyLB%!36bM(ii^~W~###RB;S$6T2@A4|ZH+R9;e?vD zdd~Tri{$Bz?n<3{FRpGbSel4~94O1GVA+3$Q}AS}RHl2j`Nr<;@A0mA zf!T^qf)%{+N(zI2S2yrS3#=#332n3?5>Bpe6p*wK0uZ7gq=9HFu{YV50_r(i@rKxn zhxVdAE(XZ4ZN)S8qJ?QI9^Q)<76b7R2IAUVd=GxT7>LJaAa1=yD`PMaH{PP=3 z8%@}5G+uw$FU*ExZ!{s=XtXkjfw0?X)SNS&LXt}lc~wy9OXY8tYuoda*+-(rh#Vst z&T|5(_LP0 z&;Z6Ct5VSQI>{2TUcbJyl1Er36YN61tX5gdBT^ob@<=1kvhD#%MA#(}A@%xM_sB^^ zh?5AVjA7j~WZmAvVqieM5w`V)6dd$oVB~ruMD>PN#$X`83fTUaYe3j0q|;8 zQl@|0oVG>m;Y2_<^;jJj!0(v~3Is{0TL^E|#N4G-NC0P5%YDy_x70H#5`a@GJrt(S zCXeg?GXd&cwlKh#;?|d76At=imLvO8jC@HeW9*ePlr03yrtr7gHLdDK!{#h~;WQfJ zh*4M1_ia(^8;&;KPR~`h&v73J> zJ`O&f)lBhG@bMOA55Lv8?cz7#8ujt@hIy*Ne0J+KqJF*YT8;A-k6PzP`^5*D*vjNt zwh6k0=o{5&;HqWNJwVh0mOTup`l7DA==BT5(b!dAgxiar6^bL&Ui9ox91ZDxL~ZXw z#`r$laWr=CBSO6ot&G8dhc~08qt1V7C_bw>XPhTacFeFkAgIJ`Q0ae^F>+9eQBXN? zl;N948DEdik6u2OFwc-o?gnIoah(nROq+J(Y%p%K!IN#;$ZXTLhm-WR1GM8~%(_d$ zwp&`O1cld83Q)I0;3?8Q<^1`~cKejS9zm%UBL>vYQCBi@58RoH(1w-dX_;K8sFcC*hk`8oy1a3l+3u72chRo;94aayJvu$C$(^22T cR1%fzCeSW3Fbp54m?-N+g*pa50GDAHwYE(|-T(jq delta 1652 zcmV-)28;Ri4cHBkKLI$AKsJ#!g-*QLrQmj~- z;+ba5CD(98_%ko|;vvcI9k#tq?yE#3yu<)B?2=`7<5bygUS*pVEAD>{03LVAjlLt- z`yD4=S;4kk@S=41%Pud30j!54X2b82jBlDDXIJEpd@WY|MHI{cnKLf=s_&;F-=;(l zI;CJKUv2o#Kz5@p`CDESxaP2QwwA9aCsylxyJG^Q(6CEB>S>;dLPB;)!PXXi&6ukh zP`7($2NWcw0N_fn^2vWhSaa}B?FhM+BTm6n&Pq)*{I>=O3v zoZRLA6`MY$Zmm-33U=>m@UJxRf*JLF>WAj?rv7KmqLan%8aaPi{4oh)we)1RoCKfX z*C_xuSOvJPm4K^84Y&kF;BPH3xWLNP3lcp^DCy=L{jq8Nu}!_PRRDFCU3}x){28qI z)T@3V)akx6y>6|d1svD~U=A!}x!EN0d$E)z*jP=_N3=SZ8S+GZ^ojaf@W zL56Lb$$W^J%o~3*38?4yGL!k(W-{;0L@8sK$-FfaIcG2sO=myP0Dx--JXn0ug8@K} z%YYQvFrbw|48UZ=fSS{O#_)y5&E|xE35OU?sA!v04}KTD3@04haKf6lMj69!LQPve z=X}XU^8C*2N}YP;OM1RMuS8DIuWrs+nuxs|D9fr~*_wY-*vV9>Om}Sk#P03yan`)R zY)L1<65eu6K*?!LJts@z@N+?QYS^7!1VCZc%dv1L2TB z6SjfI3;Tb$*>LPY6QV$)l|c-IU7%5O&U6Y%F5TxJwKU!B5I7tF`_XJ z&X*}luRHf+CfG9RIFe$2&c9Pw?JjwtcPvTaZC~*?$GjPU38)2NQiD4;@r7j-lq-8$ zR9Pm)iU-I@cv0s`N(Nm&@b%N%>ol@REsKCGV#$9ZN|tj|%C%Sqlz*O&_7)Zc1L}>itv96Lpcexp*Bc?KH?%Sa0|90raF$j*-YShNa+M3fu4W}= zYMX!4wus#yaR|pAtNjA(d#0QMK@#c~!aFrFqqK4fuvyh|-}B-<^^Ecauql-u3R7p3 zhxPvn2X!i27_gV(b}vB?4*F%5Bk!dc?Io>@5i4gXTL> zjJkTp??WFT$KHq$u4nuUb0bEmp7Ad%1_pnWCShHgfZ&)0^Ii;$T$+S!Y0@ZTFc7v3 z$T^FF#SjJ-DB0@M`~l?H3@nUfD>NBc;AAUw>NX}-4Uw*md3qzg*89Aw638X05)vHC zMSmb_j;J}ya}A(9u4&h$=B$_J8kzRErM*$c@LUUA6VI$>ia(^8;&;xcR~`h&v73J> zK6XBy)lBh`^YIpD55Lv8?cz7?8ujsYz&zGqJ{fuquV0584 zkM9$Xqp^D*5$b(tWef&99E>g;byj~v@mb9&<2-V*W4hG=P9<)gO8=vbk)2A6oXU}- z4BtG;_;zr9^!l-cd4^um66+O#8QgK?V;9&OV`W}CJ>oTP6ZpdB7#)?E^| z+0a@gD7+3*fVv$5Pm%5^=g$|m-KG3(4@xZ`F`#yiy4tyC${vkfJ4d*7wo_>K2-VIi zWmmG=(D|5NHsOhwv6G@F4??C1JJE)RkGwg6>#+H58Rnsh1w*GM_;Fm9n}~xJK?gcK y05+k>fH4fE0_O9kyEWd%EZVJiI;h%BB~h_z0_`Ll!|-u}iL%ZUsPh99P07}~o+lgt diff --git a/dev/persistent_tasks/index.html b/dev/persistent_tasks/index.html index 62b134c..a4feed9 100644 --- a/dev/persistent_tasks/index.html +++ b/dev/persistent_tasks/index.html @@ -22,4 +22,4 @@ ⋮ end

to

    while task_should_run[]
         ⋮
-    end

where

const task_should_run = Ref(true)

is a global constant in your module. Setting task_should_run[] = false from outside that while loop will cause it to terminate on its next iteration, allowing the Task to finish.

Additional information

Julia's devdocs also discuss this issue.

Test functions

Aqua.test_persistent_tasksFunction
Aqua.test_persistent_tasks(package)

Test whether loading package creates persistent Tasks which may block precompilation of dependent packages. See also Aqua.find_persistent_tasks_deps.

If you provide an optional expr, this tests whether loading package and running expr creates persistent Tasks. For example, you might start and shutdown a web server, and this will test that there aren't any persistent Tasks.

On Julia version 1.9 and before, this test always succeeds.

Arguments

  • package: a top-level Module or Base.PkgId.

Keyword Arguments

  • broken::Bool = false: If true, it uses @test_broken instead of @test.
  • tmax::Real = 5: the maximum time (in seconds) to wait after loading the package before forcibly shutting down the precompilation process (triggering a test failure).
  • expr::Expr = quote end: An expression to run in the precompile package.
Note

Aqua.test_persistent_tasks(package) creates a package with package as a dependency and runs the precompilation process. This requires that package is instantiable with the information in the Project.toml file alone. In particular, this will not work if some of package's dependencies are deved packages or are given as a local path or a git repository in the Manifest.toml.

source
+ end

where

const task_should_run = Ref(true)

is a global constant in your module. Setting task_should_run[] = false from outside that while loop will cause it to terminate on its next iteration, allowing the Task to finish.

Additional information

Julia's devdocs also discuss this issue.

Test functions

Aqua.test_persistent_tasksFunction
Aqua.test_persistent_tasks(package)

Test whether loading package creates persistent Tasks which may block precompilation of dependent packages. See also Aqua.find_persistent_tasks_deps.

If you provide an optional expr, this tests whether loading package and running expr creates persistent Tasks. For example, you might start and shutdown a web server, and this will test that there aren't any persistent Tasks.

On Julia version 1.9 and before, this test always succeeds.

Arguments

  • package: a top-level Module or Base.PkgId.

Keyword Arguments

  • broken::Bool = false: If true, it uses @test_broken instead of @test.
  • tmax::Real = 5: the maximum time (in seconds) to wait after loading the package before forcibly shutting down the precompilation process (triggering a test failure).
  • expr::Expr = quote end: An expression to run in the precompile package.
Note

Aqua.test_persistent_tasks(package) creates a package with package as a dependency and runs the precompilation process. This requires that package is instantiable with the information in the Project.toml file alone. In particular, this will not work if some of package's dependencies are deved packages or are given as a local path or a git repository in the Manifest.toml.

source
diff --git a/dev/piracies/index.html b/dev/piracies/index.html index d5bebaa..6deed94 100644 --- a/dev/piracies/index.html +++ b/dev/piracies/index.html @@ -14,4 +14,4 @@ bar(x::Vector{D}) = 4 # slightly bad (may cause invalidations) bar(x::Union{C,D}) = 5 # slightly bad (a change in PkgA may turn it into piracy) # (for example changing bar(x::C) = 1 to bar(x::Union{C,Int}) = 1) -end

The following cases are enumerated by the return values in the example above:

  1. This is the worst case of type piracy. The value of bar(C()) can be either 1 or 42 and will depend on whether PkgB is loaded or not.
  2. This is also a bad case of type piracy. bar() throws a MethodError with only PkgA available, and returns 2 with PkgB loaded. PkgA may add a method for bar() that takes no arguments in the future, and then this is equivalent to case 1.
  3. This is a moderately bad case of type piracy. bar(Union{}[]) returns 3 when PkgB is loaded, and 43 when PkgB is not loaded, although neither of the occurring types are defined in PkgB. This case is not as bad as cases 1 and 2, because it is only about behavior around Union{}, which has no instances.
  4. Depending on ones understanding of type piracy, this could be considered piracy as well. In particular, this may cause invalidations.
  5. This is a slightly bad case of type piracy. In the current form, bar(C()) returns 42 as the dispatch on Union{C,D} is less specific. However, a future change in PkgA may change this behavior, e.g. by changing bar(x::C) to bar(x::Union{C,Int}) the call bar(C()) would become ambiguous.
Note

The test function below currently only checks for cases 1 and 2.

Test function

Aqua.test_piraciesFunction
test_piracies(m::Module)

Test that m does not commit type piracies.

Keyword Arguments

  • broken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.
  • skip_deprecated::Bool = true: If true, it does not check deprecated methods.
  • treat_as_own = Union{Function, Type}[]: The types in this container are considered to be "owned" by the module m. This is useful for testing packages that deliberately commit some type piracies, e.g. modules adding higher-level functionality to a lightweight C-wrapper, or packages that are extending StatsAPI.jl.
source
+end

The following cases are enumerated by the return values in the example above:

  1. This is the worst case of type piracy. The value of bar(C()) can be either 1 or 42 and will depend on whether PkgB is loaded or not.
  2. This is also a bad case of type piracy. bar() throws a MethodError with only PkgA available, and returns 2 with PkgB loaded. PkgA may add a method for bar() that takes no arguments in the future, and then this is equivalent to case 1.
  3. This is a moderately bad case of type piracy. bar(Union{}[]) returns 3 when PkgB is loaded, and 43 when PkgB is not loaded, although neither of the occurring types are defined in PkgB. This case is not as bad as cases 1 and 2, because it is only about behavior around Union{}, which has no instances.
  4. Depending on ones understanding of type piracy, this could be considered piracy as well. In particular, this may cause invalidations.
  5. This is a slightly bad case of type piracy. In the current form, bar(C()) returns 42 as the dispatch on Union{C,D} is less specific. However, a future change in PkgA may change this behavior, e.g. by changing bar(x::C) to bar(x::Union{C,Int}) the call bar(C()) would become ambiguous.
Note

The test function below currently only checks for cases 1 and 2.

Test function

Aqua.test_piraciesFunction
test_piracies(m::Module)

Test that m does not commit type piracies.

Keyword Arguments

  • broken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.
  • skip_deprecated::Bool = true: If true, it does not check deprecated methods.
  • treat_as_own = Union{Function, Type}[]: The types in this container are considered to be "owned" by the module m. This is useful for testing packages that deliberately commit some type piracies, e.g. modules adding higher-level functionality to a lightweight C-wrapper, or packages that are extending StatsAPI.jl.
source
diff --git a/dev/project_extras/index.html b/dev/project_extras/index.html index 5ea2579..eb1f7d6 100644 --- a/dev/project_extras/index.html +++ b/dev/project_extras/index.html @@ -1,3 +1,3 @@ Project.toml extras · Aqua.jl

Project.toml extras

There are two different ways to specify test-only dependencies (see the Pkg docs):

  1. Add the test-only dependencies to the [extras] section of your Project.toml file and use a test target.
  2. Add the test-only dependencies to the [deps] section of your test/Project.toml file. This is only available in Julia 1.2 and later.

This test checks checks that, in case you use both methods, the set of test-only dependencies is the same in both ways.

Test function

Aqua.test_project_extrasFunction
test_project_extras(package::Union{Module, PkgId})
-test_project_extras(packages::Vector{Union{Module, PkgId}})

Check that test target of the root project and test project (test/Project.toml) are consistent. This is useful for supporting Julia < 1.2 while recording test-only dependency compatibility in test/Project.toml.

source
+test_project_extras(packages::Vector{Union{Module, PkgId}})

Check that test target of the root project and test project (test/Project.toml) are consistent. This is useful for supporting Julia < 1.2 while recording test-only dependency compatibility in test/Project.toml.

source diff --git a/dev/release-notes/index.html b/dev/release-notes/index.html index 88a2218..8713769 100644 --- a/dev/release-notes/index.html +++ b/dev/release-notes/index.html @@ -1,2 +1,2 @@ -Release notes · Aqua.jl

Release notes

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Version v0.8.8 - 2024-10-10

Changed

  • Improved the documentation of test_persisten_tasks. (#297)

Version v0.8.7 - 2024-04-09

  • Reverted #285, which was originally released in v0.8.6, but caused a regression. (#287, #288)

Version v0.8.6 - 2024-04-09

Changed

  • The output of test_ambiguities now gets printed to stderr instead of stdout. (#281)

Version v0.8.5 - 2024-04-03

Changed

  • When supplying broken = true to test_ambiguities, test_undefined_exports, test_piracies, or test_unbound_args, the output is shortened. In particular, the list of offending instances is no longer printed. To get the full output, set broken = false. (#272)
  • Use Changelog.jl to generate the changelog, and add it to the documentation. (#277, #279)
  • test_project_extras prints failures the same on all julia versions. In particular, 1.11 and nightly are no outliers. (#275)

Version v0.8.4 - 2023-12-01

Added

  • test_persistent_tasks now accepts an optional expr to run in the precompile package. (#255)
    • The expr option lets you test whether your precompile script leaves any dangling Tasks
    or Timers, which would make it unsafe to use as a dependency for downstream packages.

Version v0.8.3 - 2023-11-29

Changed

  • test_persistent_tasks is now less noisy. (#256)
  • Completely overhauled the documentation. Every test now has its dedicated page. (#250)

Version v0.8.2 - 2023-11-16

Changed

  • test_persistent_tasks no longer clears the environment of the subtask. Instead, it modifies LOAD_PATH directly to make stdlibs work. (#241)

Version v0.8.1 - 2023-11-16

Changed

  • test_persistent_tasks now redirects stdout and stderr of the created subtask. Furthermore, the environment of the subtask gets cleared to allow default values for JULIA_LOAD_PATH to work. (#240)

Version v0.8.0 - 2023-11-15

Added

  • Two additions check whether packages might block precompilation on Julia 1.10 or higher: (#174)
    • test_persistent_tasks tests whether "your" package can safely be used as a dependency for downstream packages. This test is enabled for the default testsuite test_all, but you can opt-out by supplying persistent_tasks=false to test_all. [BREAKING]
    • find_persistent_tasks_deps is useful if "your" package hangs upon precompilation: it runs test_persistent_tasks on all the things you depend on, and may help isolate the culprit(s).

Changed

  • In test_deps_compat, the two subtests check_extras and check_weakdeps are now run by default. (#202) [BREAKING]
  • test_deps_compat now requires compat entries for all dependencies. Stdlibs no longer get ignored. This change is motivated by similar changes in the General registry. (#215) [BREAKING]
  • test_ambiguities now excludes the keyword sorter of all excluded functions with keyword arguments as well. (#203)
  • test_piracy is renamed to test_piracies. (#230) [BREAKING]
  • test_ambiguities and test_piracies now return issues in a defined order. This order may change in a patch release of Aqua.jl. (#233)
  • Improved the message for test_project_extras failures. (#234)
  • test_deps_compat now requires a compat entry for julia This can be disabling by setting compat_julia = false. (#236) [BREAKING]

Removed

  • test_project_toml_formatting has been removed. Thus, the kwarg project_toml_formatting to test_all no longer exists. (#209) [BREAKING]

Version v0.7.4 - 2023-10-24

Added

  • test_deps_compat has two new kwargs check_extras and check_weakdeps to extend the test to these dependency categories. They are not run by default. (#200)

Changed

  • The docstring for test_stale_deps explains the situation with package extensions. (#203)
  • The logo of Aqua.jl has been updated. (#128)

Version v0.7.3 - 2023-09-25

Added

  • test_deps_compat has a new kwarg broken to mark the test as broken using Test.@test_broken. (#193)

Fixed

  • test_piracy no longer prints warnings for methods where the third argument is a TypeVar. (#188)

Version v0.7.2 - 2023-09-19

Changed

  • test_undefined_exports additionally prints the modules of the undefined exports in the failure report. (#177)

Version v0.7.1 - 2023-09-05

Fixed

  • test_piracy no longer reports type piracy in the kwsorter, i.e. kwcall should no longer appear in the report. (#171)

Version v0.7.0 - 2023-08-29

Added

  • Installation and usage instructions to the documentation. (#159)

Changed

  • test_ambiguities now allows to exclude non-singleton callables. Excluding a type means to exclude all methods of the callable (sometimes also called "functor") and the constructor. (#144) [BREAKING]
  • test_piracy considers more functions. Callables and qualified names are now also checked. (#156) [BREAKING]

Fixed

  • test_ambiguities prints less unnecessary whitespace. (#158)
  • test_ambiguities no longer hangs indefinitely when there are many ambiguities. (#166)

Version v0.6.7 - 2023-09-19

Changed

  • test_undefined_exports additionally prints the modules of the undefined exports in the failure report. (#177)

Fixed

  • test_ambiguities prints less unnecessary whitespace. (#158)
  • Fix test_piracy for some methods with arguments of custom subtypes of Function. (#170)

Version v0.6.6 - 2023-08-24

Fixed

  • test_ambiguities no longer hangs indefinitely when there are many ambiguities. (#166)

Version v0.6.5 - 2023-06-26

Fixed

  • Typo when calling kwargs. (#153)

Version v0.6.4 - 2023-06-25

Added

  • test_piracy has a new kwarg treat_as_own. It is useful for testing packages that deliberately commit some type piracy, e.g. modules adding higher-level functionality to a lightweight C-wrapper, or packages that are extending StatsAPI.jl. (#140)

Changed

  • Explanation of test_unbound_args in the docstring. (#146)

Fixed

  • Callable objects with type parameters no longer error in test_ambiguities' kwarg exclude. (#142)

Version v0.6.3 - 2023-06-05

Changed

  • When installing a method for a union type, it is only reported by test_piracy if all types in the union are foreign (instead of any for arguments). (#131)

Fixed

  • test_deps_compat's kwarg ignore now works as intended. (#130)
  • Weakdeps are not reported as stale by test_stale_deps anymore. (#135)

Version v0.6.2 - 2023-06-02

Added

  • test_ambiguities, test_undefined_exports, test_piracy, and test_unbound_args each have a new kwarg broken to mark the test as broken using Test.@test_broken. (#124)

Changed

  • test_piracy now prints the offending methods in a more readable way. (#93)
  • Extend test_project_toml_formatting to docs/Project.toml. (#115)

Fixed

  • test_stale_deps no longer fails if any of the loaded packages prints during loading. (#113)
  • Clarified the error message of test_unbound_args. (#103)
  • Clarified the error message of test_project_toml_formatting. (#122)
+Release notes · Aqua.jl

Release notes

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Version v0.8.9 - 2024-10-15

Changed

  • Change test_ambiguities to only return ambiguities that happen in the target package. (#309)

Version v0.8.8 - 2024-10-10

Changed

  • Improved the documentation of test_persisten_tasks. (#297)

Version v0.8.7 - 2024-04-09

  • Reverted #285, which was originally released in v0.8.6, but caused a regression. (#287, #288)

Version v0.8.6 - 2024-04-09

Changed

  • The output of test_ambiguities now gets printed to stderr instead of stdout. (#281)

Version v0.8.5 - 2024-04-03

Changed

  • When supplying broken = true to test_ambiguities, test_undefined_exports, test_piracies, or test_unbound_args, the output is shortened. In particular, the list of offending instances is no longer printed. To get the full output, set broken = false. (#272)
  • Use Changelog.jl to generate the changelog, and add it to the documentation. (#277, #279)
  • test_project_extras prints failures the same on all julia versions. In particular, 1.11 and nightly are no outliers. (#275)

Version v0.8.4 - 2023-12-01

Added

  • test_persistent_tasks now accepts an optional expr to run in the precompile package. (#255)
    • The expr option lets you test whether your precompile script leaves any dangling Tasks
    or Timers, which would make it unsafe to use as a dependency for downstream packages.

Version v0.8.3 - 2023-11-29

Changed

  • test_persistent_tasks is now less noisy. (#256)
  • Completely overhauled the documentation. Every test now has its dedicated page. (#250)

Version v0.8.2 - 2023-11-16

Changed

  • test_persistent_tasks no longer clears the environment of the subtask. Instead, it modifies LOAD_PATH directly to make stdlibs work. (#241)

Version v0.8.1 - 2023-11-16

Changed

  • test_persistent_tasks now redirects stdout and stderr of the created subtask. Furthermore, the environment of the subtask gets cleared to allow default values for JULIA_LOAD_PATH to work. (#240)

Version v0.8.0 - 2023-11-15

Added

  • Two additions check whether packages might block precompilation on Julia 1.10 or higher: (#174)
    • test_persistent_tasks tests whether "your" package can safely be used as a dependency for downstream packages. This test is enabled for the default testsuite test_all, but you can opt-out by supplying persistent_tasks=false to test_all. [BREAKING]
    • find_persistent_tasks_deps is useful if "your" package hangs upon precompilation: it runs test_persistent_tasks on all the things you depend on, and may help isolate the culprit(s).

Changed

  • In test_deps_compat, the two subtests check_extras and check_weakdeps are now run by default. (#202) [BREAKING]
  • test_deps_compat now requires compat entries for all dependencies. Stdlibs no longer get ignored. This change is motivated by similar changes in the General registry. (#215) [BREAKING]
  • test_ambiguities now excludes the keyword sorter of all excluded functions with keyword arguments as well. (#203)
  • test_piracy is renamed to test_piracies. (#230) [BREAKING]
  • test_ambiguities and test_piracies now return issues in a defined order. This order may change in a patch release of Aqua.jl. (#233)
  • Improved the message for test_project_extras failures. (#234)
  • test_deps_compat now requires a compat entry for julia This can be disabling by setting compat_julia = false. (#236) [BREAKING]

Removed

  • test_project_toml_formatting has been removed. Thus, the kwarg project_toml_formatting to test_all no longer exists. (#209) [BREAKING]

Version v0.7.4 - 2023-10-24

Added

  • test_deps_compat has two new kwargs check_extras and check_weakdeps to extend the test to these dependency categories. They are not run by default. (#200)

Changed

  • The docstring for test_stale_deps explains the situation with package extensions. (#203)
  • The logo of Aqua.jl has been updated. (#128)

Version v0.7.3 - 2023-09-25

Added

  • test_deps_compat has a new kwarg broken to mark the test as broken using Test.@test_broken. (#193)

Fixed

  • test_piracy no longer prints warnings for methods where the third argument is a TypeVar. (#188)

Version v0.7.2 - 2023-09-19

Changed

  • test_undefined_exports additionally prints the modules of the undefined exports in the failure report. (#177)

Version v0.7.1 - 2023-09-05

Fixed

  • test_piracy no longer reports type piracy in the kwsorter, i.e. kwcall should no longer appear in the report. (#171)

Version v0.7.0 - 2023-08-29

Added

  • Installation and usage instructions to the documentation. (#159)

Changed

  • test_ambiguities now allows to exclude non-singleton callables. Excluding a type means to exclude all methods of the callable (sometimes also called "functor") and the constructor. (#144) [BREAKING]
  • test_piracy considers more functions. Callables and qualified names are now also checked. (#156) [BREAKING]

Fixed

  • test_ambiguities prints less unnecessary whitespace. (#158)
  • test_ambiguities no longer hangs indefinitely when there are many ambiguities. (#166)

Version v0.6.7 - 2023-09-19

Changed

  • test_undefined_exports additionally prints the modules of the undefined exports in the failure report. (#177)

Fixed

  • test_ambiguities prints less unnecessary whitespace. (#158)
  • Fix test_piracy for some methods with arguments of custom subtypes of Function. (#170)

Version v0.6.6 - 2023-08-24

Fixed

  • test_ambiguities no longer hangs indefinitely when there are many ambiguities. (#166)

Version v0.6.5 - 2023-06-26

Fixed

  • Typo when calling kwargs. (#153)

Version v0.6.4 - 2023-06-25

Added

  • test_piracy has a new kwarg treat_as_own. It is useful for testing packages that deliberately commit some type piracy, e.g. modules adding higher-level functionality to a lightweight C-wrapper, or packages that are extending StatsAPI.jl. (#140)

Changed

  • Explanation of test_unbound_args in the docstring. (#146)

Fixed

  • Callable objects with type parameters no longer error in test_ambiguities' kwarg exclude. (#142)

Version v0.6.3 - 2023-06-05

Changed

  • When installing a method for a union type, it is only reported by test_piracy if all types in the union are foreign (instead of any for arguments). (#131)

Fixed

  • test_deps_compat's kwarg ignore now works as intended. (#130)
  • Weakdeps are not reported as stale by test_stale_deps anymore. (#135)

Version v0.6.2 - 2023-06-02

Added

  • test_ambiguities, test_undefined_exports, test_piracy, and test_unbound_args each have a new kwarg broken to mark the test as broken using Test.@test_broken. (#124)

Changed

  • test_piracy now prints the offending methods in a more readable way. (#93)
  • Extend test_project_toml_formatting to docs/Project.toml. (#115)

Fixed

  • test_stale_deps no longer fails if any of the loaded packages prints during loading. (#113)
  • Clarified the error message of test_unbound_args. (#103)
  • Clarified the error message of test_project_toml_formatting. (#122)
diff --git a/dev/search_index.js b/dev/search_index.js index 2df8422..d21505f 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"persistent_tasks/#Persistent-Tasks","page":"Persistent Tasks","title":"Persistent Tasks","text":"","category":"section"},{"location":"persistent_tasks/#Motivation","page":"Persistent Tasks","title":"Motivation","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Julia 1.10 and higher wait for all running Tasks to finish before writing out the precompiled (cached) version of the package. One consequence is that a package that launches Tasks in its __init__ function may precompile successfully, but block precompilation of any packages that depend on it.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"The symptom of this problem is a message","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"◐ MyPackage: Waiting for background task / IO / timer. Interrupt to inspect...","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"that may appear during precompilation, with that precompilation process \"hanging\" until you press Ctrl-C.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Aqua has checks to determine whether your package causes this problem. Conversely, if you're a victim of this problem, it also has tools to help you determine which of your dependencies is causing the problem.","category":"page"},{"location":"persistent_tasks/#Example","page":"Persistent Tasks","title":"Example","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Let's create a dummy package, PkgA, that launches a persistent Task:","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"module PkgA\nconst t = Ref{Timer}() # used to prevent the Timer from being garbage-collected\n__init__() = t[] = Timer(0.1; interval=1) # create a persistent `Timer` `Task`\nend","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"PkgA will precompile successfully, because PkgA.__init__() does not run when PkgA is precompiled. However,","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"module PkgB\nusing PkgA\nend","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"fails to precompile: using PkgA runs PkgA.__init__(), which leaves the Timer Task running, and that causes precompilation of PkgB to hang.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Without Aqua's tests, the developers of PkgA might not realize that their package is essentially unusable with any other package.","category":"page"},{"location":"persistent_tasks/#Checking-for-persistent-tasks","page":"Persistent Tasks","title":"Checking for persistent tasks","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Running all of Aqua's tests will automatically check whether your package falls into this trap. In addition, there are ways to manually run (or tweak) this specific test.","category":"page"},{"location":"persistent_tasks/#Manually-running-the-peristent-tasks-check","page":"Persistent Tasks","title":"Manually running the peristent-tasks check","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Aqua.test_persistent_tasks(MyPackage) will check whether MyPackage blocks precompilation for any packages that depend on it.","category":"page"},{"location":"persistent_tasks/#Using-an-expr-to-check-more-than-just-__init__","page":"Persistent Tasks","title":"Using an expr to check more than just __init__","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"By default, Aqua.test_persistent_tasks only checks whether a package's __init__ function leaves persistent tasks running. To check whether other package functions leave persistent tasks running, pass a quoted expression:","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Aqua.test_persistent_tasks(MyPackage, quote\n # Code to run after loading MyPackage\n server = MyPackage.start_server()\n MyPackage.stop_server!(server) # ideally, this this should cleanly shut everything down. Does it?\nend)","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Here is an example test with a dummy expr which will obviously fail, because it's explicitly spawning a Task that never dies.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"using Aqua\nAqua.test_persistent_tasks(Aqua, expr = quote\n Threads.@spawn while true sleep(0.5) end\nend)","category":"page"},{"location":"persistent_tasks/#How-the-test-works","page":"Persistent Tasks","title":"How the test works","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"This test works by launching a Julia process that tries to precompile a dummy package similar to PkgB above, modified to signal back to Aqua when PkgA has finished loading. The test fails if the gap between loading PkgA and finishing precompilation exceeds time tmax.","category":"page"},{"location":"persistent_tasks/#How-to-fix-failing-packages","page":"Persistent Tasks","title":"How to fix failing packages","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Often, the easiest fix is to modify the __init__ function to check whether the Julia process is precompiling some other package; if so, don't launch the persistent Tasks.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"function __init__()\n # Other setup code here\n if ccall(:jl_generating_output, Cint, ()) == 0 # if we're not precompiling...\n # launch persistent tasks here\n end\nend","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"In more complex cases, you may need to modify the task to support a clean shutdown. For example, if you have a Task that runs a never-terminating while loop, you could change","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":" while true\n ⋮\n end","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"to","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":" while task_should_run[]\n ⋮\n end","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"where","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"const task_should_run = Ref(true)","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"is a global constant in your module. Setting task_should_run[] = false from outside that while loop will cause it to terminate on its next iteration, allowing the Task to finish.","category":"page"},{"location":"persistent_tasks/#Additional-information","page":"Persistent Tasks","title":"Additional information","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Julia's devdocs also discuss this issue.","category":"page"},{"location":"persistent_tasks/#test_persistent_tasks","page":"Persistent Tasks","title":"Test functions","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Aqua.test_persistent_tasks\nAqua.find_persistent_tasks_deps","category":"page"},{"location":"persistent_tasks/#Aqua.test_persistent_tasks","page":"Persistent Tasks","title":"Aqua.test_persistent_tasks","text":"Aqua.test_persistent_tasks(package)\n\nTest whether loading package creates persistent Tasks which may block precompilation of dependent packages. See also Aqua.find_persistent_tasks_deps.\n\nIf you provide an optional expr, this tests whether loading package and running expr creates persistent Tasks. For example, you might start and shutdown a web server, and this will test that there aren't any persistent Tasks.\n\nOn Julia version 1.9 and before, this test always succeeds.\n\nArguments\n\npackage: a top-level Module or Base.PkgId.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test.\ntmax::Real = 5: the maximum time (in seconds) to wait after loading the package before forcibly shutting down the precompilation process (triggering a test failure).\nexpr::Expr = quote end: An expression to run in the precompile package.\n\nnote: Note\nAqua.test_persistent_tasks(package) creates a package with package as a dependency and runs the precompilation process. This requires that package is instantiable with the information in the Project.toml file alone. In particular, this will not work if some of package's dependencies are deved packages or are given as a local path or a git repository in the Manifest.toml.\n\n\n\n\n\n","category":"function"},{"location":"persistent_tasks/#Aqua.find_persistent_tasks_deps","page":"Persistent Tasks","title":"Aqua.find_persistent_tasks_deps","text":"Aqua.find_persistent_tasks_deps(package; broken = Dict{String,Bool}(), kwargs...)\n\nTest all the dependencies of package with Aqua.test_persistent_tasks. On Julia 1.10 and higher, it returns a list of all dependencies failing the test. These are likely the ones blocking precompilation of your package.\n\nAny additional kwargs (e.g., tmax) are passed to Aqua.test_persistent_tasks.\n\n\n\n\n\n","category":"function"},{"location":"deps_compat/#Compat-entries","page":"Compat entries","title":"Compat entries","text":"","category":"section"},{"location":"deps_compat/","page":"Compat entries","title":"Compat entries","text":"In your Project.toml you can (and should) use compat entries to specify with which versions of Julia and your dependencies your package is compatible with. This is important to ease the installation and upgrade of your package for users, and to keep everything working in the case of breaking changes in Julia or your dependencies.","category":"page"},{"location":"deps_compat/","page":"Compat entries","title":"Compat entries","text":"For more details, see the Pkg docs.","category":"page"},{"location":"deps_compat/#test_deps_compat","page":"Compat entries","title":"Test function","text":"","category":"section"},{"location":"deps_compat/","page":"Compat entries","title":"Compat entries","text":"Aqua.test_deps_compat","category":"page"},{"location":"deps_compat/#Aqua.test_deps_compat","page":"Compat entries","title":"Aqua.test_deps_compat","text":"Aqua.test_deps_compat(package)\n\nTest that the Project.toml of package has a compat entry for each package listed under deps and for julia.\n\nArguments\n\npackages: a top-level Module, a Base.PkgId, or a collection of them.\n\nKeyword Arguments\n\nTest choosers\n\ncheck_julia = true: If true, additionally check for a compat entry for \"julia\".\ncheck_extras = true: If true, additionally check \"extras\". A NamedTuple can be used to pass keyword arguments with test options (see below).\ncheck_weakdeps = true: If true, additionally check \"weakdeps\". A NamedTuple can be used to pass keyword arguments with test options (see below).\n\nTest options\n\nIf these keyword arguments are set directly, they only apply to the standard test for \"deps\". To apply them to \"extras\" and \"weakdeps\", pass them as a NamedTuple to the corresponding check_$x keyword argument.\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test for \"deps\".\nignore::Vector{Symbol}: names of dependent packages to be ignored.\n\n\n\n\n\n","category":"function"},{"location":"project_extras/#Project.toml-extras","page":"Project.toml extras","title":"Project.toml extras","text":"","category":"section"},{"location":"project_extras/","page":"Project.toml extras","title":"Project.toml extras","text":"There are two different ways to specify test-only dependencies (see the Pkg docs):","category":"page"},{"location":"project_extras/","page":"Project.toml extras","title":"Project.toml extras","text":"Add the test-only dependencies to the [extras] section of your Project.toml file and use a test target.\nAdd the test-only dependencies to the [deps] section of your test/Project.toml file. This is only available in Julia 1.2 and later.","category":"page"},{"location":"project_extras/","page":"Project.toml extras","title":"Project.toml extras","text":"This test checks checks that, in case you use both methods, the set of test-only dependencies is the same in both ways.","category":"page"},{"location":"project_extras/#test_project_extras","page":"Project.toml extras","title":"Test function","text":"","category":"section"},{"location":"project_extras/","page":"Project.toml extras","title":"Project.toml extras","text":"Aqua.test_project_extras","category":"page"},{"location":"project_extras/#Aqua.test_project_extras","page":"Project.toml extras","title":"Aqua.test_project_extras","text":"test_project_extras(package::Union{Module, PkgId})\ntest_project_extras(packages::Vector{Union{Module, PkgId}})\n\nCheck that test target of the root project and test project (test/Project.toml) are consistent. This is useful for supporting Julia < 1.2 while recording test-only dependency compatibility in test/Project.toml.\n\n\n\n\n\n","category":"function"},{"location":"ambiguities/#Ambiguities","page":"Ambiguities","title":"Ambiguities","text":"","category":"section"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"Method ambiguities are cases where multiple methods are applicable to a given set of arguments, without having a most specific method.","category":"page"},{"location":"ambiguities/#Examples","page":"Ambiguities","title":"Examples","text":"","category":"section"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"One easy example is the following:","category":"page"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"f(x::Int, y::Integer) = 1\nf(x::Integer, y::Int) = 2\n\nprintln(f(1, 2))","category":"page"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"This will throw an MethodError because both methods are equally specific. The solution is to add a third method:","category":"page"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"f(x::Int, y::Int) = ? # `?` is dependent on the use case, most times it will be `1` or `2`","category":"page"},{"location":"ambiguities/#test_ambiguities","page":"Ambiguities","title":"Test function","text":"","category":"section"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"Aqua.test_ambiguities","category":"page"},{"location":"ambiguities/#Aqua.test_ambiguities","page":"Ambiguities","title":"Aqua.test_ambiguities","text":"test_ambiguities(package::Union{Module, PkgId})\ntest_ambiguities(packages::Vector{Union{Module, PkgId}})\n\nTest that there is no method ambiguities in given package(s). It calls Test.detect_ambiguities in a separated clean process to avoid false-positives.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.\ncolor::Union{Bool, Nothing} = nothing: Enable/disable colorful output if a Bool. nothing (default) means to inherit the setting in the current process.\nexclude::AbstractVector = []: A vector of functions or types to be excluded from ambiguity testing. A function means to exclude all its methods. A type means to exclude all its methods of the callable (sometimes also called \"functor\") and the constructor. That is to say, MyModule.MyType means to ignore ambiguities between (::MyType)(x, y::Int) and (::MyType)(x::Int, y).\nrecursive::Bool = true: Passed to Test.detect_ambiguities. Note that the default here (true) is different from detect_ambiguities. This is for testing ambiguities in methods defined in all sub-modules.\nOther keyword arguments such as imported and ambiguous_bottom are passed to Test.detect_ambiguities as-is.\n\n\n\n\n\n","category":"function"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"EditURL = \"https://github.com/JuliaTesting/Aqua.jl/blob/master/CHANGELOG.md\"","category":"page"},{"location":"release-notes/#Release-notes","page":"Release notes","title":"Release notes","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"All notable changes to this project will be documented in this file.","category":"page"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.","category":"page"},{"location":"release-notes/#Version-[v0.8.8](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.8)-2024-10-10","page":"Release notes","title":"Version v0.8.8 - 2024-10-10","text":"","category":"section"},{"location":"release-notes/#Changed","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Improved the documentation of test_persisten_tasks. (#297)","category":"page"},{"location":"release-notes/#Version-[v0.8.7](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.7)-2024-04-09","page":"Release notes","title":"Version v0.8.7 - 2024-04-09","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Reverted #285, which was originally released in v0.8.6, but caused a regression. (#287, #288)","category":"page"},{"location":"release-notes/#Version-[v0.8.6](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.6)-2024-04-09","page":"Release notes","title":"Version v0.8.6 - 2024-04-09","text":"","category":"section"},{"location":"release-notes/#Changed-2","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"The output of test_ambiguities now gets printed to stderr instead of stdout. (#281)","category":"page"},{"location":"release-notes/#Version-[v0.8.5](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.5)-2024-04-03","page":"Release notes","title":"Version v0.8.5 - 2024-04-03","text":"","category":"section"},{"location":"release-notes/#Changed-3","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"When supplying broken = true to test_ambiguities, test_undefined_exports, test_piracies, or test_unbound_args, the output is shortened. In particular, the list of offending instances is no longer printed. To get the full output, set broken = false. (#272)\nUse Changelog.jl to generate the changelog, and add it to the documentation. (#277, #279)\ntest_project_extras prints failures the same on all julia versions. In particular, 1.11 and nightly are no outliers. (#275)","category":"page"},{"location":"release-notes/#Version-[v0.8.4](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.4)-2023-12-01","page":"Release notes","title":"Version v0.8.4 - 2023-12-01","text":"","category":"section"},{"location":"release-notes/#Added","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_persistent_tasks now accepts an optional expr to run in the precompile package. (#255)\nThe expr option lets you test whether your precompile script leaves any dangling Tasks\nor Timers, which would make it unsafe to use as a dependency for downstream packages.","category":"page"},{"location":"release-notes/#Version-[v0.8.3](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.3)-2023-11-29","page":"Release notes","title":"Version v0.8.3 - 2023-11-29","text":"","category":"section"},{"location":"release-notes/#Changed-4","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_persistent_tasks is now less noisy. (#256)\nCompletely overhauled the documentation. Every test now has its dedicated page. (#250)","category":"page"},{"location":"release-notes/#Version-[v0.8.2](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.2)-2023-11-16","page":"Release notes","title":"Version v0.8.2 - 2023-11-16","text":"","category":"section"},{"location":"release-notes/#Changed-5","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_persistent_tasks no longer clears the environment of the subtask. Instead, it modifies LOAD_PATH directly to make stdlibs work. (#241)","category":"page"},{"location":"release-notes/#Version-[v0.8.1](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.1)-2023-11-16","page":"Release notes","title":"Version v0.8.1 - 2023-11-16","text":"","category":"section"},{"location":"release-notes/#Changed-6","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_persistent_tasks now redirects stdout and stderr of the created subtask. Furthermore, the environment of the subtask gets cleared to allow default values for JULIA_LOAD_PATH to work. (#240)","category":"page"},{"location":"release-notes/#Version-[v0.8.0](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.0)-2023-11-15","page":"Release notes","title":"Version v0.8.0 - 2023-11-15","text":"","category":"section"},{"location":"release-notes/#Added-2","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Two additions check whether packages might block precompilation on Julia 1.10 or higher: (#174)\ntest_persistent_tasks tests whether \"your\" package can safely be used as a dependency for downstream packages. This test is enabled for the default testsuite test_all, but you can opt-out by supplying persistent_tasks=false to test_all. [BREAKING]\nfind_persistent_tasks_deps is useful if \"your\" package hangs upon precompilation: it runs test_persistent_tasks on all the things you depend on, and may help isolate the culprit(s).","category":"page"},{"location":"release-notes/#Changed-7","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"In test_deps_compat, the two subtests check_extras and check_weakdeps are now run by default. (#202) [BREAKING]\ntest_deps_compat now requires compat entries for all dependencies. Stdlibs no longer get ignored. This change is motivated by similar changes in the General registry. (#215) [BREAKING]\ntest_ambiguities now excludes the keyword sorter of all excluded functions with keyword arguments as well. (#203)\ntest_piracy is renamed to test_piracies. (#230) [BREAKING]\ntest_ambiguities and test_piracies now return issues in a defined order. This order may change in a patch release of Aqua.jl. (#233)\nImproved the message for test_project_extras failures. (#234)\ntest_deps_compat now requires a compat entry for julia This can be disabling by setting compat_julia = false. (#236) [BREAKING]","category":"page"},{"location":"release-notes/#Removed","page":"Release notes","title":"Removed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_project_toml_formatting has been removed. Thus, the kwarg project_toml_formatting to test_all no longer exists. (#209) [BREAKING]","category":"page"},{"location":"release-notes/#Version-[v0.7.4](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.4)-2023-10-24","page":"Release notes","title":"Version v0.7.4 - 2023-10-24","text":"","category":"section"},{"location":"release-notes/#Added-3","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_deps_compat has two new kwargs check_extras and check_weakdeps to extend the test to these dependency categories. They are not run by default. (#200)","category":"page"},{"location":"release-notes/#Changed-8","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"The docstring for test_stale_deps explains the situation with package extensions. (#203)\nThe logo of Aqua.jl has been updated. (#128)","category":"page"},{"location":"release-notes/#Version-[v0.7.3](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.3)-2023-09-25","page":"Release notes","title":"Version v0.7.3 - 2023-09-25","text":"","category":"section"},{"location":"release-notes/#Added-4","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_deps_compat has a new kwarg broken to mark the test as broken using Test.@test_broken. (#193)","category":"page"},{"location":"release-notes/#Fixed","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_piracy no longer prints warnings for methods where the third argument is a TypeVar. (#188)","category":"page"},{"location":"release-notes/#Version-[v0.7.2](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.2)-2023-09-19","page":"Release notes","title":"Version v0.7.2 - 2023-09-19","text":"","category":"section"},{"location":"release-notes/#Changed-9","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_undefined_exports additionally prints the modules of the undefined exports in the failure report. (#177)","category":"page"},{"location":"release-notes/#Version-[v0.7.1](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.1)-2023-09-05","page":"Release notes","title":"Version v0.7.1 - 2023-09-05","text":"","category":"section"},{"location":"release-notes/#Fixed-2","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_piracy no longer reports type piracy in the kwsorter, i.e. kwcall should no longer appear in the report. (#171)","category":"page"},{"location":"release-notes/#Version-[v0.7.0](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.0)-2023-08-29","page":"Release notes","title":"Version v0.7.0 - 2023-08-29","text":"","category":"section"},{"location":"release-notes/#Added-5","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Installation and usage instructions to the documentation. (#159)","category":"page"},{"location":"release-notes/#Changed-10","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities now allows to exclude non-singleton callables. Excluding a type means to exclude all methods of the callable (sometimes also called \"functor\") and the constructor. (#144) [BREAKING]\ntest_piracy considers more functions. Callables and qualified names are now also checked. (#156) [BREAKING]","category":"page"},{"location":"release-notes/#Fixed-3","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities prints less unnecessary whitespace. (#158)\ntest_ambiguities no longer hangs indefinitely when there are many ambiguities. (#166)","category":"page"},{"location":"release-notes/#Version-[v0.6.7](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.7)-2023-09-19","page":"Release notes","title":"Version v0.6.7 - 2023-09-19","text":"","category":"section"},{"location":"release-notes/#Changed-11","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_undefined_exports additionally prints the modules of the undefined exports in the failure report. (#177)","category":"page"},{"location":"release-notes/#Fixed-4","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities prints less unnecessary whitespace. (#158)\nFix test_piracy for some methods with arguments of custom subtypes of Function. (#170)","category":"page"},{"location":"release-notes/#Version-[v0.6.6](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.6)-2023-08-24","page":"Release notes","title":"Version v0.6.6 - 2023-08-24","text":"","category":"section"},{"location":"release-notes/#Fixed-5","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities no longer hangs indefinitely when there are many ambiguities. (#166)","category":"page"},{"location":"release-notes/#Version-[v0.6.5](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.5)-2023-06-26","page":"Release notes","title":"Version v0.6.5 - 2023-06-26","text":"","category":"section"},{"location":"release-notes/#Fixed-6","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Typo when calling kwargs. (#153)","category":"page"},{"location":"release-notes/#Version-[v0.6.4](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.4)-2023-06-25","page":"Release notes","title":"Version v0.6.4 - 2023-06-25","text":"","category":"section"},{"location":"release-notes/#Added-6","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_piracy has a new kwarg treat_as_own. It is useful for testing packages that deliberately commit some type piracy, e.g. modules adding higher-level functionality to a lightweight C-wrapper, or packages that are extending StatsAPI.jl. (#140)","category":"page"},{"location":"release-notes/#Changed-12","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Explanation of test_unbound_args in the docstring. (#146)","category":"page"},{"location":"release-notes/#Fixed-7","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Callable objects with type parameters no longer error in test_ambiguities' kwarg exclude. (#142)","category":"page"},{"location":"release-notes/#Version-[v0.6.3](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.3)-2023-06-05","page":"Release notes","title":"Version v0.6.3 - 2023-06-05","text":"","category":"section"},{"location":"release-notes/#Changed-13","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"When installing a method for a union type, it is only reported by test_piracy if all types in the union are foreign (instead of any for arguments). (#131)","category":"page"},{"location":"release-notes/#Fixed-8","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_deps_compat's kwarg ignore now works as intended. (#130)\nWeakdeps are not reported as stale by test_stale_deps anymore. (#135)","category":"page"},{"location":"release-notes/#Version-[v0.6.2](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.2)-2023-06-02","page":"Release notes","title":"Version v0.6.2 - 2023-06-02","text":"","category":"section"},{"location":"release-notes/#Added-7","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities, test_undefined_exports, test_piracy, and test_unbound_args each have a new kwarg broken to mark the test as broken using Test.@test_broken. (#124)","category":"page"},{"location":"release-notes/#Changed-14","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_piracy now prints the offending methods in a more readable way. (#93)\nExtend test_project_toml_formatting to docs/Project.toml. (#115)","category":"page"},{"location":"release-notes/#Fixed-9","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_stale_deps no longer fails if any of the loaded packages prints during loading. (#113)\nClarified the error message of test_unbound_args. (#103)\nClarified the error message of test_project_toml_formatting. (#122)","category":"page"},{"location":"piracies/#Type-piracy","page":"Type piracy","title":"Type piracy","text":"","category":"section"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"Type piracy is a term used to describe adding methods to a foreign function with only foreign arguments. This is considered bad practice because it can cause unexpected behavior when the function is called, in particular, it can change the behavior of one of your dependencies depending on if your package is loaded or not. This makes it hard to reason about the behavior of your code, and may introduce bugs that are hard to track down.","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"See Julia documentation for more information about type piracy.","category":"page"},{"location":"piracies/#Examples","page":"Type piracy","title":"Examples","text":"","category":"section"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"Say that PkgA is foreign, and let's look at the different ways that PkgB extends its function bar.","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"module PkgA\n struct C end\n bar(x::C) = 42\n bar(x::Vector) = 43\nend\n\nmodule PkgB \n import PkgA: bar, C\n struct D end\n bar(x::C) = 1\n bar(xs::D...) = 2\n bar(x::Vector{<:D}) = 3\n bar(x::Vector{D}) = 4 # slightly bad (may cause invalidations)\n bar(x::Union{C,D}) = 5 # slightly bad (a change in PkgA may turn it into piracy)\n # (for example changing bar(x::C) = 1 to bar(x::Union{C,Int}) = 1)\nend","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"The following cases are enumerated by the return values in the example above:","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"This is the worst case of type piracy. The value of bar(C()) can be either 1 or 42 and will depend on whether PkgB is loaded or not.\nThis is also a bad case of type piracy. bar() throws a MethodError with only PkgA available, and returns 2 with PkgB loaded. PkgA may add a method for bar() that takes no arguments in the future, and then this is equivalent to case 1.\nThis is a moderately bad case of type piracy. bar(Union{}[]) returns 3 when PkgB is loaded, and 43 when PkgB is not loaded, although neither of the occurring types are defined in PkgB. This case is not as bad as cases 1 and 2, because it is only about behavior around Union{}, which has no instances.\nDepending on ones understanding of type piracy, this could be considered piracy as well. In particular, this may cause invalidations.\nThis is a slightly bad case of type piracy. In the current form, bar(C()) returns 42 as the dispatch on Union{C,D} is less specific. However, a future change in PkgA may change this behavior, e.g. by changing bar(x::C) to bar(x::Union{C,Int}) the call bar(C()) would become ambiguous.","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"note: Note\nThe test function below currently only checks for cases 1 and 2.","category":"page"},{"location":"piracies/#test_piracies","page":"Type piracy","title":"Test function","text":"","category":"section"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"Aqua.test_piracies","category":"page"},{"location":"piracies/#Aqua.test_piracies","page":"Type piracy","title":"Aqua.test_piracies","text":"test_piracies(m::Module)\n\nTest that m does not commit type piracies.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.\nskip_deprecated::Bool = true: If true, it does not check deprecated methods.\ntreat_as_own = Union{Function, Type}[]: The types in this container are considered to be \"owned\" by the module m. This is useful for testing packages that deliberately commit some type piracies, e.g. modules adding higher-level functionality to a lightweight C-wrapper, or packages that are extending StatsAPI.jl.\n\n\n\n\n\n","category":"function"},{"location":"unbound_args/#Unbound-Type-Parameters","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"","category":"section"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"An unbound type parameter is a type parameter with a where, that does not occur in the signature of some dispatch of the method.","category":"page"},{"location":"unbound_args/#Examples","page":"Unbound Type Parameters","title":"Examples","text":"","category":"section"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"The following methods each have T as an unbound type parameter:","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"f(x::Int) where {T} = do_something(x)\ng(x::T...) where {T} = println(T)","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"In the cases of f above, the unbound type parameter T is neither present in the signature of the methods nor as a bound of another type parameter. Here, the type parameter T can be removed without changing any semantics.","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"For signatures with Vararg (cf. g above), the type parameter is unbound for the zero-argument case (e.g. g()).","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"g(1.0, 2.0)\ng(1)\ng()","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"A possible fix would be to replace g by two methods.","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"g() = println(Int) # Defaults to `Int`\ng(x1::T, x2::T...) where {T} = println(T)\ng(1.0, 2.0)\ng(1)\ng()","category":"page"},{"location":"unbound_args/#test_unbound_args","page":"Unbound Type Parameters","title":"Test function","text":"","category":"section"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"Aqua.test_unbound_args","category":"page"},{"location":"unbound_args/#Aqua.test_unbound_args","page":"Unbound Type Parameters","title":"Aqua.test_unbound_args","text":"test_unbound_args(module::Module)\n\nTest that all methods in module and its submodules do not have unbound type parameters. An unbound type parameter is a type parameter with a where, that does not occur in the signature of some dispatch of the method.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.\n\n\n\n\n\n","category":"function"},{"location":"stale_deps/#Stale-dependencies","page":"Stale dependencies","title":"Stale dependencies","text":"","category":"section"},{"location":"stale_deps/#test_stale_deps","page":"Stale dependencies","title":"Test function","text":"","category":"section"},{"location":"stale_deps/","page":"Stale dependencies","title":"Stale dependencies","text":"Aqua.test_stale_deps","category":"page"},{"location":"stale_deps/#Aqua.test_stale_deps","page":"Stale dependencies","title":"Aqua.test_stale_deps","text":"Aqua.test_stale_deps(package; [ignore])\n\nTest that package loads all dependencies listed in Project.toml. Note that this does not imply that package loads the dependencies directly, this can be achieved via transitivity as well.\n\nnote: Weak dependencies and extensions\nDue to the automatic loading of package extensions once all of their trigger dependencies are loaded, Aqua.jl can, by design of julia, not check if a package extension indeed loads all of its trigger dependencies using import or using. \n\nwarning: Known bug\nCurrently, Aqua.test_stale_deps does not detect stale dependencies when they are in the sysimage. This is considered a bug and may be fixed in the future. Such a release is considered non-breaking.\n\nArguments\n\npackages: a top-level Module, a Base.PkgId, or a collection of them.\n\nKeyword Arguments\n\nignore::Vector{Symbol}: names of dependent packages to be ignored.\n\n\n\n\n\n","category":"function"},{"location":"exports/#Undefined-exports","page":"Undefined exports","title":"Undefined exports","text":"","category":"section"},{"location":"exports/#test_undefined_exports","page":"Undefined exports","title":"Test function","text":"","category":"section"},{"location":"exports/","page":"Undefined exports","title":"Undefined exports","text":"Aqua.test_undefined_exports","category":"page"},{"location":"exports/#Aqua.test_undefined_exports","page":"Undefined exports","title":"Aqua.test_undefined_exports","text":"test_undefined_exports(module::Module)\n\nTest that all exported names in module actually exist.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.\n\n\n\n\n\n","category":"function"},{"location":"test_all/#test_all","page":"Test everything","title":"Test everything","text":"","category":"section"},{"location":"test_all/","page":"Test everything","title":"Test everything","text":"This test runs most of the other tests in this module. The defaults should be fine for most packages. If you have a package that needs to customize the test, you can do so by providing appropriate keyword arguments to Aqua.test_all() (see below)","category":"page"},{"location":"test_all/","page":"Test everything","title":"Test everything","text":"Aqua.test_all","category":"page"},{"location":"test_all/#Aqua.test_all","page":"Test everything","title":"Aqua.test_all","text":"test_all(testtarget::Module)\n\nRun the following tests:\n\ntest_ambiguities([testtarget, Base, Core])\ntest_unbound_args(testtarget)\ntest_undefined_exports(testtarget)\ntest_project_extras(testtarget)\ntest_stale_deps(testtarget)\ntest_deps_compat(testtarget)\ntest_piracies(testtarget)\ntest_persistent_tasks(testtarget)\n\nThe keyword argument $x (e.g., ambiguities) can be used to control whether or not to run test_$x (e.g., test_ambiguities). If test_$x supports keyword arguments, a NamedTuple can also be passed to $x to specify the keyword arguments for test_$x.\n\nKeyword Arguments\n\nambiguities = true\nunbound_args = true\nundefined_exports = true\nproject_extras = true\nstale_deps = true\ndeps_compat = true\npiracies = true\npersistent_tasks = true\n\n\n\n\n\n","category":"function"},{"location":"#Aqua.jl:-*A*uto-*QU*ality-*A*ssurance-for-Julia-packages","page":"Home","title":"Aqua.jl: Auto QUality Assurance for Julia packages","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Aqua.jl provides functions to run a few automatable checks for Julia packages:","category":"page"},{"location":"","page":"Home","title":"Home","text":"There are no method ambiguities.\nThere are no undefined exports.\nThere are no unbound type parameters.\nThere are no stale dependencies listed in Project.toml.\nCheck that test target of the root project Project.toml and test project (test/Project.toml) are consistent.\nCheck that all external packages listed in deps have corresponding compat entries.\nThere are no \"obvious\" type piracies.\nThe package does not create any persistent Tasks that might block precompilation of dependencies.","category":"page"},{"location":"#Quick-usage","page":"Home","title":"Quick usage","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Call Aqua.test_all(YourPackage) from the REPL, e.g.,","category":"page"},{"location":"","page":"Home","title":"Home","text":"using YourPackage\nusing Aqua\nAqua.test_all(YourPackage)","category":"page"},{"location":"#How-to-add-Aqua.jl...","page":"Home","title":"How to add Aqua.jl...","text":"","category":"section"},{"location":"#...as-a-test-dependency?","page":"Home","title":"...as a test dependency?","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"There are two ways to add Aqua.jl as a test dependency to your package. To avoid breaking tests when a new Aqua.jl version is released, it is recommended to add a version bound for Aqua.jl.","category":"page"},{"location":"","page":"Home","title":"Home","text":"In YourPackage/test/Project.toml, add Aqua.jl to [dep] and [compat] sections, like\n[deps]\nAqua = \"4c88cf16-eb10-579e-8560-4a9242c79595\"\nTest = \"8dfed614-e22c-5e08-85e1-65c5234f0b40\"\n\n[compat]\nAqua = \"0.8\"\nIn YourPackage/Project.toml, add Aqua.jl to [compat] and [extras] section and the test target, like\n[compat]\nAqua = \"0.8\"\n\n[extras]\nAqua = \"4c88cf16-eb10-579e-8560-4a9242c79595\"\nTest = \"8dfed614-e22c-5e08-85e1-65c5234f0b40\"\n\n[targets]\ntest = [\"Aqua\", \"Test\"]","category":"page"},{"location":"","page":"Home","title":"Home","text":"If your package supports Julia pre-1.2, you need to use the second approach, although you can use both approaches at the same time.","category":"page"},{"location":"","page":"Home","title":"Home","text":"warning: Warning\nIn normal use, Aqua.jl should not be added to [deps] in YourPackage/Project.toml!","category":"page"},{"location":"#...to-your-tests?","page":"Home","title":"...to your tests?","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"It is recommended to create a separate file YourPackage/test/Aqua.jl that gets included in YourPackage/test/runtests.jl with either","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Aqua\nAqua.test_all(YourPackage)","category":"page"},{"location":"","page":"Home","title":"Home","text":"or some fine-grained checks with options, e.g.,","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Aqua\n\n@testset \"Aqua.jl\" begin\n Aqua.test_all(\n YourPackage;\n ambiguities=(exclude=[SomePackage.some_function], broken=true),\n stale_deps=(ignore=[:SomePackage],),\n deps_compat=(ignore=[:SomeOtherPackage],),\n piracies=false,\n )\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"Note, that for all tests with no explicit options provided, the default options are used.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For more details on the options, see the respective functions here.","category":"page"},{"location":"#Examples","page":"Home","title":"Examples","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The following is a small selection of packages that use Aqua.jl:","category":"page"},{"location":"","page":"Home","title":"Home","text":"GAP.jl\nHecke.jl\nOscar.jl","category":"page"}] +[{"location":"persistent_tasks/#Persistent-Tasks","page":"Persistent Tasks","title":"Persistent Tasks","text":"","category":"section"},{"location":"persistent_tasks/#Motivation","page":"Persistent Tasks","title":"Motivation","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Julia 1.10 and higher wait for all running Tasks to finish before writing out the precompiled (cached) version of the package. One consequence is that a package that launches Tasks in its __init__ function may precompile successfully, but block precompilation of any packages that depend on it.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"The symptom of this problem is a message","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"◐ MyPackage: Waiting for background task / IO / timer. Interrupt to inspect...","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"that may appear during precompilation, with that precompilation process \"hanging\" until you press Ctrl-C.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Aqua has checks to determine whether your package causes this problem. Conversely, if you're a victim of this problem, it also has tools to help you determine which of your dependencies is causing the problem.","category":"page"},{"location":"persistent_tasks/#Example","page":"Persistent Tasks","title":"Example","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Let's create a dummy package, PkgA, that launches a persistent Task:","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"module PkgA\nconst t = Ref{Timer}() # used to prevent the Timer from being garbage-collected\n__init__() = t[] = Timer(0.1; interval=1) # create a persistent `Timer` `Task`\nend","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"PkgA will precompile successfully, because PkgA.__init__() does not run when PkgA is precompiled. However,","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"module PkgB\nusing PkgA\nend","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"fails to precompile: using PkgA runs PkgA.__init__(), which leaves the Timer Task running, and that causes precompilation of PkgB to hang.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Without Aqua's tests, the developers of PkgA might not realize that their package is essentially unusable with any other package.","category":"page"},{"location":"persistent_tasks/#Checking-for-persistent-tasks","page":"Persistent Tasks","title":"Checking for persistent tasks","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Running all of Aqua's tests will automatically check whether your package falls into this trap. In addition, there are ways to manually run (or tweak) this specific test.","category":"page"},{"location":"persistent_tasks/#Manually-running-the-peristent-tasks-check","page":"Persistent Tasks","title":"Manually running the peristent-tasks check","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Aqua.test_persistent_tasks(MyPackage) will check whether MyPackage blocks precompilation for any packages that depend on it.","category":"page"},{"location":"persistent_tasks/#Using-an-expr-to-check-more-than-just-__init__","page":"Persistent Tasks","title":"Using an expr to check more than just __init__","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"By default, Aqua.test_persistent_tasks only checks whether a package's __init__ function leaves persistent tasks running. To check whether other package functions leave persistent tasks running, pass a quoted expression:","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Aqua.test_persistent_tasks(MyPackage, quote\n # Code to run after loading MyPackage\n server = MyPackage.start_server()\n MyPackage.stop_server!(server) # ideally, this this should cleanly shut everything down. Does it?\nend)","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Here is an example test with a dummy expr which will obviously fail, because it's explicitly spawning a Task that never dies.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"using Aqua\nAqua.test_persistent_tasks(Aqua, expr = quote\n Threads.@spawn while true sleep(0.5) end\nend)","category":"page"},{"location":"persistent_tasks/#How-the-test-works","page":"Persistent Tasks","title":"How the test works","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"This test works by launching a Julia process that tries to precompile a dummy package similar to PkgB above, modified to signal back to Aqua when PkgA has finished loading. The test fails if the gap between loading PkgA and finishing precompilation exceeds time tmax.","category":"page"},{"location":"persistent_tasks/#How-to-fix-failing-packages","page":"Persistent Tasks","title":"How to fix failing packages","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Often, the easiest fix is to modify the __init__ function to check whether the Julia process is precompiling some other package; if so, don't launch the persistent Tasks.","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"function __init__()\n # Other setup code here\n if ccall(:jl_generating_output, Cint, ()) == 0 # if we're not precompiling...\n # launch persistent tasks here\n end\nend","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"In more complex cases, you may need to modify the task to support a clean shutdown. For example, if you have a Task that runs a never-terminating while loop, you could change","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":" while true\n ⋮\n end","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"to","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":" while task_should_run[]\n ⋮\n end","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"where","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"const task_should_run = Ref(true)","category":"page"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"is a global constant in your module. Setting task_should_run[] = false from outside that while loop will cause it to terminate on its next iteration, allowing the Task to finish.","category":"page"},{"location":"persistent_tasks/#Additional-information","page":"Persistent Tasks","title":"Additional information","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Julia's devdocs also discuss this issue.","category":"page"},{"location":"persistent_tasks/#test_persistent_tasks","page":"Persistent Tasks","title":"Test functions","text":"","category":"section"},{"location":"persistent_tasks/","page":"Persistent Tasks","title":"Persistent Tasks","text":"Aqua.test_persistent_tasks\nAqua.find_persistent_tasks_deps","category":"page"},{"location":"persistent_tasks/#Aqua.test_persistent_tasks","page":"Persistent Tasks","title":"Aqua.test_persistent_tasks","text":"Aqua.test_persistent_tasks(package)\n\nTest whether loading package creates persistent Tasks which may block precompilation of dependent packages. See also Aqua.find_persistent_tasks_deps.\n\nIf you provide an optional expr, this tests whether loading package and running expr creates persistent Tasks. For example, you might start and shutdown a web server, and this will test that there aren't any persistent Tasks.\n\nOn Julia version 1.9 and before, this test always succeeds.\n\nArguments\n\npackage: a top-level Module or Base.PkgId.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test.\ntmax::Real = 5: the maximum time (in seconds) to wait after loading the package before forcibly shutting down the precompilation process (triggering a test failure).\nexpr::Expr = quote end: An expression to run in the precompile package.\n\nnote: Note\nAqua.test_persistent_tasks(package) creates a package with package as a dependency and runs the precompilation process. This requires that package is instantiable with the information in the Project.toml file alone. In particular, this will not work if some of package's dependencies are deved packages or are given as a local path or a git repository in the Manifest.toml.\n\n\n\n\n\n","category":"function"},{"location":"persistent_tasks/#Aqua.find_persistent_tasks_deps","page":"Persistent Tasks","title":"Aqua.find_persistent_tasks_deps","text":"Aqua.find_persistent_tasks_deps(package; broken = Dict{String,Bool}(), kwargs...)\n\nTest all the dependencies of package with Aqua.test_persistent_tasks. On Julia 1.10 and higher, it returns a list of all dependencies failing the test. These are likely the ones blocking precompilation of your package.\n\nAny additional kwargs (e.g., tmax) are passed to Aqua.test_persistent_tasks.\n\n\n\n\n\n","category":"function"},{"location":"deps_compat/#Compat-entries","page":"Compat entries","title":"Compat entries","text":"","category":"section"},{"location":"deps_compat/","page":"Compat entries","title":"Compat entries","text":"In your Project.toml you can (and should) use compat entries to specify with which versions of Julia and your dependencies your package is compatible with. This is important to ease the installation and upgrade of your package for users, and to keep everything working in the case of breaking changes in Julia or your dependencies.","category":"page"},{"location":"deps_compat/","page":"Compat entries","title":"Compat entries","text":"For more details, see the Pkg docs.","category":"page"},{"location":"deps_compat/#test_deps_compat","page":"Compat entries","title":"Test function","text":"","category":"section"},{"location":"deps_compat/","page":"Compat entries","title":"Compat entries","text":"Aqua.test_deps_compat","category":"page"},{"location":"deps_compat/#Aqua.test_deps_compat","page":"Compat entries","title":"Aqua.test_deps_compat","text":"Aqua.test_deps_compat(package)\n\nTest that the Project.toml of package has a compat entry for each package listed under deps and for julia.\n\nArguments\n\npackages: a top-level Module, a Base.PkgId, or a collection of them.\n\nKeyword Arguments\n\nTest choosers\n\ncheck_julia = true: If true, additionally check for a compat entry for \"julia\".\ncheck_extras = true: If true, additionally check \"extras\". A NamedTuple can be used to pass keyword arguments with test options (see below).\ncheck_weakdeps = true: If true, additionally check \"weakdeps\". A NamedTuple can be used to pass keyword arguments with test options (see below).\n\nTest options\n\nIf these keyword arguments are set directly, they only apply to the standard test for \"deps\". To apply them to \"extras\" and \"weakdeps\", pass them as a NamedTuple to the corresponding check_$x keyword argument.\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test for \"deps\".\nignore::Vector{Symbol}: names of dependent packages to be ignored.\n\n\n\n\n\n","category":"function"},{"location":"project_extras/#Project.toml-extras","page":"Project.toml extras","title":"Project.toml extras","text":"","category":"section"},{"location":"project_extras/","page":"Project.toml extras","title":"Project.toml extras","text":"There are two different ways to specify test-only dependencies (see the Pkg docs):","category":"page"},{"location":"project_extras/","page":"Project.toml extras","title":"Project.toml extras","text":"Add the test-only dependencies to the [extras] section of your Project.toml file and use a test target.\nAdd the test-only dependencies to the [deps] section of your test/Project.toml file. This is only available in Julia 1.2 and later.","category":"page"},{"location":"project_extras/","page":"Project.toml extras","title":"Project.toml extras","text":"This test checks checks that, in case you use both methods, the set of test-only dependencies is the same in both ways.","category":"page"},{"location":"project_extras/#test_project_extras","page":"Project.toml extras","title":"Test function","text":"","category":"section"},{"location":"project_extras/","page":"Project.toml extras","title":"Project.toml extras","text":"Aqua.test_project_extras","category":"page"},{"location":"project_extras/#Aqua.test_project_extras","page":"Project.toml extras","title":"Aqua.test_project_extras","text":"test_project_extras(package::Union{Module, PkgId})\ntest_project_extras(packages::Vector{Union{Module, PkgId}})\n\nCheck that test target of the root project and test project (test/Project.toml) are consistent. This is useful for supporting Julia < 1.2 while recording test-only dependency compatibility in test/Project.toml.\n\n\n\n\n\n","category":"function"},{"location":"ambiguities/#Ambiguities","page":"Ambiguities","title":"Ambiguities","text":"","category":"section"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"Method ambiguities are cases where multiple methods are applicable to a given set of arguments, without having a most specific method.","category":"page"},{"location":"ambiguities/#Examples","page":"Ambiguities","title":"Examples","text":"","category":"section"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"One easy example is the following:","category":"page"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"f(x::Int, y::Integer) = 1\nf(x::Integer, y::Int) = 2\n\nprintln(f(1, 2))","category":"page"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"This will throw an MethodError because both methods are equally specific. The solution is to add a third method:","category":"page"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"f(x::Int, y::Int) = ? # `?` is dependent on the use case, most times it will be `1` or `2`","category":"page"},{"location":"ambiguities/#test_ambiguities","page":"Ambiguities","title":"Test function","text":"","category":"section"},{"location":"ambiguities/","page":"Ambiguities","title":"Ambiguities","text":"Aqua.test_ambiguities","category":"page"},{"location":"ambiguities/#Aqua.test_ambiguities","page":"Ambiguities","title":"Aqua.test_ambiguities","text":"test_ambiguities(package::Union{Module, PkgId})\ntest_ambiguities(packages::Vector{Union{Module, PkgId}})\n\nTest that there is no method ambiguities in given package(s). It calls Test.detect_ambiguities in a separated clean process to avoid false-positives.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.\ncolor::Union{Bool, Nothing} = nothing: Enable/disable colorful output if a Bool. nothing (default) means to inherit the setting in the current process.\nexclude::AbstractVector = []: A vector of functions or types to be excluded from ambiguity testing. A function means to exclude all its methods. A type means to exclude all its methods of the callable (sometimes also called \"functor\") and the constructor. That is to say, MyModule.MyType means to ignore ambiguities between (::MyType)(x, y::Int) and (::MyType)(x::Int, y).\nrecursive::Bool = true: Passed to Test.detect_ambiguities. Note that the default here (true) is different from detect_ambiguities. This is for testing ambiguities in methods defined in all sub-modules.\nOther keyword arguments such as imported and ambiguous_bottom are passed to Test.detect_ambiguities as-is.\n\n\n\n\n\n","category":"function"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"EditURL = \"https://github.com/JuliaTesting/Aqua.jl/blob/master/CHANGELOG.md\"","category":"page"},{"location":"release-notes/#Release-notes","page":"Release notes","title":"Release notes","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"All notable changes to this project will be documented in this file.","category":"page"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.","category":"page"},{"location":"release-notes/#Version-[v0.8.9](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.9)-2024-10-15","page":"Release notes","title":"Version v0.8.9 - 2024-10-15","text":"","category":"section"},{"location":"release-notes/#Changed","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Change test_ambiguities to only return ambiguities that happen in the target package. (#309)","category":"page"},{"location":"release-notes/#Version-[v0.8.8](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.8)-2024-10-10","page":"Release notes","title":"Version v0.8.8 - 2024-10-10","text":"","category":"section"},{"location":"release-notes/#Changed-2","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Improved the documentation of test_persisten_tasks. (#297)","category":"page"},{"location":"release-notes/#Version-[v0.8.7](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.7)-2024-04-09","page":"Release notes","title":"Version v0.8.7 - 2024-04-09","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Reverted #285, which was originally released in v0.8.6, but caused a regression. (#287, #288)","category":"page"},{"location":"release-notes/#Version-[v0.8.6](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.6)-2024-04-09","page":"Release notes","title":"Version v0.8.6 - 2024-04-09","text":"","category":"section"},{"location":"release-notes/#Changed-3","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"The output of test_ambiguities now gets printed to stderr instead of stdout. (#281)","category":"page"},{"location":"release-notes/#Version-[v0.8.5](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.5)-2024-04-03","page":"Release notes","title":"Version v0.8.5 - 2024-04-03","text":"","category":"section"},{"location":"release-notes/#Changed-4","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"When supplying broken = true to test_ambiguities, test_undefined_exports, test_piracies, or test_unbound_args, the output is shortened. In particular, the list of offending instances is no longer printed. To get the full output, set broken = false. (#272)\nUse Changelog.jl to generate the changelog, and add it to the documentation. (#277, #279)\ntest_project_extras prints failures the same on all julia versions. In particular, 1.11 and nightly are no outliers. (#275)","category":"page"},{"location":"release-notes/#Version-[v0.8.4](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.4)-2023-12-01","page":"Release notes","title":"Version v0.8.4 - 2023-12-01","text":"","category":"section"},{"location":"release-notes/#Added","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_persistent_tasks now accepts an optional expr to run in the precompile package. (#255)\nThe expr option lets you test whether your precompile script leaves any dangling Tasks\nor Timers, which would make it unsafe to use as a dependency for downstream packages.","category":"page"},{"location":"release-notes/#Version-[v0.8.3](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.3)-2023-11-29","page":"Release notes","title":"Version v0.8.3 - 2023-11-29","text":"","category":"section"},{"location":"release-notes/#Changed-5","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_persistent_tasks is now less noisy. (#256)\nCompletely overhauled the documentation. Every test now has its dedicated page. (#250)","category":"page"},{"location":"release-notes/#Version-[v0.8.2](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.2)-2023-11-16","page":"Release notes","title":"Version v0.8.2 - 2023-11-16","text":"","category":"section"},{"location":"release-notes/#Changed-6","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_persistent_tasks no longer clears the environment of the subtask. Instead, it modifies LOAD_PATH directly to make stdlibs work. (#241)","category":"page"},{"location":"release-notes/#Version-[v0.8.1](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.1)-2023-11-16","page":"Release notes","title":"Version v0.8.1 - 2023-11-16","text":"","category":"section"},{"location":"release-notes/#Changed-7","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_persistent_tasks now redirects stdout and stderr of the created subtask. Furthermore, the environment of the subtask gets cleared to allow default values for JULIA_LOAD_PATH to work. (#240)","category":"page"},{"location":"release-notes/#Version-[v0.8.0](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.8.0)-2023-11-15","page":"Release notes","title":"Version v0.8.0 - 2023-11-15","text":"","category":"section"},{"location":"release-notes/#Added-2","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Two additions check whether packages might block precompilation on Julia 1.10 or higher: (#174)\ntest_persistent_tasks tests whether \"your\" package can safely be used as a dependency for downstream packages. This test is enabled for the default testsuite test_all, but you can opt-out by supplying persistent_tasks=false to test_all. [BREAKING]\nfind_persistent_tasks_deps is useful if \"your\" package hangs upon precompilation: it runs test_persistent_tasks on all the things you depend on, and may help isolate the culprit(s).","category":"page"},{"location":"release-notes/#Changed-8","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"In test_deps_compat, the two subtests check_extras and check_weakdeps are now run by default. (#202) [BREAKING]\ntest_deps_compat now requires compat entries for all dependencies. Stdlibs no longer get ignored. This change is motivated by similar changes in the General registry. (#215) [BREAKING]\ntest_ambiguities now excludes the keyword sorter of all excluded functions with keyword arguments as well. (#203)\ntest_piracy is renamed to test_piracies. (#230) [BREAKING]\ntest_ambiguities and test_piracies now return issues in a defined order. This order may change in a patch release of Aqua.jl. (#233)\nImproved the message for test_project_extras failures. (#234)\ntest_deps_compat now requires a compat entry for julia This can be disabling by setting compat_julia = false. (#236) [BREAKING]","category":"page"},{"location":"release-notes/#Removed","page":"Release notes","title":"Removed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_project_toml_formatting has been removed. Thus, the kwarg project_toml_formatting to test_all no longer exists. (#209) [BREAKING]","category":"page"},{"location":"release-notes/#Version-[v0.7.4](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.4)-2023-10-24","page":"Release notes","title":"Version v0.7.4 - 2023-10-24","text":"","category":"section"},{"location":"release-notes/#Added-3","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_deps_compat has two new kwargs check_extras and check_weakdeps to extend the test to these dependency categories. They are not run by default. (#200)","category":"page"},{"location":"release-notes/#Changed-9","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"The docstring for test_stale_deps explains the situation with package extensions. (#203)\nThe logo of Aqua.jl has been updated. (#128)","category":"page"},{"location":"release-notes/#Version-[v0.7.3](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.3)-2023-09-25","page":"Release notes","title":"Version v0.7.3 - 2023-09-25","text":"","category":"section"},{"location":"release-notes/#Added-4","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_deps_compat has a new kwarg broken to mark the test as broken using Test.@test_broken. (#193)","category":"page"},{"location":"release-notes/#Fixed","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_piracy no longer prints warnings for methods where the third argument is a TypeVar. (#188)","category":"page"},{"location":"release-notes/#Version-[v0.7.2](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.2)-2023-09-19","page":"Release notes","title":"Version v0.7.2 - 2023-09-19","text":"","category":"section"},{"location":"release-notes/#Changed-10","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_undefined_exports additionally prints the modules of the undefined exports in the failure report. (#177)","category":"page"},{"location":"release-notes/#Version-[v0.7.1](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.1)-2023-09-05","page":"Release notes","title":"Version v0.7.1 - 2023-09-05","text":"","category":"section"},{"location":"release-notes/#Fixed-2","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_piracy no longer reports type piracy in the kwsorter, i.e. kwcall should no longer appear in the report. (#171)","category":"page"},{"location":"release-notes/#Version-[v0.7.0](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.7.0)-2023-08-29","page":"Release notes","title":"Version v0.7.0 - 2023-08-29","text":"","category":"section"},{"location":"release-notes/#Added-5","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Installation and usage instructions to the documentation. (#159)","category":"page"},{"location":"release-notes/#Changed-11","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities now allows to exclude non-singleton callables. Excluding a type means to exclude all methods of the callable (sometimes also called \"functor\") and the constructor. (#144) [BREAKING]\ntest_piracy considers more functions. Callables and qualified names are now also checked. (#156) [BREAKING]","category":"page"},{"location":"release-notes/#Fixed-3","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities prints less unnecessary whitespace. (#158)\ntest_ambiguities no longer hangs indefinitely when there are many ambiguities. (#166)","category":"page"},{"location":"release-notes/#Version-[v0.6.7](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.7)-2023-09-19","page":"Release notes","title":"Version v0.6.7 - 2023-09-19","text":"","category":"section"},{"location":"release-notes/#Changed-12","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_undefined_exports additionally prints the modules of the undefined exports in the failure report. (#177)","category":"page"},{"location":"release-notes/#Fixed-4","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities prints less unnecessary whitespace. (#158)\nFix test_piracy for some methods with arguments of custom subtypes of Function. (#170)","category":"page"},{"location":"release-notes/#Version-[v0.6.6](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.6)-2023-08-24","page":"Release notes","title":"Version v0.6.6 - 2023-08-24","text":"","category":"section"},{"location":"release-notes/#Fixed-5","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities no longer hangs indefinitely when there are many ambiguities. (#166)","category":"page"},{"location":"release-notes/#Version-[v0.6.5](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.5)-2023-06-26","page":"Release notes","title":"Version v0.6.5 - 2023-06-26","text":"","category":"section"},{"location":"release-notes/#Fixed-6","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Typo when calling kwargs. (#153)","category":"page"},{"location":"release-notes/#Version-[v0.6.4](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.4)-2023-06-25","page":"Release notes","title":"Version v0.6.4 - 2023-06-25","text":"","category":"section"},{"location":"release-notes/#Added-6","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_piracy has a new kwarg treat_as_own. It is useful for testing packages that deliberately commit some type piracy, e.g. modules adding higher-level functionality to a lightweight C-wrapper, or packages that are extending StatsAPI.jl. (#140)","category":"page"},{"location":"release-notes/#Changed-13","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Explanation of test_unbound_args in the docstring. (#146)","category":"page"},{"location":"release-notes/#Fixed-7","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"Callable objects with type parameters no longer error in test_ambiguities' kwarg exclude. (#142)","category":"page"},{"location":"release-notes/#Version-[v0.6.3](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.3)-2023-06-05","page":"Release notes","title":"Version v0.6.3 - 2023-06-05","text":"","category":"section"},{"location":"release-notes/#Changed-14","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"When installing a method for a union type, it is only reported by test_piracy if all types in the union are foreign (instead of any for arguments). (#131)","category":"page"},{"location":"release-notes/#Fixed-8","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_deps_compat's kwarg ignore now works as intended. (#130)\nWeakdeps are not reported as stale by test_stale_deps anymore. (#135)","category":"page"},{"location":"release-notes/#Version-[v0.6.2](https://github.com/JuliaTesting/Aqua.jl/releases/tag/v0.6.2)-2023-06-02","page":"Release notes","title":"Version v0.6.2 - 2023-06-02","text":"","category":"section"},{"location":"release-notes/#Added-7","page":"Release notes","title":"Added","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_ambiguities, test_undefined_exports, test_piracy, and test_unbound_args each have a new kwarg broken to mark the test as broken using Test.@test_broken. (#124)","category":"page"},{"location":"release-notes/#Changed-15","page":"Release notes","title":"Changed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_piracy now prints the offending methods in a more readable way. (#93)\nExtend test_project_toml_formatting to docs/Project.toml. (#115)","category":"page"},{"location":"release-notes/#Fixed-9","page":"Release notes","title":"Fixed","text":"","category":"section"},{"location":"release-notes/","page":"Release notes","title":"Release notes","text":"test_stale_deps no longer fails if any of the loaded packages prints during loading. (#113)\nClarified the error message of test_unbound_args. (#103)\nClarified the error message of test_project_toml_formatting. (#122)","category":"page"},{"location":"piracies/#Type-piracy","page":"Type piracy","title":"Type piracy","text":"","category":"section"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"Type piracy is a term used to describe adding methods to a foreign function with only foreign arguments. This is considered bad practice because it can cause unexpected behavior when the function is called, in particular, it can change the behavior of one of your dependencies depending on if your package is loaded or not. This makes it hard to reason about the behavior of your code, and may introduce bugs that are hard to track down.","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"See Julia documentation for more information about type piracy.","category":"page"},{"location":"piracies/#Examples","page":"Type piracy","title":"Examples","text":"","category":"section"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"Say that PkgA is foreign, and let's look at the different ways that PkgB extends its function bar.","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"module PkgA\n struct C end\n bar(x::C) = 42\n bar(x::Vector) = 43\nend\n\nmodule PkgB \n import PkgA: bar, C\n struct D end\n bar(x::C) = 1\n bar(xs::D...) = 2\n bar(x::Vector{<:D}) = 3\n bar(x::Vector{D}) = 4 # slightly bad (may cause invalidations)\n bar(x::Union{C,D}) = 5 # slightly bad (a change in PkgA may turn it into piracy)\n # (for example changing bar(x::C) = 1 to bar(x::Union{C,Int}) = 1)\nend","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"The following cases are enumerated by the return values in the example above:","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"This is the worst case of type piracy. The value of bar(C()) can be either 1 or 42 and will depend on whether PkgB is loaded or not.\nThis is also a bad case of type piracy. bar() throws a MethodError with only PkgA available, and returns 2 with PkgB loaded. PkgA may add a method for bar() that takes no arguments in the future, and then this is equivalent to case 1.\nThis is a moderately bad case of type piracy. bar(Union{}[]) returns 3 when PkgB is loaded, and 43 when PkgB is not loaded, although neither of the occurring types are defined in PkgB. This case is not as bad as cases 1 and 2, because it is only about behavior around Union{}, which has no instances.\nDepending on ones understanding of type piracy, this could be considered piracy as well. In particular, this may cause invalidations.\nThis is a slightly bad case of type piracy. In the current form, bar(C()) returns 42 as the dispatch on Union{C,D} is less specific. However, a future change in PkgA may change this behavior, e.g. by changing bar(x::C) to bar(x::Union{C,Int}) the call bar(C()) would become ambiguous.","category":"page"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"note: Note\nThe test function below currently only checks for cases 1 and 2.","category":"page"},{"location":"piracies/#test_piracies","page":"Type piracy","title":"Test function","text":"","category":"section"},{"location":"piracies/","page":"Type piracy","title":"Type piracy","text":"Aqua.test_piracies","category":"page"},{"location":"piracies/#Aqua.test_piracies","page":"Type piracy","title":"Aqua.test_piracies","text":"test_piracies(m::Module)\n\nTest that m does not commit type piracies.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.\nskip_deprecated::Bool = true: If true, it does not check deprecated methods.\ntreat_as_own = Union{Function, Type}[]: The types in this container are considered to be \"owned\" by the module m. This is useful for testing packages that deliberately commit some type piracies, e.g. modules adding higher-level functionality to a lightweight C-wrapper, or packages that are extending StatsAPI.jl.\n\n\n\n\n\n","category":"function"},{"location":"unbound_args/#Unbound-Type-Parameters","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"","category":"section"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"An unbound type parameter is a type parameter with a where, that does not occur in the signature of some dispatch of the method.","category":"page"},{"location":"unbound_args/#Examples","page":"Unbound Type Parameters","title":"Examples","text":"","category":"section"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"The following methods each have T as an unbound type parameter:","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"f(x::Int) where {T} = do_something(x)\ng(x::T...) where {T} = println(T)","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"In the cases of f above, the unbound type parameter T is neither present in the signature of the methods nor as a bound of another type parameter. Here, the type parameter T can be removed without changing any semantics.","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"For signatures with Vararg (cf. g above), the type parameter is unbound for the zero-argument case (e.g. g()).","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"g(1.0, 2.0)\ng(1)\ng()","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"A possible fix would be to replace g by two methods.","category":"page"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"g() = println(Int) # Defaults to `Int`\ng(x1::T, x2::T...) where {T} = println(T)\ng(1.0, 2.0)\ng(1)\ng()","category":"page"},{"location":"unbound_args/#test_unbound_args","page":"Unbound Type Parameters","title":"Test function","text":"","category":"section"},{"location":"unbound_args/","page":"Unbound Type Parameters","title":"Unbound Type Parameters","text":"Aqua.test_unbound_args","category":"page"},{"location":"unbound_args/#Aqua.test_unbound_args","page":"Unbound Type Parameters","title":"Aqua.test_unbound_args","text":"test_unbound_args(module::Module)\n\nTest that all methods in module and its submodules do not have unbound type parameters. An unbound type parameter is a type parameter with a where, that does not occur in the signature of some dispatch of the method.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.\n\n\n\n\n\n","category":"function"},{"location":"stale_deps/#Stale-dependencies","page":"Stale dependencies","title":"Stale dependencies","text":"","category":"section"},{"location":"stale_deps/#test_stale_deps","page":"Stale dependencies","title":"Test function","text":"","category":"section"},{"location":"stale_deps/","page":"Stale dependencies","title":"Stale dependencies","text":"Aqua.test_stale_deps","category":"page"},{"location":"stale_deps/#Aqua.test_stale_deps","page":"Stale dependencies","title":"Aqua.test_stale_deps","text":"Aqua.test_stale_deps(package; [ignore])\n\nTest that package loads all dependencies listed in Project.toml. Note that this does not imply that package loads the dependencies directly, this can be achieved via transitivity as well.\n\nnote: Weak dependencies and extensions\nDue to the automatic loading of package extensions once all of their trigger dependencies are loaded, Aqua.jl can, by design of julia, not check if a package extension indeed loads all of its trigger dependencies using import or using. \n\nwarning: Known bug\nCurrently, Aqua.test_stale_deps does not detect stale dependencies when they are in the sysimage. This is considered a bug and may be fixed in the future. Such a release is considered non-breaking.\n\nArguments\n\npackages: a top-level Module, a Base.PkgId, or a collection of them.\n\nKeyword Arguments\n\nignore::Vector{Symbol}: names of dependent packages to be ignored.\n\n\n\n\n\n","category":"function"},{"location":"exports/#Undefined-exports","page":"Undefined exports","title":"Undefined exports","text":"","category":"section"},{"location":"exports/#test_undefined_exports","page":"Undefined exports","title":"Test function","text":"","category":"section"},{"location":"exports/","page":"Undefined exports","title":"Undefined exports","text":"Aqua.test_undefined_exports","category":"page"},{"location":"exports/#Aqua.test_undefined_exports","page":"Undefined exports","title":"Aqua.test_undefined_exports","text":"test_undefined_exports(module::Module)\n\nTest that all exported names in module actually exist.\n\nKeyword Arguments\n\nbroken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.\n\n\n\n\n\n","category":"function"},{"location":"test_all/#test_all","page":"Test everything","title":"Test everything","text":"","category":"section"},{"location":"test_all/","page":"Test everything","title":"Test everything","text":"This test runs most of the other tests in this module. The defaults should be fine for most packages. If you have a package that needs to customize the test, you can do so by providing appropriate keyword arguments to Aqua.test_all() (see below)","category":"page"},{"location":"test_all/","page":"Test everything","title":"Test everything","text":"Aqua.test_all","category":"page"},{"location":"test_all/#Aqua.test_all","page":"Test everything","title":"Aqua.test_all","text":"test_all(testtarget::Module)\n\nRun the following tests:\n\ntest_ambiguities([testtarget])\ntest_unbound_args(testtarget)\ntest_undefined_exports(testtarget)\ntest_project_extras(testtarget)\ntest_stale_deps(testtarget)\ntest_deps_compat(testtarget)\ntest_piracies(testtarget)\ntest_persistent_tasks(testtarget)\n\nThe keyword argument $x (e.g., ambiguities) can be used to control whether or not to run test_$x (e.g., test_ambiguities). If test_$x supports keyword arguments, a NamedTuple can also be passed to $x to specify the keyword arguments for test_$x.\n\nKeyword Arguments\n\nambiguities = true\nunbound_args = true\nundefined_exports = true\nproject_extras = true\nstale_deps = true\ndeps_compat = true\npiracies = true\npersistent_tasks = true\n\n\n\n\n\n","category":"function"},{"location":"#Aqua.jl:-*A*uto-*QU*ality-*A*ssurance-for-Julia-packages","page":"Home","title":"Aqua.jl: Auto QUality Assurance for Julia packages","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Aqua.jl provides functions to run a few automatable checks for Julia packages:","category":"page"},{"location":"","page":"Home","title":"Home","text":"There are no method ambiguities.\nThere are no undefined exports.\nThere are no unbound type parameters.\nThere are no stale dependencies listed in Project.toml.\nCheck that test target of the root project Project.toml and test project (test/Project.toml) are consistent.\nCheck that all external packages listed in deps have corresponding compat entries.\nThere are no \"obvious\" type piracies.\nThe package does not create any persistent Tasks that might block precompilation of dependencies.","category":"page"},{"location":"#Quick-usage","page":"Home","title":"Quick usage","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Call Aqua.test_all(YourPackage) from the REPL, e.g.,","category":"page"},{"location":"","page":"Home","title":"Home","text":"using YourPackage\nusing Aqua\nAqua.test_all(YourPackage)","category":"page"},{"location":"#How-to-add-Aqua.jl...","page":"Home","title":"How to add Aqua.jl...","text":"","category":"section"},{"location":"#...as-a-test-dependency?","page":"Home","title":"...as a test dependency?","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"There are two ways to add Aqua.jl as a test dependency to your package. To avoid breaking tests when a new Aqua.jl version is released, it is recommended to add a version bound for Aqua.jl.","category":"page"},{"location":"","page":"Home","title":"Home","text":"In YourPackage/test/Project.toml, add Aqua.jl to [dep] and [compat] sections, like\n[deps]\nAqua = \"4c88cf16-eb10-579e-8560-4a9242c79595\"\nTest = \"8dfed614-e22c-5e08-85e1-65c5234f0b40\"\n\n[compat]\nAqua = \"0.8\"\nIn YourPackage/Project.toml, add Aqua.jl to [compat] and [extras] section and the test target, like\n[compat]\nAqua = \"0.8\"\n\n[extras]\nAqua = \"4c88cf16-eb10-579e-8560-4a9242c79595\"\nTest = \"8dfed614-e22c-5e08-85e1-65c5234f0b40\"\n\n[targets]\ntest = [\"Aqua\", \"Test\"]","category":"page"},{"location":"","page":"Home","title":"Home","text":"If your package supports Julia pre-1.2, you need to use the second approach, although you can use both approaches at the same time.","category":"page"},{"location":"","page":"Home","title":"Home","text":"warning: Warning\nIn normal use, Aqua.jl should not be added to [deps] in YourPackage/Project.toml!","category":"page"},{"location":"#...to-your-tests?","page":"Home","title":"...to your tests?","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"It is recommended to create a separate file YourPackage/test/Aqua.jl that gets included in YourPackage/test/runtests.jl with either","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Aqua\nAqua.test_all(YourPackage)","category":"page"},{"location":"","page":"Home","title":"Home","text":"or some fine-grained checks with options, e.g.,","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Aqua\n\n@testset \"Aqua.jl\" begin\n Aqua.test_all(\n YourPackage;\n ambiguities=(exclude=[SomePackage.some_function], broken=true),\n stale_deps=(ignore=[:SomePackage],),\n deps_compat=(ignore=[:SomeOtherPackage],),\n piracies=false,\n )\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"Note, that for all tests with no explicit options provided, the default options are used.","category":"page"},{"location":"","page":"Home","title":"Home","text":"For more details on the options, see the respective functions here.","category":"page"},{"location":"#Examples","page":"Home","title":"Examples","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The following is a small selection of packages that use Aqua.jl:","category":"page"},{"location":"","page":"Home","title":"Home","text":"GAP.jl\nHecke.jl\nOscar.jl","category":"page"}] } diff --git a/dev/stale_deps/index.html b/dev/stale_deps/index.html index 3d62f14..99fbd31 100644 --- a/dev/stale_deps/index.html +++ b/dev/stale_deps/index.html @@ -1,2 +1,2 @@ -Stale dependencies · Aqua.jl

Stale dependencies

Test function

Aqua.test_stale_depsFunction
Aqua.test_stale_deps(package; [ignore])

Test that package loads all dependencies listed in Project.toml. Note that this does not imply that package loads the dependencies directly, this can be achieved via transitivity as well.

Weak dependencies and extensions

Due to the automatic loading of package extensions once all of their trigger dependencies are loaded, Aqua.jl can, by design of julia, not check if a package extension indeed loads all of its trigger dependencies using import or using.

Known bug

Currently, Aqua.test_stale_deps does not detect stale dependencies when they are in the sysimage. This is considered a bug and may be fixed in the future. Such a release is considered non-breaking.

Arguments

  • packages: a top-level Module, a Base.PkgId, or a collection of them.

Keyword Arguments

  • ignore::Vector{Symbol}: names of dependent packages to be ignored.
source
+Stale dependencies · Aqua.jl

Stale dependencies

Test function

Aqua.test_stale_depsFunction
Aqua.test_stale_deps(package; [ignore])

Test that package loads all dependencies listed in Project.toml. Note that this does not imply that package loads the dependencies directly, this can be achieved via transitivity as well.

Weak dependencies and extensions

Due to the automatic loading of package extensions once all of their trigger dependencies are loaded, Aqua.jl can, by design of julia, not check if a package extension indeed loads all of its trigger dependencies using import or using.

Known bug

Currently, Aqua.test_stale_deps does not detect stale dependencies when they are in the sysimage. This is considered a bug and may be fixed in the future. Such a release is considered non-breaking.

Arguments

  • packages: a top-level Module, a Base.PkgId, or a collection of them.

Keyword Arguments

  • ignore::Vector{Symbol}: names of dependent packages to be ignored.
source
diff --git a/dev/test_all/index.html b/dev/test_all/index.html index ca55d39..ed7e308 100644 --- a/dev/test_all/index.html +++ b/dev/test_all/index.html @@ -1,2 +1,2 @@ -Test everything · Aqua.jl

Test everything

This test runs most of the other tests in this module. The defaults should be fine for most packages. If you have a package that needs to customize the test, you can do so by providing appropriate keyword arguments to Aqua.test_all() (see below)

Aqua.test_allFunction
test_all(testtarget::Module)

Run the following tests:

The keyword argument $x (e.g., ambiguities) can be used to control whether or not to run test_$x (e.g., test_ambiguities). If test_$x supports keyword arguments, a NamedTuple can also be passed to $x to specify the keyword arguments for test_$x.

Keyword Arguments

  • ambiguities = true
  • unbound_args = true
  • undefined_exports = true
  • project_extras = true
  • stale_deps = true
  • deps_compat = true
  • piracies = true
  • persistent_tasks = true
source
+Test everything · Aqua.jl

Test everything

This test runs most of the other tests in this module. The defaults should be fine for most packages. If you have a package that needs to customize the test, you can do so by providing appropriate keyword arguments to Aqua.test_all() (see below)

Aqua.test_allFunction
test_all(testtarget::Module)

Run the following tests:

The keyword argument $x (e.g., ambiguities) can be used to control whether or not to run test_$x (e.g., test_ambiguities). If test_$x supports keyword arguments, a NamedTuple can also be passed to $x to specify the keyword arguments for test_$x.

Keyword Arguments

  • ambiguities = true
  • unbound_args = true
  • undefined_exports = true
  • project_extras = true
  • stale_deps = true
  • deps_compat = true
  • piracies = true
  • persistent_tasks = true
source
diff --git a/dev/unbound_args/index.html b/dev/unbound_args/index.html index 71b8066..99213fa 100644 --- a/dev/unbound_args/index.html +++ b/dev/unbound_args/index.html @@ -1,4 +1,4 @@ Unbound Type Parameters · Aqua.jl

Unbound Type Parameters

An unbound type parameter is a type parameter with a where, that does not occur in the signature of some dispatch of the method.

Examples

The following methods each have T as an unbound type parameter:

julia> f(x::Int) where {T} = do_something(x)WARNING: method definition for f at REPL[1]:1 declares type variable T but does not use it.
 f (generic function with 1 method)
julia> g(x::T...) where {T} = println(T)g (generic function with 1 method)

In the cases of f above, the unbound type parameter T is neither present in the signature of the methods nor as a bound of another type parameter. Here, the type parameter T can be removed without changing any semantics.

For signatures with Vararg (cf. g above), the type parameter is unbound for the zero-argument case (e.g. g()).

julia> g(1.0, 2.0)Float64
julia> g(1)Int64
julia> g()ERROR: UndefVarError: `T` not defined in static parameter matching -Suggestion: run Test.detect_unbound_args to detect method arguments that do not fully constrain a type parameter.

A possible fix would be to replace g by two methods.

julia> g() = println(Int)  # Defaults to `Int`g (generic function with 1 method)
julia> g(x1::T, x2::T...) where {T} = println(T)g (generic function with 2 methods)
julia> g(1.0, 2.0)Float64
julia> g(1)Int64
julia> g()Int64

Test function

Aqua.test_unbound_argsFunction
test_unbound_args(module::Module)

Test that all methods in module and its submodules do not have unbound type parameters. An unbound type parameter is a type parameter with a where, that does not occur in the signature of some dispatch of the method.

Keyword Arguments

  • broken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.
source
+Suggestion: run Test.detect_unbound_args to detect method arguments that do not fully constrain a type parameter.

A possible fix would be to replace g by two methods.

julia> g() = println(Int)  # Defaults to `Int`g (generic function with 1 method)
julia> g(x1::T, x2::T...) where {T} = println(T)g (generic function with 2 methods)
julia> g(1.0, 2.0)Float64
julia> g(1)Int64
julia> g()Int64

Test function

Aqua.test_unbound_argsFunction
test_unbound_args(module::Module)

Test that all methods in module and its submodules do not have unbound type parameters. An unbound type parameter is a type parameter with a where, that does not occur in the signature of some dispatch of the method.

Keyword Arguments

  • broken::Bool = false: If true, it uses @test_broken instead of @test and shortens the error message.
source