blob: 1c6590149fa03e8578766e2838a9095a0d72af90 [file] [log] [blame]
R David Murray3edd22a2011-04-18 13:59:37 -04001import types
2import unittest
3import email.policy
4
5class PolicyAPITests(unittest.TestCase):
6
7 longMessage = True
8
9 # These default values are the ones set on email.policy.default.
10 # If any of these defaults change, the docs must be updated.
11 policy_defaults = {
12 'max_line_length': 78,
13 'linesep': '\n',
14 'must_be_7bit': False,
15 'raise_on_defect': False,
16 }
17
18 # For each policy under test, we give here the values of the attributes
19 # that are different from the defaults for that policy.
20 policies = {
21 email.policy.Policy(): {},
22 email.policy.default: {},
23 email.policy.SMTP: {'linesep': '\r\n'},
24 email.policy.HTTP: {'linesep': '\r\n', 'max_line_length': None},
25 email.policy.strict: {'raise_on_defect': True},
26 }
27
28 def test_defaults(self):
29 for policy, changed_defaults in self.policies.items():
30 expected = self.policy_defaults.copy()
31 expected.update(changed_defaults)
32 for attr, value in expected.items():
33 self.assertEqual(getattr(policy, attr), value,
34 ("change {} docs/docstrings if defaults have "
35 "changed").format(policy))
36
37 def test_all_attributes_covered(self):
38 for attr in dir(email.policy.default):
39 if (attr.startswith('_') or
40 isinstance(getattr(email.policy.Policy, attr),
41 types.FunctionType)):
42 continue
43 else:
44 self.assertIn(attr, self.policy_defaults,
45 "{} is not fully tested".format(attr))
46
47 def test_policy_is_immutable(self):
48 for policy in self.policies:
49 for attr in self.policy_defaults:
50 with self.assertRaisesRegex(AttributeError, attr+".*read-only"):
51 setattr(policy, attr, None)
52 with self.assertRaisesRegex(AttributeError, 'no attribute.*foo'):
53 policy.foo = None
54
55 def test_set_policy_attrs_when_calledl(self):
56 testattrdict = { attr: None for attr in self.policy_defaults }
57 for policyclass in self.policies:
58 policy = policyclass.clone(**testattrdict)
59 for attr in self.policy_defaults:
60 self.assertIsNone(getattr(policy, attr))
61
62 def test_reject_non_policy_keyword_when_called(self):
63 for policyclass in self.policies:
64 with self.assertRaises(TypeError):
65 policyclass(this_keyword_should_not_be_valid=None)
66 with self.assertRaises(TypeError):
67 policyclass(newtline=None)
68
69 def test_policy_addition(self):
70 expected = self.policy_defaults.copy()
71 p1 = email.policy.default.clone(max_line_length=100)
72 p2 = email.policy.default.clone(max_line_length=50)
73 added = p1 + p2
74 expected.update(max_line_length=50)
75 for attr, value in expected.items():
76 self.assertEqual(getattr(added, attr), value)
77 added = p2 + p1
78 expected.update(max_line_length=100)
79 for attr, value in expected.items():
80 self.assertEqual(getattr(added, attr), value)
81 added = added + email.policy.default
82 for attr, value in expected.items():
83 self.assertEqual(getattr(added, attr), value)
84
85 def test_register_defect(self):
86 class Dummy:
87 def __init__(self):
88 self.defects = []
89 obj = Dummy()
90 defect = object()
91 policy = email.policy.Policy()
92 policy.register_defect(obj, defect)
93 self.assertEqual(obj.defects, [defect])
94 defect2 = object()
95 policy.register_defect(obj, defect2)
96 self.assertEqual(obj.defects, [defect, defect2])
97
98 class MyObj:
99 def __init__(self):
100 self.defects = []
101
102 class MyDefect(Exception):
103 pass
104
105 def test_handle_defect_raises_on_strict(self):
106 foo = self.MyObj()
107 defect = self.MyDefect("the telly is broken")
108 with self.assertRaisesRegex(self.MyDefect, "the telly is broken"):
109 email.policy.strict.handle_defect(foo, defect)
110
111 def test_handle_defect_registers_defect(self):
112 foo = self.MyObj()
113 defect1 = self.MyDefect("one")
114 email.policy.default.handle_defect(foo, defect1)
115 self.assertEqual(foo.defects, [defect1])
116 defect2 = self.MyDefect("two")
117 email.policy.default.handle_defect(foo, defect2)
118 self.assertEqual(foo.defects, [defect1, defect2])
119
120 class MyPolicy(email.policy.Policy):
R David Murray7104c722012-03-16 21:39:57 -0400121 defects = None
122 def __init__(self, *args, **kw):
123 super().__init__(*args, defects=[], **kw)
R David Murray3edd22a2011-04-18 13:59:37 -0400124 def register_defect(self, obj, defect):
125 self.defects.append(defect)
126
127 def test_overridden_register_defect_still_raises(self):
128 foo = self.MyObj()
129 defect = self.MyDefect("the telly is broken")
130 with self.assertRaisesRegex(self.MyDefect, "the telly is broken"):
131 self.MyPolicy(raise_on_defect=True).handle_defect(foo, defect)
132
133 def test_overriden_register_defect_works(self):
134 foo = self.MyObj()
135 defect1 = self.MyDefect("one")
136 my_policy = self.MyPolicy()
137 my_policy.handle_defect(foo, defect1)
138 self.assertEqual(my_policy.defects, [defect1])
139 self.assertEqual(foo.defects, [])
140 defect2 = self.MyDefect("two")
141 my_policy.handle_defect(foo, defect2)
142 self.assertEqual(my_policy.defects, [defect1, defect2])
143 self.assertEqual(foo.defects, [])
144
145 # XXX: Need subclassing tests.
146 # For adding subclassed objects, make sure the usual rules apply (subclass
147 # wins), but that the order still works (right overrides left).
148
149if __name__ == '__main__':
150 unittest.main()