this repo has no description
1#!/usr/bin/env python3
2# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
3import unittest
4from _string import formatter_field_name_split, formatter_parser
5
6
7class FormatterFieldNameSplitTests(unittest.TestCase):
8 def test_multiple_subscripts_returns_multiple_subscripts(self):
9 res, it = formatter_field_name_split("0[2][3]")
10 self.assertEqual(res, 0)
11 self.assertEqual(tuple(it), ((False, 2), (False, 3)))
12
13 def test_non_dot_or_bracket_between_brackets_raises_value_error(self):
14 res, it = formatter_field_name_split("0[4]a[20]")
15 self.assertEqual(res, 0)
16 self.assertEqual(it.__next__(), (False, 4))
17 with self.assertRaises(ValueError) as context:
18 it.__next__()
19 self.assertEqual(
20 str(context.exception),
21 "Only '.' or '[' may follow ']' in format field specifier",
22 )
23
24 def test_string_as_subscript_uses_string_as_subscript(self):
25 res, it = formatter_field_name_split("0[a]")
26 self.assertEqual(res, 0)
27 self.assertEqual(tuple(it), ((False, "a"),))
28
29 def test_left_bracket_as_subscript_uses_bracket_as_subscript(self):
30 res, it = formatter_field_name_split("0[[]")
31 self.assertEqual(res, 0)
32 self.assertEqual(tuple(it), ((False, "["),))
33
34 def test_incomplete_subscript_raises_value_error(self):
35 res, it = formatter_field_name_split("0[2")
36 self.assertEqual(res, 0)
37 with self.assertRaises(ValueError) as context:
38 it.__next__()
39 self.assertEqual(str(context.exception), "Missing ']' in format string")
40
41 res, it = formatter_field_name_split("[2")
42 # TODO(T64268423): Once CPython has a fix, test for 0 instead of "" or
43 # 0.
44 self.assertTrue(res == "" or res == 0)
45 with self.assertRaises(ValueError):
46 it.__next__()
47
48 res, it = formatter_field_name_split("][")
49 self.assertEqual(res, "]")
50 with self.assertRaises(ValueError):
51 it.__next__()
52
53 def test_missing_left_bracket_includes_right_bracket_in_field_name(self):
54 res, it = formatter_field_name_split("2]")
55 self.assertEqual(res, "2]")
56 self.assertEqual(tuple(it), ())
57
58 res, it = formatter_field_name_split("]2")
59 self.assertEqual(res, "]2")
60 self.assertEqual(tuple(it), ())
61
62 def test_missing_subscript_raises_value_error(self):
63 res, it = formatter_field_name_split("[]")
64 # TODO(T64268423): Once CPython has a fix, test for 0 instead of "" or
65 # 0.
66 self.assertTrue(res == "" or res == 0)
67 with self.assertRaises(ValueError):
68 it.__next__()
69
70 def test_number_indexed_with_subscript(self):
71 res, it = formatter_field_name_split("0[2]")
72 self.assertEqual(res, 0)
73 self.assertEqual(tuple(it), ((False, 2),))
74
75 def test_name_indexed_with_subscript(self):
76 res, it = formatter_field_name_split("hello[2]")
77 self.assertEqual(res, "hello")
78 self.assertEqual(tuple(it), ((False, 2),))
79
80 def test_no_name_indexed_with_subscript(self):
81 res, it = formatter_field_name_split("[2]")
82 # TODO(T64268423): Once CPython has a fix, test for 0 instead of "" or
83 # 0.
84 self.assertTrue(res == "" or res == 0)
85 self.assertEqual(tuple(it), ((False, 2),))
86
87 def test_select_attr_from_name(self):
88 res, it = formatter_field_name_split("hello.attr")
89 self.assertEqual(res, "hello")
90 self.assertEqual(tuple(it), ((True, "attr"),))
91
92 def test_select_multiple_attr_from_name(self):
93 res, it = formatter_field_name_split("hello.first.second.third")
94 self.assertEqual(res, "hello")
95 self.assertEqual(
96 tuple(it), ((True, "first"), (True, "second"), (True, "third"))
97 )
98
99 def test_select_attr_from_number(self):
100 res, it = formatter_field_name_split("0.attr")
101 self.assertEqual(res, 0)
102 self.assertEqual(tuple(it), ((True, "attr"),))
103
104 def test_select_attr_from_name_and_index_with_subscript(self):
105 res1, it1 = formatter_field_name_split("hello.attr[2]")
106 res2, it2 = formatter_field_name_split("hello[2].attr")
107 self.assertEqual(res1, res2, "hello")
108 self.assertEqual(tuple(it1), ((True, "attr"), (False, 2)))
109 self.assertEqual(tuple(it2), ((False, 2), (True, "attr")))
110
111 def test_select_attr_from_number_and_index_with_subscript(self):
112 res1, it1 = formatter_field_name_split("0.attr[2]")
113 res2, it2 = formatter_field_name_split("0[2].attr")
114 self.assertEqual(res1, res2, 0)
115 self.assertEqual(tuple(it1), ((True, "attr"), (False, 2)))
116 self.assertEqual(tuple(it2), ((False, 2), (True, "attr")))
117
118 def test_missing_attr_raises_value_error(self):
119 res, it = formatter_field_name_split("hello.")
120 with self.assertRaises(ValueError) as context:
121 it.__next__()
122 self.assertEqual(str(context.exception), "Empty attribute in format string")
123
124 def test_simple_string_returns_string_iter_tuple(self):
125 res, it = formatter_field_name_split("foo")
126 self.assertEqual(res, "foo")
127 self.assertEqual(tuple(it), ())
128
129 def test_empty_string_returns_string_iter_tuple(self):
130 res, it = formatter_field_name_split("")
131 self.assertEqual(res, "")
132 self.assertEqual(tuple(it), ())
133
134 def test_simple_string_returns_int_iter_tuple(self):
135 res, it = formatter_field_name_split("42")
136 self.assertEqual(res, 42)
137 self.assertEqual(tuple(it), ())
138
139 def test_non_string_raises_type_error(self):
140 with self.assertRaises(TypeError):
141 formatter_field_name_split(42)
142
143
144class FormatterParserTests(unittest.TestCase):
145 def test_empty_string_returns_empty_tuple(self):
146 self.assertEqual(tuple(formatter_parser("")), ())
147
148 def test_simple_string_returns_tuple(self):
149 self.assertEqual(tuple(formatter_parser(" ")), ((" ", None, None, None),))
150 self.assertEqual(
151 tuple(formatter_parser("hello")), (("hello", None, None, None),)
152 )
153 self.assertEqual(
154 tuple(formatter_parser("~!@#$%^&*()<>.")),
155 (("~!@#$%^&*()<>.", None, None, None),),
156 )
157
158 def test_double_curlies(self):
159 self.assertEqual(tuple(formatter_parser("{{")), (("{", None, None, None),))
160 self.assertEqual(tuple(formatter_parser("}}")), (("}", None, None, None),))
161 self.assertEqual(
162 tuple(formatter_parser("{{ab")),
163 (("{", None, None, None), ("ab", None, None, None)),
164 )
165 self.assertEqual(
166 tuple(formatter_parser("}}ab")),
167 (("}", None, None, None), ("ab", None, None, None)),
168 )
169 self.assertEqual(tuple(formatter_parser("ab{{")), (("ab{", None, None, None),))
170 self.assertEqual(tuple(formatter_parser("ab}}")), (("ab}", None, None, None),))
171 self.assertEqual(
172 tuple(formatter_parser("ab{{cd")),
173 (("ab{", None, None, None), ("cd", None, None, None)),
174 )
175 self.assertEqual(
176 tuple(formatter_parser("ab}}cd")),
177 (("ab}", None, None, None), ("cd", None, None, None)),
178 )
179 self.assertEqual(
180 tuple(formatter_parser("he{{}}llo")),
181 (
182 ("he{", None, None, None),
183 ("}", None, None, None),
184 ("llo", None, None, None),
185 ),
186 )
187
188 def test_format_with_identifier_returns_tuple(self):
189 self.assertEqual(tuple(formatter_parser("{}")), (("", "", "", None),))
190 self.assertEqual(tuple(formatter_parser("{foo}")), (("", "foo", "", None),))
191 self.assertEqual(
192 tuple(formatter_parser("foo{bar}")), (("foo", "bar", "", None),)
193 )
194
195 def test_format_with_conversion_specifier_returns_tuple(self):
196 self.assertEqual(tuple(formatter_parser("{!x}")), (("", "", "", "x"),))
197 self.assertEqual(tuple(formatter_parser("{foo!x}")), (("", "foo", "", "x"),))
198 self.assertEqual(tuple(formatter_parser("{!x}")), (("", "", "", "x"),))
199 self.assertEqual(
200 tuple(formatter_parser("foo{bar!b}")), (("foo", "bar", "", "b"),)
201 )
202 self.assertEqual(tuple(formatter_parser("{!}}")), (("", "", "", "}"),))
203 self.assertEqual(tuple(formatter_parser("{!{}")), (("", "", "", "{"),))
204
205 def test_format_with_spec_returns_tuple(self):
206 self.assertEqual(tuple(formatter_parser("{:foo}")), (("", "", "foo", None),))
207 self.assertEqual(
208 tuple(formatter_parser("{:foo!x}")), (("", "", "foo!x", None),)
209 )
210 self.assertEqual(
211 tuple(formatter_parser("{foo:bar}")), (("", "foo", "bar", None),)
212 )
213 self.assertEqual(
214 tuple(formatter_parser("foo{bar:baz}")), (("foo", "bar", "baz", None),)
215 )
216
217 def test_format_with_curly_in_spec_returns_tuple(self):
218 self.assertEqual(
219 tuple(formatter_parser("{:{foo}}")), (("", "", "{foo}", None),)
220 )
221 self.assertEqual(tuple(formatter_parser("{:{}}")), (("", "", "{}", None),))
222 self.assertEqual(
223 tuple(formatter_parser("{:{foo{bar}baz}}")),
224 (("", "", "{foo{bar}baz}", None),),
225 )
226 self.assertEqual(
227 tuple(formatter_parser("{:foo{bar}baz}")), (("", "", "foo{bar}baz", None),)
228 )
229
230 def test_format_with_square_in_spec_returns_tuple(self):
231 self.assertEqual(
232 tuple(formatter_parser("ab{0[0]}cd")),
233 (("ab", "0[0]", "", None), ("cd", None, None, None)),
234 )
235 self.assertEqual(
236 tuple(formatter_parser("ab{hello[0]}cd")),
237 (("ab", "hello[0]", "", None), ("cd", None, None, None)),
238 )
239 self.assertEqual(
240 tuple(formatter_parser("ab{[0]}cd")),
241 (("ab", "[0]", "", None), ("cd", None, None, None)),
242 )
243 self.assertEqual(
244 tuple(formatter_parser("ab{[0][1][2]}cd")),
245 (("ab", "[0][1][2]", "", None), ("cd", None, None, None)),
246 )
247
248 def test_format_with_all_returns_tuple(self):
249 self.assertEqual(
250 tuple(formatter_parser("foo{bar!r:baz}bam {15:2} {xxx!a}")),
251 (
252 ("foo", "bar", "baz", "r"),
253 ("bam ", "15", "2", None),
254 (" ", "xxx", "", "a"),
255 ),
256 )
257
258 def test_unbalanced_rcurly_raises_value_error(self):
259 with self.assertRaises(ValueError) as context:
260 tuple(formatter_parser("}"))
261 self.assertEqual(
262 str(context.exception), "Single '}' encountered in format string"
263 )
264
265 with self.assertRaises(ValueError) as context:
266 tuple(formatter_parser("a} }"))
267 self.assertEqual(
268 str(context.exception), "Single '}' encountered in format string"
269 )
270
271 def test_unbalanced_lcurly_raises_value_error(self):
272 with self.assertRaises(ValueError) as context:
273 tuple(formatter_parser("{"))
274 self.assertEqual(
275 str(context.exception), "Single '{' encountered in format string"
276 )
277
278 with self.assertRaises(ValueError) as context:
279 tuple(formatter_parser("a{bcd"))
280 self.assertEqual(str(context.exception), "expected '}' before end of string")
281
282 with self.assertRaises(ValueError) as context:
283 tuple(formatter_parser("a{bcd!"))
284 self.assertEqual(
285 str(context.exception),
286 "end of string while looking for conversion specifier",
287 )
288
289 with self.assertRaises(ValueError) as context:
290 tuple(formatter_parser("a{bcd!x"))
291 self.assertEqual(str(context.exception), "unmatched '{' in format spec")
292
293 with self.assertRaises(ValueError) as context:
294 tuple(formatter_parser("a{bcd:"))
295 self.assertEqual(str(context.exception), "unmatched '{' in format spec")
296
297 def test_missing_conversion_specifier_raises_value_error(self):
298 with self.assertRaises(ValueError) as context:
299 tuple(formatter_parser("a{bcd!}"))
300 self.assertEqual(str(context.exception), "unmatched '{' in format spec")
301
302 def test_chars_after_conversion_specifier_raises_value_error(self):
303 with self.assertRaises(ValueError) as context:
304 tuple(formatter_parser("a{bcd!xy}"))
305 self.assertEqual(
306 str(context.exception), "expected ':' after conversion specifier"
307 )
308
309 def test_lcurly_in_field_name_raises_value_error(self):
310 with self.assertRaises(ValueError) as context:
311 tuple(formatter_parser("{foo{bar}baz}"))
312 self.assertEqual(str(context.exception), "unexpected '{' in field name")
313
314 def test_non_string_raise_type_error(self):
315 with self.assertRaises(TypeError):
316 tuple(formatter_parser(42))
317
318
319if __name__ == "__main__":
320 unittest.main()