Skip to content

Commit

Permalink
Merge pull request #170 from JuliaLang/io_reorg
Browse files Browse the repository at this point in the history
Support for IO renaming
  • Loading branch information
malmaud committed Feb 8, 2016
2 parents ef01d6b + 3e72df3 commit e7a4884
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 3 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,13 @@ Currently, the `@compat` macro supports the following syntaxes:

* `super` is now `supertype` [#14338](https://github.com/JuliaLang/julia/pull/14338)


* `qr(A, pivot=b)` is now `qr(A, Val{b})`, likewise for `qrfact` and `qrfact!`


* `readall` and `readbytes` are now `readstring` and `read` [#14660](https://github.com/JuliaLang/julia/pull/14660)


## New macros

* `@inline` and `@noinline` have been added. On 0.3, these are "no-ops," meaning they don't actually do anything.
Expand Down
34 changes: 32 additions & 2 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -764,12 +764,12 @@ end
if VERSION < v"0.4.0-dev+1653"
function rm_recursive(path)
if islink(path) || !isdir(path)
Filesystem.rm(path)
rm(path)
else
for p in readdir(path)
rm_recursive(joinpath(path, p))
end
rmdir(path)
rm(path)
end
end

Expand All @@ -793,4 +793,34 @@ if VERSION < v"0.4.0-dev+1653"
end
end

if VERSION < v"0.5.0-dev+2228"
const readstring = readall
export readstring

Base.read(s::IO) = readbytes(s)
Base.read(s::IO, nb) = readbytes(s, nb)

Base.write(filename::AbstractString, args...) = open(io->write(io, args...), filename, "w")

Base.read(filename::AbstractString, args...) = open(io->read(io, args...), filename)
Base.read!(filename::AbstractString, a) = open(io->read!(io, a), filename)
Base.readuntil(filename::AbstractString, args...) = open(io->readuntil(io, args...), filename)
Base.readline(filename::AbstractString) = open(readline, filename)
Base.readlines(filename::AbstractString) = open(readlines, filename)
Base.readavailable(s::IOStream) = read!(s, @compat Vector{UInt8}(nb_available(s)))
Base.readavailable(s::IOBuffer) = read(s)

function Base.write(to::IO, from::IO)
while !eof(from)
write(to, readavailable(from))
end
end

function Base.eachline(filename::AbstractString)
s = open(filename)
EachLine(s, ()->close(s))
end

end

end # module
195 changes: 194 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ end

extrapath = @windows? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : ""
@compat withenv("PATH" => extrapath * ENV["PATH"]) do
@test readall(pipeline(`echo hello`, `sort`)) == "hello\n"
@test readstring(pipeline(`echo hello`, `sort`)) == "hello\n"
@test success(pipeline(`true`, `true`))
end

Expand Down Expand Up @@ -598,3 +598,196 @@ let
@test tmpdir != ""
@test !isdir(tmpdir)
end

# https://github.com/JuliaLang/julia/pull/14660
mktempdir() do dir

verbose = false

# Create test file...
filename = joinpath(dir, "file.txt")
text = "C1,C2\n1,2\na,b\n"

# List of IO producers...
l = [
("IOStream", (text) -> begin
write(filename, text)
open(filename)
end),
("IOBuffer", (text)->IOBuffer(text))
]

open_streams = Any[]
function cleanup()
for s in open_streams
try close(s) end
end
end

for (name, f) in l

io = ()->(s=f(text); push!(open_streams, s); s)

write(filename, text)

verbose && println("$name read...")
@test read(io(), UInt8) == read(IOBuffer(text), UInt8)
@test read(io(), UInt8) == read(filename, UInt8)
@test read(io(), Int) == read(IOBuffer(text), Int)
@test read(io(), Int) == read(filename,Int)
s1 = io()
s2 = IOBuffer(text)
@test read(s1, UInt32, 2) == read(s2, UInt32, 2)
@test !eof(s1)
@test read(s1, UInt8, 5) == read(s2, UInt8, 5)
@test !eof(s1)
@test read(s1, UInt8, 1) == read(s2, UInt8, 1)
@test eof(s1)
@test_throws EOFError read(s1, UInt8)
@test eof(s1)
close(s1)
close(s2)

verbose && println("$name eof...")
n = length(text) - 1
@test @compat read!(io(), Vector{UInt8}(n)) ==
read!(IOBuffer(text), Vector{UInt8}(n))
@test @compat (s = io(); read!(s, Vector{UInt8}(n)); !eof(s))
n = length(text)
@test @compat read!(io(), Vector{UInt8}(n)) ==
read!(IOBuffer(text), Vector{UInt8}(n))
@test @compat (s = io(); read!(s, Vector{UInt8}(n)); eof(s))
n = length(text) + 1
@test_throws EOFError @compat read!(io(), Vector{UInt8}(n))
@test_throws EOFError @compat read!(io(), Vector{UInt8}(n))

old_text = text
cleanup()
const SZ_UNBUFFERED_IO = 65536

for text in [
old_text,
convert(UTF8String, Char['A' + i % 52 for i in 1:(div(SZ_UNBUFFERED_IO,2))]),
convert(UTF8String, Char['A' + i % 52 for i in 1:( SZ_UNBUFFERED_IO -1)]),
convert(UTF8String, Char['A' + i % 52 for i in 1:( SZ_UNBUFFERED_IO )]),
convert(UTF8String, Char['A' + i % 52 for i in 1:( SZ_UNBUFFERED_IO +1)])
]

write(filename, text)

verbose && println("$name readstring...")
@test readstring(io()) == text

@test readstring(io()) == readstring(filename)


verbose && println("$name read...")
@test @compat read(io()) == UInt8[convert(UInt8, _) for _ in text]

@test read(io()) == read(filename)

cleanup()


verbose && println("$name readbytes!...")
l = length(text)
for n = [1, 2, l-2, l-1, l, l+1, l+2]
@compat a1 = Vector{UInt8}(n);
@compat a2 = Vector{UInt8}(n)
s1 = io()
s2 = IOBuffer(text)
n1 = readbytes!(s1, a1)
n2 = readbytes!(s2, a2)
@test n1 == n2
@test length(a1) == length(a2)
@test a1[1:n1] == a2[1:n2]
@test n <= length(text) || eof(s1)
@test n <= length(text) || eof(s2)

cleanup()
end

verbose && println("$name read!...")
l = length(text)
for n = [1, 2, l-2, l-1, l]
@test @compat read!(io(), Vector{UInt8}(n)) ==
read!(IOBuffer(text), Vector{UInt8}(n))
@test @compat read!(io(), Vector{UInt8}(n)) ==
read!(filename, Vector{UInt8}(n))

cleanup()
end
@test_throws EOFError @compat read!(io(), Vector{UInt8}(length(text)+1))


verbose && println("$name readuntil...")
@test readuntil(io(), '\n') == readuntil(IOBuffer(text),'\n')
@test readuntil(io(), '\n') == readuntil(filename,'\n')
@test readuntil(io(), "\n") == readuntil(IOBuffer(text),"\n")
@test readuntil(io(), "\n") == readuntil(filename,"\n")
@test readuntil(io(), ',') == readuntil(IOBuffer(text),',')
@test readuntil(io(), ',') == readuntil(filename,',')

cleanup()

verbose && println("$name readline...")
@test readline(io()) == readline(IOBuffer(text))
@test readline(io()) == readline(filename)

verbose && println("$name readlines...")
@test readlines(io()) == readlines(IOBuffer(text))
@test readlines(io()) == readlines(filename)
@test collect(eachline(io())) == collect(eachline(IOBuffer(text)))
@test collect(eachline(io())) == collect(eachline(filename))

cleanup()

verbose && println("$name countlines...")
@test countlines(io()) == countlines(IOBuffer(text))

# verbose && println("$name readcsv...")
# @test readcsv(io()) == readcsv(IOBuffer(text))
# @test readcsv(io()) == readcsv(filename)

cleanup()
end

text = old_text
write(filename, text)

verbose && println("$name position...")
@test @compat (s = io(); read!(s, Vector{UInt8}(4)); position(s)) == 4

verbose && println("$name seek...")
for n = 0:length(text)-1
@test readlines(seek(io(), n)) == readlines(seek(IOBuffer(text), n))
cleanup()
end
verbose && println("$name skip...")
for n = 0:length(text)-1
@test readlines(seek(io(), n)) == readlines(seek(IOBuffer(text), n))
@test readlines(skip(io(), n)) == readlines(skip(IOBuffer(text), n))
cleanup()
end
verbose && println("$name seekend...")
@test readstring(seekend(io())) == ""

verbose && println("$name write(::IOStream, ...)")
to = open("$filename.to", "w")
write(to, io())
close(to)
@test readstring("$filename.to") == text

verbose && println("$name write(filename, ...)")
write("$filename.to", io())
@test readstring("$filename.to") == text

verbose && println("$name write(::IOBuffer, ...)")
@compat to = IOBuffer(UInt8[convert(UInt8, _) for _ in text], false, true)
write(to, io())
@test takebuf_string(to) == text

cleanup()
end

end

0 comments on commit e7a4884

Please sign in to comment.