Skip to content
Merged
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
4 changes: 4 additions & 0 deletions mathics/builtin/box/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ def __new__(cls, *elements, **kwargs):
instance._elements = None
return instance

def __init(self, *args, **kwargs):
super().__init(args, kwargs)
self.boxes = []

def do_format(self, evaluation, format):
return self

Expand Down
39 changes: 24 additions & 15 deletions mathics/builtin/box/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
from abc import ABC
from math import atan2, cos, degrees, pi, sin
from typing import Any, Dict, Optional, Tuple
from typing import Any, Dict, Final, List, Optional, Tuple

from mathics.builtin.box.expression import BoxExpression
from mathics.builtin.colors.color_directives import (
Expand Down Expand Up @@ -43,7 +43,7 @@
SymbolRegularPolygonBox = Symbol("RegularPolygonBox")


class _GraphicsElementBox(BoxExpression, ABC):
class GraphicsElementBox(BoxExpression, ABC):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the underscore was to avoid considering this class as a Builtin to be shown in the documentation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(In WMA this builtin does not exist)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the underscore was to avoid considering this class as a Builtin to be shown in the documentation.

The entire module is marked no-doc. So this should no longer be a reason for having an underscore. In Python, an underscore typically indicates a private class, and this is not private. If it had an underscore previously, that was the wrong way to solve the problem. But at any rate this problem does not exist.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(In WMA this builtin does not exist)

I don't understand what this is getting at. We have many classes in Mathics3 and some built-in function classes that do not exist in WMA.

Copy link
Contributor

@mmatera mmatera Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the underscore was to avoid considering this class as a Builtin to be shown in the documentation.

The entire module is marked no-doc. So this should no longer be a reason for having an underscore. In Python, an underscore typically indicates a private class, and this is not private. If it had an underscore previously, that was the wrong way to solve the problem. But at any rate this problem does not exist.

It should not be loaded as a Built-in symbol. Check what happens in the CLI when you entry

?BoxGraphicsElement

The underscore prevents that this class contribute with a definition. But this is a symptom that this module does not belongs to mathics.builtin.box module.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I get in this branch:

In[1]:= ? GraphicsElementBox
Out[1]= box representation for a graphics element
        
        Attributes[GraphicsElementBox] = {Protected, ReadProtected}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be loaded as a Built-in symbol. Check what happens in the CLI when you entry

?BoxGraphicsElement

I think you mean ?GraphicsElementBox, right?

The underscore prevents that this class contribute with a definition. But this is a symptom that this module does not belongs here.

If it gets renamed with the word Box first, I don't think that will get added as a definition, right? I think that's how BoxExpression works, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be loaded as a Built-in symbol. Check what happens in the CLI when you entry
?BoxGraphicsElement

I think you mean ?GraphicsElementBox, right?

yep

The underscore prevents that this class contribute with a definition. But this is a symptom that this module does not belongs here.

If it gets renamed with the word Box first, I don't think that will get added as a definition, right? I think that's how BoxExpression works, right?

We was very clever if we did that...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it is, it is loaded. But OK, it is not terrible. We can adjust it later.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just looked at the code. What is done to define list DOES_NOT_ADD_BUILTIN_DEFINITION = [...] in the module.

See https://github.com/Mathics3/mathics-core/blob/master/mathics/builtin/forms/base.py#L51

And that is far better than overloading the meaning of underscore at the beginning of a list. I'll add this in there now.

def init(self, graphics, item=None, style={}, opacity=1.0):
if item is not None and not item.has_form(self.get_name(), None):
raise BoxExpressionError
Expand All @@ -53,7 +53,13 @@ def init(self, graphics, item=None, style={}, opacity=1.0):
self.is_completely_visible = False # True for axis elements


class _Polyline(_GraphicsElementBox):
# GraphicsElementBox Builtin class that should not get added as a definition,
# and therefore not added to to external documentation.

DOES_NOT_ADD_BUILTIN_DEFINITION: Final[List[BoxExpression]] = [GraphicsElementBox]


class _Polyline(GraphicsElementBox):
"""
A structure containing a list of line segments
stored in ``self.lines`` created from
Expand Down Expand Up @@ -109,12 +115,12 @@ def extent(self) -> list:
return result


# Note: has to come before _ArcBox
class _RoundBox(_GraphicsElementBox):
# Note: has to come before ArcBox
class RoundBox(GraphicsElementBox):
face_element: Optional[bool] = None

def init(self, graphics, style, item):
super(_RoundBox, self).init(graphics, item, style)
super().init(graphics, item, style)
if len(item.elements) not in (1, 2):
raise BoxExpressionError
self.edge_color, self.face_color = style.get_style(
Expand All @@ -137,7 +143,7 @@ def init(self, graphics, style, item):

def extent(self) -> list:
"""
Compute the bounding box for _RoundBox. Note that
Compute the bounding box for RoundBox. Note that
We handle ellipses here too.
"""
line_width = self.style.get_line_width(face_element=self.face_element) / 2
Expand All @@ -150,7 +156,7 @@ def extent(self) -> list:
return [(x - rx, y - ry), (x - rx, y + ry), (x + rx, y - ry), (x + rx, y + ry)]


class _ArcBox(_RoundBox):
class ArcBox(RoundBox):
def init(self, graphics, style, item):
if len(item.elements) == 3:
arc_expr = item.elements[2]
Expand All @@ -175,7 +181,7 @@ def init(self, graphics, style, item):
item = Expression(Symbol(item.get_head_name()), *item.elements[:2])
else:
self.arc = None
super(_ArcBox, self).init(graphics, style, item)
super().init(graphics, style, item)

def _arc_params(self):
x, y = self.c.pos()
Expand Down Expand Up @@ -214,7 +220,7 @@ def init(self, graphics, style, item=None):
if not item:
raise BoxExpressionError

super(ArrowBox, self).init(graphics, item, style)
super().init(graphics, item, style)

elements = item.elements
if len(elements) == 2:
Expand Down Expand Up @@ -428,7 +434,7 @@ def init(self, graphics, style, item, options):
self.spline_degree = spline_degree.get_int_value()


class CircleBox(_ArcBox):
class CircleBox(ArcBox):
"""
<dl>
<dt>'CircleBox'
Expand All @@ -440,7 +446,7 @@ class CircleBox(_ArcBox):
summary_text = "is the symbol used in boxing 'Circle' expressions"


class DiskBox(_ArcBox):
class DiskBox(ArcBox):
"""
<dl>
<dt>'DiskBox'
Expand Down Expand Up @@ -471,6 +477,9 @@ def init(self, *items, **kwargs):
self.background_color = None
self.tooltip_text: Optional[str] = None
self.evaluation = kwargs.pop("_evaluation", None)
self.boxwidth: int = -1
self.boxheight: int = -1
self.boxes: list = []

@property
def elements(self):
Expand Down Expand Up @@ -500,7 +509,7 @@ def boxes_to_svg(self, elements=None, **options) -> str:
return svg_body


class FilledCurveBox(_GraphicsElementBox):
class FilledCurveBox(GraphicsElementBox):
"""
<dl>
<dt>'FilledCurveBox'
Expand Down Expand Up @@ -580,7 +589,7 @@ def extent(self):
return result


class InsetBox(_GraphicsElementBox):
class InsetBox(GraphicsElementBox):
# We have no documentation for this (yet).
no_doc = True

Expand Down Expand Up @@ -791,7 +800,7 @@ def process_option(self, name, value):
raise BoxExpressionError


class RectangleBox(_GraphicsElementBox):
class RectangleBox(GraphicsElementBox):
# We have no documentation for this (yet).
no_doc = True

Expand Down
12 changes: 6 additions & 6 deletions mathics/builtin/box/graphics3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
from mathics.builtin.box.graphics import (
ArrowBox,
GraphicsBox,
GraphicsElementBox,
LineBox,
PointBox,
PolygonBox,
_GraphicsElementBox,
)
from mathics.builtin.colors.color_directives import Opacity, RGBColor, _ColorObject
from mathics.builtin.drawing.graphics3d import Graphics3D, Style3D
Expand Down Expand Up @@ -75,7 +75,7 @@ def _apply_boxscaling(self, boxscale):
coords.scale(boxscale)


class Cone3DBox(_GraphicsElementBox):
class Cone3DBox(GraphicsElementBox):
# """
# Internal Python class used when Boxing a 'Cone' object.
# """
Expand Down Expand Up @@ -119,7 +119,7 @@ def _apply_boxscaling(self, boxscale):
pass


class Cuboid3DBox(_GraphicsElementBox):
class Cuboid3DBox(GraphicsElementBox):
# """
# Internal Python class used when Boxing a 'Cuboid' object.
# """
Expand Down Expand Up @@ -147,7 +147,7 @@ def _apply_boxscaling(self, boxscale):
pass


class Cylinder3DBox(_GraphicsElementBox):
class Cylinder3DBox(GraphicsElementBox):
# """
# Internal Python class used when Boxing a 'Cylinder' object.
# """
Expand Down Expand Up @@ -271,7 +271,7 @@ def _apply_boxscaling(self, boxscale):
coords.scale(boxscale)


class Sphere3DBox(_GraphicsElementBox):
class Sphere3DBox(GraphicsElementBox):
# summary_text = "box representation for a sphere"

# We have no documentation for this (yet).
Expand Down Expand Up @@ -311,7 +311,7 @@ def _apply_boxscaling(self, boxscale):
pass


class Tube3DBox(_GraphicsElementBox):
class Tube3DBox(GraphicsElementBox):
# summary_text = "box representation for a tube"

# We have no documentation for this (yet).
Expand Down
4 changes: 2 additions & 2 deletions mathics/builtin/box/uniform_polyhedra.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import numbers

from mathics.builtin.box.graphics import _GraphicsElementBox
from mathics.builtin.box.graphics import GraphicsElementBox
from mathics.builtin.colors.color_directives import Opacity, _ColorObject
from mathics.builtin.drawing.graphics3d import Coords3D
from mathics.builtin.drawing.graphics_internals import GLOBALS3D
Expand All @@ -11,7 +11,7 @@
no_doc = True


class UniformPolyhedron3DBox(_GraphicsElementBox):
class UniformPolyhedron3DBox(GraphicsElementBox):
# Let's overwrite the default summary_text here,
# to recover the spaces.
summary_text = "box representation of a 3d uniform polyhedron"
Expand Down
9 changes: 5 additions & 4 deletions mathics/builtin/forms/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Final, List

import mathics.core.definitions as definitions
from mathics.core.builtin import Builtin
from mathics.core.symbols import Symbol
Expand Down Expand Up @@ -44,8 +46,7 @@ def __new__(cls, *args, **kwargs):
return instance


# FormBaseClass is a public Builtin class that
# should not get added as a definition (and therefore not added to
# to external documentation.
# FormBaseClass is a Builtin class that should not get added as a
# definition, and therefore not added to to external documentation.

DOES_NOT_ADD_BUILTIN_DEFINITION = [FormBaseClass]
DOES_NOT_ADD_BUILTIN_DEFINITION: Final[List[Builtin]] = [FormBaseClass]
35 changes: 15 additions & 20 deletions mathics/format/render/__init__.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
"""
Lower-level formatting routines.

Built-in Lower-level formatting includes Asymptote, MathML, SVG,
threejs, and plain text. We hope and expect other formatting to other
kinds backend renderers like matplotlib, can be done by following the
pattern used here.

These routines typically get called in formatting Mathics3 Box objects.
"""Rendering routines.

The higher level *Forms* (e.g. TeXForm, MathMLForm) typically cause
specific formatters to get called, (e.g. latex, mathml). However, the
two concepts and levels are a little bit different. A given From can
cause invoke of several formatters, which the front-end can influence
based on its capabilities and back-end renders available to it.
Mathics3 Built-in rendering includes renderers to Asymptote, MathML,
SVG, threejs, and plain text. We hope and expect other formatting to
other kinds backend renderers, like matplotlib, can be done by
following the pattern used here.

For example, in graphics there may be several different kinds of
renderers, SVG, or Asymptote for a particular kind of graphics Box.
The front-end needs to decides which format it better suited for it.
The Box, however, is created via a particular high-level Form.
Input to the renders come from some sort of Mathics3 Box.

As another example, front-end may decide to use MathJaX to render
TeXForm if the front-end supports this and the user so desires that.
The higher level Forms (e.g. TeXForm, MathMLForm) typically cause
specific boxing routines to get invoked. From this and the capabilites
and desires of a front end, different rendering routines will invoked
for each kind boxes created. This, in turn, produces strings in
(AMS)LaTeX, MathML, SVG, asymptote, or plain text.

For example, to process the Mathics3 builtin BezierCurve, a
BezierCurveBox will get created. Mathics3 has SVG and an Asymptote
renderers for BezierCurveBoxes. Which one is used is decided on by
the front-end's needs.
"""

import glob
Expand Down
Loading
Loading