66 */
77package com .oracle .graal .python .runtime .formatting ;
88
9+ import static com .oracle .graal .python .nodes .SpecialMethodNames .__GETITEM__ ;
910import static com .oracle .graal .python .nodes .SpecialMethodNames .__INDEX__ ;
1011import static com .oracle .graal .python .nodes .SpecialMethodNames .__INT__ ;
1112import static com .oracle .graal .python .runtime .exception .PythonErrorType .MemoryError ;
1718import java .math .MathContext ;
1819
1920import com .oracle .graal .python .builtins .PythonBuiltinClassType ;
21+ import com .oracle .graal .python .builtins .objects .PNone ;
2022import com .oracle .graal .python .builtins .objects .PythonAbstractObject ;
2123import com .oracle .graal .python .builtins .objects .floats .PFloat ;
2224import com .oracle .graal .python .builtins .objects .function .PKeyword ;
@@ -219,6 +221,24 @@ protected InternalFormat.Formatter formatInteger(Object intObj, InternalFormat.S
219221 return fi ;
220222 }
221223
224+ /**
225+ * Should this argument be treated as a mapping or as a single argument. This logic differs
226+ * between string and bytes formatting.
227+ */
228+ protected abstract boolean useAsMapping (Object args1 , PythonObjectLibrary lib , Object lazyClass );
229+
230+ protected boolean isString (Object args1 , Object lazyClass ) {
231+ return PGuards .isString (args1 ) || isSubtype (lazyClass , PythonBuiltinClassType .PString );
232+ }
233+
234+ protected boolean isMapping (Object args1 ) {
235+ return lookupAttribute (args1 , __GETITEM__ ) != PNone .NO_VALUE ;
236+ }
237+
238+ protected static boolean isSubtype (Object lazyClass , PythonBuiltinClassType clazz ) {
239+ return IsSubtypeNodeGen .getUncached ().execute (lazyClass , clazz );
240+ }
241+
222242 /**
223243 * Main service of this class: format one or more arguments with the format string supplied at
224244 * construction.
@@ -238,15 +258,16 @@ private T formatImpl(Object args1) {
238258
239259 // We need to do a full subtype-check because native objects may inherit from tuple but have
240260 // Java type 'PythonNativeObject' (e.g. 'namedtuple' alias 'structseq').
241- boolean tupleArgs = PGuards .isPTuple (args1 ) || IsSubtypeNodeGen .getUncached ().execute (PythonObjectLibrary .getUncached ().getLazyPythonClass (args1 ), PythonBuiltinClassType .PTuple );
242- assert tupleArgs || !PGuards .isPTuple (args1 );
261+ PythonObjectLibrary args1Lib = PythonObjectLibrary .getFactory ().getUncached (args1 );
262+ final Object args1LazyClass = args1Lib .getLazyPythonClass (args1 );
263+ boolean tupleArgs = PGuards .isPTuple (args1 ) || isSubtype (args1LazyClass , PythonBuiltinClassType .PTuple );
243264 if (tupleArgs ) {
244265 // We will simply work through the tuple elements
245266 argIndex = 0 ;
246267 } else {
247268 // Not a tuple, but possibly still some kind of container: use
248269 // special argIndex values.
249- if (! PGuards . isString (args1 ) && PythonObjectLibrary . getUncached (). isMapping ( args1 )) {
270+ if (useAsMapping (args1 , args1Lib , args1LazyClass )) {
250271 mapping = args1 ;
251272 argIndex = -3 ;
252273 }
0 commit comments