Python Compatibility

calcpy is compatible with Python 3.8+ only since it depends on some features of Python 3.8.

It is not recommended to deploy it in older Python versions, but if you indeed want to support older Python versions, you can download source codes from GitHub and remove the dependencies in the source codes.

Download Source Codes

Visit http://www.github.com/zhiqingxiao/calcpy to download the source codes.

Remove Dependency on Python 3.8

The codes depend on Python 3.8 feature positional only parameters (PEP 570). In order to remove this dependency, you can remove all , / in the source codes.

The version __version__ is generated by importlib.metadata, which is available in Python 3.8. In order to remove this dependency, you can replace importlib.metadata with the third-party package importlib_metadata.

The file /_api.py uses some functions that are provided by Python 3.8+ only, including math.comb(), math.dist(), math.isqrt(), math.prod(). You can remove the the dependency by the following changes:

  • Search comb = math.comb in /_api.py. Remove it or change it the following codes:

def comb(n, k):
    """Calculate the number of ways to choose k items from n items without repetition and without order.

    Parameters:
        n: Number of items.
        k: Number of items to choose.

    Returns:
        The number of ways to choose k items from n items.

    Example:
        >>> comb(5, 2)
        10
        >>> comb(5, 0)
        1
    """
    if k < 0 or k > n:
        return 0
    if k == 0 or k == n:
        return 1
    k = min(k, n - k)
    c = 1
    for i in range(k):
        c = c * (n - i) // (i + 1)
    return c
  • Search dist = math.dist in /_api.py. Remove it or change it the following codes:

def dist(p, q):
    """Calculate the Euclidean distance between two points.

    Parameters:
        p: First point.
        q: Second point.

    Returns:
        The Euclidean distance between p and q.

    Examples:
        >>> dist([1, 2], [4, 6])
        5.0
        >>> dist((1, 2), (4, 6))
        5.0
    """
    return math.sqrt(sum((x - y) ** 2 for x, y in zip(p, q)))
  • Search isqrt = math.isqrt in /_api.py. Remove it or change it the following codes:

def isqrt(n):
    """Calculate the integer square root of a non-negative integer.

    Parameters:
        n: Non-negative integer.

    Returns:
        The integer square root of n.

    Example:
        >>> isqrt(16)
        4
        >>> isqrt(15)
        3
    """
    if n < 0:
        raise ValueError("Square root not defined for negative numbers")
    return int(n**0.5)
  • Search prod = math.prod in /_api.py. Remove it or change it the following codes:

def prod(iterable, start=1):
    """Calculate the product of all elements in an iterable.

    Parameters:
        iterable: An iterable object.
        start: Starting value.

    Returns:
        The product of all elements in the iterable.

    Example:
        >>> prod([1, 2, 3])
        6
        >>> prod([1, 2, 3], start=10)
        60
    """
    return functools.reduce(operator.mul, iterable, start)

Remove Dependency on Python 3.7

The __init__.py file uses the Python 3.7 feature module __gettattr__ (PEP 562). In order to remove the dependency, you can change the __getattr__ function in __init__.py to the following codes:

class API:
    def __getattr__(self, name):
        return getcomponent(_api, name)

api = API()

And then change relevant imports from calcpy to imports from calcpy.api. For example, change from calcpy import add to from calcpy import api; add = api.add.

The file /_api.py uses a function that are provided by Python 3.7+ only, i.e. math.remainder(). You can remove the dependency by the following way:

  • Search remainder = math.remainder in /_api.py. Remove it or change it the following codes:

def remainder(x, y):
    """Calculate the remainder of x divided by y.

    Parameters:
        x: Dividend.
        y: Divisor.

    Returns:
        The remainder of x divided by y.

    Example:
        >>> remainder(5, 2)
        1.0
        >>> remainder(5, -2)
        -1.0
    """
    return x - y * math.floor(x / y)