summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/typeobj.rst5
-rw-r--r--Doc/library/logging.config.rst25
-rw-r--r--Lib/calendar.py11
-rw-r--r--Lib/test/pickletester.py13
-rw-r--r--Lib/test/test_calendar.py7
-rw-r--r--Misc/NEWS5
-rw-r--r--Modules/_pickle.c3
7 files changed, 63 insertions, 6 deletions
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index 4a6335c..68ca9ad 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -745,6 +745,11 @@ type objects) *must* have the :attr:`ob_size` field.
This field is not inherited by subtypes (though the attributes defined in here
are inherited through a different mechanism).
+ .. warning::
+
+ It is not safe to use :c:func:`PyDict_SetItem` on or otherwise modify
+ :attr:`tp_dict` with the dictionary C-API.
+
.. c:member:: descrgetfunc PyTypeObject.tp_descr_get
diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst
index bb80a7f..b2dd71e 100644
--- a/Doc/library/logging.config.rst
+++ b/Doc/library/logging.config.rst
@@ -513,6 +513,31 @@ the system will attempt to retrieve the value from
to ``config_dict['handlers']['myhandler']['mykey']['123']`` if that
fails.
+
+.. _logging-import-resolution:
+
+Import resolution and custom importers
+""""""""""""""""""""""""""""""""""""""
+
+Import resolution, by default, uses the builtin :func:`__import__` function
+to do its importing. You may want to replace this with your own importing
+mechanism: if so, you can replace the :attr:`importer` attribute of the
+:class:`DictConfigurator` or its superclass, the
+:class:`BaseConfigurator` class. However, you need to be
+careful because of the way functions are accessed from classes via
+descriptors. If you are using a Python callable to do your imports, and you
+want to define it at class level rather than instance level, you need to wrap
+it with :func:`staticmethod`. For example::
+
+ from importlib import import_module
+ from logging.config import BaseConfigurator
+
+ BaseConfigurator.importer = staticmethod(import_module)
+
+You don't need to wrap with :func:`staticmethod` if you're setting the import
+callable on a configurator *instance*.
+
+
.. _logging-config-fileformat:
Configuration file format
diff --git a/Lib/calendar.py b/Lib/calendar.py
index 84aa3a4..0301d6b 100644
--- a/Lib/calendar.py
+++ b/Lib/calendar.py
@@ -636,7 +636,7 @@ def main(args):
parser.add_option(
"-e", "--encoding",
dest="encoding", default=None,
- help="Encoding to use for output"
+ help="Encoding to use for output."
)
parser.add_option(
"-t", "--type",
@@ -662,10 +662,11 @@ def main(args):
if encoding is None:
encoding = sys.getdefaultencoding()
optdict = dict(encoding=encoding, css=options.css)
+ write = sys.stdout.buffer.write
if len(args) == 1:
- print(cal.formatyearpage(datetime.date.today().year, **optdict))
+ write(cal.formatyearpage(datetime.date.today().year, **optdict))
elif len(args) == 2:
- print(cal.formatyearpage(int(args[1]), **optdict))
+ write(cal.formatyearpage(int(args[1]), **optdict))
else:
parser.error("incorrect number of arguments")
sys.exit(1)
@@ -687,9 +688,11 @@ def main(args):
else:
parser.error("incorrect number of arguments")
sys.exit(1)
+ write = sys.stdout.write
if options.encoding:
result = result.encode(options.encoding)
- print(result)
+ write = sys.stdout.buffer.write
+ write(result)
if __name__ == "__main__":
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index a843486..e4ab0dd 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -1418,6 +1418,19 @@ class AbstractPicklerUnpicklerObjectTests(unittest.TestCase):
def test_multiple_unpicklings_unseekable(self):
self._check_multiple_unpicklings(UnseekableIO)
+ def test_unpickling_buffering_readline(self):
+ # Issue #12687: the unpickler's buffering logic could fail with
+ # text mode opcodes.
+ data = list(range(10))
+ for proto in protocols:
+ for buf_size in range(1, 11):
+ f = io.BufferedRandom(io.BytesIO(), buffer_size=buf_size)
+ pickler = self.pickler_class(f, protocol=proto)
+ pickler.dump(data)
+ f.seek(0)
+ unpickler = self.unpickler_class(f)
+ self.assertEqual(unpickler.load(), data)
+
if __name__ == "__main__":
# Print some stuff that can be used to rewrite DATA{0,1,2}
diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py
index 4bd758b..d3093ac 100644
--- a/Lib/test/test_calendar.py
+++ b/Lib/test/test_calendar.py
@@ -2,6 +2,7 @@ import calendar
import unittest
from test import support
+from test.script_helper import assert_python_ok
import time
import locale
@@ -451,6 +452,11 @@ class LeapdaysTestCase(unittest.TestCase):
self.assertEqual(calendar.leapdays(1997,2020), 5)
+class ConsoleOutputTestCase(unittest.TestCase):
+ def test_outputs_bytes(self):
+ (return_code, stdout, stderr) = assert_python_ok('-m', 'calendar', '--type=html', '2010')
+ self.assertEqual(stdout[:6], b'<?xml ')
+
def test_main():
support.run_unittest(
OutputTestCase,
@@ -460,6 +466,7 @@ def test_main():
TimegmTestCase,
MonthRangeTestCase,
LeapdaysTestCase,
+ ConsoleOutputTestCase
)
diff --git a/Misc/NEWS b/Misc/NEWS
index dcdda84..c9a0522 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -41,6 +41,11 @@ Core and Builtins
Library
-------
+- Issue #12687: Fix a possible buffering bug when unpickling text mode
+ (protocol 0, mostly) pickles.
+
+- Issue #10087: Fix the html output format of the calendar module.
+
- Issue #12540: Prevent zombie IDLE processes on Windows due to changes
in os.kill().
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 287f0a3..001360b 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -1034,9 +1034,8 @@ _Unpickler_Readline(UnpicklerObject *self, char **result)
num_read = _Unpickler_ReadFromFile(self, READ_WHOLE_LINE);
if (num_read < 0)
return -1;
- *result = self->input_buffer;
self->next_read_idx = num_read;
- return num_read;
+ return _Unpickler_CopyLine(self, self->input_buffer, num_read, result);
}
/* If we get here, we've run off the end of the input string. Return the