From d8b7ba1796f9dd93b7db3ab7f4e0c9fce6e3e036 Mon Sep 17 00:00:00 2001 From: m-wells Date: Fri, 14 Feb 2020 13:26:15 -0500 Subject: [PATCH] better error messages --- Project.toml | 2 +- README.ipynb | 79 +++++++++++++++++++++----------------- README.md | 73 ++++++++++++++++++----------------- src/AlignedBinaryFormat.jl | 20 +++++----- src/abffile.jl | 2 +- src/abfkey.jl | 10 ++--- src/read_write.jl | 13 ++++--- src/showio.jl | 2 +- test/runtests.jl | 33 +++++++++++++++- 9 files changed, 137 insertions(+), 97 deletions(-) diff --git a/Project.toml b/Project.toml index da90f42..1236484 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "AlignedBinaryFormat" uuid = "94fc9360-1a5e-4d84-93be-ddbadb32b3a7" authors = ["m-wells "] -version = "0.5.0" +version = "0.5.1" [deps] Mmap = "a63ad114-7e13-5084-954f-fe012c677804" diff --git a/README.ipynb b/README.ipynb index 90bc22b..aa1e8e6 100644 --- a/README.ipynb +++ b/README.ipynb @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -85,15 +85,22 @@ "execution_count": 4, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "string(AbfSerializer) = \"AbfSerializer\"\n" + ] + }, { "data": { "text/plain": [ - "AlignedBinaryFormat.AbfFile([read] )\n", + "AlignedBinaryFormat.AbfFile([read] )\n", "┌────────────┬──────────────────┬───────────┬────────┬────────────┐\n", "│ label │ type │ shape │ bytes │ status │\n", "├────────────┼──────────────────┼───────────┼────────┼────────────┤\n", "│ bitmat │ BitArray{2} │ (3, 2) │ <8B> │ unloaded │\n", - "│ foo │ Foo │ (-1,) │ <118B> │ unloaded │\n", + "│ foo │ Foo │ (-1,) │ <121B> │ unloaded │\n", "│ log │ String │ (28,) │ <112B> │ unloaded │\n", "│ my x array │ Array{Float16,1} │ (4,) │ <8B> │ unloaded │\n", "│ type │ DataType │ (-1,) │ <23B> │ unloaded │\n", @@ -119,7 +126,7 @@ "\n", "abfopen(temp, \"r+\") do abf\n", " write(abf, \"type\", Bar)\n", - " write(abf, \"foo\", Serialized(Foo(rand(3), -1)))\n", + " write(abf, \"foo\", AbfSerializer(Foo(rand(3), -1)))\n", "end\n", "\n", "abf = abfopen(temp, \"r\")" @@ -144,16 +151,16 @@ "name": "stdout", "output_type": "stream", "text": [ - "count(abf[\"bitmat\"]) = 2\n", + "count(abf[\"bitmat\"]) = 5\n", "this is what I did\n", "and how!\n", "\n", - "AlignedBinaryFormat.AbfFile([read] )\n", + "AlignedBinaryFormat.AbfFile([read] )\n", "┌────────────┬──────────────────┬───────────┬────────┬────────────┐\n", "│ label │ type │ shape │ bytes │ status │\n", "├────────────┼──────────────────┼───────────┼────────┼────────────┤\n", "│ bitmat │ BitArray{2} │ (3, 2) │ <8B> │ loaded │\n", - "│ foo │ Foo │ (-1,) │ <118B> │ unloaded │\n", + "│ foo │ Foo │ (-1,) │ <121B> │ unloaded │\n", "│ log │ String │ (28,) │ <112B> │ loaded │\n", "│ my x array │ Array{Float16,1} │ (4,) │ <8B> │ loaded │\n", "│ type │ DataType │ (-1,) │ <23B> │ unloaded │\n", @@ -216,18 +223,18 @@ "output_type": "stream", "text": [ "x = 10-element Array{Float64,1}:\n", - " 0.13117086919645993\n", - " 0.8140523381099063 \n", - " 0.44152928499795685\n", - " 0.6776307667284676 \n", - " 0.2542185344974299 \n", - " 0.6641164907956227 \n", - " 0.6446525613063578 \n", - " 0.17166524697749908\n", - " 0.0775201232187761 \n", - " 0.6548927372122209 \n", + " 0.41808342392430364\n", + " 0.8340965780634206 \n", + " 0.4422525925297145 \n", + " 0.7464876087842214 \n", + " 0.8760053500303144 \n", + " 0.8812312947613306 \n", + " 0.12907825453926614\n", + " 0.8227926275555029 \n", + " 0.5770610771209626 \n", + " 0.2427376128034029 \n", "\n", - "AlignedBinaryFormat.AbfFile([read/write] )\n", + "AlignedBinaryFormat.AbfFile([read/write] )\n", "┌───────┬──────────────────┬───────┬───────┬────────┐\n", "│ label │ type │ shape │ bytes │ status │\n", "├───────┼──────────────────┼───────┼───────┼────────┤\n", @@ -235,23 +242,23 @@ "└───────┴──────────────────┴───────┴───────┴────────┘\n", "\n", "\n", - "AlignedBinaryFormat.AbfFile([closed] )\n", + "AlignedBinaryFormat.AbfFile([closed] )\n", "┌───────┬──────┬───────┬───────┬────────┐\n", "│ label │ type │ shape │ bytes │ status │\n", "├───────┼──────┼───────┼───────┼────────┤\n", "└───────┴──────┴───────┴───────┴────────┘\n", "\n", "x = 10-element Array{Float64,1}:\n", - " 0.13117086919645993\n", - " 0.8140523381099063 \n", - " 0.44152928499795685\n", - " 0.6776307667284676 \n", - " 0.2542185344974299 \n", - " 0.6641164907956227 \n", - " 0.6446525613063578 \n", - " 0.17166524697749908\n", - " 0.0775201232187761 \n", - " 0.6548927372122209 \n", + " 0.41808342392430364\n", + " 0.8340965780634206 \n", + " 0.4422525925297145 \n", + " 0.7464876087842214 \n", + " 0.8760053500303144 \n", + " 0.8812312947613306 \n", + " 0.12907825453926614\n", + " 0.8227926275555029 \n", + " 0.5770610771209626 \n", + " 0.2427376128034029 \n", "\n" ] } @@ -302,27 +309,27 @@ "output_type": "stream", "text": [ "file opened with \"w\"\n", - "AlignedBinaryFormat.ReadOnlyError(IOStream())\n", + "AlignedBinaryFormat.ReadOnlyError(IOStream())\n", "\n", "file opened with \"w+\"\n", - "x[1] = 0.8475538319109697\n", + "x[1] = 0.9897101065968341\n", "x[1] = -1.0\n", "\n", "file opened with \"r+\"\n", "(abf[\"x\"])[1] = 3.0\n", - "abf[\"y\"] = [0.5593607069994619, 0.9602697380386047]\n", + "abf[\"y\"] = [0.8188509909345121, 0.7005578254412208]\n", "\n", "file opened with \"r\"\n", "x[1] = 3.0\n", - "abf[\"y\"] = [0.5593607069994619, 0.9602697380386047]\n", + "abf[\"y\"] = [0.8188509909345121, 0.7005578254412208]\n", "ReadOnlyMemoryError()\n", "\n", "file opened with \"a\"\n", - "AlignedBinaryFormat.ReadOnlyError(IOStream())\n", + "AlignedBinaryFormat.ReadOnlyError(IOStream())\n", "\n", "file opened with \"a+\"\n", "(read(abf, \"x\"))[1] = 3.0\n", - "(read(abf, \"z\"))[1] = 0.14952197365579378\n" + "(read(abf, \"z\"))[1] = 0.07216051054053385\n" ] } ], @@ -468,7 +475,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "AlignedBinaryFormat.AbfFile([read/write] )\n", + "AlignedBinaryFormat.AbfFile([read/write] )\n", "┌───────────┬──────────────────┬─────────┬────────┬────────────┐\n", "│ label │ type │ shape │ bytes │ status │\n", "├───────────┼──────────────────┼─────────┼────────┼────────────┤\n", diff --git a/README.md b/README.md index 572e3aa..9160b90 100644 --- a/README.md +++ b/README.md @@ -59,21 +59,24 @@ end abfopen(temp, "r+") do abf write(abf, "type", Bar) - write(abf, "foo", Serialized(Foo(rand(3), -1))) + write(abf, "foo", AbfSerializer(Foo(rand(3), -1))) end abf = abfopen(temp, "r") ``` + string(AbfSerializer) = "AbfSerializer" - AlignedBinaryFormat.AbfFile([read] ) + + + AlignedBinaryFormat.AbfFile([read] ) ┌────────────┬──────────────────┬───────────┬────────┬────────────┐ │ label │ type │ shape │ bytes │ status │ ├────────────┼──────────────────┼───────────┼────────┼────────────┤ │ bitmat │ BitArray{2} │ (3, 2) │ <8B> │ unloaded │ - │ foo │ Foo │ (-1,) │ <118B> │ unloaded │ + │ foo │ Foo │ (-1,) │ <121B> │ unloaded │ │ log │ String │ (28,) │ <112B> │ unloaded │ │ my x array │ Array{Float16,1} │ (4,) │ <8B> │ unloaded │ │ type │ DataType │ (-1,) │ <23B> │ unloaded │ @@ -97,16 +100,16 @@ println(read(abf, "log")) show(abf) ``` - count(abf["bitmat"]) = 2 + count(abf["bitmat"]) = 5 this is what I did and how! - AlignedBinaryFormat.AbfFile([read] ) + AlignedBinaryFormat.AbfFile([read] ) ┌────────────┬──────────────────┬───────────┬────────┬────────────┐ │ label │ type │ shape │ bytes │ status │ ├────────────┼──────────────────┼───────────┼────────┼────────────┤ │ bitmat │ BitArray{2} │ (3, 2) │ <8B> │ loaded │ - │ foo │ Foo │ (-1,) │ <118B> │ unloaded │ + │ foo │ Foo │ (-1,) │ <121B> │ unloaded │ │ log │ String │ (28,) │ <112B> │ loaded │ │ my x array │ Array{Float16,1} │ (4,) │ <8B> │ loaded │ │ type │ DataType │ (-1,) │ <23B> │ unloaded │ @@ -150,18 +153,18 @@ println("\n") ``` x = 10-element Array{Float64,1}: - 0.13117086919645993 - 0.8140523381099063 - 0.44152928499795685 - 0.6776307667284676 - 0.2542185344974299 - 0.6641164907956227 - 0.6446525613063578 - 0.17166524697749908 - 0.0775201232187761 - 0.6548927372122209 + 0.41808342392430364 + 0.8340965780634206 + 0.4422525925297145 + 0.7464876087842214 + 0.8760053500303144 + 0.8812312947613306 + 0.12907825453926614 + 0.8227926275555029 + 0.5770610771209626 + 0.2427376128034029 - AlignedBinaryFormat.AbfFile([read/write] ) + AlignedBinaryFormat.AbfFile([read/write] ) ┌───────┬──────────────────┬───────┬───────┬────────┐ │ label │ type │ shape │ bytes │ status │ ├───────┼──────────────────┼───────┼───────┼────────┤ @@ -169,23 +172,23 @@ println("\n") └───────┴──────────────────┴───────┴───────┴────────┘ - AlignedBinaryFormat.AbfFile([closed] ) + AlignedBinaryFormat.AbfFile([closed] ) ┌───────┬──────┬───────┬───────┬────────┐ │ label │ type │ shape │ bytes │ status │ ├───────┼──────┼───────┼───────┼────────┤ └───────┴──────┴───────┴───────┴────────┘ x = 10-element Array{Float64,1}: - 0.13117086919645993 - 0.8140523381099063 - 0.44152928499795685 - 0.6776307667284676 - 0.2542185344974299 - 0.6641164907956227 - 0.6446525613063578 - 0.17166524697749908 - 0.0775201232187761 - 0.6548927372122209 + 0.41808342392430364 + 0.8340965780634206 + 0.4422525925297145 + 0.7464876087842214 + 0.8760053500303144 + 0.8812312947613306 + 0.12907825453926614 + 0.8227926275555029 + 0.5770610771209626 + 0.2427376128034029 @@ -258,27 +261,27 @@ end; ``` file opened with "w" - AlignedBinaryFormat.ReadOnlyError(IOStream()) + AlignedBinaryFormat.ReadOnlyError(IOStream()) file opened with "w+" - x[1] = 0.8475538319109697 + x[1] = 0.9897101065968341 x[1] = -1.0 file opened with "r+" (abf["x"])[1] = 3.0 - abf["y"] = [0.5593607069994619, 0.9602697380386047] + abf["y"] = [0.8188509909345121, 0.7005578254412208] file opened with "r" x[1] = 3.0 - abf["y"] = [0.5593607069994619, 0.9602697380386047] + abf["y"] = [0.8188509909345121, 0.7005578254412208] ReadOnlyMemoryError() file opened with "a" - AlignedBinaryFormat.ReadOnlyError(IOStream()) + AlignedBinaryFormat.ReadOnlyError(IOStream()) file opened with "a+" (read(abf, "x"))[1] = 3.0 - (read(abf, "z"))[1] = 0.14952197365579378 + (read(abf, "z"))[1] = 0.07216051054053385 ## Why not use `JLD/HDF5`? @@ -345,7 +348,7 @@ abfopen(temp, "w+") do abf end; ``` - AlignedBinaryFormat.AbfFile([read/write] ) + AlignedBinaryFormat.AbfFile([read/write] ) ┌───────────┬──────────────────┬─────────┬────────┬────────────┐ │ label │ type │ shape │ bytes │ status │ ├───────────┼──────────────────┼─────────┼────────┼────────────┤ diff --git a/src/AlignedBinaryFormat.jl b/src/AlignedBinaryFormat.jl index 180ba17..99ddfed 100644 --- a/src/AlignedBinaryFormat.jl +++ b/src/AlignedBinaryFormat.jl @@ -4,29 +4,29 @@ using Printf using Mmap using Serialization -export abfopen, Serialized +export abfopen, AbfSerializer #--------------------------------------------------------------------------------------------------- -struct ReadOnlyError <: Exception +struct AbfReadError <: Exception io::IOStream end -function Base.showerror(io::IO, e::ReadOnlyError) - print(io, "isreadable(", e.io.name, ") = ", isreadable(io)) +function Base.showerror(io::IO, e::T) where T<:AbfReadError + print(io, T, ": isreadable(", e.io.name, ") = ", isreadable(e.io)) end -check_readable(io::IOStream) = isreadable(io) || throw(ReadOnlyError(io)) +check_readable(io::IOStream) = isreadable(io) ? nothing : throw(AbfReadError(io)) -struct WriteOnlyError <: Exception +struct AbfWriteError <: Exception io::IOStream end -function Base.showerror(io::IO, e::WriteOnlyError) - print(io, "iswritable(", e.io.name, ") = ", iswritable(io)) -end +#function Base.showerror(io::IO, e::AbfWriteError) +# print(io, "iswritable(", e.io.name, ") = ", iswritable(e.io)) +#end -check_writable(io::IOStream) = iswritable(io) || throw(WriteOnlyError(io)) +check_writable(io::IOStream) = iswritable(io) ? nothing : throw(AbfWriteError(io)) #--------------------------------------------------------------------------------------------------- diff --git a/src/abffile.jl b/src/abffile.jl index 3a84376..d1c9dc1 100644 --- a/src/abffile.jl +++ b/src/abffile.jl @@ -65,7 +65,7 @@ function Base.read(abf::AbfFile, k::String) x = read_str(abf.io) elseif abfkey.T == DataType x = deserialize(abf.io) - elseif isa(abfkey.T, Deserialized) + elseif isa(abfkey.T, AbfDeserializer) x = getfield(deserialize(abf.io), :x) else x = Mmap.mmap(abf.io, abfkey.T, abfkey.shape) diff --git a/src/abfkey.jl b/src/abfkey.jl index fc89239..d46f5d4 100644 --- a/src/abfkey.jl +++ b/src/abfkey.jl @@ -68,18 +68,18 @@ numchars(x::Int) = Int64(x/sizeof(Char)) #--------------------------------------------------------------------------------------------------- -struct Serialized{T} +struct AbfSerializer{T} x::T end -struct Deserialized +struct AbfDeserializer str::String end struct AbfKey pos::Int64 - T::Union{DataType, Deserialized} + T::Union{DataType, AbfDeserializer} shape::Tuple{Vararg{Int64}} nbytes::Int64 @@ -103,6 +103,6 @@ struct AbfKey #----------------------------------------------------------------------------------------------- - AbfKey(pos::Int64, T::Union{DataType,Serialized}, nbytes::Int) = new(pos, T, (-1,), nbytes) - AbfKey(pos::Int64, T::Deserialized, nbytes::Int) = new(pos, T, (-1,), nbytes) + AbfKey(pos::Int64, T::Union{DataType,AbfSerializer}, nbytes::Int) = new(pos, T, (-1,), nbytes) + AbfKey(pos::Int64, T::AbfDeserializer, nbytes::Int) = new(pos, T, (-1,), nbytes) end diff --git a/src/read_write.jl b/src/read_write.jl index 4ba15b8..1ed563d 100644 --- a/src/read_write.jl +++ b/src/read_write.jl @@ -37,7 +37,7 @@ end write_type(io::IOStream, data::T) where T<:Union{BitArray,Array} = write_str(io, string(T)) write_type(io::IOStream, x::AbstractString) = write_str(io, string(String)) write_type(io::IOStream, x::DataType) = write_str(io, string(DataType)) -write_type(io::IOStream, x::T) where T<:Serialized = write_str(io, string(T)) +write_type(io::IOStream, x::T) where T<:AbfSerializer = write_str(io, string(T)) #read_type(io::IOStream, ::Type{BitArray}) = BitArray{read(io, Int64)} #read_type(io::IOStream, ::Type{Array}) = Array{TYPELOOKUP[read_str(io)], read(io,Int64)} @@ -60,8 +60,8 @@ end function parse_type_serialized(x::String) # +1 for the { and } characters - t = chop(x, head = length(string(Serialized))+1, tail = 1) - return Deserialized(t) + t = chop(x, head = length(string(AbfSerializer))+1, tail = 1) + return AbfDeserializer(t) end function read_type(io::IOStream) @@ -70,7 +70,8 @@ function read_type(io::IOStream) occursin(r"^BitArray", x) && return parse_type_bitarray(x) x == "String" && return String x == "DataType" && return DataType - startswith(x, string(Serialized)) && return parse_type_serialized(x) + @show string(AbfSerializer) + startswith(x, string(AbfSerializer)) && return parse_type_serialized(x) error("the following type is not recognized: ", x) end @@ -147,7 +148,7 @@ end #--------------------------------------------------------------------------------------------------- -function _abfwrite(io::IOStream, T::Union{DataType,Serialized}) +function _abfwrite(io::IOStream, T::Union{DataType,AbfSerializer}) mark(io) write(io, -1) pos = position(io) @@ -159,7 +160,7 @@ function _abfwrite(io::IOStream, T::Union{DataType,Serialized}) abfkey end -function _abfread(io::IOStream, T::Union{Type{DataType}, Deserialized}) +function _abfread(io::IOStream, T::Union{Type{DataType}, AbfDeserializer}) n = read(io, Int64) pos = position(io) skip(io, n) diff --git a/src/showio.jl b/src/showio.jl index c4a7aa7..810b53b 100644 --- a/src/showio.jl +++ b/src/showio.jl @@ -29,7 +29,7 @@ function Base.show(io::IO, a::AbfKey) print_bytes(io, a.nbytes) end -Base.show(io::IO, d::Deserialized) = print(io, d.str) +Base.show(io::IO, d::AbfDeserializer) = print(io, d.str) function cpad(str, n::Int) nspace = (n - length(str))/2 diff --git a/test/runtests.jl b/test/runtests.jl index 054cc4e..4660c41 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,7 @@ using Test using AlignedBinaryFormat -using AlignedBinaryFormat: AbfFile, write_str, read_str, write_type, read_type +using AlignedBinaryFormat: AbfFile, write_str, read_str, write_type, read_type, AbfReadError, + AbfWriteError @testset "open/close" begin temp = tempname() @@ -152,7 +153,7 @@ end abfopen(temp, "w+") do abf write(abf, "bar", Foo) abf["x"] = x - write(abf, "foo", Serialized(y)) + write(abf, "foo", AbfSerializer(y)) end abfopen(temp, "r") do abf @@ -169,6 +170,28 @@ end end end +@testset "exception handling" begin + temp = tempname() + try + x = rand(20,4) + abfopen(temp, "w") do abf + abf["x"] = x + @test_throws AbfReadError abf["x"] + end + abfopen(temp, "r") do abf + @test_throws AbfWriteError begin + abf["y"] = x + end + end + + finally + isfile(temp) && rm(temp) + end + +end + + + # not much of a test set but it will atleast catch method errors @testset "show" begin temp = tempname() @@ -183,6 +206,12 @@ end @test x == sprint(show,abf) x = sprint(show, abf.abfkeys["x"]) @test x == sprint(show,abf.abfkeys["x"]) + + x = sprint(showerror, AbfReadError(abf.io)) + @test x == sprint(showerror, AbfReadError(abf.io)) + + x = sprint(showerror, AbfWriteError(abf.io)) + @test x == sprint(showerror, AbfWriteError(abf.io)) end finally