Backport of PEP 3101, Advanced String Formatting, from py3k.
Highlights:
- Adding PyObject_Format.
- Adding string.Format class.
- Adding __format__ for str, unicode, int, long, float, datetime.
- Adding builtin format.
- Adding ''.format and u''.format.
- str/unicode fixups for formatters.
The files in Objects/stringlib that implement PEP 3101 (stringdefs.h,
unicodedefs.h, formatter.h, string_format.h) are identical in trunk
and py3k. Any changes from here on should be made to trunk, and
changes will propogate to py3k).
diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py
index 21b8890..cb639b4 100644
--- a/Lib/test/test_datetime.py
+++ b/Lib/test/test_datetime.py
@@ -854,6 +854,32 @@
# A naive object replaces %z and %Z w/ empty strings.
self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
+ def test_format(self):
+ dt = self.theclass(2007, 9, 10)
+ self.assertEqual(dt.__format__(''), str(dt))
+
+ # check that a derived class's __str__() gets called
+ class A(self.theclass):
+ def __str__(self):
+ return 'A'
+ a = A(2007, 9, 10)
+ self.assertEqual(a.__format__(''), 'A')
+
+ # check that a derived class's strftime gets called
+ class B(self.theclass):
+ def strftime(self, format_spec):
+ return 'B'
+ b = B(2007, 9, 10)
+ self.assertEqual(b.__format__(''), str(dt))
+
+ for fmt in ["m:%m d:%d y:%y",
+ "m:%m d:%d y:%y H:%H M:%M S:%S",
+ "%z %Z",
+ ]:
+ self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
+ self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
+ self.assertEqual(b.__format__(fmt), 'B')
+
def test_resolution_info(self):
self.assert_(isinstance(self.theclass.min, self.theclass))
self.assert_(isinstance(self.theclass.max, self.theclass))
@@ -1136,6 +1162,32 @@
# str is ISO format with the separator forced to a blank.
self.assertEqual(str(t), "0002-03-02 00:00:00")
+ def test_format(self):
+ dt = self.theclass(2007, 9, 10, 4, 5, 1, 123)
+ self.assertEqual(dt.__format__(''), str(dt))
+
+ # check that a derived class's __str__() gets called
+ class A(self.theclass):
+ def __str__(self):
+ return 'A'
+ a = A(2007, 9, 10, 4, 5, 1, 123)
+ self.assertEqual(a.__format__(''), 'A')
+
+ # check that a derived class's strftime gets called
+ class B(self.theclass):
+ def strftime(self, format_spec):
+ return 'B'
+ b = B(2007, 9, 10, 4, 5, 1, 123)
+ self.assertEqual(b.__format__(''), str(dt))
+
+ for fmt in ["m:%m d:%d y:%y",
+ "m:%m d:%d y:%y H:%H M:%M S:%S",
+ "%z %Z",
+ ]:
+ self.assertEqual(dt.__format__(fmt), dt.strftime(fmt))
+ self.assertEqual(a.__format__(fmt), dt.strftime(fmt))
+ self.assertEqual(b.__format__(fmt), 'B')
+
def test_more_ctime(self):
# Test fields that TestDate doesn't touch.
import time
@@ -1767,6 +1819,30 @@
# A naive object replaces %z and %Z with empty strings.
self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''")
+ def test_format(self):
+ t = self.theclass(1, 2, 3, 4)
+ self.assertEqual(t.__format__(''), str(t))
+
+ # check that a derived class's __str__() gets called
+ class A(self.theclass):
+ def __str__(self):
+ return 'A'
+ a = A(1, 2, 3, 4)
+ self.assertEqual(a.__format__(''), 'A')
+
+ # check that a derived class's strftime gets called
+ class B(self.theclass):
+ def strftime(self, format_spec):
+ return 'B'
+ b = B(1, 2, 3, 4)
+ self.assertEqual(b.__format__(''), str(t))
+
+ for fmt in ['%H %M %S',
+ ]:
+ self.assertEqual(t.__format__(fmt), t.strftime(fmt))
+ self.assertEqual(a.__format__(fmt), t.strftime(fmt))
+ self.assertEqual(b.__format__(fmt), 'B')
+
def test_str(self):
self.assertEqual(str(self.theclass(1, 2, 3, 4)), "01:02:03.000004")
self.assertEqual(str(self.theclass(10, 2, 3, 4000)), "10:02:03.004000")