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
f8c2001f
Commit
f8c2001f
authored
Dec 21, 2014
by
Benjamin Peterson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
allow more operations to work on detached streams (closes #23093)
Patch by Martin Panter.
parent
22b21357
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
58 additions
and
40 deletions
+58
-40
Lib/_pyio.py
Lib/_pyio.py
+2
-2
Lib/test/test_io.py
Lib/test/test_io.py
+14
-0
Misc/NEWS
Misc/NEWS
+3
-0
Modules/_io/bufferedio.c
Modules/_io/bufferedio.c
+1
-1
Modules/_io/textio.c
Modules/_io/textio.c
+38
-37
No files found.
Lib/_pyio.py
View file @
f8c2001f
...
...
@@ -775,7 +775,7 @@ class _BufferedIOMixin(BufferedIOBase):
clsname
=
self
.
__class__
.
__name__
try
:
name
=
self
.
name
except
AttributeError
:
except
Exception
:
return
"<_pyio.{0}>"
.
format
(
clsname
)
else
:
return
"<_pyio.{0} name={1!r}>"
.
format
(
clsname
,
name
)
...
...
@@ -1538,7 +1538,7 @@ class TextIOWrapper(TextIOBase):
def
__repr__
(
self
):
try
:
name
=
self
.
name
except
AttributeError
:
except
Exception
:
return
"<_pyio.TextIOWrapper encoding='{0}'>"
.
format
(
self
.
encoding
)
else
:
return
"<_pyio.TextIOWrapper name={0!r} encoding='{1}'>"
.
format
(
...
...
Lib/test/test_io.py
View file @
f8c2001f
...
...
@@ -654,6 +654,8 @@ class CommonBufferedTests:
self
.
assertIs
(
buf
.
detach
(),
raw
)
self
.
assertRaises
(
ValueError
,
buf
.
detach
)
repr
(
buf
)
# Should still work
def
test_fileno
(
self
):
rawio
=
self
.
MockRawIO
()
bufio
=
self
.
tp
(
rawio
)
...
...
@@ -1922,6 +1924,12 @@ class TextIOWrapperTest(unittest.TestCase):
self
.
assertEqual
(
r
.
getvalue
(),
b"howdy"
)
self
.
assertRaises
(
ValueError
,
t
.
detach
)
# Operations independent of the detached stream should still work
repr
(
t
)
self
.
assertEqual
(
t
.
encoding
,
"ascii"
)
self
.
assertEqual
(
t
.
errors
,
"strict"
)
self
.
assertFalse
(
t
.
line_buffering
)
def
test_repr
(
self
):
raw
=
self
.
BytesIO
(
"hello"
.
encode
(
"utf-8"
))
b
=
self
.
BufferedReader
(
raw
)
...
...
@@ -1936,6 +1944,9 @@ class TextIOWrapperTest(unittest.TestCase):
self
.
assertEqual
(
repr
(
t
),
"<%s.TextIOWrapper name='dummy' encoding='utf-8'>"
%
modname
)
t
.
buffer
.
detach
()
repr
(
t
)
# Should not raise an exception
def
test_line_buffering
(
self
):
r
=
self
.
BytesIO
()
b
=
self
.
BufferedWriter
(
r
,
1000
)
...
...
@@ -2537,6 +2548,9 @@ class CTextIOWrapperTest(TextIOWrapperTest):
self
.
assertRaises
(
ValueError
,
t
.
__init__
,
b
,
newline
=
'xyzzy'
)
self
.
assertRaises
(
ValueError
,
t
.
read
)
t
=
self
.
TextIOWrapper
.
__new__
(
self
.
TextIOWrapper
)
self
.
assertRaises
(
Exception
,
repr
,
t
)
def
test_garbage_collection
(
self
):
# C TextIOWrapper objects are collected, and collecting them flushes
# all data to disk.
...
...
Misc/NEWS
View file @
f8c2001f
...
...
@@ -15,6 +15,9 @@ Core and Builtins
Library
-------
- Issue #23093: In the io, module allow more operations to work on detached
streams.
- Issue #23071: Added missing names to codecs.__all__. Patch by Martin Panter.
- Issue #23016: A warning no longer produces an AttributeError when sys.stderr
...
...
Modules/_io/bufferedio.c
View file @
f8c2001f
...
...
@@ -1222,7 +1222,7 @@ buffered_repr(buffered *self)
nameobj
=
PyObject_GetAttrString
((
PyObject
*
)
self
,
"name"
);
if
(
nameobj
==
NULL
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_
AttributeError
))
if
(
PyErr_ExceptionMatches
(
PyExc_
Exception
))
PyErr_Clear
();
else
return
NULL
;
...
...
Modules/_io/textio.c
View file @
f8c2001f
...
...
@@ -1152,25 +1152,27 @@ textiowrapper_closed_get(textio *self, void *context);
#define CHECK_INITIALIZED(self) \
if (self->ok <= 0) { \
if (self->detached) { \
PyErr_SetString(PyExc_ValueError, \
"underlying buffer has been detached"); \
} else { \
PyErr_SetString(PyExc_ValueError, \
"I/O operation on uninitialized object"); \
} \
PyErr_SetString(PyExc_ValueError, \
"I/O operation on uninitialized object"); \
return NULL; \
}
#define CHECK_ATTACHED(self) \
CHECK_INITIALIZED(self); \
if (self->detached) { \
PyErr_SetString(PyExc_ValueError, \
"underlying buffer has been detached"); \
return NULL; \
}
#define CHECK_
INITIALIZ
ED_INT(self) \
#define CHECK_
ATTACH
ED_INT(self) \
if (self->ok <= 0) { \
if (self->detached) { \
PyErr_SetString(PyExc_ValueError, \
"underlying buffer has been detached"); \
} else { \
PyErr_SetString(PyExc_ValueError, \
"I/O operation on uninitialized object"); \
} \
PyErr_SetString(PyExc_ValueError, \
"I/O operation on uninitialized object"); \
return -1; \
} else if (self->detached) { \
PyErr_SetString(PyExc_ValueError, \
"underlying buffer has been detached"); \
return -1; \
}
...
...
@@ -1179,7 +1181,7 @@ static PyObject *
textiowrapper_detach
(
textio
*
self
)
{
PyObject
*
buffer
,
*
res
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
res
=
PyObject_CallMethodObjArgs
((
PyObject
*
)
self
,
_PyIO_str_flush
,
NULL
);
if
(
res
==
NULL
)
return
NULL
;
...
...
@@ -1187,7 +1189,6 @@ textiowrapper_detach(textio *self)
buffer
=
self
->
buffer
;
self
->
buffer
=
NULL
;
self
->
detached
=
1
;
self
->
ok
=
0
;
return
buffer
;
}
...
...
@@ -1244,7 +1245,7 @@ textiowrapper_write(textio *self, PyObject *args)
int
haslf
=
0
;
int
needflush
=
0
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
if
(
!
PyArg_ParseTuple
(
args
,
"U:write"
,
&
text
))
{
return
NULL
;
...
...
@@ -1486,7 +1487,7 @@ textiowrapper_read(textio *self, PyObject *args)
Py_ssize_t
n
=
-
1
;
PyObject
*
result
=
NULL
,
*
chunks
=
NULL
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
if
(
!
PyArg_ParseTuple
(
args
,
"|O&:read"
,
&
_PyIO_ConvertSsize_t
,
&
n
))
return
NULL
;
...
...
@@ -1849,7 +1850,7 @@ textiowrapper_readline(textio *self, PyObject *args)
PyObject
*
limitobj
=
NULL
;
Py_ssize_t
limit
=
-
1
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
if
(
!
PyArg_ParseTuple
(
args
,
"|O:readline"
,
&
limitobj
))
{
return
NULL
;
}
...
...
@@ -2004,7 +2005,7 @@ textiowrapper_seek(textio *self, PyObject *args)
PyObject
*
res
;
int
cmp
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
if
(
!
PyArg_ParseTuple
(
args
,
"O|i:seek"
,
&
cookieObj
,
&
whence
))
return
NULL
;
...
...
@@ -2189,7 +2190,7 @@ textiowrapper_tell(textio *self, PyObject *args)
PyObject
*
saved_state
=
NULL
;
char
*
input
,
*
input_end
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
CHECK_CLOSED
(
self
);
if
(
!
self
->
seekable
)
{
...
...
@@ -2353,7 +2354,7 @@ textiowrapper_truncate(textio *self, PyObject *args)
PyObject
*
pos
=
Py_None
;
PyObject
*
res
;
CHECK_
INITIALIZ
ED
(
self
)
CHECK_
ATTACH
ED
(
self
)
if
(
!
PyArg_ParseTuple
(
args
,
"|O:truncate"
,
&
pos
))
{
return
NULL
;
}
...
...
@@ -2376,7 +2377,7 @@ textiowrapper_repr(textio *self)
nameobj
=
PyObject_GetAttrString
((
PyObject
*
)
self
,
"name"
);
if
(
nameobj
==
NULL
)
{
if
(
PyErr_ExceptionMatches
(
PyExc_
AttributeError
))
if
(
PyErr_ExceptionMatches
(
PyExc_
Exception
))
PyErr_Clear
();
else
goto
error
;
...
...
@@ -2408,42 +2409,42 @@ error:
static
PyObject
*
textiowrapper_fileno
(
textio
*
self
,
PyObject
*
args
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
return
PyObject_CallMethod
(
self
->
buffer
,
"fileno"
,
NULL
);
}
static
PyObject
*
textiowrapper_seekable
(
textio
*
self
,
PyObject
*
args
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
return
PyObject_CallMethod
(
self
->
buffer
,
"seekable"
,
NULL
);
}
static
PyObject
*
textiowrapper_readable
(
textio
*
self
,
PyObject
*
args
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
return
PyObject_CallMethod
(
self
->
buffer
,
"readable"
,
NULL
);
}
static
PyObject
*
textiowrapper_writable
(
textio
*
self
,
PyObject
*
args
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
return
PyObject_CallMethod
(
self
->
buffer
,
"writable"
,
NULL
);
}
static
PyObject
*
textiowrapper_isatty
(
textio
*
self
,
PyObject
*
args
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
return
PyObject_CallMethod
(
self
->
buffer
,
"isatty"
,
NULL
);
}
static
PyObject
*
textiowrapper_flush
(
textio
*
self
,
PyObject
*
args
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
CHECK_CLOSED
(
self
);
self
->
telling
=
self
->
seekable
;
if
(
_textiowrapper_writeflush
(
self
)
<
0
)
...
...
@@ -2456,7 +2457,7 @@ textiowrapper_close(textio *self, PyObject *args)
{
PyObject
*
res
;
int
r
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
res
=
textiowrapper_closed_get
(
self
,
NULL
);
if
(
res
==
NULL
)
...
...
@@ -2498,7 +2499,7 @@ textiowrapper_iternext(textio *self)
{
PyObject
*
line
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
self
->
telling
=
0
;
if
(
Py_TYPE
(
self
)
==
&
PyTextIOWrapper_Type
)
{
...
...
@@ -2534,14 +2535,14 @@ textiowrapper_iternext(textio *self)
static
PyObject
*
textiowrapper_name_get
(
textio
*
self
,
void
*
context
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
return
PyObject_GetAttrString
(
self
->
buffer
,
"name"
);
}
static
PyObject
*
textiowrapper_closed_get
(
textio
*
self
,
void
*
context
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
return
PyObject_GetAttr
(
self
->
buffer
,
_PyIO_str_closed
);
}
...
...
@@ -2549,7 +2550,7 @@ static PyObject *
textiowrapper_newlines_get
(
textio
*
self
,
void
*
context
)
{
PyObject
*
res
;
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
if
(
self
->
decoder
==
NULL
)
Py_RETURN_NONE
;
res
=
PyObject_GetAttr
(
self
->
decoder
,
_PyIO_str_newlines
);
...
...
@@ -2576,7 +2577,7 @@ textiowrapper_errors_get(textio *self, void *context)
static
PyObject
*
textiowrapper_chunk_size_get
(
textio
*
self
,
void
*
context
)
{
CHECK_
INITIALIZ
ED
(
self
);
CHECK_
ATTACH
ED
(
self
);
return
PyLong_FromSsize_t
(
self
->
chunk_size
);
}
...
...
@@ -2584,7 +2585,7 @@ static int
textiowrapper_chunk_size_set
(
textio
*
self
,
PyObject
*
arg
,
void
*
context
)
{
Py_ssize_t
n
;
CHECK_
INITIALIZ
ED_INT
(
self
);
CHECK_
ATTACH
ED_INT
(
self
);
n
=
PyNumber_AsSsize_t
(
arg
,
PyExc_TypeError
);
if
(
n
==
-
1
&&
PyErr_Occurred
())
return
-
1
;
...
...
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