1+ # Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+ # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+ #
4+ # The Universal Permissive License (UPL), Version 1.0
5+ #
6+ # Subject to the condition set forth below, permission is hereby granted to any
7+ # person obtaining a copy of this software, associated documentation and/or
8+ # data (collectively the "Software"), free of charge and under any and all
9+ # copyright rights in the Software, and any and all patent rights owned or
10+ # freely licensable by each licensor hereunder covering either (i) the
11+ # unmodified Software as contributed to or provided by such licensor, or (ii)
12+ # the Larger Works (as defined below), to deal in both
13+ #
14+ # (a) the Software, and
15+ #
16+ # (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+ # one is included with the Software each a "Larger Work" to which the Software
18+ # is contributed by such licensors),
19+ #
20+ # without restriction, including without limitation the rights to copy, create
21+ # derivative works of, display, perform, and distribute the Software and make,
22+ # use, sell, offer for sale, import, export, have made, and have sold the
23+ # Software and the Larger Work(s), and to sublicense the foregoing rights on
24+ # either these or other terms.
25+ #
26+ # This license is subject to the following condition:
27+ #
28+ # The above copyright notice and either this complete permission notice or at a
29+ # minimum a reference to the UPL must be included in all copies or substantial
30+ # portions of the Software.
31+ #
32+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+ # SOFTWARE.
39+
40+ import unittest
41+
42+
43+ class Polymorph :
44+ def __index__ (self ):
45+ return 42
46+ def __int__ (self ):
47+ return 1
48+ def __float__ (self ):
49+ return 3.14
50+ def __str__ (self ):
51+ return "hello"
52+ def __bytes__ (self ):
53+ return b"bytes"
54+
55+
56+ # This is all one needs to implement to satisfy PyCheck_Mapping
57+ class MyPseudoMapping :
58+ def __getitem__ (self , item ):
59+ return item
60+
61+
62+ def test_formatting ():
63+ # tests some corner-cases that the standard tests do not cover
64+ assert format (- 12e8 , "0=30,.4f" ) == '-0,000,000,001,200,000,000.0000'
65+ assert b"%(mykey)d" % {b'mykey' : 42 } == b"42"
66+ assert b"%c" % b'q' == b"q"
67+ assert "%-5d" % 42 == "42 "
68+ assert "%.*f" % (- 2 , 2.5 ) == "2"
69+ assert "%.*f" % (True , 2.51 ) == "2.5"
70+ assert "%ld" % 42 == "42"
71+
72+ assert "%c" % Polymorph () == "*"
73+ assert "%d" % Polymorph () == "1"
74+ assert "%x" % Polymorph () == "2a"
75+ assert "%s" % Polymorph () == "hello"
76+ assert "%.2f" % Polymorph () == "3.14"
77+ assert b"%c" % Polymorph () == b"*"
78+ assert b"%s" % Polymorph () == b"bytes"
79+
80+ assert type (bytearray ("hello %d" , "ascii" ) % 42 ) == bytearray
81+ assert type (b"hello %d" % 42 ) == bytes
82+
83+ # No error about too many arguments,
84+ # because the object is considered as a mapping...
85+ assert " " % MyPseudoMapping () == " "
86+
87+
88+ def test_complex_formatting ():
89+ assert format (3 + 2j , ">20,.4f" ) == " 3.0000+2.0000j"
90+ assert format (3 + 2j , "+.2f" ) == "+3.00+2.00j"
91+ assert format (- 3 + 2j , "+.2f" ) == "-3.00+2.00j"
92+ assert format (3 + 2j , "-.3f" ) == "3.000+2.000j"
93+ assert format (3 - 2j , "-.3f" ) == "3.000-2.000j"
94+ assert format (- 3 - 2j , "-.3f" ) == "-3.000-2.000j"
95+ assert format (3 + 2j , " .1f" ) == " 3.0+2.0j"
96+ assert format (- 3 + 2j , " .1f" ) == "-3.0+2.0j"
97+ assert format (complex (3 ), ".1g" ) == "3+0j"
98+ assert format (3j , ".1g" ) == "0+3j"
99+ assert format (- 3j , ".1g" ) == "-0-3j"
100+ assert format (3j , "" ) == "3j"
101+ assert format (1 + 0j , "" ) == "(1+0j)"
102+ assert format (1 + 2j , "" ) == "(1+2j)"
103+ assert format (complex (1 , float ("NaN" )), "" ) == "(1+nanj)"
104+ assert format (complex (1 , float ("Inf" )), "" ) == "(1+infj)"
105+
106+
107+ class AnyRepr :
108+ def __init__ (self , val ):
109+ self .val = val
110+ def __repr__ (self ):
111+ return self .val
112+
113+
114+ def test_non_ascii_repr ():
115+ assert "%a" % AnyRepr ("\t " ) == "\t "
116+ assert "%a" % AnyRepr ("\\ " ) == "\\ "
117+ assert "%a" % AnyRepr ("\\ " ) == "\\ "
118+ assert "%a" % AnyRepr ("\u0378 " ) == "\\ u0378"
119+ assert "%r" % AnyRepr ("\u0378 " ) == "\u0378 "
120+ assert "%a" % AnyRepr ("\u0374 " ) == "\\ u0374"
121+ assert "%r" % AnyRepr ("\u0374 " ) == "\u0374 "
122+
123+ assert b"%a" % AnyRepr ("\t " ) == b"\t "
124+ assert b"%a" % AnyRepr ("\\ " ) == b"\\ "
125+ assert b"%a" % AnyRepr ("\\ " ) == b"\\ "
126+ assert b"%a" % AnyRepr ("\u0378 " ) == b"\\ u0378"
127+ assert b"%r" % AnyRepr ("\u0378 " ) == b"\\ u0378"
128+ assert b"%a" % AnyRepr ("\u0374 " ) == b"\\ u0374"
129+ assert b"%r" % AnyRepr ("\u0374 " ) == b"\\ u0374"
130+
131+
132+ class FormattingErrorsTest (unittest .TestCase ):
133+ def test_formatting_errors (self ):
134+ self .assertRaises (TypeError , lambda : format (- 12e8 , b"0=30,.4f" ))
135+ self .assertRaises (TypeError , lambda : format (42 , b"0=30,.4f" ))
136+ self .assertRaises (TypeError , lambda : format ("str" , b"0=30,.4f" ))
137+ self .assertRaises (TypeError , lambda : format (3 + 1j , b"0=30,.4f" ))
138+ self .assertRaises (TypeError , lambda : b"hello" % b"world" )
139+ self .assertRaises (TypeError , lambda : b"%f" % "str" )
140+ self .assertRaises (TypeError , lambda : b"%c" % "str" )
141+
142+ self .assertRaises (KeyError , lambda : b"%(mykey)d" % {"mykey" : 42 })
143+ self .assertRaises (KeyError , lambda : "%(mykey)d" % {b"mykey" : 42 })
144+ self .assertRaises (OverflowError , lambda : b"%c" % 260 )
145+
146+ self .assertRaises (ValueError , lambda : format (3 + 2j , "f=30,.4f" ))
147+ self .assertRaises (ValueError , lambda : format (3 + 2j , "0=30,.4f" ))
0 commit comments