script.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. """Generic script exporter class for any kernel language"""
  2. # Copyright (c) Jupyter Development Team.
  3. # Distributed under the terms of the Modified BSD License.
  4. import sys
  5. if sys.version_info < (3, 10):
  6. from importlib_metadata import entry_points # type:ignore[import-not-found]
  7. else:
  8. from importlib.metadata import entry_points
  9. from traitlets import Dict, default
  10. from .base import get_exporter
  11. from .templateexporter import TemplateExporter
  12. class ScriptExporter(TemplateExporter):
  13. """A script exporter."""
  14. # Caches of already looked-up and instantiated exporters for delegation:
  15. _exporters = Dict()
  16. _lang_exporters = Dict()
  17. export_from_notebook = "Script"
  18. @default("template_file")
  19. def _template_file_default(self):
  20. return "script.j2"
  21. @default("template_name")
  22. def _template_name_default(self):
  23. return "script"
  24. def _get_language_exporter(self, lang_name):
  25. """Find an exporter for the language name from notebook metadata.
  26. Uses the nbconvert.exporters.script group of entry points.
  27. Returns None if no exporter is found.
  28. """
  29. if lang_name not in self._lang_exporters:
  30. try:
  31. exporters = entry_points(group="nbconvert.exporters.script")
  32. exporter = [e for e in exporters if e.name == lang_name][0].load() # noqa: RUF015
  33. except (KeyError, IndexError):
  34. self._lang_exporters[lang_name] = None
  35. else:
  36. # TODO: passing config is wrong, but changing this revealed more complicated issues
  37. self._lang_exporters[lang_name] = exporter(config=self.config, parent=self)
  38. return self._lang_exporters[lang_name]
  39. def from_notebook_node(self, nb, resources=None, **kw):
  40. """Convert from notebook node."""
  41. langinfo = nb.metadata.get("language_info", {})
  42. # delegate to custom exporter, if specified
  43. exporter_name = langinfo.get("nbconvert_exporter")
  44. if exporter_name and exporter_name != "script":
  45. self.log.debug("Loading script exporter: %s", exporter_name)
  46. if exporter_name not in self._exporters:
  47. exporter = get_exporter(exporter_name)
  48. # TODO: passing config is wrong, but changing this revealed more complicated issues
  49. self._exporters[exporter_name] = exporter(config=self.config, parent=self)
  50. exporter = self._exporters[exporter_name]
  51. return exporter.from_notebook_node(nb, resources, **kw)
  52. # Look up a script exporter for this notebook's language
  53. lang_name = langinfo.get("name")
  54. if lang_name:
  55. self.log.debug("Using script exporter for language: %s", lang_name)
  56. exporter = self._get_language_exporter(lang_name)
  57. if exporter is not None:
  58. return exporter.from_notebook_node(nb, resources, **kw)
  59. # Fall back to plain script export
  60. self.file_extension = langinfo.get("file_extension", ".txt")
  61. self.output_mimetype = langinfo.get("mimetype", "text/plain")
  62. return super().from_notebook_node(nb, resources, **kw)