Skip to content

Commit 324db23

Browse files
committed
Fixes for dispatch in Blob open() methods
The dispatch here was confusing. Refactor this so that opening a Blob with various types dispatches down to a method involving the data root resource controller and path relative to that.
1 parent 3082103 commit 324db23

File tree

3 files changed

+53
-19
lines changed

3 files changed

+53
-19
lines changed

src/BlobTree.jl

+41-12
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ abstract type AbstractBlobTree; end
1919
# TODO: Should we have `istree` separate from `isdir`?
2020
Base.isdir(x::AbstractBlobTree) = true
2121
Base.isfile(tree::AbstractBlobTree) = false
22+
Base.ispath(x::AbstractBlobTree) = true
2223

2324
# Number of children is not known without a (potentially high-latency) call to
2425
# an external resource
@@ -125,27 +126,62 @@ Base.basename(file::Blob) = basename(file.path)
125126
Base.abspath(file::Blob) = AbsPath(file.root, file.path)
126127
Base.isdir(file::Blob) = false
127128
Base.isfile(file::Blob) = true
129+
Base.ispath(file::Blob) = true
128130

129131
function Base.show(io::IO, ::MIME"text/plain", file::Blob)
130-
print(io, "📄 ", file.path, " @ ", sys_abspath(file.root))
132+
print(io, "📄 ", file.path, " @ ", summary(file.root))
131133
end
132134

133135
function AbstractTrees.printnode(io::IO, file::Blob)
134136
print(io, "📄 ", basename(file))
135137
end
136138

139+
# Opening as Vector{UInt8} or as String uses IO interface
137140
function Base.open(f::Function, ::Type{Vector{UInt8}}, file::Blob)
138-
open(IO, file) do io
141+
open(IO, file.root, file.path) do io
139142
f(read(io)) # TODO: use Mmap?
140143
end
141144
end
142145

143146
function Base.open(f::Function, ::Type{String}, file::Blob)
144-
open(Vector{UInt8}, file) do buf
145-
f(String(buf))
147+
open(IO, file.root, file.path) do io
148+
f(read(io, String))
146149
end
147150
end
148151

152+
# Default open-type for Blob is IO
153+
Base.open(f::Function, file::Blob; kws...) = open(f, IO, file.root, file.path; kws...)
154+
155+
# Opening Blob as itself is trivial
156+
function Base.open(f::Function, ::Type{Blob}, file::Blob)
157+
f(file)
158+
end
159+
160+
# open with other types T defers to the underlying storage system
161+
function Base.open(f::Function, ::Type{T}, file::Blob; kws...) where {T}
162+
open(f, T, file.root, file.path; kws...)
163+
end
164+
165+
# Unscoped form of open
166+
function Base.open(::Type{T}, file::Blob; kws...) where {T}
167+
open(identity, T, file; kws...)
168+
end
169+
170+
# read() is also supported for `Blob`s
171+
Base.read(file::Blob) = read(file.root, file.path)
172+
Base.read(file::Blob, ::Type{T}) where {T} = read(file.root, file.path, T)
173+
174+
175+
# Support for opening AbsPath
176+
#
177+
# TODO: Put this elsewhere?
178+
function Base.open(f::Function, ::Type{T}, path::AbsPath; kws...) where {T}
179+
open(f, T, path.root, path.path; kws...)
180+
end
181+
182+
Base.open(f::Function, path::AbsPath; kws...) = open(f, IO, path.root, path.path; kws...)
183+
184+
149185
#-------------------------------------------------------------------------------
150186
struct BlobTree{Root} <: AbstractBlobTree
151187
root::Root
@@ -165,7 +201,7 @@ function Base.show(io::IO, ::MIME"text/plain", tree::AbstractBlobTree)
165201
# `children()` for all our trees. It'd be much easier if
166202
# `AbstractTrees.has_children()` was used consistently upstream.
167203
cs = children(tree)
168-
println(io, "📂 Tree ", tree.path, " @ ", tree.root)
204+
println(io, "📂 Tree ", tree.path, " @ ", summary(tree.root))
169205
for (i, c) in enumerate(cs)
170206
print(io, " ", isdir(c) ? '📁' : '📄', " ", basename(c))
171207
if i != length(cs)
@@ -228,15 +264,8 @@ function children(tree::BlobTree)
228264
[tree[c] for c in child_names]
229265
end
230266

231-
Base.open(f::Function, file::Blob; kws...) = open(f, file.root, file.path; kws...)
232-
Base.open(f::Function, path::AbsPath; kws...) = open(f, path.root, path.path; kws...)
233-
234267
function Base.open(f::Function, ::Type{BlobTree}, tree::BlobTree)
235268
f(tree)
236269
end
237270

238-
function Base.open(f::Function, ::Type{Blob}, file::Blob)
239-
f(file)
240-
end
241-
242271
# Base.open(::Type{T}, file::Blob; kws...) where {T} = open(identity, T, file.root, file.path; kws...)

src/DataSets.jl

+5
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ include("filesystem.jl")
270270
# opened. See check_scoped_open for a way to help users avoid errors when using
271271
# this (ie, if `identity` is not a valid argument to open() because resources
272272
# would be closed before it returns).
273+
#
274+
# FIXME: Consider removing this. It should likely be replaced with `load()`, in
275+
# analogy to FileIO.jl's load operation:
276+
# * `load()` is "load the entire file into memory as such-and-such type"
277+
# * `open()` is "open this resource, and run some function while it's open"
273278
Base.open(as_type, conf::DataSet) = open(identity, as_type, conf)
274279

275280
"""

src/filesystem.jl

+7-7
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,21 @@ sys_abspath(file::Blob) = sys_abspath(file.root, file.path)
2121
# AbsPath{<:AbstractFileSystemRoot} rather than usin double dispatch?
2222
Base.isdir(root::AbstractFileSystemRoot, path::RelPath) = isdir(sys_abspath(root, path))
2323
Base.isfile(root::AbstractFileSystemRoot, path::RelPath) = isfile(sys_abspath(root, path))
24+
Base.ispath(root::AbstractFileSystemRoot, path::RelPath) = ispath(sys_abspath(root, path))
2425
Base.read(root::AbstractFileSystemRoot, path::RelPath, ::Type{T}) where {T} =
2526
read(sys_abspath(root, path), T)
27+
Base.read(root::AbstractFileSystemRoot, path::RelPath) where {T} =
28+
read(sys_abspath(root, path))
2629

27-
# TODO: Is it possible to get a generic version of this without type piracy?
28-
function Base.open(::Type{T}, file::Blob{<:AbstractFileSystemRoot}; kws...) where {T}
29-
open(identity, T, file)
30-
end
30+
Base.summary(io::IO, root::AbstractFileSystemRoot) = print(io, sys_abspath(root))
3131

32-
function Base.open(f::Function, ::Type{IO}, file::Blob{<:AbstractFileSystemRoot};
32+
function Base.open(f::Function, ::Type{IO}, root::AbstractFileSystemRoot, path;
3333
write=false, read=!write, kws...)
34-
if !iswriteable(file.root) && write
34+
if !iswriteable(root) && write
3535
error("Error writing file at read-only path $path")
3636
end
3737
check_scoped_open(f, IO)
38-
open(f, sys_abspath(file.root, file.path); read=read, write=write, kws...)
38+
open(f, sys_abspath(root, path); read=read, write=write, kws...)
3939
end
4040

4141
function Base.mkdir(root::AbstractFileSystemRoot, path::RelPath; kws...)

0 commit comments

Comments
 (0)