diff --git a/mathics/builtin/arithfns/basic.py b/mathics/builtin/arithfns/basic.py index cfa0be31d..c7c0b78e9 100644 --- a/mathics/builtin/arithfns/basic.py +++ b/mathics/builtin/arithfns/basic.py @@ -80,7 +80,7 @@ class CubeRoot(Builtin): } rules = { - "CubeRoot[n_?NumericQ]": "If[n > 0, Power[n, Divide[1, 3]], Times[-1, Power[Times[-1, n], Divide[1, 3]]]]", + "CubeRoot[n_?NumberQ]": "If[n > 0, Power[n, Divide[1, 3]], Times[-1, Power[Times[-1, n], Divide[1, 3]]]]", "CubeRoot[n_]": "Power[n, Divide[1, 3]]", "MakeBoxes[CubeRoot[x_], f:StandardForm|TraditionalForm]": ( "RadicalBox[MakeBoxes[x, f], 3]" diff --git a/mathics/builtin/datentime.py b/mathics/builtin/datentime.py index d552cd995..55b4ee8cf 100644 --- a/mathics/builtin/datentime.py +++ b/mathics/builtin/datentime.py @@ -899,10 +899,6 @@ class DateString(_DateFormat): rules = { "DateString[]": "DateString[DateList[], $DateStringFormat]", - "DateString[epochtime_?(VectorQ[#1, NumericQ]&)]": ( - "DateString[epochtime, $DateStringFormat]" - ), - "DateString[epochtime_?NumericQ]": ("DateString[epochtime, $DateStringFormat]"), "DateString[format_?(VectorQ[#1, StringQ]&)]": ( "DateString[DateList[], format]" ), diff --git a/mathics/builtin/drawing/graphics3d.py b/mathics/builtin/drawing/graphics3d.py index 219e5566f..d2a08e97e 100644 --- a/mathics/builtin/drawing/graphics3d.py +++ b/mathics/builtin/drawing/graphics3d.py @@ -7,7 +7,7 @@ from mathics.version import __version__ # noqa used in loading to check consistency. -from mathics.core.expression import Expression, Real +from mathics.core.expression import Expression, Real, Integer, Rational from mathics.builtin.base import BoxConstructError, Builtin, InstanceableBuiltin from mathics.builtin.colors.color_directives import RGBColor @@ -301,7 +301,10 @@ class Cylinder(Builtin): = -Graphics3D- """ - messages = {"oddn": "The number of points must be even."} + messages = { + "oddn": "The number of points must be even.", + "nrr": "The radius must be a real number", + } rules = { "Cylinder[]": "Cylinder[{{0, 0, 0}, {1, 1, 1}}, 1]", @@ -309,10 +312,14 @@ class Cylinder(Builtin): } def apply_check(self, positions, radius, evaluation): - "Cylinder[positions_List, radius_?NumericQ]" + "Cylinder[positions_List, radius_]" if len(positions.get_leaves()) % 2 == 1: # The number of points is odd, so abort. evaluation.error("Cylinder", "oddn", positions) + if not isinstance(radius, (Integer, Rational, Real)): + nradius = Expression(SymbolN, radius).evaluate(evaluation) + if not isinstance(nradius, (Integer, Rational, Real)): + evaluation.error("Cylinder", "nrr", radius) - return Expression("Cylinder", positions, radius) + return diff --git a/mathics/builtin/drawing/image.py b/mathics/builtin/drawing/image.py index 7039afa79..531ccce91 100644 --- a/mathics/builtin/drawing/image.py +++ b/mathics/builtin/drawing/image.py @@ -136,7 +136,7 @@ class ImageImport(_ImageBuiltin): """ def apply(self, path, evaluation): - """ImageImport[path_?StringQ]""" + """ImageImport[path_String]""" pillow = PIL.Image.open(path.get_string_value()) pixels = numpy.asarray(pillow) is_rgb = len(pixels.shape) >= 3 and pixels.shape[2] >= 3 diff --git a/mathics/builtin/drawing/uniform_polyhedra.py b/mathics/builtin/drawing/uniform_polyhedra.py index 80cb355f0..44475b810 100644 --- a/mathics/builtin/drawing/uniform_polyhedra.py +++ b/mathics/builtin/drawing/uniform_polyhedra.py @@ -42,7 +42,7 @@ class UniformPolyhedron(Builtin): } def apply(self, name, positions, edgelength, evaluation): - "UniformPolyhedron[name_String, positions_List, edgelength_?NumericQ]" + "UniformPolyhedron[name_String, positions_List, edgelength_?NumberQ]" if name.to_python(string_quotes=False) not in uniform_polyhedra_set: evaluation.error("UniformPolyhedron", "argtype", name) @@ -63,8 +63,8 @@ class Dodecahedron(Builtin): rules = { "Dodecahedron[]": """UniformPolyhedron["dodecahedron"]""", - "Dodecahedron[l_?NumericQ]": """UniformPolyhedron["dodecahedron", {{0, 0, 0}}, l]""", - "Dodecahedron[positions_List, l_?NumericQ]": """UniformPolyhedron["dodecahedron", positions, l]""", + "Dodecahedron[l_?NumberQ]": """UniformPolyhedron["dodecahedron", {{0, 0, 0}}, l]""", + "Dodecahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["dodecahedron", positions, l]""", } @@ -81,8 +81,8 @@ class Icosahedron(Builtin): rules = { "Icosahedron[]": """UniformPolyhedron["icosahedron"]""", - "Icosahedron[l_?NumericQ]": """UniformPolyhedron["icosahedron", {{0, 0, 0}}, l]""", - "Icosahedron[positions_List, l_?NumericQ]": """UniformPolyhedron["icosahedron", positions, l]""", + "Icosahedron[l_?NumberQ]": """UniformPolyhedron["icosahedron", {{0, 0, 0}}, l]""", + "Icosahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["icosahedron", positions, l]""", } @@ -99,8 +99,8 @@ class Octahedron(Builtin): rules = { "Octahedron[]": """UniformPolyhedron["octahedron"]""", - "Octahedron[l_?NumericQ]": """UniformPolyhedron["octahedron", {{0, 0, 0}}, l]""", - "Octahedron[positions_List, l_?NumericQ]": """UniformPolyhedron["octahedron", positions, l]""", + "Octahedron[l_?NumberQ]": """UniformPolyhedron["octahedron", {{0, 0, 0}}, l]""", + "Octahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["octahedron", positions, l]""", } @@ -117,8 +117,8 @@ class Tetrahedron(Builtin): rules = { "Tetrahedron[]": """UniformPolyhedron["tetrahedron"]""", - "Tetrahedron[l_?NumericQ]": """UniformPolyhedron["tetrahedron", {{0, 0, 0}}, l]""", - "Tetrahedron[positions_List, l_?NumericQ]": """UniformPolyhedron["tetrahedron", positions, l]""", + "Tetrahedron[l_?NumberQ]": """UniformPolyhedron["tetrahedron", {{0, 0, 0}}, l]""", + "Tetrahedron[positions_List, l_?NumberQ]": """UniformPolyhedron["tetrahedron", positions, l]""", } def apply_with_length(self, length, evaluation): diff --git a/mathics/builtin/files_io/filesystem.py b/mathics/builtin/files_io/filesystem.py index 5f62888c5..d67ca154b 100644 --- a/mathics/builtin/files_io/filesystem.py +++ b/mathics/builtin/files_io/filesystem.py @@ -1058,7 +1058,7 @@ class FileNameJoin(Builtin): } def apply(self, pathlist, evaluation, options): - "FileNameJoin[pathlist_?ListQ, OptionsPattern[FileNameJoin]]" + "FileNameJoin[pathlist_List, OptionsPattern[FileNameJoin]]" py_pathlist = pathlist.to_python() if not all(isinstance(p, str) and p[0] == p[-1] == '"' for p in py_pathlist): @@ -2217,8 +2217,8 @@ class ToFileName(Builtin): rules = { "ToFileName[dir_String, name_String]": "FileNameJoin[{dir, name}]", - "ToFileName[dirs_?ListQ, name_String]": "FileNameJoin[Append[dirs, name]]", - "ToFileName[dirs_?ListQ]": "FileNameJoin[dirs]", + "ToFileName[dirs_List, name_String]": "FileNameJoin[Append[dirs, name]]", + "ToFileName[dirs_List]": "FileNameJoin[dirs]", } diff --git a/mathics/builtin/inout.py b/mathics/builtin/inout.py index 4ef568e3f..73b669f7c 100644 --- a/mathics/builtin/inout.py +++ b/mathics/builtin/inout.py @@ -2526,7 +2526,7 @@ def default_NumberFormat(man, base, exp, options): return man def apply_list_n(self, expr, n, evaluation, options) -> Expression: - "NumberForm[expr_?ListQ, n_, OptionsPattern[NumberForm]]" + "NumberForm[expr_List, n_, OptionsPattern[NumberForm]]" options = [ Expression("RuleDelayed", Symbol(key), value) for key, value in options.items() @@ -2537,7 +2537,7 @@ def apply_list_n(self, expr, n, evaluation, options) -> Expression: ) def apply_list_nf(self, expr, n, f, evaluation, options) -> Expression: - "NumberForm[expr_?ListQ, {n_, f_}, OptionsPattern[NumberForm]]" + "NumberForm[expr_List, {n_, f_}, OptionsPattern[NumberForm]]" options = [ Expression("RuleDelayed", Symbol(key), value) for key, value in options.items() diff --git a/mathics/builtin/intfns/combinatorial.py b/mathics/builtin/intfns/combinatorial.py index e12e373aa..dc8f69210 100644 --- a/mathics/builtin/intfns/combinatorial.py +++ b/mathics/builtin/intfns/combinatorial.py @@ -381,7 +381,7 @@ class Subsets(Builtin): """ rules = { - "Subsets[list_ , Pattern[n,_?ListQ|All|DirectedInfinity[1]], spec_]": "Take[Subsets[list, n], spec]", + "Subsets[list_ , Pattern[n,_List|All|DirectedInfinity[1]], spec_]": "Take[Subsets[list, n], spec]", } messages = { @@ -421,7 +421,7 @@ def apply_1(self, list, n, evaluation): return Expression("List", *nested_list) def apply_2(self, list, n, evaluation): - "Subsets[list_, Pattern[n,_?ListQ|All|DirectedInfinity[1]]]" + "Subsets[list_, Pattern[n,_List|All|DirectedInfinity[1]]]" expr = Expression("Subsets", list, n) @@ -495,7 +495,7 @@ def apply_2(self, list, n, evaluation): return Expression("List", *nested_list) def apply_3(self, list, n, spec, evaluation): - "Subsets[list_?AtomQ, Pattern[n,_?ListQ|All|DirectedInfinity[1]], spec_]" + "Subsets[list_?AtomQ, Pattern[n,_List|All|DirectedInfinity[1]], spec_]" return evaluation.message( "Subsets", "normal", Expression("Subsets", list, n, spec) diff --git a/mathics/builtin/lists.py b/mathics/builtin/lists.py index 5df4c8e20..9359b28a8 100644 --- a/mathics/builtin/lists.py +++ b/mathics/builtin/lists.py @@ -311,7 +311,7 @@ def check_options(self, expr, evaluation, options): return None def apply(self, list1, list2, evaluation, options={}): - "ContainsOnly[list1_?ListQ, list2_?ListQ, OptionsPattern[ContainsOnly]]" + "ContainsOnly[list1_List, list2_List, OptionsPattern[ContainsOnly]]" same_test = self.get_option(options, "SameTest", evaluation) @@ -1320,7 +1320,7 @@ def apply(self, mlist, func, evaluation): return outer([inner(l) for l in result]) def apply_multiple(self, mlist, funcs, evaluation): - "SplitBy[mlist_, funcs_?ListQ]" + "SplitBy[mlist_, funcs_List]" expr = Expression("Split", mlist, funcs) if mlist.is_atom(): diff --git a/mathics/builtin/numbers/calculus.py b/mathics/builtin/numbers/calculus.py index 995d12877..f180eb0da 100644 --- a/mathics/builtin/numbers/calculus.py +++ b/mathics/builtin/numbers/calculus.py @@ -852,7 +852,7 @@ class Solve(Builtin): "Cases[Solve[eqs, vars], {Rule[x_,y_?RealNumberQ]}]" ), "Solve[eqs_, vars_, Integers]": ( - "Cases[Solve[eqs, vars], {Rule[x_,y_?IntegerQ]}]" + "Cases[Solve[eqs, vars], {Rule[x_,y_Integer]}]" ), } diff --git a/mathics/builtin/numbers/numbertheory.py b/mathics/builtin/numbers/numbertheory.py index c29c90795..982b3b6a2 100644 --- a/mathics/builtin/numbers/numbertheory.py +++ b/mathics/builtin/numbers/numbertheory.py @@ -268,7 +268,7 @@ class FromContinuedFraction(SympyFunction): attributes = ("NumericFunction",) def apply_1(self, expr, evaluation): - "%(name)s[expr_?ListQ]" + "%(name)s[expr_List]" nums = expr.to_python() if all(isinstance(i, int) for i in nums): return from_sympy(sympy.continued_fraction_reduce(nums)) @@ -487,7 +487,7 @@ class NextPrime(Builtin): } def apply(self, n, k, evaluation): - "NextPrime[n_?NumericQ, k_?IntegerQ]" + "NextPrime[n_?NumericQ, k_Integer]" py_k = k.to_python(n_evaluation=evaluation) py_n = n.to_python(n_evaluation=evaluation) @@ -711,10 +711,8 @@ class RandomPrime(Builtin): rules = { "RandomPrime[imax_?NotListQ]": "RandomPrime[{1, imax}, 1]", - "RandomPrime[int_?ListQ]": "RandomPrime[int, 1]", - "RandomPrime[imax_?ListQ, n_?ArrayQ]": ( - "ConstantArray[RandomPrime[imax, 1], n]" - ), + "RandomPrime[int_List]": "RandomPrime[int, 1]", + "RandomPrime[imax_List, n_?ArrayQ]": ("ConstantArray[RandomPrime[imax, 1], n]"), "RandomPrime[imax_?NotListQ, n_?ArrayQ]": ( "ConstantArray[RandomPrime[{1, imax}, 1], n]" ), @@ -723,7 +721,7 @@ class RandomPrime(Builtin): # TODO: Use random state as in other randomised methods within mathics def apply(self, interval, n, evaluation): - "RandomPrime[interval_?ListQ, n_]" + "RandomPrime[interval_List, n_]" if not isinstance(n, Integer): evaluation.message("RandomPrime", "posdim", n) diff --git a/mathics/builtin/numbers/randomnumbers.py b/mathics/builtin/numbers/randomnumbers.py index d7edd91fe..d2dd03bd3 100644 --- a/mathics/builtin/numbers/randomnumbers.py +++ b/mathics/builtin/numbers/randomnumbers.py @@ -325,7 +325,7 @@ def apply(self, rmin, rmax, evaluation): return Integer(rand.randint(rmin, rmax)) def apply_list(self, rmin, rmax, ns, evaluation): - "RandomInteger[{rmin_, rmax_}, ns_?ListQ]" + "RandomInteger[{rmin_, rmax_}, ns_List]" if not isinstance(rmin, Integer) or not isinstance(rmax, Integer): return evaluation.message( "RandomInteger", "unifr", Expression("List", rmin, rmax) @@ -406,7 +406,7 @@ def apply(self, xmin, xmax, evaluation): return Real(rand.randreal(min_value, max_value)) def apply_list(self, xmin, xmax, ns, evaluation): - "RandomReal[{xmin_, xmax_}, ns_?ListQ]" + "RandomReal[{xmin_, xmax_}, ns_List]" if not ( isinstance(xmin, (Real, Integer)) and isinstance(xmax, (Real, Integer)) @@ -717,7 +717,7 @@ class Random(Builtin): "Random[Real, {zmin_Real, zmax_Real}]": "RandomReal[{zmin, zmax}]", "Random[Complex]": "RandomComplex[]", "Random[Complex, zmax_Complex]": "RandomComplex[zmax]", - "Random[Complex, {zmin_?NumericQ, zmax_?NumericQ}]": "RandomComplex[{zmin, zmax}]", + "Random[Complex, {zmin_?NumberQ, zmax_?NumberQ}]": "RandomComplex[{zmin, zmax}]", } diff --git a/mathics/builtin/optimization.py b/mathics/builtin/optimization.py index 51c15c36b..f0f9729bf 100644 --- a/mathics/builtin/optimization.py +++ b/mathics/builtin/optimization.py @@ -69,7 +69,7 @@ def apply_onevariable(self, f, x, evaluation): ) def apply_multiplevariable(self, f, vars, evaluation): - "Minimize[f_?NotListQ, vars_?ListQ]" + "Minimize[f_?NotListQ, vars_List]" head_name = vars.get_head_name() vars_or = vars @@ -149,7 +149,7 @@ def apply_multiplevariable(self, f, vars, evaluation): ) def apply_constraints(self, f, vars, evaluation): - "Minimize[f_?ListQ, vars_?ListQ]" + "Minimize[f_List, vars_List]" head_name = vars.get_head_name() vars_or = vars vars = vars.leaves @@ -380,7 +380,7 @@ def apply(self, f, vars, evaluation): return from_python(solutions) def apply_constraints(self, f, vars, evaluation): - "Maximize[f_?ListQ, vars_]" + "Maximize[f_List, vars_]" constraints = [function for function in f.leaves] constraints[0] = from_sympy(constraints[0].to_sympy() * -1) diff --git a/mathics/builtin/patterns.py b/mathics/builtin/patterns.py index c7b535b7d..958ae6edc 100644 --- a/mathics/builtin/patterns.py +++ b/mathics/builtin/patterns.py @@ -51,6 +51,7 @@ Real, SymbolFalse, SymbolList, + SymbolN, SymbolTrue, ) from mathics.core.rules import Rule @@ -476,9 +477,16 @@ def init(self, expr): def quick_pattern_test(self, candidate, test, evaluation): if test == "System`NumberQ": return isinstance(candidate, Number) + if test == "System`NumericQ": + if isinstance(candidate, Number): + return True + # Otherwise, follow the standard evaluation elif test == "System`RealNumberQ": if isinstance(candidate, (Integer, Rational, Real)): return True + candidate = Expression(SymbolN, candidate).evaluate(evaluation) + if isinstance(candidate, Real): + return True return False # pass elif test == "System`Positive": @@ -486,11 +494,21 @@ def quick_pattern_test(self, candidate, test, evaluation): return candidate.value > 0 return False # pass + elif test == "System`NonPositive": + if isinstance(candidate, (Integer, Rational, Real)): + return candidate.value <= 0 + return False + # pass elif test == "System`Negative": if isinstance(candidate, (Integer, Rational, Real)): return candidate.value < 0 return False # pass + elif test == "System`NonNegative": + if isinstance(candidate, (Integer, Rational, Real)): + return candidate.value >= 0 + return False + # pass elif test == "System`NegativePowerQ": return ( candidate.has_form("Power", 2) diff --git a/mathics/builtin/physchemdata.py b/mathics/builtin/physchemdata.py index a0793d071..4e0048ef8 100644 --- a/mathics/builtin/physchemdata.py +++ b/mathics/builtin/physchemdata.py @@ -144,7 +144,7 @@ def apply_name(self, name, prop, evaluation): return self.apply_int(from_python(indx), prop, evaluation) def apply_int(self, n, prop, evaluation): - "ElementData[n_?IntegerQ, prop_]" + "ElementData[n_Integer, prop_]" py_n = n.to_python() py_prop = prop.to_python() diff --git a/mathics/builtin/quantities.py b/mathics/builtin/quantities.py index 343eba996..7dc421480 100644 --- a/mathics/builtin/quantities.py +++ b/mathics/builtin/quantities.py @@ -189,7 +189,7 @@ def validate(self, unit, evaluation): return True def apply_makeboxes(self, mag, unit, f, evaluation): - "MakeBoxes[Quantity[mag_, unit_?StringQ], f:StandardForm|TraditionalForm|OutputForm|InputForm]" + "MakeBoxes[Quantity[mag_, unit_String], f:StandardForm|TraditionalForm|OutputForm|InputForm]" q_unit = unit.get_string_value().lower() if self.validate(unit, evaluation): @@ -200,7 +200,7 @@ def apply_makeboxes(self, mag, unit, f, evaluation): ) def apply_n(self, mag, unit, evaluation): - "Quantity[mag_, unit_?StringQ]" + "Quantity[mag_, unit_String]" if self.validate(unit, evaluation): if mag.has_form("List", None): diff --git a/mathics/builtin/system.py b/mathics/builtin/system.py index 7153ddee8..f8e1ba914 100644 --- a/mathics/builtin/system.py +++ b/mathics/builtin/system.py @@ -94,7 +94,7 @@ class Environment(Builtin): """ def apply(self, var, evaluation): - "Environment[var_?StringQ]" + "Environment[var_String]" env_var = var.get_string_value() if env_var not in os.environ: return SymbolFailed @@ -358,7 +358,7 @@ class Run(Builtin): """ def apply(self, command, evaluation): - "Run[command_?StringQ]" + "Run[command_String]" command_str = command.to_python() return Integer(subprocess.call(command_str, shell=True))