Skip to content

Commit 7df7951

Browse files
committed
Fix for nan/inf literals
The repr for these values is not valid python
1 parent 397a171 commit 7df7951

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

.github/workflows/test_corpus.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ jobs:
7474
7575
- name: Run tests
7676
run: |
77+
if [[ "${matrix.python}" == "python3.3" || "${matrix.python}" == "python3.4" || "${matrix.python}" == "python3.5" ]]; then
78+
# These versions randomise the hash seed, but don't preserve dict order
79+
# This affects how names are assigned. Disable the hash randomisation for
80+
# deterministic results.
81+
export PYTHONHASHSEED=0
82+
fi
83+
7784
${{matrix.python}} workflow/corpus_test/generate_results.py /corpus /corpus-results $(<sha.txt) ${{ inputs.regenerate-results }}
7885
7986
generate_report:

src/python_minifier/transforms/constant_folding.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ def visit_BinOp(self, node):
4040

4141
try:
4242
original_expression = expression_printer(node)
43-
value = eval(original_expression)
43+
globals = {}
44+
locals = {}
45+
value = eval(original_expression, globals, locals)
4446
except Exception as e:
4547
return node
4648

@@ -65,19 +67,28 @@ def visit_BinOp(self, node):
6567
expression_printer = ExpressionPrinter()
6668
folded_expression = expression_printer(new_node)
6769

68-
if len(folded_expression) > len(original_expression):
69-
# Result is longer than original expression
70+
if len(folded_expression) >= len(original_expression):
71+
# Result is not shorter than original expression
7072
return node
7173

72-
globals = {'__builtins__': {}} # Completely empty globals
73-
locals = {}
74-
assert eval(folded_expression, globals, locals) == value
74+
try:
75+
globals = {'__builtins__': {'float': float}}
76+
locals = {}
77+
folded_value = eval(folded_expression, globals, locals)
78+
except NameError as ne:
79+
if ne.name in ['inf', 'infj', 'nan']:
80+
# When the value is something like inf+0j the expression printer will print it that way, which is not valid Python.
81+
# In python code it should be '1e999+0j', which parses as a BinOp that the expression printer can handle.
82+
# It's not worth fixing the expression printer to handle this case, since it is unlikely to occur in real code.
83+
return node
84+
raise
85+
86+
if isinstance(value, float) and math.isnan(value):
87+
assert math.isnan(folded_value)
88+
else:
89+
assert folded_value == value and type(folded_value) == type(value)
7590

76-
# Some complex number values are parsed as a BinOp
77-
# Make sure we represent our AST the same way so it roundtrips correctly
78-
parsed_folded_expression = ast.parse(folded_expression, 'folded expression', 'eval')
79-
assert isinstance(parsed_folded_expression, ast.Expression)
80-
if isinstance(parsed_folded_expression.body, ast.BinOp):
81-
new_node = parsed_folded_expression.body
91+
#print(f'{original_expression=}')
92+
#print(f'{folded_expression=}')
8293

8394
return self.add_child(new_node, node.parent, node.namespace)

0 commit comments

Comments
 (0)