11"""
2- PyIO(x; own=false, text=missing, buflen=4096)
2+ PyIO(x; own=false, text=missing, line_buffering=false, buflen=4096)
33
44Wrap the Python IO stream `x` as a Julia IO stream.
55
@@ -10,6 +10,8 @@ If `text=true` then `x` must be a text stream and only UTF-8 must be written (i.
1010If `text` is not specified then it is chosen automatically.
1111If `x` is a text stream and you really need a binary stream, then often `PyIO(x.buffer)` will work.
1212
13+ If `line_buffering=true` then output is flushed at each line.
14+
1315For efficiency, reads and writes are buffered before being sent to `x`.
1416The size of the buffers is `buflen`.
1517The buffers are cleared using `flush`.
@@ -20,6 +22,8 @@ mutable struct PyIO <: IO
2022 own:: Bool
2123 # true if `o` is text, false if binary
2224 text:: Bool
25+ # true to flush whenever '\n' or '\r' is encountered
26+ line_buffering:: Bool
2327 # true if we are definitely at the end of the file; false if we are not or don't know
2428 eof:: Bool
2529 # input buffer
@@ -29,7 +33,7 @@ mutable struct PyIO <: IO
2933 obuflen:: Int
3034 obuf:: Vector{UInt8}
3135
32- function PyIO (x; own:: Bool = false , text:: Union{Missing,Bool} = missing , buflen:: Integer = 4096 , ibuflen:: Integer = buflen, obuflen:: Integer = buflen)
36+ function PyIO (x; own:: Bool = false , text:: Union{Missing,Bool} = missing , buflen:: Integer = 4096 , ibuflen:: Integer = buflen, obuflen:: Integer = buflen, line_buffering :: Bool = false )
3337 if text === missing
3438 text = pyhasattr (x, " encoding" )
3539 end
@@ -39,7 +43,7 @@ mutable struct PyIO <: IO
3943 ibuflen > 0 || error (" ibuflen must be positive" )
4044 obuflen = convert (Int, obuflen)
4145 obuflen > 0 || error (" obuflen must be positive" )
42- new (Py (x), own, text, false , ibuflen, UInt8[], obuflen, UInt8[])
46+ new (Py (x), own, text, line_buffering, false , ibuflen, UInt8[], obuflen, UInt8[])
4347 end
4448end
4549export PyIO
@@ -136,23 +140,37 @@ Base.isopen(io::PyIO) = !pyconvert(Bool, @py io.closed)
136140
137141function Base. unsafe_write (io:: PyIO , ptr:: Ptr{UInt8} , n:: UInt )
138142 ntodo = n
139- while true
143+ while ntodo > 0
140144 nroom = max (0 , io. obuflen - length (io. obuf))
141145 if ntodo < nroom
142- append! (io. obuf, unsafe_wrap (Array, ptr, ntodo))
143- return n
146+ buf = unsafe_wrap (Array, ptr, ntodo)
147+ if io. line_buffering
148+ i = findlast (∈ ((0x0A , 0x0D )), buf)
149+ if i === nothing
150+ append! (io. obuf, buf)
151+ else
152+ append! (io. obuf, unsafe_wrap (Array, ptr, i))
153+ putobuf (io)
154+ append! (io. obuf, unsafe_wrap (Array, ptr+ i, ntodo- i))
155+ end
156+ else
157+ append! (io. obuf, buf)
158+ end
159+ break
144160 else
145- append! (io. obuf, unsafe_wrap (Array, ptr, nroom))
161+ buf = unsafe_wrap (Array, ptr, nroom)
162+ append! (io. obuf, buf)
146163 putobuf (io)
147164 ptr += nroom
148165 ntodo -= nroom
149166 end
150167 end
168+ return n
151169end
152170
153171function Base. write (io:: PyIO , c:: UInt8 )
154172 push! (io. obuf, c)
155- if length (io. obuf) ≥ io. obuflen
173+ if ( length (io. obuf) ≥ io. obuflen) || (io . line_buffering && (c == 0x0A || c == 0x0D ))
156174 putobuf (io)
157175 end
158176 return
0 commit comments