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

83 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 06:09 +0000

1# -*- coding: utf-8 -*- 

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

3 

4# Copyright (c) IPython Development Team. 

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

6 

7 

8from binascii import b2a_hex 

9import os 

10import sys 

11import warnings 

12 

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

14 

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

16# utility functions 

17#----------------------------------------------------------------------------- 

18 

19 

20def _merge(d1, d2): 

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

22 

23 Updates d1 in-place 

24 """ 

25 

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

27 return d2 

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

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

30 return d1 

31 

32 

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

34# Main functions 

35#----------------------------------------------------------------------------- 

36 

37class _Sentinel: 

38 def __repr__(self): 

39 return "<deprecated>" 

40 

41 

42_sentinel = _Sentinel() 

43 

44# use * to indicate transient is keyword-only 

45def publish_display_data( 

46 data, metadata=None, source=_sentinel, *, transient=None, **kwargs 

47): 

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

49 

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

51 more details about this message type. 

52 

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

54 

55 Parameters 

56 ---------- 

57 data : dict 

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

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

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

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

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

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

64 representation to use. 

65 metadata : dict 

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

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

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

69 to specify metadata about particular representations. 

70 source : str, deprecated 

71 Unused. 

72 transient : dict, keyword-only 

73 A dictionary of transient data, such as display_id. 

74 """ 

75 from IPython.core.interactiveshell import InteractiveShell 

76 

77 if source is not _sentinel: 

78 warnings.warn( 

79 "The `source` parameter emit a deprecation warning since" 

80 " IPython 8.0, it had no effects for a long time and will " 

81 " be removed in future versions.", 

82 DeprecationWarning, 

83 stacklevel=2, 

84 ) 

85 display_pub = InteractiveShell.instance().display_pub 

86 

87 # only pass transient if supplied, 

88 # to avoid errors with older ipykernel. 

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

90 if transient: 

91 kwargs['transient'] = transient 

92 

93 display_pub.publish( 

94 data=data, 

95 metadata=metadata, 

96 **kwargs 

97 ) 

98 

99 

100def _new_id(): 

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

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

103 

104 

105def display( 

106 *objs, 

107 include=None, 

108 exclude=None, 

109 metadata=None, 

110 transient=None, 

111 display_id=None, 

112 raw=False, 

113 clear=False, 

114 **kwargs 

115): 

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

117 

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

119 Frontends can decide which representation is used and how. 

120 

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

122 frontends see Jupyter notebook examples with rich display logic. 

123 

124 Parameters 

125 ---------- 

126 *objs : object 

127 The Python objects to display. 

128 raw : bool, optional 

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

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

131 include : list, tuple or set, optional 

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

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

134 in this list will be computed. 

135 exclude : list, tuple or set, optional 

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

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

138 except for those included in this argument. 

139 metadata : dict, optional 

140 A dictionary of metadata to associate with the output. 

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

142 representation formats, if they exist. 

143 transient : dict, optional 

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

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

146 display_id : str, bool optional 

147 Set an id for the display. 

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

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

150 clear : bool, optional 

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

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

153 **kwargs : additional keyword-args, optional 

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

155 

156 Returns 

157 ------- 

158 handle: DisplayHandle 

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

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

161 (default). 

162 

163 Examples 

164 -------- 

165 >>> class Json(object): 

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

167 ... self.json = json 

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

169 ... import json 

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

171 ... def __repr__(self): 

172 ... return str(self.json) 

173 ... 

174 

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

176 

177 >>> print(d) 

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

179 

180 >>> display(d) 

181 { 

182 "1": 2, 

183 "3": { 

184 "4": 5 

185 } 

186 } 

187 

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

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

190 

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

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

193 <function _repr_pprint at 0x...> 

194 >>> display(7-5) 

195 II 

196 

197 >>> del plain.type_printers[int] 

198 >>> display(7-5) 

199 2 

200 

201 See Also 

202 -------- 

203 :func:`update_display` 

204 

205 Notes 

206 ----- 

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

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

209 other, rich representations including: 

210 

211 - HTML 

212 - JSON 

213 - PNG 

214 - JPEG 

215 - SVG 

216 - LaTeX 

217 

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

219 handled by IPython's display system. 

220 

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

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

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

224 values they must return: 

225 

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

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

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

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

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

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

232 or a tuple (see below). 

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

234 from all mimetypes to data. 

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

236 

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

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

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

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

241 

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

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

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

245 

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

247 order to register custom formatters for already existing types 

248 (:ref:`integrating_rich_display`). 

249 

250 .. versionadded:: 5.4 display available without import 

251 .. versionadded:: 6.1 display available without import 

252 

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

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

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

256 following import at the top of your file:: 

257 

258 from IPython.display import display 

259 

260 """ 

261 from IPython.core.interactiveshell import InteractiveShell 

262 

263 if not InteractiveShell.initialized(): 

264 # Directly print objects. 

265 print(*objs) 

266 return 

267 

268 if transient is None: 

269 transient = {} 

270 if metadata is None: 

271 metadata={} 

272 if display_id: 

273 if display_id is True: 

274 display_id = _new_id() 

275 transient['display_id'] = display_id 

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

277 raise TypeError('display_id required for update_display') 

278 if transient: 

279 kwargs['transient'] = transient 

280 

281 if not objs and display_id: 

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

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

284 # can be updated later 

285 objs = [{}] 

286 raw = True 

287 

288 if not raw: 

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

290 

291 if clear: 

292 clear_output(wait=True) 

293 

294 for obj in objs: 

295 if raw: 

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

297 else: 

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

299 if not format_dict: 

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

301 continue 

302 if metadata: 

303 # kwarg-specified metadata gets precedence 

304 _merge(md_dict, metadata) 

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

306 if display_id: 

307 return DisplayHandle(display_id) 

308 

309 

310# use * for keyword-only display_id arg 

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

312 """Update an existing display by id 

313 

314 Parameters 

315 ---------- 

316 obj 

317 The object with which to update the display 

318 display_id : keyword-only 

319 The id of the display to update 

320 

321 See Also 

322 -------- 

323 :func:`display` 

324 """ 

325 kwargs['update'] = True 

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

327 

328 

329class DisplayHandle(object): 

330 """A handle on an updatable display 

331 

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

333 

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

335 and update existing instances. 

336 

337 See Also 

338 -------- 

339 

340 :func:`display`, :func:`update_display` 

341 

342 """ 

343 

344 def __init__(self, display_id=None): 

345 if display_id is None: 

346 display_id = _new_id() 

347 self.display_id = display_id 

348 

349 def __repr__(self): 

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

351 

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

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

354 

355 Parameters 

356 ---------- 

357 obj 

358 object to display 

359 **kwargs 

360 additional keyword arguments passed to display 

361 """ 

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

363 

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

365 """Update existing displays with my id 

366 

367 Parameters 

368 ---------- 

369 obj 

370 object to display 

371 **kwargs 

372 additional keyword arguments passed to update_display 

373 """ 

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

375 

376 

377def clear_output(wait=False): 

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

379 

380 Parameters 

381 ---------- 

382 wait : bool [default: false] 

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

384 from IPython.core.interactiveshell import InteractiveShell 

385 if InteractiveShell.initialized(): 

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

387 else: 

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

389 sys.stdout.flush() 

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

391 sys.stderr.flush()