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
59142db6
Commit
59142db6
authored
Oct 31, 2011
by
Ross Lagerwall
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #12797: Added custom opener parameter to builtin open() and FileIO.open().
parent
ab06e3f2
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
89 additions
and
22 deletions
+89
-22
Doc/library/functions.rst
Doc/library/functions.rst
+10
-1
Doc/library/io.rst
Doc/library/io.rst
+10
-1
Lib/_pyio.py
Lib/_pyio.py
+8
-2
Lib/test/test_io.py
Lib/test/test_io.py
+9
-0
Misc/NEWS
Misc/NEWS
+3
-0
Modules/_io/_iomodule.c
Modules/_io/_iomodule.c
+12
-6
Modules/_io/fileio.c
Modules/_io/fileio.c
+37
-12
No files found.
Doc/library/functions.rst
View file @
59142db6
...
@@ -776,7 +776,7 @@ are always available. They are listed here in alphabetical order.
...
@@ -776,7 +776,7 @@ are always available. They are listed here in alphabetical order.
:meth:`__index__` method that returns an integer.
:meth:`__index__` method that returns an integer.
.. function:: open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)
.. function:: open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True
, opener=None
)
Open *file* and return a corresponding stream. If the file cannot be opened,
Open *file* and return a corresponding stream. If the file cannot be opened,
an :exc:`OSError` is raised.
an :exc:`OSError` is raised.
...
@@ -883,6 +883,15 @@ are always available. They are listed here in alphabetical order.
...
@@ -883,6 +883,15 @@ are always available. They are listed here in alphabetical order.
closed. If a filename is given *closefd* has no effect and must be ``True``
closed. If a filename is given *closefd* has no effect and must be ``True``
(the default).
(the default).
A custom opener can be used by passing a callable as *opener*. The underlying
file descriptor for the file object is then obtained by calling *opener* with
(*file*, *flags*). *opener* must return an open file descriptor (passing
:mod:`os.open` as *opener* results in functionality similar to passing
``None``).
.. versionchanged:: 3.3
The *opener* parameter was added.
The type of file object returned by the :func:`open` function depends on the
The type of file object returned by the :func:`open` function depends on the
mode. When :func:`open` is used to open a file in a text mode (``'w'``,
mode. When :func:`open` is used to open a file in a text mode (``'w'``,
``'r'``, ``'wt'``, ``'rt'``, etc.), it returns a subclass of
``'r'``, ``'wt'``, ``'rt'``, etc.), it returns a subclass of
...
...
Doc/library/io.rst
View file @
59142db6
...
@@ -458,7 +458,7 @@ I/O Base Classes
...
@@ -458,7 +458,7 @@ I/O Base Classes
Raw File I/O
Raw File I/O
^^^^^^^^^^^^
^^^^^^^^^^^^
.. class:: FileIO(name, mode='r', closefd=True)
.. class:: FileIO(name, mode='r', closefd=True
, opener=None
)
:class:`FileIO` represents an OS-level file containing bytes data.
:class:`FileIO` represents an OS-level file containing bytes data.
It implements the :class:`RawIOBase` interface (and therefore the
It implements the :class:`RawIOBase` interface (and therefore the
...
@@ -479,6 +479,15 @@ Raw File I/O
...
@@ -479,6 +479,15 @@ Raw File I/O
The :meth:`read` (when called with a positive argument), :meth:`readinto`
The :meth:`read` (when called with a positive argument), :meth:`readinto`
and :meth:`write` methods on this class will only make one system call.
and :meth:`write` methods on this class will only make one system call.
A custom opener can be used by passing a callable as *opener*. The underlying
file descriptor for the file object is then obtained by calling *opener* with
(*name*, *flags*). *opener* must return an open file descriptor (passing
:mod:`os.open` as *opener* results in functionality similar to passing
``None``).
.. versionchanged:: 3.3
The *opener* parameter was added.
In addition to the attributes and methods from :class:`IOBase` and
In addition to the attributes and methods from :class:`IOBase` and
:class:`RawIOBase`, :class:`FileIO` provides the following data
:class:`RawIOBase`, :class:`FileIO` provides the following data
attributes and methods:
attributes and methods:
...
...
Lib/_pyio.py
View file @
59142db6
...
@@ -27,7 +27,7 @@ BlockingIOError = BlockingIOError
...
@@ -27,7 +27,7 @@ BlockingIOError = BlockingIOError
def
open
(
file
,
mode
=
"r"
,
buffering
=-
1
,
encoding
=
None
,
errors
=
None
,
def
open
(
file
,
mode
=
"r"
,
buffering
=-
1
,
encoding
=
None
,
errors
=
None
,
newline
=
None
,
closefd
=
True
):
newline
=
None
,
closefd
=
True
,
opener
=
None
):
r"""Open file and return a stream. Raise IOError upon failure.
r"""Open file and return a stream. Raise IOError upon failure.
...
@@ -122,6 +122,12 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
...
@@ -122,6 +122,12 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
be kept open when the file is closed. This does not work when a file name is
be kept open when the file is closed. This does not work when a file name is
given and must be True in that case.
given and must be True in that case.
A custom opener can be used by passing a callable as *opener*. The
underlying file descriptor for the file object is then obtained by calling
*opener* with (*file*, *flags*). *opener* must return an open file
descriptor (passing os.open as *opener* results in functionality similar to
passing None).
open() returns a file object whose type depends on the mode, and
open() returns a file object whose type depends on the mode, and
through which the standard file operations such as reading and writing
through which the standard file operations such as reading and writing
are performed. When open() is used to open a file in a text mode ('w',
are performed. When open() is used to open a file in a text mode ('w',
...
@@ -176,7 +182,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
...
@@ -176,7 +182,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
(
writing
and
"w"
or
""
)
+
(
writing
and
"w"
or
""
)
+
(
appending
and
"a"
or
""
)
+
(
appending
and
"a"
or
""
)
+
(
updating
and
"+"
or
""
),
(
updating
and
"+"
or
""
),
closefd
)
closefd
,
opener
=
opener
)
line_buffering
=
False
line_buffering
=
False
if
buffering
==
1
or
buffering
<
0
and
raw
.
isatty
():
if
buffering
==
1
or
buffering
<
0
and
raw
.
isatty
():
buffering
=
-
1
buffering
=
-
1
...
...
Lib/test/test_io.py
View file @
59142db6
...
@@ -621,6 +621,15 @@ class IOTest(unittest.TestCase):
...
@@ -621,6 +621,15 @@ class IOTest(unittest.TestCase):
for
obj
in
test
:
for
obj
in
test
:
self
.
assertTrue
(
hasattr
(
obj
,
"__dict__"
))
self
.
assertTrue
(
hasattr
(
obj
,
"__dict__"
))
def
test_opener
(
self
):
with
self
.
open
(
support
.
TESTFN
,
"w"
)
as
f
:
f
.
write
(
"egg
\
n
"
)
fd
=
os
.
open
(
support
.
TESTFN
,
os
.
O_RDONLY
)
def
opener
(
path
,
flags
):
return
fd
with
self
.
open
(
"non-existent"
,
"r"
,
opener
=
opener
)
as
f
:
self
.
assertEqual
(
f
.
read
(),
"egg
\
n
"
)
class
CIOTest
(
IOTest
):
class
CIOTest
(
IOTest
):
def
test_IOBase_finalize
(
self
):
def
test_IOBase_finalize
(
self
):
...
...
Misc/NEWS
View file @
59142db6
...
@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
...
@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
Core and Builtins
Core and Builtins
-----------------
-----------------
- Issue #12797: Added custom opener parameter to builtin open() and
FileIO.open().
- Issue #10519: Avoid unnecessary recursive function calls in
- Issue #10519: Avoid unnecessary recursive function calls in
setobject.c.
setobject.c.
...
...
Modules/_io/_iomodule.c
View file @
59142db6
...
@@ -95,7 +95,7 @@ PyDoc_STRVAR(module_doc,
...
@@ -95,7 +95,7 @@ PyDoc_STRVAR(module_doc,
*/
*/
PyDoc_STRVAR
(
open_doc
,
PyDoc_STRVAR
(
open_doc
,
"open(file, mode='r', buffering=-1, encoding=None,
\n
"
"open(file, mode='r', buffering=-1, encoding=None,
\n
"
" errors=None, newline=None, closefd=True) -> file object
\n
"
" errors=None, newline=None, closefd=True
, opener=None
) -> file object
\n
"
"
\n
"
"
\n
"
"Open file and return a stream. Raise IOError upon failure.
\n
"
"Open file and return a stream. Raise IOError upon failure.
\n
"
"
\n
"
"
\n
"
...
@@ -190,6 +190,12 @@ PyDoc_STRVAR(open_doc,
...
@@ -190,6 +190,12 @@ PyDoc_STRVAR(open_doc,
"when the file is closed. This does not work when a file name is given
\n
"
"when the file is closed. This does not work when a file name is given
\n
"
"and must be True in that case.
\n
"
"and must be True in that case.
\n
"
"
\n
"
"
\n
"
"A custom opener can be used by passing a callable as *opener*. The
\n
"
"underlying file descriptor for the file object is then obtained by
\n
"
"calling *opener* with (*file*, *flags*). *opener* must return an open
\n
"
"file descriptor (passing os.open as *opener* results in functionality
\n
"
"similar to passing None).
\n
"
"
\n
"
"open() returns a file object whose type depends on the mode, and
\n
"
"open() returns a file object whose type depends on the mode, and
\n
"
"through which the standard file operations such as reading and writing
\n
"
"through which the standard file operations such as reading and writing
\n
"
"are performed. When open() is used to open a file in a text mode ('w',
\n
"
"are performed. When open() is used to open a file in a text mode ('w',
\n
"
...
@@ -210,8 +216,8 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds)
...
@@ -210,8 +216,8 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds)
{
{
char
*
kwlist
[]
=
{
"file"
,
"mode"
,
"buffering"
,
char
*
kwlist
[]
=
{
"file"
,
"mode"
,
"buffering"
,
"encoding"
,
"errors"
,
"newline"
,
"encoding"
,
"errors"
,
"newline"
,
"closefd"
,
NULL
};
"closefd"
,
"opener"
,
NULL
};
PyObject
*
file
;
PyObject
*
file
,
*
opener
=
Py_None
;
char
*
mode
=
"r"
;
char
*
mode
=
"r"
;
int
buffering
=
-
1
,
closefd
=
1
;
int
buffering
=
-
1
,
closefd
=
1
;
char
*
encoding
=
NULL
,
*
errors
=
NULL
,
*
newline
=
NULL
;
char
*
encoding
=
NULL
,
*
errors
=
NULL
,
*
newline
=
NULL
;
...
@@ -228,10 +234,10 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds)
...
@@ -228,10 +234,10 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds)
_Py_IDENTIFIER
(
isatty
);
_Py_IDENTIFIER
(
isatty
);
_Py_IDENTIFIER
(
fileno
);
_Py_IDENTIFIER
(
fileno
);
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"O|sizzzi:open"
,
kwlist
,
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"O|sizzzi
O
:open"
,
kwlist
,
&
file
,
&
mode
,
&
buffering
,
&
file
,
&
mode
,
&
buffering
,
&
encoding
,
&
errors
,
&
newline
,
&
encoding
,
&
errors
,
&
newline
,
&
closefd
))
{
&
closefd
,
&
opener
))
{
return
NULL
;
return
NULL
;
}
}
...
@@ -331,7 +337,7 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds)
...
@@ -331,7 +337,7 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds)
/* Create the Raw file stream */
/* Create the Raw file stream */
raw
=
PyObject_CallFunction
((
PyObject
*
)
&
PyFileIO_Type
,
raw
=
PyObject_CallFunction
((
PyObject
*
)
&
PyFileIO_Type
,
"Osi"
,
file
,
rawmode
,
closefd
);
"OsiO"
,
file
,
rawmode
,
closefd
,
opener
);
if
(
raw
==
NULL
)
if
(
raw
==
NULL
)
return
NULL
;
return
NULL
;
...
...
Modules/_io/fileio.c
View file @
59142db6
...
@@ -212,9 +212,9 @@ static int
...
@@ -212,9 +212,9 @@ static int
fileio_init
(
PyObject
*
oself
,
PyObject
*
args
,
PyObject
*
kwds
)
fileio_init
(
PyObject
*
oself
,
PyObject
*
args
,
PyObject
*
kwds
)
{
{
fileio
*
self
=
(
fileio
*
)
oself
;
fileio
*
self
=
(
fileio
*
)
oself
;
static
char
*
kwlist
[]
=
{
"file"
,
"mode"
,
"closefd"
,
NULL
};
static
char
*
kwlist
[]
=
{
"file"
,
"mode"
,
"closefd"
,
"opener"
,
NULL
};
const
char
*
name
=
NULL
;
const
char
*
name
=
NULL
;
PyObject
*
nameobj
,
*
stringobj
=
NULL
;
PyObject
*
nameobj
,
*
stringobj
=
NULL
,
*
opener
=
Py_None
;
char
*
mode
=
"r"
;
char
*
mode
=
"r"
;
char
*
s
;
char
*
s
;
#ifdef MS_WINDOWS
#ifdef MS_WINDOWS
...
@@ -233,8 +233,9 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
...
@@ -233,8 +233,9 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
return
-
1
;
return
-
1
;
}
}
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"O|si:fileio"
,
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"O|siO:fileio"
,
kwlist
,
&
nameobj
,
&
mode
,
&
closefd
))
kwlist
,
&
nameobj
,
&
mode
,
&
closefd
,
&
opener
))
return
-
1
;
return
-
1
;
if
(
PyFloat_Check
(
nameobj
))
{
if
(
PyFloat_Check
(
nameobj
))
{
...
@@ -363,8 +364,9 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
...
@@ -363,8 +364,9 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
goto
error
;
goto
error
;
}
}
Py_BEGIN_ALLOW_THREADS
errno
=
0
;
errno
=
0
;
if
(
opener
==
Py_None
)
{
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
#ifdef MS_WINDOWS
if
(
widename
!=
NULL
)
if
(
widename
!=
NULL
)
self
->
fd
=
_wopen
(
widename
,
flags
,
0666
);
self
->
fd
=
_wopen
(
widename
,
flags
,
0666
);
...
@@ -372,6 +374,25 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
...
@@ -372,6 +374,25 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
#endif
#endif
self
->
fd
=
open
(
name
,
flags
,
0666
);
self
->
fd
=
open
(
name
,
flags
,
0666
);
Py_END_ALLOW_THREADS
Py_END_ALLOW_THREADS
}
else
{
PyObject
*
fdobj
=
PyObject_CallFunction
(
opener
,
"Oi"
,
nameobj
,
flags
);
if
(
fdobj
==
NULL
)
goto
error
;
if
(
!
PyLong_Check
(
fdobj
))
{
Py_DECREF
(
fdobj
);
PyErr_SetString
(
PyExc_TypeError
,
"expected integer from opener"
);
goto
error
;
}
self
->
fd
=
PyLong_AsLong
(
fdobj
);
Py_DECREF
(
fdobj
);
if
(
self
->
fd
==
-
1
)
{
goto
error
;
}
}
if
(
self
->
fd
<
0
)
{
if
(
self
->
fd
<
0
)
{
#ifdef MS_WINDOWS
#ifdef MS_WINDOWS
if
(
widename
!=
NULL
)
if
(
widename
!=
NULL
)
...
@@ -1017,13 +1038,17 @@ fileio_getstate(fileio *self)
...
@@ -1017,13 +1038,17 @@ fileio_getstate(fileio *self)
PyDoc_STRVAR
(
fileio_doc
,
PyDoc_STRVAR
(
fileio_doc
,
"file(name: str[, mode: str]) -> file IO object
\n
"
"file(name: str[, mode: str]
[, opener: None]
) -> file IO object
\n
"
"
\n
"
"
\n
"
"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),
\n
"
"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),
\n
"
"writing or appending. The file will be created if it doesn't exist
\n
"
"writing or appending. The file will be created if it doesn't exist
\n
"
"when opened for writing or appending; it will be truncated when
\n
"
"when opened for writing or appending; it will be truncated when
\n
"
"opened for writing. Add a '+' to the mode to allow simultaneous
\n
"
"opened for writing. Add a '+' to the mode to allow simultaneous
\n
"
"reading and writing."
);
"reading and writing. A custom opener can be used by passing a
\n
"
"callable as *opener*. The underlying file descriptor for the file
\n
"
"object is then obtained by calling opener with (*name*, *flags*).
\n
"
"*opener* must return an open file descriptor (passing os.open as
\n
"
"*opener* results in functionality similar to passing None)."
);
PyDoc_STRVAR
(
read_doc
,
PyDoc_STRVAR
(
read_doc
,
"read(size: int) -> bytes. read at most size bytes, returned as bytes.
\n
"
"read(size: int) -> bytes. read at most size bytes, returned as bytes.
\n
"
...
...
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