Skip to content

Commit

Permalink
threejs: access files through features, for simpler configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
tornaria committed Jan 15, 2024
1 parent 7cecbff commit 7dfff8b
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/sage/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st
JMOL_DIR = var("JMOL_DIR")
MATHJAX_DIR = var("MATHJAX_DIR", join(SAGE_SHARE, "mathjax"))
MTXLIB = var("MTXLIB", join(SAGE_SHARE, "meataxe"))
THREEJS_DIR = var("THREEJS_DIR", join(SAGE_SHARE, "threejs-sage"))
THREEJS_DIR = var("THREEJS_DIR")
PPLPY_DOCS = var("PPLPY_DOCS", join(SAGE_SHARE, "doc", "pplpy"))
MAXIMA = var("MAXIMA", "maxima")
MAXIMA_FAS = var("MAXIMA_FAS")
Expand Down
64 changes: 64 additions & 0 deletions src/sage/features/threejs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import os

from . import StaticFile


class Threejs(StaticFile):
r"""
A :class:`~sage.features.Feature` which describes the presence of
threejs-sage in a few standard locations.
EXAMPLES::
sage: from sage.features.threejs import Threejs
sage: bool(Threejs().is_present()) # needs threejs
True
"""

def __init__(self):
r"""
TESTS::
sage: from sage.features.threejs import Threejs
sage: isinstance(Threejs(), Threejs)
True
"""
from sage.env import SAGE_SHARE, THREEJS_DIR

version = self.required_version()

threejs_search_path = THREEJS_DIR or (
os.path.join(SAGE_SHARE, "jupyter", "nbextensions", "threejs-sage"),
os.path.join(SAGE_SHARE, "sagemath", "threejs-sage"),
os.path.join(SAGE_SHARE, "sage", "threejs"),
os.path.join(SAGE_SHARE, "threejs-sage")
)

StaticFile.__init__(
self, name="threejs",
filename=os.path.join(version, "three.min.js"),
spkg="threejs",
type="standard",
search_path=threejs_search_path,
description="JavaScript library to display 3D graphics")

def required_version(self):
"""
Return the version of threejs that Sage requires.
EXAMPLES::
sage: from sage.features.threejs import Threejs
sage: Threejs().required_version()
'r...'
"""
from sage.env import SAGE_EXTCODE

filename = os.path.join(SAGE_EXTCODE, 'threejs', 'threejs-version.txt')

with open(filename) as f:
return f.read().strip()


def all_features():
return [Threejs()]
7 changes: 5 additions & 2 deletions src/sage/repl/ipython_kernel/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
SAGE_EXTCODE,
SAGE_VENV,
SAGE_VERSION,
THREEJS_DIR,
)


Expand Down Expand Up @@ -123,14 +122,18 @@ def use_local_threejs(self):
EXAMPLES::
sage: # needs threejs
sage: from sage.repl.ipython_kernel.install import SageKernelSpec
sage: spec = SageKernelSpec(prefix=tmp_dir())
sage: spec.use_local_threejs()
sage: threejs = os.path.join(spec.nbextensions_dir, 'threejs-sage')
sage: os.path.isdir(threejs)
True
"""
src = THREEJS_DIR
from sage.features.threejs import Threejs
if not Threejs().is_present():
return
src = os.path.dirname(os.path.dirname(Threejs().absolute_filename()))
dst = os.path.join(self.nbextensions_dir, 'threejs-sage')
self.symlink(src, dst)

Expand Down
15 changes: 9 additions & 6 deletions src/sage/repl/rich_output/backend_ipython.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,15 +409,18 @@ def threejs_offline_scripts(self):
EXAMPLES::
sage: # needs threejs
sage: from sage.repl.rich_output.backend_ipython import BackendIPythonCommandline
sage: backend = BackendIPythonCommandline()
sage: backend.threejs_offline_scripts() # needs sage.plot
sage: backend.threejs_offline_scripts()
'...<script ...</script>...'
"""
from sage.env import THREEJS_DIR
from sage.repl.rich_output.display_manager import _required_threejs_version
from sage.features.threejs import Threejs

if not Threejs().is_present():
return ''

script = os.path.join(THREEJS_DIR, '{}/three.min.js'.format(_required_threejs_version()))
script = Threejs().absolute_filename()

return '\n<script src="{0}"></script>'.format(script)

Expand Down Expand Up @@ -596,12 +599,12 @@ def threejs_offline_scripts(self):
'...<script src="/nbextensions/threejs-sage/r.../three.min.js...<\\/script>...'
"""
from sage.repl.rich_output import get_display_manager
from sage.repl.rich_output.display_manager import _required_threejs_version
from sage.features.threejs import Threejs
CDN_script = get_display_manager().threejs_scripts(online=True)
CDN_script = CDN_script.replace('</script>', r'<\/script>').replace('\n', ' \\\n')
return """
<script src="/nbextensions/threejs-sage/{}/three.min.js"></script>
<script>
if ( !window.THREE ) document.write('{}');
</script>
""".format(_required_threejs_version(), CDN_script)
""".format(Threejs().required_version(), CDN_script)
19 changes: 2 additions & 17 deletions src/sage/repl/rich_output/display_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,6 @@
from sage.repl.rich_output.preferences import DisplayPreferences


def _required_threejs_version():
"""
Return the version of threejs that Sage requires.
EXAMPLES::
sage: from sage.repl.rich_output.display_manager import _required_threejs_version
sage: _required_threejs_version() # needs sage.plot
'r...'
"""
import os
import sage.env
with open(os.path.join(sage.env.SAGE_EXTCODE, 'threejs', 'threejs-version.txt')) as f:
return f.read().strip()


class DisplayException(Exception):
"""
Base exception for all rich output-related exceptions.
Expand Down Expand Up @@ -768,8 +752,9 @@ def threejs_scripts(self, online):
ValueError: current backend does not support
offline threejs graphics
"""
from sage.features.threejs import Threejs
if online:
version = _required_threejs_version()
version = Threejs().required_version()
return """
<script src="https://cdn.jsdelivr.net/gh/sagemath/threejs-sage@{0}/build/three.min.js"></script>
""".format(version)
Expand Down

0 comments on commit 7dfff8b

Please sign in to comment.