[Python-checkins] cpython (merge 3.5 -> default): Merge with 3.5

steve.dower python-checkins at python.org
Fri Sep 9 15:10:07 EDT 2016


https://hg.python.org/cpython/rev/da4c4979fc19
changeset: 103440:da4c4979fc19
parent: 103437:70758c12e888
parent: 103439:fa89e107f43d
user: Steve Dower <steve.dower at microsoft.com>
date: Fri Sep 09 12:09:07 2016 -0700
summary:
 Merge with 3.5
files:
 Lib/email/contentmanager.py | 9 +++--
 Lib/test/test_email/__init__.py | 12 ++++++-
 Lib/test/test_email/test_inversion.py | 23 ++++++++++++++-
 Misc/NEWS | 5 +++
 PC/_msi.c | 20 +++++++++++-
 5 files changed, 59 insertions(+), 10 deletions(-)
diff --git a/Lib/email/contentmanager.py b/Lib/email/contentmanager.py
--- a/Lib/email/contentmanager.py
+++ b/Lib/email/contentmanager.py
@@ -126,12 +126,13 @@
 msg.set_param(key, value)
 
 
-# XXX: This is a cleaned-up version of base64mime.body_encode. It would
-# be nice to drop both this and quoprimime.body_encode in favor of
-# enhanced binascii routines that accepted a max_line_length parameter.
+# XXX: This is a cleaned-up version of base64mime.body_encode (including a bug
+# fix in the calculation of unencoded_bytes_per_line). It would be nice to
+# drop both this and quoprimime.body_encode in favor of enhanced binascii
+# routines that accepted a max_line_length parameter.
 def _encode_base64(data, max_line_length):
 encoded_lines = []
- unencoded_bytes_per_line = max_line_length * 3 // 4
+ unencoded_bytes_per_line = max_line_length // 4 * 3
 for i in range(0, len(data), unencoded_bytes_per_line):
 thisline = data[i:i+unencoded_bytes_per_line]
 encoded_lines.append(binascii.b2a_base64(thisline).decode('ascii'))
diff --git a/Lib/test/test_email/__init__.py b/Lib/test/test_email/__init__.py
--- a/Lib/test/test_email/__init__.py
+++ b/Lib/test/test_email/__init__.py
@@ -120,6 +120,10 @@
 Note: if and only if the generated test name is a valid identifier can it
 be used to select the test individually from the unittest command line.
 
+ The values in the params dict can be a single value, a tuple, or a
+ dict. If a single value of a tuple, it is passed to the test function
+ as positional arguments. If a dict, it is a passed via **kw.
+
 """
 paramdicts = {}
 testers = collections.defaultdict(list)
@@ -148,8 +152,12 @@
 if name.startswith(paramsname):
 testnameroot = 'test_' + name[len(paramsname):]
 for paramname, params in paramsdict.items():
- test = (lambda self, name=name, params=params:
- getattr(self, name)(*params))
+ if hasattr(params, 'keys'):
+ test = (lambda self, name=name, params=params:
+ getattr(self, name)(**params))
+ else:
+ test = (lambda self, name=name, params=params:
+ getattr(self, name)(*params))
 testname = testnameroot + '_' + paramname
 test.__name__ = testname
 testfuncs[testname] = test
diff --git a/Lib/test/test_email/test_inversion.py b/Lib/test/test_email/test_inversion.py
--- a/Lib/test/test_email/test_inversion.py
+++ b/Lib/test/test_email/test_inversion.py
@@ -7,6 +7,7 @@
 import io
 import unittest
 from email import policy, message_from_bytes
+from email.message import EmailMessage
 from email.generator import BytesGenerator
 from test.test_email import TestEmailBase, parameterize
 
@@ -23,7 +24,10 @@
 
 
 @parameterize
-class TestInversion(TestEmailBase, unittest.TestCase):
+class TestInversion(TestEmailBase):
+
+ policy = policy.default
+ message = EmailMessage
 
 def msg_as_input(self, msg):
 m = message_from_bytes(msg, policy=policy.SMTP)
@@ -44,6 +48,23 @@
 
 }
 
+ payload_params = {
+ 'plain_text': dict(payload='This is a test\n'*20),
+ 'base64_text': dict(payload=(('xy a'*40+'\n')*5), cte='base64'),
+ 'qp_text': dict(payload=(('xy a'*40+'\n')*5), cte='quoted-printable'),
+ }
+
+ def payload_as_body(self, payload, **kw):
+ msg = self._make_message()
+ msg['From'] = 'foo'
+ msg['To'] = 'bar'
+ msg['Subject'] = 'payload round trip test'
+ msg.set_content(payload, **kw)
+ b = bytes(msg)
+ msg2 = message_from_bytes(b, policy=self.policy)
+ self.assertEqual(bytes(msg2), b)
+ self.assertEqual(msg2.get_content(), payload)
+
 
 if __name__ == '__main__':
 unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -113,6 +113,11 @@
 Library
 -------
 
+- Issue #24594: Validates persist parameter when opening MSI database
+
+- Issue #28047: Fixed calculation of line length used for the base64 CTE
+ in the new email policies.
+
 - Issue #27576: Fix call order in OrderedDict.__init__().
 
 - email.generator.DecodedGenerator now supports the policy keyword.
diff --git a/PC/_msi.c b/PC/_msi.c
--- a/PC/_msi.c
+++ b/PC/_msi.c
@@ -955,6 +955,17 @@
 0, /*tp_is_gc*/
 };
 
+#define Py_NOT_PERSIST(x, flag) \
+ (x != (int)(flag) && \
+ x != ((int)(flag) | MSIDBOPEN_PATCHFILE))
+
+#define Py_INVALID_PERSIST(x) \
+ (Py_NOT_PERSIST(x, MSIDBOPEN_READONLY) && \
+ Py_NOT_PERSIST(x, MSIDBOPEN_TRANSACT) && \
+ Py_NOT_PERSIST(x, MSIDBOPEN_DIRECT) && \
+ Py_NOT_PERSIST(x, MSIDBOPEN_CREATE) && \
+ Py_NOT_PERSIST(x, MSIDBOPEN_CREATEDIRECT))
+
 static PyObject* msiopendb(PyObject *obj, PyObject *args)
 {
 int status;
@@ -962,11 +973,14 @@
 int persist;
 MSIHANDLE h;
 msiobj *result;
-
 if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist))
 return NULL;
-
- status = MsiOpenDatabase(path, (LPCSTR)persist, &h);
+ /* We need to validate that persist is a valid MSIDBOPEN_* value. Otherwise,
+ MsiOpenDatabase may treat the value as a pointer, leading to unexpected
+ behavior. */
+ if (Py_INVALID_PERSIST(persist))
+ return msierror(ERROR_INVALID_PARAMETER);
+ status = MsiOpenDatabase(path, (LPCSTR)persist, &h);
 if (status != ERROR_SUCCESS)
 return msierror(status);
 
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /