<p dir="ltr"><br>
On 4 Mar 2013 19:19, "Robert Collins" <<a href="mailto:robertc@robertcollins.net">robertc@robertcollins.net</a>> wrote:<br>
><br>
> On 4 March 2013 22:12, Nick Coghlan <<a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>> wrote:<br>
> > On Mon, Mar 4, 2013 at 4:44 PM, Robert Collins<br>
> > <<a href="mailto:robertc@robertcollins.net">robertc@robertcollins.net</a>> wrote:<br>
> >> Some variations I can think of...<br>
> >><br>
> >> The buffer_only flag I suggested, on read_into, read1, read etc.<br>
> >><br>
> >> Have detach return the buffered data as you suggest - that would be<br>
> >> incompatible unless we stash it on the raw object somewhere, or do<br>
> >> something along those lines.<br>
> >><br>
> >> A read0 - analogous to read1, returns data from the buffer, but<br>
> >> guarantees no underlying calls.<br>
> >><br>
> >> I think exposing the buffer more explicitly is a good principle,<br>
> >> independent of whether we change detach or not.<br>
> ><br>
> > As Guido noted, you actually have multiple layers of buffering to<br>
> > contend with - for a text stream, you may have already decoded<br>
> > characters and partially decoded data in the codec's internal buffer,<br>
> > in addition to any data in the IO buffer. That's actually one of the<br>
> > interesting problems with supporting a "set_encoding()" method on IO<br>
> > streams (see <a href="http://bugs.python.org/issue15216">http://bugs.python.org/issue15216</a>).<br>
><br>
> Indeed. Fun! Caches are useful but add complexity :)<br>
><br>
> > How does the following API sound for your purposes? (this is based on<br>
> > what set_encoding() effectively has to do under the hood):<br>
> ><br>
> >     BufferedReader:<br>
> ><br>
> >         def push_data(binary_data):<br>
> >             """Prepends contents of 'data' to the internal buffer"""<br>
> ><br>
> >         def clear_buffer():<br>
> >             """Clears the internal buffer and returns the previous<br>
> > content as a bytes object"""<br>
> ><br>
> >     TextIOWrapper:<br>
> ><br>
> >         def push_data(char_data, binary_data=b""):<br>
> >             """Prepends contents of 'data' to the internal buffer. If<br>
> > binary_data is provided, it is pushed into the underlying IO buffered<br>
> > reader. Raises UnsupportedOperation if the underlying stream has no<br>
> > "push_data" method."""<br>
> ><br>
> >         def clear_buffer():<br>
> >             """Clears the internal buffers and returns the previous<br>
> > content as a (char_data, binary_data) pair. The binary data includes<br>
> > any data that was queued inside the codec, as well as the contents of<br>
> > the underlying IO buffer"""<br>
><br>
> That would make the story of 'get me back to raw IO' straightforward,<br>
> though the TextIOWrapper's clear_buffer semantics are a little unclear<br>
> to me from just the docstring. I think having TextIOWrapper only<br>
> return bytes from clear_buffer and only accept bytes in push_data<br>
> would be simpler to reason about, if a little more complex on the<br>
> internals.</p>
<p dir="ltr">I originally had it defined that way, but as Victor points out in the set_encoding issue, decoding is potentially lossy in the general case, so we can't reliably convert already decoded characters back to bytes. The appropriate way to handle that is going to be application specific, so I changed the proposed API to produce a (str, bytes) 2-tuple.</p>

<p dir="ltr">Cheers,<br>
Nick.</p>
<p dir="ltr">><br>
> Now, one could implement 'read0' manually using read1 + clear_buffer +<br>
> push_data:<br>
> # first, unwrap back to a bytes layer<br>
> buffer = textstream.buffer()<br>
> buffer.push_data(textstream.clear_buffer[1])<br>
> def read0(n):<br>
>     data = buffer.clear_buffer()<br>
>     result = data[:n]<br>
>     buffer.push_data(data[n:])<br>
>     return result<br>
><br>
> But it might be more efficient to define read0 directly on BufferedIOReader.<br>
><br>
> -Rob<br>
><br>
> --<br>
> Robert Collins <<a href="mailto:rbtcollins@hp.com">rbtcollins@hp.com</a>><br>
> Distinguished Technologist<br>
> HP Cloud Services<br>
</p>