Skip to content

Commit 6212284

Browse files
authored
Fix mypy errors (#1145)
I've been going through fixing mypy errors, and have gotten through about half of them. In the process I've added some extra error handling that fixes some exceptions I've seen due to methods being called on the wrong types. Current master: > Found 1718 errors in 183 files (checked 443 source files) This branch: > Found 872 errors in 155 files (checked 443 source files) Feel free to squash all these commits, the only reason I've left them separate is that I made sure the test suite was passing after each one.
1 parent 2f709d7 commit 6212284

29 files changed

+517
-395
lines changed

mathics/builtin/atomic/numbers.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ class MaxPrecision(Predefined):
668668
= 3.141592654
669669
"""
670670

671-
is_numeric = False
671+
_is_numeric = False
672672
messages = {
673673
"precset": "Cannot set `1` to `2`; value must be a positive number or Infinity.",
674674
"preccon": "Cannot set `1` such that $MaxPrecision < $MinPrecision.",
@@ -702,7 +702,7 @@ class MachineEpsilon_(Predefined):
702702
= {0., 0., 2.22045×10^-16}
703703
"""
704704

705-
is_numeric = True
705+
_is_numeric = True
706706
name = "$MachineEpsilon"
707707

708708
summary_text = "the difference between 1.0 and the next-nearest number representable as a machine-precision number"
@@ -729,7 +729,7 @@ class MachinePrecision_(Predefined):
729729
summary_text = (
730730
"the number of decimal digits of precision for machine-precision numbers"
731731
)
732-
is_numeric = True
732+
_is_numeric = True
733733
rules = {
734734
"$MachinePrecision": "N[MachinePrecision]",
735735
}
@@ -749,7 +749,7 @@ class MachinePrecision(Predefined):
749749
= 15.9545897701910033463281614204
750750
"""
751751

752-
is_numeric = True
752+
_is_numeric = True
753753
rules = {
754754
"N[MachinePrecision, prec_]": (
755755
"N[Log[10, 2] * %i, prec]" % FP_MANTISA_BINARY_DIGITS
@@ -786,7 +786,7 @@ class MinPrecision(Builtin):
786786
}
787787

788788
name = "$MinPrecision"
789-
is_numeric = True
789+
_is_numeric = True
790790
rules = {
791791
"$MinPrecision": "0",
792792
}

mathics/builtin/box/expression.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# This is never intended to go in Mathics3 docs
22
no_doc = True
33

4+
from typing import Optional, Sequence, Union
5+
46
from mathics.core.attributes import A_PROTECTED, A_READ_PROTECTED
57
from mathics.core.builtin import BuiltinElement
68
from mathics.core.element import BoxElementMixin
@@ -109,8 +111,8 @@ def get_head_name(self):
109111
def get_lookup_name(self):
110112
return self.get_name()
111113

112-
def get_sort_key(self) -> tuple:
113-
return self.to_expression().get_sort_key()
114+
def get_sort_key(self, pattern_sort=False) -> tuple:
115+
return self.to_expression().get_sort_key(pattern_sort)
114116

115117
def get_string_value(self):
116118
return "-@" + self.get_head_name() + "@-"
@@ -119,7 +121,13 @@ def get_string_value(self):
119121
def head(self):
120122
return self.get_head()
121123

122-
def has_form(self, heads, *element_counts):
124+
@head.setter
125+
def head(self, value):
126+
raise ValueError("BoxExpression.head is write protected.")
127+
128+
def has_form(
129+
self, heads: Union[Sequence[str], str], *element_counts: Optional[int]
130+
) -> bool:
123131
"""
124132
element_counts:
125133
(,): no elements allowed
@@ -133,9 +141,13 @@ def has_form(self, heads, *element_counts):
133141
if isinstance(heads, (tuple, list, set)):
134142
if head_name not in [ensure_context(h) for h in heads]:
135143
return False
136-
else:
144+
elif isinstance(heads, str):
137145
if head_name != ensure_context(heads):
138146
return False
147+
else:
148+
raise TypeError(
149+
f"Heads must be a string or a sequence of strings, not {type(heads)}"
150+
)
139151
if not element_counts:
140152
return False
141153
if element_counts and element_counts[0] is not None:
@@ -151,10 +163,6 @@ def has_form(self, heads, *element_counts):
151163
return False
152164
return True
153165

154-
@head.setter
155-
def head(self, value):
156-
raise ValueError("BoxExpression.head is write protected.")
157-
158166
@property
159167
def is_literal(self) -> bool:
160168
"""

mathics/builtin/list/constructing.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
See also Constructing Vectors.
99
"""
1010

11+
import typing
1112
from itertools import permutations
13+
from typing import Optional, Tuple
1214

1315
from mathics.builtin.box.layout import RowBox
1416
from mathics.core.atoms import Integer, is_integer_rational_or_real
@@ -20,7 +22,7 @@
2022
from mathics.core.evaluation import Evaluation
2123
from mathics.core.expression import Expression, structure
2224
from mathics.core.list import ListExpression
23-
from mathics.core.symbols import Atom
25+
from mathics.core.symbols import Atom, Symbol
2426
from mathics.core.systemsymbols import SymbolNormal
2527
from mathics.eval.lists import get_tuples, list_boxes
2628

@@ -268,9 +270,9 @@ def eval(self, imin, imax, di, evaluation: Evaluation):
268270
and isinstance(di, Integer)
269271
):
270272
pm = 1 if di.value >= 0 else -1
271-
result = [Integer(i) for i in range(imin.value, imax.value + pm, di.value)]
272273
return ListExpression(
273-
*result, elements_properties=range_list_elements_properties
274+
*[Integer(i) for i in range(imin.value, imax.value + pm, di.value)],
275+
elements_properties=range_list_elements_properties,
274276
)
275277

276278
imin = imin.to_sympy()
@@ -344,7 +346,7 @@ def eval(self, li, evaluation: Evaluation):
344346
def eval_n(self, li, n, evaluation: Evaluation):
345347
"Permutations[li_List, n_]"
346348

347-
rs = None
349+
rs: Optional[Tuple[int, ...]] = None
348350
if isinstance(n, Integer):
349351
py_n = min(n.get_int_value(), len(li.elements))
350352
elif n.has_form("List", 1) and isinstance(n.elements[0], Integer):
@@ -359,12 +361,12 @@ def eval_n(self, li, n, evaluation: Evaluation):
359361

360362
if py_n is None or py_n < 0:
361363
evaluation.message(
362-
self.get_name(), "nninfseq", Expression(self.get_name(), li, n)
364+
self.get_name(), "nninfseq", Expression(Symbol(self.get_name()), li, n)
363365
)
364366
return
365367

366368
if rs is None:
367-
rs = range(py_n + 1)
369+
rs = tuple(range(py_n + 1))
368370

369371
inner = structure("List", li, evaluation)
370372
outer = structure("List", inner, evaluation)
@@ -431,7 +433,7 @@ def eval(self, expr, patterns, f, evaluation: Evaluation):
431433
"Reap[expr_, {patterns___}, f_]"
432434

433435
patterns = patterns.get_sequence()
434-
sown = [
436+
sown: typing.List[typing.Tuple[BasePattern, list]] = [
435437
(BasePattern.create(pattern, evaluation=evaluation), [])
436438
for pattern in patterns
437439
]

mathics/builtin/list/rearrange.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ def eval_zero(self, element, n, evaluation: Evaluation):
232232
Integer0,
233233
Integer0,
234234
evaluation,
235-
lambda: Expression(self.get_name(), element, n),
235+
lambda: Expression(Symbol(self.get_name()), element, n),
236236
)
237237

238238
def eval(self, element, n, x, evaluation: Evaluation):
@@ -243,7 +243,7 @@ def eval(self, element, n, x, evaluation: Evaluation):
243243
x,
244244
Integer0,
245245
evaluation,
246-
lambda: Expression(self.get_name(), element, n, x),
246+
lambda: Expression(Symbol(self.get_name()), element, n, x),
247247
)
248248

249249
def eval_margin(self, element, n, x, m, evaluation: Evaluation):
@@ -254,7 +254,7 @@ def eval_margin(self, element, n, x, m, evaluation: Evaluation):
254254
x,
255255
m,
256256
evaluation,
257-
lambda: Expression(self.get_name(), element, n, x, m),
257+
lambda: Expression(Symbol(self.get_name()), element, n, x, m),
258258
)
259259

260260

@@ -354,6 +354,8 @@ def _gather(self, keys, values, equivalence):
354354
class _Rotate(Builtin):
355355
messages = {"rspec": "`` should be an integer or a list of integers."}
356356

357+
_sign: int
358+
357359
def _rotate(self, expr, n, evaluation: Evaluation):
358360
if not isinstance(expr, Expression):
359361
return expr
@@ -363,12 +365,12 @@ def _rotate(self, expr, n, evaluation: Evaluation):
363365
return expr
364366

365367
index = (self._sign * n[0]) % len(elements) # with Python's modulo: index >= 1
366-
new_elements = chain(elements[index:], elements[:index])
368+
new_elements = tuple(chain(elements[index:], elements[:index]))
367369

368370
if len(n) > 1:
369-
new_elements = [
371+
new_elements = tuple(
370372
self._rotate(item, n[1:], evaluation) for item in new_elements
371-
]
373+
)
372374

373375
return expr.restructure(expr.head, new_elements, evaluation)
374376

mathics/builtin/numbers/algebra.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,9 @@ def eval(self, expr, evaluation):
438438

439439

440440
# Get a coefficient of form in an expression
441-
def _coefficient(name, expr, form, n, evaluation):
441+
def _coefficient(
442+
name: str, expr: Expression, form: Expression, n: Integer, evaluation: Evaluation
443+
) -> BaseElement:
442444
if expr is SymbolNull or form is SymbolNull or n is SymbolNull:
443445
return Integer0
444446

@@ -450,18 +452,11 @@ def _coefficient(name, expr, form, n, evaluation):
450452
sympy_var = form.to_sympy()
451453
sympy_n = n.to_sympy()
452454

453-
def combine_exprs(exprs):
454-
result = 0
455-
for e in exprs:
456-
result += e
457-
return result
458-
459455
# expand sub expressions if they contain variables
460-
sympy_exprs = [
456+
sympy_expr: sympy.Expr = sum(
461457
sympy.expand(e) if sympy_var.free_symbols.issubset(e.free_symbols) else e
462458
for e in sympy_exprs
463-
]
464-
sympy_expr = combine_exprs(sympy_exprs)
459+
)
465460
sympy_result = sympy_expr.coeff(sympy_var, sympy_n)
466461
return from_sympy(sympy_result)
467462

@@ -519,16 +514,18 @@ class Coefficient(Builtin):
519514

520515
summary_text = "coefficient of a monomial in a polynomial expression"
521516

522-
def eval_noform(self, expr, evaluation):
517+
def eval_noform(self, expr: Expression, evaluation: Evaluation):
523518
"Coefficient[expr_]"
524519
evaluation.message("Coefficient", "argtu")
525520

526-
def eval(self, expr, form, evaluation):
521+
def eval(self, expr: Expression, form: Expression, evaluation: Evaluation):
527522
"Coefficient[expr_, form_]"
528523
return _coefficient(self.__class__.__name__, expr, form, Integer1, evaluation)
529524

530-
def eval_n(self, expr, form, n, evaluation):
531-
"Coefficient[expr_, form_, n_]"
525+
def eval_n(
526+
self, expr: Expression, form: Expression, n: Integer, evaluation: Evaluation
527+
):
528+
"Coefficient[expr_, form_, n_Integer]"
532529
return _coefficient(self.__class__.__name__, expr, form, n, evaluation)
533530

534531

@@ -559,9 +556,8 @@ def coeff_power_internal(
559556

560557
# ###### Auxiliary functions #########
561558
def key_powers(lst: list) -> Union[int, float]:
562-
key = Expression(SymbolPlus, *lst)
563-
key = key.evaluate(evaluation)
564-
if key.is_numeric(evaluation):
559+
key = Expression(SymbolPlus, *lst).evaluate(evaluation)
560+
if key is not None and key.is_numeric(evaluation):
565561
return key.to_python()
566562
return 0
567563

0 commit comments

Comments
 (0)