Skip to content

Commit

Permalink
Modernize Python metadata (local) (#1014)
Browse files Browse the repository at this point in the history
Local fork of #1013 - Adds redoes packaging in the form that 3.12 is
going to need since setuptools is deprecated.

In the process, something happened with the way that Cython gets run and
we were then getting lots of Cython type annotation mismatch failures.
So these have been corrected.

We could split this into just the Cython corrections and then apply the
packaging toml changes in #1013.

Your thoughts? @mmatera  and @mkoeppe

---------

Co-authored-by: Matthias Koeppe <[email protected]>
  • Loading branch information
rocky and mkoeppe authored Mar 12, 2024
1 parent 8c66dee commit ffb3647
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 186 deletions.
2 changes: 1 addition & 1 deletion mathics/builtin/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ def match(self, yield_func, expression, vars, evaluation, **kwargs):
yield_func(vars, None)

def get_match_candidates(
self, elements, expression, attributes, evaluation, vars={}
self, elements: tuple, expression, attributes, evaluation, vars={}
):
existing = vars.get(self.varname, None)
if existing is None:
Expand Down
9 changes: 5 additions & 4 deletions mathics/core/atoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ def __neg__(self) -> "MachineReal":
def do_copy(self) -> "MachineReal":
return MachineReal(self._value)

def get_precision(self) -> float:
def get_precision(self) -> int:
"""Returns the default specification for precision in N and other numerical functions."""
return FP_MANTISA_BINARY_DIGITS

Expand Down Expand Up @@ -545,9 +545,9 @@ def __neg__(self) -> "PrecisionReal":
def do_copy(self) -> "PrecisionReal":
return PrecisionReal(self.value)

def get_precision(self) -> float:
def get_precision(self) -> int:
"""Returns the default specification for precision (in binary digits) in N and other numerical functions."""
return self.value._prec + 1.0
return self.value._prec + 1

@property
def is_zero(self) -> bool:
Expand Down Expand Up @@ -801,6 +801,7 @@ def is_machine_precision(self) -> bool:
return True
return False

# FIXME: funny name get_float_value returns complex?
def get_float_value(self, permit_complex=False) -> Optional[complex]:
if permit_complex:
real = self.real.get_float_value()
Expand All @@ -810,7 +811,7 @@ def get_float_value(self, permit_complex=False) -> Optional[complex]:
else:
return None

def get_precision(self) -> Optional[float]:
def get_precision(self) -> Optional[int]:
"""Returns the default specification for precision in N and other numerical functions.
When `None` is be returned no precision is has been defined and this object's value is
exact.
Expand Down
6 changes: 3 additions & 3 deletions mathics/core/builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import re
from functools import lru_cache, total_ordering
from itertools import chain
from typing import Any, Callable, Dict, Iterable, List, Optional, Union, cast
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union, cast

import mpmath
import sympy
Expand Down Expand Up @@ -1122,8 +1122,8 @@ def get_lookup_name(self) -> str:
return self.get_name()

def get_match_candidates(
self, elements, expression, attributes, evaluation, vars={}
):
self, elements: Tuple[BaseElement], expression, attributes, evaluation, vars={}
) -> Tuple[BaseElement]:
return elements

def get_match_count(self, vars={}):
Expand Down
2 changes: 1 addition & 1 deletion mathics/core/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ def get_name(self):
def get_option_values(self, evaluation, allow_symbols=False, stop_on_error=True):
pass

def get_precision(self) -> Optional[float]:
def get_precision(self) -> Optional[int]:
"""Returns the default specification for precision in N and other
numerical functions. It is expected to be redefined in those
classes that provide inexact arithmetic like PrecisionReal.
Expand Down
6 changes: 4 additions & 2 deletions mathics/core/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import time
from bisect import bisect_left
from itertools import chain
from typing import Any, Callable, Iterable, List, Optional, Tuple, Type
from typing import Any, Callable, Iterable, List, Optional, Tuple, Type, Union

import sympy

Expand Down Expand Up @@ -1356,7 +1356,9 @@ def rules():
# Expr8: to_expression("Plus", n1,..., n1) (nontrivial evaluation to a long expression, with just undefined symbols)
#

def round_to_float(self, evaluation=None, permit_complex=False) -> Optional[float]:
def round_to_float(
self, evaluation=None, permit_complex=False
) -> Optional[Union[float, complex]]:
"""
Round to a Python float. Return None if rounding is not possible.
This can happen if self or evaluation is NaN.
Expand Down
6 changes: 3 additions & 3 deletions mathics/core/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import string
from math import ceil, log
from sys import float_info
from typing import List, Optional
from typing import List, Optional, Union

import mpmath
import sympy
Expand Down Expand Up @@ -70,7 +70,7 @@ def _get_float_inf(value, evaluation) -> Optional[float]:

def get_precision(
value: BaseElement, evaluation, show_messages: bool = True
) -> Optional[float]:
) -> Optional[Union[int, float]]:
"""
Returns the ``float`` in the interval [``$MinPrecision``, ``$MaxPrecision``] closest
to ``value``.
Expand Down Expand Up @@ -136,7 +136,7 @@ def prec(dps) -> int:
return max(1, int(round((int(dps) + 1) * LOG2_10)))


def min_prec(*args: BaseElement) -> Optional[float]:
def min_prec(*args: BaseElement) -> Optional[int]:
"""
Returns the precision of the expression with the minimum precision.
If all the expressions are exact or non numeric, return None.
Expand Down
10 changes: 5 additions & 5 deletions mathics/core/pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def get_match_candidates(
evaluation: Evaluation,
vars: dict = {},
):
return []
return tuple()

def get_match_candidates_count(
self,
Expand Down Expand Up @@ -434,7 +434,7 @@ def yield_choice(pre_vars):
self.match_element(
yield_func,
next_element,
next_elements,
tuple(next_elements),
([], expression.elements),
pre_vars,
expression,
Expand Down Expand Up @@ -642,7 +642,7 @@ def yield_next(next):
# for setting in per_name(groups.items(), vars):
# def yield_name(setting):
# yield_func(setting)
per_name(yield_choice, list(groups.items()), vars)
per_name(yield_choice, tuple(groups.items()), vars)
else:
yield_choice(vars)

Expand Down Expand Up @@ -715,7 +715,7 @@ def match_element(

match_count = element.get_match_count(vars)
element_candidates = element.get_match_candidates(
rest_expression[1], # element.candidates,
tuple(rest_expression[1]), # element.candidates,
expression,
attributes,
evaluation,
Expand Down Expand Up @@ -861,7 +861,7 @@ def yield_wrapping(item):

self.get_wrappings(
yield_wrapping,
items,
tuple(items),
match_count[1],
expression,
attributes,
Expand Down
11 changes: 9 additions & 2 deletions mathics/core/symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-

import time
from typing import Any, FrozenSet, List, Optional
from typing import Any, FrozenSet, List, Optional, Union

from mathics.core.element import (
BaseElement,
Expand Down Expand Up @@ -666,6 +666,9 @@ class SymbolConstant(Symbol):

# We use __new__ here to unsure that two Integer's that have the same value
# return the same object.

_value = None

def __new__(cls, name, value):
name = ensure_context(name)
self = cls._symbol_constants.get(name)
Expand Down Expand Up @@ -830,7 +833,11 @@ def __floordiv__(self, other) -> BaseElement:
def __pow__(self, other) -> BaseElement:
return self.create_expression(SymbolPower, self, other)

def round_to_float(self, evaluation=None, permit_complex=False) -> Optional[float]:
# FIXME: The name "round_to_float" is misleading when
# permit_complex is True.
def round_to_float(
self, evaluation=None, permit_complex=False
) -> Optional[Union[complex, float]]:
"""
Round to a Python float. Return None if rounding is not possible.
This can happen if self or evaluation is NaN.
Expand Down
2 changes: 1 addition & 1 deletion mathics/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def permutations(items):
item = items[index]
# if item not in already_taken:
for sub in permutations(items[:index] + items[index + 1 :]):
yield [item] + sub
yield [item] + list(sub)
# already_taken.add(item)


Expand Down
7 changes: 5 additions & 2 deletions mathics/eval/makeboxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


import typing
from typing import Any, Dict, Type
from typing import Any, Dict, Optional, Type

from mathics.core.atoms import Complex, Integer, Rational, Real, String, SymbolI
from mathics.core.convert.expression import to_expression_with_specialization
Expand Down Expand Up @@ -392,7 +392,10 @@ def do_format_expression(


def parenthesize(
precedence: int, element: Type[BaseElement], element_boxes, when_equal: bool
precedence: Optional[int],
element: Type[BaseElement],
element_boxes,
when_equal: bool,
) -> Type[Expression]:
"""
"Determines if ``element_boxes`` needs to be surrounded with parenthesis.
Expand Down
146 changes: 146 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
[build-system]
requires = [
"setuptools>=61.2",
"cython>=0.15.1; implementation_name!='pypy'"
]

[project]
name = "Mathics3"
description = "A general-purpose computer algebra system."
dependencies = [
"Mathics-Scanner >= 1.3.0",
"llvmlite",
"mpmath>=1.2.0",
"numpy<1.27",
"palettable",
# Pillow 9.1.0 supports BigTIFF with big-endian byte order.
# ExampleData image hedy.tif is in this format.
# Pillow 9.2 handles sunflowers.jpg
"pillow >= 9.2",
"pint",
"python-dateutil",
"requests",
"setuptools",
"sympy>=1.8",
]
requires-python = ">=3.7"
readme = "README.rst"
license = {text = "GPL"}
keywords = ["Mathematica", "Wolfram", "Interpreter", "Shell", "Math", "CAS"]
maintainers = [
{name = "Mathics Group", email = "[email protected]"},
]
classifiers = [
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Programming Language :: Python",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Mathematics",
"Topic :: Scientific/Engineering :: Physics",
"Topic :: Software Development :: Interpreters",
]
dynamic = ["version"]

[project.urls]
Homepage = "https://mathics.org/"
Downloads = "https://github.com/Mathics3/mathics-core/releases"

[project.optional-dependencies]
dev = [
"pexpect",
"pytest",
]
full = [
"ipywidgets",
"lxml",
"psutil",
"pyocr",
"scikit-image >= 0.17",
"unidecode",
"wordcloud >= 1.9.3",
]
cython = [
"cython",
]

[project.scripts]
mathics = "mathics.main:main"

[tool.setuptools]
include-package-data = false
packages = [
"mathics",
"mathics.algorithm",
"mathics.compile",
"mathics.core",
"mathics.core.convert",
"mathics.core.parser",
"mathics.builtin",
"mathics.builtin.arithfns",
"mathics.builtin.assignments",
"mathics.builtin.atomic",
"mathics.builtin.binary",
"mathics.builtin.box",
"mathics.builtin.colors",
"mathics.builtin.distance",
"mathics.builtin.exp_structure",
"mathics.builtin.drawing",
"mathics.builtin.fileformats",
"mathics.builtin.files_io",
"mathics.builtin.forms",
"mathics.builtin.functional",
"mathics.builtin.image",
"mathics.builtin.intfns",
"mathics.builtin.list",
"mathics.builtin.matrices",
"mathics.builtin.numbers",
"mathics.builtin.numpy_utils",
"mathics.builtin.pymimesniffer",
"mathics.builtin.pympler",
"mathics.builtin.quantum_mechanics",
"mathics.builtin.scipy_utils",
"mathics.builtin.specialfns",
"mathics.builtin.statistics",
"mathics.builtin.string",
"mathics.builtin.testing_expressions",
"mathics.builtin.vectors",
"mathics.eval",
"mathics.doc",
"mathics.format",
]

[tool.setuptools.package-data]
"mathics" = [
"data/*.csv",
"data/*.json",
"data/*.yml",
"data/*.yaml",
"data/*.pcl",
"data/ExampleData/*",
"doc/xml/data",
"doc/tex/data",
"autoload/*.m",
"autoload-cli/*.m",
"autoload/formats/*/Import.m",
"autoload/formats/*/Export.m",
"packages/*/*.m",
"packages/*/Kernel/init.m",
]
"mathics.doc" = [
"documentation/*.mdoc",
"xml/data",
]
"mathics.builtin.pymimesniffer" = [
"mimetypes.xml",
]

[tool.setuptools.dynamic]
version = {attr = "mathics.version.__version__"}
Loading

1 comment on commit ffb3647

@mmatera
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this PR makes everything work again, I am OK to merge this all together. Thanks again @mkoeppe and @rocky for all this work!

Please sign in to comment.