this repo has no description
at trunk 320 lines 13 kB view raw
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()