Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Include/internal/pycore_global_objects_fini_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(intern)
STRUCT_FOR_ID(intersection)
STRUCT_FOR_ID(interval)
STRUCT_FOR_ID(io)
STRUCT_FOR_ID(is_running)
STRUCT_FOR_ID(is_struct)
STRUCT_FOR_ID(isatty)
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_runtime_init_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Include/internal/pycore_unicodeobject_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions Lib/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@
IncrementalNewlineDecoder, text_encoding, TextIOWrapper)


# Pretend this exception was created here.
UnsupportedOperation.__module__ = "io"

# for seek()
SEEK_SET = 0
SEEK_CUR = 1
Expand Down
2 changes: 1 addition & 1 deletion Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
import os
import builtins
import _sitebuiltins
import io
import _io as io
import stat

# Prefixes for site-packages; add additional prefixes like /usr/local here
Expand Down
19 changes: 19 additions & 0 deletions Lib/test/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,25 @@ def test_invalid_operations(self):
self.assertRaises(exc, fp.seek, 1, self.SEEK_CUR)
self.assertRaises(exc, fp.seek, -1, self.SEEK_END)

@support.cpython_only
def test_startup_optimization(self):
# gh-132952: Test that `io` is not imported at startup and that the
# __module__ of UnsupportedOperation is set to "io".
assert_python_ok("-S", "-c", textwrap.dedent(
"""
import sys
assert "io" not in sys.modules
try:
sys.stdin.truncate()
except Exception as e:
typ = type(e)
assert typ.__module__ == "io", (typ, typ.__module__)
assert typ.__name__ == "UnsupportedOperation", (typ, typ.__name__)
else:
raise AssertionError("Expected UnsupportedOperation")
"""
))

@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
def test_optional_abilities(self):
# Test for OSError when optional APIs are not supported
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import test.support
from test import support
from test.support.script_helper import assert_python_ok
from test.support import import_helper
from test.support import os_helper
from test.support import socket_helper
from test.support import captured_stderr
Expand Down Expand Up @@ -574,6 +575,17 @@ def test_license_exists_at_url(self):
code = e.code
self.assertEqual(code, 200, msg="Can't find " + url)

@support.cpython_only
def test_lazy_imports(self):
import_helper.ensure_lazy_imports("site", [
"io",
"locale",
"traceback",
"atexit",
"warnings",
"textwrap",
])


class StartupImportTests(unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Speed up startup with the ``-S`` argument by about 19% by importing the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is worth mentioning "vs what" when stating an improvement %.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's 19% vs. before this commit, but it's only 1.5% faster than 3.13.0 (which is probably what most users care about, since they don't run main). I would argue 1.5% is in the noise, so we probably shouldn't have a what's new entry at all -- this is just counteracting a regression in 3.14 development.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's only a NEWS entry, not text in the What's New, so I'll remove the 19% claim but leave the NEWS entry since this could affect behavior some users care about.

private ``_io`` module instead of :mod:`io`.
5 changes: 5 additions & 0 deletions Modules/_io/_iomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,11 @@ iomodule_exec(PyObject *m)
"UnsupportedOperation", PyExc_OSError, PyExc_ValueError);
if (state->unsupported_operation == NULL)
return -1;
if (PyObject_SetAttrString(state->unsupported_operation,
"__module__", &_Py_ID(io)) < 0)
{
return -1;
}
if (PyModule_AddObjectRef(m, "UnsupportedOperation",
state->unsupported_operation) < 0)
{
Expand Down
4 changes: 2 additions & 2 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -2762,7 +2762,7 @@ init_set_builtins_open(void)
goto error;
}

if (!(wrapper = PyImport_ImportModuleAttrString("io", "open"))) {
if (!(wrapper = PyImport_ImportModuleAttrString("_io", "open"))) {
goto error;
}

Expand Down Expand Up @@ -2807,7 +2807,7 @@ init_sys_streams(PyThreadState *tstate)
}
#endif

if (!(iomod = PyImport_ImportModule("io"))) {
if (!(iomod = PyImport_ImportModule("_io"))) {
goto error;
}

Expand Down
Loading