Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/display_functions.py: 22%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

77 statements  

1"""Top-level display functions for displaying object in different formats.""" 

2 

3# Copyright (c) IPython Development Team. 

4# Distributed under the terms of the Modified BSD License. 

5 

6 

7from binascii import b2a_hex 

8import os 

9import sys 

10import warnings 

11 

12__all__ = ['display', 'clear_output', 'publish_display_data', 'update_display', 'DisplayHandle'] 

13 

14#----------------------------------------------------------------------------- 

15# utility functions 

16#----------------------------------------------------------------------------- 

17 

18 

19def _merge(d1, d2): 

20 """Like update, but merges sub-dicts instead of clobbering at the top level. 

21 

22 Updates d1 in-place 

23 """ 

24 

25 if not isinstance(d2, dict) or not isinstance(d1, dict): 

26 return d2 

27 for key, value in d2.items(): 

28 d1[key] = _merge(d1.get(key), value) 

29 return d1 

30 

31 

32#----------------------------------------------------------------------------- 

33# Main functions 

34#----------------------------------------------------------------------------- 

35 

36# use * to indicate transient is keyword-only 

37def publish_display_data(data, metadata=None, *, transient=None, **kwargs): 

38 """Publish data and metadata to all frontends. 

39 

40 See the ``display_data`` message in the messaging documentation for 

41 more details about this message type. 

42 

43 Keys of data and metadata can be any mime-type. 

44 

45 Parameters 

46 ---------- 

47 data : dict 

48 A dictionary having keys that are valid MIME types (like 

49 'text/plain' or 'image/svg+xml') and values that are the data for 

50 that MIME type. The data itself must be a JSON'able data 

51 structure. Minimally all data should have the 'text/plain' data, 

52 which can be displayed by all frontends. If more than the plain 

53 text is given, it is up to the frontend to decide which 

54 representation to use. 

55 metadata : dict 

56 A dictionary for metadata related to the data. This can contain 

57 arbitrary key, value pairs that frontends can use to interpret 

58 the data. mime-type keys matching those in data can be used 

59 to specify metadata about particular representations. 

60 transient : dict, keyword-only 

61 A dictionary of transient data, such as display_id. 

62 """ 

63 from IPython.core.interactiveshell import InteractiveShell 

64 

65 display_pub = InteractiveShell.instance().display_pub 

66 

67 # only pass transient if supplied, 

68 # to avoid errors with older ipykernel. 

69 # TODO: We could check for ipykernel version and provide a detailed upgrade message. 

70 if transient: 

71 kwargs['transient'] = transient 

72 

73 display_pub.publish( 

74 data=data, 

75 metadata=metadata, 

76 **kwargs 

77 ) 

78 

79 

80def _new_id(): 

81 """Generate a new random text id with urandom""" 

82 return b2a_hex(os.urandom(16)).decode('ascii') 

83 

84 

85def display( 

86 *objs, 

87 include=None, 

88 exclude=None, 

89 metadata=None, 

90 transient=None, 

91 display_id=None, 

92 raw=False, 

93 clear=False, 

94 **kwargs, 

95): 

96 """Display a Python object in all frontends. 

97 

98 By default all representations will be computed and sent to the frontends. 

99 Frontends can decide which representation is used and how. 

100 

101 In terminal IPython this will be similar to using :func:`print`, for use in richer 

102 frontends see Jupyter notebook examples with rich display logic. 

103 

104 Parameters 

105 ---------- 

106 *objs : object 

107 The Python objects to display. 

108 raw : bool, optional 

109 Are the objects to be displayed already mimetype-keyed dicts of raw display data, 

110 or Python objects that need to be formatted before display? [default: False] 

111 include : list, tuple or set, optional 

112 A list of format type strings (MIME types) to include in the 

113 format data dict. If this is set *only* the format types included 

114 in this list will be computed. 

115 exclude : list, tuple or set, optional 

116 A list of format type strings (MIME types) to exclude in the format 

117 data dict. If this is set all format types will be computed, 

118 except for those included in this argument. 

119 metadata : dict, optional 

120 A dictionary of metadata to associate with the output. 

121 mime-type keys in this dictionary will be associated with the individual 

122 representation formats, if they exist. 

123 transient : dict, optional 

124 A dictionary of transient data to associate with the output. 

125 Data in this dict should not be persisted to files (e.g. notebooks). 

126 display_id : str, bool optional 

127 Set an id for the display. 

128 This id can be used for updating this display area later via update_display. 

129 If given as `True`, generate a new `display_id` 

130 clear : bool, optional 

131 Should the output area be cleared before displaying anything? If True, 

132 this will wait for additional output before clearing. [default: False] 

133 **kwargs : additional keyword-args, optional 

134 Additional keyword-arguments are passed through to the display publisher. 

135 

136 Returns 

137 ------- 

138 handle: DisplayHandle 

139 Returns a handle on updatable displays for use with :func:`update_display`, 

140 if `display_id` is given. Returns :any:`None` if no `display_id` is given 

141 (default). 

142 

143 Examples 

144 -------- 

145 >>> class Json(object): 

146 ... def __init__(self, json): 

147 ... self.json = json 

148 ... def _repr_pretty_(self, pp, cycle): 

149 ... import json 

150 ... pp.text(json.dumps(self.json, indent=2)) 

151 ... def __repr__(self): 

152 ... return str(self.json) 

153 ... 

154 

155 >>> d = Json({1:2, 3: {4:5}}) 

156 

157 >>> print(d) 

158 {1: 2, 3: {4: 5}} 

159 

160 >>> display(d) 

161 { 

162 "1": 2, 

163 "3": { 

164 "4": 5 

165 } 

166 } 

167 

168 >>> def int_formatter(integer, pp, cycle): 

169 ... pp.text('I'*integer) 

170 

171 >>> plain = get_ipython().display_formatter.formatters['text/plain'] 

172 >>> plain.for_type(int, int_formatter) 

173 <function _repr_pprint at 0x...> 

174 >>> display(7-5) 

175 II 

176 

177 >>> del plain.type_printers[int] 

178 >>> display(7-5) 

179 2 

180 

181 See Also 

182 -------- 

183 :func:`update_display` 

184 

185 Notes 

186 ----- 

187 In Python, objects can declare their textual representation using the 

188 `__repr__` method. IPython expands on this idea and allows objects to declare 

189 other, rich representations including: 

190 

191 - HTML 

192 - JSON 

193 - PNG 

194 - JPEG 

195 - SVG 

196 - LaTeX 

197 

198 A single object can declare some or all of these representations; all are 

199 handled by IPython's display system. 

200 

201 The main idea of the first approach is that you have to implement special 

202 display methods when you define your class, one for each representation you 

203 want to use. Here is a list of the names of the special methods and the 

204 values they must return: 

205 

206 - `_repr_html_`: return raw HTML as a string, or a tuple (see below). 

207 - `_repr_json_`: return a JSONable dict, or a tuple (see below). 

208 - `_repr_jpeg_`: return raw JPEG data, or a tuple (see below). 

209 - `_repr_png_`: return raw PNG data, or a tuple (see below). 

210 - `_repr_svg_`: return raw SVG data as a string, or a tuple (see below). 

211 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$", 

212 or a tuple (see below). 

213 - `_repr_mimebundle_`: return a full mimebundle containing the mapping 

214 from all mimetypes to data. 

215 Use this for any mime-type not listed above. 

216 

217 The above functions may also return the object's metadata alonside the 

218 data. If the metadata is available, the functions will return a tuple 

219 containing the data and metadata, in that order. If there is no metadata 

220 available, then the functions will return the data only. 

221 

222 When you are directly writing your own classes, you can adapt them for 

223 display in IPython by following the above approach. But in practice, you 

224 often need to work with existing classes that you can't easily modify. 

225 

226 You can refer to the documentation on integrating with the display system in 

227 order to register custom formatters for already existing types 

228 (:ref:`integrating_rich_display`). 

229 

230 .. versionadded:: 5.4 display available without import 

231 .. versionadded:: 6.1 display available without import 

232 

233 Since IPython 5.4 and 6.1 :func:`display` is automatically made available to 

234 the user without import. If you are using display in a document that might 

235 be used in a pure python context or with older version of IPython, use the 

236 following import at the top of your file:: 

237 

238 from IPython.display import display 

239 

240 """ 

241 from IPython.core.interactiveshell import InteractiveShell 

242 

243 if not InteractiveShell.initialized(): 

244 # Directly print objects. 

245 print(*objs) 

246 return 

247 

248 if transient is None: 

249 transient = {} 

250 if metadata is None: 

251 metadata={} 

252 if display_id: 

253 if display_id is True: 

254 display_id = _new_id() 

255 transient['display_id'] = display_id 

256 if kwargs.get('update') and 'display_id' not in transient: 

257 raise TypeError('display_id required for update_display') 

258 if transient: 

259 kwargs['transient'] = transient 

260 

261 if not objs and display_id: 

262 # if given no objects, but still a request for a display_id, 

263 # we assume the user wants to insert an empty output that 

264 # can be updated later 

265 objs = [{}] 

266 raw = True 

267 

268 if not raw: 

269 format = InteractiveShell.instance().display_formatter.format 

270 

271 if clear: 

272 clear_output(wait=True) 

273 

274 for obj in objs: 

275 if raw: 

276 publish_display_data(data=obj, metadata=metadata, **kwargs) 

277 else: 

278 format_dict, md_dict = format(obj, include=include, exclude=exclude) 

279 if not format_dict: 

280 # nothing to display (e.g. _ipython_display_ took over) 

281 continue 

282 if metadata: 

283 # kwarg-specified metadata gets precedence 

284 _merge(md_dict, metadata) 

285 publish_display_data(data=format_dict, metadata=md_dict, **kwargs) 

286 if display_id: 

287 return DisplayHandle(display_id) 

288 

289 

290# use * for keyword-only display_id arg 

291def update_display(obj, *, display_id, **kwargs): 

292 """Update an existing display by id 

293 

294 Parameters 

295 ---------- 

296 obj 

297 The object with which to update the display 

298 display_id : keyword-only 

299 The id of the display to update 

300 

301 See Also 

302 -------- 

303 :func:`display` 

304 """ 

305 kwargs['update'] = True 

306 display(obj, display_id=display_id, **kwargs) 

307 

308 

309class DisplayHandle: 

310 """A handle on an updatable display 

311 

312 Call `.update(obj)` to display a new object. 

313 

314 Call `.display(obj`) to add a new instance of this display, 

315 and update existing instances. 

316 

317 See Also 

318 -------- 

319 

320 :func:`display`, :func:`update_display` 

321 

322 """ 

323 

324 def __init__(self, display_id=None): 

325 if display_id is None: 

326 display_id = _new_id() 

327 self.display_id = display_id 

328 

329 def __repr__(self): 

330 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id) 

331 

332 def display(self, obj, **kwargs): 

333 """Make a new display with my id, updating existing instances. 

334 

335 Parameters 

336 ---------- 

337 obj 

338 object to display 

339 **kwargs 

340 additional keyword arguments passed to display 

341 """ 

342 display(obj, display_id=self.display_id, **kwargs) 

343 

344 def update(self, obj, **kwargs): 

345 """Update existing displays with my id 

346 

347 Parameters 

348 ---------- 

349 obj 

350 object to display 

351 **kwargs 

352 additional keyword arguments passed to update_display 

353 """ 

354 update_display(obj, display_id=self.display_id, **kwargs) 

355 

356 

357def clear_output(wait=False): 

358 """Clear the output of the current cell receiving output. 

359 

360 Parameters 

361 ---------- 

362 wait : bool [default: false] 

363 Wait to clear the output until new output is available to replace it.""" 

364 from IPython.core.interactiveshell import InteractiveShell 

365 if InteractiveShell.initialized(): 

366 InteractiveShell.instance().display_pub.clear_output(wait) 

367 else: 

368 print('\033[2K\r', end='') 

369 sys.stdout.flush() 

370 print('\033[2K\r', end='') 

371 sys.stderr.flush()