Skip to content

Commit b81b089

Browse files
authored
Merge pull request #181 from JuliaIO/sd/07
fixes for 0.7
2 parents 31fb1ed + 427629c commit b81b089

File tree

7 files changed

+77
-58
lines changed

7 files changed

+77
-58
lines changed

src/FileIO.jl

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export DataFormat,
2828
metadata
2929

3030
import Base.showerror
31+
using Base: RefValue
3132

3233
include("query.jl")
3334
include("error_handling.jl")

src/loadsave.jl

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
const sym2loader = Dict{Symbol,Vector{Symbol}}()
22
const sym2saver = Dict{Symbol,Vector{Symbol}}()
3+
const has_pkg3 = try
4+
using Pkg3
5+
true
6+
catch e
7+
false
8+
end
39

4-
function is_installed(pkg::Symbol)
5-
isdefined(Main, pkg) && isa(getfield(Main, pkg), Module) && return true # is a module defined in Main scope
6-
path = Base.find_in_path(string(pkg)) # hacky way to determine if a Package is installed
7-
path == nothing && return false
8-
return isfile(path)
10+
if isdefined(Base, :find_in_path)
11+
function is_installed(pkg::Symbol)
12+
isdefined(Main, pkg) && isa(getfield(Main, pkg), Module) && return true # is a module defined in Main scope
13+
path = Base.find_in_path(string(pkg)) # hacky way to determine if a Package is installed
14+
path == nothing && return false
15+
return isfile(path)
16+
end
17+
elseif has_pkg3 && isdefined(Pkg3, :installed)
18+
is_installed(pkg::Symbol) = get(Pkg3.installed(), string(pkg), nothing) != nothing
919
end
1020

1121
function checked_import(pkg::Symbol)

src/query.jl

+26-21
Original file line numberDiff line numberDiff line change
@@ -245,43 +245,42 @@ written in known `Format`. For example, `Stream{PNG}(io)` would
245245
indicate PNG format. If known, the optional `filename` argument can
246246
be used to improve error messages, etc.
247247
"""
248-
struct Stream{F<:DataFormat,IOtype<:IO} <: Formatted{F}
248+
struct Stream{F <: DataFormat, IOtype <: IO} <: Formatted{F}
249249
io::IOtype
250-
filename::Nullable{String}
250+
filename::Union{String, Nothing}
251251
end
252252

253-
Stream{F<:DataFormat}(::Type{F}, io::IO) = Stream{F,typeof(io)}(io, Nullable{String}())
254-
Stream{F<:DataFormat}(::Type{F}, io::IO, filename::AbstractString) = Stream{F,typeof(io)}(io,String(filename))
255-
Stream{F<:DataFormat}(::Type{F}, io::IO, filename) = Stream{F,typeof(io)}(io,filename)
256-
Stream{F}(file::File{F}, io::IO) = Stream{F,typeof(io)}(io,filename(file))
253+
Stream{F<:DataFormat}(::Type{F}, io::IO) = Stream{F,typeof(io)}(io, nothing)
254+
Stream{F<:DataFormat}(::Type{F}, io::IO, filename::AbstractString) = Stream{F, typeof(io)}(io, String(filename))
255+
Stream{F<:DataFormat}(::Type{F}, io::IO, filename) = Stream{F, typeof(io)}(io, filename)
256+
Stream{F}(file::File{F}, io::IO) = Stream{F, typeof(io)}(io, filename(file))
257257

258258
"`stream(s)` returns the stream associated with `Stream` `s`"
259259
stream(s::Stream) = s.io
260260

261261
"""
262-
`filename(stream)` returns a nullable-string of the filename
263-
associated with `Stream` `stream`.
262+
`filename(stream)` returns a string of the filename
263+
associated with `Stream` `stream`, or nothing if there is no file associated.
264264
"""
265265
filename(s::Stream) = s.filename
266266

267267
"""
268268
`file_extension(file)` returns a nullable-string for the file extension associated with `Stream` `stream`.
269269
"""
270270
function file_extension(f::Stream)
271-
isnull(filename(f)) && return filename(f)
272-
splitext(get(filename(f)))[2]
271+
fname = filename(f)
272+
(fname == nothing) && return nothing
273+
splitext(fname)[2]
273274
end
274275

275276
# Note this closes the stream. It's useful when you've opened
276277
# the file to check the magic bytes, but don't want to leave
277278
# a dangling stream.
278279
function file!{F}(strm::Stream{F})
279280
f = filename(strm)
280-
if isnull(f)
281-
error("filename unknown")
282-
end
281+
f == nothing && error("filename unknown")
283282
close(strm.io)
284-
File{F}(get(f))
283+
File{F}(f)
285284
end
286285

287286
# Implement standard I/O operations for File and Stream
@@ -329,9 +328,9 @@ skipmagic(io, magic::Function) = nothing
329328
skipmagic{N}(io, magic::NTuple{N,UInt8}) = seek(io, length(magic))
330329
function skipmagic(io, magic::Tuple)
331330
lengths = map(length, magic)
332-
all(x->lengths[1] == x, lengths) && return seek(io, lengths[1]) # it doesn't matter what magic bytes get skipped as they all have the same length
331+
all(x-> lengths[1] == x, lengths) && return seek(io, lengths[1]) # it doesn't matter what magic bytes get skipped as they all have the same length
333332
magic = [magic...]
334-
sort!(magic, lt=(a,b)-> length(a)>= length(b)) # start with longest first, to avoid overlapping magic bytes
333+
sort!(magic, lt = (a,b)-> length(a) >= length(b)) # start with longest first, to avoid overlapping magic bytes
335334
seekend(io)
336335
len = position(io)
337336
seekstart(io)
@@ -397,9 +396,9 @@ hasfunction(s::Tuple) = false #has magic
397396
`query(io, [filename])` returns a `Stream` object with information about the
398397
format inferred from the magic bytes.
399398
"""
400-
query(io::IO, filename) = query(io, Nullable(String(filename)))
399+
query(io::IO, filename) = query(io, String(filename))
401400

402-
function query(io::IO, filename::Nullable{String}=Nullable{String}())
401+
function query(io::IO, filename::Union{Nothing, String} = nothing)
403402
magic = Vector{UInt8}(0)
404403
pos = position(io)
405404
for p in magic_list
@@ -408,7 +407,7 @@ function query(io::IO, filename::Nullable{String}=Nullable{String}())
408407
while length(m) > length(magic)
409408
if eof(io)
410409
seek(io, pos)
411-
return Stream{unknown_df,typeof(io)}(io, filename)
410+
return Stream{unknown_df, typeof(io)}(io, filename)
412411
end
413412
push!(magic, read(io, UInt8))
414413
end
@@ -421,8 +420,14 @@ function query(io::IO, filename::Nullable{String}=Nullable{String}())
421420
for p in magic_func
422421
seek(io, pos)
423422
f = first(p)
424-
if f(io)
425-
return Stream{DataFormat{last(p)},typeof(io)}(seek(io, pos), filename)
423+
try
424+
if f(io)
425+
return Stream{DataFormat{last(p)},typeof(io)}(seek(io, pos), filename)
426+
end
427+
catch e
428+
println("There was an error in magick function $f")
429+
println("Please open an issue at FileIO.jl. Error:")
430+
println(e)
426431
end
427432
end
428433
seek(io, pos)

src/registry.jl

+17-21
Original file line numberDiff line numberDiff line change
@@ -160,21 +160,19 @@ add_format(format"FLAC","fLaC",".flac",[:FLAC])
160160
### Complex cases
161161

162162
# bedGraph: the complication is that the magic bytes may start at any location within an indeterminate header.
163-
const bedgraph_magic = UInt8[0x74, 0x79, 0x70, 0x65, 0x3D, 0x62, 0x65, 0x64, 0x47, 0x72, 0x61, 0x70, 0x68]
164163
function detect_bedgraph(io)
165-
position(io) == 0 || return false
166-
167-
line = ""
168-
164+
bedgraph_magic = b"type=bedGraph"
169165
# Check lines for magic bytes.
170-
while !eof(io) && !ismatch(r"^\s*([A-Za-z]+\S*)\s+(\d+)\s+(\d+)\s+(\S*\d)\s*$", line) # Note: regex is used to limit the search by exiting the loop when a line matches the bedGraph track format.
171-
line = readline(io, chomp=false)
172-
173-
if contains(line, String(bedgraph_magic)) # Note: String(bedgraph_magic) = "type=bedGraph"
174-
return true
166+
pos = 1
167+
while !eof(io)
168+
r = read(io, UInt8)
169+
if bedgraph_magic[pos] == r
170+
pos >= length(bedgraph_magic) && return true
171+
pos += 1
172+
else
173+
pos = 1
175174
end
176175
end
177-
178176
return false
179177
end
180178
add_format(format"bedGraph", detect_bedgraph, [".bedgraph"], [:BedgraphFiles])
@@ -235,28 +233,27 @@ end
235233
add_format(format"HDF5", detecthdf5, [".h5", ".hdf5"], [:HDF5])
236234

237235
function detect_stlascii(io)
236+
pos = position(io)
238237
try
239-
position(io) != 0 && (seekstart(io); return false)
240238
seekend(io)
241239
len = position(io)
242-
seekstart(io)
240+
seek(io, pos)
243241
len < 80 && return false
244242
header = read(io, 80) # skip header
245-
seekstart(io)
243+
seek(io, pos)
246244
header[1:6] == b"solid " && !detect_stlbinary(io)
247245
finally
248-
seekstart(io)
246+
seek(io, pos)
249247
end
250248
end
251249

252250
function detect_stlbinary(io)
253-
size_header = 80+sizeof(UInt32)
254-
size_triangleblock = (4*3*sizeof(Float32)) + sizeof(UInt16)
255-
256-
position(io) != 0 && (seekstart(io); return false)
251+
size_header = 80 + sizeof(UInt32)
252+
size_triangleblock = (4 * 3 * sizeof(Float32)) + sizeof(UInt16)
253+
pos = position(io)
257254
seekend(io)
258255
len = position(io)
259-
seekstart(io)
256+
seek(io, pos)
260257
len < size_header && return false
261258

262259
skip(io, 80) # skip header
@@ -267,7 +264,6 @@ function detect_stlbinary(io)
267264
attrib_byte_count = read(io, UInt16) # read last attrib_byte
268265
attrib_byte_count != zero(UInt16) && (seekstart(io); return false) # should be zero as not used
269266
result = eof(io) # if end of file, we have a stl!
270-
seekstart(io)
271267
return result
272268
end
273269
add_format(format"STL_ASCII", detect_stlascii, [".stl", ".STL"], [:MeshIO])

test/error_handling.jl

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
println("these tests will print warnings: ")
2+
3+
if VERSION > v"0.6.9"
4+
const fetch07 = fetch
5+
else
6+
const fetch07 = wait
7+
end
8+
29
@testset "Not installed" begin
310
eval(Base, :(is_interactive = true)) # for interactive error handling
411

@@ -9,11 +16,11 @@ println("these tests will print warnings: ")
916
rserr, wrerr = redirect_stderr()
1017
ref = @async save("test.not_installed", nothing)
1118
println(wr, "y")
12-
@test_throws CompositeException wait(ref) #("unknown package NotInstalled")
19+
@test_throws CompositeException fetch07(ref) #("unknown package NotInstalled")
1320
ref = @async save("test.not_installed", nothing)
1421
println(wr, "invalid") #test invalid input
1522
println(wr, "n") # don't install
16-
wait(ref)
23+
fetch07(ref)
1724
@test istaskdone(ref)
1825

1926
close(rs);close(wr);close(rserr);close(wrerr)

test/loadsave.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ add_saver(format"DUMMY", :Dummy)
175175
f = File(format"DUMMY", fnrel)
176176
@test !(isabspath(filename(f)))
177177
open(f) do s
178-
@test isabspath(get(filename(s)))
179-
@test endswith(get(filename(s)),fn)
178+
@test isabspath(filename(s))
179+
@test endswith(filename(s), fn)
180180
end
181181
end
182182

@@ -192,8 +192,8 @@ add_saver(format"DUMMY", :Dummy)
192192
f = File(format"DUMMY", fnrel)
193193
@test !(isabspath(filename(f)))
194194
open(f) do s
195-
@test isabspath(get(filename(s)))
196-
@test endswith(get(filename(s)),fn2)
195+
@test isabspath(filename(s))
196+
@test endswith(filename(s),fn2)
197197
end
198198
end
199199
rm(fn2)

test/query.jl

+5-5
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ try
9393
io = IOBuffer()
9494
s = Stream(format"JUNK", io)
9595
@test typeof(s) == Stream{DataFormat{:JUNK},IOBuffer}
96-
@test isnull(filename(s))
96+
@test filename(s) == nothing
9797
@test_throws Exception FileIO.file!(s)
9898
s = Stream(format"JUNK", io, "junk.jnk")
99-
@test get(filename(s)) == "junk.jnk"
100-
s = Stream(format"JUNK", io, Nullable("junk2.jnk"))
101-
@test get(filename(s)) == "junk2.jnk"
99+
@test filename(s) == "junk.jnk"
100+
s = Stream(format"JUNK", io, "junk2.jnk")
101+
@test filename(s) == "junk2.jnk"
102102
end
103103

104104
@testset "query" begin
@@ -122,7 +122,7 @@ try
122122
q = query(io)
123123
@test typeof(q) == Stream{format"JUNK",typeof(io)}
124124
@test !(unknown(q))
125-
@test isnull(file_extension(q))
125+
@test file_extension(q) == nothing
126126

127127
# File with correct extension
128128
str = String(take!(io))

0 commit comments

Comments
 (0)