From 1da8d5f35fb9009af3bded259f47e3ae07b26fd9 Mon Sep 17 00:00:00 2001 From: James Thomas Date: Tue, 11 Apr 2023 19:29:29 +0530 Subject: [PATCH] Add Matplotlib support in the standard interpreter * comint-mime.py (__COMINT_MIME_setup): Add Matplotlib backend module and loader. --- comint-mime.py | 100 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/comint-mime.py b/comint-mime.py index d55698c..6c7425c 100644 --- a/comint-mime.py +++ b/comint-mime.py @@ -1,12 +1,16 @@ # This file is part of https://github.com/astoff/comint-mime def __COMINT_MIME_setup(types): + ipython = False try: ipython = get_ipython() assert ipython except: - print("`comint-mime' error: IPython is required") - return + try: + from matplotlib import _api + except: + print("`comint-mime' error: IPython or Matplotlib is required") + return from base64 import encodebytes from functools import partial @@ -21,19 +25,6 @@ def __COMINT_MIME_setup(types): SIZE_LIMIT = 4000 - MIME_TYPES = { - "image/png": encoding_workaround, - "image/jpeg": encoding_workaround, - "text/latex": str.encode, - "text/html": str.encode, - "application/json": lambda d: to_json(d).encode(), - } - - if types == "all": - types = MIME_TYPES - else: - types = types.split(";") - def print_osc(type, encoder, data, meta): meta = meta or {} if encoder: @@ -48,14 +39,75 @@ def __COMINT_MIME_setup(types): payload = encodebytes(data).decode() print(f"\033]5151;{header}\n{payload}\033\\") - ipython.enable_matplotlib("inline") - ipython.display_formatter.active_types = list(MIME_TYPES.keys()) - for mime, encoder in MIME_TYPES.items(): - ipython.display_formatter.formatters[mime].enabled = mime in types - ipython.mime_renderers[mime] = partial(print_osc, mime, encoder) + if ipython: + MIME_TYPES = { + "image/png": encoding_workaround, + "image/jpeg": encoding_workaround, + "text/latex": str.encode, + "text/html": str.encode, + "application/json": lambda d: to_json(d).encode(), + } - if types: - print("`comint-mime' enabled for", - ", ".join(t for t in types if t in MIME_TYPES.keys())) + if types == "all": + types = MIME_TYPES + else: + types = types.split(";") + + ipython.enable_matplotlib("inline") + ipython.display_formatter.active_types = list(MIME_TYPES.keys()) + for mime, encoder in MIME_TYPES.items(): + ipython.display_formatter.formatters[mime].enabled = mime in types + ipython.mime_renderers[mime] = partial(print_osc, mime, encoder) + + if types: + print("`comint-mime' enabled for", + ", ".join(t for t in types if t in MIME_TYPES.keys())) + else: + print("`comint-mime' disabled") else: - print("`comint-mime' disabled") + from importlib.abc import Loader, MetaPathFinder + from importlib.machinery import ModuleSpec + from sys import meta_path + from matplotlib.backend_bases import FigureManagerBase + from matplotlib.backends.backend_agg import FigureCanvasAgg + from matplotlib import use + + class BackendModuleLoader(Loader): + def create_module(self, spec): + return None + def exec_module(self, module): + from io import BytesIO + from base64 import encodebytes + from json import dumps as to_json + from pathlib import Path + + class FigureCanvasEmacsComintMime(FigureCanvasAgg): + manager_class = _api.classproperty(lambda cls: FigureManagerEmacsComintMime) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + class FigureManagerEmacsComintMime(FigureManagerBase): + + def __init__(self, canvas, num): + super().__init__(canvas, num) + + def show(self): + self.canvas.figure.draw_without_rendering() + buf = BytesIO() + self.canvas.print_png(buf) + print_osc("image/png", encoding_workaround, buf.getvalue(), None) + + module.FigureCanvas = FigureCanvasEmacsComintMime + module.FigureManager = FigureManagerEmacsComintMime + + class BackendModuleFinder(MetaPathFinder): + def find_spec(self, fullname, path, target=None): + if fullname == 'emacscomintmime': + return ModuleSpec(fullname, BackendModuleLoader()) + else: + return None + + meta_path.append(BackendModuleFinder()) + use("module://emacscomintmime") + print("`comint-mime' enabled for Matplotlib") -- 2.34.1