Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
56452eea
Commit
56452eea
authored
Apr 13, 2015
by
Antoine Pitrou
Browse files
Options
Browse Files
Download
Plain Diff
Issue #22982: Improve BOM handling when seeking to multiple positions of a writable text file.
parents
682d0552
85e3ee74
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
52 additions
and
15 deletions
+52
-15
Lib/_pyio.py
Lib/_pyio.py
+15
-11
Lib/test/test_io.py
Lib/test/test_io.py
+13
-0
Misc/NEWS
Misc/NEWS
+3
-0
Modules/_io/textio.c
Modules/_io/textio.c
+21
-4
No files found.
Lib/_pyio.py
View file @
56452eea
...
...
@@ -2275,6 +2275,19 @@ class TextIOWrapper(TextIOBase):
return
buffer
def
seek
(
self
,
cookie
,
whence
=
0
):
def
_reset_encoder
(
position
):
"""Reset the encoder (merely useful for proper BOM handling)"""
try
:
encoder
=
self
.
_encoder
or
self
.
_get_encoder
()
except
LookupError
:
# Sometimes the encoder doesn't exist
pass
else
:
if
position
!=
0
:
encoder
.
setstate
(
0
)
else
:
encoder
.
reset
()
if
self
.
closed
:
raise
ValueError
(
"tell on closed file"
)
if
not
self
.
_seekable
:
...
...
@@ -2295,6 +2308,7 @@ class TextIOWrapper(TextIOBase):
self
.
_snapshot
=
None
if
self
.
_decoder
:
self
.
_decoder
.
reset
()
_reset_encoder
(
position
)
return
position
if
whence
!=
0
:
raise
ValueError
(
"unsupported whence (%r)"
%
(
whence
,))
...
...
@@ -2332,17 +2346,7 @@ class TextIOWrapper(TextIOBase):
raise
OSError
(
"can't restore logical file position"
)
self
.
_decoded_chars_used
=
chars_to_skip
# Finally, reset the encoder (merely useful for proper BOM handling)
try
:
encoder
=
self
.
_encoder
or
self
.
_get_encoder
()
except
LookupError
:
# Sometimes the encoder doesn't exist
pass
else
:
if
cookie
!=
0
:
encoder
.
setstate
(
0
)
else
:
encoder
.
reset
()
_reset_encoder
(
cookie
)
return
cookie
def
read
(
self
,
size
=
None
):
...
...
Lib/test/test_io.py
View file @
56452eea
...
...
@@ -2730,6 +2730,19 @@ class TextIOWrapperTest(unittest.TestCase):
with
self
.
open
(
filename
,
'rb'
)
as
f
:
self
.
assertEqual
(
f
.
read
(),
'bbbzzz'
.
encode
(
charset
))
def
test_seek_append_bom
(
self
):
# Same test, but first seek to the start and then to the end
filename
=
support
.
TESTFN
for
charset
in
(
'utf-8-sig'
,
'utf-16'
,
'utf-32'
):
with
self
.
open
(
filename
,
'w'
,
encoding
=
charset
)
as
f
:
f
.
write
(
'aaa'
)
with
self
.
open
(
filename
,
'a'
,
encoding
=
charset
)
as
f
:
f
.
seek
(
0
)
f
.
seek
(
0
,
self
.
SEEK_END
)
f
.
write
(
'xxx'
)
with
self
.
open
(
filename
,
'rb'
)
as
f
:
self
.
assertEqual
(
f
.
read
(),
'aaaxxx'
.
encode
(
charset
))
def
test_errors_property
(
self
):
with
self
.
open
(
support
.
TESTFN
,
"w"
)
as
f
:
self
.
assertEqual
(
f
.
errors
,
"strict"
)
...
...
Misc/NEWS
View file @
56452eea
...
...
@@ -24,6 +24,9 @@ Core and Builtins
Library
-------
- Issue #22982: Improve BOM handling when seeking to multiple positions of
a writable text file.
- Issue #23464: Removed deprecated asyncio JoinableQueue.
- Issue #23529: Limit the size of decompressed data when reading from
...
...
Modules/_io/textio.c
View file @
56452eea
...
...
@@ -2048,11 +2048,10 @@ _textiowrapper_decoder_setstate(textio *self, cookie_type *cookie)
}
static
int
_textiowrapper_encoder_
setstate
(
textio
*
self
,
cookie_type
*
cookie
)
_textiowrapper_encoder_
reset
(
textio
*
self
,
int
start_of_stream
)
{
PyObject
*
res
;
/* Same as _textiowrapper_decoder_setstate() above. */
if
(
cookie
->
start_pos
==
0
&&
cookie
->
dec_flags
==
0
)
{
if
(
start_of_stream
)
{
res
=
PyObject_CallMethodObjArgs
(
self
->
encoder
,
_PyIO_str_reset
,
NULL
);
self
->
encoding_start_of_stream
=
1
;
}
...
...
@@ -2067,6 +2066,14 @@ _textiowrapper_encoder_setstate(textio *self, cookie_type *cookie)
return
0
;
}
static
int
_textiowrapper_encoder_setstate
(
textio
*
self
,
cookie_type
*
cookie
)
{
/* Same as _textiowrapper_decoder_setstate() above. */
return
_textiowrapper_encoder_reset
(
self
,
cookie
->
start_pos
==
0
&&
cookie
->
dec_flags
==
0
);
}
static
PyObject
*
textiowrapper_seek
(
textio
*
self
,
PyObject
*
args
)
{
...
...
@@ -2134,7 +2141,17 @@ textiowrapper_seek(textio *self, PyObject *args)
}
res
=
_PyObject_CallMethodId
(
self
->
buffer
,
&
PyId_seek
,
"ii"
,
0
,
2
);
Py_XDECREF
(
cookieObj
);
Py_CLEAR
(
cookieObj
);
if
(
res
==
NULL
)
goto
fail
;
if
(
self
->
encoder
)
{
/* If seek() == 0, we are at the start of stream, otherwise not */
cmp
=
PyObject_RichCompareBool
(
res
,
_PyIO_zero
,
Py_EQ
);
if
(
cmp
<
0
||
_textiowrapper_encoder_reset
(
self
,
cmp
))
{
Py_DECREF
(
res
);
goto
fail
;
}
}
return
res
;
}
else
if
(
whence
!=
0
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment