From 20ff589fd8b5cb9e5a4f6f03a887781073ce5eaf Mon Sep 17 00:00:00 2001 From: Jan Philipp Thiele Date: Thu, 20 Nov 2025 20:28:59 +0100 Subject: [PATCH 1/4] PROOF OF CONCEPT: a function to write extension functions with matching warning --- src/io.jl | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/io.jl b/src/io.jl index 553aa026..5dfc240d 100644 --- a/src/io.jl +++ b/src/io.jl @@ -7,6 +7,30 @@ WriteVTK.VTKCellType(::Type{<:Quadrilateral2D}) = VTKCellTypes.VTK_QUAD WriteVTK.VTKCellType(::Type{<:Tetrahedron3D}) = VTKCellTypes.VTK_TETRA WriteVTK.VTKCellType(::Type{<:Hexahedron3D}) = VTKCellTypes.VTK_HEXAHEDRON +function prepare_extension_function(fname::Symbol,x) + expr = quote + function $fname($x;kwargs...) + @info "single parameter function" + end + end + eval(expr) +end + +function prepare_extension_function(fname::Symbol,weakdeps::Vector{Symbol},x::Symbol) + expr = quote + function $fname($x;kwargs...) + if mapreduce(x->x in names(Main,imported=true),&,$weakdeps) + @error "Extension was loaded but argument types are wrong" + else + @error "This specific function is part of an extension.\n"* + "To use it install and load the following modules:"* + mapreduce(x->"\n"*x,*,String.($weakdeps)) + end + end + end + eval(expr) +end + """ $(TYPEDSIGNATURES) @@ -162,19 +186,11 @@ function simplexgrid(file::String; format = "", kwargs...) end function simplexgrid(file::String, ::Type{Val{:msh}}; kwargs...) - return try - simplexgrid_from_gmsh(file) - catch e - throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read msh files.")) - end + return simplexgrid_from_gmsh(file) end function simplexgrid(file::String, ::Type{Val{:geo}}; kwargs...) - return try - simplexgrid_from_gmsh(file) - catch e - throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read geo files.")) - end + return simplexgrid_from_gmsh(file) end function simplexgrid(file::String, ::Type{Val{:sg}}; kwargs...) @@ -272,7 +288,10 @@ function simplexgrid(file::String, ::Type{Val{:sg}}; kwargs...) return g end -function simplexgrid_from_gmsh end +prepare_extension_function(:simplexgrid_from_gmsh,[:Gmsh],:filename) +# function simplexgrid_from_gmsh(filename; incomplete = false, Tc = Float32, Ti = Int32) +# throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read msh or geo files.")) +# end function simplexgrid_to_gmsh end From 83f7d0f1aae3cb3696779504001d8d4212b28426 Mon Sep 17 00:00:00 2001 From: Jan Philipp Thiele Date: Fri, 21 Nov 2025 09:28:19 +0100 Subject: [PATCH 2/4] Add new Extension Exceptions --- src/io.jl | 56 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/io.jl b/src/io.jl index 5dfc240d..fae2ee28 100644 --- a/src/io.jl +++ b/src/io.jl @@ -7,28 +7,50 @@ WriteVTK.VTKCellType(::Type{<:Quadrilateral2D}) = VTKCellTypes.VTK_QUAD WriteVTK.VTKCellType(::Type{<:Tetrahedron3D}) = VTKCellTypes.VTK_TETRA WriteVTK.VTKCellType(::Type{<:Hexahedron3D}) = VTKCellTypes.VTK_HEXAHEDRON -function prepare_extension_function(fname::Symbol,x) - expr = quote - function $fname($x;kwargs...) - @info "single parameter function" - end - end - eval(expr) +struct ExtensionLoadError <: Exception + fname::Symbol + weakdeps::Vector{Symbol} +end + +Base.showerror(io::IO, e::ExtensionLoadError) = + print( + io, + "ExtensionLoadError: " + * "The function " * String(e.fname) * " is part of an extension.\n" + * "Suggestion: Install and load the following modules:" + * mapreduce(x -> "\n" * x, *, String.(e.weakdeps)) +) + +struct ExtensionMethodError <: Exception + fn::Function + x +end + + +function Base.showerror(io::IO, e::ExtensionMethodError) + fname = String(nameof(e.fn)) + print( + io, + "ExtensionMethodError: no method matching " * fname * "(::" * String(nameof(typeof(e.x))) * ")\n" + * "The function " * fname * " exists in a loaded extension, but no method is defined for this combination of argument types.\n" + * "\n" + * "Candidates are:\n" + ) + return println.(io, filter(x -> x != which(e.fn, (typeof(e.x),)), methods(e.fn))) end -function prepare_extension_function(fname::Symbol,weakdeps::Vector{Symbol},x::Symbol) +function prepare_extension_function(fname::Symbol, weakdeps::Vector{Symbol}, x::Symbol) expr = quote - function $fname($x;kwargs...) - if mapreduce(x->x in names(Main,imported=true),&,$weakdeps) - @error "Extension was loaded but argument types are wrong" + function $fname($x; kwargs...) + if mapreduce(x -> isdefined(Main, x), &, $weakdeps) + throw(ExtensionMethodError($fname, $x)) else - @error "This specific function is part of an extension.\n"* - "To use it install and load the following modules:"* - mapreduce(x->"\n"*x,*,String.($weakdeps)) + throw(ExtensionLoadError(nameof($fname), $weakdeps)) end + return nothing end end - eval(expr) + return eval(expr) end """ @@ -288,8 +310,8 @@ function simplexgrid(file::String, ::Type{Val{:sg}}; kwargs...) return g end -prepare_extension_function(:simplexgrid_from_gmsh,[:Gmsh],:filename) -# function simplexgrid_from_gmsh(filename; incomplete = false, Tc = Float32, Ti = Int32) +prepare_extension_function(:simplexgrid_from_gmsh, [:Gmsh], :filename) +# function simplexgrid_from_gmsh(filename; incomplete = false, Tc = Float32, Ti = Int32) # throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read msh or geo files.")) # end From bbe61b7b676cf3a38ecfd21068683140b6702a4a Mon Sep 17 00:00:00 2001 From: Jan Philipp Thiele Date: Thu, 27 Nov 2025 11:37:28 +0100 Subject: [PATCH 3/4] prepare_extension_function works with multiple args --- src/io.jl | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/io.jl b/src/io.jl index fae2ee28..ed353a62 100644 --- a/src/io.jl +++ b/src/io.jl @@ -23,27 +23,30 @@ Base.showerror(io::IO, e::ExtensionLoadError) = struct ExtensionMethodError <: Exception fn::Function - x + args::Tuple end function Base.showerror(io::IO, e::ExtensionMethodError) fname = String(nameof(e.fn)) - print( - io, - "ExtensionMethodError: no method matching " * fname * "(::" * String(nameof(typeof(e.x))) * ")\n" - * "The function " * fname * " exists in a loaded extension, but no method is defined for this combination of argument types.\n" - * "\n" - * "Candidates are:\n" + argtypes = typeof.(e.args) + println(io, + "ExtensionMethodError: no method matching " * fname + * "(" * join(map(x-> "::"*String(nameof(x)),argtypes),',') + * ")") + println(io,"The function " * fname * " exists in a loaded extension," + *" but no method is defined for this combination of argument types.\n" + * "\nCandidates are:\n" ) - return println.(io, filter(x -> x != which(e.fn, (typeof(e.x),)), methods(e.fn))) + println.(io, filter(x -> x != which(e.fn, (argtypes...,)), methods(e.fn))) + return nothing end -function prepare_extension_function(fname::Symbol, weakdeps::Vector{Symbol}, x::Symbol) +function prepare_extension_function(fname::Symbol, weakdeps::Vector{Symbol}, args::Vector{Symbol}) expr = quote - function $fname($x; kwargs...) - if mapreduce(x -> isdefined(Main, x), &, $weakdeps) - throw(ExtensionMethodError($fname, $x)) + function $fname($(args...); kwargs...) + if mapreduce(x -> isdefined(Main, x) && isa(getfield(Main,x),Module), &, $weakdeps) + throw(ExtensionMethodError($fname, ($(args...),))) else throw(ExtensionLoadError(nameof($fname), $weakdeps)) end @@ -310,11 +313,12 @@ function simplexgrid(file::String, ::Type{Val{:sg}}; kwargs...) return g end -prepare_extension_function(:simplexgrid_from_gmsh, [:Gmsh], :filename) +prepare_extension_function(:simplexgrid_from_gmsh, [:Gmsh], [:filename]) # function simplexgrid_from_gmsh(filename; incomplete = false, Tc = Float32, Ti = Int32) # throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read msh or geo files.")) # end + function simplexgrid_to_gmsh end function mixedgrid_from_gmsh end From 7b84348cda1e59c6109e67d44b06ac5f1d0e27f1 Mon Sep 17 00:00:00 2001 From: Jan Philipp Thiele Date: Tue, 16 Dec 2025 15:50:28 +0100 Subject: [PATCH 4/4] Use new package ExtensionErrors --- Project.toml | 7 ++++++- src/io.jl | 59 +++------------------------------------------------- 2 files changed, 9 insertions(+), 57 deletions(-) diff --git a/Project.toml b/Project.toml index 42e505df..de922ccd 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ExtendableGrids" uuid = "cfc395e8-590f-11e8-1f13-43a2532b2fa8" -authors = ["Juergen Fuhrmann ", "Christian Merdon ", "Johannes Taraz ", "Patrick Jaap "] version = "1.14.2" +authors = ["Juergen Fuhrmann ", "Christian Merdon ", "Johannes Taraz ", "Patrick Jaap "] [deps] AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" @@ -10,6 +10,7 @@ Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" ElasticArrays = "fdbdab4c-e67f-52f5-8c3f-e7b388dad3d4" +ExtensionErrors = "b7d44a4a-b691-4b61-aae1-e3eded184641" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" @@ -27,6 +28,9 @@ Metis = "2679e427-3c69-5b7f-982b-ece356f1e94b" TetGen = "c5d3f3f7-f850-59f6-8a2e-ffc6dc1317ea" Triangulate = "f7e6ffb2-c36d-4f8f-a77e-16e897189344" +[sources] +ExtensionErrors = {rev = "main", url = "https://github.com/jpthiele/ExtensionErrors.jl.git"} + [extensions] ExtendableGridsGmshExt = "Gmsh" ExtendableGridsMetisExt = "Metis" @@ -40,6 +44,7 @@ Compat = "4.10" Dates = "1.9" DocStringExtensions = "0.8,0.9" ElasticArrays = "1" +ExtensionErrors = "1.0.0" Gmsh = "0.2.2,0.3" Graphs = "1.11.1" InteractiveUtils = "1.9" diff --git a/src/io.jl b/src/io.jl index ed353a62..b9bc2c5e 100644 --- a/src/io.jl +++ b/src/io.jl @@ -1,5 +1,5 @@ using WriteVTK - +using ExtensionErrors # conversion from AbstractElementGeometry to WriteVTK.VTKCellTypes WriteVTK.VTKCellType(::Type{<:AbstractElementGeometry1D}) = VTKCellTypes.VTK_LINE WriteVTK.VTKCellType(::Type{<:Triangle2D}) = VTKCellTypes.VTK_TRIANGLE @@ -7,55 +7,6 @@ WriteVTK.VTKCellType(::Type{<:Quadrilateral2D}) = VTKCellTypes.VTK_QUAD WriteVTK.VTKCellType(::Type{<:Tetrahedron3D}) = VTKCellTypes.VTK_TETRA WriteVTK.VTKCellType(::Type{<:Hexahedron3D}) = VTKCellTypes.VTK_HEXAHEDRON -struct ExtensionLoadError <: Exception - fname::Symbol - weakdeps::Vector{Symbol} -end - -Base.showerror(io::IO, e::ExtensionLoadError) = - print( - io, - "ExtensionLoadError: " - * "The function " * String(e.fname) * " is part of an extension.\n" - * "Suggestion: Install and load the following modules:" - * mapreduce(x -> "\n" * x, *, String.(e.weakdeps)) -) - -struct ExtensionMethodError <: Exception - fn::Function - args::Tuple -end - - -function Base.showerror(io::IO, e::ExtensionMethodError) - fname = String(nameof(e.fn)) - argtypes = typeof.(e.args) - println(io, - "ExtensionMethodError: no method matching " * fname - * "(" * join(map(x-> "::"*String(nameof(x)),argtypes),',') - * ")") - println(io,"The function " * fname * " exists in a loaded extension," - *" but no method is defined for this combination of argument types.\n" - * "\nCandidates are:\n" - ) - println.(io, filter(x -> x != which(e.fn, (argtypes...,)), methods(e.fn))) - return nothing -end - -function prepare_extension_function(fname::Symbol, weakdeps::Vector{Symbol}, args::Vector{Symbol}) - expr = quote - function $fname($(args...); kwargs...) - if mapreduce(x -> isdefined(Main, x) && isa(getfield(Main,x),Module), &, $weakdeps) - throw(ExtensionMethodError($fname, ($(args...),))) - else - throw(ExtensionLoadError(nameof($fname), $weakdeps)) - end - return nothing - end - end - return eval(expr) -end - """ $(TYPEDSIGNATURES) @@ -313,14 +264,10 @@ function simplexgrid(file::String, ::Type{Val{:sg}}; kwargs...) return g end -prepare_extension_function(:simplexgrid_from_gmsh, [:Gmsh], [:filename]) -# function simplexgrid_from_gmsh(filename; incomplete = false, Tc = Float32, Ti = Int32) -# throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read msh or geo files.")) -# end - +@extensionfunction simplexgrid_from_gmsh(filename;incomplete=false,Tc = Float32,Ti=Int32) Gmsh function simplexgrid_to_gmsh end -function mixedgrid_from_gmsh end +@extensionfunction mixedgrid_from_gmsh(filename;Tc = Float32, Ti = Int32) Gmsh function mixedgrid_to_gmsh end