-
Notifications
You must be signed in to change notification settings - Fork 82
/
loadsave.jl
136 lines (120 loc) · 4.49 KB
/
loadsave.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
const sym2loader = Dict{Symbol,Vector{Symbol}}()
const sym2saver = Dict{Symbol,Vector{Symbol}}()
function is_installed(pkg::Symbol)
isdefined(Main, pkg) && isa(getfield(Main, pkg), Module) && return true # is a module defined in Main scope
path = Base.find_in_path(string(pkg)) # hacky way to determine if a Package is installed
path == nothing && return false
return isfile(path)
end
function checked_import(pkg::Symbol)
isdefined(Main, pkg) && return getfield(Main, pkg)
isdefined(FileIO, pkg) && return getfield(FileIO, pkg)
!is_installed(pkg) && throw(NotInstalledError(pkg, ""))
!isdefined(Main, pkg) && eval(Main, Expr(:import, pkg))
return getfield(Main, pkg)
end
for (applicable_, add_, dict_) in (
(:applicable_loaders, :add_loader, :sym2loader),
(:applicable_savers, :add_saver, :sym2saver))
@eval begin
function $applicable_{sym}(::Union{Type{DataFormat{sym}}, Formatted{DataFormat{sym}}})
if haskey($dict_, sym)
return $dict_[sym]
end
error("No $($applicable_) found for $(sym)")
end
function $add_{sym}(::Type{DataFormat{sym}}, pkg::Symbol)
list = get($dict_, sym, Symbol[])
$dict_[sym] = push!(list, pkg)
end
end
end
"`add_loader(fmt, :Package)` triggers `using Package` before loading format `fmt`"
add_loader
"`add_saver(fmt, :Package)` triggers `using Package` before saving format `fmt`"
add_saver
"""
- `load(filename)` loads the contents of a formatted file, trying to infer
the format from `filename` and/or magic bytes in the file.
- `load(strm)` loads from an `IOStream` or similar object. In this case,
the magic bytes are essential.
- `load(File(format"PNG",filename))` specifies the format directly, and bypasses inference.
- `load(f; options...)` passes keyword arguments on to the loader.
"""
load(s::Union{AbstractString,IO}, args...; options...) =
load(query(s), args...; options...)
"""
- `save(filename, data...)` saves the contents of a formatted file,
trying to infer the format from `filename`.
- `save(Stream(format"PNG",io), data...)` specifies the format directly, and bypasses inference.
- `save(f, data...; options...)` passes keyword arguments on to the saver.
"""
save(s::Union{AbstractString,IO}, data...; options...) =
save(query(s), data...; options...)
function save(s::Union{AbstractString,IO}; options...)
data -> save(s, data; options...)
end
# Forced format
function save{sym}(df::Type{DataFormat{sym}}, f::AbstractString, data...; options...)
libraries = applicable_savers(df)
checked_import(libraries[1])
eval(Main, :($save($File($(DataFormat{sym}), $f),
$data...; $options...)))
end
function save{sym}(df::Type{DataFormat{sym}}, s::IO, data...; options...)
libraries = applicable_savers(df)
checked_import(libraries[1])
eval(Main, :($save($Stream($(DataFormat{sym}), $s),
$data...; $options...)))
end
# Fallbacks
function load{F}(q::Formatted{F}, args...; options...)
if unknown(q)
isfile(filename(q)) || open(filename(q)) # force systemerror
throw(UnknownFormat(q))
end
libraries = applicable_loaders(q)
failures = Any[]
for library in libraries
try
Library = checked_import(library)
if !has_method_from(methods(Library.load), Library)
throw(LoaderError(string(library), "load not defined"))
end
return eval(Main, :($(Library.load)($q, $args...; $options...)))
catch e
push!(failures, (e, q))
end
end
handle_exceptions(failures, "loading \"$(filename(q))\"")
end
function save{F}(q::Formatted{F}, data...; options...)
unknown(q) && throw(UnknownFormat(q))
libraries = applicable_savers(q)
failures = Any[]
for library in libraries
try
Library = checked_import(library)
if !has_method_from(methods(Library.save), Library)
throw(WriterError(string(library), "save not defined"))
end
return eval(Main, :($(Library.save)($q, $data...; $options...)))
catch e
push!(failures, (e, q))
end
end
handle_exceptions(failures, "saving \"$(filename(q))\"")
end
function has_method_from(mt, Library)
for m in mt
if getmodule(m) == Library
return true
end
end
false
end
if VERSION < v"0.5.0-dev+3543"
getmodule(m) = m.func.code.module
else
getmodule(m) = m.module
end