@@ -161,7 +161,7 @@ def _format(self, object, stream, indent, allowance, context, level):
161161 return
162162 rep = self ._repr (object , context , level - 1 )
163163 typ = type (object )
164- max_width = self ._width - 1 - indent - allowance
164+ max_width = self ._width - indent - allowance
165165 sepLines = len (rep ) > max_width
166166 write = stream .write
167167
@@ -174,24 +174,14 @@ def _format(self, object, stream, indent, allowance, context, level):
174174 length = len (object )
175175 if length :
176176 context [objid ] = 1
177- indent = indent + self ._indent_per_level
178177 if issubclass (typ , _OrderedDict ):
179178 items = list (object .items ())
180179 else :
181180 items = sorted (object .items (), key = _safe_tuple )
182- key , ent = items [0 ]
183- rep = self ._repr (key , context , level )
184- write (rep )
185- write (': ' )
186- self ._format (ent , stream , indent + len (rep ) + 2 ,
187- allowance + 1 , context , level )
188- if length > 1 :
189- for key , ent in items [1 :]:
190- rep = self ._repr (key , context , level )
191- write (',\n %s%s: ' % (' ' * indent , rep ))
192- self ._format (ent , stream , indent + len (rep ) + 2 ,
193- allowance + 1 , context , level )
194- indent = indent - self ._indent_per_level
181+ self ._format_dict_items (items , stream ,
182+ indent + self ._indent_per_level ,
183+ allowance + 1 ,
184+ context , level )
195185 del context [objid ]
196186 write ('}' )
197187 return
@@ -207,7 +197,10 @@ def _format(self, object, stream, indent, allowance, context, level):
207197 endchar = ']'
208198 elif issubclass (typ , tuple ):
209199 write ('(' )
210- endchar = ')'
200+ if length == 1 :
201+ endchar = ',)'
202+ else :
203+ endchar = ')'
211204 else :
212205 if not length :
213206 write (rep )
@@ -227,10 +220,9 @@ def _format(self, object, stream, indent, allowance, context, level):
227220 context [objid ] = 1
228221 self ._format_items (object , stream ,
229222 indent + self ._indent_per_level ,
230- allowance + 1 , context , level )
223+ allowance + len (endchar ),
224+ context , level )
231225 del context [objid ]
232- if issubclass (typ , tuple ) and length == 1 :
233- write (',' )
234226 write (endchar )
235227 return
236228
@@ -239,19 +231,27 @@ def _format(self, object, stream, indent, allowance, context, level):
239231 lines = object .splitlines (True )
240232 if level == 1 :
241233 indent += 1
242- max_width -= 2
234+ allowance += 1
235+ max_width1 = max_width = self ._width - indent
243236 for i , line in enumerate (lines ):
244237 rep = repr (line )
245- if len (rep ) <= max_width :
238+ if i == len (lines ) - 1 :
239+ max_width1 -= allowance
240+ if len (rep ) <= max_width1 :
246241 chunks .append (rep )
247242 else :
248243 # A list of alternating (non-space, space) strings
249- parts = re .split (r'(\s+)' , line ) + ['' ]
244+ parts = re .findall (r'\S*\s*' , line )
245+ assert parts
246+ assert not parts [- 1 ]
247+ parts .pop () # drop empty last part
248+ max_width2 = max_width
250249 current = ''
251- for i in range (0 , len (parts ), 2 ):
252- part = parts [i ] + parts [i + 1 ]
250+ for j , part in enumerate (parts ):
253251 candidate = current + part
254- if len (repr (candidate )) > max_width :
252+ if j == len (parts ) - 1 and i == len (lines ) - 1 :
253+ max_width2 -= allowance
254+ if len (repr (candidate )) > max_width2 :
255255 if current :
256256 chunks .append (repr (current ))
257257 current = part
@@ -273,12 +273,41 @@ def _format(self, object, stream, indent, allowance, context, level):
273273 return
274274 write (rep )
275275
276+ def _format_dict_items (self , items , stream , indent , allowance , context ,
277+ level ):
278+ write = stream .write
279+ delimnl = ',\n ' + ' ' * indent
280+ last_index = len (items ) - 1
281+ for i , (key , ent ) in enumerate (items ):
282+ last = i == last_index
283+ rep = self ._repr (key , context , level )
284+ write (rep )
285+ write (': ' )
286+ self ._format (ent , stream , indent + len (rep ) + 2 ,
287+ allowance if last else 1 ,
288+ context , level )
289+ if not last :
290+ write (delimnl )
291+
276292 def _format_items (self , items , stream , indent , allowance , context , level ):
277293 write = stream .write
278294 delimnl = ',\n ' + ' ' * indent
279295 delim = ''
280- width = max_width = self ._width - indent - allowance + 2
281- for ent in items :
296+ width = max_width = self ._width - indent + 1
297+ it = iter (items )
298+ try :
299+ next_ent = next (it )
300+ except StopIteration :
301+ return
302+ last = False
303+ while not last :
304+ ent = next_ent
305+ try :
306+ next_ent = next (it )
307+ except StopIteration :
308+ last = True
309+ max_width -= allowance
310+ width -= allowance
282311 if self ._compact :
283312 rep = self ._repr (ent , context , level )
284313 w = len (rep ) + 2
@@ -294,7 +323,9 @@ def _format_items(self, items, stream, indent, allowance, context, level):
294323 continue
295324 write (delim )
296325 delim = delimnl
297- self ._format (ent , stream , indent , allowance , context , level )
326+ self ._format (ent , stream , indent ,
327+ allowance if last else 1 ,
328+ context , level )
298329
299330 def _repr (self , object , context , level ):
300331 repr , readable , recursive = self .format (object , context .copy (),
0 commit comments