Skip to content

Commit d5b5a09

Browse files
mmaterarocky
andauthored
Fix character encoding (#1062)
Looking at #1061 I realized we could not change `$CharacterEncoding` from inside the session. This PR makes the behavior of this symbol closer to the one in WMA. --------- Co-authored-by: rocky <[email protected]>
1 parent 2a594cc commit d5b5a09

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ Compatibility
2424
* ``Graphics`` and ``Graphics3D`` including wrong primitives and directives
2525
are shown with a pink background. In the Mathics-Django interface, a tooltip
2626
error message is also shown.
27+
* Improving support for ``$CharacterEncoding``. Now it is possible to change it
28+
from inside the session.
29+
2730

2831
Internals
2932
---
@@ -38,6 +41,7 @@ Internals
3841
* Built-in code is directed explicitly rather than implicitly. This facilitates the ability to lazy load
3942
builtins or "autoload" them a la GNU Emacs autoload.
4043

44+
4145
Bugs
4246
----
4347

mathics/builtin/atomic/strings.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@
2424
from mathics.core.list import ListExpression
2525
from mathics.core.parser import MathicsFileLineFeeder, parse
2626
from mathics.core.symbols import Symbol, SymbolTrue
27-
from mathics.core.systemsymbols import SymbolFailed, SymbolInputForm, SymbolOutputForm
27+
from mathics.core.systemsymbols import (
28+
SymbolFailed,
29+
SymbolInputForm,
30+
SymbolNone,
31+
SymbolOutputForm,
32+
)
2833
from mathics.eval.strings import eval_ToString
2934
from mathics.settings import SYSTEM_CHARACTER_ENCODING
3035

@@ -322,19 +327,46 @@ class CharacterEncoding(Predefined):
322327
>> $CharacterEncoding
323328
= ...
324329
330+
By setting its value to one of the values in '$CharacterEncodings', \
331+
operators are formatted differently. For example,
332+
333+
>> $CharacterEncoding = "ASCII"; a -> b
334+
= ...
335+
>> $CharacterEncoding = "UTF-8"; a -> b
336+
= ...
337+
338+
Setting its value to 'None' restore the value to \
339+
'$SystemCharacterEncoding':
340+
>> $CharacterEncoding = None;
341+
>> $SystemCharacterEncoding == $CharacterEncoding
342+
= True
343+
325344
See also <url>
326345
:$SystemCharacterEncoding:
327346
/doc/reference-of-built-in-symbols/atomic-elements-of-expressions/string-manipulation/$systemcharacterencoding/</url>.
328347
"""
329348

330349
name = "$CharacterEncoding"
350+
messages = {
351+
"charcode": "`1` is not a valid character encoding. Possible settings are the names given by $CharacterEncodings or None."
352+
}
331353
value = f'"{SYSTEM_CHARACTER_ENCODING}"'
332354
rules = {
333355
"$CharacterEncoding": value,
334356
}
335357

336358
summary_text = "default character encoding"
337359

360+
def eval_set(self, value, evaluation):
361+
"""Set[$CharacterEncoding, value_]"""
362+
if value is SymbolNone:
363+
value = String(SYSTEM_CHARACTER_ENCODING)
364+
if isinstance(value, String) and value.value in _encodings.keys():
365+
evaluation.definitions.set_ownvalue("System`$CharacterEncoding", value)
366+
else:
367+
evaluation.message("$CharacterEncoding", "charcode", value)
368+
return value
369+
338370

339371
class CharacterEncodings(Predefined):
340372
"""

mathics/session.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ def evaluate(self, str_expression, timeout=None, form=None):
103103

104104
def evaluate_as_in_cli(self, str_expression, timeout=None, form=None, src_name=""):
105105
"""This method parse and evaluate the expression using the session.evaluation.evaluate method"""
106+
self.evaluation.out = []
106107
query = self.evaluation.parse(str_expression, src_name)
107108
if query is not None:
108109
res = self.evaluation.evaluate(query, timeout=timeout, format=form)

test/builtin/files_io/test_importexport.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os.path as osp
44
import sys
55
import tempfile
6-
from test.helper import check_evaluation, evaluate, session
6+
from test.helper import check_evaluation, check_evaluation_as_in_cli, evaluate, session
77

88
import pytest
99

@@ -267,9 +267,23 @@ def test_inividually():
267267
assert outs == [f"Cannot infer format of file {filename}."]
268268

269269

270-
# TODO:
271-
# mmatera: please put in pytest conditionally
272-
# >> System`Convert`B64Dump`B64Encode["∫ f  x"]
273-
# = 4oirIGYg752MIHg=
274-
# >> System`Convert`B64Dump`B64Decode[%]
275-
# = ∫ f  x
270+
@pytest.mark.parametrize(
271+
("str_expr", "msgs", "str_expected", "fail_msg"),
272+
[
273+
(
274+
r'System`Convert`B64Dump`B64Encode["∫ f  x"]',
275+
None,
276+
r"4oirIGYg752MIHg=",
277+
None,
278+
),
279+
(
280+
r'System`Convert`B64Dump`B64Decode["4oirIGYg752MIHg="]',
281+
None,
282+
r"∫ f  x",
283+
None,
284+
),
285+
],
286+
)
287+
def test_b64encode(str_expr, msgs, str_expected, fail_msg):
288+
"""special case"""
289+
check_evaluation_as_in_cli(str_expr, str_expected, fail_msg, msgs)

0 commit comments

Comments
 (0)