Skip to content

Commit 11ff71d

Browse files
authored
Merge pull request #359 from 1st1/bytesmod
Add support for proper %s formatting of newbytes
2 parents 6addfaa + 70b61bc commit 11ff71d

File tree

3 files changed

+101
-31
lines changed

3 files changed

+101
-31
lines changed

src/future/types/newbytes.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,29 @@ def __mul__(self, other):
174174
def __rmul__(self, other):
175175
return newbytes(super(newbytes, self).__rmul__(other))
176176

177+
def __mod__(self, vals):
178+
if isinstance(vals, newbytes):
179+
vals = _builtin_bytes.__str__(vals)
180+
181+
elif isinstance(vals, tuple):
182+
newvals = []
183+
for v in vals:
184+
if isinstance(v, newbytes):
185+
v = _builtin_bytes.__str__(v)
186+
newvals.append(v)
187+
vals = tuple(newvals)
188+
189+
elif (hasattr(vals.__class__, '__getitem__') and
190+
hasattr(vals.__class__, 'iteritems')):
191+
for k, v in vals.iteritems():
192+
if isinstance(v, newbytes):
193+
vals[k] = _builtin_bytes.__str__(v)
194+
195+
return _builtin_bytes.__mod__(self, vals)
196+
197+
def __imod__(self, other):
198+
return self.__mod__(other)
199+
177200
def join(self, iterable_of_bytes):
178201
errmsg = 'sequence item {0}: expected bytes, {1} found'
179202
if isbytes(iterable_of_bytes) or istext(iterable_of_bytes):

src/future/utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656

5757

5858
PY3 = sys.version_info[0] == 3
59+
PY35 = sys.version_info[0:2] >= (3, 5)
5960
PY2 = sys.version_info[0] == 2
6061
PY26 = sys.version_info[0:2] == (2, 6)
6162
PY27 = sys.version_info[0:2] == (2, 7)

tests/test_future/test_bytes.py

Lines changed: 77 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -552,37 +552,83 @@ def test_maketrans(self):
552552
self.assertRaises(ValueError, bytes.maketrans, b'abc', b'xyzq')
553553
self.assertRaises(TypeError, bytes.maketrans, 'abc', 'def')
554554

555-
# def test_mod(self):
556-
# """
557-
# From Py3.5 test suite (post-PEP 461).
558-
#
559-
# The bytes mod code is in _PyBytes_Format() in bytesobject.c in Py3.5.
560-
# """
561-
# b = b'hello, %b!'
562-
# orig = b
563-
# b = b % b'world'
564-
# self.assertEqual(b, b'hello, world!')
565-
# self.assertEqual(orig, b'hello, %b!')
566-
# self.assertFalse(b is orig)
567-
# b = b'%s / 100 = %d%%'
568-
# a = b % (b'seventy-nine', 79)
569-
# self.assertEqual(a, b'seventy-nine / 100 = 79%')
570-
571-
# def test_imod(self):
572-
# """
573-
# From Py3.5 test suite (post-PEP 461)
574-
# """
575-
# # if (3, 0) <= sys.version_info[:2] < (3, 5):
576-
# # raise unittest.SkipTest('bytes % not yet implemented on Py3.0-3.4')
577-
# b = bytes(b'hello, %b!')
578-
# orig = b
579-
# b %= b'world'
580-
# self.assertEqual(b, b'hello, world!')
581-
# self.assertEqual(orig, b'hello, %b!')
582-
# self.assertFalse(b is orig)
583-
# b = bytes(b'%s / 100 = %d%%')
584-
# b %= (b'seventy-nine', 79)
585-
# self.assertEqual(b, b'seventy-nine / 100 = 79%')
555+
@unittest.skipUnless(utils.PY2, 'test requires Python 2')
556+
def test_mod_custom_dict(self):
557+
import UserDict
558+
559+
class MyDict(UserDict.UserDict):
560+
pass
561+
562+
d = MyDict()
563+
d['foo'] = bytes(b'bar')
564+
self.assertFalse(isinstance(d, dict))
565+
self.assertTrue(isinstance(d, UserDict.UserDict))
566+
567+
self.assertEqual(bytes(b'%(foo)s') % d, b'bar')
568+
569+
@unittest.skipUnless(utils.PY35 or utils.PY2,
570+
'test requires Python 2 or 3.5+')
571+
def test_mod_more(self):
572+
self.assertEqual(b'%s' % b'aaa', b'aaa')
573+
self.assertEqual(bytes(b'%s') % b'aaa', b'aaa')
574+
self.assertEqual(bytes(b'%s') % bytes(b'aaa'), b'aaa')
575+
576+
self.assertEqual(b'%s' % (b'aaa',), b'aaa')
577+
self.assertEqual(bytes(b'%s') % (b'aaa',), b'aaa')
578+
self.assertEqual(bytes(b'%s') % (bytes(b'aaa'),), b'aaa')
579+
580+
self.assertEqual(bytes(b'%(x)s') % {'x': b'aaa'}, b'aaa')
581+
self.assertEqual(bytes(b'%(x)s') % {'x': bytes(b'aaa')}, b'aaa')
582+
583+
@unittest.skipUnless(utils.PY35 or utils.PY2,
584+
'test requires Python 2 or 3.5+')
585+
def test_mod(self):
586+
"""
587+
From Py3.5 test suite (post-PEP 461).
588+
589+
The bytes mod code is in _PyBytes_Format() in bytesobject.c in Py3.5.
590+
"""
591+
592+
# XXX Add support for %b!
593+
#
594+
# b = bytes(b'hello, %b!')
595+
# orig = b
596+
# b = b % b'world'
597+
# self.assertEqual(b, b'hello, world!')
598+
# self.assertEqual(orig, b'hello, %b!')
599+
# self.assertFalse(b is orig)
600+
601+
b = bytes(b'%s / 100 = %d%%')
602+
a = b % (b'seventy-nine', 79)
603+
self.assertEqual(a, b'seventy-nine / 100 = 79%')
604+
605+
b = bytes(b'%s / 100 = %d%%')
606+
a = b % (bytes(b'seventy-nine'), 79)
607+
self.assertEqual(a, b'seventy-nine / 100 = 79%')
608+
609+
@unittest.skipUnless(utils.PY35 or utils.PY2,
610+
'test requires Python 2 or 3.5+')
611+
def test_imod(self):
612+
"""
613+
From Py3.5 test suite (post-PEP 461)
614+
"""
615+
# if (3, 0) <= sys.version_info[:2] < (3, 5):
616+
# raise unittest.SkipTest('bytes % not yet implemented on Py3.0-3.4')
617+
618+
# b = bytes(b'hello, %b!')
619+
# orig = b
620+
# b %= b'world'
621+
# self.assertEqual(b, b'hello, world!')
622+
# self.assertEqual(orig, b'hello, %b!')
623+
# self.assertFalse(b is orig)
624+
625+
b = bytes(b'%s / 100 = %d%%')
626+
b %= (b'seventy-nine', 79)
627+
self.assertEqual(b, b'seventy-nine / 100 = 79%')
628+
629+
b = bytes(b'%s / 100 = %d%%')
630+
b %= (bytes(b'seventy-nine'), 79)
631+
self.assertEqual(b, b'seventy-nine / 100 = 79%')
586632

587633
# def test_mod_pep_461(self):
588634
# """

0 commit comments

Comments
 (0)