Skip to content
This repository has been archived by the owner on Jul 16, 2023. It is now read-only.

Commit

Permalink
mild static optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
rjdbcm committed Nov 30, 2021
1 parent b282104 commit 7bd8895
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 30 deletions.
2 changes: 0 additions & 2 deletions Aspidites/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
]
try:
from Aspidites.api import *

Maybe.__doc__ = Maybe.__doc__
except ImportError:
pass

42 changes: 36 additions & 6 deletions Aspidites/_vendor/contracts/main_actual.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@
# # And after everything else is loaded, load the utils
# else:
# print('already loading...')
import cython

from .syntax import ParseException
from .library.extensions import CheckCallableWithSelf
from .library import CheckCallable, Extension, SeparateContext, identifier_expression
from .library import CheckCallable, Extension, SeparateContext, identifier_expression, CheckType
from .inspection import can_accept_self, can_accept_at_least_one_argument
from .interface import (
ContractException,
ContractSyntaxError,
Where,
describe_value,
)
from .parser import parse_contract_string_actual
from .parser import parse_contract_string_actual, Storage
from .syntax import contract_expression
from .inspection import getfullargspec



def get_annotations(function):
return getfullargspec(function).annotations

Expand All @@ -35,8 +38,10 @@ def get_all_arg_names(function):
return all_args


@cython.ccall
@cython.inline
def new_contract_impl(identifier, condition):
from .main import parse_flexible_spec
msg: str

# Be friendly
if not isinstance(identifier, str):
Expand Down Expand Up @@ -85,14 +90,39 @@ def new_contract_impl(identifier, condition):
# We assume it is a condition that should parse cleanly
try:
# could call parse_flexible_spec as well here
bare_contract = parse_contract_string_actual(condition)
if condition in Storage.string2contract:
bare_contract = Storage.string2contract[condition]
try:
c = contract_expression.parseString(condition, parseAll=True)[0]
assert hasattr(c, "__contract__"), "Want Contract, not %r" % c
if '$' not in condition:
Storage.string2contract[condition] = c
bare_contract = c
except Exception as e:
msg = "%s" % e
if hasattr(e, "loc"): # ParseBaseException
where = Where(condition, character=e.loc)
raise ContractSyntaxError(msg, where=where)
else:
raise # ContractDefinitionError
except ContractSyntaxError as e:
msg = "The given condition %r does not parse cleanly: %s" % (condition, e)
raise ValueError(msg)
# Important: types are callable, so check this first.
elif hasattr(condition, "__weakrefoffset__"):
# parse_flexible_spec can take care of types
bare_contract = parse_flexible_spec(condition)
if hasattr(
condition, "__contract__"
): # isinstance(spec, Contract) substitute using the __contract__ slot
bare_contract = condition
elif hasattr(condition, "__weakrefoffset__"): # isinstance(spec, type)
bare_contract = CheckType(condition)
elif isinstance(condition, str):
bare_contract = parse_contract_string_actual(condition)
else:
msg = "I want either a string or a type, not %s." % describe_value(condition)
raise ContractException(msg)

# Lastly, it should be a callable
elif hasattr(condition, "__call__"):
# Check that the signature is right
Expand Down
11 changes: 11 additions & 0 deletions Aspidites/api/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def __init__(self, func=None, *args, **kwargs):


@cython.ccall
@cython.inline
def SafeSlice(x, start=None, stop=None, step=None):
if not stop and not step:
return x[start]
Expand All @@ -120,6 +121,7 @@ def SafeLoop(x: Any):

# noinspection PyPep8Naming,PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeFactorial(a):
if a < 0 or isnan(a) or isinf(a) or isinstance(a, (float, complex)):
return Undefined(SafeFactorial, a)
Expand All @@ -128,6 +130,7 @@ def SafeFactorial(a):

# noinspection PyPep8Naming,PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeUnaryAdd(a):
if isnan(a) or not isinstance(a, numbers.Number):
return Undefined(SafeUnaryAdd, a)
Expand All @@ -136,6 +139,7 @@ def SafeUnaryAdd(a):

# noinspection PyPep8Naming,PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeUnarySub(a):
if isnan(a) or not isinstance(a, numbers.Number):
return Undefined(SafeUnarySub, a)
Expand All @@ -144,6 +148,7 @@ def SafeUnarySub(a):

# noinspection PyPep8Naming,PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeFloorDiv(a, b):
if isinf(a) or b == 0 or (isinf(a) and isinf(b)):
return Undefined(SafeFloorDiv, a, b)
Expand All @@ -152,24 +157,28 @@ def SafeFloorDiv(a, b):

# noinspection PyPep8Naming,PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeMul(a, b):
return a * b


# noinspection PyPep8Naming,PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeSub(a, b):
return a - b


# noinspection PyPep8Naming,PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeAdd(a, b):
return a + b


# noinspection PyPep8Naming,PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeDiv(a, b):
if b == 0 or (isinf(a) and isinf(b)):
return Undefined(SafeDiv, a, b)
Expand All @@ -178,6 +187,7 @@ def SafeDiv(a, b):

# noinspection PyPep8Naming, PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeMod(a, b):
if isinf(a) or b == 0:
return Undefined(SafeMod, a, b)
Expand All @@ -186,6 +196,7 @@ def SafeMod(a, b):

# noinspection PyPep8Naming, PyProtectedMember,PyUnresolvedReferences
@cython.ccall
@cython.inline
def SafeExp(a, b):
if (
(a == 0 and b == 0) or (isinf(a) and b == 0) or (isinf(b) and a == 0)
Expand Down
54 changes: 32 additions & 22 deletions Aspidites/api/monads.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import sys

# ~ do not used the vendored version of getouterframes ~
from types import FunctionType
from inspect import getouterframes
from contextlib import suppress
from warnings import warn
Expand All @@ -28,11 +29,6 @@

from .math import Undefined, Warn

@cython.ccall
@cython.inline
def _apply(f, args=None, kwargs=None):
return f(*(args or tuple()), **(kwargs or {}))


class Surely:
"""A monad for a successful programmatic unit.
Expand Down Expand Up @@ -95,10 +91,32 @@ def __new__(cls, instance__=Undefined(), *args, **kwargs):
return cls.__instance__


@cython.ccall
@cython.inline
def __maybe(instance, func, args, kwargs, _warn, warn_undefined):
e: Exception
w: str
warn_undefined: bool
try:
with suppress(ValueError):
val = instance or func(*(args or tuple()), **(kwargs or {}))
with suppress(UnboundLocalError):
instance = val
# SURELY #
return instance
instance = Undefined(func, args, kwargs)
except Exception as e:
if warn_undefined:
w = _warn.create(e)
warn(w, category=RuntimeWarning, stacklevel=0)
# UNDEFINED #
instance = Undefined(func, args, kwargs)
return instance


class Maybe:
"""Sandboxes a function call and handles Exceptions by returning an instance of
:class:`Aspidites.math.Undefined`"""

__slots__ = v("_func", "_args", "_kwargs", "_stack", "_warn", "__instance__")

def __init__(self, func, *args, **kwargs):
Expand All @@ -110,7 +128,7 @@ def __init__(self, func, *args, **kwargs):
self._warn = Warn(self._stack, self._func, self._args, self._kwargs)
self.__instance__ = Undefined()
with suppress(Exception):
self.__instance__ = _apply(self.func, self.args, self.kwargs)
self.__instance__ = self._func(*(self._args or tuple()), **(self._kwargs or {}))

def __repr__(self) -> str:
maybe = self.__class__.__name__
Expand Down Expand Up @@ -144,18 +162,10 @@ def kwargs(self) -> Dict[AnyStr, Any]:
return self._kwargs

def __call__(self, warn_undefined=True):
try:
with suppress(ValueError):
val = self.__instance__ or _apply(self.func, self.args, self.kwargs)
with suppress(UnboundLocalError):
self.__instance__ = val
# SURELY #
return self.__instance__
self.__instance__ = Undefined(self.func, self.args, self.kwargs)
except Exception as e:
if warn_undefined:
w = self._warn.create(e)
warn(w, category=RuntimeWarning, stacklevel=0)
# UNDEFINED #
self.__instance__ = Undefined(self.func, self.args, self.kwargs)
return self.__instance__
return __maybe(
self.__instance__,
self._func,
self._args,
self.kwargs,
self._warn,
warn_undefined)

0 comments on commit 7bd8895

Please sign in to comment.