Merge with 3.5
This commit is contained in:
commit
2a2becc1d1
|
@ -126,12 +126,13 @@ def _finalize_set(msg, disposition, filename, cid, params):
|
|||
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'))
|
||||
|
|
|
@ -120,6 +120,10 @@ def parameterize(cls):
|
|||
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 @@ def parameterize(cls):
|
|||
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
|
||||
|
|
|
@ -7,6 +7,7 @@ producing RFC valid messages.
|
|||
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 @@ def dedent(bstr):
|
|||
|
||||
|
||||
@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 @@ class TestInversion(TestEmailBase, unittest.TestCase):
|
|||
|
||||
}
|
||||
|
||||
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()
|
||||
|
|
|
@ -113,6 +113,11 @@ Core and Builtins
|
|||
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.
|
||||
|
|
20
PC/_msi.c
20
PC/_msi.c
|
@ -955,6 +955,17 @@ static PyTypeObject msidb_Type = {
|
|||
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 @@ static PyObject* msiopendb(PyObject *obj, PyObject *args)
|
|||
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue