Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e02e3a9
Improve use of CharacterEncoding
mmatera Mar 15, 2026
586d3a4
Merge branch 'master' into fix_ToStringEncoding
mmatera Mar 15, 2026
96ea4e8
Merge branch 'master' into fix_ToStringEncoding
mmatera Mar 16, 2026
cd526f5
Merge branch 'master' into fix_ToStringEncoding
rocky Mar 20, 2026
dc9c8ad
Merge remote-tracking branch 'origin/master' into fix_ToStringEncoding
mmatera Mar 24, 2026
1a53c1a
not finished
mmatera Mar 25, 2026
3d4b0a5
hangle encoding in doctests
mmatera Mar 25, 2026
0218bd9
adjust tests
mmatera Mar 25, 2026
1324c41
commenting out the Mathml tests
mmatera Mar 25, 2026
f58574c
Merge remote-tracking branch 'origin/master' into fix_ToStringEncoding
mmatera Mar 25, 2026
79dcf9d
adding missing module
mmatera Mar 25, 2026
e7f88e5
avoid circular import
mmatera Mar 25, 2026
0595532
using Mathics3-scanner tables. Moving encoding.py to mathics.eval
mmatera Mar 25, 2026
1670da6
remove hard coded table
mmatera Mar 25, 2026
d9e7eb5
last tweaks
mmatera Mar 27, 2026
b01006c
Merge branch 'master' into fix_ToStringEncoding
mmatera Mar 29, 2026
8a33df5
Merge branch 'master' into fix_ToStringEncoding
mmatera Mar 30, 2026
2d82c6d
Merge branch 'master' into fix_ToStringEncoding
mmatera Apr 3, 2026
68cb8b9
parent 6239c8346809177f6497fc594e4cc20b0c9d9686
mmatera Mar 29, 2026
cd3cf0d
parent 6239c8346809177f6497fc594e4cc20b0c9d9686
mmatera Mar 29, 2026
b743191
strip result before the comparison
mmatera Apr 4, 2026
ba5d790
fix wrong character
mmatera Apr 4, 2026
17ab410
Merge remote-tracking branch 'origin/master' into fix_ToStringEncoding
mmatera Apr 4, 2026
55ac83b
merge with handle_encoding_in_docpipeline
mmatera Apr 4, 2026
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
19 changes: 16 additions & 3 deletions mathics/builtin/atomic/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,7 @@ class ToString(Builtin):
"""

options = {
"CharacterEncoding": '"Unicode"',
"CharacterEncoding": "$CharacterEncoding",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For ToString, the default CharacterEncoding should be $CharacterEncoding

"FormatType": "OutputForm",
"NumberMarks": "$NumberMarks",
"PageHeight": "Infinity",
Expand All @@ -898,8 +898,21 @@ def eval_default(self, value, evaluation: Evaluation, options: dict):

def eval_form(self, expr, form, evaluation: Evaluation, options: dict):
"ToString[expr_, form_Symbol, OptionsPattern[ToString]]"
encoding = options["System`CharacterEncoding"]
return eval_ToString(expr, form, encoding.value, evaluation)
encoding = options["System`CharacterEncoding"].evaluate(evaluation)
if isinstance(encoding, String):
encoding_str = encoding.value
if encoding_str not in _encodings:
evaluation.message("$CharacterEncoding", "charcode", encoding)
encoding_str = evaluation.definitions.get_ownvalue(
"System`$SystemCharacterEncoding"
).value
else:
evaluation.message("$CharacterEncoding", "charcode", encoding)
encoding_str = evaluation.definitions.get_ownvalue(
"System`$SystemCharacterEncoding"
).value

return eval_ToString(expr, form, encoding_str, evaluation)


class Transliterate(Builtin):
Expand Down
1 change: 1 addition & 0 deletions mathics/core/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ def to_tex(self, **options) -> str:
return self.to_format("latex", **options)

def to_text(self, **options) -> str:
options.setdefault("encoding", "Unicode")
return self.to_format("text", **options)

# Deprecated
Expand Down
7 changes: 6 additions & 1 deletion mathics/core/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,10 +419,15 @@ def format_output(self, expr, format=None):
if result is None:
return None

try:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This ensures that when expressions are formatted as text, the encoding is always applied. With this change, if we specify that the encoding is "ASCII", all the tests must match with ASCII outputs.

encoding = self.definitions.get_ownvalue("System`$CharacterEncoding").value
except AttributeError:
encoding = "Unicode"

try:
# With the new implementation, if result is not a ``BoxExpression``
# then we should raise a BoxError here.
boxes = result.to_text(evaluation=self)
boxes = result.to_text(evaluation=self, encoding=encoding)
except BoxError:
self.message(
"General", "notboxes", Expression(SymbolFullForm, result).evaluate(self)
Expand Down
1 change: 1 addition & 0 deletions mathics/docpipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ def test_case(
)
if not comparison_result:
print("result != wanted")
print(test_pipeline.session.evaluate("$CharacterEncoding"))
fail_msg = f"Result: {result}\nWanted: {test.result}"
if out:
fail_msg += "\nAdditional output:\n"
Expand Down
14 changes: 11 additions & 3 deletions mathics/eval/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,17 @@
def eval_ToString(
expr: BaseElement, form: Symbol, encoding: String, evaluation: Evaluation
) -> String:
boxes = format_element(expr, evaluation, form, encoding=encoding)
text = boxes.to_text(evaluation=evaluation)
return String(text)
from mathics.format.render.text import EncodingNameError

boxes = format_element(expr, evaluation, form)
Copy link
Copy Markdown
Member

@rocky rocky Mar 25, 2026

Choose a reason for hiding this comment

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

If the final idea is that the strings in format_element are going to get converted, then I think this is approaching this the wrong way.

Instead, format_element needs to take the parameters expr, form, and encoding to produce boxes that have the appropriate strings in them initially.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Okay, but this doesn't align with how the experiments I showed you suggest WMA works. It does not matter how you create a string or a Box expression; in the end, an encoding pass is applied. And if you do the conversion earlier, a double conversion spoils the result.
Handling encoding at the level of format_element is like to modify the underlying structure of a Graphics object, because you know in the end it is going to be converted into a PNG file.

Copy link
Copy Markdown
Member

@rocky rocky Mar 25, 2026

Choose a reason for hiding this comment

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

Okay, but this doesn't align with how the experiments I showed you suggest WMA works.

I did not find anywhere in those experiments that there was a string that was encoded one way, and inside ToString, it got reencoded, as opposed to being encoded correctly initially.

It does not matter how you create a string or a Box expression; in the end, an encoding pass is applied.

That is not at issue here. What is at issue here is taking a string that was wrongly encoded and re-encoding it.

Consider this example where I set a breakpoint at the location we are discussing:

$ mathics3
...
In[1]:= ToString[a >= b, CharacterEncoding -> "ASCII"]
(/tmp/Mathics3/mathics-core/mathics/eval/strings.py:30:5 @46): eval_ToString
-- 30     try:
(trepan3k) list
 25    	    expr: BaseElement, form: Symbol, encoding: String, evaluation: Evaluation
 26    	) -> String:
 27    	
 28    	    boxes = format_element(expr, evaluation, form)
 29    	    breakpoint()
 30  ->	    try:
 31    	        return String(boxes.to_text(evaluation=evaluation, encoding=encoding))
 32    	    except EncodingNameError:
 33    	        # Mimic the WMA behavior. In the future, we can implement the mechanism
 34    	        # with encodings stored in .m files, and give a chance with it.
(trepan3k) boxes.elements
(<Expression: <Symbol: System`PaneBox>[<String: ""a ≥ b"">]>, <Expression: <Symbol: ...

<String: ""a ≥ b""> is wrong. That should be <String: ""a >= b"">.

And if you do the conversion earlier, a double conversion spoils the result. Handling encoding at the level of format_element is like to modify the underlying structure of a Graphics object, because you know in the end it is going to be converted into a PNG file.

This is not relevant here. We started with a Mathics3 Expression, and inside format_element, this expression got turned into an incorrect string, because encoding information indicating that strings are supposed to be ASCII was not respected inside format_element.

Another viable solution might be to have format_element not convert the expression a >= b to a String, and leave it as an Expression for later. But, I am not sure that is possible or correct. I believe only that what is done is incorrect and there's no evidence right now that WMA is reencoding strings instead of encoding them correctly initially.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

<String: ""a ≥ b""> is wrong. That should be <String: ""a >= b"">.

I have been looking again this, and again, this is a central misunderstanding: as I see this, the line 28

    	    boxes = format_element(expr, evaluation, form)

must return a boxed expression that uses the internal representation (Unicode/UTF-8). Then, the result <String: ""a ≥ b""> is correct. The encoding is applied in line 31

    	        return String(boxes.to_text(evaluation=evaluation, encoding=encoding))

which takes the box expression and converts it into a Python string, in the request encoding.

The advantage of this approach is that all the codepage translation machinary is completely localized in one module. The drawback is that we have to scan each character to see if we need to translate it. But this is how WMA does it, and I guess they developers had very good reasons to do in this way.

try:
return String(boxes.to_text(evaluation=evaluation, encoding=encoding))
except EncodingNameError:
# Mimic the WMA behavior. In the future, we can implement the mechanism
# with encodings stored in .m files, and give a chance with it.
evaluation.message("Get", "noopen", String("encodings/" + encoding + "." + "m"))

return String(boxes.to_text(evaluation=evaluation, encoding="Unicode"))


def eval_StringContainsQ(name, string, patt, evaluation, options, matched):
Expand Down
1 change: 1 addition & 0 deletions mathics/format/box/numberform.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def default_numberformat_outputform(man, base, exp, opts):
"ExponentFunction": lambda x: (SymbolNull if abs(x.value) <= 5 else x),
"ExponentStep": 1,
"NumberFormat": default_numberformat_outputform,
# TODO: Pick from MathicsScanner tables...
"NumberMultiplier": "×",
"NumberPadding": ["", "0"],
"NumberPoint": ".",
Expand Down
5 changes: 3 additions & 2 deletions mathics/format/form/outputform.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ def render_output_form(expr: BaseElement, evaluation: Evaluation, **kwargs):
"""
format_expr: Expression = do_format(expr, evaluation, SymbolOutputForm) # type: ignore

kwargs.setdefault("encoding", "Unicode")
while format_expr.has_form("HoldForm", 1): # type: ignore
format_expr = format_expr.elements[0]

Expand Down Expand Up @@ -338,7 +339,7 @@ def other_forms(expr, evaluation, **kwargs):
raise _WrongFormattedExpression

result = format_element(expr, evaluation, SymbolStandardForm, **kwargs)
return result.to_text()
return result.to_text(evaluation=evaluation, **kwargs)


@register_outputform("System`Integer")
Expand All @@ -357,7 +358,7 @@ def integer_outputform(n, evaluation, **kwargs):
result = numberform_to_boxes(n, digits, padding, evaluation, py_options)
if isinstance(result, String):
return result.value
return result.to_text()
return result.to_text(**kwargs)


@register_outputform("System`Image")
Expand Down
72 changes: 70 additions & 2 deletions mathics/format/render/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"""
Mathics3 box rendering to plain text.
"""

from mathics.builtin.box.graphics import GraphicsBox
from mathics.builtin.box.graphics3d import Graphics3DBox
from mathics.builtin.box.layout import (
Expand Down Expand Up @@ -34,6 +33,75 @@
add_render_function(FormBox, convert_inner_box_field)


# Map WMA encoding names to Python encoding names
ENCODING_WMA_TO_PYTHON = {
"WindowsEastEurope": "cp1250",
"WindowsCyrillic": "cp1251",
"WindowsANSI": "cp1252",
"WindowsGreek": "cp1252",
"WindowsTurkish": "cp1254",
}


class EncodingNameError(Exception):
pass


def get_encoding_table(encoding: str):
"""
Return a dictionary with a map from
character codes in the internal (Unicode)
representation to the request encoding.
"""
if encoding == "Unicode":
return {}

# In the final implementation, this should load the corresponding
# json table or an encoding file as in WMA
# SystemFiles/CharacterEncodings/*.m
# If the encoding is not available, raise an EncodingError
try:
return {
"ASCII": {
"⧴": ":>",
"⇒": "=>",
"↔": "<->",
"⩵": "==",
"∧": "&&",
"⊻": r"\[Xor]",
"≠": "!=",
"≤": "<=",
"→": "->",
"⇾": "->",
"⇾": "->",
"⇴": "->",
"∫": r"\[Integral]",
"": r"\[DifferentialD]",
"𝑑": r"\[DifferentialD]",
"⧦": r"\[Equivalent]",
"×": r" x ",
},
"UTF-8": {},
}[encoding]
except KeyError:
raise EncodingNameError


def encode_string_value(value: str, encoding: str):
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This function is a just a proof of concept. The final version should look into the MathicsScanner tables

"""Convert an Unicode string `value` to the required `encoding`"""

# In WMA, encodings are readed from SystemFiles/CharacterEncodings/*.m
# on the fly. We should load them from Mathics3-Scanner tables.
encoding_table = get_encoding_table(encoding)
if not encoding_table:
return value
result = ""
for ch in value:
ch = encoding_table.get(ch, ch)
result += ch
return result


def fractionbox(box: FractionBox, **options) -> str:
# Note: values set in `options` take precedence over `box_options`
child_options = {**options, **box.box_options}
Expand Down Expand Up @@ -159,7 +227,7 @@ def string(s: String, **options) -> str:
if value.startswith('"') and value.endswith('"'): # nopep8
if not show_string_characters:
value = value[1:-1]
return value
return encode_string_value(value, options["encoding"])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How do we know that "encoding" has always been passed in the options dictionary? Should this be options.get instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I put this way to check that indeed we passed the option. But yes, we can use get instead.



add_render_function(String, string)
Expand Down
8 changes: 4 additions & 4 deletions test/builtin/files_io/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,28 +231,28 @@ def test_close():
(
'stream = StringToStream["1.523E-19"]; Read[stream, Real]',
None,
"1.523×10^-19",
"1.523 x 10^-19",
Copy link
Copy Markdown
Member

@rocky rocky Mar 27, 2026

Choose a reason for hiding this comment

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

I thought you were going to rewrite so that we aren't testing impossible behavior?

Such as testing at the encoding-independent level.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, but to do that, I need to do it in several steps, in order to avoid a much larger PRs. The plan is go over this in the next round.

Copy link
Copy Markdown
Member

@rocky rocky Mar 27, 2026

Choose a reason for hiding this comment

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

How can we break up this PR into smaller, self-contained conceptual pieces?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not sure, because when I tried to do it in smaller pieces, I was not able to make you understand what I was doing. Maybe now I can split the part of MathML, then the encoding function, then docpipeline, then remove the internal encoding and the other fixes.

"",
),
("Close[stream];", None, "Null", ""),
(
'stream = StringToStream["-1.523e19"]; Read[stream, Real]',
None,
"-1.523×10^19",
"-1.523 x 10^19",
"",
),
("Close[stream];", None, "Null", ""),
(
'stream = StringToStream["3*^10"]; Read[stream, Real]',
None,
"3.×10^10",
"3. x 10^10",
"",
),
("Close[stream];", None, "Null", ""),
(
'stream = StringToStream["3.*^10"]; Read[stream, Real]',
None,
"3.×10^10",
"3. x 10^10",
"",
),
("Close[stream];", None, "Null", ""),
Expand Down
2 changes: 1 addition & 1 deletion test/builtin/files_io/test_importexport.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ def test_inividually():
(
r'System`Convert`B64Dump`B64Decode["4oirIGYg752MIHg="]',
None,
r" f x",
r"\[Integral] f \[DifferentialD] x",
None,
),
],
Expand Down
4 changes: 2 additions & 2 deletions test/builtin/numbers/test_trig.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ def test_ArcCos():
("ArcTan[-1, 0]", None, "Pi", None),
("ArcTan[0, 1]", None, "Pi / 2", None),
("ArcTan[0, -1]", None, "-Pi / 2", None),
("Cos[1.5 Pi]", None, "-1.83697×10^-16", None),
("Cos[1.5 Pi]", None, "-1.83697 x 10^-16", None),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How can I see this behavior using wolframscript?

When I try using InputForm I see this:

In[1]:= Cos[1.5 Pi] // InputForm                                                            

Out[1]//InputForm= -1.8369701987210297*^-16

Copy link
Copy Markdown
Contributor Author

@mmatera mmatera Mar 25, 2026

Choose a reason for hiding this comment

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

Actually, you can't: InputForm uses this base*^exp notation, while OutputForm uses the 2D form

In[3]:= 2.3*^43                                                                 

              43
Out[3]= 2.3 10

The closest form is the EngineeringForm:

In[4]:= EngineeringForm[2.3*^32]                                                

                                   30
Out[4]//EngineeringForm= 230. × 10

which uses the times operator. By setting the character encoding to ASCII, we see the use of x instead of Times:

In[5]:= $CharacterEncoding="ASCII"                                              

Out[5]= ASCII

In[6]:= EngineeringForm[2.3*^32]                                                

                                  30
Out[6]//EngineeringForm= 230. x 10

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ok. Thanks for the clarification. So, in what environment do we see exactly "-1.83697 x 10^-16" as the output of "2.3*^43"?

And how am I to understand that in this test, I am matching that kind of environment?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In the test/format/ folder, there are two files, one is format_tests.yaml which we use for the test, and another format_tests-WMA.yaml which contains the corresponding outputs in WMA.
Regarding which environment, I am running WMA 12.04 in Ubuntu 22.04.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Regarding which environment,

I am sorry that I wasn't clear. By environment, I mean in what Wolfram program or product do we see this kind of output appearing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is because we have not yet implemented a 2D OutputForm. In any case, looking at this, what we should test in most of the cases, is the match regarding the internal representation, and not regarding the format, which is just one aspect to be tested.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Normally, I'd say yes, please let's match the internal representation. But...

Unless we know that there is a WMA internal representation that we are trying to match, or unless right now this internal representation has a concrete impact on output we can see today that matches WMA, I'd say, let's not test things (let alone exhaustive tests) of something that could very well change (even if ever so slightly) as we fill things in, such as for 2D character layout.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OK, but that's the point. With the "internal" representation of the result, I mean FullForm, which is readily accessible. Then, aspects related to the format can be tested in focused tests. This allows us to avoid worring about the representation of \[Times], when what we want to test if whether two numerical results are the same.

Copy link
Copy Markdown
Member

@rocky rocky Mar 25, 2026

Choose a reason for hiding this comment

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

Testing against an internal representation as a quicker, more understandable, and more trackable way to ensure that FullForm output is correct is not only fine, but it is preferable. (Of course, there will be some end-to-end "blackbox" FullForm tests as well.)

Writing tests to track the internal representation for how that might be used in 2D character output that hasn't been fleshed out and is not implemented is, however, not a good idea.

That should be delayed until we have the 2D renderer in place.

Copy link
Copy Markdown
Member

@rocky rocky Mar 25, 2026

Choose a reason for hiding this comment

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

Logic note:

In "Unless x then y", when x is false, y can happen.

("N[Sin[1], 40]", None, "0.8414709848078965066525023216302989996226", None),
("Tan[0.5 Pi]", None, "1.63312×10^16", None),
("Tan[0.5 Pi]", None, "1.63312 x 10^16", None),
],
)
def test_trig(str_expr, msgs, str_expected, fail_msg):
Expand Down
16 changes: 10 additions & 6 deletions test/builtin/test_binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,12 @@
('WbR[{1, 0, 0, 0, 0, 0, 240, 255}, "Real64"]', "Indeterminate", None),
## Real128
## 0x0000
('WbR[{0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, "Real128"]', "0.×10^-4965", None),
('WbR[{0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,128}, "Real128"]', "0.×10^-4965", None),
('WbR[{0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}, "Real128"]', "0. x 10^-4965", None),
(
'WbR[{0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,128}, "Real128"]',
"0. x 10^-4965",
None,
),
## 0x0001 - 0x7FFE
(
'WbR[{0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,255,63}, "Real128"]',
Expand All @@ -256,12 +260,12 @@
),
(
'WbR[{135, 62, 233, 137, 22, 208, 233, 210, 133, 82, 251, 92, 220, 216, 207, 72}, "Real128"]',
"2.45563355727491021879689747166252×10^679",
"2.45563355727491021879689747166252 x 10^679",
None,
),
(
'z=WbR[{74, 95, 30, 234, 116, 130, 1, 84, 20, 133, 245, 221, 113, 110, 219, 212}, "Real128"]',
"-4.52840681592341879518366539335138×10^1607",
"-4.52840681592341879518366539335138 x 10^1607",
None,
),
("z // Precision", "33.", None),
Expand Down Expand Up @@ -427,8 +431,8 @@ def test_ByteOrdering(str_expr, str_expected, fail_msg):
@pytest.mark.parametrize(
("str_expr", "str_expected"),
[
("NumericArray[{{1,2},{3,4}}]", "<Integer64, 2×2>"),
("ToString[NumericArray[{{1,2},{3,4}}]]", "<Integer64, 2×2>"),
("NumericArray[{{1,2},{3,4}}]", "<Integer64, 2 x 2>"),
("ToString[NumericArray[{{1,2},{3,4}}]]", "<Integer64, 2 x 2>"),
("Head[NumericArray[{1,2}]]", "NumericArray"),
("AtomQ[NumericArray[{1,2}]]", "True"),
("First[NumericArray[{1,2,3}]]", "1"),
Expand Down
16 changes: 8 additions & 8 deletions test/builtin/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ def test_makeboxes_form(expr, form, head, subhead):
("NumberForm[14310983091809]", None, "14310983091809", None),
## Zero case
("z0 = 0.0;z1 = 0.0000000000000000000000000000;", None, "Null", None),
("NumberForm[{z0, z1}, 10]", None, "{0., 0.×10^-28}", None),
("NumberForm[{z0, z1}, {10, 4}]", None, "{0.0000, 0.0000×10^-28}", None),
("NumberForm[{z0, z1}, 10]", None, "{0., 0. x 10^-28}", None),
("NumberForm[{z0, z1}, {10, 4}]", None, "{0.0000, 0.0000 x 10^-28}", None),
("z0=.;z1=.;", None, "Null", None),
## Trailing zeros
("NumberForm[1.0, 10]", None, "1.", None),
Expand All @@ -67,7 +67,7 @@ def test_makeboxes_form(expr, form, head, subhead):
(
"NumberForm[{2^123, 2^123.}, 4, ExponentFunction -> ((#1) &)]",
None,
"{10633823966279326983230456482242756608, 1.063×10^37}",
"{10633823966279326983230456482242756608, 1.063 x 10^37}",
None,
),
("NumberForm[{0, 10, -512}, {10, 3}]", None, "{0.000, 10.000, -512.000}", None),
Expand Down Expand Up @@ -178,7 +178,7 @@ def test_makeboxes_form(expr, form, head, subhead):
(
"NumberForm[12345.123456789, 14, ExponentFunction -> ((#) &)]",
None,
"1.2345123456789×10^4",
"1.2345123456789 x 10^4",
None,
),
(
Expand All @@ -191,7 +191,7 @@ def test_makeboxes_form(expr, form, head, subhead):
(
"NumberForm[y, 10, ExponentFunction -> (3 Quotient[#, 3] &)]",
None,
"{114.0256472×10^-12, 3.267763643×10^-3, 93.64804748×10^3, 2.683779414×10^12, 76.91214221×10^18}",
"{114.0256472 x 10^-12, 3.267763643 x 10^-3, 93.64804748 x 10^3, 2.683779414 x 10^12, 76.91214221 x 10^18}",
None,
),
(
Expand All @@ -207,7 +207,7 @@ def test_makeboxes_form(expr, form, head, subhead):
(
"NumberForm[10^8 N[Pi], 10, ExponentStep -> 3]",
None,
"314.1592654×10^6",
"314.1592654 x 10^6",
None,
),
(
Expand All @@ -225,7 +225,7 @@ def test_makeboxes_form(expr, form, head, subhead):
(
"NumberForm[y, 10, ExponentStep -> 6]",
None,
"{114.0256472×10^-12, 3267.763643×10^-6, 93648.04748, 2.683779414×10^12, 76.91214221×10^18}",
"{114.0256472 x 10^-12, 3267.763643 x 10^-6, 93648.04748, 2.683779414 x 10^12, 76.91214221 x 10^18}",
None,
),
## NumberFormat
Expand Down Expand Up @@ -318,7 +318,7 @@ def test_makeboxes_form(expr, form, head, subhead):
(
'NumberForm[N[10^ 7 Pi], 15, DigitBlock -> 3, NumberSeparator -> {",", " "}]',
None,
"3.141 592 653 589 79×10^7",
"3.141 592 653 589 79 x 10^7",
None,
),
(
Expand Down
6 changes: 3 additions & 3 deletions test/builtin/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@ def test_realvalued():
(
"N[3^200]",
None,
"2.65614×10^95",
"2.65614 x 10^95",
"Numeric converts a large integer to a MachineReal without losing precision",
),
(
"N[2^1023]",
None,
"8.98847×10^307",
"8.98847 x 10^307",
"Numeric display digits for value under 2^1024 is DefaultPrintDisplay value 6",
),
(
"N[2^1024]",
None,
"1.797693134862316×10^308",
"1.797693134862316 x 10^308",
"Numeric display digits for value on or over= 2^1024 is $MachineDigits",
),
(
Expand Down
Loading
Loading