Repository: sympy/sympy
File: sympy/parsing/sympy_parser.py (Python)

Code before:

from keyword import iskeyword

import ast
import unicodedata
from io import StringIO
import builtins
import types
from typing import Any, Callable, TYPE_CHECKING
from functools import reduce
from sympy.assumptions.ask import AssumptionKeys
from sympy.core.basic import Basic
from sympy.core import Symbol
from sympy.core.function import Function
from sympy.utilities.misc import func_name
from sympy.functions.elementary.miscellaneous import Max, Min

if TYPE_CHECKING:
    from typing_extensions import TypeAlias


null = ''

TOKEN: TypeAlias = tuple[int, str]
DICT: TypeAlias = dict[str, Any]
TRANS: TypeAlias = Callable[[list[TOKEN], DICT, DICT], list[TOKEN]]

def _token_splittable(token_name: str) -> bool:
    """
    Predicate for whether a token name can be split into multiple tokens.

    A token is splittable if it does not contain an underscore character and
    it is not the name of a Greek letter. This is used to implicitly convert
    expressions like 'xyz' into 'x*y*z'.
    """
    if '_' in token_name:
        return False
    try:
        return not unicodedata.lookup('GREEK SMALL LETTER ' + token_name)
    except KeyError:
        return len(token_name) > 1


def _token_callable(token: TOKEN, local_dict: DICT, global_dict: DICT, nextToken=None):
    """
    Predicate for whether a token name represents a callable function.

    Essentially wraps ``callable``, but looks up the token name in the
    locals and globals.
    """
    func = local_dict.get(token[1])

Review comment (suggestion):
This change makes Sphinx want to see TRANS in the docs apparently. I'm not sure what the advantage is of having TypeAlias here rather than a plain assignment. Obviously in future we will want to use the type statement but minimum Python version is 3.9 right now.

Code after:

from keyword import iskeyword

import ast
import unicodedata
from io import StringIO
import builtins
import types
from typing import Any, Callable
from functools import reduce
from sympy.assumptions.ask import AssumptionKeys
from sympy.core.basic import Basic
from sympy.core import Symbol
from sympy.core.function import Function
from sympy.utilities.misc import func_name
from sympy.functions.elementary.miscellaneous import Max, Min


null = ''

TOKEN = tuple[int, str]
DICT = dict[str, Any]
TRANS = Callable[[list[TOKEN], DICT, DICT], list[TOKEN]]

def _token_splittable(token_name: str) -> bool:
    """
    Predicate for whether a token name can be split into multiple tokens.

    A token is splittable if it does not contain an underscore character and
    it is not the name of a Greek letter. This is used to implicitly convert
    expressions like 'xyz' into 'x*y*z'.
    """
    if '_' in token_name:
        return False
    try:
        return not unicodedata.lookup('GREEK SMALL LETTER ' + token_name)
    except KeyError:
        return len(token_name) > 1


def _token_callable(token: TOKEN, local_dict: DICT, global_dict: DICT, nextToken=None):
    """
    Predicate for whether a token name represents a callable function.

    Essentially wraps ``callable``, but looks up the token name in the
    locals and globals.
    """
    func = local_dict.get(token[1])
    if not func:
        func = global_dict.get(token[1])
    return callable(func) and not isinstance(func, Symbol)