18
18
from sparkmagic .utils .utils import parse_argstring_or_throw , get_coerce_value , initialize_auth , Namespace
19
19
from sparkmagic .utils .sparkevents import SparkEvents
20
20
from sparkmagic .utils .constants import LANGS_SUPPORTED
21
+ from sparkmagic .utils .dataframe_parser import cell_contains_dataframe , CellOutputHtmlParser
21
22
from sparkmagic .livyclientlib .command import Command
22
23
from sparkmagic .livyclientlib .endpoint import Endpoint
23
- from sparkmagic .magics .sparkmagicsbase import SparkMagicBase
24
+ from sparkmagic .magics .sparkmagicsbase import SparkMagicBase , SparkOutputHandler
24
25
from sparkmagic .livyclientlib .exceptions import handle_expected_exceptions , wrap_unexpected_exceptions , \
25
26
BadUserDataException
26
27
@@ -57,6 +58,7 @@ def __init__(self, shell, data=None, spark_events=None):
57
58
self .language = u""
58
59
self .endpoint = None
59
60
self .fatal_error = False
61
+ self .allow_retry_fatal = False
60
62
self .fatal_error_message = u""
61
63
if spark_events is None :
62
64
spark_events = SparkEvents ()
@@ -153,6 +155,11 @@ def help(self, line, cell="", local_ns=None):
153
155
</ul>
154
156
</td>
155
157
</tr>
158
+ <tr>
159
+ <td>pretty</td>
160
+ <td>%%pretty</td>
161
+ <td>If the cell output is a dataframe, like <code>df.show()</code>, then it will pretty print the dataframe as an HTML table</td>
162
+ </tr>
156
163
</table>
157
164
"""
158
165
self .ipython_display .html (help_html )
@@ -258,14 +265,36 @@ def configure(self, line, cell="", local_ns=None):
258
265
@wrap_unexpected_exceptions
259
266
@handle_expected_exceptions
260
267
def spark (self , line , cell = "" , local_ns = None ):
261
- if self ._do_not_call_start_session (u"" ):
262
- args = parse_argstring_or_throw ( self . spark , line )
268
+ if not self ._do_not_call_start_session (u"" ):
269
+ return
263
270
264
- coerce = get_coerce_value (args .coerce )
271
+ args = parse_argstring_or_throw (self .spark , line )
272
+
273
+ coerce = get_coerce_value (args .coerce )
274
+
275
+ self .execute_spark (cell , args .output , args .samplemethod , args .maxrows , args .samplefraction , None , coerce )
276
+
277
+ @cell_magic
278
+ @needs_local_scope
279
+ @wrap_unexpected_exceptions
280
+ @handle_expected_exceptions
281
+ def pretty (self , line , cell = "" , local_ns = None ):
282
+ """Evaluates a cell and converts dataframes in cell output to HTML tables."""
283
+ if not self ._do_not_call_start_session (u"" ):
284
+ return
285
+
286
+ def pretty_output_handler (out ):
287
+ if cell_contains_dataframe (out ):
288
+ self .ipython_display .html (CellOutputHtmlParser .to_html (out ))
289
+ else :
290
+ self .ipython_display .write (out )
291
+
292
+ so = SparkOutputHandler (html = self .ipython_display .html ,
293
+ text = pretty_output_handler ,
294
+ default = self .ipython_display .display )
295
+
296
+ self .execute_spark (cell , None , None , None , None , None , None , output_handler = so )
265
297
266
- self .execute_spark (cell , args .output , args .samplemethod , args .maxrows , args .samplefraction , None , coerce )
267
- else :
268
- return
269
298
270
299
@magic_arguments ()
271
300
@cell_magic
@@ -282,15 +311,15 @@ def spark(self, line, cell="", local_ns=None):
282
311
@wrap_unexpected_exceptions
283
312
@handle_expected_exceptions
284
313
def sql (self , line , cell = "" , local_ns = None ):
285
- if self ._do_not_call_start_session ("" ):
286
- args = parse_argstring_or_throw ( self . sql , line )
314
+ if not self ._do_not_call_start_session ("" ):
315
+ return
287
316
288
- coerce = get_coerce_value ( args . coerce )
317
+ args = parse_argstring_or_throw ( self . sql , line )
289
318
290
- return self . execute_sqlquery ( cell , args .samplemethod , args . maxrows , args . samplefraction ,
291
- None , args . output , args . quiet , coerce )
292
- else :
293
- return
319
+ coerce = get_coerce_value ( args .coerce )
320
+
321
+ return self . execute_sqlquery ( cell , args . samplemethod , args . maxrows , args . samplefraction ,
322
+ None , args . output , args . quiet , coerce )
294
323
295
324
@magic_arguments ()
296
325
@cell_magic
@@ -347,17 +376,19 @@ def _do_not_call_start_session(self, line, cell="", local_ns=None):
347
376
# No need to add the handle_expected_exceptions decorator to this since we manually catch all
348
377
# exceptions when starting the session.
349
378
350
- if self .fatal_error :
379
+ if self .fatal_error and not self . allow_retry_fatal :
351
380
self .ipython_display .send_error (self .fatal_error_message )
352
381
return False
353
382
354
383
if not self .session_started :
355
384
skip = False
356
385
properties = conf .get_session_properties (self .language )
357
- self .session_started = True
358
386
359
387
try :
360
388
self .spark_controller .add_session (self .session_name , self .endpoint , skip , properties )
389
+ self .session_started = True
390
+ self .fatal_error = False
391
+ self .fatal_error_message = u""
361
392
except Exception as e :
362
393
self .fatal_error = True
363
394
self .fatal_error_message = conf .fatal_error_suggestion ().format (e )
@@ -371,6 +402,11 @@ def _do_not_call_start_session(self, line, cell="", local_ns=None):
371
402
372
403
return self .session_started
373
404
405
+ @cell_magic
406
+ def _do_not_call_allow_retry_fatal (self , line , cell = "" , local_ns = None ):
407
+ # enable the flag to retry session creation
408
+ self .allow_retry_fatal = True
409
+
374
410
@cell_magic
375
411
@handle_expected_exceptions
376
412
def _do_not_call_delete_session (self , line , cell = "" , local_ns = None ):
0 commit comments