load all tests in package helper code used by a number of test modules base test class currently the default policy is compat32 by setting that as the default here we make minimal changes in the testemail tests compared to their pre3 3 state likewise the default message object is message backward compatibility to minimize testemail test changes our byte strings are really encoded strings improve diff output self assertequalself bytesreprfirst self bytesreprsecond def assertdefectsequalself actual expected self assertequallenactual lenexpected actual for i in rangelenactual self assertisinstanceactuali expectedi item formati def parameterizecls paramdicts testers collections defaultdictlist for name attr in cls dict items if name endswith params if not hasattrattr keys d for x in attr if not hasattrx iter x x n joinstrv for v in x replace dn x attr d paramdictsname 7 as attr if as in name testersname split as 0 as appendname testfuncs for name in paramdicts if name not in testers raise valueerrorno tester found for formatname for name in testers if name not in paramdicts raise valueerrorno params found for formatname for name attr in cls dict items for paramsname paramsdict in paramdicts items if name startswithparamsname testnameroot test namelenparamsname for paramname params in paramsdict items if hasattrparams keys test lambda self namename paramsparams getattrself nameparams else test lambda self namename paramsparams getattrself nameparams testname testnameroot paramname test name testname testfuncstestname test for key value in testfuncs items setattrcls key value return cls load all tests in package helper code used by a number of test modules base test class currently the default policy is compat32 by setting that as the default here we make minimal changes in the test_email tests compared to their pre 3 3 state likewise the default message object is message backward compatibility to minimize test_email test changes our byte strings are really encoded strings improve diff output a test method parameterization class decorator parameters are specified as the value of a class attribute that ends with the string _params call the portion before _params the prefix then a method to be parameterized must have the same prefix the string _as_ and an arbitrary suffix the value of the _params attribute may be either a dictionary or a list the values in the dictionary and the elements of the list may either be single values or a list if single values they are turned into single element tuples however derived the resulting sequence is passed via args to the parameterized test function in a _params dictionary the keys become part of the name of the generated tests in a _params list the values in the list are converted into a string by joining the string values of the elements of the tuple by _ and converting any blanks into _ s and this become part of the name the full name of a generated test is a test_ prefix the portion of the test function name after the _as_ separator plus an _ plus the name derived as explained above for example if we have count_params range 2 def count_as_foo_arg self foo self assertequal foo 1 myfunc foo we will get parameterized test methods named test_foo_arg_0 test_foo_arg_1 test_foo_arg_2 or we could have example_params foo bar 1 bing bang 2 def example_as_myfunc_input self name count self assertequal name str count myfunc name count and get test_myfunc_input_foo test_myfunc_input_bing 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
import os
import unittest
import collections
import email
from email.message import Message
from email._policybase import compat32
from test.support import load_package_tests
from test.test_email import __file__ as landmark


def load_tests(*args):
    return load_package_tests(os.path.dirname(__file__), *args)




def openfile(filename, *args, **kws):
    path = os.path.join(os.path.dirname(landmark), 'data', filename)
    return open(path, *args, **kws)



class TestEmailBase(unittest.TestCase):

    maxDiff = None
    
    
    
    policy = compat32
    
    message = Message

    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)
        self.addTypeEqualityFunc(bytes, self.assertBytesEqual)

    
    ndiffAssertEqual = unittest.TestCase.assertEqual

    def _msgobj(self, filename):
        with openfile(filename, encoding="utf-8") as fp:
            return email.message_from_file(fp, policy=self.policy)

    def _str_msg(self, string, message=None, policy=None):
        if policy is None:
            policy = self.policy
        if message is None:
            message = self.message
        return email.message_from_string(string, message, policy=policy)

    def _bytes_msg(self, bytestring, message=None, policy=None):
        if policy is None:
            policy = self.policy
        if message is None:
            message = self.message
        return email.message_from_bytes(bytestring, message, policy=policy)

    def _make_message(self):
        return self.message(policy=self.policy)

    def _bytes_repr(self, b):
        return [repr(x) for x in b.splitlines(keepends=True)]

    def assertBytesEqual(self, first, second, msg):
        
        self.assertEqual(self._bytes_repr(first), self._bytes_repr(second))

    def assertDefectsEqual(self, actual, expected):
        self.assertEqual(len(actual), len(expected), actual)
        for i in range(len(actual)):
            self.assertIsInstance(actual[i], expected[i],
                                    'item {}'.format(i))


def parameterize(cls):
    
    paramdicts = {}
    testers = collections.defaultdict(list)
    for name, attr in cls.__dict__.items():
        if name.endswith('_params'):
            if not hasattr(attr, 'keys'):
                d = {}
                for x in attr:
                    if not hasattr(x, '__iter__'):
                        x = (x,)
                    n = '_'.join(str(v) for v in x).replace(' ', '_')
                    d[n] = x
                attr = d
            paramdicts[name[:-7] + '_as_'] = attr
        if '_as_' in name:
            testers[name.split('_as_')[0] + '_as_'].append(name)
    testfuncs = {}
    for name in paramdicts:
        if name not in testers:
            raise ValueError("No tester found for {}".format(name))
    for name in testers:
        if name not in paramdicts:
            raise ValueError("No params found for {}".format(name))
    for name, attr in cls.__dict__.items():
        for paramsname, paramsdict in paramdicts.items():
            if name.startswith(paramsname):
                testnameroot = 'test_' + name[len(paramsname):]
                for paramname, params in paramsdict.items():
                    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
    for key, value in testfuncs.items():
        setattr(cls, key, value)
    return cls