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

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

76 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 

10 

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

12 

13#----------------------------------------------------------------------------- 

14# utility functions 

15#----------------------------------------------------------------------------- 

16 

17 

18def _merge(d1, d2): 

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

20 

21 Updates d1 in-place 

22 """ 

23 

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

25 return d2 

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

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

28 return d1 

29 

30 

31#----------------------------------------------------------------------------- 

32# Main functions 

33#----------------------------------------------------------------------------- 

34 

35# use * to indicate transient is keyword-only 

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

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

38 

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

40 more details about this message type. 

41 

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

43 

44 Parameters 

45 ---------- 

46 data : dict 

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

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

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

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

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

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

53 representation to use. 

54 metadata : dict 

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

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

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

58 to specify metadata about particular representations. 

59 transient : dict, keyword-only 

60 A dictionary of transient data, such as display_id. 

61 """ 

62 from IPython.core.interactiveshell import InteractiveShell 

63 

64 display_pub = InteractiveShell.instance().display_pub 

65 

66 # only pass transient if supplied, 

67 # to avoid errors with older ipykernel. 

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

69 if transient: 

70 kwargs['transient'] = transient 

71 

72 display_pub.publish( 

73 data=data, 

74 metadata=metadata, 

75 **kwargs 

76 ) 

77 

78 

79def _new_id(): 

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

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

82 

83 

84def display( 

85 *objs, 

86 include=None, 

87 exclude=None, 

88 metadata=None, 

89 transient=None, 

90 display_id=None, 

91 raw=False, 

92 clear=False, 

93 **kwargs, 

94): 

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

96 

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

98 Frontends can decide which representation is used and how. 

99 

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

101 frontends see Jupyter notebook examples with rich display logic. 

102 

103 Parameters 

104 ---------- 

105 *objs : object 

106 The Python objects to display. 

107 raw : bool, optional 

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

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

110 include : list, tuple or set, optional 

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

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

113 in this list will be computed. 

114 exclude : list, tuple or set, optional 

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

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

117 except for those included in this argument. 

118 metadata : dict, optional 

119 A dictionary of metadata to associate with the output. 

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

121 representation formats, if they exist. 

122 transient : dict, optional 

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

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

125 display_id : str, bool optional 

126 Set an id for the display. 

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

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

129 clear : bool, optional 

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

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

132 **kwargs : additional keyword-args, optional 

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

134 

135 Returns 

136 ------- 

137 handle: DisplayHandle 

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

139 if `display_id` is given. Returns :py:data:`None` if no `display_id` is given 

140 (default). 

141 

142 Examples 

143 -------- 

144 >>> class Json(object): 

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

146 ... self.json = json 

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

148 ... import json 

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

150 ... def __repr__(self): 

151 ... return str(self.json) 

152 ... 

153 

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

155 

156 >>> print(d) 

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

158 

159 >>> display(d) 

160 { 

161 "1": 2, 

162 "3": { 

163 "4": 5 

164 } 

165 } 

166 

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

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

169 

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

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

172 <function _repr_pprint at 0x...> 

173 >>> display(7-5) 

174 II 

175 

176 >>> del plain.type_printers[int] 

177 >>> display(7-5) 

178 2 

179 

180 See Also 

181 -------- 

182 :func:`update_display` 

183 

184 Notes 

185 ----- 

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

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

188 other, rich representations including: 

189 

190 - HTML 

191 - JSON 

192 - PNG 

193 - JPEG 

194 - SVG 

195 - LaTeX 

196 

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

198 handled by IPython's display system. 

199 

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

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

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

203 values they must return: 

204 

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

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

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

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

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

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

211 or a tuple (see below). 

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

213 from all mimetypes to data. 

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

215 

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

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

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

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

220 

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

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

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

224 

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

226 order to register custom formatters for already existing types 

227 (:ref:`integrating_rich_display`). 

228 

229 .. versionadded:: 5.4 display available without import 

230 .. versionadded:: 6.1 display available without import 

231 

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

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

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

235 following import at the top of your file:: 

236 

237 from IPython.display import display 

238 

239 """ 

240 from IPython.core.interactiveshell import InteractiveShell 

241 

242 if not InteractiveShell.initialized(): 

243 # Directly print objects. 

244 print(*objs) 

245 return 

246 

247 if transient is None: 

248 transient = {} 

249 if metadata is None: 

250 metadata={} 

251 if display_id: 

252 if display_id is True: 

253 display_id = _new_id() 

254 transient['display_id'] = display_id 

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

256 raise TypeError('display_id required for update_display') 

257 if transient: 

258 kwargs['transient'] = transient 

259 

260 if not objs and display_id: 

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

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

263 # can be updated later 

264 objs = [{}] 

265 raw = True 

266 

267 if not raw: 

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

269 

270 if clear: 

271 clear_output(wait=True) 

272 

273 for obj in objs: 

274 if raw: 

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

276 else: 

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

278 if not format_dict: 

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

280 continue 

281 if metadata: 

282 # kwarg-specified metadata gets precedence 

283 _merge(md_dict, metadata) 

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

285 if display_id: 

286 return DisplayHandle(display_id) 

287 

288 

289# use * for keyword-only display_id arg 

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

291 """Update an existing display by id 

292 

293 Parameters 

294 ---------- 

295 obj 

296 The object with which to update the display 

297 display_id : keyword-only 

298 The id of the display to update 

299 

300 See Also 

301 -------- 

302 :func:`display` 

303 """ 

304 kwargs['update'] = True 

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

306 

307 

308class DisplayHandle: 

309 """A handle on an updatable display 

310 

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

312 

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

314 and update existing instances. 

315 

316 See Also 

317 -------- 

318 

319 :func:`display`, :func:`update_display` 

320 

321 """ 

322 

323 def __init__(self, display_id=None): 

324 if display_id is None: 

325 display_id = _new_id() 

326 self.display_id = display_id 

327 

328 def __repr__(self): 

329 return "<{} display_id={}>".format(self.__class__.__name__, self.display_id) 

330 

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

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

333 

334 Parameters 

335 ---------- 

336 obj 

337 object to display 

338 **kwargs 

339 additional keyword arguments passed to display 

340 """ 

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

342 

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

344 """Update existing displays with my id 

345 

346 Parameters 

347 ---------- 

348 obj 

349 object to display 

350 **kwargs 

351 additional keyword arguments passed to update_display 

352 """ 

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

354 

355 

356def clear_output(wait=False): 

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

358 

359 Parameters 

360 ---------- 

361 wait : bool [default: false] 

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

363 from IPython.core.interactiveshell import InteractiveShell 

364 if InteractiveShell.initialized(): 

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

366 else: 

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

368 sys.stdout.flush() 

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

370 sys.stderr.flush()