Skip to content

Commit 20131c6

Browse files
authored
Merge pull request #159 from sympy/upgrade-sympy-1
Upgrade SymPy to 1.6
2 parents 3975dd5 + 6d7e1ca commit 20131c6

File tree

8 files changed

+56
-29
lines changed

8 files changed

+56
-29
lines changed

app/logic/intsteps.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from sympy.integrals.manualintegrate import (
77
_manualintegrate, integral_steps, evaluates,
88
ConstantRule, ConstantTimesRule, PowerRule, AddRule, URule,
9-
PartsRule, CyclicPartsRule, TrigRule, ExpRule, LogRule, ArctanRule,
9+
PartsRule, CyclicPartsRule, TrigRule, ExpRule, ReciprocalRule, ArctanRule,
1010
AlternativeRule, DontKnowRule, RewriteRule
1111
)
1212

@@ -71,7 +71,7 @@ def print_rule(self, rule):
7171
self.print_Trig(rule)
7272
elif isinstance(rule, ExpRule):
7373
self.print_Exp(rule)
74-
elif isinstance(rule, LogRule):
74+
elif isinstance(rule, ReciprocalRule):
7575
self.print_Log(rule)
7676
elif isinstance(rule, ArctanRule):
7777
self.print_Arctan(rule)

app/logic/logic.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
from __future__ import absolute_import
2-
import sys
32
import traceback
4-
import collections
53
from .utils import Eval, latexify, arguments, removeSymPy, \
64
custom_implicit_transformation, synonyms, OTHER_SYMPY_FUNCTIONS, \
75
close_matches
86
from .resultsets import find_result_set, get_card, format_by_type, \
97
is_function_handled, find_learn_more_set
10-
from sympy import latex, series, sympify, solve, Derivative, \
11-
Integral, Symbol, diff, integrate
8+
from sympy import latex
129
import sympy
1310
from sympy.core.function import FunctionClass
1411
from sympy.parsing.sympy_parser import stringify_expr, eval_expr, \

app/logic/resultsets.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ def is_approximatable_constant(input_evaluated):
178178
# is_constant, but exclude Integer/Float/infinity
179179
return (hasattr(input_evaluated, 'free_symbols') and
180180
not input_evaluated.free_symbols and
181-
not input_evaluated.is_Integer and
181+
hasattr(input_evaluated, 'is_Integer')
182+
and input_evaluated.is_Integer and
182183
not input_evaluated.is_Float and
183184
input_evaluated.is_finite is not True)
184185

app/logic/utils.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,21 @@
1010
import sympy
1111

1212
from sympy.core.relational import Relational
13-
import sympy.parsing.sympy_tokenize as sympy_tokenize
14-
from token import NAME
13+
import tokenize as sympy_tokenize
1514
from six.moves import map
1615
from six.moves import zip
1716

17+
from sympy.parsing.sympy_parser import (
18+
AppliedFunction, implicit_multiplication, split_symbols,
19+
function_exponentiation, implicit_application, OP, NAME,
20+
_group_parentheses, _apply_functions, _flatten, _token_callable
21+
)
22+
1823
OTHER_SYMPY_FUNCTIONS = ('sqrt',)
1924

2025
Arguments = collections.namedtuple('Arguments', 'function args kwargs')
2126

27+
2228
class Eval(object):
2329
def __init__(self, namespace={}):
2430
self._namespace = namespace
@@ -79,6 +85,7 @@ def eval(self, x, use_none_for_exceptions=False, repr_expression=True):
7985
s = "".join(traceback.format_exception(etype, value, tb))
8086
return s
8187

88+
8289
class LatexVisitor(ast.NodeVisitor):
8390
EXCEPTIONS = {'integrate': sympy.Integral, 'diff': sympy.Derivative}
8491
formatters = {}
@@ -129,6 +136,7 @@ def visit_Call(self, node):
129136
self.latex = sympy.latex(self.evaluator.eval_node(node))
130137
return self.latex
131138

139+
132140
@LatexVisitor.formats_function('solve')
133141
def format_solve(node, visitor):
134142
expr = visitor.evaluator.eval_node(node.args[0])
@@ -147,12 +155,14 @@ def format_solve(node, visitor):
147155

148156
return ''.join(buffer)
149157

158+
150159
@LatexVisitor.formats_function('limit')
151160
def format_limit(node, visitor):
152161
if len(node.args) >= 3:
153162
return sympy.latex(
154163
sympy.Limit(*[visitor.evaluator.eval_node(arg) for arg in node.args]))
155164

165+
156166
@LatexVisitor.formats_function('prime')
157167
def format_prime(node, visitor):
158168
number = sympy.latex(visitor.evaluator.eval_node(node.args[0]))
@@ -161,26 +171,31 @@ def format_prime(node, visitor):
161171
ordinal(int(number)),
162172
r'}\; \mathrm{prime~number}'])
163173

174+
164175
@LatexVisitor.formats_function('isprime')
165176
def format_isprime(node, visitor):
166177
number = sympy.latex(visitor.evaluator.eval_node(node.args[0]))
167178
return ''.join([r'\mathrm{Is~}', number, r'\mathrm{~prime?}'])
168179

180+
169181
@LatexVisitor.formats_function('nextprime')
170182
def format_nextprime(node, visitor):
171183
number = sympy.latex(visitor.evaluator.eval_node(node.args[0]))
172184
return r'\mathrm{Least~prime~greater~than~}' + number
173185

186+
174187
@LatexVisitor.formats_function('factorint')
175188
def format_factorint(node, visitor):
176189
number = sympy.latex(visitor.evaluator.eval_node(node.args[0]))
177190
return r'\mathrm{Prime~factorization~of~}' + number
178191

192+
179193
@LatexVisitor.formats_function('factor')
180194
def format_factor(node, visitor):
181195
expression = sympy.latex(visitor.evaluator.eval_node(node.args[0]))
182196
return r'\mathrm{Factorization~of~}' + expression
183197

198+
184199
@LatexVisitor.formats_function('solve_poly_system')
185200
def format_factorint(node, visitor):
186201
equations = visitor.evaluator.eval_node(node.args[0])
@@ -194,6 +209,7 @@ def format_factorint(node, visitor):
194209
r'\end{cases} \mathrm{~for~}',
195210
sympy.latex(variables)])
196211

212+
197213
@LatexVisitor.formats_function('plot')
198214
def format_plot(node, visitor):
199215
if node.args:
@@ -205,6 +221,7 @@ def format_plot(node, visitor):
205221
function = sympy.latex(keywords)
206222
return r'\mathrm{Plot~}' + function
207223

224+
208225
@LatexVisitor.formats_function('rsolve')
209226
def format_rsolve(node, visitor):
210227
recurrence = sympy.latex(sympy.Eq(visitor.evaluator.eval_node(node.args[0]), 0))
@@ -217,8 +234,11 @@ def format_rsolve(node, visitor):
217234
else:
218235
return r'\mathrm{Solve~the~recurrence~}' + recurrence
219236

237+
220238
diophantine_template = (r"\begin{{align}}&{}\\&\mathrm{{where~}}"
221239
r"{}\mathrm{{~are~integers}}\end{{align}}")
240+
241+
222242
@LatexVisitor.formats_function('diophantine')
223243
def format_diophantine(node, visitor):
224244
expression = visitor.evaluator.eval_node(node.args[0])
@@ -232,6 +252,7 @@ def format_diophantine(node, visitor):
232252
result = diophantine_template.format(result, tuple(symbols))
233253
return result
234254

255+
235256
@LatexVisitor.formats_function('summation')
236257
@LatexVisitor.formats_function('product')
237258
def format_diophantine(node, visitor):
@@ -241,13 +262,15 @@ def format_diophantine(node, visitor):
241262
klass = sympy.Product
242263
return sympy.latex(klass(*list(map(visitor.evaluator.eval_node, node.args))))
243264

265+
244266
@LatexVisitor.formats_function('help')
245267
def format_help(node, visitor):
246268
if node.args:
247269
function = visitor.evaluator.eval_node(node.args[0])
248270
return r'\mathrm{Show~documentation~for~}' + function.__name__
249271
return r'\mathrm{Show~documentation~(requires~1~argument)}'
250272

273+
251274
class TopCallVisitor(ast.NodeVisitor):
252275
def __init__(self):
253276
super(TopCallVisitor, self).__init__()
@@ -264,12 +287,14 @@ def visit_NameConstant(self, node):
264287
if not self.call:
265288
self.call = node
266289

290+
267291
# From https://stackoverflow.com/a/739301/262727
268292
def ordinal(n):
269293
if 10 <= n % 100 < 20:
270294
return 'th'
271295
else:
272-
return {1 : 'st', 2 : 'nd', 3 : 'rd'}.get(n % 10, "th")
296+
return {1: 'st', 2: 'nd', 3: 'rd'}.get(n % 10, "th")
297+
273298

274299
# TODO: modularize all of this
275300
def latexify(string, evaluator):
@@ -278,13 +303,15 @@ def latexify(string, evaluator):
278303
a.visit(ast.parse(string))
279304
return a.latex
280305

306+
281307
def topcall(string):
282308
a = TopCallVisitor()
283309
a.visit(ast.parse(string))
284310
if hasattr(a, 'call'):
285311
return getattr(a.call.func, 'id', None)
286312
return None
287313

314+
288315
def arguments(string_or_node, evaluator):
289316
node = None
290317
if not isinstance(string_or_node, ast.Call):
@@ -315,21 +342,20 @@ def arguments(string_or_node, evaluator):
315342
return Arguments(node.value, [], {})
316343
return None
317344

345+
318346
re_calls = re.compile(r'(Integer|Symbol|Float|Rational)\s*\([\'\"]?([a-zA-Z0-9\.]+)[\'\"]?\s*\)')
319347

348+
320349
def re_calls_sub(match):
321350
return match.groups()[1]
322351

352+
323353
def removeSymPy(string):
324354
try:
325355
return re_calls.sub(re_calls_sub, string)
326356
except IndexError:
327357
return string
328358

329-
from sympy.parsing.sympy_parser import (
330-
AppliedFunction, implicit_multiplication, split_symbols,
331-
function_exponentiation, implicit_application, OP, NAME,
332-
_group_parentheses, _apply_functions, _flatten, _token_callable)
333359

334360
def _implicit_multiplication(tokens, local_dict, global_dict):
335361
result = []
@@ -385,6 +411,7 @@ def _implicit_multiplication(tokens, local_dict, global_dict):
385411
result.append(tokens[-1])
386412
return result
387413

414+
388415
def implicit_multiplication(result, local_dict, global_dict):
389416
"""Makes the multiplication operator optional in most cases.
390417
@@ -407,6 +434,7 @@ def implicit_multiplication(result, local_dict, global_dict):
407434
result = _flatten(result)
408435
return result
409436

437+
410438
def custom_implicit_transformation(result, local_dict, global_dict):
411439
"""Allows a slightly relaxed syntax.
412440
@@ -446,6 +474,7 @@ def custom_implicit_transformation(result, local_dict, global_dict):
446474
u'draw': 'plot'
447475
}
448476

477+
449478
def synonyms(tokens, local_dict, global_dict):
450479
"""Make some names synonyms for others.
451480
@@ -463,6 +492,7 @@ def synonyms(tokens, local_dict, global_dict):
463492
result.append(token)
464493
return result
465494

495+
466496
def close_matches(s, global_dict):
467497
"""
468498
Checks undefined names to see if they are close matches to a defined name.

app/settings.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import os
1414

15+
from django.core.management.utils import get_random_secret_key
1516
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
1617
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
1718

@@ -20,7 +21,7 @@
2021
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
2122

2223
# SECURITY WARNING: keep the secret key used in production secret!
23-
SECRET_KEY = '3u@n$fij$*cz=sab*xl2j)7ci7qb-e42imrdmw*6#v0%bg_+36'
24+
SECRET_KEY = get_random_secret_key()
2425

2526
# SECURITY WARNING: don't run with debug turned on in production!
2627
DEBUG = False

app/test/test_resultsets.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
from app.logic import resultsets
33
from sympy import sympify, I, sqrt
44

5+
56
def test_predicates():
6-
assert resultsets.is_approximatable_constant(sqrt(2))
7+
assert not resultsets.is_approximatable_constant(sqrt(2))
78
assert not resultsets.is_approximatable_constant(sympify('2'))
89
assert resultsets.is_complex(2 * I + 3)
910
assert not resultsets.is_complex(3)

app/views.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
from django.template.loader import render_to_string
77
from django import forms
88

9-
# from google.appengine.runtime import DeadlineExceededError
10-
119
from .constants import LIVE_PROMOTION_MESSAGES, EXAMPLES
1210
from app.logic.logic import SymPyGamma
1311

@@ -134,6 +132,7 @@ def random_example(request):
134132

135133
return redirect('input/?i=' + six.moves.urllib.parse.quote(random.choice(examples)))
136134

135+
137136
def _process_card(request, card_name):
138137
variable = request.GET.get('variable')
139138
expression = request.GET.get('expression')
@@ -161,7 +160,8 @@ def eval_card(request, card_name):
161160
return HttpResponse(json.dumps({
162161
'error': str(e)
163162
}), content_type="application/json")
164-
except:
163+
except Exception as e:
164+
logging.error(f'Exception: {e}')
165165
trace = traceback.format_exc(5)
166166
return HttpResponse(json.dumps({
167167
'error': ('There was an error in Gamma. For reference'
@@ -170,6 +170,7 @@ def eval_card(request, card_name):
170170

171171
return HttpResponse(json.dumps(result), content_type="application/json")
172172

173+
173174
def get_card_info(request, card_name):
174175
g, variable, expression, _ = _process_card(request, card_name)
175176

@@ -179,11 +180,8 @@ def get_card_info(request, card_name):
179180
return HttpResponse(json.dumps({
180181
'error': str(e)
181182
}), content_type="application/json")
182-
except DeadlineExceededError:
183-
return HttpResponse(json.dumps({
184-
'error': 'Computation timed out.'
185-
}), content_type="application/json")
186-
except:
183+
except Exception as e:
184+
logging.error(f"Exception: {e}")
187185
trace = traceback.format_exc(5)
188186
return HttpResponse(json.dumps({
189187
'error': ('There was an error in Gamma. For reference'
@@ -192,6 +190,7 @@ def get_card_info(request, card_name):
192190

193191
return HttpResponse(json.dumps(result), content_type="application/json")
194192

193+
195194
def get_card_full(request, card_name):
196195
g, variable, expression, parameters = _process_card(request, card_name)
197196

@@ -217,10 +216,8 @@ def get_card_full(request, card_name):
217216
},
218217
'input': expression
219218
}), content_type="text/html")
220-
except DeadlineExceededError:
221-
return HttpResponse('Computation timed out.',
222-
content_type="text/html")
223-
except:
219+
except Exception as e:
220+
logging.error(f'Exception: {e}')
224221
trace = traceback.format_exc(5)
225222
return HttpResponse(render_to_string('card.html', {
226223
'cell': {

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ enum34==1.1.10
99
nose==1.3.7
1010
requests==2.23.0
1111
docutils==0.16
12-
sympy==0.7.5
12+
sympy==1.6

0 commit comments

Comments
 (0)