mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-19 07:15:36 -04:00
122 lines
3.5 KiB
Python
122 lines
3.5 KiB
Python
from __future__ import absolute_import, print_function, unicode_literals
|
|
|
|
import math
|
|
from .shared import string, to_str, fromNow, JSONTemplateError
|
|
|
|
|
|
class BuiltinError(JSONTemplateError):
|
|
pass
|
|
|
|
|
|
def build(context):
|
|
builtins = {}
|
|
|
|
def builtin(name, variadic=None, argument_tests=None, minArgs=None):
|
|
def wrap(fn):
|
|
def bad(reason=None):
|
|
raise BuiltinError(
|
|
(reason or 'invalid arguments to builtin: {}').format(name))
|
|
if variadic:
|
|
def invoke(*args):
|
|
if minArgs:
|
|
if len(args) < minArgs:
|
|
bad("too few arguments to {}")
|
|
for arg in args:
|
|
if not variadic(arg):
|
|
bad()
|
|
return fn(*args)
|
|
|
|
elif argument_tests:
|
|
def invoke(*args):
|
|
if len(args) != len(argument_tests):
|
|
bad()
|
|
for t, arg in zip(argument_tests, args):
|
|
if not t(arg):
|
|
bad()
|
|
return fn(*args)
|
|
|
|
else:
|
|
def invoke(*args):
|
|
return fn(*args)
|
|
|
|
builtins[name] = invoke
|
|
return fn
|
|
return wrap
|
|
|
|
def is_number(v):
|
|
return isinstance(v, (int, float)) and not isinstance(v, bool)
|
|
|
|
def is_string(v):
|
|
return isinstance(v, string)
|
|
|
|
def is_string_or_array(v):
|
|
return isinstance(v, (string, list))
|
|
|
|
def anything_except_array(v):
|
|
return isinstance(v, (string, int, float, bool)) or v is None
|
|
|
|
def anything(v):
|
|
return isinstance(v, (string, int, float, list, dict)) or v is None or callable(v)
|
|
|
|
# ---
|
|
|
|
builtin('min', variadic=is_number, minArgs=1)(min)
|
|
builtin('max', variadic=is_number, minArgs=1)(max)
|
|
builtin('sqrt', argument_tests=[is_number])(math.sqrt)
|
|
builtin('abs', argument_tests=[is_number])(abs)
|
|
|
|
@builtin('ceil', argument_tests=[is_number])
|
|
def ceil(v):
|
|
return int(math.ceil(v))
|
|
|
|
@builtin('floor', argument_tests=[is_number])
|
|
def floor(v):
|
|
return int(math.floor(v))
|
|
|
|
@builtin('lowercase', argument_tests=[is_string])
|
|
def lowercase(v):
|
|
return v.lower()
|
|
|
|
@builtin('uppercase', argument_tests=[is_string])
|
|
def lowercase(v):
|
|
return v.upper()
|
|
|
|
builtin('len', argument_tests=[is_string_or_array])(len)
|
|
builtin('str', argument_tests=[anything_except_array])(to_str)
|
|
builtin('number', variadic=is_string, minArgs=1)(float)
|
|
|
|
@builtin('strip', argument_tests=[is_string])
|
|
def strip(s):
|
|
return s.strip()
|
|
|
|
@builtin('rstrip', argument_tests=[is_string])
|
|
def rstrip(s):
|
|
return s.rstrip()
|
|
|
|
@builtin('lstrip', argument_tests=[is_string])
|
|
def lstrip(s):
|
|
return s.lstrip()
|
|
|
|
@builtin('fromNow', variadic=is_string, minArgs=1)
|
|
def fromNow_builtin(offset, reference=None):
|
|
return fromNow(offset, reference or context.get('now'))
|
|
|
|
@builtin('typeof', argument_tests=[anything])
|
|
def typeof(v):
|
|
if isinstance(v, bool):
|
|
return 'boolean'
|
|
elif isinstance(v, string):
|
|
return 'string'
|
|
elif isinstance(v, (int, float)):
|
|
return 'number'
|
|
elif isinstance(v, list):
|
|
return 'array'
|
|
elif isinstance(v, dict):
|
|
return 'object'
|
|
elif v is None:
|
|
return None
|
|
elif callable(v):
|
|
return 'function'
|
|
|
|
return builtins
|