Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attributes bitset #2

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions pymathics/asy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,55 @@
import os

from pymathics.asy.version import __version__
from pymathics.asy.exportasy import (ExportToJPG,
ExportToPNG,
ExportToSVG,
ExportToPDF)
from pymathics.asy.graphics import (AsyGraphicsBox)
from pymathics.asy.exportasy import ExportToJPG, ExportToPNG, ExportToSVG, ExportToPDF
from pymathics.asy.graphics import AsyGraphicsBox
from mathics.core.expression import Expression, String, SymbolTrue
from mathics.core.evaluation import Evaluation
from mathics.builtin.files_io.importexport import Export as MathicsExport
__all__ = ("__version__", "ExportToJPG", "ExportToPNG", "ExportToSVG", "ExportToPDF",
"AsyGraphicsBox", "pymathics_version_data", "asy_path")

__all__ = (
"__version__",
"ExportToJPG",
"ExportToPNG",
"ExportToSVG",
"ExportToPDF",
"AsyGraphicsBox",
"pymathics_version_data",
"asy_path",
)

ROOT_DIR = pkg_resources.resource_filename('pymathics.asy', '')

ROOT_DIR = pkg_resources.resource_filename("pymathics.asy", "")

import shutil

try:
asy_path = shutil.which("asy")
print("asy found in ", asy_path)
except:
print("asy path couldn't be found. Set to asy")
asy_path = "asy"


def onload(definitions):
# from mathics.builtin import box_constructs
# box_constructs["System`GraphicsBox"] = AsyGraphicsBox(expression=False)
# box_constructs["System`Graphics3DBox"] = AsyGraphics3DBox(expression=False)
# from mathics.builtin import box_constructs
# box_constructs["System`GraphicsBox"] = AsyGraphicsBox(expression=False)
# box_constructs["System`Graphics3DBox"] = AsyGraphics3DBox(expression=False)
MathicsExport._extdict["pdf"] = "PDF"
definitions.set_ownvalue("Settings`UseAsyForGraphics2D", SymbolTrue)
for root, dirs, files in os.walk(os.path.join(ROOT_DIR, "autoload")):
for path in [os.path.join(root, f) for f in files if f.endswith(".m")]:
Expression("Get", String(path)).evaluate(Evaluation(definitions))


# To be recognized as an external mathics module, the following variable
# is required:
#




pymathics_version_data = {
"author": "The Mathics Team",
"version": __version__,
"requires": [],
"onload" : onload
"onload": onload,
}
3 changes: 0 additions & 3 deletions pymathics/asy/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
# -*- coding: utf-8 -*-
from mathics.builtin.base import Builtin, String



63 changes: 37 additions & 26 deletions pymathics/asy/exportasy.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,67 +11,76 @@
import tempfile
import os
from subprocess import DEVNULL, STDOUT, check_call
from mathics.core.expression import (Expression, String, BoxError, SymbolFailed, SymbolNull)
from mathics.core.expression import (
Expression,
String,
BoxError,
SymbolFailed,
SymbolNull,
)
from mathics_scanner import replace_wl_with_plain_text
from mathics.builtin.drawing.image import Image
from mathics.builtin import Builtin
from mathics.core.attributes import hold_rest, protected


class _AsyExporter(Builtin):
attributes = ("HoldRest", )
attributes = hold_rest | protected

messages = {"boxerr": "Not able to interpret box `1`",
"nowrtacs": "ExportToPDF requires write access.",
"asyfld" : "Asymptote failed to generate the file",
messages = {
"boxerr": "Not able to interpret box `1`",
"nowrtacs": "ExportToPDF requires write access.",
"asyfld": "Asymptote failed to generate the file",
}

extension = None

def apply_asy(self, filename, expr, evaluation, **options):
'%(name)s[filename_String, expr_, OptionsPattern[%(name)s]]'
"%(name)s[filename_String, expr_, OptionsPattern[%(name)s]]"

if expr.get_head_name() == "System`Image":
res = Expression("System`ImageExport", filename, expr)
res = Expression("System`ImageExport", filename, expr)
return res.evaluate(evaluation)

filename = filename.value
if expr.get_head_name() not in ("System`Graphics", "System`Graphics3D"):
expr = Expression("Text", expr)
expr = Expression("Graphics",
Expression("List",
expr)
)
expr = Expression("Graphics", Expression("List", expr))

asy_code = Expression("MakeBoxes", expr).evaluate(evaluation)
try:
asy_code = asy_code.boxes_to_tex(evaluation=evaluation)
except BoxError as e:
evaluation.message(self.get_name(),"boxerr", e.box)
evaluation.message(self.get_name(), "boxerr", e.box)
return SymbolFailed

asy_code = asy_code[13:-10]
asy_code = replace_wl_with_plain_text(asy_code, False)
# TODO: Handle properly WL characters to latex commands
asy_code = asy_code.replace("\\[DifferentialD]", "d ")
fin = os.path.join(tempfile._get_default_tempdir(),
next(tempfile._get_candidate_names()))
fin = os.path.join(
tempfile._get_default_tempdir(), next(tempfile._get_candidate_names())
)
from pymathics.asy import asy_path

try:
with open(fin, 'w+') as borrador:
with open(fin, "w+") as borrador:
borrador.write(asy_code)
except:
evaluation.message(self.get_name(),"nowrtacs")
evaluation.message(self.get_name(), "nowrtacs")
return SymbolFailed
if self.extension == "svg":
cmdline = [asy_path, '-f', self.extension,
'--svgemulation' ,
'-o',
filename,
fin]
cmdline = [
asy_path,
"-f",
self.extension,
"--svgemulation",
"-o",
filename,
fin,
]
else:
cmdline = [asy_path, '-f', self.extension,
'-o',
filename,
fin]
cmdline = [asy_path, "-f", self.extension, "-o", filename, fin]
try:
check_call(cmdline, stdout=DEVNULL, stderr=DEVNULL)
except:
Expand All @@ -91,6 +100,7 @@ class ExportToSVG(_AsyExporter):
Then, from the asy set of instructions, a pdf is built
</dl>
"""

extension = "svg"
context = "System`Convert`TextDump`"

Expand Down Expand Up @@ -122,6 +132,7 @@ class ExportToPNG(_AsyExporter):
Then, from the asy set of instructions, a pdf is built
</dl>
"""

extension = "png"
context = "System`Convert`Image`"

Expand All @@ -137,6 +148,6 @@ class ExportToJPG(_AsyExporter):
Then, from the asy set of instructions, a pdf is built
</dl>
"""

extension = "jpeg"
context = "System`Convert`Image`"

71 changes: 40 additions & 31 deletions pymathics/asy/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import numbers



from mathics.builtin.base import (
Builtin,
InstanceableBuiltin,
Expand All @@ -37,26 +36,30 @@
from_python,
)

from mathics.builtin.graphics import (GRAPHICS_OPTIONS,
GraphicsBox,
Graphics,
asy_number,
RGBColor)
from mathics.builtin.graphics import (
GRAPHICS_OPTIONS,
GraphicsBox,
Graphics,
asy_number,
RGBColor,
)

from mathics.formatter.asy import asy_create_pens
from mathics.builtin.drawing.graphics3d import Graphics3D, Graphics3DElements

from mathics.core.attributes import hold_all, protected, read_protected


class AsyGraphicsBox(GraphicsBox):
context="System`"
context = "System`"
options = Graphics.options
_graphics = Graphics(expression=False)
attributes = ("HoldAll", "ReadProtected")
attributes = hold_all | protected | read_protected

messages = {
"asynotav": 'Asymptote is not available in this system. Using the buggy backend.',
"noasyfile": 'Asy requires write permisions over a temporary file, but it was not available. Using the buggy backend',
"asyfail": 'Asymptote failed building the svg picture. Using the buggy backend.',
"asynotav": "Asymptote is not available in this system. Using the buggy backend.",
"noasyfile": "Asy requires write permisions over a temporary file, but it was not available. Using the buggy backend",
"asyfail": "Asymptote failed building the svg picture. Using the buggy backend.",
}

def apply_makeboxes(self, content, evaluation, options):
Expand All @@ -82,8 +85,8 @@ def boxes_to_tex(self, leaves=None, **options):
endline = widthheight.find("\n")
widthheight = widthheight[:endline]
width, height = widthheight.split(",")
width = float(width[:-2])*60
height = float(height[:-4])*60
width = float(width[:-2]) * 60
height = float(height[:-4]) * 60
return (tex, width, height)

def boxes_to_mathml(self, leaves=None, **options):
Expand All @@ -92,27 +95,34 @@ def boxes_to_mathml(self, leaves=None, **options):
evaluation = options.get("evaluation", None)
check_asy = False
if evaluation:
check_asy = evaluation.definitions.get_ownvalue("Settings`UseAsyForGraphics2D")
check_asy = evaluation.definitions.get_ownvalue(
"Settings`UseAsyForGraphics2D"
)
if check_asy:
check_asy = check_asy.replace.is_true()
if check_asy:
import os
from subprocess import DEVNULL, STDOUT, check_call
from pymathics.asy import asy_path
import tempfile

try:
check_call([asy_path, '--version'], stdout=DEVNULL, stderr=DEVNULL)
check_call([asy_path, "--version"], stdout=DEVNULL, stderr=DEVNULL)
except:
check_asy = False
evaluation.message("AsyGraphicsBox", "asynotav")
Expression("Set", Symbol("Settings`UseAsyForGraphics2D"), SymbolFalse).evaluate(evaluation)
Expression(
"Set", Symbol("Settings`UseAsyForGraphics2D"), SymbolFalse
).evaluate(evaluation)

if check_asy:
asy, width, height = self.boxes_to_tex(leaves, forxml=True, **options)
fin = os.path.join(tempfile._get_default_tempdir(), next(tempfile._get_candidate_names()))
fin = os.path.join(
tempfile._get_default_tempdir(), next(tempfile._get_candidate_names())
)
fout = fin + ".png"
try:
with open(fin, 'w+') as borrador:
with open(fin, "w+") as borrador:
borrador.write(asy)
except:
evaluation.message("AsyGraphicsBox", "noasyfile")
Expand All @@ -121,26 +131,25 @@ def boxes_to_mathml(self, leaves=None, **options):
if check_asy:
try:
# check_call(['asy', '-f', 'svg', '--svgemulation' ,'-o', fout, fin], stdout=DEVNULL, stderr=DEVNULL)
check_call([asy_path, '-f', 'png', '-render', '16', '-o', fout, fin], stdout=DEVNULL, stderr=DEVNULL)
check_call(
[asy_path, "-f", "png", "-render", "16", "-o", fout, fin],
stdout=DEVNULL,
stderr=DEVNULL,
)
except:
evaluation.message("AsyGraphicsBox", "asyfail")
check_asy = False

if check_asy:
with open(fout, 'rb') as ff:
with open(fout, "rb") as ff:
png = ff.read()

return (
'''
<mglyph width="%d" height="%d" src="data:image/png;base64,%s"/></mglyph>'''
% (
int(width),
int(height),
base64.b64encode(png).decode("utf8"),
# base64.b64encode(svg.encode("utf8")).decode("utf8"),
)
return """
<mglyph width="%d" height="%d" src="data:image/png;base64,%s"/></mglyph>""" % (
int(width),
int(height),
base64.b64encode(png).decode("utf8"),
# base64.b64encode(svg.encode("utf8")).decode("utf8"),
)
# Not using asymptote. Continue with the buggy backend...
return super(AsyGraphicsBox, self).boxes_to_mathml(leaves=leaves, **options)


2 changes: 1 addition & 1 deletion pymathics/asy/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
# This file is suitable for sourcing inside POSIX shell as
# well as importing into Python. That's why there is no
# space around "=" below.
__version__="1.0.0"
__version__ = "1.0.0"
4 changes: 1 addition & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
version=__version__,
packages=find_namespace_packages(include=["pymathics.asy.*"]),
install_requires=["mathics3>=1.1.0"],
package_data = {"pymathics-asy": ["autoload/formats/*/Export.m"]},
package_data={"pymathics-asy": ["autoload/formats/*/Export.m"]},
# don't pack Mathics in egg because of media files, etc.
zip_safe=False,
# metadata for upload to PyPI
Expand All @@ -53,5 +53,3 @@


# Install autoload path


1 change: 1 addition & 0 deletions test/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
session = MathicsSession(add_builtin=True, catch_interrupt=False)
# session.evaluate('LoadModule["pymathics.asy"]')


def check_evaluation(str_expr: str, str_expected: str, message=""):
"""Helper function to test that a WL expression against
its results"""
Expand Down
3 changes: 2 additions & 1 deletion test/test_asy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


import shutil

try:
asy_path = shutil.which("asy")
print("asy found in ", asy_path)
Expand All @@ -16,7 +17,7 @@

def test_asycmd():
try:
assert os.system(asy_path +" -version") == 0
assert os.system(asy_path + " -version") == 0
except:
print("path=", asy_path)
assert False
Loading