Skip to content

Commit e960c17

Browse files
committed
Merge branch 'master' into port-marshal-to-pep757/127936
2 parents 44c7c6a + 6ea04da commit e960c17

File tree

8 files changed

+142
-20
lines changed

8 files changed

+142
-20
lines changed

Doc/library/calendar.rst

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,33 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is
3838
itself. This is the job of subclasses.
3939

4040

41-
:class:`Calendar` instances have the following methods:
41+
:class:`Calendar` instances have the following methods and attributes:
42+
43+
.. attribute:: firstweekday
44+
45+
The first weekday as an integer (0--6).
46+
47+
This property can also be set and read using
48+
:meth:`~Calendar.setfirstweekday` and
49+
:meth:`~Calendar.getfirstweekday` respectively.
4250

4351
.. method:: getfirstweekday()
4452

45-
Return an :class:`int` for the current first weekday (0-6).
53+
Return an :class:`int` for the current first weekday (0--6).
54+
55+
Identical to reading the :attr:`~Calendar.firstweekday` property.
4656

4757
.. method:: setfirstweekday(firstweekday)
4858

49-
Set the first weekday to *firstweekday*, passed as an :class:`int` where Monday is 0 and Sunday is 6.
59+
Set the first weekday to *firstweekday*, passed as an :class:`int` (0--6)
60+
61+
Identical to setting the :attr:`~Calendar.firstweekday` property.
5062

5163
.. method:: iterweekdays()
5264

5365
Return an iterator for the week day numbers that will be used for one
5466
week. The first value from the iterator will be the same as the value of
55-
the :attr:`firstweekday` property.
67+
the :attr:`~Calendar.firstweekday` property.
5668

5769

5870
.. method:: itermonthdates(year, month)

Doc/library/ctypes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,8 @@ different ways, depending on the type and number of the parameters in the call:
18121812
the COM interface as first argument, in addition to those parameters that
18131813
are specified in the :attr:`!argtypes` tuple.
18141814

1815+
.. availability:: Windows
1816+
18151817

18161818
The optional *paramflags* parameter creates foreign function wrappers with much
18171819
more functionality than the features described above.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import io
2+
import unittest
3+
from http import client
4+
from test.test_httplib import FakeSocket
5+
from unittest import mock
6+
from xml.dom import getDOMImplementation, minidom, xmlbuilder
7+
8+
SMALL_SAMPLE = b"""<?xml version="1.0"?>
9+
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xdc="http://www.xml.com/books">
10+
<!-- A comment -->
11+
<title>Introduction to XSL</title>
12+
<hr/>
13+
<p><xdc:author xdc:attrib="prefixed attribute" attrib="other attrib">A. Namespace</xdc:author></p>
14+
</html>"""
15+
16+
17+
class XMLBuilderTest(unittest.TestCase):
18+
def test_entity_resolver(self):
19+
body = (
20+
b"HTTP/1.1 200 OK\r\nContent-Type: text/xml; charset=utf-8\r\n\r\n"
21+
+ SMALL_SAMPLE
22+
)
23+
24+
sock = FakeSocket(body)
25+
response = client.HTTPResponse(sock)
26+
response.begin()
27+
attrs = {"open.return_value": response}
28+
opener = mock.Mock(**attrs)
29+
30+
resolver = xmlbuilder.DOMEntityResolver()
31+
32+
with mock.patch("urllib.request.build_opener") as mock_build:
33+
mock_build.return_value = opener
34+
source = resolver.resolveEntity(None, "http://example.com/2000/svg")
35+
36+
self.assertIsInstance(source, xmlbuilder.DOMInputSource)
37+
self.assertIsNone(source.publicId)
38+
self.assertEqual(source.systemId, "http://example.com/2000/svg")
39+
self.assertEqual(source.baseURI, "http://example.com/2000/")
40+
self.assertEqual(source.encoding, "utf-8")
41+
self.assertIs(source.byteStream, response)
42+
43+
self.assertIsNone(source.characterStream)
44+
self.assertIsNone(source.stringData)
45+
46+
def test_builder(self):
47+
imp = getDOMImplementation()
48+
self.assertIsInstance(imp, xmlbuilder.DOMImplementationLS)
49+
50+
builder = imp.createDOMBuilder(imp.MODE_SYNCHRONOUS, None)
51+
self.assertIsInstance(builder, xmlbuilder.DOMBuilder)
52+
53+
def test_parse_uri(self):
54+
body = (
55+
b"HTTP/1.1 200 OK\r\nContent-Type: text/xml; charset=utf-8\r\n\r\n"
56+
+ SMALL_SAMPLE
57+
)
58+
59+
sock = FakeSocket(body)
60+
response = client.HTTPResponse(sock)
61+
response.begin()
62+
attrs = {"open.return_value": response}
63+
opener = mock.Mock(**attrs)
64+
65+
with mock.patch("urllib.request.build_opener") as mock_build:
66+
mock_build.return_value = opener
67+
68+
imp = getDOMImplementation()
69+
builder = imp.createDOMBuilder(imp.MODE_SYNCHRONOUS, None)
70+
document = builder.parseURI("http://example.com/2000/svg")
71+
72+
self.assertIsInstance(document, minidom.Document)
73+
self.assertEqual(len(document.childNodes), 1)
74+
75+
def test_parse_with_systemId(self):
76+
response = io.BytesIO(SMALL_SAMPLE)
77+
78+
with mock.patch("urllib.request.urlopen") as mock_open:
79+
mock_open.return_value = response
80+
81+
imp = getDOMImplementation()
82+
source = imp.createDOMInputSource()
83+
builder = imp.createDOMBuilder(imp.MODE_SYNCHRONOUS, None)
84+
source.systemId = "http://example.com/2000/svg"
85+
document = builder.parse(source)
86+
87+
self.assertIsInstance(document, minidom.Document)
88+
self.assertEqual(len(document.childNodes), 1)

Lib/xml/dom/xmlbuilder.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def parse(self, input):
189189
options.filter = self.filter
190190
options.errorHandler = self.errorHandler
191191
fp = input.byteStream
192-
if fp is None and options.systemId:
192+
if fp is None and input.systemId:
193193
import urllib.request
194194
fp = urllib.request.urlopen(input.systemId)
195195
return self._parse_bytestream(fp, options)
@@ -247,10 +247,12 @@ def _create_opener(self):
247247

248248
def _guess_media_encoding(self, source):
249249
info = source.byteStream.info()
250-
if "Content-Type" in info:
251-
for param in info.getplist():
252-
if param.startswith("charset="):
253-
return param.split("=", 1)[1].lower()
250+
# import email.message
251+
# assert isinstance(info, email.message.Message)
252+
charset = info.get_param('charset')
253+
if charset is not None:
254+
return charset.lower()
255+
return None
254256

255257

256258
class DOMInputSource(object):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Allow :meth:`!xml.dom.xmlbuilder.DOMParser.parse` to correctly handle
2+
:class:`!xml.dom.xmlbuilder.DOMInputSource` instances that only have a
3+
:attr:`!systemId` attribute set.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :meth:`!xml.dom.xmlbuilder.DOMEntityResolver.resolveEntity`, which was
2+
broken by the Python 3.0 transition.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Usage of the unified Apple System Log APIs was disabled when the minimum
2+
macOS version is earlier than 10.12.

Python/pylifecycle.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,25 @@
4646

4747
#if defined(__APPLE__)
4848
# include <AvailabilityMacros.h>
49+
# include <TargetConditionals.h>
4950
# include <mach-o/loader.h>
50-
# include <os/log.h>
51+
// The os_log unified logging APIs were introduced in macOS 10.12, iOS 10.0,
52+
// tvOS 10.0, and watchOS 3.0;
53+
# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
54+
# define HAS_APPLE_SYSTEM_LOG 1
55+
# elif defined(TARGET_OS_OSX) && TARGET_OS_OSX
56+
# if defined(MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
57+
# define HAS_APPLE_SYSTEM_LOG 1
58+
# else
59+
# define HAS_APPLE_SYSTEM_LOG 0
60+
# endif
61+
# else
62+
# define HAS_APPLE_SYSTEM_LOG 0
63+
# endif
64+
65+
# if HAS_APPLE_SYSTEM_LOG
66+
# include <os/log.h>
67+
# endif
5168
#endif
5269

5370
#ifdef HAVE_SIGNAL_H
@@ -77,7 +94,7 @@ static PyStatus init_sys_streams(PyThreadState *tstate);
7794
#ifdef __ANDROID__
7895
static PyStatus init_android_streams(PyThreadState *tstate);
7996
#endif
80-
#if defined(__APPLE__)
97+
#if defined(__APPLE__) && HAS_APPLE_SYSTEM_LOG
8198
static PyStatus init_apple_streams(PyThreadState *tstate);
8299
#endif
83100
static void wait_for_thread_shutdown(PyThreadState *tstate);
@@ -1262,7 +1279,7 @@ init_interp_main(PyThreadState *tstate)
12621279
return status;
12631280
}
12641281
#endif
1265-
#if defined(__APPLE__)
1282+
#if defined(__APPLE__) && HAS_APPLE_SYSTEM_LOG
12661283
if (config->use_system_logger) {
12671284
status = init_apple_streams(tstate);
12681285
if (_PyStatus_EXCEPTION(status)) {
@@ -2946,7 +2963,7 @@ init_android_streams(PyThreadState *tstate)
29462963

29472964
#endif // __ANDROID__
29482965

2949-
#if defined(__APPLE__)
2966+
#if defined(__APPLE__) && HAS_APPLE_SYSTEM_LOG
29502967

29512968
static PyObject *
29522969
apple_log_write_impl(PyObject *self, PyObject *args)
@@ -2957,14 +2974,9 @@ apple_log_write_impl(PyObject *self, PyObject *args)
29572974
return NULL;
29582975
}
29592976

2960-
// Call the underlying Apple logging API. The os_log unified logging APIs
2961-
// were introduced in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0;
2962-
// this call is a no-op on older versions.
2963-
#if TARGET_OS_IPHONE || (TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12)
29642977
// Pass the user-provided text through explicit %s formatting
29652978
// to avoid % literals being interpreted as a formatting directive.
29662979
os_log_with_type(OS_LOG_DEFAULT, logtype, "%s", text);
2967-
#endif
29682980
Py_RETURN_NONE;
29692981
}
29702982

@@ -2999,7 +3011,6 @@ init_apple_streams(PyThreadState *tstate)
29993011
if (result == NULL) {
30003012
goto error;
30013013
}
3002-
30033014
goto done;
30043015

30053016
error:
@@ -3013,7 +3024,7 @@ init_apple_streams(PyThreadState *tstate)
30133024
return status;
30143025
}
30153026

3016-
#endif // __APPLE__
3027+
#endif // __APPLE__ && HAS_APPLE_SYSTEM_LOG
30173028

30183029

30193030
static void

0 commit comments

Comments
 (0)