From b82bf127f86f9b43498fc04713023a5e8393e25b Mon Sep 17 00:00:00 2001 From: John Miller Date: Wed, 27 Nov 2019 20:38:40 -0700 Subject: [PATCH] New commands for setting matplotlib configuration. See new functions `ein:pytools-set-figure-dpi', `ein:pytools-set-matplotlib-parameter'. Added some tests as well. --- features/ob-ein.feature | 2 +- features/step-definitions/ein-steps.el | 2 +- lisp/ein-pytools.el | 34 ++++++++++++++++++++++- lisp/ein_remote_safe.py | 37 ++++++++++++++++++++++---- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/features/ob-ein.feature b/features/ob-ein.feature index 4b2a890..2f6007c 100644 --- a/features/ob-ein.feature +++ b/features/ob-ein.feature @@ -115,7 +115,7 @@ Scenario: Specific port, portless localhost refers to same, concurrent execution @org @complete @skip-travis Scenario: Completion in an anonymous source block Given I set "ein:completion-backend" to eval "(quote ein:use-company-backend)" - Given I eval "(global-company-mode +1)" + Given I eval (global-company-mode +1) Given I stop the server When I open temp file "complete.org" And I call "org-mode" diff --git a/features/step-definitions/ein-steps.el b/features/step-definitions/ein-steps.el index f3728d2..2bfea7f 100644 --- a/features/step-definitions/ein-steps.el +++ b/features/step-definitions/ein-steps.el @@ -425,7 +425,7 @@ (lambda (variable value) (set (intern variable) (eval (car (read-from-string value)))))) -(When "^I eval \"\\(.+\\)\"$" +(When "^I eval \\(.+\\)$" (lambda (expr) (eval (car (read-from-string expr))))) diff --git a/lisp/ein-pytools.el b/lisp/ein-pytools.el index 7c2dcfd..baac9a7 100644 --- a/lisp/ein-pytools.el +++ b/lisp/ein-pytools.el @@ -31,6 +31,7 @@ (require 'ein-kernel) (require 'ein-notebook) +(require 'ein-shared-output) (defun ein:goto-file (filename lineno &optional other-window) "Jump to file FILEAME at line LINENO. @@ -410,9 +411,40 @@ Currently EIN/IPython supports exporting to the following formats: "Set the default figure size for matplotlib figures. Works by setting `rcParams['figure.figsize']`." (interactive "nWidth: \nnHeight: ") (ein:shared-output-eval-string (ein:get-kernel) - (format "__ein_set_figure_size(%s,%s)" width height) + (format "__ein_set_figure_size('[%s, %s]')" width height) nil)) +(defun ein:pytools-set-figure-dpi (dpi) + "Set the default figure dpi for matplotlib figures. Works by setting `rcParams['figure.figsize']`." + (interactive "nFigure DPI: ") + (ein:shared-output-eval-string (ein:get-kernel) + (format "__ein_set_figure_dpi('%s')" dpi) + nil)) + +(defun ein:pytools-set-matplotlib-parameter (param value) + "Generically set any matplotlib parameter exposed in the matplotlib.pyplot.rcParams variable. Value is evaluated as a Python expression, so be careful of side effects." + (interactive + (list (completing-read "Parameter: " (ein:pytools--get-matplotlib-params) nil t) + (read-string "Value: " nil))) + (let* ((split (cl-position ?. param)) + (family (cl-subseq param 0 split)) + (setting (cl-subseq param (1+ split)))) + (ein:shared-output-eval-string (ein:get-kernel) + (format "__ein_set_matplotlib_param('%s', '%s', '%s')" family setting value) + nil))) + +(defun ein:pytools--get-matplotlib-params () + (ein:shared-output-eval-string (ein:get-kernel) + (format "__ein_get_matplotlib_params()") + nil) + (with-current-buffer (ein:shared-output-create-buffer) + (ein:wait-until #'(lambda () + (slot-value (slot-value *ein:shared-output* :cell) :outputs)) + nil + 5.0) + (let ((outputs (first (slot-value (slot-value *ein:shared-output* :cell) :outputs)))) + (ein:json-read-from-string (plist-get outputs :text))))) + (provide 'ein-pytools) ;;; ein-pytools.el ends here diff --git a/lisp/ein_remote_safe.py b/lisp/ein_remote_safe.py index ba148f1..2207b0d 100644 --- a/lisp/ein_remote_safe.py +++ b/lisp/ein_remote_safe.py @@ -20,6 +20,14 @@ along with ein.py. If not, see . """ +__ein_pytools_version = "1.0.0" + +try: + from matplotlib import rc as __ein_rc + from matplotlib import rcParams as __ein_rcParams + __ein_matplotlib_available = True +except ImportError: + __ein_matplotlib_available = False def __ein_export_nb(nb_json, format): import IPython.nbconvert as nbconvert @@ -61,13 +69,32 @@ try: except ImportError: __ein_find_edit_target = __ein_find_edit_target_012 -def __ein_set_figure_size(*dim): - try: - from matplotlib.pyplot import rcParams - rcParams['figure.figsize'] = dim - except: + +def __ein_set_matplotlib_param(family, setting, value): + settings = {} + if __ein_matplotlib_available: + settings[setting] = eval(value) + __ein_rc(family, **settings) + else: raise RuntimeError("Matplotlib not installed in this instance of python!") + +def __ein_set_figure_size(dim): + __ein_set_matplotlib_param('figure', 'figsize', dim) + + +def __ein_set_figure_dpi(dpi): + __ein_set_matplotlib_param('figure', 'dpi', dpi) + + +def __ein_get_matplotlib_params(): + if __ein_matplotlib_available: + import json + print(json.dumps([k for k in __ein_rcParams.keys()])) + else: + raise RuntimeError("Matplotlib not installed in this instance of python!") + + def __ein_find_source(name): """Given an object as string, `name`, print its place in source code.""" # FIXME: use JSON display object instead of stdout