Skip to content

Commit 75f7732

Browse files
committed
Merge pull request #6948 from stevengj/cmdio
RFC: deprecate readsfrom/writesto in favor of simply using open on AbstractCmd
2 parents c21b14f + 4fa4aae commit 75f7732

10 files changed

+76
-48
lines changed

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ Deprecated or removed
342342

343343
* `bitmix` is replaced by a 2-argument form of `hash`.
344344

345+
* `readsfrom` and `writesto` are replaced by `open` ([#6948]).
346+
345347
[#4042]: https://github.com/JuliaLang/julia/issues/4042
346348
[#5164]: https://github.com/JuliaLang/julia/issues/5164
347349
[#4026]: https://github.com/JuliaLang/julia/issues/4026

base/deprecated.jl

+3
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@ Set{T<:Number}(xs::T...) = Set{T}(xs)
457457
@deprecate bitmix(x, y::Union(Uint32, Int32)) convert(Uint32, hash(x, uint(y)))
458458
@deprecate bitmix(x, y::Union(Uint64, Int64)) convert(Uint64, hash(x, hash(y)))
459459

460+
@deprecate readsfrom(cmd, args...) open(cmd, "r", args...)
461+
@deprecate writesto(cmd, args...) open(cmd, "w", args...)
462+
460463
# 0.3 discontinued functions
461464

462465
scale!{T<:Base.LinAlg.BlasReal}(X::Array{T}, s::Complex) = error("scale!: Cannot scale a real array by a complex value in-place. Use scale(X::Array{Real}, s::Complex) instead.")

base/exports.jl

-2
Original file line numberDiff line numberDiff line change
@@ -1259,12 +1259,10 @@ export
12591259
process_exited,
12601260
process_running,
12611261
readandwrite,
1262-
readsfrom,
12631262
run,
12641263
setenv,
12651264
spawn,
12661265
success,
1267-
writesto,
12681266

12691267
# C interface
12701268
c_free,

base/interactiveutil.jl

+6-8
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,9 @@ end
6666

6767
@osx_only begin
6868
function clipboard(x)
69-
w,p = writesto(`pbcopy`)
70-
print(w,x)
71-
close(w)
72-
wait(p)
69+
open(`pbcopy`, "w") do io
70+
print(io, x)
71+
end
7372
end
7473
clipboard() = readall(`pbpaste`)
7574
end
@@ -89,10 +88,9 @@ end
8988
cmd = c == :xsel ? `xsel --nodetach --input --clipboard` :
9089
c == :xclip ? `xclip -quiet -in -selection clipboard` :
9190
error("unexpected clipboard command: $c")
92-
w,p = writesto(cmd)
93-
print(w,x)
94-
close(w)
95-
wait(p)
91+
open(cmd, "w") do io
92+
print(io, x)
93+
end
9694
end
9795
function clipboard()
9896
c = clipboardcmd()

base/multi.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,7 @@ function launch_local_workers(cman::LocalManager, np::Integer, config::Dict)
11181118

11191119
# start the processes first...
11201120
for i in 1:np
1121-
io, pobj = readsfrom(detach(`$(dir)/$(exename) --bind-to $(LPROC.bind_addr) $exeflags`))
1121+
io, pobj = open(detach(`$(dir)/$(exename) --bind-to $(LPROC.bind_addr) $exeflags`), "r")
11221122
io_objs[i] = io
11231123
configs[i] = merge(config, {:process => pobj})
11241124
end
@@ -1175,7 +1175,7 @@ function launch_ssh_workers(cman::SSHManager, np::Integer, config::Dict)
11751175
cmd = `sh -l -c $(shell_escape(cmd))` # shell to launch under
11761176
cmd = `ssh -n $sshflags $host $(shell_escape(cmd))` # use ssh to remote launch
11771177

1178-
io, pobj = readsfrom(detach(cmd))
1178+
io, pobj = open(detach(cmd), "r")
11791179
io_objs[i] = io
11801180
configs[i] = merge(config, {:machine => cman.machines[i]})
11811181
end

base/process.jl

+31-23
Original file line numberDiff line numberDiff line change
@@ -423,30 +423,43 @@ function eachline(cmd::AbstractCmd,stdin)
423423
end
424424
eachline(cmd::AbstractCmd) = eachline(cmd,DevNull)
425425

426-
#returns a pipe to read from the last command in the pipelines
427-
readsfrom(cmds::AbstractCmd) = readsfrom(cmds, DevNull)
428-
function readsfrom(cmds::AbstractCmd, stdin::AsyncStream)
429-
processes = @tmp_rpipe out tmp spawn(false, cmds, (stdin,tmp,STDERR))
430-
start_reading(out)
431-
(out, processes)
426+
# return a (Pipe,Process) pair to write/read to/from the pipeline
427+
function open(cmds::AbstractCmd, mode::String="r", stdio::AsyncStream=DevNull)
428+
if mode == "r"
429+
processes = @tmp_rpipe out tmp spawn(false, cmds, (stdio,tmp,STDERR))
430+
start_reading(out)
431+
(out, processes)
432+
elseif mode == "w"
433+
processes = @tmp_wpipe tmp inpipe spawn(false,cmds, (tmp,stdio,STDERR))
434+
(inpipe, processes)
435+
else
436+
throw(ArgumentError("mode must be \"r\" or \"w\", not \"$mode\""))
437+
end
432438
end
433439

434-
function writesto(cmds::AbstractCmd, stdout::UVStream)
435-
processes = @tmp_wpipe tmp inpipe spawn(false, cmds, (tmp,stdout,STDERR))
436-
(inpipe, processes)
440+
function open(f::Function, cmds::AbstractCmd, args...)
441+
io, P = open(cmds, args...)
442+
ret = try
443+
f(io)
444+
catch
445+
kill(P)
446+
rethrow()
447+
finally
448+
close(io)
449+
end
450+
success(P) || pipeline_error(P)
451+
return ret
437452
end
438-
writesto(cmds::AbstractCmd) = writesto(cmds, DevNull)
439453

454+
# TODO: convert this to use open(cmd, "r+"), with a single read/write pipe
440455
function readandwrite(cmds::AbstractCmd)
441-
(out, processes) = @tmp_wpipe tmp inpipe readsfrom(cmds, tmp)
456+
(out, processes) = @tmp_wpipe tmp inpipe open(cmds, "r", tmp)
442457
(out, inpipe, processes)
443458
end
444459

445460
function readbytes(cmd::AbstractCmd, stdin::AsyncStream=DevNull)
446-
(out,pc) = readsfrom(cmd, stdin)
447-
if !success(pc)
448-
pipeline_error(pc)
449-
end
461+
(out,pc) = open(cmd, "r", stdin)
462+
!success(pc) && pipeline_error(P)
450463
wait_close(out)
451464
return takebuf_array(out.buffer)
452465
end
@@ -455,15 +468,10 @@ function readall(cmd::AbstractCmd, stdin::AsyncStream=DevNull)
455468
return bytestring(readbytes(cmd, stdin))
456469
end
457470

458-
writeall(cmd::AbstractCmd, stdin::String) = writeall(cmd, stdin, DevNull)
459-
function writeall(cmd::AbstractCmd, stdin::String, stdout::AsyncStream)
460-
(in,pc) = writesto(cmd, stdout)
461-
write(in, stdin)
462-
close(in)
463-
if !success(pc)
464-
pipeline_error(pc)
471+
function writeall(cmd::AbstractCmd, stdin::String, stdout::AsyncStream=DevNull)
472+
open(cmd, "w", stdout) do io
473+
write(io, stdin)
465474
end
466-
return true
467475
end
468476

469477
function run(cmds::AbstractCmd,args...)

base/sharedarray.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,9 @@ function print_shmem_limits(slen)
317317
@linux_only pfx = "kernel"
318318
@osx_only pfx = "kern.sysv"
319319

320-
shmmax_MB = div(int(split(readall(readsfrom(`sysctl $(pfx).shmmax`)[1]))[end]), 1024*1024)
321-
page_size = int(split(readall(readsfrom(`getconf PAGE_SIZE`)[1]))[end])
322-
shmall_MB = div(int(split(readall(readsfrom(`sysctl $(pfx).shmall`)[1]))[end]) * page_size, 1024*1024)
320+
shmmax_MB = div(int(split(readall(`sysctl $(pfx).shmmax`))[end]), 1024*1024)
321+
page_size = int(split(readall(`getconf PAGE_SIZE`))[end])
322+
shmall_MB = div(int(split(readall(`sysctl $(pfx).shmall`))[end]) * page_size, 1024*1024)
323323

324324
println("System max size of single shmem segment(MB) : ", shmmax_MB,
325325
"\nSystem max size of all shmem segments(MB) : ", shmall_MB,

doc/manual/running-external-programs.rst

+9
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ can be used instead::
4747
julia> (chomp(a)) == "hello"
4848
true
4949

50+
More generally, you can use ``open`` to read from or write to an external
51+
command. For example:
52+
53+
julia> open(`less`, "w", STDOUT) do io
54+
for i = 1:1000
55+
println(io, i)
56+
end
57+
end
58+
5059
.. _man-command-interpolation:
5160

5261
Interpolation

doc/stdlib/base.rst

+16-7
Original file line numberDiff line numberDiff line change
@@ -4978,13 +4978,22 @@ System
49784978

49794979
Send a signal to a process. The default is to terminate the process.
49804980

4981-
.. function:: readsfrom(command)
4982-
4983-
Starts running a command asynchronously, and returns a tuple (stream,process). The first value is a stream reading from the process' standard output.
4984-
4985-
.. function:: writesto(command)
4986-
4987-
Starts running a command asynchronously, and returns a tuple (stream,process). The first value is a stream writing to the process' standard input.
4981+
.. function:: open(command, mode::String="r", stdio=DevNull)
4982+
4983+
Start running ``command`` asynchronously, and return a tuple
4984+
``(stream,process)``. If ``mode`` is ``"r"``, then ``stream``
4985+
reads from the process's standard output and ``stdio`` optionally
4986+
specifies the process's standard input stream. If ``mode`` is
4987+
``"w"``, then ``stream`` writes to the process's standard input
4988+
and ``stdio`` optionally specifies the process's standard output
4989+
stream.
4990+
4991+
.. function:: open(f::Function, command, mode::String="r", stdio=DevNull)
4992+
4993+
Similar to ``open(command, mode, stdio)``, but calls ``f(stream)``
4994+
on the resulting read or write stream, then closes the stream
4995+
and waits for the process to complete. Returns the value returned
4996+
by ``f``.
49884997

49894998
.. function:: readandwrite(command)
49904999

test/spawn.jl

+4-3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ end
6565
file = tempname()
6666
run(`echo hello world` |> file)
6767
@test readall(file |> `cat`) == "hello world\n"
68+
@test open(readall, file |> `cat`, "r") == "hello world\n"
6869
rm(file)
6970

7071
# Stream Redirection
@@ -99,9 +100,9 @@ str2 = readall(stdout)
99100

100101
# This test hangs if the end of run walk across uv streams calls shutdown on a stream that is shutting down.
101102
file = tempname()
102-
stdin, proc = writesto(`cat -` |> file)
103-
write(stdin, str)
104-
close(stdin)
103+
open(`cat -` |> file, "w") do io
104+
write(io, str)
105+
end
105106
rm(file)
106107

107108
# issue #3373

0 commit comments

Comments
 (0)