| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e4dc324 commit 8c66326
22 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,9 @@ | |||
| 1 | + PyObject * | ||
| 2 | + unicode_unicode__format__(PyObject *self, PyObject *args); | ||
| 3 | + | ||
| 4 | + PyObject * | ||
| 5 | + unicode_long__format__(PyObject *self, PyObject *args); | ||
| 6 | + | ||
| 7 | + PyObject * | ||
| 8 | + unicode_float__format__(PyObject *self, PyObject *args); | ||
| 9 | + | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1437,6 +1437,11 @@ PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strchr( | |||
| 1437 | 1437 | const Py_UNICODE *s, Py_UNICODE c | |
| 1438 | 1438 | ); | |
| 1439 | 1439 | ||
| 1440 | + PyObject * | ||
| 1441 | + _unicodeformatter_iterator(PyObject *str); | ||
| 1442 | + PyObject * | ||
| 1443 | + _unicodeformatter_lookup(PyObject *field_name, PyObject *args, | ||
| 1444 | + PyObject *kwargs); | ||
| 1440 | 1445 | ||
| 1441 | 1446 | #ifdef __cplusplus | |
| 1442 | 1447 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -189,3 +189,42 @@ def convert(mo): | |||
| 189 | 189 | raise ValueError('Unrecognized named group in pattern', | |
| 190 | 190 | self.pattern) | |
| 191 | 191 | return self.pattern.sub(convert, self.template) | |
| 192 | + | ||
| 193 | + | ||
| 194 | + | ||
| 195 | + ######################################################################## | ||
| 196 | + # the Formatter class | ||
| 197 | + # see PEP 3101 for details and purpose of this class | ||
| 198 | + | ||
| 199 | + # The hard parts are reused from the C implementation. They're | ||
| 200 | + # exposed here via the sys module. sys was chosen because it's always | ||
| 201 | + # available and doesn't have to be dynamically loaded. | ||
| 202 | + | ||
| 203 | + # The parser is implemented in sys._formatter_parser. | ||
| 204 | + # The "object lookup" is implemented in sys._formatter_lookup | ||
| 205 | + | ||
| 206 | + from sys import _formatter_parser, _formatter_lookup | ||
| 207 | + | ||
| 208 | + class Formatter: | ||
| 209 | + def format(self, format_string, *args, **kwargs): | ||
| 210 | + return self.vformat(format_string, args, kwargs) | ||
| 211 | + | ||
| 212 | + def vformat(self, format_string, args, kwargs): | ||
| 213 | + result = [] | ||
| 214 | + for (is_markup, literal, field_name, format_spec, conversion) in \ | ||
| 215 | + _formatter_parser(format_string): | ||
| 216 | + if is_markup: | ||
| 217 | + # find the object | ||
| 218 | + index, name, obj = _formatter_lookup(field_name, args, kwargs) | ||
| 219 | + else: | ||
| 220 | + result.append(literal) | ||
| 221 | + return ''.join(result) | ||
| 222 | + | ||
| 223 | + def get_value(self, key, args, kwargs): | ||
| 224 | + pass | ||
| 225 | + | ||
| 226 | + def check_unused_args(self, used_args, args, kwargs): | ||
| 227 | + pass | ||
| 228 | + | ||
| 229 | + def format_field(self, value, format_spec): | ||
| 230 | + pass | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -517,6 +517,32 @@ def __float__(self): | |||
| 517 | 517 | self.assertAlmostEqual(float(Foo3(21)), 42.) | |
| 518 | 518 | self.assertRaises(TypeError, float, Foo4(42)) | |
| 519 | 519 | ||
| 520 | + def test_format(self): | ||
| 521 | + class A: | ||
| 522 | + def __init__(self, x): | ||
| 523 | + self.x = x | ||
| 524 | + def __format__(self, format_spec): | ||
| 525 | + return str(self.x) + format_spec | ||
| 526 | + | ||
| 527 | + # class that returns a bad type from __format__ | ||
| 528 | + class H: | ||
| 529 | + def __format__(self, format_spec): | ||
| 530 | + return 1.0 | ||
| 531 | + | ||
| 532 | + self.assertEqual(format(3, ''), '3') | ||
| 533 | + self.assertEqual(format(A(3), 'spec'), '3spec') | ||
| 534 | + | ||
| 535 | + # for builtin types, format(x, "") == str(x) | ||
| 536 | + self.assertEqual(format(17**13, ""), str(17**13)) | ||
| 537 | + self.assertEqual(format(1.0, ""), str(1.0)) | ||
| 538 | + self.assertEqual(format(3.1415e104, ""), str(3.1415e104)) | ||
| 539 | + self.assertEqual(format(-3.1415e104, ""), str(-3.1415e104)) | ||
| 540 | + self.assertEqual(format(3.1415e-104, ""), str(3.1415e-104)) | ||
| 541 | + self.assertEqual(format(-3.1415e-104, ""), str(-3.1415e-104)) | ||
| 542 | + self.assertEqual(format(object, ""), str(object)) | ||
| 543 | + | ||
| 544 | + #self.assertRaises(TypeError, format, H(), "") | ||
| 545 | + | ||
| 520 | 546 | def test_getattr(self): | |
| 521 | 547 | import sys | |
| 522 | 548 | self.assert_(getattr(sys, 'stdout') is sys.stdout) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -173,6 +173,7 @@ def merge(self, other): | |||
| 173 | 173 | '__delslice__', | |
| 174 | 174 | '__doc__', | |
| 175 | 175 | '__eq__', | |
| 176 | + '__format__', | ||
| 176 | 177 | '__ge__', | |
| 177 | 178 | '__getattribute__', | |
| 178 | 179 | '__getitem__', | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -114,12 +114,44 @@ def neg_neg(): | |||
| 114 | 114 | self.assertEquals(pos_pos(), neg_pos()) | |
| 115 | 115 | self.assertEquals(pos_neg(), neg_neg()) | |
| 116 | 116 | ||
| 117 | + class FormatTestCase(unittest.TestCase): | ||
| 118 | + def testFormat(self): | ||
| 119 | + # these should be rewritten to use both format(x, spec) and | ||
| 120 | + # x.__format__(spec) | ||
| 121 | + | ||
| 122 | + self.assertEqual(format(0.0, 'f'), '0.000000') | ||
| 123 | + | ||
| 124 | + # the default is 'g', except for empty format spec | ||
| 125 | + self.assertEqual(format(0.0, ''), '0.0') | ||
| 126 | + self.assertEqual(format(0.01, ''), '0.01') | ||
| 127 | + self.assertEqual(format(0.01, 'g'), '0.01') | ||
| 128 | + | ||
| 129 | + self.assertEqual(format(0, 'f'), '0.000000') | ||
| 130 | + | ||
| 131 | + self.assertEqual(format(1.0, 'f'), '1.000000') | ||
| 132 | + self.assertEqual(format(1, 'f'), '1.000000') | ||
| 133 | + | ||
| 134 | + self.assertEqual(format(-1.0, 'f'), '-1.000000') | ||
| 135 | + self.assertEqual(format(-1, 'f'), '-1.000000') | ||
| 136 | + | ||
| 137 | + self.assertEqual(format( 1.0, ' f'), ' 1.000000') | ||
| 138 | + self.assertEqual(format(-1.0, ' f'), '-1.000000') | ||
| 139 | + self.assertEqual(format( 1.0, '+f'), '+1.000000') | ||
| 140 | + self.assertEqual(format(-1.0, '+f'), '-1.000000') | ||
| 141 | + | ||
| 142 | + # % formatting | ||
| 143 | + self.assertEqual(format(-1.0, '%'), '-100.000000%') | ||
| 144 | + | ||
| 145 | + # conversion to string should fail | ||
| 146 | + self.assertRaises(ValueError, format, 3.0, "s") | ||
| 147 | + | ||
| 117 | 148 | ||
| 118 | 149 | def test_main(): | |
| 119 | 150 | test_support.run_unittest( | |
| 120 | 151 | FormatFunctionsTestCase, | |
| 121 | 152 | UnknownFormatTestCase, | |
| 122 | - IEEEFormatTestCase) | ||
| 153 | + IEEEFormatTestCase, | ||
| 154 | + FormatTestCase) | ||
| 123 | 155 | ||
| 124 | 156 | if __name__ == '__main__': | |
| 125 | 157 | test_main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -493,6 +493,50 @@ def __cmp__(self, other): | |||
| 493 | 493 | eq(x > y, Rcmp > 0, Frm("%r > %r %d", x, y, Rcmp)) | |
| 494 | 494 | eq(x >= y, Rcmp >= 0, Frm("%r >= %r %d", x, y, Rcmp)) | |
| 495 | 495 | ||
| 496 | + def test_format(self): | ||
| 497 | + self.assertEqual(format(123456789, 'd'), '123456789') | ||
| 498 | + self.assertEqual(format(123456789, 'd'), '123456789') | ||
| 499 | + | ||
| 500 | + # hex | ||
| 501 | + self.assertEqual(format(3, "x"), "3") | ||
| 502 | + self.assertEqual(format(3, "X"), "3") | ||
| 503 | + self.assertEqual(format(1234, "x"), "4d2") | ||
| 504 | + self.assertEqual(format(-1234, "x"), "-4d2") | ||
| 505 | + self.assertEqual(format(1234, "8x"), " 4d2") | ||
| 506 | + # XXX fix self.assertEqual(format(-1234, "8x"), " -4d2") | ||
| 507 | + self.assertEqual(format(1234, "x"), "4d2") | ||
| 508 | + self.assertEqual(format(-1234, "x"), "-4d2") | ||
| 509 | + self.assertEqual(format(-3, "x"), "-3") | ||
| 510 | + self.assertEqual(format(-3, "X"), "-3") | ||
| 511 | + self.assertEqual(format(int('be', 16), "x"), "be") | ||
| 512 | + self.assertEqual(format(int('be', 16), "X"), "BE") | ||
| 513 | + self.assertEqual(format(-int('be', 16), "x"), "-be") | ||
| 514 | + self.assertEqual(format(-int('be', 16), "X"), "-BE") | ||
| 515 | + | ||
| 516 | + # octal | ||
| 517 | + self.assertEqual(format(3, "b"), "11") | ||
| 518 | + self.assertEqual(format(-3, "b"), "-11") | ||
| 519 | + self.assertEqual(format(1234, "b"), "10011010010") | ||
| 520 | + self.assertEqual(format(-1234, "b"), "-10011010010") | ||
| 521 | + self.assertEqual(format(1234, "-b"), "10011010010") | ||
| 522 | + self.assertEqual(format(-1234, "-b"), "-10011010010") | ||
| 523 | + self.assertEqual(format(1234, " b"), " 10011010010") | ||
| 524 | + self.assertEqual(format(-1234, " b"), "-10011010010") | ||
| 525 | + self.assertEqual(format(1234, "+b"), "+10011010010") | ||
| 526 | + self.assertEqual(format(-1234, "+b"), "-10011010010") | ||
| 527 | + | ||
| 528 | + # conversion to float | ||
| 529 | + self.assertEqual(format(0, 'f'), '0.000000') | ||
| 530 | + | ||
| 531 | + # make sure these are errors | ||
| 532 | + self.assertRaises(ValueError, format, 3, "1.3") # precision disallowed | ||
| 533 | + return | ||
| 534 | + self.assertRaises(ValueError, format, 3, "+c") # sign not allowed | ||
| 535 | + # with 'c' | ||
| 536 | + self.assertRaises(ValueError, format, 3, "R") # bogus format type | ||
| 537 | + # conversion to string should fail | ||
| 538 | + self.assertRaises(ValueError, format, 3, "s") | ||
| 539 | + | ||
| 496 | 540 | def test_main(): | |
| 497 | 541 | test_support.run_unittest(LongTest) | |
| 498 | 542 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,6 +15,14 @@ def test_attrs(self): | |||
| 15 | 15 | string.punctuation | |
| 16 | 16 | string.printable | |
| 17 | 17 | ||
| 18 | + def test_formatter(self): | ||
| 19 | + fmt = string.Formatter() | ||
| 20 | + self.assertEqual(fmt.format("foo"), "foo") | ||
| 21 | + | ||
| 22 | + # Formatter not working you for lookups | ||
| 23 | + #self.assertEqual(fmt.format("foo{0}", "bar"), "foobar") | ||
| 24 | + | ||
| 25 | + | ||
| 18 | 26 | def test_maketrans(self): | |
| 19 | 27 | transtable = '\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`xyzdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377' | |
| 20 | 28 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments